Merge branch 'thinkpad' into test
[pandora-kernel.git] / drivers / misc / thinkpad_acpi.c
index 62aebaa..4db1cf9 100644 (file)
@@ -158,7 +158,6 @@ enum {
 #define TPACPI_INFO   KERN_INFO   TPACPI_LOG
 #define TPACPI_DEBUG  KERN_DEBUG  TPACPI_LOG
 
-#define TPACPI_DBG_ALL         0xffff
 #define TPACPI_DBG_ALL         0xffff
 #define TPACPI_DBG_INIT                0x0001
 #define TPACPI_DBG_EXIT                0x0002
@@ -582,7 +581,8 @@ static int __init register_tpacpi_subdriver(struct ibm_struct *ibm)
 
        ibm->acpi->driver = kzalloc(sizeof(struct acpi_driver), GFP_KERNEL);
        if (!ibm->acpi->driver) {
-               printk(TPACPI_ERR "kzalloc(ibm->driver) failed\n");
+               printk(TPACPI_ERR
+                      "failed to allocate memory for ibm->acpi->driver\n");
                return -ENOMEM;
        }
 
@@ -838,6 +838,13 @@ static int parse_strtoul(const char *buf,
        return 0;
 }
 
+static void tpacpi_disable_brightness_delay(void)
+{
+       if (acpi_evalf(hkey_handle, NULL, "PWMS", "qvd", 0))
+               printk(TPACPI_NOTICE
+                       "ACPI backlight control delay disabled\n");
+}
+
 static int __init tpacpi_query_bcl_levels(acpi_handle handle)
 {
        struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
@@ -2139,6 +2146,8 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
        if (!tp_features.hotkey)
                return 1;
 
+       tpacpi_disable_brightness_delay();
+
        hotkey_dev_attributes = create_attr_set(13, NULL);
        if (!hotkey_dev_attributes)
                return -ENOMEM;
@@ -2512,6 +2521,8 @@ static void hotkey_suspend(pm_message_t state)
 
 static void hotkey_resume(void)
 {
+       tpacpi_disable_brightness_delay();
+
        if (hotkey_mask_get())
                printk(TPACPI_ERR
                       "error while trying to read hot key mask "
@@ -5983,6 +5994,52 @@ static void fan_exit(void)
        flush_workqueue(tpacpi_wq);
 }
 
+static void fan_suspend(pm_message_t state)
+{
+       if (!fan_control_allowed)
+               return;
+
+       /* Store fan status in cache */
+       fan_get_status_safe(NULL);
+       if (tp_features.fan_ctrl_status_undef)
+               fan_control_desired_level = TP_EC_FAN_AUTO;
+}
+
+static void fan_resume(void)
+{
+       u8 saved_fan_level;
+       u8 current_level = 7;
+       bool do_set = false;
+
+       /* DSDT *always* updates status on resume */
+       tp_features.fan_ctrl_status_undef = 0;
+
+       saved_fan_level = fan_control_desired_level;
+       if (!fan_control_allowed ||
+           (fan_get_status_safe(&current_level) < 0))
+               return;
+
+       switch (fan_control_access_mode) {
+       case TPACPI_FAN_WR_ACPI_SFAN:
+               do_set = (saved_fan_level > current_level);
+               break;
+       case TPACPI_FAN_WR_ACPI_FANS:
+       case TPACPI_FAN_WR_TPEC:
+               do_set = ((saved_fan_level & TP_EC_FAN_FULLSPEED) ||
+                         (saved_fan_level == 7 &&
+                          !(current_level & TP_EC_FAN_FULLSPEED)));
+               break;
+       default:
+               return;
+       }
+       if (do_set) {
+               printk(TPACPI_NOTICE
+                       "restoring fan level to 0x%02x\n",
+                       saved_fan_level);
+               fan_set_level_safe(saved_fan_level);
+       }
+}
+
 static int fan_read(char *p)
 {
        int len = 0;
@@ -6174,6 +6231,8 @@ static struct ibm_struct fan_driver_data = {
        .read = fan_read,
        .write = fan_write,
        .exit = fan_exit,
+       .suspend = fan_suspend,
+       .resume = fan_resume,
 };
 
 /****************************************************************************