aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform/x86/intel-hid.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/platform/x86/intel-hid.c')
-rw-r--r--drivers/platform/x86/intel-hid.c40
1 files changed, 35 insertions, 5 deletions
diff --git a/drivers/platform/x86/intel-hid.c b/drivers/platform/x86/intel-hid.c
index 63ba2cbd04c2..8519e0f97bdd 100644
--- a/drivers/platform/x86/intel-hid.c
+++ b/drivers/platform/x86/intel-hid.c
@@ -23,6 +23,7 @@
23#include <linux/platform_device.h> 23#include <linux/platform_device.h>
24#include <linux/input/sparse-keymap.h> 24#include <linux/input/sparse-keymap.h>
25#include <linux/acpi.h> 25#include <linux/acpi.h>
26#include <linux/suspend.h>
26#include <acpi/acpi_bus.h> 27#include <acpi/acpi_bus.h>
27 28
28MODULE_LICENSE("GPL"); 29MODULE_LICENSE("GPL");
@@ -75,6 +76,7 @@ static const struct key_entry intel_array_keymap[] = {
75struct intel_hid_priv { 76struct intel_hid_priv {
76 struct input_dev *input_dev; 77 struct input_dev *input_dev;
77 struct input_dev *array; 78 struct input_dev *array;
79 bool wakeup_mode;
78}; 80};
79 81
80static int intel_hid_set_enable(struct device *device, bool enable) 82static int intel_hid_set_enable(struct device *device, bool enable)
@@ -116,23 +118,37 @@ static void intel_button_array_enable(struct device *device, bool enable)
116 dev_warn(device, "failed to set button capability\n"); 118 dev_warn(device, "failed to set button capability\n");
117} 119}
118 120
119static int intel_hid_pl_suspend_handler(struct device *device) 121static int intel_hid_pm_prepare(struct device *device)
120{ 122{
121 intel_hid_set_enable(device, false); 123 struct intel_hid_priv *priv = dev_get_drvdata(device);
122 intel_button_array_enable(device, false); 124
125 priv->wakeup_mode = true;
126 return 0;
127}
123 128
129static int intel_hid_pl_suspend_handler(struct device *device)
130{
131 if (pm_suspend_via_firmware()) {
132 intel_hid_set_enable(device, false);
133 intel_button_array_enable(device, false);
134 }
124 return 0; 135 return 0;
125} 136}
126 137
127static int intel_hid_pl_resume_handler(struct device *device) 138static int intel_hid_pl_resume_handler(struct device *device)
128{ 139{
129 intel_hid_set_enable(device, true); 140 struct intel_hid_priv *priv = dev_get_drvdata(device);
130 intel_button_array_enable(device, true);
131 141
142 priv->wakeup_mode = false;
143 if (pm_resume_via_firmware()) {
144 intel_hid_set_enable(device, true);
145 intel_button_array_enable(device, true);
146 }
132 return 0; 147 return 0;
133} 148}
134 149
135static const struct dev_pm_ops intel_hid_pl_pm_ops = { 150static const struct dev_pm_ops intel_hid_pl_pm_ops = {
151 .prepare = intel_hid_pm_prepare,
136 .freeze = intel_hid_pl_suspend_handler, 152 .freeze = intel_hid_pl_suspend_handler,
137 .thaw = intel_hid_pl_resume_handler, 153 .thaw = intel_hid_pl_resume_handler,
138 .restore = intel_hid_pl_resume_handler, 154 .restore = intel_hid_pl_resume_handler,
@@ -186,6 +202,19 @@ static void notify_handler(acpi_handle handle, u32 event, void *context)
186 unsigned long long ev_index; 202 unsigned long long ev_index;
187 acpi_status status; 203 acpi_status status;
188 204
205 if (priv->wakeup_mode) {
206 /* Wake up on 5-button array events only. */
207 if (event == 0xc0 || !priv->array)
208 return;
209
210 if (sparse_keymap_entry_from_scancode(priv->array, event))
211 pm_wakeup_hard_event(&device->dev);
212 else
213 dev_info(&device->dev, "unknown event 0x%x\n", event);
214
215 return;
216 }
217
189 /* 0xC0 is for HID events, other values are for 5 button array */ 218 /* 0xC0 is for HID events, other values are for 5 button array */
190 if (event != 0xc0) { 219 if (event != 0xc0) {
191 if (!priv->array || 220 if (!priv->array ||
@@ -270,6 +299,7 @@ static int intel_hid_probe(struct platform_device *device)
270 "failed to enable HID power button\n"); 299 "failed to enable HID power button\n");
271 } 300 }
272 301
302 device_init_wakeup(&device->dev, true);
273 return 0; 303 return 0;
274 304
275err_remove_notify: 305err_remove_notify: