From 17b9d03c182da6c9dba4dc39da5850e8fac1d407 Mon Sep 17 00:00:00 2001 From: AceLan Kao Date: Thu, 8 Sep 2011 10:43:08 +0800 Subject: [PATCH] acer-wmi: support Acer Aspire/eMachines 4739z There are 2 kind of 4739Z, the one that vendor name is ACER sents out the correct brightness key events, so we don't need quirk for it. And another one with eMachines as it's vendor name follows Acer WMI spec. and doesn't sent out brightness key events, so I added a new quirk, quirk_acer_aspire_4739z, for it, and handle the key events in acer_wmi_notify(). BTW, we need other key event types that defined in Acer WMI spec., so I added them in acer_wmi_event_ids enumerate. Signed-off-by: AceLan Kao --- drivers/platform/x86/acer-wmi.c | 77 +++++++++++++++++++++++++++++++++++++-- 1 files changed, 73 insertions(+), 4 deletions(-) diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index df730c9..a353153 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -94,6 +94,10 @@ MODULE_ALIAS("wmi:676AA15E-6A47-4D9F-A2CC-1E6D18D14026"); enum acer_wmi_event_ids { WMID_HOTKEY_EVENT = 0x1, + WMID_HOTKEY_BREAK_EVENT = 0x2, + WMID_GRAPHIC_SWITCH_EVENT = 0x3, + WMID_BRIGHTNESS_CHANGE_EVENT = 0x4, + WMID_SENSOR_EVENT = 0x5, }; static const struct key_entry acer_wmi_keymap[] = { @@ -112,9 +116,9 @@ static const struct key_entry acer_wmi_keymap[] = { {KE_IGNORE, 0x45, {KEY_STOP} }, {KE_IGNORE, 0x48, {KEY_VOLUMEUP} }, {KE_IGNORE, 0x49, {KEY_VOLUMEDOWN} }, - {KE_IGNORE, 0x61, {KEY_SWITCHVIDEOMODE} }, - {KE_IGNORE, 0x62, {KEY_BRIGHTNESSUP} }, - {KE_IGNORE, 0x63, {KEY_BRIGHTNESSDOWN} }, + {KE_KEY, 0x61, {KEY_SWITCHVIDEOMODE} }, + {KE_KEY, 0x62, {KEY_BRIGHTNESSUP} }, + {KE_KEY, 0x63, {KEY_BRIGHTNESSDOWN} }, {KE_KEY, 0x64, {KEY_SWITCHVIDEOMODE} }, /* Display Switch */ {KE_IGNORE, 0x81, {KEY_SLEEP} }, {KE_KEY, 0x82, {KEY_TOUCHPAD_TOGGLE} }, /* Touch Pad On/Off */ @@ -131,6 +135,15 @@ struct event_return_value { u32 reserved; } __attribute__((packed)); + +struct brightness_event { + u8 function; + u8 brightness; + u8 brightness_2nd_display; + u8 reserved; + u32 reserved2; +} __packed; + /* * GUID3 Get Device Status device flags */ @@ -199,6 +212,7 @@ enum interface_flags { #define ACER_DEFAULT_THREEG 0 static int max_brightness = 0xF; +static int cur_brightness = 9; static int mailled = -1; static int brightness = -1; @@ -310,6 +324,10 @@ static struct quirk_entry quirk_lenovo_ideapad_s205 = { .wireless = 3, }; +static struct quirk_entry quirk_acer_aspire_4739z = { + .brightness = 2, +}; + /* The Aspire One has a dummy ACPI-WMI interface - disable it */ static struct dmi_system_id __devinitdata acer_blacklist[] = { { @@ -368,6 +386,23 @@ static struct dmi_system_id acer_quirks[] = { }, { .callback = dmi_matched, + .ident = "Acer Aspire 4739Z", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "AS4739Z"), + }, + }, + { + .callback = dmi_matched, + .ident = "Acer eMachines 4739Z", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "eMachines"), + DMI_MATCH(DMI_PRODUCT_NAME, "AS4739Z"), + }, + .driver_data = &quirk_acer_aspire_4739z, + }, + { + .callback = dmi_matched, .ident = "Acer Aspire 5100", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), @@ -1446,7 +1481,7 @@ static void acer_rfkill_exit(void) static ssize_t show_bool_threeg(struct device *dev, struct device_attribute *attr, char *buf) { - u32 result; \ + u32 result; acpi_status status; pr_info("This threeg sysfs will be removed in 2012" @@ -1501,6 +1536,7 @@ static void acer_wmi_notify(u32 value, void *context) struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *obj; struct event_return_value return_value; + struct brightness_event brightness_value; acpi_status status; u16 device_state; const struct key_entry *key; @@ -1531,6 +1567,7 @@ static void acer_wmi_notify(u32 value, void *context) switch (return_value.function) { case WMID_HOTKEY_EVENT: + case WMID_HOTKEY_BREAK_EVENT: device_state = return_value.device_state; pr_debug("device state: 0x%x\n", device_state); @@ -1558,6 +1595,38 @@ static void acer_wmi_notify(u32 value, void *context) 1, true); } break; + case WMID_BRIGHTNESS_CHANGE_EVENT: + /* to avoid the brightness event be handled twice */ + if (quirks->brightness != 2) + break; + /* we need ACPI video backlight support */ + if (!acpi_video_backlight_support()) + break; + + brightness_value = + *((struct brightness_event *)&return_value); + /* brightness is decreasing */ + if (cur_brightness > brightness_value.brightness) + key = sparse_keymap_entry_from_scancode( + acer_wmi_input_dev, 0x63); + /* brightness is increasing */ + else if (cur_brightness < brightness_value.brightness) + key = sparse_keymap_entry_from_scancode( + acer_wmi_input_dev, 0x62); + /* brightness is already at the bottom */ + else if (cur_brightness == 0) + key = sparse_keymap_entry_from_scancode( + acer_wmi_input_dev, 0x63); + /* brightness is already at the top */ + else if (cur_brightness == 9) + key = sparse_keymap_entry_from_scancode( + acer_wmi_input_dev, 0x62); + + sparse_keymap_report_entry(acer_wmi_input_dev, key, 1, true); + cur_brightness = return_value.key_num; + break; + case WMID_GRAPHIC_SWITCH_EVENT: + case WMID_SENSOR_EVENT: default: pr_warn("Unknown function number - %d - %d\n", return_value.function, return_value.key_num); -- 1.7.5.4