diff options
author | Jesse Barnes <jbarnes@virtuousgeek.org> | 2009-09-10 18:28:02 -0400 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2009-09-10 19:09:11 -0400 |
commit | 7e12715ecc47a8a59154afe2746e48998225bb69 (patch) | |
tree | 308e53b58027772bd114585f57c4180eb89239a7 /drivers/acpi | |
parent | af729a26ccc3ff9ad834a5e96f455aab20f176cd (diff) |
ACPI button: provide lid status functions
Some drivers need to know when a lid event occurs and get the current
status. This can be useful for when a platform firmware clobbers some
hardware state at lid time, and a driver needs to restore things when
the lid is opened again.
Acked-by: Matthew Garrett <mjg59@srcf.ucam.org>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Diffstat (limited to 'drivers/acpi')
-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 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 */ |