diff options
Diffstat (limited to 'drivers/misc')
-rw-r--r-- | drivers/misc/thinkpad_acpi.c | 91 |
1 files changed, 84 insertions, 7 deletions
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; | |||
1018 | 1018 | ||
1019 | static struct mutex hotkey_mutex; | 1019 | static struct mutex hotkey_mutex; |
1020 | 1020 | ||
1021 | static enum { /* Reasons for waking up */ | ||
1022 | TP_ACPI_WAKEUP_NONE = 0, /* None or unknown */ | ||
1023 | TP_ACPI_WAKEUP_BAYEJ, /* Bay ejection request */ | ||
1024 | TP_ACPI_WAKEUP_UNDOCK, /* Undock request */ | ||
1025 | } hotkey_wakeup_reason; | ||
1026 | |||
1027 | static int hotkey_autosleep_ack; | ||
1028 | |||
1021 | static int hotkey_orig_status; | 1029 | static int hotkey_orig_status; |
1022 | static u32 hotkey_orig_mask; | 1030 | static u32 hotkey_orig_mask; |
1023 | static u32 hotkey_all_mask; | 1031 | static u32 hotkey_all_mask; |
@@ -1661,6 +1669,29 @@ static ssize_t hotkey_report_mode_show(struct device *dev, | |||
1661 | static struct device_attribute dev_attr_hotkey_report_mode = | 1669 | static struct device_attribute dev_attr_hotkey_report_mode = |
1662 | __ATTR(hotkey_report_mode, S_IRUGO, hotkey_report_mode_show, NULL); | 1670 | __ATTR(hotkey_report_mode, S_IRUGO, hotkey_report_mode_show, NULL); |
1663 | 1671 | ||
1672 | /* sysfs wakeup reason ------------------------------------------------- */ | ||
1673 | static ssize_t hotkey_wakeup_reason_show(struct device *dev, | ||
1674 | struct device_attribute *attr, | ||
1675 | char *buf) | ||
1676 | { | ||
1677 | return snprintf(buf, PAGE_SIZE, "%d\n", hotkey_wakeup_reason); | ||
1678 | } | ||
1679 | |||
1680 | static struct device_attribute dev_attr_hotkey_wakeup_reason = | ||
1681 | __ATTR(wakeup_reason, S_IRUGO, hotkey_wakeup_reason_show, NULL); | ||
1682 | |||
1683 | /* sysfs wakeup hotunplug_complete ------------------------------------- */ | ||
1684 | static ssize_t hotkey_wakeup_hotunplug_complete_show(struct device *dev, | ||
1685 | struct device_attribute *attr, | ||
1686 | char *buf) | ||
1687 | { | ||
1688 | return snprintf(buf, PAGE_SIZE, "%d\n", hotkey_autosleep_ack); | ||
1689 | } | ||
1690 | |||
1691 | static struct device_attribute dev_attr_hotkey_wakeup_hotunplug_complete = | ||
1692 | __ATTR(wakeup_hotunplug_complete, S_IRUGO, | ||
1693 | hotkey_wakeup_hotunplug_complete_show, NULL); | ||
1694 | |||
1664 | /* --------------------------------------------------------------------- */ | 1695 | /* --------------------------------------------------------------------- */ |
1665 | 1696 | ||
1666 | static struct attribute *hotkey_attributes[] __initdata = { | 1697 | static struct attribute *hotkey_attributes[] __initdata = { |
@@ -1683,6 +1714,8 @@ static struct attribute *hotkey_mask_attributes[] __initdata = { | |||
1683 | &dev_attr_hotkey_all_mask.attr, | 1714 | &dev_attr_hotkey_all_mask.attr, |
1684 | &dev_attr_hotkey_recommended_mask.attr, | 1715 | &dev_attr_hotkey_recommended_mask.attr, |
1685 | #endif | 1716 | #endif |
1717 | &dev_attr_hotkey_wakeup_reason.attr, | ||
1718 | &dev_attr_hotkey_wakeup_hotunplug_complete.attr, | ||
1686 | }; | 1719 | }; |
1687 | 1720 | ||
1688 | static int __init hotkey_init(struct ibm_init_struct *iibm) | 1721 | static int __init hotkey_init(struct ibm_init_struct *iibm) |
@@ -1822,7 +1855,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) | |||
1822 | str_supported(tp_features.hotkey)); | 1855 | str_supported(tp_features.hotkey)); |
1823 | 1856 | ||
1824 | if (tp_features.hotkey) { | 1857 | if (tp_features.hotkey) { |
1825 | hotkey_dev_attributes = create_attr_set(10, NULL); | 1858 | hotkey_dev_attributes = create_attr_set(12, NULL); |
1826 | if (!hotkey_dev_attributes) | 1859 | if (!hotkey_dev_attributes) |
1827 | return -ENOMEM; | 1860 | return -ENOMEM; |
1828 | res = add_many_to_attr_set(hotkey_dev_attributes, | 1861 | res = add_many_to_attr_set(hotkey_dev_attributes, |
@@ -2051,6 +2084,48 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event) | |||
2051 | unk_ev = 1; | 2084 | unk_ev = 1; |
2052 | } | 2085 | } |
2053 | break; | 2086 | break; |
2087 | case 2: | ||
2088 | /* Wakeup reason */ | ||
2089 | switch (hkey) { | ||
2090 | case 0x2304: /* suspend, undock */ | ||
2091 | case 0x2404: /* hibernation, undock */ | ||
2092 | hotkey_wakeup_reason = TP_ACPI_WAKEUP_UNDOCK; | ||
2093 | ignore_acpi_ev = 1; | ||
2094 | break; | ||
2095 | case 0x2305: /* suspend, bay eject */ | ||
2096 | case 0x2405: /* hibernation, bay eject */ | ||
2097 | hotkey_wakeup_reason = TP_ACPI_WAKEUP_BAYEJ; | ||
2098 | ignore_acpi_ev = 1; | ||
2099 | break; | ||
2100 | default: | ||
2101 | unk_ev = 1; | ||
2102 | } | ||
2103 | if (hotkey_wakeup_reason != TP_ACPI_WAKEUP_NONE) { | ||
2104 | printk(TPACPI_INFO | ||
2105 | "woke up due to a hot-unplug " | ||
2106 | "request...\n"); | ||
2107 | } | ||
2108 | break; | ||
2109 | case 3: | ||
2110 | /* bay-related wakeups */ | ||
2111 | if (hkey == 0x3003) { | ||
2112 | hotkey_autosleep_ack = 1; | ||
2113 | printk(TPACPI_INFO | ||
2114 | "bay ejected\n"); | ||
2115 | } else { | ||
2116 | unk_ev = 1; | ||
2117 | } | ||
2118 | break; | ||
2119 | case 4: | ||
2120 | /* dock-related wakeups */ | ||
2121 | if (hkey == 0x4003) { | ||
2122 | hotkey_autosleep_ack = 1; | ||
2123 | printk(TPACPI_INFO | ||
2124 | "undocked\n"); | ||
2125 | } else { | ||
2126 | unk_ev = 1; | ||
2127 | } | ||
2128 | break; | ||
2054 | case 5: | 2129 | case 5: |
2055 | /* 0x5000-0x5FFF: On screen display helpers */ | 2130 | /* 0x5000-0x5FFF: On screen display helpers */ |
2056 | switch (hkey) { | 2131 | switch (hkey) { |
@@ -2075,12 +2150,6 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event) | |||
2075 | } | 2150 | } |
2076 | /* fallthrough to default */ | 2151 | /* fallthrough to default */ |
2077 | default: | 2152 | default: |
2078 | /* case 2: dock-related */ | ||
2079 | /* 0x2305 - T43 waking up due to bay lever | ||
2080 | * eject while aslept */ | ||
2081 | /* case 3: ultra-bay related. maybe bay in dock? */ | ||
2082 | /* 0x3003 - T43 after wake up by bay lever | ||
2083 | * eject (0x2305) */ | ||
2084 | unk_ev = 1; | 2153 | unk_ev = 1; |
2085 | } | 2154 | } |
2086 | if (unk_ev) { | 2155 | if (unk_ev) { |
@@ -2105,6 +2174,13 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event) | |||
2105 | } | 2174 | } |
2106 | } | 2175 | } |
2107 | 2176 | ||
2177 | static void hotkey_suspend(pm_message_t state) | ||
2178 | { | ||
2179 | /* Do these on suspend, we get the events on early resume! */ | ||
2180 | hotkey_wakeup_reason = TP_ACPI_WAKEUP_NONE; | ||
2181 | hotkey_autosleep_ack = 0; | ||
2182 | } | ||
2183 | |||
2108 | static void hotkey_resume(void) | 2184 | static void hotkey_resume(void) |
2109 | { | 2185 | { |
2110 | if (hotkey_mask_get()) | 2186 | if (hotkey_mask_get()) |
@@ -2212,6 +2288,7 @@ static struct ibm_struct hotkey_driver_data = { | |||
2212 | .write = hotkey_write, | 2288 | .write = hotkey_write, |
2213 | .exit = hotkey_exit, | 2289 | .exit = hotkey_exit, |
2214 | .resume = hotkey_resume, | 2290 | .resume = hotkey_resume, |
2291 | .suspend = hotkey_suspend, | ||
2215 | .acpi = &ibm_hotkey_acpidriver, | 2292 | .acpi = &ibm_hotkey_acpidriver, |
2216 | }; | 2293 | }; |
2217 | 2294 | ||