From 7deef550f3a7d44c1d52a6d54f824e7e180c08ae Mon Sep 17 00:00:00 2001 From: Azael Avalos Date: Wed, 22 Jul 2015 18:09:10 -0600 Subject: toshiba_acpi: Adapt /proc/acpi/toshiba/keys to TOS1900 devices Since the introduction of TOS1900 devices support to the driver, the "keys" entry under the proc directory was broken, given that it only handled TOS620X devices accordingly. This patch adapts the code to show the hotkey values of TOS1900 devices too, and in case some programs are still using that interface, hotkeys reporting should now work on these devices. Signed-off-by: Azael Avalos Signed-off-by: Darren Hart --- drivers/platform/x86/toshiba_acpi.c | 56 +++++++++++++------------------------ 1 file changed, 20 insertions(+), 36 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index 3ad7b1fa24ce..c3a0c4d0c1dc 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -1499,32 +1499,10 @@ static const struct file_operations fan_proc_fops = { static int keys_proc_show(struct seq_file *m, void *v) { struct toshiba_acpi_dev *dev = m->private; - u32 hci_result; - u32 value; - - if (!dev->key_event_valid && dev->system_event_supported) { - hci_result = hci_read(dev, HCI_SYSTEM_EVENT, &value); - if (hci_result == TOS_SUCCESS) { - dev->key_event_valid = 1; - dev->last_key_event = value; - } else if (hci_result == TOS_FIFO_EMPTY) { - /* Better luck next time */ - } else if (hci_result == TOS_NOT_SUPPORTED) { - /* - * This is a workaround for an unresolved issue on - * some machines where system events sporadically - * become disabled. - */ - hci_result = hci_write(dev, HCI_SYSTEM_EVENT, 1); - pr_notice("Re-enabled hotkeys\n"); - } else { - pr_err("Error reading hotkey status\n"); - return -EIO; - } - } seq_printf(m, "hotkey_ready: %d\n", dev->key_event_valid); seq_printf(m, "hotkey: 0x%04x\n", dev->last_key_event); + return 0; } @@ -2361,22 +2339,28 @@ static void toshiba_acpi_report_hotkey(struct toshiba_acpi_dev *dev, static void toshiba_acpi_process_hotkeys(struct toshiba_acpi_dev *dev) { - u32 hci_result, value; - int retries = 3; - int scancode; - if (dev->info_supported) { - scancode = toshiba_acpi_query_hotkey(dev); - if (scancode < 0) + int scancode = toshiba_acpi_query_hotkey(dev); + + if (scancode < 0) { pr_err("Failed to query hotkey event\n"); - else if (scancode != 0) + } else if (scancode != 0) { toshiba_acpi_report_hotkey(dev, scancode); + dev->key_event_valid = 1; + dev->last_key_event = scancode; + } } else if (dev->system_event_supported) { + u32 result; + u32 value; + int retries = 3; + do { - hci_result = hci_read(dev, HCI_SYSTEM_EVENT, &value); - switch (hci_result) { + result = hci_read(dev, HCI_SYSTEM_EVENT, &value); + switch (result) { case TOS_SUCCESS: toshiba_acpi_report_hotkey(dev, (int)value); + dev->key_event_valid = 1; + dev->last_key_event = value; break; case TOS_NOT_SUPPORTED: /* @@ -2384,15 +2368,15 @@ static void toshiba_acpi_process_hotkeys(struct toshiba_acpi_dev *dev) * issue on some machines where system events * sporadically become disabled. */ - hci_result = - hci_write(dev, HCI_SYSTEM_EVENT, 1); - pr_notice("Re-enabled hotkeys\n"); + result = hci_write(dev, HCI_SYSTEM_EVENT, 1); + if (result == TOS_SUCCESS) + pr_notice("Re-enabled hotkeys\n"); /* Fall through */ default: retries--; break; } - } while (retries && hci_result != TOS_FIFO_EMPTY); + } while (retries && result != TOS_FIFO_EMPTY); } } -- cgit v1.2.3 From fc5462f8525b47fa219452289ecb22c921c16823 Mon Sep 17 00:00:00 2001 From: Azael Avalos Date: Wed, 22 Jul 2015 18:09:11 -0600 Subject: toshiba_acpi: Add /dev/toshiba_acpi device There were previous attempts to "merge" the toshiba SMM module to the toshiba_acpi one, they were trying to imitate what the old toshiba module does, however, some models (TOS1900 devices) come with a "crippled" implementation and do not provide all the "features" a "genuine" Toshiba BIOS does. This patch adds a new device called toshiba_acpi, which aim is to enable userspace to access the SMM on Toshiba laptops via ACPI calls. Creating a new convenience _IOWR command to access the SCI functions by opening/closing the SCI internally to avoid buggy BIOS, while at the same time providing backwards compatibility. Older programs (and new) who wish to access the SMM on newer models can do it by pointing their path to /dev/toshiba_acpi (instead of /dev/toshiba) as the toshiba.h header was modified to reflect these changes as well as adds all the toshiba_acpi paths and command, however, it is strongly recommended to use the new IOCTL for any SCI command to avoid any buggy BIOS. Signed-off-by: Azael Avalos Signed-off-by: Darren Hart --- drivers/platform/x86/toshiba_acpi.c | 91 +++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index c3a0c4d0c1dc..802577f43a23 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -50,6 +50,8 @@ #include #include #include +#include +#include #include MODULE_AUTHOR("John Belmonte"); @@ -170,6 +172,7 @@ struct toshiba_acpi_dev { struct led_classdev led_dev; struct led_classdev kbd_led; struct led_classdev eco_led; + struct miscdevice miscdev; int force_fan; int last_key_event; @@ -2239,6 +2242,81 @@ static struct attribute_group toshiba_attr_group = { .attrs = toshiba_attributes, }; +/* + * Misc device + */ +static int toshiba_acpi_smm_bridge(SMMRegisters *regs) +{ + u32 in[TCI_WORDS] = { regs->eax, regs->ebx, regs->ecx, + regs->edx, regs->esi, regs->edi }; + u32 out[TCI_WORDS]; + acpi_status status; + + status = tci_raw(toshiba_acpi, in, out); + if (ACPI_FAILURE(status)) { + pr_err("ACPI call to query SMM registers failed\n"); + return -EIO; + } + + /* Fillout the SMM struct with the TCI call results */ + regs->eax = out[0]; + regs->ebx = out[1]; + regs->ecx = out[2]; + regs->edx = out[3]; + regs->esi = out[4]; + regs->edi = out[5]; + + return 0; +} + +static long toshiba_acpi_ioctl(struct file *fp, unsigned int cmd, + unsigned long arg) +{ + SMMRegisters __user *argp = (SMMRegisters __user *)arg; + SMMRegisters regs; + int ret; + + if (!argp) + return -EINVAL; + + switch (cmd) { + case TOSH_SMM: + if (copy_from_user(®s, argp, sizeof(SMMRegisters))) + return -EFAULT; + ret = toshiba_acpi_smm_bridge(®s); + if (ret) + return ret; + if (copy_to_user(argp, ®s, sizeof(SMMRegisters))) + return -EFAULT; + break; + case TOSHIBA_ACPI_SCI: + if (copy_from_user(®s, argp, sizeof(SMMRegisters))) + return -EFAULT; + /* Ensure we are being called with a SCI_{GET, SET} register */ + if (regs.eax != SCI_GET && regs.eax != SCI_SET) + return -EINVAL; + if (!sci_open(toshiba_acpi)) + return -EIO; + ret = toshiba_acpi_smm_bridge(®s); + sci_close(toshiba_acpi); + if (ret) + return ret; + if (copy_to_user(argp, ®s, sizeof(SMMRegisters))) + return -EFAULT; + break; + default: + return -EINVAL; + } + + return 0; +} + +static const struct file_operations toshiba_acpi_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = toshiba_acpi_ioctl, + .llseek = noop_llseek, +}; + /* * Hotkeys */ @@ -2540,6 +2618,8 @@ static int toshiba_acpi_remove(struct acpi_device *acpi_dev) { struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev); + misc_deregister(&dev->miscdev); + remove_toshiba_proc_entries(dev); if (dev->sysfs_created) @@ -2611,6 +2691,17 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev) return -ENOMEM; dev->acpi_dev = acpi_dev; dev->method_hci = hci_method; + dev->miscdev.minor = MISC_DYNAMIC_MINOR; + dev->miscdev.name = "toshiba_acpi"; + dev->miscdev.fops = &toshiba_acpi_fops; + + ret = misc_register(&dev->miscdev); + if (ret) { + pr_err("Failed to register miscdevice\n"); + kfree(dev); + return ret; + } + acpi_dev->driver_data = dev; dev_set_drvdata(&acpi_dev->dev, dev); -- cgit v1.2.3 From a88bc06e5aec4984f5bf01c6d410a0939134f737 Mon Sep 17 00:00:00 2001 From: Azael Avalos Date: Wed, 22 Jul 2015 18:09:12 -0600 Subject: toshiba_acpi: Avoid registering input device on WMI event laptops Commit f11f999e9890 ("toshiba_acpi: Refuse to load on machines with buggy INFO implementations") denied loading on laptops with a WMI Event GUID given that such laptops manage the hotkeys via that interface, however, such laptops have a working Toshiba Configuration Interface (TCI), and thus, such commit denied several supported features. This patch avoids registering the input device and ignores all hotkey events on laptops with such WMI Event GUID, making the supported features found in those laptops to work. Signed-off-by: Azael Avalos Signed-off-by: Darren Hart --- drivers/platform/x86/toshiba_acpi.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index 802577f43a23..48b16b323c89 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -2466,6 +2466,11 @@ static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev) u32 hci_result; int error; + if (wmi_has_guid(TOSHIBA_WMI_EVENT_GUID)) { + pr_info("WMI event detected, hotkeys will not be monitored\n"); + return 0; + } + error = toshiba_acpi_enable_hotkeys(dev); if (error) return error; @@ -2813,6 +2818,14 @@ static void toshiba_acpi_notify(struct acpi_device *acpi_dev, u32 event) switch (event) { case 0x80: /* Hotkeys and some system events */ + /* + * Machines with this WMI GUID aren't supported due to bugs in + * their AML. + * + * Return silently to avoid triggering a netlink event. + */ + if (wmi_has_guid(TOSHIBA_WMI_EVENT_GUID)) + return; toshiba_acpi_process_hotkeys(dev); break; case 0x81: /* Dock events */ @@ -2899,14 +2912,6 @@ static int __init toshiba_acpi_init(void) { int ret; - /* - * Machines with this WMI guid aren't supported due to bugs in - * their AML. This check relies on wmi initializing before - * toshiba_acpi to guarantee guids have been identified. - */ - if (wmi_has_guid(TOSHIBA_WMI_EVENT_GUID)) - return -ENODEV; - toshiba_proc_dir = proc_mkdir(PROC_TOSHIBA, acpi_root_dir); if (!toshiba_proc_dir) { pr_err("Unable to create proc dir " PROC_TOSHIBA "\n"); -- cgit v1.2.3 From 695f6060903cefa08ffb78433136f51ac0f94488 Mon Sep 17 00:00:00 2001 From: Azael Avalos Date: Wed, 22 Jul 2015 18:09:13 -0600 Subject: toshiba_acpi: Transflective backlight updates This patch changes the tr function second parameter from bool to u32, to be on par with the rest of the TCI functions of the driver, and the code was updated accordingly. Also, the check for translective support was moved to the *add function, as the {__get, set}_lcd_brightness functions make use of it. Signed-off-by: Azael Avalos Signed-off-by: Darren Hart --- drivers/platform/x86/toshiba_acpi.c | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index 48b16b323c89..649786de4a79 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -1187,22 +1187,17 @@ static int toshiba_hotkey_event_type_get(struct toshiba_acpi_dev *dev, } /* Transflective Backlight */ -static int get_tr_backlight_status(struct toshiba_acpi_dev *dev, bool *enabled) +static int get_tr_backlight_status(struct toshiba_acpi_dev *dev, u32 *status) { - u32 hci_result; - u32 status; + u32 hci_result = hci_read(dev, HCI_TR_BACKLIGHT, status); - hci_result = hci_read(dev, HCI_TR_BACKLIGHT, &status); - *enabled = !status; return hci_result == TOS_SUCCESS ? 0 : -EIO; } -static int set_tr_backlight_status(struct toshiba_acpi_dev *dev, bool enable) +static int set_tr_backlight_status(struct toshiba_acpi_dev *dev, u32 status) { - u32 hci_result; - u32 value = !enable; + u32 hci_result = hci_write(dev, HCI_TR_BACKLIGHT, !status); - hci_result = hci_write(dev, HCI_TR_BACKLIGHT, value); return hci_result == TOS_SUCCESS ? 0 : -EIO; } @@ -1216,12 +1211,11 @@ static int __get_lcd_brightness(struct toshiba_acpi_dev *dev) int brightness = 0; if (dev->tr_backlight_supported) { - bool enabled; - int ret = get_tr_backlight_status(dev, &enabled); + int ret = get_tr_backlight_status(dev, &value); if (ret) return ret; - if (enabled) + if (value) return 0; brightness++; } @@ -1271,8 +1265,7 @@ static int set_lcd_brightness(struct toshiba_acpi_dev *dev, int value) u32 hci_result; if (dev->tr_backlight_supported) { - bool enable = !value; - int ret = set_tr_backlight_status(dev, enable); + int ret = set_tr_backlight_status(dev, !value); if (ret) return ret; @@ -2563,7 +2556,6 @@ static int toshiba_acpi_setup_backlight(struct toshiba_acpi_dev *dev) struct backlight_properties props; int brightness; int ret; - bool enabled; /* * Some machines don't support the backlight methods at all, and @@ -2580,10 +2572,6 @@ static int toshiba_acpi_setup_backlight(struct toshiba_acpi_dev *dev) return 0; } - /* Determine whether or not BIOS supports transflective backlight */ - ret = get_tr_backlight_status(dev, &enabled); - dev->tr_backlight_supported = !ret; - /* * Tell acpi-video-detect code to prefer vendor backlight on all * systems with transflective backlight and on dmi matched systems. @@ -2723,6 +2711,10 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev) if (toshiba_acpi_setup_keyboard(dev)) pr_info("Unable to activate hotkeys\n"); + /* Determine whether or not BIOS supports transflective backlight */ + ret = get_tr_backlight_status(dev, &dummy); + dev->tr_backlight_supported = !ret; + ret = toshiba_acpi_setup_backlight(dev); if (ret) goto error; -- cgit v1.2.3 From d7e4f2e2ca392bce468718bcbba808108d81d501 Mon Sep 17 00:00:00 2001 From: Azael Avalos Date: Wed, 22 Jul 2015 19:37:47 -0600 Subject: toshiba_acpi: Remove unused wireless defines Commit 2b74103547b4 ("toshiba_acpi: Remove bluetooth rfkill code") removed bluetooth related code, however, the wireless defines were not removed and are unused. This patch simply removes those defines as there is no code using them. Signed-off-by: Azael Avalos Signed-off-by: Darren Hart --- drivers/platform/x86/toshiba_acpi.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index 649786de4a79..90d8cb1c2e27 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -113,7 +113,6 @@ MODULE_LICENSE("GPL"); #define HCI_VIDEO_OUT 0x001c #define HCI_HOTKEY_EVENT 0x001e #define HCI_LCD_BRIGHTNESS 0x002a -#define HCI_WIRELESS 0x0056 #define HCI_ACCELEROMETER 0x006d #define HCI_KBD_ILLUMINATION 0x0095 #define HCI_ECO_MODE 0x0097 @@ -142,10 +141,6 @@ MODULE_LICENSE("GPL"); #define HCI_VIDEO_OUT_LCD 0x1 #define HCI_VIDEO_OUT_CRT 0x2 #define HCI_VIDEO_OUT_TV 0x4 -#define HCI_WIRELESS_KILL_SWITCH 0x01 -#define HCI_WIRELESS_BT_PRESENT 0x0f -#define HCI_WIRELESS_BT_ATTACH 0x40 -#define HCI_WIRELESS_BT_POWER 0x80 #define SCI_KBD_MODE_MASK 0x1f #define SCI_KBD_MODE_FNZ 0x1 #define SCI_KBD_MODE_AUTO 0x2 -- cgit v1.2.3 From d50c9005d32b4eda6e11f7ec4f1b00a93088e0ca Mon Sep 17 00:00:00 2001 From: Azael Avalos Date: Wed, 22 Jul 2015 19:37:46 -0600 Subject: toshiba_acpi: Reorder toshiba_acpi_alt_keymap entries This patch simply reorders the entries found in the new keymap by ascending order, this is simply a cosmetic change, no functionality was modified. Signed-off-by: Azael Avalos Signed-off-by: Darren Hart --- drivers/platform/x86/toshiba_acpi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index 90d8cb1c2e27..6013a11caeea 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -246,16 +246,16 @@ static const struct key_entry toshiba_acpi_keymap[] = { }; static const struct key_entry toshiba_acpi_alt_keymap[] = { - { KE_KEY, 0x157, { KEY_MUTE } }, { KE_KEY, 0x102, { KEY_ZOOMOUT } }, { KE_KEY, 0x103, { KEY_ZOOMIN } }, { KE_KEY, 0x12c, { KEY_KBDILLUMTOGGLE } }, { KE_KEY, 0x139, { KEY_ZOOMRESET } }, - { KE_KEY, 0x13e, { KEY_SWITCHVIDEOMODE } }, { KE_KEY, 0x13c, { KEY_BRIGHTNESSDOWN } }, { KE_KEY, 0x13d, { KEY_BRIGHTNESSUP } }, - { KE_KEY, 0x158, { KEY_WLAN } }, + { KE_KEY, 0x13e, { KEY_SWITCHVIDEOMODE } }, { KE_KEY, 0x13f, { KEY_TOUCHPAD_TOGGLE } }, + { KE_KEY, 0x157, { KEY_MUTE } }, + { KE_KEY, 0x158, { KEY_WLAN } }, { KE_END, 0 }, }; -- cgit v1.2.3 From 1e574dbfadafd9fd1f2a414efb731d7538277e71 Mon Sep 17 00:00:00 2001 From: Azael Avalos Date: Wed, 22 Jul 2015 19:37:49 -0600 Subject: toshiba_acpi: Change some variables to avoid warnings from ninja-check This patch changes some variables to avoid warnings from ninja-check. We are basically moving some variables inside the conditionals where such variables are being used, and we are checking the returned values of some others. Signed-off-by: Azael Avalos Signed-off-by: Darren Hart --- drivers/platform/x86/toshiba_acpi.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index 6013a11caeea..3bfdfddc38ac 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -1651,7 +1651,6 @@ static ssize_t kbd_backlight_mode_store(struct device *dev, { struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev); int mode; - int time; int ret; @@ -1682,7 +1681,7 @@ static ssize_t kbd_backlight_mode_store(struct device *dev, /* Only make a change if the actual mode has changed */ if (toshiba->kbd_mode != mode) { /* Shift the time to "base time" (0x3c0000 == 60 seconds) */ - time = toshiba->kbd_time << HCI_MISC_SHIFT; + int time = toshiba->kbd_time << HCI_MISC_SHIFT; /* OR the "base time" to the actual method format */ if (toshiba->kbd_type == 1) { @@ -2856,10 +2855,14 @@ static void toshiba_acpi_notify(struct acpi_device *acpi_dev, u32 event) static int toshiba_acpi_suspend(struct device *device) { struct toshiba_acpi_dev *dev = acpi_driver_data(to_acpi_device(device)); - u32 result; - if (dev->hotkey_dev) + if (dev->hotkey_dev) { + u32 result; + result = hci_write(dev, HCI_HOTKEY_EVENT, HCI_HOTKEY_DISABLE); + if (result != TOS_SUCCESS) + pr_info("Unable to disable hotkeys\n"); + } return 0; } @@ -2867,10 +2870,10 @@ static int toshiba_acpi_suspend(struct device *device) static int toshiba_acpi_resume(struct device *device) { struct toshiba_acpi_dev *dev = acpi_driver_data(to_acpi_device(device)); - int error; if (dev->hotkey_dev) { - error = toshiba_acpi_enable_hotkeys(dev); + int error = toshiba_acpi_enable_hotkeys(dev); + if (error) pr_info("Unable to re-enable hotkeys\n"); } -- cgit v1.2.3 From 3e07e5baa2af166a6f38a51e14ff036c341a57c7 Mon Sep 17 00:00:00 2001 From: Azael Avalos Date: Mon, 27 Jul 2015 19:22:23 -0600 Subject: toshiba_acpi: Add set_fan_status function This patch adds a new function named "set_fan_status" to complement its get* counterpart, as well as to avoid code duplication between "fan_proc_write" and "fan_store". Also, both functions (get*, set*) are now checking for TOS_FAILURE, TOS_NOT_SUPPORTED and TOS_SUCCESS (to be on par with the rest of the HCI/SCI functions), printing an error message, returning -ENODEV and zero respectively. The proc and sysfs functions were updated to reflect these changes as well, returning -EIO for proc, and propagating the error value on the sysfs functions. Signed-off-by: Azael Avalos Signed-off-by: Darren Hart --- drivers/platform/x86/toshiba_acpi.c | 66 ++++++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 26 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index 3bfdfddc38ac..f7228987bd50 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -1422,27 +1422,47 @@ static const struct file_operations video_proc_fops = { .write = video_proc_write, }; +/* Fan status */ static int get_fan_status(struct toshiba_acpi_dev *dev, u32 *status) { - u32 hci_result; + u32 result = hci_read(dev, HCI_FAN, status); - hci_result = hci_read(dev, HCI_FAN, status); - return hci_result == TOS_SUCCESS ? 0 : -EIO; + if (result == TOS_FAILURE) + pr_err("ACPI call to get Fan status failed\n"); + else if (result == TOS_NOT_SUPPORTED) + return -ENODEV; + else if (result == TOS_SUCCESS) + return 0; + + return -EIO; +} + +static int set_fan_status(struct toshiba_acpi_dev *dev, u32 status) +{ + u32 result = hci_write(dev, HCI_FAN, status); + + if (result == TOS_FAILURE) + pr_err("ACPI call to set Fan status failed\n"); + else if (result == TOS_NOT_SUPPORTED) + return -ENODEV; + else if (result == TOS_SUCCESS) + return 0; + + return -EIO; } static int fan_proc_show(struct seq_file *m, void *v) { struct toshiba_acpi_dev *dev = m->private; - int ret; u32 value; - ret = get_fan_status(dev, &value); - if (!ret) { - seq_printf(m, "running: %d\n", (value > 0)); - seq_printf(m, "force_on: %d\n", dev->force_fan); - } + if (get_fan_status(dev, &value)) + return -EIO; - return ret; + seq_printf(m, "running: %d\n", (value > 0)); + seq_printf(m, "force_on: %d\n", dev->force_fan); + + return 0; } static int fan_proc_open(struct inode *inode, struct file *file) @@ -1457,23 +1477,20 @@ static ssize_t fan_proc_write(struct file *file, const char __user *buf, char cmd[42]; size_t len; int value; - u32 hci_result; len = min(count, sizeof(cmd) - 1); if (copy_from_user(cmd, buf, len)) return -EFAULT; cmd[len] = '\0'; - if (sscanf(cmd, " force_on : %i", &value) == 1 && - value >= 0 && value <= 1) { - hci_result = hci_write(dev, HCI_FAN, value); - if (hci_result == TOS_SUCCESS) - dev->force_fan = value; - else - return -EIO; - } else { + if (sscanf(cmd, " force_on : %i", &value) != 1 && + value != 0 && value != 1) return -EINVAL; - } + + if (set_fan_status(dev, value)) + return -EIO; + + dev->force_fan = value; return count; } @@ -1610,7 +1627,6 @@ static ssize_t fan_store(struct device *dev, const char *buf, size_t count) { struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev); - u32 result; int state; int ret; @@ -1621,11 +1637,9 @@ static ssize_t fan_store(struct device *dev, if (state != 0 && state != 1) return -EINVAL; - result = hci_write(toshiba, HCI_FAN, state); - if (result == TOS_FAILURE) - return -EIO; - else if (result == TOS_NOT_SUPPORTED) - return -ENODEV; + ret = set_fan_status(toshiba, state); + if (ret) + return ret; return count; } -- cgit v1.2.3 From ea215a3f909c570521a9cc276163837ffa2c621a Mon Sep 17 00:00:00 2001 From: Azael Avalos Date: Fri, 31 Jul 2015 21:58:12 -0600 Subject: toshiba_acpi: Change *available functions return type This patch changes the *available functions return type from int to void. The checks for support of their respective features are done inside such functions and there was no need to return anything as we can flag the queried feature as supported inside these functions. The code was adapted accordingly to these changes and two new variables were created and another was changed from uint to bool. Also, the function toshiba_acceleremoter_supported was renamed to toshiba_accelerometer_available to maintain the naming consistency on the driver. Signed-off-by: Azael Avalos Signed-off-by: Darren Hart --- drivers/platform/x86/toshiba_acpi.c | 129 +++++++++++++++++------------------- 1 file changed, 62 insertions(+), 67 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index f7228987bd50..d983dc45f30d 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -187,7 +187,6 @@ struct toshiba_acpi_dev { unsigned int info_supported:1; unsigned int tr_backlight_supported:1; unsigned int kbd_illum_supported:1; - unsigned int kbd_led_registered:1; unsigned int touchpad_supported:1; unsigned int eco_supported:1; unsigned int accelerometer_supported:1; @@ -198,6 +197,10 @@ struct toshiba_acpi_dev { unsigned int panel_power_on_supported:1; unsigned int usb_three_supported:1; unsigned int sysfs_created:1; + + bool kbd_led_registered; + bool illumination_led_registered; + bool eco_led_registered; }; static struct toshiba_acpi_dev *toshiba_acpi; @@ -439,26 +442,26 @@ static u32 sci_write(struct toshiba_acpi_dev *dev, u32 reg, u32 in1) } /* Illumination support */ -static int toshiba_illumination_available(struct toshiba_acpi_dev *dev) +static void toshiba_illumination_available(struct toshiba_acpi_dev *dev) { u32 in[TCI_WORDS] = { SCI_GET, SCI_ILLUMINATION, 0, 0, 0, 0 }; u32 out[TCI_WORDS]; acpi_status status; + dev->illumination_supported = 0; + dev->illumination_led_registered = false; + if (!sci_open(dev)) - return 0; + return; status = tci_raw(dev, in, out); sci_close(dev); - if (ACPI_FAILURE(status)) { + if (ACPI_FAILURE(status)) pr_err("ACPI call to query Illumination support failed\n"); - return 0; - } else if (out[0] == TOS_NOT_SUPPORTED) { + else if (out[0] == TOS_NOT_SUPPORTED) pr_info("Illumination device not available\n"); - return 0; - } - - return 1; + else if (out[0] == TOS_SUCCESS) + dev->illumination_supported = 1; } static void toshiba_illumination_set(struct led_classdev *cdev, @@ -510,41 +513,42 @@ static enum led_brightness toshiba_illumination_get(struct led_classdev *cdev) } /* KBD Illumination */ -static int toshiba_kbd_illum_available(struct toshiba_acpi_dev *dev) +static void toshiba_kbd_illum_available(struct toshiba_acpi_dev *dev) { u32 in[TCI_WORDS] = { SCI_GET, SCI_KBD_ILLUM_STATUS, 0, 0, 0, 0 }; u32 out[TCI_WORDS]; acpi_status status; + dev->kbd_illum_supported = 0; + dev->kbd_led_registered = false; + if (!sci_open(dev)) - return 0; + return; status = tci_raw(dev, in, out); sci_close(dev); if (ACPI_FAILURE(status) || out[0] == TOS_INPUT_DATA_ERROR) { pr_err("ACPI call to query kbd illumination support failed\n"); - return 0; } else if (out[0] == TOS_NOT_SUPPORTED) { pr_info("Keyboard illumination not available\n"); - return 0; + } else if (out[0] == TOS_SUCCESS) { + /* + * Check for keyboard backlight timeout max value, + * previous kbd backlight implementation set this to + * 0x3c0003, and now the new implementation set this + * to 0x3c001a, use this to distinguish between them. + */ + if (out[3] == SCI_KBD_TIME_MAX) + dev->kbd_type = 2; + else + dev->kbd_type = 1; + /* Get the current keyboard backlight mode */ + dev->kbd_mode = out[2] & SCI_KBD_MODE_MASK; + /* Get the current time (1-60 seconds) */ + dev->kbd_time = out[2] >> HCI_MISC_SHIFT; + /* Flag as supported */ + dev->kbd_illum_supported = 1; } - - /* - * Check for keyboard backlight timeout max value, - * previous kbd backlight implementation set this to - * 0x3c0003, and now the new implementation set this - * to 0x3c001a, use this to distinguish between them. - */ - if (out[3] == SCI_KBD_TIME_MAX) - dev->kbd_type = 2; - else - dev->kbd_type = 1; - /* Get the current keyboard backlight mode */ - dev->kbd_mode = out[2] & SCI_KBD_MODE_MASK; - /* Get the current time (1-60 seconds) */ - dev->kbd_time = out[2] >> HCI_MISC_SHIFT; - - return 1; } static int toshiba_kbd_illum_status_set(struct toshiba_acpi_dev *dev, u32 time) @@ -665,12 +669,15 @@ static int toshiba_touchpad_get(struct toshiba_acpi_dev *dev, u32 *state) } /* Eco Mode support */ -static int toshiba_eco_mode_available(struct toshiba_acpi_dev *dev) +static void toshiba_eco_mode_available(struct toshiba_acpi_dev *dev) { acpi_status status; u32 in[TCI_WORDS] = { HCI_GET, HCI_ECO_MODE, 0, 0, 0, 0 }; u32 out[TCI_WORDS]; + dev->eco_supported = 0; + dev->eco_led_registered = false; + status = tci_raw(dev, in, out); if (ACPI_FAILURE(status)) { pr_err("ACPI call to get ECO led failed\n"); @@ -691,10 +698,8 @@ static int toshiba_eco_mode_available(struct toshiba_acpi_dev *dev) if (ACPI_FAILURE(status) || out[0] == TOS_FAILURE) pr_err("ACPI call to get ECO led failed\n"); else if (out[0] == TOS_SUCCESS) - return 1; + dev->eco_supported = 1; } - - return 0; } static enum led_brightness @@ -734,30 +739,28 @@ static void toshiba_eco_mode_set_status(struct led_classdev *cdev, } /* Accelerometer support */ -static int toshiba_accelerometer_supported(struct toshiba_acpi_dev *dev) +static void toshiba_accelerometer_available(struct toshiba_acpi_dev *dev) { u32 in[TCI_WORDS] = { HCI_GET, HCI_ACCELEROMETER2, 0, 0, 0, 0 }; u32 out[TCI_WORDS]; acpi_status status; + dev->accelerometer_supported = 0; + /* * Check if the accelerometer call exists, * this call also serves as initialization */ status = tci_raw(dev, in, out); - if (ACPI_FAILURE(status) || out[0] == TOS_INPUT_DATA_ERROR) { + if (ACPI_FAILURE(status) || out[0] == TOS_INPUT_DATA_ERROR) pr_err("ACPI call to query the accelerometer failed\n"); - return -EIO; - } else if (out[0] == TOS_DATA_NOT_AVAILABLE || - out[0] == TOS_NOT_INITIALIZED) { + else if (out[0] == TOS_DATA_NOT_AVAILABLE || + out[0] == TOS_NOT_INITIALIZED) pr_err("Accelerometer not initialized\n"); - return -EIO; - } else if (out[0] == TOS_NOT_SUPPORTED) { + else if (out[0] == TOS_NOT_SUPPORTED) pr_info("Accelerometer not supported\n"); - return -ENODEV; - } - - return 0; + else if (out[0] == TOS_SUCCESS) + dev->accelerometer_supported = 1; } static int toshiba_accelerometer_get(struct toshiba_acpi_dev *dev, @@ -787,7 +790,6 @@ static void toshiba_usb_sleep_charge_available(struct toshiba_acpi_dev *dev) u32 out[TCI_WORDS]; acpi_status status; - /* Set the feature to "not supported" in case of error */ dev->usb_sleep_charge_supported = 0; if (!sci_open(dev)) @@ -808,25 +810,17 @@ static void toshiba_usb_sleep_charge_available(struct toshiba_acpi_dev *dev) in[5] = SCI_USB_CHARGE_BAT_LVL; status = tci_raw(dev, in, out); + sci_close(dev); if (ACPI_FAILURE(status)) { pr_err("ACPI call to get USB Sleep and Charge mode failed\n"); - sci_close(dev); - return; } else if (out[0] == TOS_NOT_SUPPORTED) { pr_info("USB Sleep and Charge not supported\n"); - sci_close(dev); - return; } else if (out[0] == TOS_SUCCESS) { dev->usbsc_bat_level = out[2]; - /* - * If we reach this point, it means that the laptop has support - * for this feature and all values are initialized. - * Set it as supported. - */ + /* Flag as supported */ dev->usb_sleep_charge_supported = 1; } - sci_close(dev); } static int toshiba_usb_sleep_charge_get(struct toshiba_acpi_dev *dev, @@ -2639,13 +2633,13 @@ static int toshiba_acpi_remove(struct acpi_device *acpi_dev) backlight_device_unregister(dev->backlight_dev); - if (dev->illumination_supported) + if (dev->illumination_led_registered) led_classdev_unregister(&dev->led_dev); if (dev->kbd_led_registered) led_classdev_unregister(&dev->kbd_led); - if (dev->eco_supported) + if (dev->eco_led_registered) led_classdev_unregister(&dev->eco_led); if (toshiba_acpi) @@ -2727,25 +2721,27 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev) if (ret) goto error; - if (toshiba_illumination_available(dev)) { + toshiba_illumination_available(dev); + if (dev->illumination_supported) { dev->led_dev.name = "toshiba::illumination"; dev->led_dev.max_brightness = 1; dev->led_dev.brightness_set = toshiba_illumination_set; dev->led_dev.brightness_get = toshiba_illumination_get; if (!led_classdev_register(&acpi_dev->dev, &dev->led_dev)) - dev->illumination_supported = 1; + dev->illumination_led_registered = true; } - if (toshiba_eco_mode_available(dev)) { + toshiba_eco_mode_available(dev); + if (dev->eco_supported) { dev->eco_led.name = "toshiba::eco_mode"; dev->eco_led.max_brightness = 1; dev->eco_led.brightness_set = toshiba_eco_mode_set_status; dev->eco_led.brightness_get = toshiba_eco_mode_get_status; if (!led_classdev_register(&dev->acpi_dev->dev, &dev->eco_led)) - dev->eco_supported = 1; + dev->eco_led_registered = true; } - dev->kbd_illum_supported = toshiba_kbd_illum_available(dev); + toshiba_kbd_illum_available(dev); /* * Only register the LED if KBD illumination is supported * and the keyboard backlight operation mode is set to FN-Z @@ -2756,14 +2752,13 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev) dev->kbd_led.brightness_set = toshiba_kbd_backlight_set; dev->kbd_led.brightness_get = toshiba_kbd_backlight_get; if (!led_classdev_register(&dev->acpi_dev->dev, &dev->kbd_led)) - dev->kbd_led_registered = 1; + dev->kbd_led_registered = true; } ret = toshiba_touchpad_get(dev, &dummy); dev->touchpad_supported = !ret; - ret = toshiba_accelerometer_supported(dev); - dev->accelerometer_supported = !ret; + toshiba_accelerometer_available(dev); toshiba_usb_sleep_charge_available(dev); -- cgit v1.2.3 From 0409cbced3c9ab975e300584b6cc036c26974b43 Mon Sep 17 00:00:00 2001 From: Azael Avalos Date: Fri, 31 Jul 2015 21:58:13 -0600 Subject: toshiba_acpi: Remove "*not supported" feature prints Currently the driver prints "*not supported" if any of the features queried are in fact not supported, let us print the available features instead. This patch removes all instances pr_info printing "*not supported", and add a new function called "print_supported_features", which will print the available laptop features. Signed-off-by: Azael Avalos Signed-off-by: Darren Hart --- drivers/platform/x86/toshiba_acpi.c | 72 +++++++++++++++++++++++-------------- 1 file changed, 46 insertions(+), 26 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index d983dc45f30d..66b596a7f710 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -459,7 +459,7 @@ static void toshiba_illumination_available(struct toshiba_acpi_dev *dev) if (ACPI_FAILURE(status)) pr_err("ACPI call to query Illumination support failed\n"); else if (out[0] == TOS_NOT_SUPPORTED) - pr_info("Illumination device not available\n"); + return; else if (out[0] == TOS_SUCCESS) dev->illumination_supported = 1; } @@ -483,7 +483,6 @@ static void toshiba_illumination_set(struct led_classdev *cdev, pr_err("ACPI call for illumination failed\n"); return; } else if (result == TOS_NOT_SUPPORTED) { - pr_info("Illumination not supported\n"); return; } } @@ -505,7 +504,6 @@ static enum led_brightness toshiba_illumination_get(struct led_classdev *cdev) pr_err("ACPI call for illumination failed\n"); return LED_OFF; } else if (result == TOS_NOT_SUPPORTED) { - pr_info("Illumination not supported\n"); return LED_OFF; } @@ -530,7 +528,7 @@ static void toshiba_kbd_illum_available(struct toshiba_acpi_dev *dev) if (ACPI_FAILURE(status) || out[0] == TOS_INPUT_DATA_ERROR) { pr_err("ACPI call to query kbd illumination support failed\n"); } else if (out[0] == TOS_NOT_SUPPORTED) { - pr_info("Keyboard illumination not available\n"); + return; } else if (out[0] == TOS_SUCCESS) { /* * Check for keyboard backlight timeout max value, @@ -564,7 +562,6 @@ static int toshiba_kbd_illum_status_set(struct toshiba_acpi_dev *dev, u32 time) pr_err("ACPI call to set KBD backlight status failed\n"); return -EIO; } else if (result == TOS_NOT_SUPPORTED) { - pr_info("Keyboard backlight status not supported\n"); return -ENODEV; } @@ -584,7 +581,6 @@ static int toshiba_kbd_illum_status_get(struct toshiba_acpi_dev *dev, u32 *time) pr_err("ACPI call to get KBD backlight status failed\n"); return -EIO; } else if (result == TOS_NOT_SUPPORTED) { - pr_info("Keyboard backlight status not supported\n"); return -ENODEV; } @@ -603,7 +599,6 @@ static enum led_brightness toshiba_kbd_backlight_get(struct led_classdev *cdev) pr_err("ACPI call to get the keyboard backlight failed\n"); return LED_OFF; } else if (result == TOS_NOT_SUPPORTED) { - pr_info("Keyboard backlight not supported\n"); return LED_OFF; } @@ -624,7 +619,6 @@ static void toshiba_kbd_backlight_set(struct led_classdev *cdev, pr_err("ACPI call to set KBD Illumination mode failed\n"); return; } else if (result == TOS_NOT_SUPPORTED) { - pr_info("Keyboard backlight not supported\n"); return; } } @@ -758,7 +752,7 @@ static void toshiba_accelerometer_available(struct toshiba_acpi_dev *dev) out[0] == TOS_NOT_INITIALIZED) pr_err("Accelerometer not initialized\n"); else if (out[0] == TOS_NOT_SUPPORTED) - pr_info("Accelerometer not supported\n"); + return; else if (out[0] == TOS_SUCCESS) dev->accelerometer_supported = 1; } @@ -801,7 +795,6 @@ static void toshiba_usb_sleep_charge_available(struct toshiba_acpi_dev *dev) sci_close(dev); return; } else if (out[0] == TOS_NOT_SUPPORTED) { - pr_info("USB Sleep and Charge not supported\n"); sci_close(dev); return; } else if (out[0] == TOS_SUCCESS) { @@ -814,7 +807,7 @@ static void toshiba_usb_sleep_charge_available(struct toshiba_acpi_dev *dev) if (ACPI_FAILURE(status)) { pr_err("ACPI call to get USB Sleep and Charge mode failed\n"); } else if (out[0] == TOS_NOT_SUPPORTED) { - pr_info("USB Sleep and Charge not supported\n"); + return; } else if (out[0] == TOS_SUCCESS) { dev->usbsc_bat_level = out[2]; /* Flag as supported */ @@ -837,7 +830,6 @@ static int toshiba_usb_sleep_charge_get(struct toshiba_acpi_dev *dev, pr_err("ACPI call to set USB S&C mode failed\n"); return -EIO; } else if (result == TOS_NOT_SUPPORTED) { - pr_info("USB Sleep and Charge not supported\n"); return -ENODEV; } else if (result == TOS_INPUT_DATA_ERROR) { return -EIO; @@ -860,7 +852,6 @@ static int toshiba_usb_sleep_charge_set(struct toshiba_acpi_dev *dev, pr_err("ACPI call to set USB S&C mode failed\n"); return -EIO; } else if (result == TOS_NOT_SUPPORTED) { - pr_info("USB Sleep and Charge not supported\n"); return -ENODEV; } else if (result == TOS_INPUT_DATA_ERROR) { return -EIO; @@ -886,7 +877,6 @@ static int toshiba_sleep_functions_status_get(struct toshiba_acpi_dev *dev, pr_err("ACPI call to get USB S&C battery level failed\n"); return -EIO; } else if (out[0] == TOS_NOT_SUPPORTED) { - pr_info("USB Sleep and Charge not supported\n"); return -ENODEV; } else if (out[0] == TOS_INPUT_DATA_ERROR) { return -EIO; @@ -915,7 +905,6 @@ static int toshiba_sleep_functions_status_set(struct toshiba_acpi_dev *dev, pr_err("ACPI call to set USB S&C battery level failed\n"); return -EIO; } else if (out[0] == TOS_NOT_SUPPORTED) { - pr_info("USB Sleep and Charge not supported\n"); return -ENODEV; } else if (out[0] == TOS_INPUT_DATA_ERROR) { return -EIO; @@ -942,7 +931,6 @@ static int toshiba_usb_rapid_charge_get(struct toshiba_acpi_dev *dev, return -EIO; } else if (out[0] == TOS_NOT_SUPPORTED || out[0] == TOS_INPUT_DATA_ERROR) { - pr_info("USB Rapid Charge not supported\n"); return -ENODEV; } @@ -969,7 +957,6 @@ static int toshiba_usb_rapid_charge_set(struct toshiba_acpi_dev *dev, pr_err("ACPI call to set USB Rapid Charge failed\n"); return -EIO; } else if (out[0] == TOS_NOT_SUPPORTED) { - pr_info("USB Rapid Charge not supported\n"); return -ENODEV; } else if (out[0] == TOS_INPUT_DATA_ERROR) { return -EIO; @@ -991,7 +978,6 @@ static int toshiba_usb_sleep_music_get(struct toshiba_acpi_dev *dev, u32 *state) pr_err("ACPI call to get Sleep and Music failed\n"); return -EIO; } else if (result == TOS_NOT_SUPPORTED) { - pr_info("Sleep and Music not supported\n"); return -ENODEV; } else if (result == TOS_INPUT_DATA_ERROR) { return -EIO; @@ -1013,7 +999,6 @@ static int toshiba_usb_sleep_music_set(struct toshiba_acpi_dev *dev, u32 state) pr_err("ACPI call to set Sleep and Music failed\n"); return -EIO; } else if (result == TOS_NOT_SUPPORTED) { - pr_info("Sleep and Music not supported\n"); return -ENODEV; } else if (result == TOS_INPUT_DATA_ERROR) { return -EIO; @@ -1036,7 +1021,6 @@ static int toshiba_function_keys_get(struct toshiba_acpi_dev *dev, u32 *mode) pr_err("ACPI call to get KBD function keys failed\n"); return -EIO; } else if (result == TOS_NOT_SUPPORTED) { - pr_info("KBD function keys not supported\n"); return -ENODEV; } @@ -1056,7 +1040,6 @@ static int toshiba_function_keys_set(struct toshiba_acpi_dev *dev, u32 mode) pr_err("ACPI call to set KBD function keys failed\n"); return -EIO; } else if (result == TOS_NOT_SUPPORTED) { - pr_info("KBD function keys not supported\n"); return -ENODEV; } @@ -1077,7 +1060,6 @@ static int toshiba_panel_power_on_get(struct toshiba_acpi_dev *dev, u32 *state) pr_err("ACPI call to get Panel Power ON failed\n"); return -EIO; } else if (result == TOS_NOT_SUPPORTED) { - pr_info("Panel Power on not supported\n"); return -ENODEV; } else if (result == TOS_INPUT_DATA_ERROR) { return -EIO; @@ -1099,7 +1081,6 @@ static int toshiba_panel_power_on_set(struct toshiba_acpi_dev *dev, u32 state) pr_err("ACPI call to set Panel Power ON failed\n"); return -EIO; } else if (result == TOS_NOT_SUPPORTED) { - pr_info("Panel Power ON not supported\n"); return -ENODEV; } else if (result == TOS_INPUT_DATA_ERROR) { return -EIO; @@ -1122,7 +1103,6 @@ static int toshiba_usb_three_get(struct toshiba_acpi_dev *dev, u32 *state) pr_err("ACPI call to get USB 3 failed\n"); return -EIO; } else if (result == TOS_NOT_SUPPORTED) { - pr_info("USB 3 not supported\n"); return -ENODEV; } else if (result == TOS_INPUT_DATA_ERROR) { return -EIO; @@ -1144,7 +1124,6 @@ static int toshiba_usb_three_set(struct toshiba_acpi_dev *dev, u32 state) pr_err("ACPI call to set USB 3 failed\n"); return -EIO; } else if (result == TOS_NOT_SUPPORTED) { - pr_info("USB 3 not supported\n"); return -ENODEV; } else if (result == TOS_INPUT_DATA_ERROR) { return -EIO; @@ -1166,7 +1145,6 @@ static int toshiba_hotkey_event_type_get(struct toshiba_acpi_dev *dev, pr_err("ACPI call to get System type failed\n"); return -EIO; } else if (out[0] == TOS_NOT_SUPPORTED) { - pr_info("System type not supported\n"); return -ENODEV; } @@ -2609,6 +2587,46 @@ static int toshiba_acpi_setup_backlight(struct toshiba_acpi_dev *dev) return 0; } +static void print_supported_features(struct toshiba_acpi_dev *dev) +{ + pr_info("Supported laptop features:"); + + if (dev->hotkey_dev) + pr_cont(" hotkeys"); + if (dev->backlight_dev) + pr_cont(" backlight"); + if (dev->video_supported) + pr_cont(" video-out"); + if (dev->fan_supported) + pr_cont(" fan"); + if (dev->tr_backlight_supported) + pr_cont(" transflective-backlight"); + if (dev->illumination_supported) + pr_cont(" illumination"); + if (dev->kbd_illum_supported) + pr_cont(" keyboard-backlight"); + if (dev->touchpad_supported) + pr_cont(" touchpad"); + if (dev->eco_supported) + pr_cont(" eco-led"); + if (dev->accelerometer_supported) + pr_cont(" accelerometer-axes"); + if (dev->usb_sleep_charge_supported) + pr_cont(" usb-sleep-charge"); + if (dev->usb_rapid_charge_supported) + pr_cont(" usb-rapid-charge"); + if (dev->usb_sleep_music_supported) + pr_cont(" usb-sleep-music"); + if (dev->kbd_function_keys_supported) + pr_cont(" special-function-keys"); + if (dev->panel_power_on_supported) + pr_cont(" panel-power-on"); + if (dev->usb_three_supported) + pr_cont(" usb3"); + + pr_cont("\n"); +} + static int toshiba_acpi_remove(struct acpi_device *acpi_dev) { struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev); @@ -2780,6 +2798,8 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev) ret = get_fan_status(dev, &dummy); dev->fan_supported = !ret; + print_supported_features(dev); + /* * Enable the "Special Functions" mode only if they are * supported and if they are activated. -- cgit v1.2.3 From e1a949c1b9883d1d0586b0cbdd2c0cc3f55514bd Mon Sep 17 00:00:00 2001 From: Azael Avalos Date: Fri, 31 Jul 2015 21:58:14 -0600 Subject: toshiba_acpi: Refactor *{get, set} functions return value This patch refactors the return value of the driver *{get, set} functions, since the driver default error value is -EIO. All the functions now check for TOS_FAILURE, TOS_NOT_SUPPORTED and TOS_SUCCESS. On TOS_FAILURE a pr_err message is printed informing the user of the error (no change was made to this, except the check was added to the functions not checking for this). On TOS_NOT_SUPPORTED we now return -ENODEV immediately (some functions were returning -EIO and some other were not checking) On TOS_SUCCESS* we now return 0 (as a side effect, a new success value was added, since some functions return one instead of zero to indicate success). As a special case, the LED functions now check for *FAILURE on *set, and check for TOS_FAILURE and TOS_SUCCESS on *get with their "default" return value set to LED_OFF. Also the {lcd, video}_proc* functions were adapted to reflect these changes to their parent HCI functions. Signed-off-by: Azael Avalos Signed-off-by: Darren Hart --- drivers/platform/x86/toshiba_acpi.c | 177 +++++++++++++++++++++--------------- 1 file changed, 104 insertions(+), 73 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index 66b596a7f710..65adb122189f 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -93,6 +93,7 @@ MODULE_LICENSE("GPL"); /* Return codes */ #define TOS_SUCCESS 0x0000 +#define TOS_SUCCESS2 0x0001 #define TOS_OPEN_CLOSE_OK 0x0044 #define TOS_FAILURE 0x1000 #define TOS_NOT_SUPPORTED 0x8000 @@ -469,7 +470,8 @@ static void toshiba_illumination_set(struct led_classdev *cdev, { struct toshiba_acpi_dev *dev = container_of(cdev, struct toshiba_acpi_dev, led_dev); - u32 state, result; + u32 result; + u32 state; /* First request : initialize communication. */ if (!sci_open(dev)) @@ -503,7 +505,7 @@ static enum led_brightness toshiba_illumination_get(struct led_classdev *cdev) if (result == TOS_FAILURE || result == TOS_INPUT_DATA_ERROR) { pr_err("ACPI call for illumination failed\n"); return LED_OFF; - } else if (result == TOS_NOT_SUPPORTED) { + } else if (result != TOS_SUCCESS) { return LED_OFF; } @@ -565,7 +567,7 @@ static int toshiba_kbd_illum_status_set(struct toshiba_acpi_dev *dev, u32 time) return -ENODEV; } - return 0; + return result == TOS_SUCCESS ? 0 : -EIO; } static int toshiba_kbd_illum_status_get(struct toshiba_acpi_dev *dev, u32 *time) @@ -584,21 +586,22 @@ static int toshiba_kbd_illum_status_get(struct toshiba_acpi_dev *dev, u32 *time) return -ENODEV; } - return 0; + return result == TOS_SUCCESS ? 0 : -EIO; } static enum led_brightness toshiba_kbd_backlight_get(struct led_classdev *cdev) { struct toshiba_acpi_dev *dev = container_of(cdev, struct toshiba_acpi_dev, kbd_led); - u32 state, result; + u32 result; + u32 state; /* Check the keyboard backlight state */ result = hci_read(dev, HCI_KBD_ILLUMINATION, &state); if (result == TOS_FAILURE || result == TOS_INPUT_DATA_ERROR) { pr_err("ACPI call to get the keyboard backlight failed\n"); return LED_OFF; - } else if (result == TOS_NOT_SUPPORTED) { + } else if (result != TOS_SUCCESS) { return LED_OFF; } @@ -610,7 +613,8 @@ static void toshiba_kbd_backlight_set(struct led_classdev *cdev, { struct toshiba_acpi_dev *dev = container_of(cdev, struct toshiba_acpi_dev, kbd_led); - u32 state, result; + u32 result; + u32 state; /* Set the keyboard backlight state */ state = brightness ? 1 : 0; @@ -640,7 +644,7 @@ static int toshiba_touchpad_set(struct toshiba_acpi_dev *dev, u32 state) return -ENODEV; } - return 0; + return result == TOS_SUCCESS ? 0 : -EIO; } static int toshiba_touchpad_get(struct toshiba_acpi_dev *dev, u32 *state) @@ -659,7 +663,7 @@ static int toshiba_touchpad_get(struct toshiba_acpi_dev *dev, u32 *state) return -ENODEV; } - return 0; + return result == TOS_SUCCESS ? 0 : -EIO; } /* Eco Mode support */ @@ -709,6 +713,8 @@ toshiba_eco_mode_get_status(struct led_classdev *cdev) if (ACPI_FAILURE(status) || out[0] == TOS_INPUT_DATA_ERROR) { pr_err("ACPI call to get ECO led failed\n"); return LED_OFF; + } else if (out[0] != TOS_SUCCESS) { + return LED_OFF; } return out[2] ? LED_FULL : LED_OFF; @@ -769,12 +775,15 @@ static int toshiba_accelerometer_get(struct toshiba_acpi_dev *dev, if (ACPI_FAILURE(status) || out[0] == TOS_INPUT_DATA_ERROR) { pr_err("ACPI call to query the accelerometer failed\n"); return -EIO; + } else if (out[0] == TOS_NOT_SUPPORTED) { + return -ENODEV; + } else if (out[0] == TOS_SUCCESS) { + *xy = out[2]; + *z = out[4]; + return 0; } - *xy = out[2]; - *z = out[4]; - - return 0; + return -EIO; } /* Sleep (Charge and Music) utilities support */ @@ -835,7 +844,7 @@ static int toshiba_usb_sleep_charge_get(struct toshiba_acpi_dev *dev, return -EIO; } - return 0; + return result == TOS_SUCCESS ? 0 : -EIO; } static int toshiba_usb_sleep_charge_set(struct toshiba_acpi_dev *dev, @@ -857,7 +866,7 @@ static int toshiba_usb_sleep_charge_set(struct toshiba_acpi_dev *dev, return -EIO; } - return 0; + return result == TOS_SUCCESS ? 0 : -EIO; } static int toshiba_sleep_functions_status_get(struct toshiba_acpi_dev *dev, @@ -880,11 +889,12 @@ static int toshiba_sleep_functions_status_get(struct toshiba_acpi_dev *dev, return -ENODEV; } else if (out[0] == TOS_INPUT_DATA_ERROR) { return -EIO; + } else if (out[0] == TOS_SUCCESS) { + *mode = out[2]; + return 0; } - *mode = out[2]; - - return 0; + return -EIO; } static int toshiba_sleep_functions_status_set(struct toshiba_acpi_dev *dev, @@ -910,7 +920,7 @@ static int toshiba_sleep_functions_status_set(struct toshiba_acpi_dev *dev, return -EIO; } - return 0; + return out[0] == TOS_SUCCESS ? 0 : -EIO; } static int toshiba_usb_rapid_charge_get(struct toshiba_acpi_dev *dev, @@ -932,11 +942,12 @@ static int toshiba_usb_rapid_charge_get(struct toshiba_acpi_dev *dev, } else if (out[0] == TOS_NOT_SUPPORTED || out[0] == TOS_INPUT_DATA_ERROR) { return -ENODEV; + } else if (out[0] == TOS_SUCCESS || out[0] == TOS_SUCCESS2) { + *state = out[2]; + return 0; } - *state = out[2]; - - return 0; + return -EIO; } static int toshiba_usb_rapid_charge_set(struct toshiba_acpi_dev *dev, @@ -962,7 +973,7 @@ static int toshiba_usb_rapid_charge_set(struct toshiba_acpi_dev *dev, return -EIO; } - return 0; + return (out[0] == TOS_SUCCESS || out[0] == TOS_SUCCESS2) ? 0 : -EIO; } static int toshiba_usb_sleep_music_get(struct toshiba_acpi_dev *dev, u32 *state) @@ -983,7 +994,7 @@ static int toshiba_usb_sleep_music_get(struct toshiba_acpi_dev *dev, u32 *state) return -EIO; } - return 0; + return result = TOS_SUCCESS ? 0 : -EIO; } static int toshiba_usb_sleep_music_set(struct toshiba_acpi_dev *dev, u32 state) @@ -1004,7 +1015,7 @@ static int toshiba_usb_sleep_music_set(struct toshiba_acpi_dev *dev, u32 state) return -EIO; } - return 0; + return result == TOS_SUCCESS ? 0 : -EIO; } /* Keyboard function keys */ @@ -1024,7 +1035,7 @@ static int toshiba_function_keys_get(struct toshiba_acpi_dev *dev, u32 *mode) return -ENODEV; } - return 0; + return (result == TOS_SUCCESS || result == TOS_SUCCESS2) ? 0 : -EIO; } static int toshiba_function_keys_set(struct toshiba_acpi_dev *dev, u32 mode) @@ -1043,7 +1054,7 @@ static int toshiba_function_keys_set(struct toshiba_acpi_dev *dev, u32 mode) return -ENODEV; } - return 0; + return (result == TOS_SUCCESS || result == TOS_SUCCESS2) ? 0 : -EIO; } /* Panel Power ON */ @@ -1065,7 +1076,7 @@ static int toshiba_panel_power_on_get(struct toshiba_acpi_dev *dev, u32 *state) return -EIO; } - return 0; + return result == TOS_SUCCESS ? 0 : -EIO; } static int toshiba_panel_power_on_set(struct toshiba_acpi_dev *dev, u32 state) @@ -1086,7 +1097,7 @@ static int toshiba_panel_power_on_set(struct toshiba_acpi_dev *dev, u32 state) return -EIO; } - return 0; + return result == TOS_SUCCESS ? 0 : -EIO; } /* USB Three */ @@ -1108,7 +1119,7 @@ static int toshiba_usb_three_get(struct toshiba_acpi_dev *dev, u32 *state) return -EIO; } - return 0; + return (result == TOS_SUCCESS || result == TOS_SUCCESS2) ? 0 : -EIO; } static int toshiba_usb_three_set(struct toshiba_acpi_dev *dev, u32 state) @@ -1129,7 +1140,7 @@ static int toshiba_usb_three_set(struct toshiba_acpi_dev *dev, u32 state) return -EIO; } - return 0; + return (result == TOS_SUCCESS || result == TOS_SUCCESS2) ? 0 : -EIO; } /* Hotkey Event type */ @@ -1146,26 +1157,37 @@ static int toshiba_hotkey_event_type_get(struct toshiba_acpi_dev *dev, return -EIO; } else if (out[0] == TOS_NOT_SUPPORTED) { return -ENODEV; + } else if (out[0] == TOS_SUCCESS) { + *type = out[3]; + return 0; } - *type = out[3]; - - return 0; + return -EIO; } /* Transflective Backlight */ static int get_tr_backlight_status(struct toshiba_acpi_dev *dev, u32 *status) { - u32 hci_result = hci_read(dev, HCI_TR_BACKLIGHT, status); + u32 result = hci_read(dev, HCI_TR_BACKLIGHT, status); + + if (result == TOS_FAILURE) + pr_err("ACPI call to get Transflective Backlight failed\n"); + else if (result == TOS_NOT_SUPPORTED) + return -ENODEV; - return hci_result == TOS_SUCCESS ? 0 : -EIO; + return result == TOS_SUCCESS ? 0 : -EIO; } static int set_tr_backlight_status(struct toshiba_acpi_dev *dev, u32 status) { - u32 hci_result = hci_write(dev, HCI_TR_BACKLIGHT, !status); + u32 result = hci_write(dev, HCI_TR_BACKLIGHT, !status); + + if (result == TOS_FAILURE) + pr_err("ACPI call to set Transflective Backlight failed\n"); + else if (result == TOS_NOT_SUPPORTED) + return -ENODEV; - return hci_result == TOS_SUCCESS ? 0 : -EIO; + return result == TOS_SUCCESS ? 0 : -EIO; } static struct proc_dir_entry *toshiba_proc_dir; @@ -1173,7 +1195,7 @@ static struct proc_dir_entry *toshiba_proc_dir; /* LCD Brightness */ static int __get_lcd_brightness(struct toshiba_acpi_dev *dev) { - u32 hci_result; + u32 result; u32 value; int brightness = 0; @@ -1187,8 +1209,12 @@ static int __get_lcd_brightness(struct toshiba_acpi_dev *dev) brightness++; } - hci_result = hci_read(dev, HCI_LCD_BRIGHTNESS, &value); - if (hci_result == TOS_SUCCESS) + result = hci_read(dev, HCI_LCD_BRIGHTNESS, &value); + if (result == TOS_FAILURE) + pr_err("ACPI call to get LCD Brightness failed\n"); + else if (result == TOS_NOT_SUPPORTED) + return -ENODEV; + if (result == TOS_SUCCESS) return brightness + (value >> HCI_LCD_BRIGHTNESS_SHIFT); return -EIO; @@ -1204,8 +1230,8 @@ static int get_lcd_brightness(struct backlight_device *bd) static int lcd_proc_show(struct seq_file *m, void *v) { struct toshiba_acpi_dev *dev = m->private; - int value; int levels; + int value; if (!dev->backlight_dev) return -ENODEV; @@ -1219,6 +1245,7 @@ static int lcd_proc_show(struct seq_file *m, void *v) } pr_err("Error reading LCD brightness\n"); + return -EIO; } @@ -1229,7 +1256,7 @@ static int lcd_proc_open(struct inode *inode, struct file *file) static int set_lcd_brightness(struct toshiba_acpi_dev *dev, int value) { - u32 hci_result; + u32 result; if (dev->tr_backlight_supported) { int ret = set_tr_backlight_status(dev, !value); @@ -1241,8 +1268,13 @@ static int set_lcd_brightness(struct toshiba_acpi_dev *dev, int value) } value = value << HCI_LCD_BRIGHTNESS_SHIFT; - hci_result = hci_write(dev, HCI_LCD_BRIGHTNESS, value); - return hci_result == TOS_SUCCESS ? 0 : -EIO; + result = hci_write(dev, HCI_LCD_BRIGHTNESS, value); + if (result == TOS_FAILURE) + pr_err("ACPI call to set LCD Brightness failed\n"); + else if (result == TOS_NOT_SUPPORTED) + return -ENODEV; + + return result == TOS_SUCCESS ? 0 : -EIO; } static int set_lcd_status(struct backlight_device *bd) @@ -1258,24 +1290,22 @@ static ssize_t lcd_proc_write(struct file *file, const char __user *buf, struct toshiba_acpi_dev *dev = PDE_DATA(file_inode(file)); char cmd[42]; size_t len; - int value; - int ret; int levels = dev->backlight_dev->props.max_brightness + 1; + int value; len = min(count, sizeof(cmd) - 1); if (copy_from_user(cmd, buf, len)) return -EFAULT; cmd[len] = '\0'; - if (sscanf(cmd, " brightness : %i", &value) == 1 && - value >= 0 && value < levels) { - ret = set_lcd_brightness(dev, value); - if (ret == 0) - ret = count; - } else { - ret = -EINVAL; - } - return ret; + if (sscanf(cmd, " brightness : %i", &value) != 1 && + value < 0 && value > levels) + return -EINVAL; + + if (set_lcd_brightness(dev, value)) + return -EIO; + + return count; } static const struct file_operations lcd_proc_fops = { @@ -1287,22 +1317,25 @@ static const struct file_operations lcd_proc_fops = { .write = lcd_proc_write, }; +/* Video-Out */ static int get_video_status(struct toshiba_acpi_dev *dev, u32 *status) { - u32 hci_result; + u32 result = hci_read(dev, HCI_VIDEO_OUT, status); + + if (result == TOS_FAILURE) + pr_err("ACPI call to get Video-Out failed\n"); + else if (result == TOS_NOT_SUPPORTED) + return -ENODEV; - hci_result = hci_read(dev, HCI_VIDEO_OUT, status); - return hci_result == TOS_SUCCESS ? 0 : -EIO; + return result == TOS_SUCCESS ? 0 : -EIO; } static int video_proc_show(struct seq_file *m, void *v) { struct toshiba_acpi_dev *dev = m->private; u32 value; - int ret; - ret = get_video_status(dev, &value); - if (!ret) { + if (!get_video_status(dev, &value)) { int is_lcd = (value & HCI_VIDEO_OUT_LCD) ? 1 : 0; int is_crt = (value & HCI_VIDEO_OUT_CRT) ? 1 : 0; int is_tv = (value & HCI_VIDEO_OUT_TV) ? 1 : 0; @@ -1310,9 +1343,10 @@ static int video_proc_show(struct seq_file *m, void *v) seq_printf(m, "lcd_out: %d\n", is_lcd); seq_printf(m, "crt_out: %d\n", is_crt); seq_printf(m, "tv_out: %d\n", is_tv); + return 0; } - return ret; + return -EIO; } static int video_proc_open(struct inode *inode, struct file *file) @@ -1324,13 +1358,14 @@ static ssize_t video_proc_write(struct file *file, const char __user *buf, size_t count, loff_t *pos) { struct toshiba_acpi_dev *dev = PDE_DATA(file_inode(file)); - char *cmd, *buffer; - int ret; - int value; + char *buffer; + char *cmd; int remain = count; int lcd_out = -1; int crt_out = -1; int tv_out = -1; + int value; + int ret; u32 video_out; cmd = kmalloc(count + 1, GFP_KERNEL); @@ -1382,7 +1417,7 @@ static ssize_t video_proc_write(struct file *file, const char __user *buf, ret = write_acpi_int(METHOD_VIDEO_OUT, new_video_out); } - return ret ? ret : count; + return ret ? -EIO : count; } static const struct file_operations video_proc_fops = { @@ -1403,10 +1438,8 @@ static int get_fan_status(struct toshiba_acpi_dev *dev, u32 *status) pr_err("ACPI call to get Fan status failed\n"); else if (result == TOS_NOT_SUPPORTED) return -ENODEV; - else if (result == TOS_SUCCESS) - return 0; - return -EIO; + return result == TOS_SUCCESS ? 0 : -EIO; } static int set_fan_status(struct toshiba_acpi_dev *dev, u32 status) @@ -1417,10 +1450,8 @@ static int set_fan_status(struct toshiba_acpi_dev *dev, u32 status) pr_err("ACPI call to set Fan status failed\n"); else if (result == TOS_NOT_SUPPORTED) return -ENODEV; - else if (result == TOS_SUCCESS) - return 0; - return -EIO; + return result == TOS_SUCCESS ? 0 : -EIO; } static int fan_proc_show(struct seq_file *m, void *v) -- cgit v1.2.3 From a6b5354f422a1f1cd48a94ed64e54989f9ea7ee2 Mon Sep 17 00:00:00 2001 From: Azael Avalos Date: Fri, 31 Jul 2015 21:58:15 -0600 Subject: toshiba_acpi: Remove unnecessary checks and returns in HCI/SCI functions A previous patch added explicit feature checks for support, *SUCCESS* and *FAILURE to the HCI/SCI *{get, set} functions. This patch removes some unnedded checks to the driver HCI/SCI functions given that the default error return value is now set to -EIO, there is no need to check for other error values other than the ones currently checking for. Signed-off-by: Azael Avalos Signed-off-by: Darren Hart --- drivers/platform/x86/toshiba_acpi.c | 169 ++++++++++-------------------------- 1 file changed, 44 insertions(+), 125 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index 65adb122189f..c18469903eee 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -459,8 +459,6 @@ static void toshiba_illumination_available(struct toshiba_acpi_dev *dev) sci_close(dev); if (ACPI_FAILURE(status)) pr_err("ACPI call to query Illumination support failed\n"); - else if (out[0] == TOS_NOT_SUPPORTED) - return; else if (out[0] == TOS_SUCCESS) dev->illumination_supported = 1; } @@ -481,12 +479,8 @@ static void toshiba_illumination_set(struct led_classdev *cdev, state = brightness ? 1 : 0; result = sci_write(dev, SCI_ILLUMINATION, state); sci_close(dev); - if (result == TOS_FAILURE) { + if (result == TOS_FAILURE) pr_err("ACPI call for illumination failed\n"); - return; - } else if (result == TOS_NOT_SUPPORTED) { - return; - } } static enum led_brightness toshiba_illumination_get(struct led_classdev *cdev) @@ -502,7 +496,7 @@ static enum led_brightness toshiba_illumination_get(struct led_classdev *cdev) /* Check the illumination */ result = sci_read(dev, SCI_ILLUMINATION, &state); sci_close(dev); - if (result == TOS_FAILURE || result == TOS_INPUT_DATA_ERROR) { + if (result == TOS_FAILURE) { pr_err("ACPI call for illumination failed\n"); return LED_OFF; } else if (result != TOS_SUCCESS) { @@ -527,10 +521,8 @@ static void toshiba_kbd_illum_available(struct toshiba_acpi_dev *dev) status = tci_raw(dev, in, out); sci_close(dev); - if (ACPI_FAILURE(status) || out[0] == TOS_INPUT_DATA_ERROR) { + if (ACPI_FAILURE(status)) { pr_err("ACPI call to query kbd illumination support failed\n"); - } else if (out[0] == TOS_NOT_SUPPORTED) { - return; } else if (out[0] == TOS_SUCCESS) { /* * Check for keyboard backlight timeout max value, @@ -560,12 +552,10 @@ static int toshiba_kbd_illum_status_set(struct toshiba_acpi_dev *dev, u32 time) result = sci_write(dev, SCI_KBD_ILLUM_STATUS, time); sci_close(dev); - if (result == TOS_FAILURE || result == TOS_INPUT_DATA_ERROR) { + if (result == TOS_FAILURE) pr_err("ACPI call to set KBD backlight status failed\n"); - return -EIO; - } else if (result == TOS_NOT_SUPPORTED) { + else if (result == TOS_NOT_SUPPORTED) return -ENODEV; - } return result == TOS_SUCCESS ? 0 : -EIO; } @@ -579,12 +569,10 @@ static int toshiba_kbd_illum_status_get(struct toshiba_acpi_dev *dev, u32 *time) result = sci_read(dev, SCI_KBD_ILLUM_STATUS, time); sci_close(dev); - if (result == TOS_FAILURE || result == TOS_INPUT_DATA_ERROR) { + if (result == TOS_FAILURE) pr_err("ACPI call to get KBD backlight status failed\n"); - return -EIO; - } else if (result == TOS_NOT_SUPPORTED) { + else if (result == TOS_NOT_SUPPORTED) return -ENODEV; - } return result == TOS_SUCCESS ? 0 : -EIO; } @@ -598,7 +586,7 @@ static enum led_brightness toshiba_kbd_backlight_get(struct led_classdev *cdev) /* Check the keyboard backlight state */ result = hci_read(dev, HCI_KBD_ILLUMINATION, &state); - if (result == TOS_FAILURE || result == TOS_INPUT_DATA_ERROR) { + if (result == TOS_FAILURE) { pr_err("ACPI call to get the keyboard backlight failed\n"); return LED_OFF; } else if (result != TOS_SUCCESS) { @@ -619,12 +607,8 @@ static void toshiba_kbd_backlight_set(struct led_classdev *cdev, /* Set the keyboard backlight state */ state = brightness ? 1 : 0; result = hci_write(dev, HCI_KBD_ILLUMINATION, state); - if (result == TOS_FAILURE || result == TOS_INPUT_DATA_ERROR) { + if (result == TOS_FAILURE) pr_err("ACPI call to set KBD Illumination mode failed\n"); - return; - } else if (result == TOS_NOT_SUPPORTED) { - return; - } } /* TouchPad support */ @@ -637,12 +621,10 @@ static int toshiba_touchpad_set(struct toshiba_acpi_dev *dev, u32 state) result = sci_write(dev, SCI_TOUCHPAD, state); sci_close(dev); - if (result == TOS_FAILURE) { + if (result == TOS_FAILURE) pr_err("ACPI call to set the touchpad failed\n"); - return -EIO; - } else if (result == TOS_NOT_SUPPORTED) { + else if (result == TOS_NOT_SUPPORTED) return -ENODEV; - } return result == TOS_SUCCESS ? 0 : -EIO; } @@ -656,12 +638,10 @@ static int toshiba_touchpad_get(struct toshiba_acpi_dev *dev, u32 *state) result = sci_read(dev, SCI_TOUCHPAD, state); sci_close(dev); - if (result == TOS_FAILURE) { + if (result == TOS_FAILURE) pr_err("ACPI call to query the touchpad failed\n"); - return -EIO; - } else if (result == TOS_NOT_SUPPORTED) { + else if (result == TOS_NOT_SUPPORTED) return -ENODEV; - } return result == TOS_SUCCESS ? 0 : -EIO; } @@ -679,8 +659,6 @@ static void toshiba_eco_mode_available(struct toshiba_acpi_dev *dev) status = tci_raw(dev, in, out); if (ACPI_FAILURE(status)) { pr_err("ACPI call to get ECO led failed\n"); - } else if (out[0] == TOS_NOT_INSTALLED) { - pr_info("ECO led not installed"); } else if (out[0] == TOS_INPUT_DATA_ERROR) { /* * If we receive 0x8300 (Input Data Error), it means that the @@ -693,7 +671,7 @@ static void toshiba_eco_mode_available(struct toshiba_acpi_dev *dev) */ in[3] = 1; status = tci_raw(dev, in, out); - if (ACPI_FAILURE(status) || out[0] == TOS_FAILURE) + if (ACPI_FAILURE(status)) pr_err("ACPI call to get ECO led failed\n"); else if (out[0] == TOS_SUCCESS) dev->eco_supported = 1; @@ -710,7 +688,7 @@ toshiba_eco_mode_get_status(struct led_classdev *cdev) acpi_status status; status = tci_raw(dev, in, out); - if (ACPI_FAILURE(status) || out[0] == TOS_INPUT_DATA_ERROR) { + if (ACPI_FAILURE(status)) { pr_err("ACPI call to get ECO led failed\n"); return LED_OFF; } else if (out[0] != TOS_SUCCESS) { @@ -732,10 +710,8 @@ static void toshiba_eco_mode_set_status(struct led_classdev *cdev, /* Switch the Eco Mode led on/off */ in[2] = (brightness) ? 1 : 0; status = tci_raw(dev, in, out); - if (ACPI_FAILURE(status) || out[0] == TOS_INPUT_DATA_ERROR) { + if (ACPI_FAILURE(status)) pr_err("ACPI call to set ECO led failed\n"); - return; - } } /* Accelerometer support */ @@ -752,19 +728,14 @@ static void toshiba_accelerometer_available(struct toshiba_acpi_dev *dev) * this call also serves as initialization */ status = tci_raw(dev, in, out); - if (ACPI_FAILURE(status) || out[0] == TOS_INPUT_DATA_ERROR) + if (ACPI_FAILURE(status)) pr_err("ACPI call to query the accelerometer failed\n"); - else if (out[0] == TOS_DATA_NOT_AVAILABLE || - out[0] == TOS_NOT_INITIALIZED) - pr_err("Accelerometer not initialized\n"); - else if (out[0] == TOS_NOT_SUPPORTED) - return; else if (out[0] == TOS_SUCCESS) dev->accelerometer_supported = 1; } static int toshiba_accelerometer_get(struct toshiba_acpi_dev *dev, - u32 *xy, u32 *z) + u32 *xy, u32 *z) { u32 in[TCI_WORDS] = { HCI_GET, HCI_ACCELEROMETER, 0, 1, 0, 0 }; u32 out[TCI_WORDS]; @@ -772,7 +743,7 @@ static int toshiba_accelerometer_get(struct toshiba_acpi_dev *dev, /* Check the Accelerometer status */ status = tci_raw(dev, in, out); - if (ACPI_FAILURE(status) || out[0] == TOS_INPUT_DATA_ERROR) { + if (ACPI_FAILURE(status)) { pr_err("ACPI call to query the accelerometer failed\n"); return -EIO; } else if (out[0] == TOS_NOT_SUPPORTED) { @@ -815,8 +786,6 @@ static void toshiba_usb_sleep_charge_available(struct toshiba_acpi_dev *dev) sci_close(dev); if (ACPI_FAILURE(status)) { pr_err("ACPI call to get USB Sleep and Charge mode failed\n"); - } else if (out[0] == TOS_NOT_SUPPORTED) { - return; } else if (out[0] == TOS_SUCCESS) { dev->usbsc_bat_level = out[2]; /* Flag as supported */ @@ -835,14 +804,10 @@ static int toshiba_usb_sleep_charge_get(struct toshiba_acpi_dev *dev, result = sci_read(dev, SCI_USB_SLEEP_CHARGE, mode); sci_close(dev); - if (result == TOS_FAILURE) { + if (result == TOS_FAILURE) pr_err("ACPI call to set USB S&C mode failed\n"); - return -EIO; - } else if (result == TOS_NOT_SUPPORTED) { + else if (result == TOS_NOT_SUPPORTED) return -ENODEV; - } else if (result == TOS_INPUT_DATA_ERROR) { - return -EIO; - } return result == TOS_SUCCESS ? 0 : -EIO; } @@ -857,14 +822,10 @@ static int toshiba_usb_sleep_charge_set(struct toshiba_acpi_dev *dev, result = sci_write(dev, SCI_USB_SLEEP_CHARGE, mode); sci_close(dev); - if (result == TOS_FAILURE) { + if (result == TOS_FAILURE) pr_err("ACPI call to set USB S&C mode failed\n"); - return -EIO; - } else if (result == TOS_NOT_SUPPORTED) { + else if (result == TOS_NOT_SUPPORTED) return -ENODEV; - } else if (result == TOS_INPUT_DATA_ERROR) { - return -EIO; - } return result == TOS_SUCCESS ? 0 : -EIO; } @@ -884,11 +845,8 @@ static int toshiba_sleep_functions_status_get(struct toshiba_acpi_dev *dev, sci_close(dev); if (ACPI_FAILURE(status)) { pr_err("ACPI call to get USB S&C battery level failed\n"); - return -EIO; } else if (out[0] == TOS_NOT_SUPPORTED) { return -ENODEV; - } else if (out[0] == TOS_INPUT_DATA_ERROR) { - return -EIO; } else if (out[0] == TOS_SUCCESS) { *mode = out[2]; return 0; @@ -911,14 +869,10 @@ static int toshiba_sleep_functions_status_set(struct toshiba_acpi_dev *dev, in[5] = SCI_USB_CHARGE_BAT_LVL; status = tci_raw(dev, in, out); sci_close(dev); - if (ACPI_FAILURE(status)) { + if (ACPI_FAILURE(status)) pr_err("ACPI call to set USB S&C battery level failed\n"); - return -EIO; - } else if (out[0] == TOS_NOT_SUPPORTED) { + else if (out[0] == TOS_NOT_SUPPORTED) return -ENODEV; - } else if (out[0] == TOS_INPUT_DATA_ERROR) { - return -EIO; - } return out[0] == TOS_SUCCESS ? 0 : -EIO; } @@ -938,9 +892,7 @@ static int toshiba_usb_rapid_charge_get(struct toshiba_acpi_dev *dev, sci_close(dev); if (ACPI_FAILURE(status)) { pr_err("ACPI call to get USB Rapid Charge failed\n"); - return -EIO; - } else if (out[0] == TOS_NOT_SUPPORTED || - out[0] == TOS_INPUT_DATA_ERROR) { + } else if (out[0] == TOS_NOT_SUPPORTED) { return -ENODEV; } else if (out[0] == TOS_SUCCESS || out[0] == TOS_SUCCESS2) { *state = out[2]; @@ -964,14 +916,10 @@ static int toshiba_usb_rapid_charge_set(struct toshiba_acpi_dev *dev, in[5] = SCI_USB_CHARGE_RAPID_DSP; status = tci_raw(dev, in, out); sci_close(dev); - if (ACPI_FAILURE(status)) { + if (ACPI_FAILURE(status)) pr_err("ACPI call to set USB Rapid Charge failed\n"); - return -EIO; - } else if (out[0] == TOS_NOT_SUPPORTED) { + else if (out[0] == TOS_NOT_SUPPORTED) return -ENODEV; - } else if (out[0] == TOS_INPUT_DATA_ERROR) { - return -EIO; - } return (out[0] == TOS_SUCCESS || out[0] == TOS_SUCCESS2) ? 0 : -EIO; } @@ -985,14 +933,10 @@ static int toshiba_usb_sleep_music_get(struct toshiba_acpi_dev *dev, u32 *state) result = sci_read(dev, SCI_USB_SLEEP_MUSIC, state); sci_close(dev); - if (result == TOS_FAILURE) { + if (result == TOS_FAILURE) pr_err("ACPI call to get Sleep and Music failed\n"); - return -EIO; - } else if (result == TOS_NOT_SUPPORTED) { + else if (result == TOS_NOT_SUPPORTED) return -ENODEV; - } else if (result == TOS_INPUT_DATA_ERROR) { - return -EIO; - } return result = TOS_SUCCESS ? 0 : -EIO; } @@ -1006,14 +950,10 @@ static int toshiba_usb_sleep_music_set(struct toshiba_acpi_dev *dev, u32 state) result = sci_write(dev, SCI_USB_SLEEP_MUSIC, state); sci_close(dev); - if (result == TOS_FAILURE) { + if (result == TOS_FAILURE) pr_err("ACPI call to set Sleep and Music failed\n"); - return -EIO; - } else if (result == TOS_NOT_SUPPORTED) { + else if (result == TOS_NOT_SUPPORTED) return -ENODEV; - } else if (result == TOS_INPUT_DATA_ERROR) { - return -EIO; - } return result == TOS_SUCCESS ? 0 : -EIO; } @@ -1028,12 +968,10 @@ static int toshiba_function_keys_get(struct toshiba_acpi_dev *dev, u32 *mode) result = sci_read(dev, SCI_KBD_FUNCTION_KEYS, mode); sci_close(dev); - if (result == TOS_FAILURE || result == TOS_INPUT_DATA_ERROR) { + if (result == TOS_FAILURE) pr_err("ACPI call to get KBD function keys failed\n"); - return -EIO; - } else if (result == TOS_NOT_SUPPORTED) { + else if (result == TOS_NOT_SUPPORTED) return -ENODEV; - } return (result == TOS_SUCCESS || result == TOS_SUCCESS2) ? 0 : -EIO; } @@ -1047,12 +985,10 @@ static int toshiba_function_keys_set(struct toshiba_acpi_dev *dev, u32 mode) result = sci_write(dev, SCI_KBD_FUNCTION_KEYS, mode); sci_close(dev); - if (result == TOS_FAILURE || result == TOS_INPUT_DATA_ERROR) { + if (result == TOS_FAILURE) pr_err("ACPI call to set KBD function keys failed\n"); - return -EIO; - } else if (result == TOS_NOT_SUPPORTED) { + else if (result == TOS_NOT_SUPPORTED) return -ENODEV; - } return (result == TOS_SUCCESS || result == TOS_SUCCESS2) ? 0 : -EIO; } @@ -1067,14 +1003,10 @@ static int toshiba_panel_power_on_get(struct toshiba_acpi_dev *dev, u32 *state) result = sci_read(dev, SCI_PANEL_POWER_ON, state); sci_close(dev); - if (result == TOS_FAILURE) { + if (result == TOS_FAILURE) pr_err("ACPI call to get Panel Power ON failed\n"); - return -EIO; - } else if (result == TOS_NOT_SUPPORTED) { + else if (result == TOS_NOT_SUPPORTED) return -ENODEV; - } else if (result == TOS_INPUT_DATA_ERROR) { - return -EIO; - } return result == TOS_SUCCESS ? 0 : -EIO; } @@ -1088,14 +1020,10 @@ static int toshiba_panel_power_on_set(struct toshiba_acpi_dev *dev, u32 state) result = sci_write(dev, SCI_PANEL_POWER_ON, state); sci_close(dev); - if (result == TOS_FAILURE) { + if (result == TOS_FAILURE) pr_err("ACPI call to set Panel Power ON failed\n"); - return -EIO; - } else if (result == TOS_NOT_SUPPORTED) { + else if (result == TOS_NOT_SUPPORTED) return -ENODEV; - } else if (result == TOS_INPUT_DATA_ERROR) { - return -EIO; - } return result == TOS_SUCCESS ? 0 : -EIO; } @@ -1110,14 +1038,10 @@ static int toshiba_usb_three_get(struct toshiba_acpi_dev *dev, u32 *state) result = sci_read(dev, SCI_USB_THREE, state); sci_close(dev); - if (result == TOS_FAILURE) { + if (result == TOS_FAILURE) pr_err("ACPI call to get USB 3 failed\n"); - return -EIO; - } else if (result == TOS_NOT_SUPPORTED) { + else if (result == TOS_NOT_SUPPORTED) return -ENODEV; - } else if (result == TOS_INPUT_DATA_ERROR) { - return -EIO; - } return (result == TOS_SUCCESS || result == TOS_SUCCESS2) ? 0 : -EIO; } @@ -1131,14 +1055,10 @@ static int toshiba_usb_three_set(struct toshiba_acpi_dev *dev, u32 state) result = sci_write(dev, SCI_USB_THREE, state); sci_close(dev); - if (result == TOS_FAILURE) { + if (result == TOS_FAILURE) pr_err("ACPI call to set USB 3 failed\n"); - return -EIO; - } else if (result == TOS_NOT_SUPPORTED) { + else if (result == TOS_NOT_SUPPORTED) return -ENODEV; - } else if (result == TOS_INPUT_DATA_ERROR) { - return -EIO; - } return (result == TOS_SUCCESS || result == TOS_SUCCESS2) ? 0 : -EIO; } @@ -1154,7 +1074,6 @@ static int toshiba_hotkey_event_type_get(struct toshiba_acpi_dev *dev, status = tci_raw(dev, in, out); if (ACPI_FAILURE(status)) { pr_err("ACPI call to get System type failed\n"); - return -EIO; } else if (out[0] == TOS_NOT_SUPPORTED) { return -ENODEV; } else if (out[0] == TOS_SUCCESS) { -- cgit v1.2.3 From 495078f892eef0ac791fd2b32393e1501b5c1c5e Mon Sep 17 00:00:00 2001 From: Azael Avalos Date: Fri, 31 Jul 2015 21:58:16 -0600 Subject: toshiba_acpi: Bump driver version to 0.23 Given that some features were added (/dev/toshiba_acpi device), some clean-ups and minor (cosmetic) changes all over the driver code, bump the driver version to 0.23 to reflect these overall changes. Signed-off-by: Azael Avalos Signed-off-by: Darren Hart --- drivers/platform/x86/toshiba_acpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index c18469903eee..6740c513919c 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -31,7 +31,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#define TOSHIBA_ACPI_VERSION "0.22" +#define TOSHIBA_ACPI_VERSION "0.23" #define PROC_INTERFACE_VERSION 1 #include -- cgit v1.2.3 From fa92a31b3335478c545cdc8e79e1e9b788184e6b Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 10 Aug 2015 10:45:45 +0200 Subject: ideapad-laptop: Add Lenovo Yoga 3 14 to no_hw_rfkill dmi list Like some of the other Yoga models the Lenovo Yoga 3 14 does not have a hw rfkill switch, and trying to read the hw rfkill switch through the ideapad module causes it to always reported blocking breaking wifi. This commit adds the Lenovo Yoga 3 14 to the no_hw_rfkill dmi list, fixing the wifi breakage. BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=1239050 Cc: stable@vger.kernel.org Signed-off-by: Hans de Goede Signed-off-by: Darren Hart --- drivers/platform/x86/ideapad-laptop.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index 76b57388d01b..81c3e582309a 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c @@ -852,6 +852,13 @@ static const struct dmi_system_id no_hw_rfkill_list[] = { DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 2"), }, }, + { + .ident = "Lenovo Yoga 3 14", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 3 14"), + }, + }, { .ident = "Lenovo Yoga 3 Pro 1370", .matches = { -- cgit v1.2.3 From 97ade7697bb104523417d0f9b5e38a8bf55ed7f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Stelmach?= Date: Wed, 29 Jul 2015 21:31:23 +0200 Subject: asus-laptop: Add key found on Asus F3M MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Asus F3M has two keys labeled with an icon of a touchpad. The first, reported as 0x6B is next to the power key and the second, reported as 0x6A, is F9 combined with Fn button. When I was pressing the latter, I was getting "Unknown key 6a pressed" message before applying this patch. Asus F3M does not support WMI so the commit does not update key mappings in the asus-nb-wmi.c file. I have not tested this mapping on any other Asus laptop. Signed-off-by: Łukasz Stelmach Signed-off-by: Darren Hart --- drivers/platform/x86/asus-laptop.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index 58d29c4f2840..f2b5d0a8adf0 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -332,6 +332,7 @@ static const struct key_entry asus_keymap[] = { {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, 0x6A, { KEY_TOUCHPAD_TOGGLE } }, /* Lock Touchpad Fn + F9 */ {KE_KEY, 0x6B, { KEY_TOUCHPAD_TOGGLE } }, /* Lock Touchpad */ {KE_KEY, 0x6C, { KEY_SLEEP } }, /* Suspend */ {KE_KEY, 0x6D, { KEY_SLEEP } }, /* Hibernate */ -- cgit v1.2.3 From 6d212b8adce4ddaa20229f781cc86bccb396a9fe Mon Sep 17 00:00:00 2001 From: Sebastian Krzyszkowiak Date: Sun, 19 Jul 2015 01:10:21 +0200 Subject: ideapad-laptop: add alternative representation for Yoga 2 to DMI table There is at least one (mine) Yoga 2 Pro in existence that has incorrect product version stored in DMI (reading as "INVALID"), causing it to not be recognized as Yoga 2 by ideapad-laptop module, which in turn causes non-existent hardware rfkills to be always reported as blocked. This change adds a second check by board name, which is "Yoga2". Looks like it also happens to be "INVALID" on some other Yoga 2 machines where product version is correct instead, so the original check is left intact to catch both cases. Signed-off-by: Sebastian Krzyszkowiak Signed-off-by: Darren Hart --- drivers/platform/x86/ideapad-laptop.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index 81c3e582309a..fce49f3c6ed6 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c @@ -859,6 +859,13 @@ static const struct dmi_system_id no_hw_rfkill_list[] = { DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 3 14"), }, }, + { + .ident = "Lenovo Yoga 2 11 / 13 / Pro", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_BOARD_NAME, "Yoga2"), + }, + }, { .ident = "Lenovo Yoga 3 Pro 1370", .matches = { -- cgit v1.2.3 From fc0bfacd045a17e385b4272dfe2387ba3a6d8745 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Giedrius=20Statkevi=C4=8Dius?= Date: Sun, 23 Aug 2015 14:41:09 +0300 Subject: hp-wireless: remove unneeded goto/label in hpwl_init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit acpi_bus_register_driver() already returns an appropriate value (0 on success, and some negative value on error) to be used in __init functions so the goto/label is redundant in hpwl_init thus remove it and directly return the value Signed-off-by: Giedrius Statkevičius Signed-off-by: Darren Hart --- drivers/platform/x86/hp-wireless.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/hp-wireless.c b/drivers/platform/x86/hp-wireless.c index 4e4cc8bd7557..988eedbd7c63 100644 --- a/drivers/platform/x86/hp-wireless.c +++ b/drivers/platform/x86/hp-wireless.c @@ -114,14 +114,9 @@ static int __init hpwl_init(void) pr_info("Initializing HPQ6001 module\n"); err = acpi_bus_register_driver(&hpwl_driver); - if (err) { + if (err) pr_err("Unable to register HP wireless control driver.\n"); - goto error_acpi_register; - } - - return 0; -error_acpi_register: return err; } -- cgit v1.2.3 From 2508a45a924dfa4a5f6e60675aa4732d888134a7 Mon Sep 17 00:00:00 2001 From: Chen Yu Date: Tue, 18 Aug 2015 23:30:25 +0800 Subject: surface pro 3: Add support driver for Surface Pro 3 buttons Since Surface Pro 3 does not follow the specs of "Windows ACPI Design Guide for SoC Platform", code in drivers/input/misc/soc_array.c can not detect these buttons on it. According to bios implementation, Surface Pro 3 encapsulates these buttons in a device named "VGBI", with _HID "MSHW0028". When any of the buttons is pressed, a specify ACPI notification code for this button will be delivered to "VGBI". For example, if power button is pressed down, ACPI notification code of 0xc6 will be sent by Notify(VGBI, 0xc6). This patch leverages "VGBI" to distinguish different ACPI notification code from Power button, Home button, Volume button, then dispatches these code to input layer. Lid is already covered by acpi button driver, so there's no need to rewrite. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=84651 Tested-by: Ethan Schoonover Tested-by: Peter Amidon Tested-by: Donavan Lance Tested-by: Stephen Just Signed-off-by: Chen Yu [dvhart@linux.intel.com: Formatting corrections in MAINTAINERS and Intel (c)] Signed-off-by: Darren Hart --- drivers/platform/x86/Kconfig | 5 + drivers/platform/x86/Makefile | 1 + drivers/platform/x86/surfacepro3_button.c | 216 ++++++++++++++++++++++++++++++ 3 files changed, 222 insertions(+) create mode 100644 drivers/platform/x86/surfacepro3_button.c (limited to 'drivers/platform') diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 6dc13e4de396..c69bb703f483 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -919,4 +919,9 @@ config INTEL_PMC_IPC The PMC is an ARC processor which defines IPC commands for communication with other entities in the CPU. +config SURFACE_PRO3_BUTTON + tristate "Power/home/volume buttons driver for Microsoft Surface Pro 3 tablet" + depends on ACPI && INPUT + ---help--- + This driver handles the power/home/volume buttons on the Microsoft Surface Pro 3 tablet. endif # X86_PLATFORM_DEVICES diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index dda95a985321..ada512819028 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile @@ -60,3 +60,4 @@ obj-$(CONFIG_INTEL_SMARTCONNECT) += intel-smartconnect.o obj-$(CONFIG_PVPANIC) += pvpanic.o obj-$(CONFIG_ALIENWARE_WMI) += alienware-wmi.o obj-$(CONFIG_INTEL_PMC_IPC) += intel_pmc_ipc.o +obj-$(CONFIG_SURFACE_PRO3_BUTTON) += surfacepro3_button.o diff --git a/drivers/platform/x86/surfacepro3_button.c b/drivers/platform/x86/surfacepro3_button.c new file mode 100644 index 000000000000..f7dade3fd2ab --- /dev/null +++ b/drivers/platform/x86/surfacepro3_button.c @@ -0,0 +1,216 @@ +/* + * power/home/volume button support for + * Microsoft Surface Pro 3 tablet. + * + * Copyright (c) 2015 Intel Corporation. + * All rights reserved. + * + * 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; version 2 + * of the License. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define SURFACE_BUTTON_HID "MSHW0028" +#define SURFACE_BUTTON_OBJ_NAME "VGBI" +#define SURFACE_BUTTON_DEVICE_NAME "Surface Pro 3 Buttons" + +#define SURFACE_BUTTON_NOTIFY_PRESS_POWER 0xc6 +#define SURFACE_BUTTON_NOTIFY_RELEASE_POWER 0xc7 + +#define SURFACE_BUTTON_NOTIFY_PRESS_HOME 0xc4 +#define SURFACE_BUTTON_NOTIFY_RELEASE_HOME 0xc5 + +#define SURFACE_BUTTON_NOTIFY_PRESS_VOLUME_UP 0xc0 +#define SURFACE_BUTTON_NOTIFY_RELEASE_VOLUME_UP 0xc1 + +#define SURFACE_BUTTON_NOTIFY_PRESS_VOLUME_DOWN 0xc2 +#define SURFACE_BUTTON_NOTIFY_RELEASE_VOLUME_DOWN 0xc3 + +ACPI_MODULE_NAME("surface pro 3 button"); + +MODULE_AUTHOR("Chen Yu"); +MODULE_DESCRIPTION("Surface Pro3 Button Driver"); +MODULE_LICENSE("GPL v2"); + +/* + * Power button, Home button, Volume buttons support is supposed to + * be covered by drivers/input/misc/soc_button_array.c, which is implemented + * according to "Windows ACPI Design Guide for SoC Platforms". + * However surface pro3 seems not to obey the specs, instead it uses + * device VGBI(MSHW0028) for dispatching the events. + * We choose acpi_driver rather than platform_driver/i2c_driver because + * although VGBI has an i2c resource connected to i2c controller, it + * is not embedded in any i2c controller's scope, thus neither platform_device + * will be created, nor i2c_client will be enumerated, we have to use + * acpi_driver. + */ +static const struct acpi_device_id surface_button_device_ids[] = { + {SURFACE_BUTTON_HID, 0}, + {"", 0}, +}; +MODULE_DEVICE_TABLE(acpi, surface_button_device_ids); + +struct surface_button { + unsigned int type; + struct input_dev *input; + char phys[32]; /* for input device */ + unsigned long pushed; + bool suspended; +}; + +static void surface_button_notify(struct acpi_device *device, u32 event) +{ + struct surface_button *button = acpi_driver_data(device); + struct input_dev *input; + int key_code = KEY_RESERVED; + bool pressed = false; + + switch (event) { + /* Power button press,release handle */ + case SURFACE_BUTTON_NOTIFY_PRESS_POWER: + pressed = true; + /*fall through*/ + case SURFACE_BUTTON_NOTIFY_RELEASE_POWER: + key_code = KEY_POWER; + break; + /* Home button press,release handle */ + case SURFACE_BUTTON_NOTIFY_PRESS_HOME: + pressed = true; + /*fall through*/ + case SURFACE_BUTTON_NOTIFY_RELEASE_HOME: + key_code = KEY_LEFTMETA; + break; + /* Volume up button press,release handle */ + case SURFACE_BUTTON_NOTIFY_PRESS_VOLUME_UP: + pressed = true; + /*fall through*/ + case SURFACE_BUTTON_NOTIFY_RELEASE_VOLUME_UP: + key_code = KEY_VOLUMEUP; + break; + /* Volume down button press,release handle */ + case SURFACE_BUTTON_NOTIFY_PRESS_VOLUME_DOWN: + pressed = true; + /*fall through*/ + case SURFACE_BUTTON_NOTIFY_RELEASE_VOLUME_DOWN: + key_code = KEY_VOLUMEDOWN; + break; + default: + dev_info_ratelimited(&device->dev, + "Unsupported event [0x%x]\n", event); + break; + } + input = button->input; + if (KEY_RESERVED == key_code) + return; + if (pressed) + pm_wakeup_event(&device->dev, 0); + if (button->suspended) + return; + input_report_key(input, key_code, pressed?1:0); + input_sync(input); +} + +#ifdef CONFIG_PM_SLEEP +static int surface_button_suspend(struct device *dev) +{ + struct acpi_device *device = to_acpi_device(dev); + struct surface_button *button = acpi_driver_data(device); + + button->suspended = true; + return 0; +} + +static int surface_button_resume(struct device *dev) +{ + struct acpi_device *device = to_acpi_device(dev); + struct surface_button *button = acpi_driver_data(device); + + button->suspended = false; + return 0; +} +#endif + +static int surface_button_add(struct acpi_device *device) +{ + struct surface_button *button; + struct input_dev *input; + const char *hid = acpi_device_hid(device); + char *name; + int error; + + if (strncmp(acpi_device_bid(device), SURFACE_BUTTON_OBJ_NAME, + strlen(SURFACE_BUTTON_OBJ_NAME))) + return -ENODEV; + + button = kzalloc(sizeof(struct surface_button), GFP_KERNEL); + if (!button) + return -ENOMEM; + + device->driver_data = button; + button->input = input = input_allocate_device(); + if (!input) { + error = -ENOMEM; + goto err_free_button; + } + + name = acpi_device_name(device); + strcpy(name, SURFACE_BUTTON_DEVICE_NAME); + snprintf(button->phys, sizeof(button->phys), "%s/buttons", hid); + + input->name = name; + input->phys = button->phys; + input->id.bustype = BUS_HOST; + input->dev.parent = &device->dev; + input_set_capability(input, EV_KEY, KEY_POWER); + input_set_capability(input, EV_KEY, KEY_LEFTMETA); + input_set_capability(input, EV_KEY, KEY_VOLUMEUP); + input_set_capability(input, EV_KEY, KEY_VOLUMEDOWN); + + error = input_register_device(input); + if (error) + goto err_free_input; + dev_info(&device->dev, + "%s [%s]\n", name, acpi_device_bid(device)); + return 0; + + err_free_input: + input_free_device(input); + err_free_button: + kfree(button); + return error; +} + +static int surface_button_remove(struct acpi_device *device) +{ + struct surface_button *button = acpi_driver_data(device); + + input_unregister_device(button->input); + kfree(button); + return 0; +} + +static SIMPLE_DEV_PM_OPS(surface_button_pm, + surface_button_suspend, surface_button_resume); + +static struct acpi_driver surface_button_driver = { + .name = "surface_pro3_button", + .class = "SurfacePro3", + .ids = surface_button_device_ids, + .ops = { + .add = surface_button_add, + .remove = surface_button_remove, + .notify = surface_button_notify, + }, + .drv.pm = &surface_button_pm, +}; + +module_acpi_driver(surface_button_driver); -- cgit v1.2.3 From efd85cf86a56898686187397adfd52dfac79aff2 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 26 Aug 2015 11:13:38 -0700 Subject: thinkpad_acpi: Remove side effects from vdbg_printk -> no_printk macro vdbg_printk when not using CONFIG_THINKPAD_ACPI_DEBUG uses no_printk which produces no logging output but always evaluates arguments. Change the macro to surround the no_printk call with do { if (0) no_printk(...); } while (0) to avoid the unnecessary argument evaluations. $ size drivers/platform/x86/thinkpad_acpi.o* text data bss dec hex filename 60918 6184 824 67926 10956 drivers/platform/x86/thinkpad_acpi.o.new 60927 6184 824 67935 1095f drivers/platform/x86/thinkpad_acpi.o.old Signed-off-by: Joe Perches Acked-by: Henrique de Moraes Holschuh Signed-off-by: Darren Hart --- drivers/platform/x86/thinkpad_acpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 33e488cf5569..131dd7464183 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -402,7 +402,7 @@ static const char *str_supported(int is_supported); #else static inline const char *str_supported(int is_supported) { return ""; } #define vdbg_printk(a_dbg_level, format, arg...) \ - no_printk(format, ##arg) + do { if (0) no_printk(format, ##arg); } while (0) #endif static void tpacpi_log_usertask(const char * const what) -- cgit v1.2.3 From 628b3198ccc235e387c0b8ee200c10c883e86644 Mon Sep 17 00:00:00 2001 From: Michael Powell Date: Sun, 2 Aug 2015 22:59:29 +0000 Subject: acer-wmi: No rfkill on HP Omen 15 wifi Prevents acer-wmi from blocking wifi on HP Omen 15 laptops Signed-off-by: Michael Powell [david.ward@ll.mit.edu: Resubmitted clean patch] Signed-off-by: Darren Hart --- drivers/platform/x86/acer-wmi.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index f6b280dbfb33..d773b9dc48a0 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -807,6 +807,7 @@ static const struct acpi_device_id norfkill_ids[] __initconst = { { "IBM0068", 0}, { "LEN0068", 0}, { "SNY5001", 0}, /* sony-laptop in charge */ + { "HPQ6601", 0}, { "", 0}, }; -- cgit v1.2.3