|
@@ -44,6 +44,7 @@
|
|
|
#include <linux/dmi.h>
|
|
|
#include <acpi/acpi_bus.h>
|
|
|
#include <acpi/acpi_drivers.h>
|
|
|
+#include <linux/suspend.h>
|
|
|
|
|
|
#define PREFIX "ACPI: "
|
|
|
|
|
@@ -89,7 +90,6 @@ module_param(allow_duplicates, bool, 0644);
|
|
|
static int register_count = 0;
|
|
|
static int acpi_video_bus_add(struct acpi_device *device);
|
|
|
static int acpi_video_bus_remove(struct acpi_device *device, int type);
|
|
|
-static int acpi_video_resume(struct acpi_device *device);
|
|
|
static void acpi_video_bus_notify(struct acpi_device *device, u32 event);
|
|
|
|
|
|
static const struct acpi_device_id video_device_ids[] = {
|
|
@@ -105,7 +105,6 @@ static struct acpi_driver acpi_video_bus = {
|
|
|
.ops = {
|
|
|
.add = acpi_video_bus_add,
|
|
|
.remove = acpi_video_bus_remove,
|
|
|
- .resume = acpi_video_resume,
|
|
|
.notify = acpi_video_bus_notify,
|
|
|
},
|
|
|
};
|
|
@@ -160,6 +159,7 @@ struct acpi_video_bus {
|
|
|
struct proc_dir_entry *dir;
|
|
|
struct input_dev *input;
|
|
|
char phys[32]; /* for input device */
|
|
|
+ struct notifier_block pm_nb;
|
|
|
};
|
|
|
|
|
|
struct acpi_video_device_flags {
|
|
@@ -1021,6 +1021,13 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
|
|
|
if (IS_ERR(device->backlight))
|
|
|
return;
|
|
|
|
|
|
+ /*
|
|
|
+ * Save current brightness level in case we have to restore it
|
|
|
+ * before acpi_video_device_lcd_set_level() is called next time.
|
|
|
+ */
|
|
|
+ device->backlight->props.brightness =
|
|
|
+ acpi_video_get_brightness(device->backlight);
|
|
|
+
|
|
|
result = sysfs_create_link(&device->backlight->dev.kobj,
|
|
|
&device->dev->dev.kobj, "device");
|
|
|
if (result)
|
|
@@ -2123,7 +2130,7 @@ static void acpi_video_bus_notify(struct acpi_device *device, u32 event)
|
|
|
{
|
|
|
struct acpi_video_bus *video = acpi_driver_data(device);
|
|
|
struct input_dev *input;
|
|
|
- int keycode;
|
|
|
+ int keycode = 0;
|
|
|
|
|
|
if (!video)
|
|
|
return;
|
|
@@ -2159,17 +2166,19 @@ static void acpi_video_bus_notify(struct acpi_device *device, u32 event)
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
- keycode = KEY_UNKNOWN;
|
|
|
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
|
|
"Unsupported event [0x%x]\n", event));
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
acpi_notifier_call_chain(device, event, 0);
|
|
|
- input_report_key(input, keycode, 1);
|
|
|
- input_sync(input);
|
|
|
- input_report_key(input, keycode, 0);
|
|
|
- input_sync(input);
|
|
|
+
|
|
|
+ if (keycode) {
|
|
|
+ input_report_key(input, keycode, 1);
|
|
|
+ input_sync(input);
|
|
|
+ input_report_key(input, keycode, 0);
|
|
|
+ input_sync(input);
|
|
|
+ }
|
|
|
|
|
|
return;
|
|
|
}
|
|
@@ -2180,7 +2189,7 @@ static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data)
|
|
|
struct acpi_device *device = NULL;
|
|
|
struct acpi_video_bus *bus;
|
|
|
struct input_dev *input;
|
|
|
- int keycode;
|
|
|
+ int keycode = 0;
|
|
|
|
|
|
if (!video_device)
|
|
|
return;
|
|
@@ -2221,39 +2230,48 @@ static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data)
|
|
|
keycode = KEY_DISPLAY_OFF;
|
|
|
break;
|
|
|
default:
|
|
|
- keycode = KEY_UNKNOWN;
|
|
|
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
|
|
"Unsupported event [0x%x]\n", event));
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
acpi_notifier_call_chain(device, event, 0);
|
|
|
- input_report_key(input, keycode, 1);
|
|
|
- input_sync(input);
|
|
|
- input_report_key(input, keycode, 0);
|
|
|
- input_sync(input);
|
|
|
+
|
|
|
+ if (keycode) {
|
|
|
+ input_report_key(input, keycode, 1);
|
|
|
+ input_sync(input);
|
|
|
+ input_report_key(input, keycode, 0);
|
|
|
+ input_sync(input);
|
|
|
+ }
|
|
|
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
-static int instance;
|
|
|
-static int acpi_video_resume(struct acpi_device *device)
|
|
|
+static int acpi_video_resume(struct notifier_block *nb,
|
|
|
+ unsigned long val, void *ign)
|
|
|
{
|
|
|
struct acpi_video_bus *video;
|
|
|
struct acpi_video_device *video_device;
|
|
|
int i;
|
|
|
|
|
|
- if (!device || !acpi_driver_data(device))
|
|
|
- return -EINVAL;
|
|
|
+ switch (val) {
|
|
|
+ case PM_HIBERNATION_PREPARE:
|
|
|
+ case PM_SUSPEND_PREPARE:
|
|
|
+ case PM_RESTORE_PREPARE:
|
|
|
+ return NOTIFY_DONE;
|
|
|
+ }
|
|
|
|
|
|
- video = acpi_driver_data(device);
|
|
|
+ video = container_of(nb, struct acpi_video_bus, pm_nb);
|
|
|
+
|
|
|
+ dev_info(&video->device->dev, "Restoring backlight state\n");
|
|
|
|
|
|
for (i = 0; i < video->attached_count; i++) {
|
|
|
video_device = video->attached_array[i].bind_info;
|
|
|
if (video_device && video_device->backlight)
|
|
|
acpi_video_set_brightness(video_device->backlight);
|
|
|
}
|
|
|
- return AE_OK;
|
|
|
+
|
|
|
+ return NOTIFY_OK;
|
|
|
}
|
|
|
|
|
|
static acpi_status
|
|
@@ -2277,6 +2295,8 @@ acpi_video_bus_match(acpi_handle handle, u32 level, void *context,
|
|
|
return AE_OK;
|
|
|
}
|
|
|
|
|
|
+static int instance;
|
|
|
+
|
|
|
static int acpi_video_bus_add(struct acpi_device *device)
|
|
|
{
|
|
|
struct acpi_video_bus *video;
|
|
@@ -2358,7 +2378,6 @@ static int acpi_video_bus_add(struct acpi_device *device)
|
|
|
set_bit(KEY_BRIGHTNESSDOWN, input->keybit);
|
|
|
set_bit(KEY_BRIGHTNESS_ZERO, input->keybit);
|
|
|
set_bit(KEY_DISPLAY_OFF, input->keybit);
|
|
|
- set_bit(KEY_UNKNOWN, input->keybit);
|
|
|
|
|
|
error = input_register_device(input);
|
|
|
if (error)
|
|
@@ -2370,6 +2389,10 @@ static int acpi_video_bus_add(struct acpi_device *device)
|
|
|
video->flags.rom ? "yes" : "no",
|
|
|
video->flags.post ? "yes" : "no");
|
|
|
|
|
|
+ video->pm_nb.notifier_call = acpi_video_resume;
|
|
|
+ video->pm_nb.priority = 0;
|
|
|
+ register_pm_notifier(&video->pm_nb);
|
|
|
+
|
|
|
return 0;
|
|
|
|
|
|
err_free_input_dev:
|
|
@@ -2396,6 +2419,8 @@ static int acpi_video_bus_remove(struct acpi_device *device, int type)
|
|
|
|
|
|
video = acpi_driver_data(device);
|
|
|
|
|
|
+ unregister_pm_notifier(&video->pm_nb);
|
|
|
+
|
|
|
acpi_video_bus_stop_devices(video);
|
|
|
acpi_video_bus_put_devices(video);
|
|
|
acpi_video_bus_remove_fs(device);
|