diff options
-rw-r--r-- | drivers/acpi/button.c | 45 | ||||
-rw-r--r-- | include/acpi/button.h | 10 |
2 files changed, 53 insertions, 2 deletions
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index 9195deba9d94..ebb593e9c380 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c | |||
@@ -113,6 +113,9 @@ static const struct file_operations acpi_button_state_fops = { | |||
113 | .release = single_release, | 113 | .release = single_release, |
114 | }; | 114 | }; |
115 | 115 | ||
116 | static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier); | ||
117 | static struct acpi_device *lid_device; | ||
118 | |||
116 | /* -------------------------------------------------------------------------- | 119 | /* -------------------------------------------------------------------------- |
117 | FS Interface (/proc) | 120 | FS Interface (/proc) |
118 | -------------------------------------------------------------------------- */ | 121 | -------------------------------------------------------------------------- */ |
@@ -229,11 +232,38 @@ static int acpi_button_remove_fs(struct acpi_device *device) | |||
229 | /* -------------------------------------------------------------------------- | 232 | /* -------------------------------------------------------------------------- |
230 | Driver Interface | 233 | Driver Interface |
231 | -------------------------------------------------------------------------- */ | 234 | -------------------------------------------------------------------------- */ |
235 | int acpi_lid_notifier_register(struct notifier_block *nb) | ||
236 | { | ||
237 | return blocking_notifier_chain_register(&acpi_lid_notifier, nb); | ||
238 | } | ||
239 | EXPORT_SYMBOL(acpi_lid_notifier_register); | ||
240 | |||
241 | int acpi_lid_notifier_unregister(struct notifier_block *nb) | ||
242 | { | ||
243 | return blocking_notifier_chain_unregister(&acpi_lid_notifier, nb); | ||
244 | } | ||
245 | EXPORT_SYMBOL(acpi_lid_notifier_unregister); | ||
246 | |||
247 | int acpi_lid_open(void) | ||
248 | { | ||
249 | acpi_status status; | ||
250 | unsigned long long state; | ||
251 | |||
252 | status = acpi_evaluate_integer(lid_device->handle, "_LID", NULL, | ||
253 | &state); | ||
254 | if (ACPI_FAILURE(status)) | ||
255 | return -ENODEV; | ||
256 | |||
257 | return !!state; | ||
258 | } | ||
259 | EXPORT_SYMBOL(acpi_lid_open); | ||
260 | |||
232 | static int acpi_lid_send_state(struct acpi_device *device) | 261 | static int acpi_lid_send_state(struct acpi_device *device) |
233 | { | 262 | { |
234 | struct acpi_button *button = acpi_driver_data(device); | 263 | struct acpi_button *button = acpi_driver_data(device); |
235 | unsigned long long state; | 264 | unsigned long long state; |
236 | acpi_status status; | 265 | acpi_status status; |
266 | int ret; | ||
237 | 267 | ||
238 | status = acpi_evaluate_integer(device->handle, "_LID", NULL, &state); | 268 | status = acpi_evaluate_integer(device->handle, "_LID", NULL, &state); |
239 | if (ACPI_FAILURE(status)) | 269 | if (ACPI_FAILURE(status)) |
@@ -242,7 +272,12 @@ static int acpi_lid_send_state(struct acpi_device *device) | |||
242 | /* input layer checks if event is redundant */ | 272 | /* input layer checks if event is redundant */ |
243 | input_report_switch(button->input, SW_LID, !state); | 273 | input_report_switch(button->input, SW_LID, !state); |
244 | input_sync(button->input); | 274 | input_sync(button->input); |
245 | return 0; | 275 | |
276 | ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device); | ||
277 | if (ret == NOTIFY_DONE) | ||
278 | ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, | ||
279 | device); | ||
280 | return ret; | ||
246 | } | 281 | } |
247 | 282 | ||
248 | static void acpi_button_notify(struct acpi_device *device, u32 event) | 283 | static void acpi_button_notify(struct acpi_device *device, u32 event) |
@@ -364,8 +399,14 @@ static int acpi_button_add(struct acpi_device *device) | |||
364 | error = input_register_device(input); | 399 | error = input_register_device(input); |
365 | if (error) | 400 | if (error) |
366 | goto err_remove_fs; | 401 | goto err_remove_fs; |
367 | if (button->type == ACPI_BUTTON_TYPE_LID) | 402 | if (button->type == ACPI_BUTTON_TYPE_LID) { |
368 | acpi_lid_send_state(device); | 403 | acpi_lid_send_state(device); |
404 | /* | ||
405 | * This assumes there's only one lid device, or if there are | ||
406 | * more we only care about the last one... | ||
407 | */ | ||
408 | lid_device = device; | ||
409 | } | ||
369 | 410 | ||
370 | if (device->wakeup.flags.valid) { | 411 | if (device->wakeup.flags.valid) { |
371 | /* Button's GPE is run-wake GPE */ | 412 | /* Button's GPE is run-wake GPE */ |
diff --git a/include/acpi/button.h b/include/acpi/button.h new file mode 100644 index 000000000000..bb643a79d651 --- /dev/null +++ b/include/acpi/button.h | |||
@@ -0,0 +1,10 @@ | |||
1 | #ifndef ACPI_BUTTON_H | ||
2 | #define ACPI_BUTTON_H | ||
3 | |||
4 | #include <linux/notifier.h> | ||
5 | |||
6 | extern int acpi_lid_notifier_register(struct notifier_block *nb); | ||
7 | extern int acpi_lid_notifier_unregister(struct notifier_block *nb); | ||
8 | extern int acpi_lid_open(void); | ||
9 | |||
10 | #endif /* ACPI_BUTTON_H */ | ||