aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@virtuousgeek.org>2009-09-10 18:28:02 -0400
committerEric Anholt <eric@anholt.net>2009-09-10 19:09:11 -0400
commit7e12715ecc47a8a59154afe2746e48998225bb69 (patch)
tree308e53b58027772bd114585f57c4180eb89239a7 /drivers/acpi
parentaf729a26ccc3ff9ad834a5e96f455aab20f176cd (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.c45
1 files changed, 43 insertions, 2 deletions
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 9195deba9d9..ebb593e9c38 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
116static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
117static 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 -------------------------------------------------------------------------- */
235int acpi_lid_notifier_register(struct notifier_block *nb)
236{
237 return blocking_notifier_chain_register(&acpi_lid_notifier, nb);
238}
239EXPORT_SYMBOL(acpi_lid_notifier_register);
240
241int acpi_lid_notifier_unregister(struct notifier_block *nb)
242{
243 return blocking_notifier_chain_unregister(&acpi_lid_notifier, nb);
244}
245EXPORT_SYMBOL(acpi_lid_notifier_unregister);
246
247int 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}
259EXPORT_SYMBOL(acpi_lid_open);
260
232static int acpi_lid_send_state(struct acpi_device *device) 261static 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
248static void acpi_button_notify(struct acpi_device *device, u32 event) 283static 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 */