From 6cae06e603339f99334bc6b276e2ac619cf0d476 Mon Sep 17 00:00:00 2001 From: AceLan Kao Date: Fri, 27 Jul 2012 16:51:59 +0800 Subject: asus-wmi: update wlan LED through rfkill led trigger For those machines with wapf=4, BIOS won't update the wireless LED, since wapf=4 means user application will take in chage of the wifi and bt. So, we have to update wlan LED status explicitly. But I found there is another wireless LED bug in launchpad and which is not in the wapf=4 quirk. So, it might be better to set wireless LED status explicitly for all machines. BugLink: https://launchpad.net/bugs/901105 Signed-off-by: AceLan Kao Signed-off-by: Matthew Garrett --- drivers/platform/x86/asus-wmi.c | 76 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index f80ae4d10f68..912ec7de71f4 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -187,6 +187,8 @@ struct asus_wmi { struct device *hwmon_device; struct platform_device *platform_device; + struct led_classdev wlan_led; + int wlan_led_wk; struct led_classdev tpd_led; int tpd_led_wk; struct led_classdev kbd_led; @@ -194,6 +196,7 @@ struct asus_wmi { struct workqueue_struct *led_workqueue; struct work_struct tpd_led_work; struct work_struct kbd_led_work; + struct work_struct wlan_led_work; struct asus_rfkill wlan; struct asus_rfkill bluetooth; @@ -456,12 +459,65 @@ static enum led_brightness kbd_led_get(struct led_classdev *led_cdev) return value; } +static int wlan_led_unknown_state(struct asus_wmi *asus) +{ + u32 result; + + asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WIRELESS_LED, &result); + + return result & ASUS_WMI_DSTS_UNKNOWN_BIT; +} + +static int wlan_led_presence(struct asus_wmi *asus) +{ + u32 result; + + asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WIRELESS_LED, &result); + + return result & ASUS_WMI_DSTS_PRESENCE_BIT; +} + +static void wlan_led_update(struct work_struct *work) +{ + int ctrl_param; + struct asus_wmi *asus; + + asus = container_of(work, struct asus_wmi, wlan_led_work); + + ctrl_param = asus->wlan_led_wk; + asus_wmi_set_devstate(ASUS_WMI_DEVID_WIRELESS_LED, ctrl_param, NULL); +} + +static void wlan_led_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + struct asus_wmi *asus; + + asus = container_of(led_cdev, struct asus_wmi, wlan_led); + + asus->wlan_led_wk = !!value; + queue_work(asus->led_workqueue, &asus->wlan_led_work); +} + +static enum led_brightness wlan_led_get(struct led_classdev *led_cdev) +{ + struct asus_wmi *asus; + u32 result; + + asus = container_of(led_cdev, struct asus_wmi, wlan_led); + asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WIRELESS_LED, &result); + + return result & ASUS_WMI_DSTS_BRIGHTNESS_MASK; +} + static void asus_wmi_led_exit(struct asus_wmi *asus) { if (!IS_ERR_OR_NULL(asus->kbd_led.dev)) led_classdev_unregister(&asus->kbd_led); if (!IS_ERR_OR_NULL(asus->tpd_led.dev)) led_classdev_unregister(&asus->tpd_led); + if (!IS_ERR_OR_NULL(asus->wlan_led.dev)) + led_classdev_unregister(&asus->wlan_led); if (asus->led_workqueue) destroy_workqueue(asus->led_workqueue); } @@ -498,6 +554,23 @@ static int asus_wmi_led_init(struct asus_wmi *asus) rv = led_classdev_register(&asus->platform_device->dev, &asus->kbd_led); + if (rv) + goto error; + } + + if (wlan_led_presence(asus)) { + INIT_WORK(&asus->wlan_led_work, wlan_led_update); + + asus->wlan_led.name = "asus::wlan"; + asus->wlan_led.brightness_set = wlan_led_set; + if (!wlan_led_unknown_state(asus)) + asus->wlan_led.brightness_get = wlan_led_get; + asus->wlan_led.flags = LED_CORE_SUSPENDRESUME; + asus->wlan_led.max_brightness = 1; + asus->wlan_led.default_trigger = "asus-wlan"; + + rv = led_classdev_register(&asus->platform_device->dev, + &asus->wlan_led); } error: @@ -813,6 +886,9 @@ static int asus_new_rfkill(struct asus_wmi *asus, if (!*rfkill) return -EINVAL; + if (dev_id == ASUS_WMI_DEVID_WLAN) + rfkill_set_led_trigger_name(*rfkill, "asus-wlan"); + rfkill_init_sw_state(*rfkill, !result); result = rfkill_register(*rfkill); if (result) { -- cgit v1.2.3 From 27eb9e7f1211ecab64027113478867adfed6a7c8 Mon Sep 17 00:00:00 2001 From: Maxim Mikityanskiy Date: Sat, 15 Dec 2012 19:31:25 +0200 Subject: msi-laptop: Use proper return codes instead of -1 Use proper function return codes instead of -1 Signed-off-by: Maxim Mikityanskiy Signed-off-by: Lee, Chun-Yi Signed-off-by: Matthew Garrett --- drivers/platform/x86/msi-laptop.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c index 2111dbb7e1e3..063113ca299e 100644 --- a/drivers/platform/x86/msi-laptop.c +++ b/drivers/platform/x86/msi-laptop.c @@ -198,7 +198,7 @@ static ssize_t set_device_state(const char *buf, size_t count, u8 mask) /* read current device state */ result = ec_read(MSI_STANDARD_EC_COMMAND_ADDRESS, &rdata); if (result < 0) - return -EINVAL; + return result; if (!!(rdata & mask) != status) { /* reverse device bit */ @@ -209,7 +209,7 @@ static ssize_t set_device_state(const char *buf, size_t count, u8 mask) result = ec_write(MSI_STANDARD_EC_COMMAND_ADDRESS, wdata); if (result < 0) - return -EINVAL; + return result; } return count; @@ -222,7 +222,7 @@ static int get_wireless_state(int *wlan, int *bluetooth) result = ec_transaction(MSI_EC_COMMAND_WIRELESS, &wdata, 1, &rdata, 1); if (result < 0) - return -1; + return result; if (wlan) *wlan = !!(rdata & 8); @@ -240,7 +240,7 @@ static int get_wireless_state_ec_standard(void) result = ec_read(MSI_STANDARD_EC_COMMAND_ADDRESS, &rdata); if (result < 0) - return -1; + return result; wlan_s = !!(rdata & MSI_STANDARD_EC_WLAN_MASK); @@ -258,7 +258,7 @@ static int get_threeg_exists(void) result = ec_read(MSI_STANDARD_EC_DEVICES_EXISTS_ADDRESS, &rdata); if (result < 0) - return -1; + return result; threeg_exists = !!(rdata & MSI_STANDARD_EC_3G_MASK); @@ -343,7 +343,7 @@ static ssize_t show_threeg(struct device *dev, /* old msi ec not support 3G */ if (old_ec_model) - return -1; + return -ENODEV; ret = get_wireless_state_ec_standard(); if (ret < 0) -- cgit v1.2.3 From 1b6517a0a99b3a950d708d31de1a015843039066 Mon Sep 17 00:00:00 2001 From: Maxim Mikityanskiy Date: Sat, 15 Dec 2012 19:31:26 +0200 Subject: msi-laptop: Work around gcc warning Assign initial value to variable in order to prevent gcc warning about uninitialized variable. Signed-off-by: Maxim Mikityanskiy Signed-off-by: Lee, Chun-Yi Signed-off-by: Matthew Garrett --- drivers/platform/x86/msi-laptop.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c index 063113ca299e..7ba107ae1d09 100644 --- a/drivers/platform/x86/msi-laptop.c +++ b/drivers/platform/x86/msi-laptop.c @@ -291,7 +291,7 @@ static ssize_t show_wlan(struct device *dev, struct device_attribute *attr, char *buf) { - int ret, enabled; + int ret, enabled = 0; if (old_ec_model) { ret = get_wireless_state(&enabled, NULL); @@ -315,7 +315,7 @@ static ssize_t show_bluetooth(struct device *dev, struct device_attribute *attr, char *buf) { - int ret, enabled; + int ret, enabled = 0; if (old_ec_model) { ret = get_wireless_state(NULL, &enabled); -- cgit v1.2.3 From 0816392b97d45b779c6ab2cfac4e1561d3ef7242 Mon Sep 17 00:00:00 2001 From: "Lee, Chun-Yi" Date: Sat, 15 Dec 2012 19:31:27 +0200 Subject: msi-laptop: merge quirk tables to one This patch introduced a quirk_entry struct, then we merged all quirk tables to msi_dmi_table. Then we can more easily to set different quirk attributes for different machine. Signed-off-by: Lee, Chun-Yi Changed this patch so that it could be applied before MSI Wind U100 support patch. Changed rfkill logic for ec_read_only quirk support. Removed delays if ec_delay = false. Signed-off-by: Maxim Mikityanskiy Acked-by: Lee, Chun-Yi Signed-off-by: Matthew Garrett --- drivers/platform/x86/msi-laptop.c | 196 ++++++++++++++++++++++++-------------- 1 file changed, 127 insertions(+), 69 deletions(-) diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c index 7ba107ae1d09..0bf94b5c2744 100644 --- a/drivers/platform/x86/msi-laptop.c +++ b/drivers/platform/x86/msi-laptop.c @@ -108,23 +108,38 @@ static const struct key_entry msi_laptop_keymap[] = { static struct input_dev *msi_laptop_input_dev; -static bool old_ec_model; static int wlan_s, bluetooth_s, threeg_s; static int threeg_exists; - -/* Some MSI 3G netbook only have one fn key to control Wlan/Bluetooth/3G, - * those netbook will load the SCM (windows app) to disable the original - * Wlan/Bluetooth control by BIOS when user press fn key, then control - * Wlan/Bluetooth/3G by SCM (software control by OS). Without SCM, user - * cann't on/off 3G module on those 3G netbook. - * On Linux, msi-laptop driver will do the same thing to disable the - * original BIOS control, then might need use HAL or other userland - * application to do the software control that simulate with SCM. - * e.g. MSI N034 netbook - */ -static bool load_scm_model; static struct rfkill *rfk_wlan, *rfk_bluetooth, *rfk_threeg; +/* MSI laptop quirks */ +struct quirk_entry { + bool old_ec_model; + + /* Some MSI 3G netbook only have one fn key to control + * Wlan/Bluetooth/3G, those netbook will load the SCM (windows app) to + * disable the original Wlan/Bluetooth control by BIOS when user press + * fn key, then control Wlan/Bluetooth/3G by SCM (software control by + * OS). Without SCM, user cann't on/off 3G module on those 3G netbook. + * On Linux, msi-laptop driver will do the same thing to disable the + * original BIOS control, then might need use HAL or other userland + * application to do the software control that simulate with SCM. + * e.g. MSI N034 netbook + */ + bool load_scm_model; + + /* Some MSI laptops need delay before reading from EC */ + bool ec_delay; + + /* Some MSI Wind netbooks (e.g. MSI Wind U100) need loading SCM to get + * some features working (e.g. ECO mode), but we cannot change + * Wlan/Bluetooth state in software and we can only read its state. + */ + bool ec_read_only; +}; + +static struct quirk_entry *quirks; + /* Hardware access */ static int set_lcd_level(int level) @@ -195,6 +210,9 @@ static ssize_t set_device_state(const char *buf, size_t count, u8 mask) if (sscanf(buf, "%i", &status) != 1 || (status < 0 || status > 1)) return -EINVAL; + if (quirks->ec_read_only) + return -EOPNOTSUPP; + /* read current device state */ result = ec_read(MSI_STANDARD_EC_COMMAND_ADDRESS, &rdata); if (result < 0) @@ -293,7 +311,7 @@ static ssize_t show_wlan(struct device *dev, int ret, enabled = 0; - if (old_ec_model) { + if (quirks->old_ec_model) { ret = get_wireless_state(&enabled, NULL); } else { ret = get_wireless_state_ec_standard(); @@ -317,7 +335,7 @@ static ssize_t show_bluetooth(struct device *dev, int ret, enabled = 0; - if (old_ec_model) { + if (quirks->old_ec_model) { ret = get_wireless_state(NULL, &enabled); } else { ret = get_wireless_state_ec_standard(); @@ -342,7 +360,7 @@ static ssize_t show_threeg(struct device *dev, int ret; /* old msi ec not support 3G */ - if (old_ec_model) + if (quirks->old_ec_model) return -ENODEV; ret = get_wireless_state_ec_standard(); @@ -448,9 +466,26 @@ static struct platform_device *msipf_device; /* Initialization */ -static int dmi_check_cb(const struct dmi_system_id *id) +static struct quirk_entry quirk_old_ec_model = { + .old_ec_model = true, +}; + +static struct quirk_entry quirk_load_scm_model = { + .load_scm_model = true, + .ec_delay = true, +}; + +static struct quirk_entry quirk_load_scm_ro_model = { + .load_scm_model = true, + .ec_read_only = true, +}; + +static int dmi_check_cb(const struct dmi_system_id *dmi) { - pr_info("Identified laptop model '%s'\n", id->ident); + pr_info("Identified laptop model '%s'\n", dmi->ident); + + quirks = dmi->driver_data; + return 1; } @@ -464,6 +499,7 @@ static struct dmi_system_id __initdata msi_dmi_table[] = { DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-STAR INT'L CO.,LTD") }, + .driver_data = &quirk_old_ec_model, .callback = dmi_check_cb }, { @@ -474,6 +510,7 @@ static struct dmi_system_id __initdata msi_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_VERSION, "0581"), DMI_MATCH(DMI_BOARD_NAME, "MS-1058") }, + .driver_data = &quirk_old_ec_model, .callback = dmi_check_cb }, { @@ -484,6 +521,7 @@ static struct dmi_system_id __initdata msi_dmi_table[] = { DMI_MATCH(DMI_BOARD_VENDOR, "MSI"), DMI_MATCH(DMI_BOARD_NAME, "MS-1412") }, + .driver_data = &quirk_old_ec_model, .callback = dmi_check_cb }, { @@ -495,12 +533,9 @@ static struct dmi_system_id __initdata msi_dmi_table[] = { DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-STAR INT'L CO.,LTD") }, + .driver_data = &quirk_old_ec_model, .callback = dmi_check_cb }, - { } -}; - -static struct dmi_system_id __initdata msi_load_scm_models_dmi_table[] = { { .ident = "MSI N034", .matches = { @@ -510,6 +545,7 @@ static struct dmi_system_id __initdata msi_load_scm_models_dmi_table[] = { DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD") }, + .driver_data = &quirk_load_scm_model, .callback = dmi_check_cb }, { @@ -521,6 +557,7 @@ static struct dmi_system_id __initdata msi_load_scm_models_dmi_table[] = { DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD") }, + .driver_data = &quirk_load_scm_model, .callback = dmi_check_cb }, { @@ -530,6 +567,7 @@ static struct dmi_system_id __initdata msi_load_scm_models_dmi_table[] = { "MICRO-STAR INTERNATIONAL CO., LTD"), DMI_MATCH(DMI_PRODUCT_NAME, "MS-N014"), }, + .driver_data = &quirk_load_scm_model, .callback = dmi_check_cb }, { @@ -539,6 +577,7 @@ static struct dmi_system_id __initdata msi_load_scm_models_dmi_table[] = { "Micro-Star International"), DMI_MATCH(DMI_PRODUCT_NAME, "CR620"), }, + .driver_data = &quirk_load_scm_model, .callback = dmi_check_cb }, { @@ -548,6 +587,7 @@ static struct dmi_system_id __initdata msi_load_scm_models_dmi_table[] = { "Micro-Star International Co., Ltd."), DMI_MATCH(DMI_PRODUCT_NAME, "U270 series"), }, + .driver_data = &quirk_load_scm_model, .callback = dmi_check_cb }, { } @@ -560,32 +600,26 @@ static int rfkill_bluetooth_set(void *data, bool blocked) * blocked == false is on * blocked == true is off */ - if (blocked) - set_device_state("0", 0, MSI_STANDARD_EC_BLUETOOTH_MASK); - else - set_device_state("1", 0, MSI_STANDARD_EC_BLUETOOTH_MASK); + int result = set_device_state(blocked ? "0" : "1", 0, + MSI_STANDARD_EC_BLUETOOTH_MASK); - return 0; + return min(result, 0); } static int rfkill_wlan_set(void *data, bool blocked) { - if (blocked) - set_device_state("0", 0, MSI_STANDARD_EC_WLAN_MASK); - else - set_device_state("1", 0, MSI_STANDARD_EC_WLAN_MASK); + int result = set_device_state(blocked ? "0" : "1", 0, + MSI_STANDARD_EC_WLAN_MASK); - return 0; + return min(result, 0); } static int rfkill_threeg_set(void *data, bool blocked) { - if (blocked) - set_device_state("0", 0, MSI_STANDARD_EC_3G_MASK); - else - set_device_state("1", 0, MSI_STANDARD_EC_3G_MASK); + int result = set_device_state(blocked ? "0" : "1", 0, + MSI_STANDARD_EC_3G_MASK); - return 0; + return min(result, 0); } static const struct rfkill_ops rfkill_bluetooth_ops = { @@ -618,18 +652,27 @@ static void rfkill_cleanup(void) } } +static bool msi_rfkill_set_state(struct rfkill *rfkill, bool blocked) +{ + if (quirks->ec_read_only) + return rfkill_set_hw_state(rfkill, blocked); + else + return rfkill_set_sw_state(rfkill, blocked); +} + static void msi_update_rfkill(struct work_struct *ignored) { get_wireless_state_ec_standard(); if (rfk_wlan) - rfkill_set_sw_state(rfk_wlan, !wlan_s); + msi_rfkill_set_state(rfk_wlan, !wlan_s); if (rfk_bluetooth) - rfkill_set_sw_state(rfk_bluetooth, !bluetooth_s); + msi_rfkill_set_state(rfk_bluetooth, !bluetooth_s); if (rfk_threeg) - rfkill_set_sw_state(rfk_threeg, !threeg_s); + msi_rfkill_set_state(rfk_threeg, !threeg_s); } -static DECLARE_DELAYED_WORK(msi_rfkill_work, msi_update_rfkill); +static DECLARE_DELAYED_WORK(msi_rfkill_dwork, msi_update_rfkill); +static DECLARE_WORK(msi_rfkill_work, msi_update_rfkill); static void msi_send_touchpad_key(struct work_struct *ignored) { @@ -644,7 +687,8 @@ static void msi_send_touchpad_key(struct work_struct *ignored) (rdata & MSI_STANDARD_EC_TOUCHPAD_MASK) ? KEY_TOUCHPAD_ON : KEY_TOUCHPAD_OFF, 1, true); } -static DECLARE_DELAYED_WORK(msi_touchpad_work, msi_send_touchpad_key); +static DECLARE_DELAYED_WORK(msi_touchpad_dwork, msi_send_touchpad_key); +static DECLARE_WORK(msi_touchpad_work, msi_send_touchpad_key); static bool msi_laptop_i8042_filter(unsigned char data, unsigned char str, struct serio *port) @@ -662,14 +706,20 @@ static bool msi_laptop_i8042_filter(unsigned char data, unsigned char str, extended = false; switch (data) { case 0xE4: - schedule_delayed_work(&msi_touchpad_work, - round_jiffies_relative(0.5 * HZ)); + if (quirks->ec_delay) { + schedule_delayed_work(&msi_touchpad_dwork, + round_jiffies_relative(0.5 * HZ)); + } else + schedule_work(&msi_touchpad_work); break; case 0x54: case 0x62: case 0x76: - schedule_delayed_work(&msi_rfkill_work, - round_jiffies_relative(0.5 * HZ)); + if (quirks->ec_delay) { + schedule_delayed_work(&msi_rfkill_dwork, + round_jiffies_relative(0.5 * HZ)); + } else + schedule_work(&msi_rfkill_work); break; } } @@ -736,8 +786,11 @@ static int rfkill_init(struct platform_device *sdev) } /* schedule to run rfkill state initial */ - schedule_delayed_work(&msi_rfkill_init, - round_jiffies_relative(1 * HZ)); + if (quirks->ec_delay) { + schedule_delayed_work(&msi_rfkill_init, + round_jiffies_relative(1 * HZ)); + } else + schedule_work(&msi_rfkill_work); return 0; @@ -761,7 +814,7 @@ static int msi_laptop_resume(struct device *device) u8 data; int result; - if (!load_scm_model) + if (!quirks->load_scm_model) return 0; /* set load SCM to disable hardware control by fn key */ @@ -819,13 +872,15 @@ static int __init load_scm_model_init(struct platform_device *sdev) u8 data; int result; - /* allow userland write sysfs file */ - dev_attr_bluetooth.store = store_bluetooth; - dev_attr_wlan.store = store_wlan; - dev_attr_threeg.store = store_threeg; - dev_attr_bluetooth.attr.mode |= S_IWUSR; - dev_attr_wlan.attr.mode |= S_IWUSR; - dev_attr_threeg.attr.mode |= S_IWUSR; + if (!quirks->ec_read_only) { + /* allow userland write sysfs file */ + dev_attr_bluetooth.store = store_bluetooth; + dev_attr_wlan.store = store_wlan; + dev_attr_threeg.store = store_threeg; + dev_attr_bluetooth.attr.mode |= S_IWUSR; + dev_attr_wlan.attr.mode |= S_IWUSR; + dev_attr_threeg.attr.mode |= S_IWUSR; + } /* disable hardware control by fn key */ result = ec_read(MSI_STANDARD_EC_SCM_LOAD_ADDRESS, &data); @@ -874,15 +929,16 @@ static int __init msi_init(void) if (acpi_disabled) return -ENODEV; - if (force || dmi_check_system(msi_dmi_table)) - old_ec_model = 1; + dmi_check_system(msi_dmi_table); + if (!quirks) + /* quirks may be NULL if no match in DMI table */ + quirks = &quirk_load_scm_model; + if (force) + quirks = &quirk_old_ec_model; - if (!old_ec_model) + if (!quirks->old_ec_model) get_threeg_exists(); - if (!old_ec_model && dmi_check_system(msi_load_scm_models_dmi_table)) - load_scm_model = 1; - if (auto_brightness < 0 || auto_brightness > 2) return -EINVAL; @@ -918,7 +974,7 @@ static int __init msi_init(void) if (ret) goto fail_platform_device1; - if (load_scm_model && (load_scm_model_init(msipf_device) < 0)) { + if (quirks->load_scm_model && (load_scm_model_init(msipf_device) < 0)) { ret = -EINVAL; goto fail_platform_device1; } @@ -928,7 +984,7 @@ static int __init msi_init(void) if (ret) goto fail_platform_device2; - if (!old_ec_model) { + if (!quirks->old_ec_model) { if (threeg_exists) ret = device_create_file(&msipf_device->dev, &dev_attr_threeg); @@ -949,9 +1005,10 @@ static int __init msi_init(void) fail_platform_device2: - if (load_scm_model) { + if (quirks->load_scm_model) { i8042_remove_filter(msi_laptop_i8042_filter); - cancel_delayed_work_sync(&msi_rfkill_work); + cancel_delayed_work_sync(&msi_rfkill_dwork); + cancel_work_sync(&msi_rfkill_work); rfkill_cleanup(); } platform_device_del(msipf_device); @@ -973,15 +1030,16 @@ fail_backlight: static void __exit msi_cleanup(void) { - if (load_scm_model) { + if (quirks->load_scm_model) { i8042_remove_filter(msi_laptop_i8042_filter); msi_laptop_input_destroy(); - cancel_delayed_work_sync(&msi_rfkill_work); + cancel_delayed_work_sync(&msi_rfkill_dwork); + cancel_work_sync(&msi_rfkill_work); rfkill_cleanup(); } sysfs_remove_group(&msipf_device->dev.kobj, &msipf_attribute_group); - if (!old_ec_model && threeg_exists) + if (!quirks->old_ec_model && threeg_exists) device_remove_file(&msipf_device->dev, &dev_attr_threeg); platform_device_unregister(msipf_device); platform_driver_unregister(&msipf_driver); -- cgit v1.2.3 From 0de6575ad0a8f19ccf91d6e783b2a1bba0edb7a5 Mon Sep 17 00:00:00 2001 From: Maxim Mikityanskiy Date: Sat, 15 Dec 2012 19:31:28 +0200 Subject: msi-laptop: Add MSI Wind U90/U100 support Add MSI Wind U90/U100 to DMI table and add some missing EC features support such as basic fan control, turbo and ECO modes and touchpad state. Tested on MSI Wind U100. Signed-off-by: Maxim Mikityanskiy Signed-off-by: Lee, Chun-Yi Signed-off-by: Matthew Garrett --- drivers/platform/x86/msi-laptop.c | 123 +++++++++++++++++++++++++++++++++++++- 1 file changed, 121 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c index 0bf94b5c2744..28bcbb21d120 100644 --- a/drivers/platform/x86/msi-laptop.c +++ b/drivers/platform/x86/msi-laptop.c @@ -82,8 +82,19 @@ #define MSI_STANDARD_EC_SCM_LOAD_ADDRESS 0x2d #define MSI_STANDARD_EC_SCM_LOAD_MASK (1 << 0) -#define MSI_STANDARD_EC_TOUCHPAD_ADDRESS 0xe4 +#define MSI_STANDARD_EC_FUNCTIONS_ADDRESS 0xe4 +/* Power LED is orange - Turbo mode */ +#define MSI_STANDARD_EC_TURBO_MASK (1 << 1) +/* Power LED is green - ECO mode */ +#define MSI_STANDARD_EC_ECO_MASK (1 << 3) +/* Touchpad is turned on */ #define MSI_STANDARD_EC_TOUCHPAD_MASK (1 << 4) +/* If this bit != bit 1, turbo mode can't be toggled */ +#define MSI_STANDARD_EC_TURBO_COOLDOWN_MASK (1 << 7) + +#define MSI_STANDARD_EC_FAN_ADDRESS 0x33 +/* If zero, fan rotates at maximal speed */ +#define MSI_STANDARD_EC_AUTOFAN_MASK (1 << 0) #ifdef CONFIG_PM_SLEEP static int msi_laptop_resume(struct device *device); @@ -435,18 +446,115 @@ static ssize_t store_auto_brightness(struct device *dev, return count; } +static ssize_t show_touchpad(struct device *dev, + struct device_attribute *attr, char *buf) +{ + + u8 rdata; + int result; + + result = ec_read(MSI_STANDARD_EC_FUNCTIONS_ADDRESS, &rdata); + if (result < 0) + return result; + + return sprintf(buf, "%i\n", !!(rdata & MSI_STANDARD_EC_TOUCHPAD_MASK)); +} + +static ssize_t show_turbo(struct device *dev, + struct device_attribute *attr, char *buf) +{ + + u8 rdata; + int result; + + result = ec_read(MSI_STANDARD_EC_FUNCTIONS_ADDRESS, &rdata); + if (result < 0) + return result; + + return sprintf(buf, "%i\n", !!(rdata & MSI_STANDARD_EC_TURBO_MASK)); +} + +static ssize_t show_eco(struct device *dev, + struct device_attribute *attr, char *buf) +{ + + u8 rdata; + int result; + + result = ec_read(MSI_STANDARD_EC_FUNCTIONS_ADDRESS, &rdata); + if (result < 0) + return result; + + return sprintf(buf, "%i\n", !!(rdata & MSI_STANDARD_EC_ECO_MASK)); +} + +static ssize_t show_turbo_cooldown(struct device *dev, + struct device_attribute *attr, char *buf) +{ + + u8 rdata; + int result; + + result = ec_read(MSI_STANDARD_EC_FUNCTIONS_ADDRESS, &rdata); + if (result < 0) + return result; + + return sprintf(buf, "%i\n", (!!(rdata & MSI_STANDARD_EC_TURBO_MASK)) | + (!!(rdata & MSI_STANDARD_EC_TURBO_COOLDOWN_MASK) << 1)); +} + +static ssize_t show_auto_fan(struct device *dev, + struct device_attribute *attr, char *buf) +{ + + u8 rdata; + int result; + + result = ec_read(MSI_STANDARD_EC_FAN_ADDRESS, &rdata); + if (result < 0) + return result; + + return sprintf(buf, "%i\n", !!(rdata & MSI_STANDARD_EC_AUTOFAN_MASK)); +} + +static ssize_t store_auto_fan(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + + int enable, result; + + if (sscanf(buf, "%i", &enable) != 1 || (enable != (enable & 1))) + return -EINVAL; + + result = ec_write(MSI_STANDARD_EC_FAN_ADDRESS, enable); + if (result < 0) + return result; + + return count; +} + static DEVICE_ATTR(lcd_level, 0644, show_lcd_level, store_lcd_level); static DEVICE_ATTR(auto_brightness, 0644, show_auto_brightness, store_auto_brightness); static DEVICE_ATTR(bluetooth, 0444, show_bluetooth, NULL); static DEVICE_ATTR(wlan, 0444, show_wlan, NULL); static DEVICE_ATTR(threeg, 0444, show_threeg, NULL); +static DEVICE_ATTR(touchpad, 0444, show_touchpad, NULL); +static DEVICE_ATTR(turbo_mode, 0444, show_turbo, NULL); +static DEVICE_ATTR(eco_mode, 0444, show_eco, NULL); +static DEVICE_ATTR(turbo_cooldown, 0444, show_turbo_cooldown, NULL); +static DEVICE_ATTR(auto_fan, 0644, show_auto_fan, store_auto_fan); static struct attribute *msipf_attributes[] = { &dev_attr_lcd_level.attr, &dev_attr_auto_brightness.attr, &dev_attr_bluetooth.attr, &dev_attr_wlan.attr, + &dev_attr_touchpad.attr, + &dev_attr_turbo_mode.attr, + &dev_attr_eco_mode.attr, + &dev_attr_turbo_cooldown.attr, + &dev_attr_auto_fan.attr, NULL }; @@ -590,6 +698,16 @@ static struct dmi_system_id __initdata msi_dmi_table[] = { .driver_data = &quirk_load_scm_model, .callback = dmi_check_cb }, + { + .ident = "MSI U90/U100", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, + "MICRO-STAR INTERNATIONAL CO., LTD"), + DMI_MATCH(DMI_PRODUCT_NAME, "U90/U100"), + }, + .driver_data = &quirk_load_scm_ro_model, + .callback = dmi_check_cb + }, { } }; @@ -679,7 +797,7 @@ static void msi_send_touchpad_key(struct work_struct *ignored) u8 rdata; int result; - result = ec_read(MSI_STANDARD_EC_TOUCHPAD_ADDRESS, &rdata); + result = ec_read(MSI_STANDARD_EC_FUNCTIONS_ADDRESS, &rdata); if (result < 0) return; @@ -1069,3 +1187,4 @@ MODULE_ALIAS("dmi:*:svnMICRO-STARINTERNATIONAL*:pnMS-N051:*"); MODULE_ALIAS("dmi:*:svnMICRO-STARINTERNATIONAL*:pnMS-N014:*"); MODULE_ALIAS("dmi:*:svnMicro-StarInternational*:pnCR620:*"); MODULE_ALIAS("dmi:*:svnMicro-StarInternational*:pnU270series:*"); +MODULE_ALIAS("dmi:*:svnMICRO-STARINTERNATIONAL*:pnU90/U100:*"); -- cgit v1.2.3 From cdeaf3868352592b206a08039b67c80c10ade8d5 Mon Sep 17 00:00:00 2001 From: Maxim Mikityanskiy Date: Sat, 15 Dec 2012 19:31:29 +0200 Subject: msi-laptop: Add missing ABI documentation Add ABI documentation for all sysfs files exposed by msi-laptop driver. Signed-off-by: Maxim Mikityanskiy Signed-off-by: Lee, Chun-Yi Signed-off-by: Matthew Garrett --- .../ABI/testing/sysfs-platform-msi-laptop | 83 ++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-platform-msi-laptop diff --git a/Documentation/ABI/testing/sysfs-platform-msi-laptop b/Documentation/ABI/testing/sysfs-platform-msi-laptop new file mode 100644 index 000000000000..307a247ba1ef --- /dev/null +++ b/Documentation/ABI/testing/sysfs-platform-msi-laptop @@ -0,0 +1,83 @@ +What: /sys/devices/platform/msi-laptop-pf/lcd_level +Date: Oct 2006 +KernelVersion: 2.6.19 +Contact: "Lennart Poettering " +Description: + Screen brightness: contains a single integer in the range 0..8. + +What: /sys/devices/platform/msi-laptop-pf/auto_brightness +Date: Oct 2006 +KernelVersion: 2.6.19 +Contact: "Lennart Poettering " +Description: + Enable automatic brightness control: contains either 0 or 1. If + set to 1 the hardware adjusts the screen brightness + automatically when the power cord is plugged/unplugged. + +What: /sys/devices/platform/msi-laptop-pf/wlan +Date: Oct 2006 +KernelVersion: 2.6.19 +Contact: "Lennart Poettering " +Description: + WLAN subsystem enabled: contains either 0 or 1. + +What: /sys/devices/platform/msi-laptop-pf/bluetooth +Date: Oct 2006 +KernelVersion: 2.6.19 +Contact: "Lennart Poettering " +Description: + Bluetooth subsystem enabled: contains either 0 or 1. Please + note that this file is constantly 0 if no Bluetooth hardware is + available. + +What: /sys/devices/platform/msi-laptop-pf/touchpad +Date: Nov 2012 +KernelVersion: 3.8 +Contact: "Maxim Mikityanskiy " +Description: + Contains either 0 or 1 and indicates if touchpad is turned on. + Touchpad state can only be toggled by pressing Fn+F3. + +What: /sys/devices/platform/msi-laptop-pf/turbo_mode +Date: Nov 2012 +KernelVersion: 3.8 +Contact: "Maxim Mikityanskiy " +Description: + Contains either 0 or 1 and indicates if turbo mode is turned + on. In turbo mode power LED is orange and processor is + overclocked. Turbo mode is available only if charging. It is + only possible to toggle turbo mode state by pressing Fn+F10, + and there is a few seconds cooldown between subsequent toggles. + If user presses Fn+F10 too frequent, turbo mode state is not + changed. + +What: /sys/devices/platform/msi-laptop-pf/eco_mode +Date: Nov 2012 +KernelVersion: 3.8 +Contact: "Maxim Mikityanskiy " +Description: + Contains either 0 or 1 and indicates if ECO mode is turned on. + In ECO mode power LED is green and userspace should do some + powersaving actions. ECO mode is available only on battery + power. ECO mode can only be toggled by pressing Fn+F10. + +What: /sys/devices/platform/msi-laptop-pf/turbo_cooldown +Date: Nov 2012 +KernelVersion: 3.8 +Contact: "Maxim Mikityanskiy " +Description: + Contains value in range 0..3: + * 0 -> Turbo mode is off + * 1 -> Turbo mode is on, cannot be turned off yet + * 2 -> Turbo mode is off, cannot be turned on yet + * 3 -> Turbo mode is on + +What: /sys/devices/platform/msi-laptop-pf/auto_fan +Date: Nov 2012 +KernelVersion: 3.8 +Contact: "Maxim Mikityanskiy " +Description: + Contains either 0 or 1 and indicates if fan speed is controlled + automatically (1) or fan runs at maximal speed (0). Can be + toggled in software. + -- cgit v1.2.3 From 03696e51d75a3f23feb6b63dc6f3976a64c40b12 Mon Sep 17 00:00:00 2001 From: Maxim Mikityanskiy Date: Sat, 15 Dec 2012 19:31:30 +0200 Subject: msi-laptop: Disable brightness control for new EC It seems that existing brightness control works only for old EC models. On newer ones auto_brightness access always timeouts and lcd_level always shows 0. So disable brightness control for new EC models. It works fine with ACPI video driver anyway. Signed-off-by: Maxim Mikityanskiy Signed-off-by: Lee, Chun-Yi Signed-off-by: Matthew Garrett --- drivers/platform/x86/msi-laptop.c | 39 +++++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c index 28bcbb21d120..6b2293875672 100644 --- a/drivers/platform/x86/msi-laptop.c +++ b/drivers/platform/x86/msi-laptop.c @@ -546,8 +546,6 @@ static DEVICE_ATTR(turbo_cooldown, 0444, show_turbo_cooldown, NULL); static DEVICE_ATTR(auto_fan, 0644, show_auto_fan, store_auto_fan); static struct attribute *msipf_attributes[] = { - &dev_attr_lcd_level.attr, - &dev_attr_auto_brightness.attr, &dev_attr_bluetooth.attr, &dev_attr_wlan.attr, &dev_attr_touchpad.attr, @@ -558,10 +556,20 @@ static struct attribute *msipf_attributes[] = { NULL }; +static struct attribute *msipf_old_attributes[] = { + &dev_attr_lcd_level.attr, + &dev_attr_auto_brightness.attr, + NULL +}; + static struct attribute_group msipf_attribute_group = { .attrs = msipf_attributes }; +static struct attribute_group msipf_old_attribute_group = { + .attrs = msipf_old_attributes +}; + static struct platform_driver msipf_driver = { .driver = { .name = "msi-laptop-pf", @@ -1062,7 +1070,7 @@ static int __init msi_init(void) /* Register backlight stuff */ - if (acpi_video_backlight_support()) { + if (!quirks->old_ec_model || acpi_video_backlight_support()) { pr_info("Brightness ignored, must be controlled by ACPI video driver\n"); } else { struct backlight_properties props; @@ -1108,14 +1116,19 @@ static int __init msi_init(void) &dev_attr_threeg); if (ret) goto fail_platform_device2; - } + } else { + ret = sysfs_create_group(&msipf_device->dev.kobj, + &msipf_old_attribute_group); + if (ret) + goto fail_platform_device2; - /* Disable automatic brightness control by default because - * this module was probably loaded to do brightness control in - * software. */ + /* Disable automatic brightness control by default because + * this module was probably loaded to do brightness control in + * software. */ - if (auto_brightness != 2) - set_auto_brightness(auto_brightness); + if (auto_brightness != 2) + set_auto_brightness(auto_brightness); + } pr_info("driver " MSI_DRIVER_VERSION " successfully loaded\n"); @@ -1163,9 +1176,11 @@ static void __exit msi_cleanup(void) platform_driver_unregister(&msipf_driver); backlight_device_unregister(msibl_device); - /* Enable automatic brightness control again */ - if (auto_brightness != 2) - set_auto_brightness(1); + if (quirks->old_ec_model) { + /* Enable automatic brightness control again */ + if (auto_brightness != 2) + set_auto_brightness(1); + } pr_info("driver unloaded\n"); } -- cgit v1.2.3 From 51c94491c82c3d9029f6e87a1a153db321d88e35 Mon Sep 17 00:00:00 2001 From: Maxim Mikityanskiy Date: Sat, 15 Dec 2012 19:31:31 +0200 Subject: msi-wmi: Fix memory leak Fix memory leak - don't forget to kfree ACPI object when returning from msi_wmi_notify() after suppressing key event. Signed-off-by: Maxim Mikityanskiy Acked-by: Anisse Astier Signed-off-by: Lee, Chun-Yi Signed-off-by: Matthew Garrett --- drivers/platform/x86/msi-wmi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/platform/x86/msi-wmi.c b/drivers/platform/x86/msi-wmi.c index 2264331bd48e..b96766b61ea3 100644 --- a/drivers/platform/x86/msi-wmi.c +++ b/drivers/platform/x86/msi-wmi.c @@ -176,7 +176,7 @@ static void msi_wmi_notify(u32 value, void *context) pr_debug("Suppressed key event 0x%X - " "Last press was %lld us ago\n", key->code, ktime_to_us(diff)); - return; + goto msi_wmi_notify_exit; } last_pressed[key->code - SCANCODE_BASE] = cur; @@ -195,6 +195,8 @@ static void msi_wmi_notify(u32 value, void *context) pr_info("Unknown key pressed - %x\n", eventcode); } else pr_info("Unknown event received\n"); + +msi_wmi_notify_exit: kfree(response.pointer); } -- cgit v1.2.3 From dd2b0251573f5d27ae58afee64256b647041382a Mon Sep 17 00:00:00 2001 From: Maxim Mikityanskiy Date: Sat, 15 Dec 2012 19:31:32 +0200 Subject: msi-wmi: Avoid repeating constants Use UUID defines in MODULE_ALIAS strings to avoid repeating strings. Signed-off-by: Maxim Mikityanskiy Acked-by: Lee, Chun-Yi Signed-off-by: Matthew Garrett --- drivers/platform/x86/msi-wmi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/platform/x86/msi-wmi.c b/drivers/platform/x86/msi-wmi.c index b96766b61ea3..4db0c550ffcb 100644 --- a/drivers/platform/x86/msi-wmi.c +++ b/drivers/platform/x86/msi-wmi.c @@ -34,14 +34,14 @@ MODULE_AUTHOR("Thomas Renninger "); MODULE_DESCRIPTION("MSI laptop WMI hotkeys driver"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("wmi:551A1F84-FBDD-4125-91DB-3EA8F44F1D45"); -MODULE_ALIAS("wmi:B6F3EEF2-3D2F-49DC-9DE3-85BCE18C62F2"); - #define DRV_NAME "msi-wmi" #define MSIWMI_BIOS_GUID "551A1F84-FBDD-4125-91DB-3EA8F44F1D45" #define MSIWMI_EVENT_GUID "B6F3EEF2-3D2F-49DC-9DE3-85BCE18C62F2" +MODULE_ALIAS("wmi:" MSIWMI_BIOS_GUID); +MODULE_ALIAS("wmi:" MSIWMI_EVENT_GUID); + #define SCANCODE_BASE 0xD0 #define MSI_WMI_BRIGHTNESSUP SCANCODE_BASE #define MSI_WMI_BRIGHTNESSDOWN (SCANCODE_BASE + 1) -- cgit v1.2.3 From b0d3bb53beaba866ce80424fb512b1669ed88da0 Mon Sep 17 00:00:00 2001 From: Maxim Mikityanskiy Date: Sat, 15 Dec 2012 19:31:33 +0200 Subject: msi-wmi: Use enums for scancodes Use enums for consecutive scancodes, rename key names from MSI_WMI_* to MSI_KEY_* and use tabs for whitespace in msi_wmi_keymap. Signed-off-by: Maxim Mikityanskiy Acked-by: Lee, Chun-Yi Signed-off-by: Matthew Garrett --- drivers/platform/x86/msi-wmi.c | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/drivers/platform/x86/msi-wmi.c b/drivers/platform/x86/msi-wmi.c index 4db0c550ffcb..112ec1488ea8 100644 --- a/drivers/platform/x86/msi-wmi.c +++ b/drivers/platform/x86/msi-wmi.c @@ -42,19 +42,21 @@ MODULE_LICENSE("GPL"); MODULE_ALIAS("wmi:" MSIWMI_BIOS_GUID); MODULE_ALIAS("wmi:" MSIWMI_EVENT_GUID); -#define SCANCODE_BASE 0xD0 -#define MSI_WMI_BRIGHTNESSUP SCANCODE_BASE -#define MSI_WMI_BRIGHTNESSDOWN (SCANCODE_BASE + 1) -#define MSI_WMI_VOLUMEUP (SCANCODE_BASE + 2) -#define MSI_WMI_VOLUMEDOWN (SCANCODE_BASE + 3) -#define MSI_WMI_MUTE (SCANCODE_BASE + 4) +enum msi_scancodes { + MSI_SCANCODE_BASE = 0xD0, + MSI_KEY_BRIGHTNESSUP = MSI_SCANCODE_BASE, + MSI_KEY_BRIGHTNESSDOWN, + MSI_KEY_VOLUMEUP, + MSI_KEY_VOLUMEDOWN, + MSI_KEY_MUTE, +}; static struct key_entry msi_wmi_keymap[] = { - { KE_KEY, MSI_WMI_BRIGHTNESSUP, {KEY_BRIGHTNESSUP} }, - { KE_KEY, MSI_WMI_BRIGHTNESSDOWN, {KEY_BRIGHTNESSDOWN} }, - { KE_KEY, MSI_WMI_VOLUMEUP, {KEY_VOLUMEUP} }, - { KE_KEY, MSI_WMI_VOLUMEDOWN, {KEY_VOLUMEDOWN} }, - { KE_KEY, MSI_WMI_MUTE, {KEY_MUTE} }, - { KE_END, 0} + { KE_KEY, MSI_KEY_BRIGHTNESSUP, {KEY_BRIGHTNESSUP} }, + { KE_KEY, MSI_KEY_BRIGHTNESSDOWN, {KEY_BRIGHTNESSDOWN} }, + { KE_KEY, MSI_KEY_VOLUMEUP, {KEY_VOLUMEUP} }, + { KE_KEY, MSI_KEY_VOLUMEDOWN, {KEY_VOLUMEDOWN} }, + { KE_KEY, MSI_KEY_MUTE, {KEY_MUTE} }, + { KE_END, 0 } }; static ktime_t last_pressed[ARRAY_SIZE(msi_wmi_keymap) - 1]; @@ -169,7 +171,7 @@ static void msi_wmi_notify(u32 value, void *context) ktime_t diff; cur = ktime_get_real(); diff = ktime_sub(cur, last_pressed[key->code - - SCANCODE_BASE]); + MSI_SCANCODE_BASE]); /* Ignore event if the same event happened in a 50 ms timeframe -> Key press may result in 10-20 GPEs */ if (ktime_to_us(diff) < 1000 * 50) { @@ -178,13 +180,13 @@ static void msi_wmi_notify(u32 value, void *context) key->code, ktime_to_us(diff)); goto msi_wmi_notify_exit; } - last_pressed[key->code - SCANCODE_BASE] = cur; + last_pressed[key->code - MSI_SCANCODE_BASE] = cur; if (key->type == KE_KEY && /* Brightness is served via acpi video driver */ (!acpi_video_backlight_support() || - (key->code != MSI_WMI_BRIGHTNESSUP && - key->code != MSI_WMI_BRIGHTNESSDOWN))) { + (key->code != MSI_KEY_BRIGHTNESSUP && + key->code != MSI_KEY_BRIGHTNESSDOWN))) { pr_debug("Send key: 0x%X - " "Input layer keycode: %d\n", key->code, key->keycode); -- cgit v1.2.3 From da8506288fc4b2cc62d0ba477c2fe2a16f8891b0 Mon Sep 17 00:00:00 2001 From: Maxim Mikityanskiy Date: Sat, 15 Dec 2012 19:31:34 +0200 Subject: msi-wmi: Make keys and backlight independent Introduced function msi_wmi_backlight_setup() that initializes backlight device. Made driver load and work if only one WMI (only for hotkeys or only for backlight) is present. Signed-off-by: Maxim Mikityanskiy Signed-off-by: Matthew Garrett --- drivers/platform/x86/msi-wmi.c | 101 ++++++++++++++++++++++++++--------------- 1 file changed, 64 insertions(+), 37 deletions(-) diff --git a/drivers/platform/x86/msi-wmi.c b/drivers/platform/x86/msi-wmi.c index 112ec1488ea8..3a6061985e4d 100644 --- a/drivers/platform/x86/msi-wmi.c +++ b/drivers/platform/x86/msi-wmi.c @@ -60,6 +60,8 @@ static struct key_entry msi_wmi_keymap[] = { }; static ktime_t last_pressed[ARRAY_SIZE(msi_wmi_keymap) - 1]; +static const char *event_wmi_guid; + static struct backlight_device *backlight; static int backlight_map[] = { 0x00, 0x33, 0x66, 0x99, 0xCC, 0xFF }; @@ -184,7 +186,7 @@ static void msi_wmi_notify(u32 value, void *context) if (key->type == KE_KEY && /* Brightness is served via acpi video driver */ - (!acpi_video_backlight_support() || + (backlight || (key->code != MSI_KEY_BRIGHTNESSUP && key->code != MSI_KEY_BRIGHTNESSDOWN))) { pr_debug("Send key: 0x%X - " @@ -202,6 +204,31 @@ msi_wmi_notify_exit: kfree(response.pointer); } +static int __init msi_wmi_backlight_setup(void) +{ + int err; + struct backlight_properties props; + + memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_PLATFORM; + props.max_brightness = ARRAY_SIZE(backlight_map) - 1; + backlight = backlight_device_register(DRV_NAME, NULL, NULL, + &msi_backlight_ops, + &props); + if (IS_ERR(backlight)) + return PTR_ERR(backlight); + + err = bl_get(NULL); + if (err < 0) { + backlight_device_unregister(backlight); + return err; + } + + backlight->props.brightness = err; + + return 0; +} + static int __init msi_wmi_input_setup(void) { int err; @@ -238,60 +265,60 @@ static int __init msi_wmi_init(void) { int err; - if (!wmi_has_guid(MSIWMI_EVENT_GUID)) { - pr_err("This machine doesn't have MSI-hotkeys through WMI\n"); - return -ENODEV; - } - err = wmi_install_notify_handler(MSIWMI_EVENT_GUID, - msi_wmi_notify, NULL); - if (ACPI_FAILURE(err)) - return -EINVAL; + if (wmi_has_guid(MSIWMI_EVENT_GUID)) { + err = msi_wmi_input_setup(); + if (err) { + pr_err("Unable to setup input device\n"); + return err; + } - err = msi_wmi_input_setup(); - if (err) - goto err_uninstall_notifier; - - if (!acpi_video_backlight_support()) { - struct backlight_properties props; - memset(&props, 0, sizeof(struct backlight_properties)); - props.type = BACKLIGHT_PLATFORM; - props.max_brightness = ARRAY_SIZE(backlight_map) - 1; - backlight = backlight_device_register(DRV_NAME, NULL, NULL, - &msi_backlight_ops, - &props); - if (IS_ERR(backlight)) { - err = PTR_ERR(backlight); + err = wmi_install_notify_handler(MSIWMI_EVENT_GUID, + msi_wmi_notify, NULL); + if (ACPI_FAILURE(err)) { + pr_err("Unable to setup WMI notify handler\n"); goto err_free_input; } - err = bl_get(NULL); - if (err < 0) - goto err_free_backlight; + pr_debug("Event handler installed\n"); + event_wmi_guid = MSIWMI_EVENT_GUID; + } + + if (wmi_has_guid(MSIWMI_BIOS_GUID) && !acpi_video_backlight_support()) { + err = msi_wmi_backlight_setup(); + if (err) { + pr_err("Unable to setup backlight device\n"); + goto err_uninstall_handler; + } + pr_debug("Backlight device created\n"); + } - backlight->props.brightness = err; + if (!event_wmi_guid && !backlight) { + pr_err("This machine doesn't have neither MSI-hotkeys nor backlight through WMI\n"); + return -ENODEV; } - pr_debug("Event handler installed\n"); return 0; -err_free_backlight: - backlight_device_unregister(backlight); +err_uninstall_handler: + if (event_wmi_guid) + wmi_remove_notify_handler(event_wmi_guid); err_free_input: - sparse_keymap_free(msi_wmi_input_dev); - input_unregister_device(msi_wmi_input_dev); -err_uninstall_notifier: - wmi_remove_notify_handler(MSIWMI_EVENT_GUID); + if (event_wmi_guid) { + sparse_keymap_free(msi_wmi_input_dev); + input_unregister_device(msi_wmi_input_dev); + } return err; } static void __exit msi_wmi_exit(void) { - if (wmi_has_guid(MSIWMI_EVENT_GUID)) { - wmi_remove_notify_handler(MSIWMI_EVENT_GUID); + if (event_wmi_guid) { + wmi_remove_notify_handler(event_wmi_guid); sparse_keymap_free(msi_wmi_input_dev); input_unregister_device(msi_wmi_input_dev); - backlight_device_unregister(backlight); } + if (backlight) + backlight_device_unregister(backlight); } module_init(msi_wmi_init); -- cgit v1.2.3 From fedda8e7385f5fb01acb8897beca90b6256fc7bd Mon Sep 17 00:00:00 2001 From: Maxim Mikityanskiy Date: Sat, 15 Dec 2012 19:31:35 +0200 Subject: msi-wmi: Introduced quirk_last_pressed Introduced quirk_last_pressed variable that would indicate if last_pressed is used or not. Also converted last_pressed to simple variable in order to allow keymap to be non-contiguous. Signed-off-by: Maxim Mikityanskiy Signed-off-by: Matthew Garrett --- drivers/platform/x86/msi-wmi.c | 54 ++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/drivers/platform/x86/msi-wmi.c b/drivers/platform/x86/msi-wmi.c index 3a6061985e4d..739bd4d17c23 100644 --- a/drivers/platform/x86/msi-wmi.c +++ b/drivers/platform/x86/msi-wmi.c @@ -43,8 +43,7 @@ MODULE_ALIAS("wmi:" MSIWMI_BIOS_GUID); MODULE_ALIAS("wmi:" MSIWMI_EVENT_GUID); enum msi_scancodes { - MSI_SCANCODE_BASE = 0xD0, - MSI_KEY_BRIGHTNESSUP = MSI_SCANCODE_BASE, + MSI_KEY_BRIGHTNESSUP = 0xD0, MSI_KEY_BRIGHTNESSDOWN, MSI_KEY_VOLUMEUP, MSI_KEY_VOLUMEDOWN, @@ -58,7 +57,9 @@ static struct key_entry msi_wmi_keymap[] = { { KE_KEY, MSI_KEY_MUTE, {KEY_MUTE} }, { KE_END, 0 } }; -static ktime_t last_pressed[ARRAY_SIZE(msi_wmi_keymap) - 1]; + +static ktime_t last_pressed; +static bool quirk_last_pressed; static const char *event_wmi_guid; @@ -153,7 +154,6 @@ static void msi_wmi_notify(u32 value, void *context) struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; static struct key_entry *key; union acpi_object *obj; - ktime_t cur; acpi_status status; status = wmi_get_event_data(value, &response); @@ -169,12 +169,15 @@ static void msi_wmi_notify(u32 value, void *context) pr_debug("Eventcode: 0x%x\n", eventcode); key = sparse_keymap_entry_from_scancode(msi_wmi_input_dev, eventcode); - if (key) { - ktime_t diff; - cur = ktime_get_real(); - diff = ktime_sub(cur, last_pressed[key->code - - MSI_SCANCODE_BASE]); - /* Ignore event if the same event happened in a 50 ms + if (!key) { + pr_info("Unknown key pressed - %x\n", eventcode); + goto msi_wmi_notify_exit; + } + + if (quirk_last_pressed) { + ktime_t cur = ktime_get_real(); + ktime_t diff = ktime_sub(cur, last_pressed); + /* Ignore event if any event happened in a 50 ms timeframe -> Key press may result in 10-20 GPEs */ if (ktime_to_us(diff) < 1000 * 50) { pr_debug("Suppressed key event 0x%X - " @@ -182,21 +185,19 @@ static void msi_wmi_notify(u32 value, void *context) key->code, ktime_to_us(diff)); goto msi_wmi_notify_exit; } - last_pressed[key->code - MSI_SCANCODE_BASE] = cur; - - if (key->type == KE_KEY && - /* Brightness is served via acpi video driver */ - (backlight || - (key->code != MSI_KEY_BRIGHTNESSUP && - key->code != MSI_KEY_BRIGHTNESSDOWN))) { - pr_debug("Send key: 0x%X - " - "Input layer keycode: %d\n", - key->code, key->keycode); - sparse_keymap_report_entry(msi_wmi_input_dev, - key, 1, true); - } - } else - pr_info("Unknown key pressed - %x\n", eventcode); + last_pressed = cur; + } + + if (key->type == KE_KEY && + /* Brightness is served via acpi video driver */ + (backlight || + (key->code != MSI_KEY_BRIGHTNESSUP && + key->code != MSI_KEY_BRIGHTNESSDOWN))) { + pr_debug("Send key: 0x%X - Input layer keycode: %d\n", + key->code, key->keycode); + sparse_keymap_report_entry(msi_wmi_input_dev, key, 1, + true); + } } else pr_info("Unknown event received\n"); @@ -250,7 +251,7 @@ static int __init msi_wmi_input_setup(void) if (err) goto err_free_keymap; - memset(last_pressed, 0, sizeof(last_pressed)); + last_pressed = ktime_set(0, 0); return 0; @@ -281,6 +282,7 @@ static int __init msi_wmi_init(void) pr_debug("Event handler installed\n"); event_wmi_guid = MSIWMI_EVENT_GUID; + quirk_last_pressed = true; } if (wmi_has_guid(MSIWMI_BIOS_GUID) && !acpi_video_backlight_support()) { -- cgit v1.2.3 From c11ac2aa520b4777e5b063f8d8e99ce00337dcd9 Mon Sep 17 00:00:00 2001 From: Maxim Mikityanskiy Date: Sat, 15 Dec 2012 19:31:36 +0200 Subject: msi-wmi: Add MSI Wind support Add MSI Wind support to msi-wmi driver. MSI Wind has different GUID for key events, different WMI key scan codes, it does not need filtering consecutive identical events and it does not support backlight control via MSIWMI_BIOS_GUID WMI. Tested on MSI Wind U100. Signed-off-by: Maxim Mikityanskiy Signed-off-by: Matthew Garrett --- drivers/platform/x86/msi-wmi.c | 65 ++++++++++++++++++++++++++++++++---------- 1 file changed, 50 insertions(+), 15 deletions(-) diff --git a/drivers/platform/x86/msi-wmi.c b/drivers/platform/x86/msi-wmi.c index 739bd4d17c23..70222f265f68 100644 --- a/drivers/platform/x86/msi-wmi.c +++ b/drivers/platform/x86/msi-wmi.c @@ -37,17 +37,27 @@ MODULE_LICENSE("GPL"); #define DRV_NAME "msi-wmi" #define MSIWMI_BIOS_GUID "551A1F84-FBDD-4125-91DB-3EA8F44F1D45" -#define MSIWMI_EVENT_GUID "B6F3EEF2-3D2F-49DC-9DE3-85BCE18C62F2" +#define MSIWMI_MSI_EVENT_GUID "B6F3EEF2-3D2F-49DC-9DE3-85BCE18C62F2" +#define MSIWMI_WIND_EVENT_GUID "5B3CC38A-40D9-7245-8AE6-1145B751BE3F" MODULE_ALIAS("wmi:" MSIWMI_BIOS_GUID); -MODULE_ALIAS("wmi:" MSIWMI_EVENT_GUID); +MODULE_ALIAS("wmi:" MSIWMI_MSI_EVENT_GUID); +MODULE_ALIAS("wmi:" MSIWMI_WIND_EVENT_GUID); enum msi_scancodes { + /* Generic MSI keys (not present on MSI Wind) */ MSI_KEY_BRIGHTNESSUP = 0xD0, MSI_KEY_BRIGHTNESSDOWN, MSI_KEY_VOLUMEUP, MSI_KEY_VOLUMEDOWN, MSI_KEY_MUTE, + /* MSI Wind keys */ + WIND_KEY_TOUCHPAD = 0x08, /* Fn+F3 touchpad toggle */ + WIND_KEY_BLUETOOTH = 0x56, /* Fn+F11 Bluetooth toggle */ + WIND_KEY_CAMERA, /* Fn+F6 webcam toggle */ + WIND_KEY_WLAN = 0x5f, /* Fn+F11 Wi-Fi toggle */ + WIND_KEY_TURBO, /* Fn+F10 turbo mode toggle */ + WIND_KEY_ECO = 0x69, /* Fn+F10 ECO mode toggle */ }; static struct key_entry msi_wmi_keymap[] = { { KE_KEY, MSI_KEY_BRIGHTNESSUP, {KEY_BRIGHTNESSUP} }, @@ -55,13 +65,34 @@ static struct key_entry msi_wmi_keymap[] = { { KE_KEY, MSI_KEY_VOLUMEUP, {KEY_VOLUMEUP} }, { KE_KEY, MSI_KEY_VOLUMEDOWN, {KEY_VOLUMEDOWN} }, { KE_KEY, MSI_KEY_MUTE, {KEY_MUTE} }, + + /* These keys work without WMI. Ignore them to avoid double keycodes */ + { KE_IGNORE, WIND_KEY_TOUCHPAD, {KEY_TOUCHPAD_TOGGLE} }, + { KE_IGNORE, WIND_KEY_BLUETOOTH, {KEY_BLUETOOTH} }, + { KE_IGNORE, WIND_KEY_CAMERA, {KEY_CAMERA} }, + { KE_IGNORE, WIND_KEY_WLAN, {KEY_WLAN} }, + + /* These are unknown WMI events found on MSI Wind */ + { KE_IGNORE, 0x00 }, + { KE_IGNORE, 0x62 }, + { KE_IGNORE, 0x63 }, + + /* These are MSI Wind keys that should be handled via WMI */ + { KE_KEY, WIND_KEY_TURBO, {KEY_PROG1} }, + { KE_KEY, WIND_KEY_ECO, {KEY_PROG2} }, + { KE_END, 0 } }; static ktime_t last_pressed; -static bool quirk_last_pressed; -static const char *event_wmi_guid; +static const struct { + const char *guid; + bool quirk_last_pressed; +} *event_wmi, event_wmis[] = { + { MSIWMI_MSI_EVENT_GUID, true }, + { MSIWMI_WIND_EVENT_GUID, false }, +}; static struct backlight_device *backlight; @@ -174,7 +205,7 @@ static void msi_wmi_notify(u32 value, void *context) goto msi_wmi_notify_exit; } - if (quirk_last_pressed) { + if (event_wmi->quirk_last_pressed) { ktime_t cur = ktime_get_real(); ktime_t diff = ktime_sub(cur, last_pressed); /* Ignore event if any event happened in a 50 ms @@ -265,15 +296,19 @@ err_free_dev: static int __init msi_wmi_init(void) { int err; + int i; + + for (i = 0; i < ARRAY_SIZE(event_wmis); i++) { + if (!wmi_has_guid(event_wmis[i].guid)) + continue; - if (wmi_has_guid(MSIWMI_EVENT_GUID)) { err = msi_wmi_input_setup(); if (err) { pr_err("Unable to setup input device\n"); return err; } - err = wmi_install_notify_handler(MSIWMI_EVENT_GUID, + err = wmi_install_notify_handler(event_wmis[i].guid, msi_wmi_notify, NULL); if (ACPI_FAILURE(err)) { pr_err("Unable to setup WMI notify handler\n"); @@ -281,8 +316,8 @@ static int __init msi_wmi_init(void) } pr_debug("Event handler installed\n"); - event_wmi_guid = MSIWMI_EVENT_GUID; - quirk_last_pressed = true; + event_wmi = &event_wmis[i]; + break; } if (wmi_has_guid(MSIWMI_BIOS_GUID) && !acpi_video_backlight_support()) { @@ -294,7 +329,7 @@ static int __init msi_wmi_init(void) pr_debug("Backlight device created\n"); } - if (!event_wmi_guid && !backlight) { + if (!event_wmi && !backlight) { pr_err("This machine doesn't have neither MSI-hotkeys nor backlight through WMI\n"); return -ENODEV; } @@ -302,10 +337,10 @@ static int __init msi_wmi_init(void) return 0; err_uninstall_handler: - if (event_wmi_guid) - wmi_remove_notify_handler(event_wmi_guid); + if (event_wmi) + wmi_remove_notify_handler(event_wmi->guid); err_free_input: - if (event_wmi_guid) { + if (event_wmi) { sparse_keymap_free(msi_wmi_input_dev); input_unregister_device(msi_wmi_input_dev); } @@ -314,8 +349,8 @@ err_free_input: static void __exit msi_wmi_exit(void) { - if (event_wmi_guid) { - wmi_remove_notify_handler(event_wmi_guid); + if (event_wmi) { + wmi_remove_notify_handler(event_wmi->guid); sparse_keymap_free(msi_wmi_input_dev); input_unregister_device(msi_wmi_input_dev); } -- cgit v1.2.3 From 982d385ad1e8a485cfd54b30469b3710935990ba Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Wed, 3 Oct 2012 11:26:25 +0200 Subject: asus-laptop: map some new keys Signed-off-by: Corentin Chary Signed-off-by: Matthew Garrett --- drivers/platform/x86/asus-laptop.c | 3 +++ drivers/platform/x86/asus-nb-wmi.c | 1 + 2 files changed, 4 insertions(+) diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index d9f9a0dbc6f3..062ddd7791cc 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -314,6 +314,8 @@ static const struct key_entry asus_keymap[] = { {KE_KEY, 0x50, { KEY_EMAIL } }, {KE_KEY, 0x51, { KEY_WWW } }, {KE_KEY, 0x55, { KEY_CALC } }, + {KE_IGNORE, 0x57, }, /* Battery mode */ + {KE_IGNORE, 0x58, }, /* AC mode */ {KE_KEY, 0x5C, { KEY_SCREENLOCK } }, /* Screenlock */ {KE_KEY, 0x5D, { KEY_WLAN } }, {KE_KEY, 0x5E, { KEY_WLAN } }, @@ -325,6 +327,7 @@ static const struct key_entry asus_keymap[] = { {KE_KEY, 0x6B, { KEY_F13 } }, /* Lock Touchpad */ {KE_KEY, 0x6C, { KEY_SLEEP } }, /* Suspend */ {KE_KEY, 0x6D, { KEY_SLEEP } }, /* Hibernate */ + {KE_IGNORE, 0x6E, }, /* Low Battery notification */ {KE_KEY, 0x7E, { KEY_BLUETOOTH } }, {KE_KEY, 0x7D, { KEY_BLUETOOTH } }, {KE_KEY, 0x82, { KEY_CAMERA } }, diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c index be790402e0f1..b70425c58638 100644 --- a/drivers/platform/x86/asus-nb-wmi.c +++ b/drivers/platform/x86/asus-nb-wmi.c @@ -185,6 +185,7 @@ static const struct key_entry asus_nb_wmi_keymap[] = { { KE_KEY, 0x62, { KEY_SWITCHVIDEOMODE } }, { KE_KEY, 0x63, { KEY_SWITCHVIDEOMODE } }, { KE_KEY, 0x6B, { KEY_TOUCHPAD_TOGGLE } }, + { KE_IGNORE, 0x6E, }, /* Low Battery notification */ { KE_KEY, 0x7D, { KEY_BLUETOOTH } }, { KE_KEY, 0x7E, { KEY_BLUETOOTH } }, { KE_KEY, 0x82, { KEY_CAMERA } }, -- cgit v1.2.3 From a935eaecef2b209ad661dadabb4e32b7c9a9b924 Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Wed, 3 Oct 2012 11:26:26 +0200 Subject: asus-{nb-wmi|laptop}.c: sync keymaps Maybe this should be shared in another module... Signed-off-by: Corentin Chary Signed-off-by: Matthew Garrett --- drivers/platform/x86/asus-laptop.c | 36 ++++++++++++++++++------------------ drivers/platform/x86/asus-nb-wmi.c | 24 ++++++++++++------------ 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index 062ddd7791cc..7ed1e9983d3e 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -304,40 +304,40 @@ static const struct key_entry asus_keymap[] = { {KE_KEY, 0x30, { KEY_VOLUMEUP } }, {KE_KEY, 0x31, { KEY_VOLUMEDOWN } }, {KE_KEY, 0x32, { KEY_MUTE } }, - {KE_KEY, 0x33, { KEY_SWITCHVIDEOMODE } }, - {KE_KEY, 0x34, { KEY_SWITCHVIDEOMODE } }, + {KE_KEY, 0x33, { KEY_DISPLAYTOGGLE } }, /* LCD on */ + {KE_KEY, 0x34, { KEY_DISPLAY_OFF } }, /* LCD off */ {KE_KEY, 0x40, { KEY_PREVIOUSSONG } }, {KE_KEY, 0x41, { KEY_NEXTSONG } }, - {KE_KEY, 0x43, { KEY_STOPCD } }, + {KE_KEY, 0x43, { KEY_STOPCD } }, /* Stop/Eject */ {KE_KEY, 0x45, { KEY_PLAYPAUSE } }, - {KE_KEY, 0x4c, { KEY_MEDIA } }, + {KE_KEY, 0x4c, { KEY_MEDIA } }, /* WMP Key */ {KE_KEY, 0x50, { KEY_EMAIL } }, {KE_KEY, 0x51, { KEY_WWW } }, {KE_KEY, 0x55, { KEY_CALC } }, {KE_IGNORE, 0x57, }, /* Battery mode */ {KE_IGNORE, 0x58, }, /* AC mode */ {KE_KEY, 0x5C, { KEY_SCREENLOCK } }, /* Screenlock */ - {KE_KEY, 0x5D, { KEY_WLAN } }, - {KE_KEY, 0x5E, { KEY_WLAN } }, - {KE_KEY, 0x5F, { KEY_WLAN } }, + {KE_KEY, 0x5D, { KEY_WLAN } }, /* WLAN Toggle */ + {KE_KEY, 0x5E, { KEY_WLAN } }, /* WLAN Enable */ + {KE_KEY, 0x5F, { KEY_WLAN } }, /* WLAN Disable */ {KE_KEY, 0x60, { KEY_SWITCHVIDEOMODE } }, - {KE_KEY, 0x61, { KEY_SWITCHVIDEOMODE } }, - {KE_KEY, 0x62, { KEY_SWITCHVIDEOMODE } }, - {KE_KEY, 0x63, { KEY_SWITCHVIDEOMODE } }, - {KE_KEY, 0x6B, { KEY_F13 } }, /* Lock Touchpad */ + {KE_KEY, 0x61, { KEY_SWITCHVIDEOMODE } }, /* LCD Only */ + {KE_KEY, 0x62, { KEY_SWITCHVIDEOMODE } }, /* CRT Only */ + {KE_KEY, 0x63, { KEY_SWITCHVIDEOMODE } }, /* LCD + CRT */ + {KE_KEY, 0x6B, { KEY_TOUCHPAD_TOGGLE } }, /* Lock Touchpad */ {KE_KEY, 0x6C, { KEY_SLEEP } }, /* Suspend */ {KE_KEY, 0x6D, { KEY_SLEEP } }, /* Hibernate */ {KE_IGNORE, 0x6E, }, /* Low Battery notification */ - {KE_KEY, 0x7E, { KEY_BLUETOOTH } }, - {KE_KEY, 0x7D, { KEY_BLUETOOTH } }, + {KE_KEY, 0x7D, { KEY_BLUETOOTH } }, /* Bluetooth Enable */ + {KE_KEY, 0x7E, { KEY_BLUETOOTH } }, /* Bluetooth Disable */ {KE_KEY, 0x82, { KEY_CAMERA } }, - {KE_KEY, 0x88, { KEY_WLAN } }, - {KE_KEY, 0x8A, { KEY_PROG1 } }, + {KE_KEY, 0x88, { KEY_RFKILL } }, /* Radio Toggle Key */ + {KE_KEY, 0x8A, { KEY_PROG1 } }, /* Color enhancement mode */ {KE_KEY, 0x95, { KEY_MEDIA } }, {KE_KEY, 0x99, { KEY_PHONE } }, - {KE_KEY, 0xc4, { KEY_KBDILLUMUP } }, - {KE_KEY, 0xc5, { KEY_KBDILLUMDOWN } }, - {KE_KEY, 0xb5, { KEY_CALC } }, + {KE_KEY, 0xB5, { KEY_CALC } }, + {KE_KEY, 0xC4, { KEY_KBDILLUMUP } }, + {KE_KEY, 0xC5, { KEY_KBDILLUMDOWN } }, {KE_END, 0}, }; diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c index b70425c58638..9f1caa72b307 100644 --- a/drivers/platform/x86/asus-nb-wmi.c +++ b/drivers/platform/x86/asus-nb-wmi.c @@ -168,9 +168,9 @@ static const struct key_entry asus_nb_wmi_keymap[] = { { KE_KEY, 0x34, { KEY_DISPLAY_OFF } }, /* LCD off */ { KE_KEY, 0x40, { KEY_PREVIOUSSONG } }, { KE_KEY, 0x41, { KEY_NEXTSONG } }, - { KE_KEY, 0x43, { KEY_STOPCD } }, + { KE_KEY, 0x43, { KEY_STOPCD } }, /* Stop/Eject */ { KE_KEY, 0x45, { KEY_PLAYPAUSE } }, - { KE_KEY, 0x4c, { KEY_MEDIA } }, + { KE_KEY, 0x4c, { KEY_MEDIA } }, /* WMP Key */ { KE_KEY, 0x50, { KEY_EMAIL } }, { KE_KEY, 0x51, { KEY_WWW } }, { KE_KEY, 0x55, { KEY_CALC } }, @@ -181,25 +181,25 @@ static const struct key_entry asus_nb_wmi_keymap[] = { { KE_KEY, 0x5E, { KEY_WLAN } }, /* Wireless console Enable */ { KE_KEY, 0x5F, { KEY_WLAN } }, /* Wireless console Disable */ { KE_KEY, 0x60, { KEY_SWITCHVIDEOMODE } }, - { KE_KEY, 0x61, { KEY_SWITCHVIDEOMODE } }, - { KE_KEY, 0x62, { KEY_SWITCHVIDEOMODE } }, - { KE_KEY, 0x63, { KEY_SWITCHVIDEOMODE } }, + { KE_KEY, 0x61, { KEY_SWITCHVIDEOMODE } }, /* LCD Only */ + { KE_KEY, 0x62, { KEY_SWITCHVIDEOMODE } }, /* CRT Only */ + { KE_KEY, 0x63, { KEY_SWITCHVIDEOMODE } }, /* LCD + CRT */ { KE_KEY, 0x6B, { KEY_TOUCHPAD_TOGGLE } }, { KE_IGNORE, 0x6E, }, /* Low Battery notification */ - { KE_KEY, 0x7D, { KEY_BLUETOOTH } }, - { KE_KEY, 0x7E, { KEY_BLUETOOTH } }, + { KE_KEY, 0x7D, { KEY_BLUETOOTH } }, /* Bluetooth Enable */ + { KE_KEY, 0x7E, { KEY_BLUETOOTH } }, /* Bluetooth Disable */ { KE_KEY, 0x82, { KEY_CAMERA } }, - { KE_KEY, 0x88, { KEY_RFKILL } }, - { KE_KEY, 0x8A, { KEY_PROG1 } }, + { KE_KEY, 0x88, { KEY_RFKILL } }, /* Radio Toggle Key */ + { KE_KEY, 0x8A, { KEY_PROG1 } }, /* Color enhancement mode */ { KE_KEY, 0x95, { KEY_MEDIA } }, { KE_KEY, 0x99, { KEY_PHONE } }, { KE_KEY, 0xA0, { KEY_SWITCHVIDEOMODE } }, /* SDSP HDMI only */ { KE_KEY, 0xA1, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + HDMI */ { KE_KEY, 0xA2, { KEY_SWITCHVIDEOMODE } }, /* SDSP CRT + HDMI */ { KE_KEY, 0xA3, { KEY_SWITCHVIDEOMODE } }, /* SDSP TV + HDMI */ - { KE_KEY, 0xb5, { KEY_CALC } }, - { KE_KEY, 0xc4, { KEY_KBDILLUMUP } }, - { KE_KEY, 0xc5, { KEY_KBDILLUMDOWN } }, + { KE_KEY, 0xB5, { KEY_CALC } }, + { KE_KEY, 0xC4, { KEY_KBDILLUMUP } }, + { KE_KEY, 0xC5, { KEY_KBDILLUMDOWN } }, { KE_END, 0}, }; -- cgit v1.2.3 From 19d3ab12e84f110009fd94f0c7b7d3008fb3494c Mon Sep 17 00:00:00 2001 From: AceLan Kao Date: Wed, 3 Oct 2012 11:26:27 +0200 Subject: asus-laptop: correct a touchpad hotkey mapping 0x60 is touchpad enable key, but is misdefined in the keymap. Signed-off-by: AceLan Kao Signed-off-by: Corentin Chary Signed-off-by: Matthew Garrett --- drivers/platform/x86/asus-laptop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index 7ed1e9983d3e..23c60558bfd3 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -320,7 +320,7 @@ static const struct key_entry asus_keymap[] = { {KE_KEY, 0x5D, { KEY_WLAN } }, /* WLAN Toggle */ {KE_KEY, 0x5E, { KEY_WLAN } }, /* WLAN Enable */ {KE_KEY, 0x5F, { KEY_WLAN } }, /* WLAN Disable */ - {KE_KEY, 0x60, { KEY_SWITCHVIDEOMODE } }, + {KE_KEY, 0x60, { KEY_TOUCHPAD_ON } }, {KE_KEY, 0x61, { KEY_SWITCHVIDEOMODE } }, /* LCD Only */ {KE_KEY, 0x62, { KEY_SWITCHVIDEOMODE } }, /* CRT Only */ {KE_KEY, 0x63, { KEY_SWITCHVIDEOMODE } }, /* LCD + CRT */ -- cgit v1.2.3 From 98bfcb8e994404efc4832efec1c7ce533ef1fb67 Mon Sep 17 00:00:00 2001 From: AceLan Kao Date: Wed, 3 Oct 2012 11:26:29 +0200 Subject: asus-nb-wmi: correct a touchpad hotkey mapping 0x60 is touchpad enable key, but is misdefined in the keymap. Signed-off-by: AceLan Kao Signed-off-by: Corentin Chary Signed-off-by: Matthew Garrett --- drivers/platform/x86/asus-nb-wmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c index 9f1caa72b307..75ce18c671ff 100644 --- a/drivers/platform/x86/asus-nb-wmi.c +++ b/drivers/platform/x86/asus-nb-wmi.c @@ -180,7 +180,7 @@ static const struct key_entry asus_nb_wmi_keymap[] = { { KE_KEY, 0x5D, { KEY_WLAN } }, /* Wireless console Toggle */ { KE_KEY, 0x5E, { KEY_WLAN } }, /* Wireless console Enable */ { KE_KEY, 0x5F, { KEY_WLAN } }, /* Wireless console Disable */ - { KE_KEY, 0x60, { KEY_SWITCHVIDEOMODE } }, + { KE_KEY, 0x60, { KEY_TOUCHPAD_ON } }, { KE_KEY, 0x61, { KEY_SW