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 f80ae4d10f6..912ec7de71f 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 2111dbb7e1e..063113ca299 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 063113ca299..7ba107ae1d0 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 7ba107ae1d0..0bf94b5c274 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 0bf94b5c274..28bcbb21d12 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 00000000000..307a247ba1e --- /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 28bcbb21d12..6b229387567 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 2264331bd48..b96766b61ea 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 b96766b61ea..4db0c550ffc 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 4db0c550ffc..112ec1488ea 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 112ec1488ea..3a6061985e4 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 3a6061985e4..739bd4d17c2 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 739bd4d17c2..70222f265f6 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 d9f9a0dbc6f..062ddd7791c 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 be790402e0f..b70425c5863 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 062ddd7791c..7ed1e9983d3 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 b70425c5863..9f1caa72b30 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 7ed1e9983d3..23c60558bfd 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 9f1caa72b30..75ce18c671f 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_SWITCHVIDEOMODE } }, /* LCD Only */ { KE_KEY, 0x62, { KEY_SWITCHVIDEOMODE } }, /* CRT Only */ { KE_KEY, 0x63, { KEY_SWITCHVIDEOMODE } }, /* LCD + CRT */ -- cgit v1.2.3 From 3da4cd2015630f50d8d80c6ff5089d3daa2306c6 Mon Sep 17 00:00:00 2001 From: AceLan Kao Date: Wed, 3 Oct 2012 11:26:28 +0200 Subject: asus-laptop: add all video switch keys Fill up all the video switch keys in the map. Signed-off-by: AceLan Kao Signed-off-by: Corentin Chary Signed-off-by: Matthew Garrett --- drivers/platform/x86/asus-laptop.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index 23c60558bfd..a8792e81d1b 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -321,9 +321,13 @@ static const struct key_entry asus_keymap[] = { {KE_KEY, 0x5E, { KEY_WLAN } }, /* WLAN Enable */ {KE_KEY, 0x5F, { KEY_WLAN } }, /* WLAN Disable */ {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 */ + {KE_KEY, 0x61, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD only */ + {KE_KEY, 0x62, { KEY_SWITCHVIDEOMODE } }, /* SDSP CRT only */ + {KE_KEY, 0x63, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + CRT */ + {KE_KEY, 0x64, { KEY_SWITCHVIDEOMODE } }, /* SDSP TV */ + {KE_KEY, 0x65, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + TV */ + {KE_KEY, 0x66, { KEY_SWITCHVIDEOMODE } }, /* SDSP CRT + TV */ + {KE_KEY, 0x67, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + CRT + TV */ {KE_KEY, 0x6B, { KEY_TOUCHPAD_TOGGLE } }, /* Lock Touchpad */ {KE_KEY, 0x6C, { KEY_SLEEP } }, /* Suspend */ {KE_KEY, 0x6D, { KEY_SLEEP } }, /* Hibernate */ @@ -333,8 +337,24 @@ static const struct key_entry asus_keymap[] = { {KE_KEY, 0x82, { KEY_CAMERA } }, {KE_KEY, 0x88, { KEY_RFKILL } }, /* Radio Toggle Key */ {KE_KEY, 0x8A, { KEY_PROG1 } }, /* Color enhancement mode */ + {KE_KEY, 0x8C, { KEY_SWITCHVIDEOMODE } }, /* SDSP DVI only */ + {KE_KEY, 0x8D, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + DVI */ + {KE_KEY, 0x8E, { KEY_SWITCHVIDEOMODE } }, /* SDSP CRT + DVI */ + {KE_KEY, 0x8F, { KEY_SWITCHVIDEOMODE } }, /* SDSP TV + DVI */ + {KE_KEY, 0x90, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + CRT + DVI */ + {KE_KEY, 0x91, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + TV + DVI */ + {KE_KEY, 0x92, { KEY_SWITCHVIDEOMODE } }, /* SDSP CRT + TV + DVI */ + {KE_KEY, 0x93, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + CRT + TV + DVI */ {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, 0xA4, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + CRT + HDMI */ + {KE_KEY, 0xA5, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + TV + HDMI */ + {KE_KEY, 0xA6, { KEY_SWITCHVIDEOMODE } }, /* SDSP CRT + TV + HDMI */ + {KE_KEY, 0xA7, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + CRT + TV + HDMI */ {KE_KEY, 0xB5, { KEY_CALC } }, {KE_KEY, 0xC4, { KEY_KBDILLUMUP } }, {KE_KEY, 0xC5, { KEY_KBDILLUMDOWN } }, -- cgit v1.2.3 From a2a96f0c7221806c8a8072b662e6deaa119833da Mon Sep 17 00:00:00 2001 From: AceLan Kao Date: Wed, 3 Oct 2012 11:26:31 +0200 Subject: asus-wmi: add display toggle quirk For machines with AMD graphic chips, it will send out WMI event and ACPI interrupt at the same time while hitting the hotkey. BIOS will notify the system the next display output mode throught WMI event code, so that windows' application can show an OSD to tell the user which mode will be taken effect. User can hit the display toggle key many times within 2 seconds to choose the mode they want. After 2 seconds, WMI dirver should send a WMIMethod(SDSP) command to tell the BIOS which mode the user chose. And then BIOS will raise another ACPI interrupt to tell the system to really switch the display mode. In Linux desktop, we don't have this kind of OSD to let users to choose the mode they want, so we don't need to call WMIMethod(SDSP) to have another ACPI interrupt. To simplify the problem, we just have to ignore the WMI event, and let the first ACPI interrupt to send out the key event. For the need, here comes another quirk to add machines with this kind of behavior. When the WMI driver receives the display toggle WMI event, and found the machin is in the list, it will do nothing and let ACPI video driver to report the key event. Signed-off-by: AceLan Kao Signed-off-by: Corentin Chary Signed-off-by: Matthew Garrett --- drivers/platform/x86/asus-nb-wmi.c | 31 ++++++++++++++++++++++++++++++- drivers/platform/x86/asus-wmi.c | 31 ++++++++++++++++++++++++++++--- drivers/platform/x86/asus-wmi.h | 7 +++++++ 3 files changed, 65 insertions(+), 4 deletions(-) diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c index 75ce18c671f..73e08260975 100644 --- a/drivers/platform/x86/asus-nb-wmi.c +++ b/drivers/platform/x86/asus-nb-wmi.c @@ -59,6 +59,17 @@ static struct quirk_entry quirk_asus_unknown = { .wapf = 0, }; +/* + * For those machines that need software to control bt/wifi status + * and can't adjust brightness through ACPI interface + * and have duplicate events(ACPI and WMI) for display toggle + */ +static struct quirk_entry quirk_asus_x55u = { + .wapf = 4, + .wmi_backlight_power = true, + .no_display_toggle = true, +}; + static struct quirk_entry quirk_asus_x401u = { .wapf = 4, }; @@ -77,6 +88,15 @@ static struct dmi_system_id asus_quirks[] = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_PRODUCT_NAME, "X401U"), }, + .driver_data = &quirk_asus_x55u, + }, + { + .callback = dmi_matched, + .ident = "ASUSTeK COMPUTER INC. X401A", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "X401A"), + }, .driver_data = &quirk_asus_x401u, }, { @@ -95,6 +115,15 @@ static struct dmi_system_id asus_quirks[] = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_PRODUCT_NAME, "X501U"), }, + .driver_data = &quirk_asus_x55u, + }, + { + .callback = dmi_matched, + .ident = "ASUSTeK COMPUTER INC. X501A", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "X501A"), + }, .driver_data = &quirk_asus_x401u, }, { @@ -131,7 +160,7 @@ static struct dmi_system_id asus_quirks[] = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_PRODUCT_NAME, "X55U"), }, - .driver_data = &quirk_asus_x401u, + .driver_data = &quirk_asus_x55u, }, { .callback = dmi_matched, diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 912ec7de71f..208e71c6184 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -1341,6 +1341,23 @@ static void asus_wmi_backlight_exit(struct asus_wmi *asus) asus->backlight_device = NULL; } +static int is_display_toggle(int code) +{ + /* display toggle keys */ + if ((code >= 0x61 && code <= 0x67) || + (code >= 0x8c && code <= 0x93) || + (code >= 0xa0 && code <= 0xa7) || + (code >= 0xd0 && code <= 0xd5)) + return 1; + + return 0; +} + +static void do_nothing(void) +{ + return; +} + static void asus_wmi_notify(u32 value, void *context) { struct asus_wmi *asus = context; @@ -1380,10 +1397,18 @@ static void asus_wmi_notify(u32 value, void *context) code = NOTIFY_BRNDOWN_MIN; if (code == NOTIFY_BRNUP_MIN || code == NOTIFY_BRNDOWN_MIN) { - if (!acpi_video_backlight_support()) + if (!acpi_video_backlight_support()) { asus_wmi_backlight_notify(asus, orig_code); - } else if (!sparse_keymap_report_event(asus->inputdev, code, - key_value, autorelease)) + } + goto exit; + } + + if (is_display_toggle(code) && + asus->driver->quirks->no_display_toggle) + goto exit; + + if (!sparse_keymap_report_event(asus->inputdev, code, + key_value, autorelease)) pr_info("Unknown key %x pressed\n", code); exit: diff --git a/drivers/platform/x86/asus-wmi.h b/drivers/platform/x86/asus-wmi.h index 4c9bd38bb0a..776524c725d 100644 --- a/drivers/platform/x86/asus-wmi.h +++ b/drivers/platform/x86/asus-wmi.h @@ -41,6 +41,13 @@ struct quirk_entry { bool store_backlight_power; bool wmi_backlight_power; int wapf; + /* + * For machines with AMD graphic chips, it will send out WMI event + * and ACPI interrupt at the same time while hitting the hotkey. + * To simplify the problem, we just have to ignore the WMI event, + * and let the ACPI interrupt to send out the key event. + */ + int no_display_toggle; }; struct asus_wmi_driver { -- cgit v1.2.3 From 24c8a4c4ba6cfe1d01575d3094d11fd35a0e7fcd Mon Sep 17 00:00:00 2001 From: AceLan Kao Date: Wed, 3 Oct 2012 11:26:30 +0200 Subject: asus-nb-wmi: add all video switch keys Fill up all the video switch keys in the map. Signed-off-by: AceLan Kao Signed-off-by: Corentin Chary Signed-off-by: Matthew Garrett --- drivers/platform/x86/asus-nb-wmi.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c index 73e08260975..9aa6642f1ab 100644 --- a/drivers/platform/x86/asus-nb-wmi.c +++ b/drivers/platform/x86/asus-nb-wmi.c @@ -210,9 +210,13 @@ 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_TOUCHPAD_ON } }, - { KE_KEY, 0x61, { KEY_SWITCHVIDEOMODE } }, /* LCD Only */ - { KE_KEY, 0x62, { KEY_SWITCHVIDEOMODE } }, /* CRT Only */ - { KE_KEY, 0x63, { KEY_SWITCHVIDEOMODE } }, /* LCD + CRT */ + { KE_KEY, 0x61, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD only */ + { KE_KEY, 0x62, { KEY_SWITCHVIDEOMODE } }, /* SDSP CRT only */ + { KE_KEY, 0x63, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + CRT */ + { KE_KEY, 0x64, { KEY_SWITCHVIDEOMODE } }, /* SDSP TV */ + { KE_KEY, 0x65, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + TV */ + { KE_KEY, 0x66, { KEY_SWITCHVIDEOMODE } }, /* SDSP CRT + TV */ + { KE_KEY, 0x67, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + CRT + TV */ { KE_KEY, 0x6B, { KEY_TOUCHPAD_TOGGLE } }, { KE_IGNORE, 0x6E, }, /* Low Battery notification */ { KE_KEY, 0x7D, { KEY_BLUETOOTH } }, /* Bluetooth Enable */ @@ -220,12 +224,24 @@ static const struct key_entry asus_nb_wmi_keymap[] = { { KE_KEY, 0x82, { KEY_CAMERA } }, { KE_KEY, 0x88, { KEY_RFKILL } }, /* Radio Toggle Key */ { KE_KEY, 0x8A, { KEY_PROG1 } }, /* Color enhancement mode */ + { KE_KEY, 0x8C, { KEY_SWITCHVIDEOMODE } }, /* SDSP DVI only */ + { KE_KEY, 0x8D, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + DVI */ + { KE_KEY, 0x8E, { KEY_SWITCHVIDEOMODE } }, /* SDSP CRT + DVI */ + { KE_KEY, 0x8F, { KEY_SWITCHVIDEOMODE } }, /* SDSP TV + DVI */ + { KE_KEY, 0x90, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + CRT + DVI */ + { KE_KEY, 0x91, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + TV + DVI */ + { KE_KEY, 0x92, { KEY_SWITCHVIDEOMODE } }, /* SDSP CRT + TV + DVI */ + { KE_KEY, 0x93, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + CRT + TV + DVI */ { 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, 0xA4, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + CRT + HDMI */ + { KE_KEY, 0xA5, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + TV + HDMI */ + { KE_KEY, 0xA6, { KEY_SWITCHVIDEOMODE } }, /* SDSP CRT + TV + HDMI */ + { KE_KEY, 0xA7, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + CRT + TV + HDMI */ { KE_KEY, 0xB5, { KEY_CALC } }, { KE_KEY, 0xC4, { KEY_KBDILLUMUP } }, { KE_KEY, 0xC5, { KEY_KBDILLUMDOWN } }, -- cgit v1.2.3 From e6c33f1fe797355f1aed53b01230bd13ef52deff Mon Sep 17 00:00:00 2001 From: "Lee, Chun-Yi" Date: Fri, 14 Dec 2012 16:14:25 +0800 Subject: acer-wmi: support Lenovo ideapad S205 10382JG wifi switch Found another Lenovo ideapad S205 the product name is 10382JG, it has a 0x78 EC register exposes the state of wifi hardware switch on the machine. So, add this patch to support Lenovo ideapad S205-10382JG wifi hardware switch in acer-wmi driver. Evidently the Ideapad S205 is just a model name on the market, but they have totally different product name in DMI table. Reference: bko#43007 https://bugzilla.kernel.org/show_bug.cgi?id=43007 Tested-by: Ivo Anjo Cc: Carlos Corbacho Cc: Matthew Garrett Cc: Dmitry Torokhov Cc: Corentin Chary Cc: Thomas Renninger Signed-off-by: Lee, Chun-Yi Signed-off-by: Matthew Garrett --- drivers/platform/x86/acer-wmi.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index afed7018a2b..8d75e0399f6 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -511,6 +511,15 @@ static struct dmi_system_id acer_quirks[] = { }, .driver_data = &quirk_fujitsu_amilo_li_1718, }, + { + .callback = dmi_matched, + .ident = "Lenovo Ideapad S205-10382JG", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "10382JG"), + }, + .driver_data = &quirk_lenovo_ideapad_s205, + }, {} }; -- cgit v1.2.3 From 5f3511d2a61e7874730d3ccc1a32d418259133be Mon Sep 17 00:00:00 2001 From: "Lee, Chun-Yi" Date: Fri, 14 Dec 2012 16:14:28 +0800 Subject: acer-wmi: support Lenovo ideapad S205 1038DPG wifi switch Found another Lenovo ideapad S205 the product name is 1038DPG, it has a 0x78 EC register exposes the state of wifi hardware switch on the machine. So, add this patch to support Lenovo ideapad S205-1038DPG wifi hardware switch in acer-wmi driver. Evidently the Ideapad S205 is just a model name on the market, but they have totally different product name in DMI table. Reference: bko#43007 https://bugzilla.kernel.org/show_bug.cgi?id=43007 Tested-by: Colin Cc: Carlos Corbacho Cc: Matthew Garrett Cc: Dmitry Torokhov Cc: Corentin Chary Cc: Thomas Renninger Signed-off-by: Lee, Chun-Yi Signed-off-by: Matthew Garrett --- drivers/platform/x86/acer-wmi.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index 8d75e0399f6..563dc3f0e3e 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -520,6 +520,15 @@ static struct dmi_system_id acer_quirks[] = { }, .driver_data = &quirk_lenovo_ideapad_s205, }, + { + .callback = dmi_matched, + .ident = "Lenovo Ideapad S205-1038DPG", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "1038DPG"), + }, + .driver_data = &quirk_lenovo_ideapad_s205, + }, {} }; -- cgit v1.2.3 From 4fca7ce39f57517a31c911d8f66931355a39457e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Trep=C3=A1k=20Vilmos?= Date: Thu, 11 Oct 2012 12:51:00 +0200 Subject: Platform: hp-wmi: add rfkill support for integrated GPS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add rfkill support for the GPS radio found in HP laptops (HP Elitebook 2170p and the like) using the Ericsson F5321/H5321 Mobile Broadband Module. Signed-off-by: Viliam Trepák Signed-off-by: Matthew Garrett --- drivers/platform/x86/hp-wmi.c | 44 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 1dde7accf27..2179c03b94d 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -60,6 +60,7 @@ enum hp_wmi_radio { HPWMI_WIFI = 0, HPWMI_BLUETOOTH = 1, HPWMI_WWAN = 2, + HPWMI_GPS = 3, }; enum hp_wmi_event_ids { @@ -147,6 +148,7 @@ static struct platform_device *hp_wmi_platform_dev; static struct rfkill *wifi_rfkill; static struct rfkill *bluetooth_rfkill; static struct rfkill *wwan_rfkill; +static struct rfkill *gps_rfkill; struct rfkill2_device { u8 id; @@ -543,6 +545,10 @@ static void hp_wmi_notify(u32 value, void *context) rfkill_set_states(wwan_rfkill, hp_wmi_get_sw_state(HPWMI_WWAN), hp_wmi_get_hw_state(HPWMI_WWAN)); + if (gps_rfkill) + rfkill_set_states(gps_rfkill, + hp_wmi_get_sw_state(HPWMI_GPS), + hp_wmi_get_hw_state(HPWMI_GPS)); break; case HPWMI_CPU_BATTERY_THROTTLE: pr_info("Unimplemented CPU throttle because of 3 Cell battery event detected\n"); @@ -670,7 +676,7 @@ static int hp_wmi_rfkill_setup(struct platform_device *device) (void *) HPWMI_WWAN); if (!wwan_rfkill) { err = -ENOMEM; - goto register_bluetooth_error; + goto register_gps_error; } rfkill_init_sw_state(wwan_rfkill, hp_wmi_get_sw_state(HPWMI_WWAN)); @@ -681,10 +687,33 @@ static int hp_wmi_rfkill_setup(struct platform_device *device) goto register_wwan_err; } + if (wireless & 0x8) { + gps_rfkill = rfkill_alloc("hp-gps", &device->dev, + RFKILL_TYPE_GPS, + &hp_wmi_rfkill_ops, + (void *) HPWMI_GPS); + if (!gps_rfkill) { + err = -ENOMEM; + goto register_bluetooth_error; + } + rfkill_init_sw_state(gps_rfkill, + hp_wmi_get_sw_state(HPWMI_GPS)); + rfkill_set_hw_state(bluetooth_rfkill, + hp_wmi_get_hw_state(HPWMI_GPS)); + err = rfkill_register(gps_rfkill); + if (err) + goto register_gps_error; + } + return 0; register_wwan_err: rfkill_destroy(wwan_rfkill); wwan_rfkill = NULL; + if (gps_rfkill) + rfkill_unregister(gps_rfkill); +register_gps_error: + rfkill_destroy(gps_rfkill); + gps_rfkill = NULL; if (bluetooth_rfkill) rfkill_unregister(bluetooth_rfkill); register_bluetooth_error: @@ -729,6 +758,10 @@ static int hp_wmi_rfkill2_setup(struct platform_device *device) type = RFKILL_TYPE_WWAN; name = "hp-wwan"; break; + case HPWMI_GPS: + type = RFKILL_TYPE_GPS; + name = "hp-gps"; + break; default: pr_warn("unknown device type 0x%x\n", state.device[i].radio_type); @@ -786,6 +819,7 @@ static int hp_wmi_bios_setup(struct platform_device *device) wifi_rfkill = NULL; bluetooth_rfkill = NULL; wwan_rfkill = NULL; + gps_rfkill = NULL; rfkill2_count = 0; if (hp_wmi_rfkill_setup(device)) @@ -835,6 +869,10 @@ static int __exit hp_wmi_bios_remove(struct platform_device *device) rfkill_unregister(wwan_rfkill); rfkill_destroy(wwan_rfkill); } + if (gps_rfkill) { + rfkill_unregister(gps_rfkill); + rfkill_destroy(gps_rfkill); + } return 0; } @@ -870,6 +908,10 @@ static int hp_wmi_resume_handler(struct device *device) rfkill_set_states(wwan_rfkill, hp_wmi_get_sw_state(HPWMI_WWAN), hp_wmi_get_hw_state(HPWMI_WWAN)); + if (gps_rfkill) + rfkill_set_states(gps_rfkill, + hp_wmi_get_sw_state(HPWMI_GPS), + hp_wmi_get_hw_state(HPWMI_GPS)); return 0; } -- cgit v1.2.3 From 16a3d9f5aa1c9e0ecddd48bdfcf44445c9dbb601 Mon Sep 17 00:00:00 2001 From: Manoj Iyer Date: Mon, 24 Sep 2012 11:57:40 -0500 Subject: thinkpad-acpi: enable loading module with new B-series Lenovo BIOS The new B series BIOS has version string 43CN46WW. The driver requires that 2nd and 3rd characters be 'E' and 'T' respectively, where as the newer BIOS has 'C' and 'N' respectively. Failing to load the module causes some of the hotkeys to not work. Before the patch ================ sudo modprobe thinkpad_acpi FATAL: Error inserting thinkpad_acpi (/lib/modules/3.5.0-15-generic/kernel/drivers/platform/x86/thinkpad_acpi.ko): No such device After the patch =============== [44937.265438] thinkpad_acpi: ThinkPad ACPI Extras v0.24 [44937.265445] thinkpad_acpi: http://ibm-acpi.sf.net/ [44937.265449] thinkpad_acpi: ThinkPad BIOS 43CN46WW, EC unknown [44937.265453] thinkpad_acpi: Lenovo Lenovo B470e, model HuronRiver Platform [44937.266479] thinkpad_acpi: detected a 8-level brightness capable ThinkPad [44937.266557] thinkpad_acpi: Standard ACPI backlight interface available, not loading native one [44937.267846] thinkpad_acpi: Console audio control enabled, mode: monitor (read only) [44937.268131] input: ThinkPad Extra Buttons as /devices/platform/thinkpad_acpi/input/input17 Signed-off-by: Manoj Iyer Tested-by: James Ferguson Signed-off-by: Matthew Garrett --- drivers/platform/x86/thinkpad_acpi.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index ebcb461bb2b..22d893654d2 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -8574,7 +8574,8 @@ static bool __pure __init tpacpi_is_valid_fw_id(const char* const s, return s && strlen(s) >= 8 && tpacpi_is_fw_digit(s[0]) && tpacpi_is_fw_digit(s[1]) && - s[2] == t && s[3] == 'T' && + s[2] == t && + (s[3] == 'T' || s[3] == 'N') && tpacpi_is_fw_digit(s[4]) && tpacpi_is_fw_digit(s[5]); } @@ -8607,7 +8608,8 @@ static int __must_check __init get_thinkpad_model_data( return -ENOMEM; /* Really ancient ThinkPad 240X will fail this, which is fine */ - if (!tpacpi_is_valid_fw_id(tp->bios_version_str, 'E')) + if (!(tpacpi_is_valid_fw_id(tp->bios_version_str, 'E') || + tpacpi_is_valid_fw_id(tp->bios_version_str, 'C'))) return 0; tp->bios_model = tp->bios_version_str[0] -- cgit v1.2.3 From d1381f45ad54e0bb40ef19f99e87187ff3458bdb Mon Sep 17 00:00:00 2001 From: Benson Leung Date: Thu, 25 Oct 2012 14:21:21 -0700 Subject: Platform: x86: Add Chrome OS Laptop driver This adds the chromeos_laptop driver. It supports the Cypress APA SMBUS touchpad as well as the isl29018 i2c ambient light sensor on the Samsung Series 5 550 Chromebook. Signed-off-by: Benson Leung Reviewed-by: Olof Johansson Signed-off-by: Matthew Garrett --- drivers/platform/x86/Kconfig | 11 ++ drivers/platform/x86/Makefile | 1 + drivers/platform/x86/chromeos_laptop.c | 205 +++++++++++++++++++++++++++++++++ 3 files changed, 217 insertions(+) create mode 100644 drivers/platform/x86/chromeos_laptop.c diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 7ab0b2fba50..585db6fa64b 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -79,6 +79,17 @@ config ASUS_LAPTOP If you have an ACPI-compatible ASUS laptop, say Y or M here. +config CHROMEOS_LAPTOP + tristate "Chrome OS Laptop" + depends on I2C + depends on DMI + ---help--- + This driver instantiates i2c and smbus devices such as + light sensors and touchpads. + + If you have a supported Chromebook, choose Y or M here. + The module will be called chromeos_laptop. + config DELL_LAPTOP tristate "Dell Laptop Extras" depends on X86 diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index bf7e4f935b1..ace2b38942f 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile @@ -50,3 +50,4 @@ obj-$(CONFIG_INTEL_MID_POWER_BUTTON) += intel_mid_powerbtn.o obj-$(CONFIG_INTEL_OAKTRAIL) += intel_oaktrail.o obj-$(CONFIG_SAMSUNG_Q10) += samsung-q10.o obj-$(CONFIG_APPLE_GMUX) += apple-gmux.o +obj-$(CONFIG_CHROMEOS_LAPTOP) += chromeos_laptop.o diff --git a/drivers/platform/x86/chromeos_laptop.c b/drivers/platform/x86/chromeos_laptop.c new file mode 100644 index 00000000000..a8329c3a9d0 --- /dev/null +++ b/drivers/platform/x86/chromeos_laptop.c @@ -0,0 +1,205 @@ +/* + * chromeos_laptop.c - Driver to instantiate Chromebook i2c/smbus devices. + * + * Author : Benson Leung + * + * Copyright (C) 2012 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include +#include + +#define CYAPA_TP_I2C_ADDR 0x67 +#define ISL_ALS_I2C_ADDR 0x44 + +static struct i2c_client *als; +static struct i2c_client *tp; + +const char *i2c_adapter_names[] = { + "SMBus I801 adapter", +}; + +/* Keep this enum consistent with i2c_adapter_names */ +enum i2c_adapter_type { + I2C_ADAPTER_SMBUS = 0, +}; + +static struct i2c_board_info __initdata cyapa_device = { + I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR), + .flags = I2C_CLIENT_WAKE, +}; + +static struct i2c_board_info __initdata isl_als_device = { + I2C_BOARD_INFO("isl29018", ISL_ALS_I2C_ADDR), +}; + +static struct i2c_client __init *__add_probed_i2c_device( + const char *name, + int bus, + struct i2c_board_info *info, + const unsigned short *addrs) +{ + const struct dmi_device *dmi_dev; + const struct dmi_dev_onboard *dev_data; + struct i2c_adapter *adapter; + struct i2c_client *client; + + if (bus < 0) + return NULL; + /* + * If a name is specified, look for irq platform information stashed + * in DMI_DEV_TYPE_DEV_ONBOARD by the Chrome OS custom system firmware. + */ + if (name) { + dmi_dev = dmi_find_device(DMI_DEV_TYPE_DEV_ONBOARD, name, NULL); + if (!dmi_dev) { + pr_err("%s failed to dmi find device %s.\n", + __func__, + name); + return NULL; + } + dev_data = (struct dmi_dev_onboard *)dmi_dev->device_data; + if (!dev_data) { + pr_err("%s failed to get data from dmi for %s.\n", + __func__, name); + return NULL; + } + info->irq = dev_data->instance; + } + + adapter = i2c_get_adapter(bus); + if (!adapter) { + pr_err("%s failed to get i2c adapter %d.\n", __func__, bus); + return NULL; + } + + /* add the i2c device */ + client = i2c_new_probed_device(adapter, info, addrs, NULL); + if (!client) + pr_err("%s failed to register device %d-%02x\n", + __func__, bus, info->addr); + else + pr_debug("%s added i2c device %d-%02x\n", + __func__, bus, info->addr); + + i2c_put_adapter(adapter); + return client; +} + +static int __init __find_i2c_adap(struct device *dev, void *data) +{ + const char *name = data; + static const char *prefix = "i2c-"; + struct i2c_adapter *adapter; + if (strncmp(dev_name(dev), prefix, strlen(prefix)) != 0) + return 0; + adapter = to_i2c_adapter(dev); + return (strncmp(adapter->name, name, strlen(name)) == 0); +} + +static int __init find_i2c_adapter_num(enum i2c_adapter_type type) +{ + struct device *dev = NULL; + struct i2c_adapter *adapter; + const char *name = i2c_adapter_names[type]; + /* find the adapter by name */ + dev = bus_find_device(&i2c_bus_type, NULL, (void *)name, + __find_i2c_adap); + if (!dev) { + pr_err("%s: i2c adapter %s not found on system.\n", __func__, + name); + return -ENODEV; + } + adapter = to_i2c_adapter(dev); + return adapter->nr; +} + +/* + * Probes for a device at a single address, the one provided by + * info->addr. + * Returns NULL if no device found. + */ +static struct i2c_client __init *add_smbus_device(const char *name, + struct i2c_board_info *info) +{ + const unsigned short addr_list[] = { info->addr, I2C_CLIENT_END }; + return __add_probed_i2c_device(name, + find_i2c_adapter_num(I2C_ADAPTER_SMBUS), + info, + addr_list); +} + +static int __init setup_lumpy_tp(const struct dmi_system_id *id) +{ + /* add cyapa touchpad on smbus */ + tp = add_smbus_device("trackpad", &cyapa_device); + return 0; +} + +static int __init setup_isl29018_als(const struct dmi_system_id *id) +{ + /* add isl29018 light sensor */ + als = add_smbus_device("lightsensor", &isl_als_device); + return 0; +} + +static struct dmi_system_id __initdata chromeos_laptop_dmi_table[] = { + { + .ident = "Samsung Series 5 550 - Touchpad", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG"), + DMI_MATCH(DMI_PRODUCT_NAME, "Lumpy"), + }, + .callback = setup_lumpy_tp, + }, + { + .ident = "Samsung Series 5 550 - Light Sensor", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG"), + DMI_MATCH(DMI_PRODUCT_NAME, "Lumpy"), + }, + .callback = setup_isl29018_als, + }, + { } +}; +MODULE_DEVICE_TABLE(dmi, chromeos_laptop_dmi_table); + +static int __init chromeos_laptop_init(void) +{ + if (!dmi_check_system(chromeos_laptop_dmi_table)) { + pr_debug("%s unsupported system.\n", __func__); + return -ENODEV; + } + return 0; +} + +static void __exit chromeos_laptop_exit(void) +{ + if (als) + i2c_unregister_device(als); + if (tp) + i2c_unregister_device(tp); +} + +module_init(chromeos_laptop_init); +module_exit(chromeos_laptop_exit); + +MODULE_DESCRIPTION("Chrome OS Laptop driver"); +MODULE_AUTHOR("Benson Leung "); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 3ec1c3983d73b1e3d4cfd72afab94c34eceafe8a Mon Sep 17 00:00:00 2001 From: Mattia Dongili Date: Fri, 21 Dec 2012 07:21:08 +0900 Subject: sony-laptop: fully enable SNY controlled modems The call to handlers 0x124 and 0x135 (rfkill control) seems to take a bitmask to control various states of the device. For our rfkill we need a fully on/off. SVZ1311Z9R/X's LTE modem needs more bits up. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=47751 Signed-off-by: Mattia Dongili Signed-off-by: Matthew Garrett Cc: stable@kernel.org --- drivers/platform/x86/sony-laptop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index ceb41eff423..0bee6c2f886 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -1534,7 +1534,7 @@ static int sony_nc_rfkill_set(void *data, bool blocked) int argument = sony_rfkill_address[(long) data] + 0x100; if (!blocked) - argument |= 0x030000; + argument |= 0x070000; return sony_call_snc_handle(sony_rfkill_handle, argument, &result); } -- cgit v1.2.3 From 3a7abcd809e75b3588dd4a6529238e2a9b009c9a Mon Sep 17 00:00:00 2001 From: Mattia Dongili Date: Fri, 21 Dec 2012 07:21:10 +0900 Subject: sony-laptop: allow reading the status of gfx switch Signed-off-by: Mattia Dongili Signed-off-by: Matthew Garrett --- drivers/platform/x86/sony-laptop.c | 121 ++++++++++++++++++++++++++++++++++--- 1 file changed, 112 insertions(+), 9 deletions(-) diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 0bee6c2f886..46c71f49a6b 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -158,6 +158,11 @@ static void sony_nc_thermal_cleanup(struct platform_device *pd); static int sony_nc_lid_resume_setup(struct platform_device *pd); static void sony_nc_lid_resume_cleanup(struct platform_device *pd); +static int sony_nc_gfx_switch_setup(struct platform_device *pd, + unsigned int handle); +static void sony_nc_gfx_switch_cleanup(struct platform_device *pd); +static int __sony_nc_gfx_switch_status_get(void); + static int sony_nc_highspeed_charging_setup(struct platform_device *pd); static void sony_nc_highspeed_charging_cleanup(struct platform_device *pd); @@ -1241,17 +1246,13 @@ static void sony_nc_notify(struct acpi_device *device, u32 event) /* Hybrid GFX switching */ sony_call_snc_handle(handle, 0x0000, &result); dprintk("GFX switch event received (reason: %s)\n", - (result & 0x01) ? - "switch change" : "unknown"); - - /* verify the switch state - * 1: discrete GFX - * 0: integrated GFX - */ - sony_call_snc_handle(handle, 0x0100, &result); + (result == 0x1) ? "switch change" : + (result == 0x2) ? "output switch" : + (result == 0x3) ? "output switch" : + ""); ev_type = GFX_SWITCH; - real_ev = result & 0xff; + real_ev = __sony_nc_gfx_switch_status_get(); break; default: @@ -1350,6 +1351,13 @@ static void sony_nc_function_setup(struct acpi_device *device, pr_err("couldn't set up thermal profile function (%d)\n", result); break; + case 0x0128: + case 0x0146: + result = sony_nc_gfx_switch_setup(pf_device, handle); + if (result) + pr_err("couldn't set up GFX Switch status (%d)\n", + result); + break; case 0x0131: result = sony_nc_highspeed_charging_setup(pf_device); if (result) @@ -1414,6 +1422,10 @@ static void sony_nc_function_cleanup(struct platform_device *pd) case 0x0122: sony_nc_thermal_cleanup(pd); break; + case 0x0128: + case 0x0146: + sony_nc_gfx_switch_cleanup(pd); + break; case 0x0131: sony_nc_highspeed_charging_cleanup(pd); break; @@ -2355,6 +2367,97 @@ static void sony_nc_lid_resume_cleanup(struct platform_device *pd) } } +/* GFX Switch position */ +enum gfx_switch { + SPEED, + STAMINA, + AUTO +}; +struct snc_gfx_switch_control { + struct device_attribute attr; + unsigned int handle; +}; +static struct snc_gfx_switch_control *gfxs_ctl; + +/* returns 0 for speed, 1 for stamina */ +static int __sony_nc_gfx_switch_status_get(void) +{ + unsigned int result; + + if (sony_call_snc_handle(gfxs_ctl->handle, 0x0100, &result)) + return -EIO; + + switch (gfxs_ctl->handle) { + case 0x0146: + /* 1: discrete GFX (speed) + * 0: integrated GFX (stamina) + */ + return result & 0x1 ? SPEED : STAMINA; + break; + case 0x0128: + /* it's a more elaborated bitmask, for now: + * 2: integrated GFX (stamina) + * 0: discrete GFX (speed) + */ + dprintk("GFX Status: 0x%x\n", result); + return result & 0x80 ? AUTO : + result & 0x02 ? STAMINA : SPEED; + break; + } + return -EINVAL; +} + +static ssize_t sony_nc_gfx_switch_status_show(struct device *dev, + struct device_attribute *attr, + char *buffer) +{ + int pos = __sony_nc_gfx_switch_status_get(); + + if (pos < 0) + return pos; + + return snprintf(buffer, PAGE_SIZE, "%s\n", pos ? "speed" : "stamina"); +} + +static int sony_nc_gfx_switch_setup(struct platform_device *pd, + unsigned int handle) +{ + unsigned int result; + + gfxs_ctl = kzalloc(sizeof(struct snc_gfx_switch_control), GFP_KERNEL); + if (!gfxs_ctl) + return -ENOMEM; + + gfxs_ctl->handle = handle; + + sysfs_attr_init(&gfxs_ctl->attr.attr); + gfxs_ctl->attr.attr.name = "gfx_switch_status"; + gfxs_ctl->attr.attr.mode = S_IRUGO; + gfxs_ctl->attr.show = sony_nc_gfx_switch_status_show; + + result = device_create_file(&pd->dev, &gfxs_ctl->attr); + if (result) + goto gfxerror; + + return 0; + +gfxerror: + kfree(gfxs_ctl); + gfxs_ctl = NULL; + + return result; +} + +static void sony_nc_gfx_switch_cleanup(struct platform_device *pd) +{ + if (gfxs_ctl) { + device_remove_file(&pd->dev, &gfxs_ctl->attr); + + kfree(gfxs_ctl); + gfxs_ctl = NULL; + } +} + /* High speed charging function */ static struct device_attribute *hsc_handle; -- cgit v1.2.3 From 7517a17c1abfc081d19298459f3d2a0d14a86566 Mon Sep 17 00:00:00 2001 From: Mattia Dongili Date: Fri, 21 Dec 2012 07:21:11 +0900 Subject: sony-laptop: support basic functions for handle 0x14B and 0x14C Z series and other recent models have 0x14? for lid and keyboard backlight. Signed-off-by: Mattia Dongili Signed-off-by: Matthew Garrett --- drivers/platform/x86/sony-laptop.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 46c71f49a6b..438c7fa999f 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -1373,6 +1373,8 @@ static void sony_nc_function_setup(struct acpi_device *device, break; case 0x0137: case 0x0143: + case 0x014b: + case 0x014c: result = sony_nc_kbd_backlight_setup(pf_device, handle); if (result) pr_err("couldn't set up keyboard backlight function (%d)\n", @@ -1435,6 +1437,8 @@ static void sony_nc_function_cleanup(struct platform_device *pd) break; case 0x0137: case 0x0143: + case 0x014b: + case 0x014c: sony_nc_kbd_backlight_cleanup(pd); break; default: @@ -1479,6 +1483,8 @@ static void sony_nc_function_resume(void) break; case 0x0137: case 0x0143: + case 0x014b: + case 0x014c: sony_nc_kbd_backlight_resume(); break; default: @@ -2636,6 +2642,8 @@ static void sony_nc_backlight_ng_read_limits(int handle, lvl_table_len = 9; break; case 0x143: + case 0x14b: + case 0x14c: lvl_table_len = 16; break; } @@ -2687,6 +2695,18 @@ static void sony_nc_backlight_setup(void) sony_nc_backlight_ng_read_limits(0x143, &sony_bl_props); max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset; + } else if (sony_find_snc_handle(0x14b) >= 0) { + ops = &sony_backlight_ng_ops; + sony_bl_props.cmd_base = 0x3000; + sony_nc_backlight_ng_read_limits(0x14b, &sony_bl_props); + max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset; + + } else if (sony_find_snc_handle(0x14c) >= 0) { + ops = &sony_backlight_ng_ops; + sony_bl_props.cmd_base = 0x3000; + sony_nc_backlight_ng_read_limits(0x14c, &sony_bl_props); + max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset; + } else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT", &unused))) { ops = &sony_backlight_ops; -- cgit v1.2.3 From 3ba0302bdd57d225b52c4b4b36975196c1572b3f Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Thu, 29 Nov 2012 09:12:38 +0100 Subject: asus-wmi: always report brightness key events Signed-off-by: Corentin Chary Signed-off-by: Matthew Garrett --- drivers/platform/x86/asus-nb-wmi.c | 2 ++ drivers/platform/x86/asus-wmi.c | 8 ++++---- drivers/platform/x86/asus-wmi.h | 2 ++ drivers/platform/x86/eeepc-wmi.c | 2 ++ 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c index 9aa6642f1ab..210b5b87212 100644 --- a/drivers/platform/x86/asus-nb-wmi.c +++ b/drivers/platform/x86/asus-nb-wmi.c @@ -190,6 +190,8 @@ static void asus_nb_wmi_quirks(struct asus_wmi_driver *driver) } static const struct key_entry asus_nb_wmi_keymap[] = { + { KE_KEY, ASUS_WMI_BRN_DOWN, { KEY_BRIGHTNESSDOWN } }, + { KE_KEY, ASUS_WMI_BRN_UP, { KEY_BRIGHTNESSUP } }, { KE_KEY, 0x30, { KEY_VOLUMEUP } }, { KE_KEY, 0x31, { KEY_VOLUMEDOWN } }, { KE_KEY, 0x32, { KEY_MUTE } }, diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 208e71c6184..e41eae31585 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -1391,16 +1391,16 @@ static void asus_wmi_notify(u32 value, void *context) } if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX) - code = NOTIFY_BRNUP_MIN; + code = ASUS_WMI_BRN_UP; else if (code >= NOTIFY_BRNDOWN_MIN && code <= NOTIFY_BRNDOWN_MAX) - code = NOTIFY_BRNDOWN_MIN; + code = ASUS_WMI_BRN_DOWN; - if (code == NOTIFY_BRNUP_MIN || code == NOTIFY_BRNDOWN_MIN) { + if (code == ASUS_WMI_BRN_DOWN || code == ASUS_WMI_BRN_UP) { if (!acpi_video_backlight_support()) { asus_wmi_backlight_notify(asus, orig_code); + goto exit; } - goto exit; } if (is_display_toggle(code) && diff --git a/drivers/platform/x86/asus-wmi.h b/drivers/platform/x86/asus-wmi.h index 776524c725d..4da4c8bafe7 100644 --- a/drivers/platform/x86/asus-wmi.h +++ b/drivers/platform/x86/asus-wmi.h @@ -30,6 +30,8 @@ #include #define ASUS_WMI_KEY_IGNORE (-1) +#define ASUS_WMI_BRN_DOWN 0x20 +#define ASUS_WMI_BRN_UP 0x2f struct module; struct key_entry; diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c index 60cb76a5b51..af67e6e56eb 100644 --- a/drivers/platform/x86/eeepc-wmi.c +++ b/drivers/platform/x86/eeepc-wmi.c @@ -63,6 +63,8 @@ MODULE_PARM_DESC(hotplug_wireless, #define HOME_RELEASE 0xe5 static const struct key_entry eeepc_wmi_keymap[] = { + { KE_KEY, ASUS_WMI_BRN_DOWN, { KEY_BRIGHTNESSDOWN } }, + { KE_KEY, ASUS_WMI_BRN_UP, { KEY_BRIGHTNESSUP } }, /* Sleep already handled via generic ACPI code */ { KE_KEY, 0x30, { KEY_VOLUMEUP } }, { KE_KEY, 0x31, { KEY_VOLUMEDOWN } }, -- cgit v1.2.3 From 2740e1bd528771dea9003a1c85f7f8d051c2808d Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Thu, 29 Nov 2012 09:12:39 +0100 Subject: asus-laptop: always report brightness key events Signed-off-by: Corentin Chary Signed-off-by: Matthew Garrett --- drivers/platform/x86/asus-laptop.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index a8792e81d1b..0eea09c1c13 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -128,10 +128,12 @@ MODULE_PARM_DESC(als_status, "Set the ALS status on boot " /* * Some events we use, same for all Asus */ -#define ATKD_BR_UP 0x10 /* (event & ~ATKD_BR_UP) = brightness level */ -#define ATKD_BR_DOWN 0x20 /* (event & ~ATKD_BR_DOWN) = britghness level */ -#define ATKD_BR_MIN ATKD_BR_UP -#define ATKD_BR_MAX (ATKD_BR_DOWN | 0xF) /* 0x2f */ +#define ATKD_BRNUP_MIN 0x10 +#define ATKD_BRNUP_MAX 0x1f +#define ATKD_BRNDOWN_MIN 0x20 +#define ATKD_BRNDOWN_MAX 0x2f +#define ATKD_BRNDOWN 0x20 +#define ATKD_BRNUP 0x2f #define ATKD_LCD_ON 0x33 #define ATKD_LCD_OFF 0x34 @@ -301,6 +303,8 @@ static const struct key_entry asus_keymap[] = { {KE_KEY, 0x17, { KEY_ZOOM } }, {KE_KEY, 0x1f, { KEY_BATTERY } }, /* End of Lenovo SL Specific keycodes */ + {KE_KEY, ATKD_BRNDOWN, { KEY_BRIGHTNESSDOWN } }, + {KE_KEY, ATKD_BRNUP, { KEY_BRIGHTNESSUP } }, {KE_KEY, 0x30, { KEY_VOLUMEUP } }, {KE_KEY, 0x31, { KEY_VOLUMEDOWN } }, {KE_KEY, 0x32, { KEY_MUTE } }, @@ -1544,15 +1548,19 @@ static void asus_acpi_notify(struct acpi_device *device, u32 event) dev_name(&asus->device->dev), event, count); - /* Brightness events are special */ - if (event >= ATKD_BR_MIN && event <= ATKD_BR_MAX) { + if (event >= ATKD_BRNUP_MIN && event <= ATKD_BRNUP_MAX) + event = ATKD_BRNUP; + else if (event >= ATKD_BRNDOWN_MIN && + event <= ATKD_BRNDOWN_MAX) + event = ATKD_BRNDOWN; - /* Ignore them completely if the acpi video driver is used */ + /* Brightness events are special */ + if (event == ATKD_BRNDOWN || event == ATKD_BRNUP) { if (asus->backlight_device != NULL) { /* Update the backlight device. */ asus_backlight_notify(asus); + return ; } - return ; } /* Accelerometer "coarse orientation change" event */ -- cgit v1.2.3 From 6e71094d98b54c2db09ef6af33b67bdece9d4ebe Mon Sep 17 00:00:00 2001 From: Benson Leung Date: Fri, 1 Feb 2013 14:34:43 -0800 Subject: Platform: x86: chromeos_laptop - Rename setup_lumpy_tp to setup_cyapa_smbus_tp The Cypress trackpad on smbus is used on other systems as well. Lets make the name more generic. Signed-off-by: Benson Leung Signed-off-by: Matthew Garrett --- drivers/platform/x86/chromeos_laptop.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/chromeos_laptop.c b/drivers/platform/x86/chromeos_laptop.c index a8329c3a9d0..6440d2250ba 100644 --- a/drivers/platform/x86/chromeos_laptop.c +++ b/drivers/platform/x86/chromeos_laptop.c @@ -145,7 +145,7 @@ static struct i2c_client __init *add_smbus_device(const char *name, addr_list); } -static int __init setup_lumpy_tp(const struct dmi_system_id *id) +static int __init setup_cyapa_smbus_tp(const struct dmi_system_id *id) { /* add cyapa touchpad on smbus */ tp = add_smbus_device("trackpad", &cyapa_device); @@ -166,7 +166,7 @@ static struct dmi_system_id __initdata chromeos_laptop_dmi_table[] = { DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG"), DMI_MATCH(DMI_PRODUCT_NAME, "Lumpy"), }, - .callback = setup_lumpy_tp, + .callback = setup_cyapa_smbus_tp, }, { .ident = "Samsung Series 5 550 - Light Sensor", -- cgit v1.2.3 From 261f171f571a82c1f990d484c374aa3f7236fe5e Mon Sep 17 00:00:00 2001 From: Benson Leung Date: Fri, 1 Feb 2013 14:34:44 -0800 Subject: Platform: x86: chromeos_laptop - Add Acer C7 trackpad Add support for the Acer C7's trackpad, which is a reuse of the Samsung Series 5 550 trackpad. Signed-off-by: Benson Leung Signed-off-by: Matthew Garrett --- drivers/platform/x86/chromeos_laptop.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/platform/x86/chromeos_laptop.c b/drivers/platform/x86/chromeos_laptop.c index 6440d2250ba..9293c66d52c 100644 --- a/drivers/platform/x86/chromeos_laptop.c +++ b/drivers/platform/x86/chromeos_laptop.c @@ -176,6 +176,13 @@ static struct dmi_system_id __initdata chromeos_laptop_dmi_table[] = { }, .callback = setup_isl29018_als, }, + { + .ident = "Acer C7 Chromebook - Touchpad", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "Parrot"), + }, + .callback = setup_cyapa_smbus_tp, + }, { } }; MODULE_DEVICE_TABLE(dmi, chromeos_laptop_dmi_table); -- cgit v1.2.3 From aabf3f442b0f42b3a37ed7beb8d5f3f249b812ca Mon Sep 17 00:00:00 2001 From: Benson Leung Date: Fri, 1 Feb 2013 14:34:45 -0800 Subject: Platform: x86: chromeos_laptop - Add Taos tsl2563 device Two legacy Chromebooks, the Cr-48, and the Acer AC700, are equipped with a Taos tsl2563 light sensor. This will instantiate the sensor on those laptops. Signed-off-by: Benson Leung Signed-off-by: Matthew Garrett --- drivers/platform/x86/chromeos_laptop.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/drivers/platform/x86/chromeos_laptop.c b/drivers/platform/x86/chromeos_laptop.c index 9293c66d52c..188b7dac778 100644 --- a/drivers/platform/x86/chromeos_laptop.c +++ b/drivers/platform/x86/chromeos_laptop.c @@ -27,6 +27,7 @@ #define CYAPA_TP_I2C_ADDR 0x67 #define ISL_ALS_I2C_ADDR 0x44 +#define TAOS_ALS_I2C_ADDR 0x29 static struct i2c_client *als; static struct i2c_client *tp; @@ -49,6 +50,10 @@ static struct i2c_board_info __initdata isl_als_device = { I2C_BOARD_INFO("isl29018", ISL_ALS_I2C_ADDR), }; +static struct i2c_board_info __initdata tsl2563_als_device = { + I2C_BOARD_INFO("tsl2563", TAOS_ALS_I2C_ADDR), +}; + static struct i2c_client __init *__add_probed_i2c_device( const char *name, int bus, @@ -159,6 +164,13 @@ static int __init setup_isl29018_als(const struct dmi_system_id *id) return 0; } +static int __init setup_tsl2563_als(const struct dmi_system_id *id) +{ + /* add tsl2563 light sensor on smbus */ + als = add_smbus_device(NULL, &tsl2563_als_device); + return 0; +} + static struct dmi_system_id __initdata chromeos_laptop_dmi_table[] = { { .ident = "Samsung Series 5 550 - Touchpad", @@ -183,6 +195,20 @@ static struct dmi_system_id __initdata chromeos_laptop_dmi_table[] = { }, .callback = setup_cyapa_smbus_tp, }, + { + .ident = "Cr-48 - Light Sensor", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "Mario"), + }, + .callback = setup_tsl2563_als, + }, + { + .ident = "Acer AC700 - Light Sensor", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "ZGB"), + }, + .callback = setup_tsl2563_als, + }, { } }; MODULE_DEVICE_TABLE(dmi, chromeos_laptop_dmi_table); -- cgit v1.2.3 From 8016bcbc380f952bfccb82fde3bb8b4b9cbd6400 Mon Sep 17 00:00:00 2001 From: Benson Leung Date: Fri, 1 Feb 2013 14:34:46 -0800 Subject: Platform: x86: chromeos_laptop - Add Taos tsl2583 device The Samsung Series 5 Chromebook is equipped with a Taos tsl2583 light sensor. Instatiate it here. Signed-off-by: Benson Leung Signed-off-by: Matthew Garrett --- drivers/platform/x86/chromeos_laptop.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/platform/x86/chromeos_laptop.c b/drivers/platform/x86/chromeos_laptop.c index 188b7dac778..95bf94fa199 100644 --- a/drivers/platform/x86/chromeos_laptop.c +++ b/drivers/platform/x86/chromeos_laptop.c @@ -50,6 +50,10 @@ static struct i2c_board_info __initdata isl_als_device = { I2C_BOARD_INFO("isl29018", ISL_ALS_I2C_ADDR), }; +static struct i2c_board_info __initdata tsl2583_als_device = { + I2C_BOARD_INFO("tsl2583", TAOS_ALS_I2C_ADDR), +}; + static struct i2c_board_info __initdata tsl2563_als_device = { I2C_BOARD_INFO("tsl2563", TAOS_ALS_I2C_ADDR), }; @@ -164,6 +168,13 @@ static int __init setup_isl29018_als(const struct dmi_system_id *id) return 0; } +static int __init setup_tsl2583_als(const struct dmi_system_id *id) +{ + /* add tsl2583 light sensor on smbus */ + als = add_smbus_device(NULL, &tsl2583_als_device); + return 0; +} + static int __init setup_tsl2563_als(const struct dmi_system_id *id) { /* add tsl2563 light sensor on smbus */ @@ -195,6 +206,13 @@ static struct dmi_system_id __initdata chromeos_laptop_dmi_table[] = { }, .callback = setup_cyapa_smbus_tp, }, + { + .ident = "Samsung Series 5 - Light Sensor", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "Alex"), + }, + .callback = setup_tsl2583_als, + }, { .ident = "Cr-48 - Light Sensor", .matches = { -- cgit v1.2.3 From e65a624b86241405b51cadc8e36944966b8c36b7 Mon Sep 17 00:00:00 2001 From: Benson Leung Date: Sun, 10 Feb 2013 16:20:17 -0800 Subject: Platform: x86: chromeos_laptop - Add HP Pavilion 14 Add support for the HP Pavilion 14 Chromebook's trackpad, which is a reuse of the Samsung Series 5 550 trackpad. Signed-off-by: Benson Leung Signed-off-by: Matthew Garrett --- drivers/platform/x86/chromeos_laptop.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/platform/x86/chromeos_laptop.c b/drivers/platform/x86/chromeos_laptop.c index 95bf94fa199..bc6599c5bbe 100644 --- a/drivers/platform/x86/chromeos_laptop.c +++ b/drivers/platform/x86/chromeos_laptop.c @@ -206,6 +206,13 @@ static struct dmi_system_id __initdata chromeos_laptop_dmi_table[] = { }, .callback = setup_cyapa_smbus_tp, }, + { + .ident = "HP Pavilion 14 Chromebook - Touchpad", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "Butterfly"), + }, + .callback = setup_cyapa_smbus_tp, + }, { .ident = "Samsung Series 5 - Light Sensor", .matches = { -- cgit v1.2.3 From 6f62bc3e8d2410b538bde9677552270055f8595a Mon Sep 17 00:00:00 2001 From: Richard Hartmann Date: Sat, 29 Dec 2012 22:51:49 +0100 Subject: drivers/platform/x86/thinkpad_acpi.c: Handle HKEY event 0x6040 Handle HKEY event generated on AC power change. The current message asks users to submit data related to this event which leads to a lot of confusion and noise on the mailing list. The following is a list affected models and 'Message-Id' from ibm-acpi-devel@lists.sourceforge.net of people who saw this event when either plugging or unplugging the AC adapter or docking or undocking their laptop. X120e - CAAAujb5v9dHdbdxDVvhNJoG4UrZC1TgKqeB_zGpAy7q8kZHMEQ@mail.gmail.com X121e - 20120817143459.GB3462@x1.osrc.amd.com X220 - Confirmed by Richard Hartmann X220i - 4F406274.7070807@gmail.com X220t - 4F489F5B.9040705@cs.tu-berlin.de X230 - CAKx4u7kqvVH0-gstomsiVYdGC0i6=bGxzaQ8sq9gbg76TGme3w@mail.gmail.com T420 - 9c848ee30b006737d0534d906bab0cf6@niklaas-baudet.net T420s - 20120608080824.GS25324@hexapodia.org W520 - 20121008181050.GF2549@ericlaptop.home.christensenplace.us Signed-off-by: Richard Hartmann Signed-off-by: Matthew Garrett --- drivers/platform/x86/thinkpad_acpi.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 22d893654d2..be9379923a9 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -209,9 +209,8 @@ enum tpacpi_hkey_event_t { TP_HKEY_EV_ALARM_SENSOR_XHOT = 0x6022, /* sensor critically hot */ TP_HKEY_EV_THM_TABLE_CHANGED = 0x6030, /* thermal table changed */ - TP_HKEY_EV_UNK_6040 = 0x6040, /* Related to AC change? - some sort of APM hint, - W520 */ + /* AC-related events */ + TP_HKEY_EV_AC_CHANGED = 0x6040, /* AC status changed */ /* Misc */ TP_HKEY_EV_RFKILL_CHANGED = 0x7000, /* rfkill switch changed */ @@ -3629,6 +3628,12 @@ static bool hotkey_notify_6xxx(const u32 hkey, "a sensor reports something is extremely hot!\n"); /* recommended action: immediate sleep/hibernate */ break; + case TP_HKEY_EV_AC_CHANGED: + /* X120e, X121e, X220, X220i, X220t, X230, T420, T420s, W520: + * AC status changed; can be triggered by plugging or + * unplugging AC adapter, docking or undocking. */ + + /* fallthrough */ case TP_HKEY_EV_KEY_NUMLOCK: case TP_HKEY_EV_KEY_FN: -- cgit v1.2.3 From f24c96eae58aeea4c36fb064cf3ee9734933f8fc Mon Sep 17 00:00:00 2001 From: "Lee, Chun-Yi" Date: Thu, 3 Jan 2013 10:37:45 +0800 Subject: acer-wmi: avoid the warning of 'devices' may be used uninitialized MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fengguang Wu run kernel build test to platform-drivers-x86/linux-next git tree on x86_64 architecture and found a warning that was introduced by 727651bf738b6b917335025d09323d0962eda114 commit: drivers/platform/x86/acer-wmi.c: In function ‘WMID_set_capabilities’: drivers/platform/x86/acer-wmi.c:1211: warning: ‘devices’ may be used uninitialized in this function This patch fixes the above warning message. Cc: Carlos Corbacho Cc: Matthew Garrett Cc: Dmitry Torokhov Cc: Corentin Chary Cc: Fengguang Wu Signed-off-by: Lee, Chun-Yi Signed-off-by: Matthew Garrett --- drivers/platform/x86/acer-wmi.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index 563dc3f0e3e..c9076bdaf2c 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -1222,6 +1222,9 @@ static acpi_status WMID_set_capabilities(void) devices = *((u32 *) obj->buffer.pointer); } else if (obj->type == ACPI_TYPE_INTEGER) { devices = (u32) obj->integer.value; + } else { + kfree(out.pointer); + return AE_ERROR; } } else { kfree(out.pointer); -- cgit v1.2.3 From 2adb95d83f6e915a7d3793a8f6aa8e6e9463357c Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Mon, 14 Jan 2013 15:50:40 -0700 Subject: asus-wmi: Fix unused function build warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the following build warning CC [M] drivers/platform/x86/asus-wmi.o drivers/platform/x86/asus-wmi.c:1356:13: warning: ‘do_nothing’ defined but not used [-Wunused-function] Signed-off-by: Shuah Khan Signed-off-by: Matthew Garrett --- drivers/platform/x86/asus-wmi.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index e41eae31585..c11b2426dac 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -1353,11 +1353,6 @@ static int is_display_toggle(int code) return 0; } -static void do_nothing(void) -{ - return; -} - static void asus_wmi_notify(u32 value, void *context) { struct asus_wmi *asus = context; -- cgit v1.2.3 From fabf85e3ca15d5b94058f391dac8df870cdd427a Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Thu, 31 Jan 2013 15:44:27 -0500 Subject: hp-wmi: Add support for SMBus hotkeys Several models of HP laptops using the same DSDT have hotkey buttons that do not work until the EC is configured to enable them. Signed-off-by: Kyle Evans Signed-off-by: Matthew Garrett --- drivers/platform/x86/hp-wmi.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 2179c03b94d..be9227dd82b 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -138,6 +138,7 @@ static const struct key_entry hp_wmi_keymap[] = { { KE_KEY, 0x2142, { KEY_MEDIA } }, { KE_KEY, 0x213b, { KEY_INFO } }, { KE_KEY, 0x2169, { KEY_DIRECTION } }, + { KE_KEY, 0x216a, { KEY_SETUP } }, { KE_KEY, 0x231b, { KEY_HELP } }, { KE_END, 0 } }; @@ -926,6 +927,9 @@ static int __init hp_wmi_init(void) err = hp_wmi_input_setup(); if (err) return err; + + //Enable magic for hotkeys that run on the SMBus + ec_write(0xe6,0x6e); } if (bios_capable) { -- cgit v1.2.3 From 34cf1df34aba1a6274deeef92ad6d02d5f52dab0 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 1 Feb 2013 16:28:27 +0300 Subject: sony-laptop: leak in error handling sony_nc_lid_resume_setup() We need to decrement "i" first because the current "i" was not allocated succesfully. Also we should go free the way down to zero to avoid a leak. Signed-off-by: Dan Carpenter Signed-off-by: Matthew Garrett --- drivers/platform/x86/sony-laptop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 438c7fa999f..9557414954f 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -2351,7 +2351,7 @@ static int sony_nc_lid_resume_setup(struct platform_device *pd) return 0; liderror: - for (; i > 0; i--) + for (i--; i >= 0; i--) device_remove_file(&pd->dev, &lid_ctl->attrs[i]); kfree(lid_ctl); -- cgit v1.2.3 From c165b80cfecc5f253e93ebd133f7c53cf81d82d5 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 20 Feb 2013 00:44:34 -0800 Subject: hp-wmi: fix handling of platform device The driver will not quite work if someone unbinds the platform device from the platform driver via sysfs (moreover it will bomb is the driver built into the kernel as hp_wmi_bios_remove is marked as __exit and will not be present in the kernel). To fix it let's use platform_driver_probe() instead of platform_driver_register(), which disables binding/unbinding via sysfs. This also allows us to mark hp_wmi_bios_setup as __init and discard it once module is initialized. Signed-off-by: Dmitry Torokhov Signed-off-by: Matthew Garrett --- drivers/platform/x86/hp-wmi.c | 69 +++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 39 deletions(-) diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index be9227dd82b..45cacf79f3a 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -73,10 +73,6 @@ enum hp_wmi_event_ids { HPWMI_LOCK_SWITCH = 7, }; -static int hp_wmi_bios_setup(struct platform_device *device); -static int __exit hp_wmi_bios_remove(struct platform_device *device); -static int hp_wmi_resume_handler(struct device *device); - struct bios_args { u32 signature; u32 command; @@ -160,21 +156,6 @@ struct rfkill2_device { static int rfkill2_count; static struct rfkill2_device rfkill2[HPWMI_MAX_RFKILL2_DEVICES]; -static const struct dev_pm_ops hp_wmi_pm_ops = { - .resume = hp_wmi_resume_handler, - .restore = hp_wmi_resume_handler, -}; - -static struct platform_driver hp_wmi_driver = { - .driver = { - .name = "hp-wmi", - .owner = THIS_MODULE, - .pm = &hp_wmi_pm_ops, - }, - .probe = hp_wmi_bios_setup, - .remove = hp_wmi_bios_remove, -}; - /* * hp_wmi_perform_query * @@ -812,7 +793,7 @@ fail: return err; } -static int hp_wmi_bios_setup(struct platform_device *device) +static int __init hp_wmi_bios_setup(struct platform_device *device) { int err; @@ -917,12 +898,29 @@ static int hp_wmi_resume_handler(struct device *device) return 0; } +static const struct dev_pm_ops hp_wmi_pm_ops = { + .resume = hp_wmi_resume_handler, + .restore = hp_wmi_resume_handler, +}; + +static struct platform_driver hp_wmi_driver = { + .driver = { + .name = "hp-wmi", + .owner = THIS_MODULE, + .pm = &hp_wmi_pm_ops, + }, + .remove = __exit_p(hp_wmi_bios_remove), +}; + static int __init hp_wmi_init(void) { int err; int event_capable = wmi_has_guid(HPWMI_EVENT_GUID); int bios_capable = wmi_has_guid(HPWMI_BIOS_GUID); + if (!bios_capable && !event_capable) + return -ENODEV; + if (event_capable) { err = hp_wmi_input_setup(); if (err) @@ -933,34 +931,29 @@ static int __init hp_wmi_init(void) } if (bios_capable) { - err = platform_driver_register(&hp_wmi_driver); - if (err) - goto err_driver_reg; - hp_wmi_platform_dev = platform_device_alloc("hp-wmi", -1); - if (!hp_wmi_platform_dev) { - err = -ENOMEM; - goto err_device_alloc; + hp_wmi_platform_dev = + platform_device_register_simple("hp-wmi", -1, NULL, 0); + if (IS_ERR(hp_wmi_platform_dev)) { + err = PTR_ERR(hp_wmi_platform_dev); + goto err_destroy_input; } - err = platform_device_add(hp_wmi_platform_dev); + + err = platform_driver_probe(&hp_wmi_driver, hp_wmi_bios_setup); if (err) - goto err_device_add; + goto err_unregister_device; } - if (!bios_capable && !event_capable) - return -ENODEV; - return 0; -err_device_add: - platform_device_put(hp_wmi_platform_dev); -err_device_alloc: - platform_driver_unregister(&hp_wmi_driver); -err_driver_reg: +err_unregister_device: + platform_device_unregister(hp_wmi_platform_dev); +err_destroy_input: if (event_capable) hp_wmi_input_destroy(); return err; } +module_init(hp_wmi_init); static void __exit hp_wmi_exit(void) { @@ -972,6 +965,4 @@ static void __exit hp_wmi_exit(void) platform_driver_unregister(&hp_wmi_driver); } } - -module_init(hp_wmi_init); module_exit(hp_wmi_exit); -- cgit v1.2.3 From 8e1ad4c4bf7b99b495625433a1fcc2b566caa222 Mon Sep 17 00:00:00 2001 From: Benson Leung Date: Thu, 21 Feb 2013 12:14:59 -0800 Subject: Platform: x86: chromeos_laptop - Add Pixel Trackpad Instantiate the atmel mxt224s trackpad on this system. The trackpad may appear at two possible addresses: 0x4b in operational mode. 0x25 in bootloader mode. Signed-off-by: Benson Leung Signed-off-by: Matthew Garrett --- drivers/platform/x86/chromeos_laptop.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/drivers/platform/x86/chromeos_laptop.c b/drivers/platform/x86/chromeos_laptop.c index bc6599c5bbe..577e64d9f0a 100644 --- a/drivers/platform/x86/chromeos_laptop.c +++ b/drivers/platform/x86/chromeos_laptop.c @@ -25,6 +25,8 @@ #include #include +#define ATMEL_TP_I2C_ADDR 0x4b +#define ATMEL_TP_I2C_BL_ADDR 0x25 #define CYAPA_TP_I2C_ADDR 0x67 #define ISL_ALS_I2C_ADDR 0x44 #define TAOS_ALS_I2C_ADDR 0x29 @@ -58,6 +60,12 @@ static struct i2c_board_info __initdata tsl2563_als_device = { I2C_BOARD_INFO("tsl2563", TAOS_ALS_I2C_ADDR), }; +static struct i2c_board_info __initdata atmel_224s_tp_device = { + I2C_BOARD_INFO("atmel_mxt_tp", ATMEL_TP_I2C_ADDR), + .platform_data = NULL, + .flags = I2C_CLIENT_WAKE, +}; + static struct i2c_client __init *__add_probed_i2c_device( const char *name, int bus, @@ -161,6 +169,19 @@ static int __init setup_cyapa_smbus_tp(const struct dmi_system_id *id) return 0; } +static int __init setup_atmel_224s_tp(const struct dmi_system_id *id) +{ + const unsigned short addr_list[] = { ATMEL_TP_I2C_BL_ADDR, + ATMEL_TP_I2C_ADDR, + I2C_CLIENT_END }; + + /* add atmel mxt touchpad on VGA DDC GMBus */ + tp = add_probed_i2c_device("trackpad", I2C_ADAPTER_VGADDC, + &atmel_224s_tp_device, addr_list); + return 0; +} + + static int __init setup_isl29018_als(const struct dmi_system_id *id) { /* add isl29018 light sensor */ @@ -191,6 +212,14 @@ static struct dmi_system_id __initdata chromeos_laptop_dmi_table[] = { }, .callback = setup_cyapa_smbus_tp, }, + { + .ident = "Chromebook Pixel - Touchpad", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"), + DMI_MATCH(DMI_PRODUCT_NAME, "Link"), + }, + .callback = setup_atmel_224s_tp, + }, { .ident = "Samsung Series 5 550 - Light Sensor", .matches = { -- cgit v1.2.3 From bcaf089c5160639d6c43091f717faa3d0dc8f3d8 Mon Sep 17 00:00:00 2001 From: Benson Leung Date: Thu, 21 Feb 2013 12:14:58 -0800 Subject: Platform: x86: chromeos_laptop - Add support for probing devices This will allow support for devices that may appear at more than one i2c address at boot time. The specific example is the atmel_mxt touch devices, which may appear at a different address if it comes up in bootloader mode. Signed-off-by: Benson Leung Signed-off-by: Matthew Garrett --- drivers/platform/x86/chromeos_laptop.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/platform/x86/chromeos_laptop.c b/drivers/platform/x86/chromeos_laptop.c index 577e64d9f0a..c13f0c5e282 100644 --- a/drivers/platform/x86/chromeos_laptop.c +++ b/drivers/platform/x86/chromeos_laptop.c @@ -147,6 +147,26 @@ static int __init find_i2c_adapter_num(enum i2c_adapter_type type) return adapter->nr; } +/* + * Takes a list of addresses in addrs as such : + * { addr1, ... , addrn, I2C_CLIENT_END }; + * add_probed_i2c_device will use i2c_new_probed_device + * and probe for devices at all of the addresses listed. + * Returns NULL if no devices found. + * See Documentation/i2c/instantiating-devices for more information. + */ +static __init struct i2c_client *add_probed_i2c_device( + const char *name, + enum i2c_adapter_type type, + struct i2c_board_info *info, + const unsigned short *addrs) +{ + return __add_probed_i2c_device(name, + find_i2c_adapter_num(type), + info, + addrs); +} + /* * Probes for a device at a single address, the one provided by * info->addr. -- cgit v1.2.3 From 33a84f8a7694e442a624556ef3ae40e91e31bd11 Mon Sep 17 00:00:00 2001 From: Yufeng Shen Date: Thu, 21 Feb 2013 12:15:00 -0800 Subject: Platform: x86: chromeos_laptop - Add Pixel Touchscreen Instantiate the atmel mxt1664s touchscreen on this system. The touchscreen may appear at two possible addresses: 0x4a in operational mode. 0x26 in bootloader mode. Signed-off-by: Yufeng Shen Signed-off-by: Benson Leung Signed-off-by: Matthew Garrett --- drivers/platform/x86/chromeos_laptop.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/drivers/platform/x86/chromeos_laptop.c b/drivers/platform/x86/chromeos_laptop.c index c13f0c5e282..e5380e772b2 100644 --- a/drivers/platform/x86/chromeos_laptop.c +++ b/drivers/platform/x86/chromeos_laptop.c @@ -27,12 +27,15 @@ #define ATMEL_TP_I2C_ADDR 0x4b #define ATMEL_TP_I2C_BL_ADDR 0x25 +#define ATMEL_TS_I2C_ADDR 0x4a +#define ATMEL_TS_I2C_BL_ADDR 0x26 #define CYAPA_TP_I2C_ADDR 0x67 #define ISL_ALS_I2C_ADDR 0x44 #define TAOS_ALS_I2C_ADDR 0x29 static struct i2c_client *als; static struct i2c_client *tp; +static struct i2c_client *ts; const char *i2c_adapter_names[] = { "SMBus I801 adapter", @@ -66,6 +69,12 @@ static struct i2c_board_info __initdata atmel_224s_tp_device = { .flags = I2C_CLIENT_WAKE, }; +static struct i2c_board_info __initdata atmel_1664s_device = { + I2C_BOARD_INFO("atmel_mxt_ts", ATMEL_TS_I2C_ADDR), + .platform_data = NULL, + .flags = I2C_CLIENT_WAKE, +}; + static struct i2c_client __init *__add_probed_i2c_device( const char *name, int bus, @@ -201,6 +210,18 @@ static int __init setup_atmel_224s_tp(const struct dmi_system_id *id) return 0; } +static int __init setup_atmel_1664s_ts(const struct dmi_system_id *id) +{ + const unsigned short addr_list[] = { ATMEL_TS_I2C_BL_ADDR, + ATMEL_TS_I2C_ADDR, + I2C_CLIENT_END }; + + /* add atmel mxt touch device on PANEL GMBus */ + ts = add_probed_i2c_device("touchscreen", I2C_ADAPTER_PANEL, + &atmel_1664s_device, addr_list); + return 0; +} + static int __init setup_isl29018_als(const struct dmi_system_id *id) { @@ -232,6 +253,14 @@ static struct dmi_system_id __initdata chromeos_laptop_dmi_table[] = { }, .callback = setup_cyapa_smbus_tp, }, + { + .ident = "Chromebook Pixel - Touchscreen", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"), + DMI_MATCH(DMI_PRODUCT_NAME, "Link"), + }, + .callback = setup_atmel_1664s_ts, + }, { .ident = "Chromebook Pixel - Touchpad", .matches = { @@ -302,6 +331,8 @@ static void __exit chromeos_laptop_exit(void) i2c_unregister_device(als); if (tp) i2c_unregister_device(tp); + if (ts) + i2c_unregister_device(ts); } module_init(chromeos_laptop_init); -- cgit v1.2.3 From e7b28845d794b0f382a3942558c24e63d5e45c32 Mon Sep 17 00:00:00 2001 From: Benson Leung Date: Thu, 21 Feb 2013 12:14:56 -0800 Subject: Platform: x86: chromeos_laptop - Add a more general add_i2c_device This will allow us to assign devices to buses by the type enum. Signed-off-by: Benson Leung Signed-off-by: Matthew Garrett --- drivers/platform/x86/chromeos_laptop.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/platform/x86/chromeos_laptop.c b/drivers/platform/x86/chromeos_laptop.c index e5380e772b2..6bde4e4c93b 100644 --- a/drivers/platform/x86/chromeos_laptop.c +++ b/drivers/platform/x86/chromeos_laptop.c @@ -181,16 +181,24 @@ static __init struct i2c_client *add_probed_i2c_device( * info->addr. * Returns NULL if no device found. */ -static struct i2c_client __init *add_smbus_device(const char *name, - struct i2c_board_info *info) +static __init struct i2c_client *add_i2c_device(const char *name, + enum i2c_adapter_type type, + struct i2c_board_info *info) { const unsigned short addr_list[] = { info->addr, I2C_CLIENT_END }; return __add_probed_i2c_device(name, - find_i2c_adapter_num(I2C_ADAPTER_SMBUS), + find_i2c_adapter_num(type), info, addr_list); } + +static struct i2c_client __init *add_smbus_device(const char *name, + struct i2c_board_info *info) +{ + return add_i2c_device(name, I2C_ADAPTER_SMBUS, info); +} + static int __init setup_cyapa_smbus_tp(const struct dmi_system_id *id) { /* add cyapa touchpad on smbus */ -- cgit v1.2.3 From cc5c3985a3b17cc7a4bfdf084950d92c8919ea4b Mon Sep 17 00:00:00 2001 From: Benson Leung Date: Thu, 21 Feb 2013 12:14:57 -0800 Subject: Platform: x86: chromeos_laptop - Add isl light sensor for Pixel The Chromebook Pixel uses an isl29023 ambient light sensor on the PANEL GMBus. Signed-off-by: Benson Leung Signed-off-by: Matthew Garrett --- drivers/platform/x86/chromeos_laptop.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/platform/x86/chromeos_laptop.c b/drivers/platform/x86/chromeos_laptop.c index 6bde4e4c93b..04a11cca399 100644 --- a/drivers/platform/x86/chromeos_laptop.c +++ b/drivers/platform/x86/chromeos_laptop.c @@ -238,6 +238,14 @@ static int __init setup_isl29018_als(const struct dmi_system_id *id) return 0; } +static int __init setup_isl29023_als(const struct dmi_system_id *id) +{ + /* add isl29023 light sensor on Panel GMBus */ + als = add_i2c_device("lightsensor", I2C_ADAPTER_PANEL, + &isl_als_device); + return 0; +} + static int __init setup_tsl2583_als(const struct dmi_system_id *id) { /* add tsl2583 light sensor on smbus */ @@ -285,6 +293,14 @@ static struct dmi_system_id __initdata chromeos_laptop_dmi_table[] = { }, .callback = setup_isl29018_als, }, + { + .ident = "Chromebook Pixel - Light Sensor", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"), + DMI_MATCH(DMI_PRODUCT_NAME, "Link"), + }, + .callback = setup_isl29023_als, + }, { .ident = "Acer C7 Chromebook - Touchpad", .matches = { -- cgit v1.2.3 From 741bf0c7be835d7fdecac5d942e88b5d43958f40 Mon Sep 17 00:00:00 2001 From: Benson Leung Date: Thu, 21 Feb 2013 12:14:55 -0800 Subject: Platform: x86: chromeos_laptop - add i915 gmbuses to adapter names Add the two other i2c buses (vga and panel) from i915. Chromebook Pixel has input and light sensor devices on these busses. Signed-off-by: Benson Leung Signed-off-by: Matthew Garrett --- drivers/platform/x86/chromeos_laptop.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/platform/x86/chromeos_laptop.c b/drivers/platform/x86/chromeos_laptop.c index 04a11cca399..93d66809355 100644 --- a/drivers/platform/x86/chromeos_laptop.c +++ b/drivers/platform/x86/chromeos_laptop.c @@ -39,11 +39,15 @@ static struct i2c_client *ts; const char *i2c_adapter_names[] = { "SMBus I801 adapter", + "i915 gmbus vga", + "i915 gmbus panel", }; /* Keep this enum consistent with i2c_adapter_names */ enum i2c_adapter_type { I2C_ADAPTER_SMBUS = 0, + I2C_ADAPTER_VGADDC, + I2C_ADAPTER_PANEL, }; static struct i2c_board_info __initdata cyapa_device = { -- cgit v1.2.3 From 16fd91e06291c964111587db15646308110c5634 Mon Sep 17 00:00:00 2001 From: Ike Panhc Date: Fri, 22 Feb 2013 16:48:40 +0800 Subject: ideapad: depends on backlight subsystem and update comment I've got a report of build failure on ideapad-laptop, which shows drivers/built-in.o: In function `ideapad_acpi_notify': ideapad-laptop.c:(.text+0x63876a): undefined reference to `backlight_force_update' drivers/built-in.o: In function `ideapad_acpi_remove': ideapad-laptop.c:(.devexit.text+0x64a7): undefined reference to `backlight_device_unregister' drivers/built-in.o: In function `ideapad_acpi_add': ideapad-laptop.c:(.devinit.text+0x45e28): undefined reference to `backlight_device_register' To select backlight subsystem can prevent this error from happening. Also update comment for this driver. Reported-by: Fengguang Wu Signed-off-by: Ike Panhc Signed-off-by: Matthew Garrett --- drivers/platform/x86/Kconfig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 585db6fa64b..242c5248fde 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -300,8 +300,10 @@ config IDEAPAD_LAPTOP depends on RFKILL && INPUT depends on SERIO_I8042 select INPUT_SPARSEKMAP + select BACKLIGHT_CLASS_DEVICE help - This is a driver for the rfkill switches on Lenovo IdeaPad netbooks. + This is a driver for Lenovo IdeaPad netbooks contains drivers for + rfkill switch, hotkey, fan control and backlight control. config THINKPAD_ACPI tristate "ThinkPad ACPI Laptop Extras" -- cgit v1.2.3 From 445e8d007c29d7f4d497c7912236b69f608340c6 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Mon, 25 Feb 2013 16:59:57 -0500 Subject: ideapad-laptop: Depend on BACKLIGHT_CLASS_DEVICE instead of selecting it Selecting BACKLIGHT_CLASS_DEVICE doesn't guarantee that any of its dependencies are enabled, and these are complicated. Depending isn't ideal for configuration UI purposes, but is probably more appropriate here. Signed-off-by: Matthew Garrett --- drivers/platform/x86/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 242c5248fde..3338437b559 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -299,8 +299,8 @@ config IDEAPAD_LAPTOP depends on ACPI depends on RFKILL && INPUT depends on SERIO_I8042 + depends on BACKLIGHT_CLASS_DEVICE select INPUT_SPARSEKMAP - select BACKLIGHT_CLASS_DEVICE help This is a driver for Lenovo IdeaPad netbooks contains drivers for rfkill switch, hotkey, fan control and backlight control. -- cgit v1.2.3