diff options
Diffstat (limited to 'drivers/acpi/button.c')
-rw-r--r-- | drivers/acpi/button.c | 45 |
1 files changed, 43 insertions, 2 deletions
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index d295bdccc09c..9335b87c5174 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c | |||
@@ -115,6 +115,9 @@ static const struct file_operations acpi_button_state_fops = { | |||
115 | .release = single_release, | 115 | .release = single_release, |
116 | }; | 116 | }; |
117 | 117 | ||
118 | static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier); | ||
119 | static struct acpi_device *lid_device; | ||
120 | |||
118 | /* -------------------------------------------------------------------------- | 121 | /* -------------------------------------------------------------------------- |
119 | FS Interface (/proc) | 122 | FS Interface (/proc) |
120 | -------------------------------------------------------------------------- */ | 123 | -------------------------------------------------------------------------- */ |
@@ -231,11 +234,38 @@ static int acpi_button_remove_fs(struct acpi_device *device) | |||
231 | /* -------------------------------------------------------------------------- | 234 | /* -------------------------------------------------------------------------- |
232 | Driver Interface | 235 | Driver Interface |
233 | -------------------------------------------------------------------------- */ | 236 | -------------------------------------------------------------------------- */ |
237 | int acpi_lid_notifier_register(struct notifier_block *nb) | ||
238 | { | ||
239 | return blocking_notifier_chain_register(&acpi_lid_notifier, nb); | ||
240 | } | ||
241 | EXPORT_SYMBOL(acpi_lid_notifier_register); | ||
242 | |||
243 | int acpi_lid_notifier_unregister(struct notifier_block *nb) | ||
244 | { | ||
245 | return blocking_notifier_chain_unregister(&acpi_lid_notifier, nb); | ||
246 | } | ||
247 | EXPORT_SYMBOL(acpi_lid_notifier_unregister); | ||
248 | |||
249 | int acpi_lid_open(void) | ||
250 | { | ||
251 | acpi_status status; | ||
252 | unsigned long long state; | ||
253 | |||
254 | status = acpi_evaluate_integer(lid_device->handle, "_LID", NULL, | ||
255 | &state); | ||
256 | if (ACPI_FAILURE(status)) | ||
257 | return -ENODEV; | ||
258 | |||
259 | return !!state; | ||
260 | } | ||
261 | EXPORT_SYMBOL(acpi_lid_open); | ||
262 | |||
234 | static int acpi_lid_send_state(struct acpi_device *device) | 263 | static int acpi_lid_send_state(struct acpi_device *device) |
235 | { | 264 | { |
236 | struct acpi_button *button = acpi_driver_data(device); | 265 | struct acpi_button *button = acpi_driver_data(device); |
237 | unsigned long long state; | 266 | unsigned long long state; |
238 | acpi_status status; | 267 | acpi_status status; |
268 | int ret; | ||
239 | 269 | ||
240 | status = acpi_evaluate_integer(device->handle, "_LID", NULL, &state); | 270 | status = acpi_evaluate_integer(device->handle, "_LID", NULL, &state); |
241 | if (ACPI_FAILURE(status)) | 271 | if (ACPI_FAILURE(status)) |
@@ -244,7 +274,12 @@ static int acpi_lid_send_state(struct acpi_device *device) | |||
244 | /* input layer checks if event is redundant */ | 274 | /* input layer checks if event is redundant */ |
245 | input_report_switch(button->input, SW_LID, !state); | 275 | input_report_switch(button->input, SW_LID, !state); |
246 | input_sync(button->input); | 276 | input_sync(button->input); |
247 | return 0; | 277 | |
278 | ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device); | ||
279 | if (ret == NOTIFY_DONE) | ||
280 | ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, | ||
281 | device); | ||
282 | return ret; | ||
248 | } | 283 | } |
249 | 284 | ||
250 | static void acpi_button_notify(struct acpi_device *device, u32 event) | 285 | static void acpi_button_notify(struct acpi_device *device, u32 event) |
@@ -366,8 +401,14 @@ static int acpi_button_add(struct acpi_device *device) | |||
366 | error = input_register_device(input); | 401 | error = input_register_device(input); |
367 | if (error) | 402 | if (error) |
368 | goto err_remove_fs; | 403 | goto err_remove_fs; |
369 | if (button->type == ACPI_BUTTON_TYPE_LID) | 404 | if (button->type == ACPI_BUTTON_TYPE_LID) { |
370 | acpi_lid_send_state(device); | 405 | acpi_lid_send_state(device); |
406 | /* | ||
407 | * This assumes there's only one lid device, or if there are | ||
408 | * more we only care about the last one... | ||
409 | */ | ||
410 | lid_device = device; | ||
411 | } | ||
371 | 412 | ||
372 | if (device->wakeup.flags.valid) { | 413 | if (device->wakeup.flags.valid) { |
373 | /* Button's GPE is run-wake GPE */ | 414 | /* Button's GPE is run-wake GPE */ |