summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/thinkpad-acpi.txt24
-rw-r--r--drivers/misc/thinkpad_acpi.c91
2 files changed, 108 insertions, 7 deletions
diff --git a/Documentation/thinkpad-acpi.txt b/Documentation/thinkpad-acpi.txt
index 3fb864733ca1..9d08e472ef74 100644
--- a/Documentation/thinkpad-acpi.txt
+++ b/Documentation/thinkpad-acpi.txt
@@ -325,6 +325,21 @@ sysfs notes:
May return -EPERM (write access locked out by module
parameter) or -EACCES (read-only).
+ wakeup_reason:
+ Set to 1 if the system is waking up because the user
+ requested a bay ejection. Set to 2 if the system is
+ waking up because the user requested the system to
+ undock. Set to zero for normal wake-ups or wake-ups
+ due to unknown reasons.
+
+ wakeup_hotunplug_complete:
+ Set to 1 if the system was waken up because of an
+ undock or bay ejection request, and that request
+ was sucessfully completed. At this point, it might
+ be useful to send the system back to sleep, at the
+ user's choice. Refer to HKEY events 0x4003 and
+ 0x3003, below.
+
input layer notes:
A Hot key is mapped to a single input layer EV_KEY event, possibly
@@ -475,6 +490,15 @@ Non hot-key ACPI HKEY event map:
The above events are not propagated by the driver, except for legacy
compatibility purposes when hotkey_report_mode is set to 1.
+0x2304 System is waking up from suspend to undock
+0x2305 System is waking up from suspend to eject bay
+0x2404 System is waking up from hibernation to undock
+0x2405 System is waking up from hibernation to eject bay
+
+The above events are never propagated by the driver.
+
+0x3003 Bay ejection (see 0x2x05) complete, can sleep again
+0x4003 Undocked (see 0x2x04), can sleep again
0x5010 Brightness level changed (newer Lenovo BIOSes)
The above events are propagated by the driver.
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c
index f5f306ae4413..9b0235dc5308 100644
--- a/drivers/misc/thinkpad_acpi.c
+++ b/drivers/misc/thinkpad_acpi.c
@@ -1018,6 +1018,14 @@ static unsigned int hotkey_config_change;
static struct mutex hotkey_mutex;
+static enum { /* Reasons for waking up */
+ TP_ACPI_WAKEUP_NONE = 0, /* None or unknown */
+ TP_ACPI_WAKEUP_BAYEJ, /* Bay ejection request */
+ TP_ACPI_WAKEUP_UNDOCK, /* Undock request */
+} hotkey_wakeup_reason;
+
+static int hotkey_autosleep_ack;
+
static int hotkey_orig_status;
static u32 hotkey_orig_mask;
static u32 hotkey_all_mask;
@@ -1661,6 +1669,29 @@ static ssize_t hotkey_report_mode_show(struct device *dev,
static struct device_attribute dev_attr_hotkey_report_mode =
__ATTR(hotkey_report_mode, S_IRUGO, hotkey_report_mode_show, NULL);
+/* sysfs wakeup reason ------------------------------------------------- */
+static ssize_t hotkey_wakeup_reason_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", hotkey_wakeup_reason);
+}
+
+static struct device_attribute dev_attr_hotkey_wakeup_reason =
+ __ATTR(wakeup_reason, S_IRUGO, hotkey_wakeup_reason_show, NULL);
+
+/* sysfs wakeup hotunplug_complete ------------------------------------- */
+static ssize_t hotkey_wakeup_hotunplug_complete_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", hotkey_autosleep_ack);
+}
+
+static struct device_attribute dev_attr_hotkey_wakeup_hotunplug_complete =
+ __ATTR(wakeup_hotunplug_complete, S_IRUGO,
+ hotkey_wakeup_hotunplug_complete_show, NULL);
+
/* --------------------------------------------------------------------- */
static struct attribute *hotkey_attributes[] __initdata = {
@@ -1683,6 +1714,8 @@ static struct attribute *hotkey_mask_attributes[] __initdata = {
&dev_attr_hotkey_all_mask.attr,
&dev_attr_hotkey_recommended_mask.attr,
#endif
+ &dev_attr_hotkey_wakeup_reason.attr,
+ &dev_attr_hotkey_wakeup_hotunplug_complete.attr,
};
static int __init hotkey_init(struct ibm_init_struct *iibm)
@@ -1822,7 +1855,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
str_supported(tp_features.hotkey));
if (tp_features.hotkey) {
- hotkey_dev_attributes = create_attr_set(10, NULL);
+ hotkey_dev_attributes = create_attr_set(12, NULL);
if (!hotkey_dev_attributes)
return -ENOMEM;
res = add_many_to_attr_set(hotkey_dev_attributes,
@@ -2051,6 +2084,48 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
unk_ev = 1;
}
break;
+ case 2:
+ /* Wakeup reason */
+ switch (hkey) {
+ case 0x2304: /* suspend, undock */
+ case 0x2404: /* hibernation, undock */
+ hotkey_wakeup_reason = TP_ACPI_WAKEUP_UNDOCK;
+ ignore_acpi_ev = 1;
+ break;
+ case 0x2305: /* suspend, bay eject */
+ case 0x2405: /* hibernation, bay eject */
+ hotkey_wakeup_reason = TP_ACPI_WAKEUP_BAYEJ;
+ ignore_acpi_ev = 1;
+ break;
+ default:
+ unk_ev = 1;
+ }
+ if (hotkey_wakeup_reason != TP_ACPI_WAKEUP_NONE) {
+ printk(TPACPI_INFO
+ "woke up due to a hot-unplug "
+ "request...\n");
+ }
+ break;
+ case 3:
+ /* bay-related wakeups */
+ if (hkey == 0x3003) {
+ hotkey_autosleep_ack = 1;
+ printk(TPACPI_INFO
+ "bay ejected\n");
+ } else {
+ unk_ev = 1;
+ }
+ break;
+ case 4:
+ /* dock-related wakeups */
+ if (hkey == 0x4003) {
+ hotkey_autosleep_ack = 1;
+ printk(TPACPI_INFO
+ "undocked\n");
+ } else {
+ unk_ev = 1;
+ }
+ break;
case 5:
/* 0x5000-0x5FFF: On screen display helpers */
switch (hkey) {
@@ -2075,12 +2150,6 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
}
/* fallthrough to default */
default:
- /* case 2: dock-related */
- /* 0x2305 - T43 waking up due to bay lever
- * eject while aslept */
- /* case 3: ultra-bay related. maybe bay in dock? */
- /* 0x3003 - T43 after wake up by bay lever
- * eject (0x2305) */
unk_ev = 1;
}
if (unk_ev) {
@@ -2105,6 +2174,13 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
}
}
+static void hotkey_suspend(pm_message_t state)
+{
+ /* Do these on suspend, we get the events on early resume! */
+ hotkey_wakeup_reason = TP_ACPI_WAKEUP_NONE;
+ hotkey_autosleep_ack = 0;
+}
+
static void hotkey_resume(void)
{
if (hotkey_mask_get())
@@ -2212,6 +2288,7 @@ static struct ibm_struct hotkey_driver_data = {
.write = hotkey_write,
.exit = hotkey_exit,
.resume = hotkey_resume,
+ .suspend = hotkey_suspend,
.acpi = &ibm_hotkey_acpidriver,
};