diff options
Diffstat (limited to 'drivers/platform/x86/intel-vbtn.c')
-rw-r--r-- | drivers/platform/x86/intel-vbtn.c | 39 |
1 files changed, 36 insertions, 3 deletions
diff --git a/drivers/platform/x86/intel-vbtn.c b/drivers/platform/x86/intel-vbtn.c index c2035e121ac2..61f106377661 100644 --- a/drivers/platform/x86/intel-vbtn.c +++ b/drivers/platform/x86/intel-vbtn.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 | ||
28 | MODULE_LICENSE("GPL"); | 29 | MODULE_LICENSE("GPL"); |
@@ -46,6 +47,7 @@ static const struct key_entry intel_vbtn_keymap[] = { | |||
46 | 47 | ||
47 | struct intel_vbtn_priv { | 48 | struct intel_vbtn_priv { |
48 | struct input_dev *input_dev; | 49 | struct input_dev *input_dev; |
50 | bool wakeup_mode; | ||
49 | }; | 51 | }; |
50 | 52 | ||
51 | static int intel_vbtn_input_setup(struct platform_device *device) | 53 | static int intel_vbtn_input_setup(struct platform_device *device) |
@@ -73,9 +75,15 @@ static void notify_handler(acpi_handle handle, u32 event, void *context) | |||
73 | struct platform_device *device = context; | 75 | struct platform_device *device = context; |
74 | struct intel_vbtn_priv *priv = dev_get_drvdata(&device->dev); | 76 | struct intel_vbtn_priv *priv = dev_get_drvdata(&device->dev); |
75 | 77 | ||
76 | if (!sparse_keymap_report_event(priv->input_dev, event, 1, true)) | 78 | if (priv->wakeup_mode) { |
77 | dev_info(&device->dev, "unknown event index 0x%x\n", | 79 | if (sparse_keymap_entry_from_scancode(priv->input_dev, event)) { |
78 | event); | 80 | pm_wakeup_hard_event(&device->dev); |
81 | return; | ||
82 | } | ||
83 | } else if (sparse_keymap_report_event(priv->input_dev, event, 1, true)) { | ||
84 | return; | ||
85 | } | ||
86 | dev_info(&device->dev, "unknown event index 0x%x\n", event); | ||
79 | } | 87 | } |
80 | 88 | ||
81 | static int intel_vbtn_probe(struct platform_device *device) | 89 | static int intel_vbtn_probe(struct platform_device *device) |
@@ -109,6 +117,7 @@ static int intel_vbtn_probe(struct platform_device *device) | |||
109 | if (ACPI_FAILURE(status)) | 117 | if (ACPI_FAILURE(status)) |
110 | return -EBUSY; | 118 | return -EBUSY; |
111 | 119 | ||
120 | device_init_wakeup(&device->dev, true); | ||
112 | return 0; | 121 | return 0; |
113 | } | 122 | } |
114 | 123 | ||
@@ -125,10 +134,34 @@ static int intel_vbtn_remove(struct platform_device *device) | |||
125 | return 0; | 134 | return 0; |
126 | } | 135 | } |
127 | 136 | ||
137 | static int intel_vbtn_pm_prepare(struct device *dev) | ||
138 | { | ||
139 | struct intel_vbtn_priv *priv = dev_get_drvdata(dev); | ||
140 | |||
141 | priv->wakeup_mode = true; | ||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | static int intel_vbtn_pm_resume(struct device *dev) | ||
146 | { | ||
147 | struct intel_vbtn_priv *priv = dev_get_drvdata(dev); | ||
148 | |||
149 | priv->wakeup_mode = false; | ||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | static const struct dev_pm_ops intel_vbtn_pm_ops = { | ||
154 | .prepare = intel_vbtn_pm_prepare, | ||
155 | .resume = intel_vbtn_pm_resume, | ||
156 | .restore = intel_vbtn_pm_resume, | ||
157 | .thaw = intel_vbtn_pm_resume, | ||
158 | }; | ||
159 | |||
128 | static struct platform_driver intel_vbtn_pl_driver = { | 160 | static struct platform_driver intel_vbtn_pl_driver = { |
129 | .driver = { | 161 | .driver = { |
130 | .name = "intel-vbtn", | 162 | .name = "intel-vbtn", |
131 | .acpi_match_table = intel_vbtn_ids, | 163 | .acpi_match_table = intel_vbtn_ids, |
164 | .pm = &intel_vbtn_pm_ops, | ||
132 | }, | 165 | }, |
133 | .probe = intel_vbtn_probe, | 166 | .probe = intel_vbtn_probe, |
134 | .remove = intel_vbtn_remove, | 167 | .remove = intel_vbtn_remove, |