summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-05-04 14:56:59 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-05-04 14:56:59 -0400
commit99a7583de5ffd5cd82c407aad32bcbdeea09155b (patch)
tree1dc442a6264bab9bb3cf93bfdc99bb76edefd8b1
parentc336bf8e658122eeab63afe0bfcb6360a381a79c (diff)
parent6df97f85611cafc3ba9c093931a5fa3bc7dea897 (diff)
Merge tag 'platform-drivers-x86-v4.12-1' of git://git.infradead.org/linux-platform-drivers-x86
Pull x86 platform-drivers update from Darren Hart: "This represents a significantly larger and more complex set of changes than those of prior merge windows. In particular, we had several changes with dependencies on other subsystems which we felt were best managed through merges of immutable branches, including one each from input, i2c, and leds. Two patches for the watchdog subsystem are included after discussion with Wim and Guenter following a collision in linux-next (this should be resolved and you should only see these two appear in this pull request). These are called out in the "External" section below. Summary of changes: - significant further cleanup of fujitsu-laptop and hp-wmi - new model support for ideapad, asus, silead, and xiaomi - new hotkeys for thinkpad and models using intel-vbtn - dell keyboard backlight improvements - build and dependency improvements - intel * ipc fixes, cleanups, and api updates - single isolated fixes noted below External: - watchdog: iTCO_wdt: Add PMC specific noreboot update api - watchdog: iTCO_wdt: cleanup set/unset no_reboot_bit functions - Merge branch 'ib/4.10-sparse-keymap-managed' - Merge branch 'i2c/for-INT33FE' - Merge branch 'linux-leds/dell-laptop-changes-for-4.12' platform/x86: - Add Intel Cherry Trail ACPI INT33FE device driver - remove sparse_keymap_free() calls - Make SILEAD_DMI depend on TOUCHSCREEN_SILEAD asus-wmi: - try to set als by default - fix cpufv sysfs file permission acer-wmi: - setup accelerometer when ACPI device was found ideapad-laptop: - Add IdeaPad V310-15ISK to no_hw_rfkill - Add IdeaPad 310-15IKB to no_hw_rfkill intel_pmc_ipc: - use gcr mem base for S0ix counter read - Fix iTCO_wdt GCS memory mapping failure - Add pmc gcr read/write/update api's - fix gcr offset dell-laptop: - Add keyboard backlight timeout AC settings - Handle return error form dell_get_intensity. - Protect kbd_state against races - Refactor kbd_led_triggers_store() hp-wireless: - reuse module_acpi_driver - add Xiaomi's hardware id to the supported list intel-vbtn: - add volume up and down INT33FE: - add i2c dependency hp-wmi: - Cleanup exit paths - Do not shadow errors in sysfs show functions - Use DEVICE_ATTR_(RO|RW) helper macros - Refactor dock and tablet state fetchers - Cleanup wireless get_(hw|sw)state functions - Refactor redundant HPWMI_READ functions - Standardize enum usage for constants - Cleanup local variable declarations - Do not shadow error values - Fix detection for dock and tablet mode - Fix error value for hp_wmi_tablet_state fujitsu-laptop: - simplify error handling in acpi_fujitsu_laptop_add() - do not log LED registration failures - switch to managed LED class devices - reorganize LED-related code - refactor LED registration - select LEDS_CLASS - remove redundant fields from struct fujitsu_bl - account for backlight power when determining brightness - do not log set_lcd_level() failures in bl_update_status() - ignore errors when setting backlight power - make disable_brightness_adjust a boolean - clean up use_alt_lcd_levels handling - sync brightness in set_lcd_level() - simplify set_lcd_level() - merge set_lcd_level_alt() into set_lcd_level() - switch to a managed backlight device - only handle backlight when appropriate - update debug message logged by call_fext_func() - rename call_fext_func() arguments - simplify call_fext_func() - clean up local variables in call_fext_func() - remove keycode fields from struct fujitsu_bl - model-dependent sparse keymap overrides - use a sparse keymap for hotkey event generation - switch to a managed hotkey input device - refactor hotkey input device setup - use a sparse keymap for brightness key events - switch to a managed backlight input device - refactor backlight input device setup - remove pf_device field from struct fujitsu_bl - only register platform device if FUJ02E3 is present - add and remove platform device in separate functions - simplify platform device attribute definitions - remove backlight-related attributes from the platform device - cleanup error labels in fujitsu_init() - only register backlight device if FUJ02B1 is present - sync backlight power status in acpi_fujitsu_laptop_add() - register backlight device in a separate function - simplify brightness key event generation logic - decrease indentation in acpi_fujitsu_bl_notify() intel-hid: - Add missing ->thaw callback - do not set parents of input devices explicitly - remove redundant set_bit() call - use devm_input_allocate_device() for HID events input device - make intel_hid_set_enable() take a boolean argument - simplify enabling/disabling HID events silead_dmi: - Add touchscreen info for Surftab Wintron 7.0 - Abort early if DMI does not match - Do not treat all devices as i2c_clients - Add entry for Insyde 7W tablets - Constify properties arrays intel_scu_ipc: - Introduce intel_scu_ipc_raw_command() - Introduce SCU_DEVICE() macro - Remove redundant subarch check - Rearrange init sequence - Platform data is mandatory asus-nb-wmi: - Add wapf4 quirk for the X302UA dell-*: - Call new led hw_changed API on kbd brightness change - Add a generic dell-laptop notifier chain eeepc-laptop: - Skip unknown key messages 0x50 0x51 thinkpad_acpi: - add mapping for new hotkeys - guard generic hotkey case" * tag 'platform-drivers-x86-v4.12-1' of git://git.infradead.org/linux-platform-drivers-x86: (108 commits) platform/x86: Make SILEAD_DMI depend on TOUCHSCREEN_SILEAD platform/x86: asus-wmi: try to set als by default platform/x86: asus-wmi: fix cpufv sysfs file permission platform/x86: acer-wmi: setup accelerometer when ACPI device was found platform/x86: ideapad-laptop: Add IdeaPad V310-15ISK to no_hw_rfkill platform/x86: intel_pmc_ipc: use gcr mem base for S0ix counter read platform/x86: intel_pmc_ipc: Fix iTCO_wdt GCS memory mapping failure watchdog: iTCO_wdt: Add PMC specific noreboot update api watchdog: iTCO_wdt: cleanup set/unset no_reboot_bit functions platform/x86: intel_pmc_ipc: Add pmc gcr read/write/update api's platform/x86: intel_pmc_ipc: fix gcr offset platform/x86: dell-laptop: Add keyboard backlight timeout AC settings platform/x86: dell-laptop: Handle return error form dell_get_intensity. platform/x86: hp-wireless: reuse module_acpi_driver platform/x86: intel-vbtn: add volume up and down platform/x86: INT33FE: add i2c dependency platform/x86: hp-wmi: Cleanup exit paths platform/x86: hp-wmi: Do not shadow errors in sysfs show functions platform/x86: hp-wmi: Use DEVICE_ATTR_(RO|RW) helper macros platform/x86: hp-wmi: Refactor dock and tablet state fetchers ...
-rw-r--r--arch/x86/include/asm/intel_pmc_ipc.h23
-rw-r--r--arch/x86/include/asm/intel_scu_ipc.h8
-rw-r--r--drivers/platform/x86/Kconfig18
-rw-r--r--drivers/platform/x86/Makefile1
-rw-r--r--drivers/platform/x86/acer-wmi.c14
-rw-r--r--drivers/platform/x86/asus-laptop.c8
-rw-r--r--drivers/platform/x86/asus-nb-wmi.c22
-rw-r--r--drivers/platform/x86/asus-wmi.c24
-rw-r--r--drivers/platform/x86/asus-wmi.h1
-rw-r--r--drivers/platform/x86/dell-laptop.c254
-rw-r--r--drivers/platform/x86/dell-smbios.c20
-rw-r--r--drivers/platform/x86/dell-smbios.h11
-rw-r--r--drivers/platform/x86/dell-wmi-aio.c6
-rw-r--r--drivers/platform/x86/dell-wmi.c20
-rw-r--r--drivers/platform/x86/eeepc-laptop.c10
-rw-r--r--drivers/platform/x86/fujitsu-laptop.c1216
-rw-r--r--drivers/platform/x86/hp-wireless.c27
-rw-r--r--drivers/platform/x86/hp-wmi.c414
-rw-r--r--drivers/platform/x86/ideapad-laptop.c19
-rw-r--r--drivers/platform/x86/intel-hid.c51
-rw-r--r--drivers/platform/x86/intel-vbtn.c4
-rw-r--r--drivers/platform/x86/intel_cht_int33fe.c143
-rw-r--r--drivers/platform/x86/intel_pmc_ipc.c156
-rw-r--r--drivers/platform/x86/intel_scu_ipc.c106
-rw-r--r--drivers/platform/x86/msi-laptop.c14
-rw-r--r--drivers/platform/x86/msi-wmi.c9
-rw-r--r--drivers/platform/x86/panasonic-laptop.c18
-rw-r--r--drivers/platform/x86/silead_dmi.c80
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c99
-rw-r--r--drivers/platform/x86/topstar-laptop.c5
-rw-r--r--drivers/platform/x86/toshiba-wmi.c5
-rw-r--r--drivers/platform/x86/toshiba_acpi.c8
-rw-r--r--drivers/watchdog/iTCO_wdt.c94
-rw-r--r--include/linux/platform_data/itco_wdt.h4
34 files changed, 1618 insertions, 1294 deletions
diff --git a/arch/x86/include/asm/intel_pmc_ipc.h b/arch/x86/include/asm/intel_pmc_ipc.h
index 4291b6a5ddf7..fac89eb78a6b 100644
--- a/arch/x86/include/asm/intel_pmc_ipc.h
+++ b/arch/x86/include/asm/intel_pmc_ipc.h
@@ -23,6 +23,11 @@
23#define IPC_ERR_EMSECURITY 6 23#define IPC_ERR_EMSECURITY 6
24#define IPC_ERR_UNSIGNEDKERNEL 7 24#define IPC_ERR_UNSIGNEDKERNEL 7
25 25
26/* GCR reg offsets from gcr base*/
27#define PMC_GCR_PMC_CFG_REG 0x08
28#define PMC_GCR_TELEM_DEEP_S0IX_REG 0x78
29#define PMC_GCR_TELEM_SHLW_S0IX_REG 0x80
30
26#if IS_ENABLED(CONFIG_INTEL_PMC_IPC) 31#if IS_ENABLED(CONFIG_INTEL_PMC_IPC)
27 32
28int intel_pmc_ipc_simple_command(int cmd, int sub); 33int intel_pmc_ipc_simple_command(int cmd, int sub);
@@ -31,6 +36,9 @@ int intel_pmc_ipc_raw_cmd(u32 cmd, u32 sub, u8 *in, u32 inlen,
31int intel_pmc_ipc_command(u32 cmd, u32 sub, u8 *in, u32 inlen, 36int intel_pmc_ipc_command(u32 cmd, u32 sub, u8 *in, u32 inlen,
32 u32 *out, u32 outlen); 37 u32 *out, u32 outlen);
33int intel_pmc_s0ix_counter_read(u64 *data); 38int intel_pmc_s0ix_counter_read(u64 *data);
39int intel_pmc_gcr_read(u32 offset, u32 *data);
40int intel_pmc_gcr_write(u32 offset, u32 data);
41int intel_pmc_gcr_update(u32 offset, u32 mask, u32 val);
34 42
35#else 43#else
36 44
@@ -56,6 +64,21 @@ static inline int intel_pmc_s0ix_counter_read(u64 *data)
56 return -EINVAL; 64 return -EINVAL;
57} 65}
58 66
67static inline int intel_pmc_gcr_read(u32 offset, u32 *data)
68{
69 return -EINVAL;
70}
71
72static inline int intel_pmc_gcr_write(u32 offset, u32 data)
73{
74 return -EINVAL;
75}
76
77static inline int intel_pmc_gcr_update(u32 offset, u32 mask, u32 val)
78{
79 return -EINVAL;
80}
81
59#endif /*CONFIG_INTEL_PMC_IPC*/ 82#endif /*CONFIG_INTEL_PMC_IPC*/
60 83
61#endif 84#endif
diff --git a/arch/x86/include/asm/intel_scu_ipc.h b/arch/x86/include/asm/intel_scu_ipc.h
index 4fb1d0abef95..81d3d8776fd9 100644
--- a/arch/x86/include/asm/intel_scu_ipc.h
+++ b/arch/x86/include/asm/intel_scu_ipc.h
@@ -3,6 +3,9 @@
3 3
4#include <linux/notifier.h> 4#include <linux/notifier.h>
5 5
6#define IPCMSG_INDIRECT_READ 0x02
7#define IPCMSG_INDIRECT_WRITE 0x05
8
6#define IPCMSG_COLD_OFF 0x80 /* Only for Tangier */ 9#define IPCMSG_COLD_OFF 0x80 /* Only for Tangier */
7 10
8#define IPCMSG_WARM_RESET 0xF0 11#define IPCMSG_WARM_RESET 0xF0
@@ -45,7 +48,10 @@ int intel_scu_ipc_update_register(u16 addr, u8 data, u8 mask);
45/* Issue commands to the SCU with or without data */ 48/* Issue commands to the SCU with or without data */
46int intel_scu_ipc_simple_command(int cmd, int sub); 49int intel_scu_ipc_simple_command(int cmd, int sub);
47int intel_scu_ipc_command(int cmd, int sub, u32 *in, int inlen, 50int intel_scu_ipc_command(int cmd, int sub, u32 *in, int inlen,
48 u32 *out, int outlen); 51 u32 *out, int outlen);
52int intel_scu_ipc_raw_command(int cmd, int sub, u8 *in, int inlen,
53 u32 *out, int outlen, u32 dptr, u32 sptr);
54
49/* I2C control api */ 55/* I2C control api */
50int intel_scu_ipc_i2c_cntrl(u32 addr, u32 *data); 56int intel_scu_ipc_i2c_cntrl(u32 addr, u32 *data);
51 57
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 883fbe7a2466..8489020ecf44 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -182,7 +182,8 @@ config FUJITSU_LAPTOP
182 depends on INPUT 182 depends on INPUT
183 depends on BACKLIGHT_CLASS_DEVICE 183 depends on BACKLIGHT_CLASS_DEVICE
184 depends on ACPI_VIDEO || ACPI_VIDEO = n 184 depends on ACPI_VIDEO || ACPI_VIDEO = n
185 depends on LEDS_CLASS || LEDS_CLASS=n 185 select INPUT_SPARSEKMAP
186 select LEDS_CLASS
186 ---help--- 187 ---help---
187 This is a driver for laptops built by Fujitsu: 188 This is a driver for laptops built by Fujitsu:
188 189
@@ -780,6 +781,19 @@ config ACPI_CMPC
780 keys as input device, backlight device, tablet and accelerometer 781 keys as input device, backlight device, tablet and accelerometer
781 devices. 782 devices.
782 783
784config INTEL_CHT_INT33FE
785 tristate "Intel Cherry Trail ACPI INT33FE Driver"
786 depends on X86 && ACPI && I2C
787 ---help---
788 This driver add support for the INT33FE ACPI device found on
789 some Intel Cherry Trail devices.
790
791 The INT33FE ACPI device has a CRS table with I2cSerialBusV2
792 resources for 3 devices: Maxim MAX17047 Fuel Gauge Controller,
793 FUSB302 USB Type-C Controller and PI3USB30532 USB switch.
794 This driver instantiates i2c-clients for these, so that standard
795 i2c drivers for these chips can bind to the them.
796
783config INTEL_HID_EVENT 797config INTEL_HID_EVENT
784 tristate "INTEL HID Event" 798 tristate "INTEL HID Event"
785 depends on ACPI 799 depends on ACPI
@@ -1087,7 +1101,7 @@ config INTEL_TURBO_MAX_3
1087 1101
1088config SILEAD_DMI 1102config SILEAD_DMI
1089 bool "Tablets with Silead touchscreens" 1103 bool "Tablets with Silead touchscreens"
1090 depends on ACPI && DMI && I2C=y && INPUT 1104 depends on ACPI && DMI && I2C=y && TOUCHSCREEN_SILEAD
1091 ---help--- 1105 ---help---
1092 Certain ACPI based tablets with Silead touchscreens do not have 1106 Certain ACPI based tablets with Silead touchscreens do not have
1093 enough data in ACPI tables for the touchscreen driver to handle 1107 enough data in ACPI tables for the touchscreen driver to handle
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index 776b3a7a4984..182a3ed6605a 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -45,6 +45,7 @@ obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o
45obj-$(CONFIG_TOSHIBA_BT_RFKILL) += toshiba_bluetooth.o 45obj-$(CONFIG_TOSHIBA_BT_RFKILL) += toshiba_bluetooth.o
46obj-$(CONFIG_TOSHIBA_HAPS) += toshiba_haps.o 46obj-$(CONFIG_TOSHIBA_HAPS) += toshiba_haps.o
47obj-$(CONFIG_TOSHIBA_WMI) += toshiba-wmi.o 47obj-$(CONFIG_TOSHIBA_WMI) += toshiba-wmi.o
48obj-$(CONFIG_INTEL_CHT_INT33FE) += intel_cht_int33fe.o
48obj-$(CONFIG_INTEL_HID_EVENT) += intel-hid.o 49obj-$(CONFIG_INTEL_HID_EVENT) += intel-hid.o
49obj-$(CONFIG_INTEL_VBTN) += intel-vbtn.o 50obj-$(CONFIG_INTEL_VBTN) += intel-vbtn.o
50obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o 51obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index dac0fbe87460..79fa5ab3fd00 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -1896,7 +1896,7 @@ static acpi_status __init acer_wmi_get_handle_cb(acpi_handle ah, u32 level,
1896 if (!strcmp(ctx, "SENR")) { 1896 if (!strcmp(ctx, "SENR")) {
1897 if (acpi_bus_get_device(ah, &dev)) 1897 if (acpi_bus_get_device(ah, &dev))
1898 return AE_OK; 1898 return AE_OK;
1899 if (!strcmp(ACER_WMID_ACCEL_HID, acpi_device_hid(dev))) 1899 if (strcmp(ACER_WMID_ACCEL_HID, acpi_device_hid(dev)))
1900 return AE_OK; 1900 return AE_OK;
1901 } else 1901 } else
1902 return AE_OK; 1902 return AE_OK;
@@ -1917,8 +1917,7 @@ static int __init acer_wmi_get_handle(const char *name, const char *prop,
1917 handle = NULL; 1917 handle = NULL;
1918 status = acpi_get_devices(prop, acer_wmi_get_handle_cb, 1918 status = acpi_get_devices(prop, acer_wmi_get_handle_cb,
1919 (void *)name, &handle); 1919 (void *)name, &handle);
1920 1920 if (ACPI_SUCCESS(status) && handle) {
1921 if (ACPI_SUCCESS(status)) {
1922 *ah = handle; 1921 *ah = handle;
1923 return 0; 1922 return 0;
1924 } else { 1923 } else {
@@ -1987,7 +1986,7 @@ static int __init acer_wmi_input_setup(void)
1987 acer_wmi_notify, NULL); 1986 acer_wmi_notify, NULL);
1988 if (ACPI_FAILURE(status)) { 1987 if (ACPI_FAILURE(status)) {
1989 err = -EIO; 1988 err = -EIO;
1990 goto err_free_keymap; 1989 goto err_free_dev;
1991 } 1990 }
1992 1991
1993 err = input_register_device(acer_wmi_input_dev); 1992 err = input_register_device(acer_wmi_input_dev);
@@ -1998,8 +1997,6 @@ static int __init acer_wmi_input_setup(void)
1998 1997
1999err_uninstall_notifier: 1998err_uninstall_notifier:
2000 wmi_remove_notify_handler(ACERWMID_EVENT_GUID); 1999 wmi_remove_notify_handler(ACERWMID_EVENT_GUID);
2001err_free_keymap:
2002 sparse_keymap_free(acer_wmi_input_dev);
2003err_free_dev: 2000err_free_dev:
2004 input_free_device(acer_wmi_input_dev); 2001 input_free_device(acer_wmi_input_dev);
2005 return err; 2002 return err;
@@ -2008,7 +2005,6 @@ err_free_dev:
2008static void acer_wmi_input_destroy(void) 2005static void acer_wmi_input_destroy(void)
2009{ 2006{
2010 wmi_remove_notify_handler(ACERWMID_EVENT_GUID); 2007 wmi_remove_notify_handler(ACERWMID_EVENT_GUID);
2011 sparse_keymap_free(acer_wmi_input_dev);
2012 input_unregister_device(acer_wmi_input_dev); 2008 input_unregister_device(acer_wmi_input_dev);
2013} 2009}
2014 2010
@@ -2290,8 +2286,8 @@ static int __init acer_wmi_init(void)
2290 if (err) 2286 if (err)
2291 return err; 2287 return err;
2292 err = acer_wmi_accel_setup(); 2288 err = acer_wmi_accel_setup();
2293 if (err) 2289 if (err && err != -ENODEV)
2294 return err; 2290 pr_warn("Cannot enable accelerometer\n");
2295 } 2291 }
2296 2292
2297 err = platform_driver_register(&acer_platform_driver); 2293 err = platform_driver_register(&acer_platform_driver);
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index 28551f5a2e07..c4768be24ba9 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -1516,14 +1516,12 @@ static int asus_input_init(struct asus_laptop *asus)
1516 error = input_register_device(input); 1516 error = input_register_device(input);
1517 if (error) { 1517 if (error) {
1518 pr_warn("Unable to register input device\n"); 1518 pr_warn("Unable to register input device\n");
1519 goto err_free_keymap; 1519 goto err_free_dev;
1520 } 1520 }
1521 1521
1522 asus->inputdev = input; 1522 asus->inputdev = input;
1523 return 0; 1523 return 0;
1524 1524
1525err_free_keymap:
1526 sparse_keymap_free(input);
1527err_free_dev: 1525err_free_dev:
1528 input_free_device(input); 1526 input_free_device(input);
1529 return error; 1527 return error;
@@ -1531,10 +1529,8 @@ err_free_dev:
1531 1529
1532static void asus_input_exit(struct asus_laptop *asus) 1530static void asus_input_exit(struct asus_laptop *asus)
1533{ 1531{
1534 if (asus->inputdev) { 1532 if (asus->inputdev)
1535 sparse_keymap_free(asus->inputdev);
1536 input_unregister_device(asus->inputdev); 1533 input_unregister_device(asus->inputdev);
1537 }
1538 asus->inputdev = NULL; 1534 asus->inputdev = NULL;
1539} 1535}
1540 1536
diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c
index dea98ffb6f60..5269a01d9bdd 100644
--- a/drivers/platform/x86/asus-nb-wmi.c
+++ b/drivers/platform/x86/asus-nb-wmi.c
@@ -111,6 +111,10 @@ static struct quirk_entry quirk_asus_x550lb = {
111 .xusb2pr = 0x01D9, 111 .xusb2pr = 0x01D9,
112}; 112};
113 113
114static struct quirk_entry quirk_asus_ux330uak = {
115 .wmi_force_als_set = true,
116};
117
114static int dmi_matched(const struct dmi_system_id *dmi) 118static int dmi_matched(const struct dmi_system_id *dmi)
115{ 119{
116 pr_info("Identified laptop model '%s'\n", dmi->ident); 120 pr_info("Identified laptop model '%s'\n", dmi->ident);
@@ -144,6 +148,15 @@ static const struct dmi_system_id asus_quirks[] = {
144 }, 148 },
145 { 149 {
146 .callback = dmi_matched, 150 .callback = dmi_matched,
151 .ident = "ASUSTeK COMPUTER INC. X302UA",
152 .matches = {
153 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
154 DMI_MATCH(DMI_PRODUCT_NAME, "X302UA"),
155 },
156 .driver_data = &quirk_asus_wapf4,
157 },
158 {
159 .callback = dmi_matched,
147 .ident = "ASUSTeK COMPUTER INC. X401U", 160 .ident = "ASUSTeK COMPUTER INC. X401U",
148 .matches = { 161 .matches = {
149 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 162 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
@@ -369,6 +382,15 @@ static const struct dmi_system_id asus_quirks[] = {
369 }, 382 },
370 { 383 {
371 .callback = dmi_matched, 384 .callback = dmi_matched,
385 .ident = "ASUSTeK COMPUTER INC. UX330UAK",
386 .matches = {
387 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
388 DMI_MATCH(DMI_PRODUCT_NAME, "UX330UAK"),
389 },
390 .driver_data = &quirk_asus_ux330uak,
391 },
392 {
393 .callback = dmi_matched,
372 .ident = "ASUSTeK COMPUTER INC. X550LB", 394 .ident = "ASUSTeK COMPUTER INC. X550LB",
373 .matches = { 395 .matches = {
374 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 396 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index 8fe5890bf539..6c7d86074b38 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -269,12 +269,10 @@ static int asus_wmi_input_init(struct asus_wmi *asus)
269 269
270 err = input_register_device(asus->inputdev); 270 err = input_register_device(asus->inputdev);
271 if (err) 271 if (err)
272 goto err_free_keymap; 272 goto err_free_dev;
273 273
274 return 0; 274 return 0;
275 275
276err_free_keymap:
277 sparse_keymap_free(asus->inputdev);
278err_free_dev: 276err_free_dev:
279 input_free_device(asus->inputdev); 277 input_free_device(asus->inputdev);
280 return err; 278 return err;
@@ -282,10 +280,8 @@ err_free_dev:
282 280
283static void asus_wmi_input_exit(struct asus_wmi *asus) 281static void asus_wmi_input_exit(struct asus_wmi *asus)
284{ 282{
285 if (asus->inputdev) { 283 if (asus->inputdev)
286 sparse_keymap_free(asus->inputdev);
287 input_unregister_device(asus->inputdev); 284 input_unregister_device(asus->inputdev);
288 }
289 285
290 asus->inputdev = NULL; 286 asus->inputdev = NULL;
291} 287}
@@ -1109,6 +1105,15 @@ static void asus_wmi_set_xusb2pr(struct asus_wmi *asus)
1109} 1105}
1110 1106
1111/* 1107/*
1108 * Some devices dont support or have borcken get_als method
1109 * but still support set method.
1110 */
1111static void asus_wmi_set_als(void)
1112{
1113 asus_wmi_set_devstate(ASUS_WMI_DEVID_ALS_ENABLE, 1, NULL);
1114}
1115
1116/*
1112 * Hwmon device 1117 * Hwmon device
1113 */ 1118 */
1114static int asus_hwmon_agfn_fan_speed_read(struct asus_wmi *asus, int fan, 1119static int asus_hwmon_agfn_fan_speed_read(struct asus_wmi *asus, int fan,
@@ -1761,7 +1766,7 @@ ASUS_WMI_CREATE_DEVICE_ATTR(cardr, 0644, ASUS_WMI_DEVID_CARDREADER);
1761ASUS_WMI_CREATE_DEVICE_ATTR(lid_resume, 0644, ASUS_WMI_DEVID_LID_RESUME); 1766ASUS_WMI_CREATE_DEVICE_ATTR(lid_resume, 0644, ASUS_WMI_DEVID_LID_RESUME);
1762ASUS_WMI_CREATE_DEVICE_ATTR(als_enable, 0644, ASUS_WMI_DEVID_ALS_ENABLE); 1767ASUS_WMI_CREATE_DEVICE_ATTR(als_enable, 0644, ASUS_WMI_DEVID_ALS_ENABLE);
1763 1768
1764static ssize_t store_cpufv(struct device *dev, struct device_attribute *attr, 1769static ssize_t cpufv_store(struct device *dev, struct device_attribute *attr,
1765 const char *buf, size_t count) 1770 const char *buf, size_t count)
1766{ 1771{
1767 int value, rv; 1772 int value, rv;
@@ -1778,7 +1783,7 @@ static ssize_t store_cpufv(struct device *dev, struct device_attribute *attr,
1778 return count; 1783 return count;
1779} 1784}
1780 1785
1781static DEVICE_ATTR(cpufv, S_IRUGO | S_IWUSR, NULL, store_cpufv); 1786static DEVICE_ATTR_WO(cpufv);
1782 1787
1783static struct attribute *platform_attributes[] = { 1788static struct attribute *platform_attributes[] = {
1784 &dev_attr_cpufv.attr, 1789 &dev_attr_cpufv.attr,
@@ -2117,6 +2122,9 @@ static int asus_wmi_add(struct platform_device *pdev)
2117 goto fail_rfkill; 2122 goto fail_rfkill;
2118 } 2123 }
2119 2124
2125 if (asus->driver->quirks->wmi_force_als_set)
2126 asus_wmi_set_als();
2127
2120 /* Some Asus desktop boards export an acpi-video backlight interface, 2128 /* Some Asus desktop boards export an acpi-video backlight interface,
2121 stop this from showing up */ 2129 stop this from showing up */
2122 chassis_type = dmi_get_system_info(DMI_CHASSIS_TYPE); 2130 chassis_type = dmi_get_system_info(DMI_CHASSIS_TYPE);
diff --git a/drivers/platform/x86/asus-wmi.h b/drivers/platform/x86/asus-wmi.h
index c9589d9342bb..6c1311f4b04d 100644
--- a/drivers/platform/x86/asus-wmi.h
+++ b/drivers/platform/x86/asus-wmi.h
@@ -44,6 +44,7 @@ struct quirk_entry {
44 bool store_backlight_power; 44 bool store_backlight_power;
45 bool wmi_backlight_power; 45 bool wmi_backlight_power;
46 bool wmi_backlight_native; 46 bool wmi_backlight_native;
47 bool wmi_force_als_set;
47 int wapf; 48 int wapf;
48 /* 49 /*
49 * For machines with AMD graphic chips, it will send out WMI event 50 * For machines with AMD graphic chips, it will send out WMI event
diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
index 2e237bad4995..ec202094bd50 100644
--- a/drivers/platform/x86/dell-laptop.c
+++ b/drivers/platform/x86/dell-laptop.c
@@ -45,6 +45,7 @@
45#define KBD_LED_AUTO_100_TOKEN 0x02F6 45#define KBD_LED_AUTO_100_TOKEN 0x02F6
46#define GLOBAL_MIC_MUTE_ENABLE 0x0364 46#define GLOBAL_MIC_MUTE_ENABLE 0x0364
47#define GLOBAL_MIC_MUTE_DISABLE 0x0365 47#define GLOBAL_MIC_MUTE_DISABLE 0x0365
48#define KBD_LED_AC_TOKEN 0x0451
48 49
49struct quirk_entry { 50struct quirk_entry {
50 u8 touchpad_led; 51 u8 touchpad_led;
@@ -1027,7 +1028,7 @@ static void touchpad_led_exit(void)
1027 * bit 2 Pointing stick 1028 * bit 2 Pointing stick
1028 * bit 3 Any mouse 1029 * bit 3 Any mouse
1029 * bits 4-7 Reserved for future use 1030 * bits 4-7 Reserved for future use
1030 * cbRES2, byte3 Current Timeout 1031 * cbRES2, byte3 Current Timeout on battery
1031 * bits 7:6 Timeout units indicator: 1032 * bits 7:6 Timeout units indicator:
1032 * 00b Seconds 1033 * 00b Seconds
1033 * 01b Minutes 1034 * 01b Minutes
@@ -1039,6 +1040,15 @@ static void touchpad_led_exit(void)
1039 * cbRES3, byte0 Current setting of ALS value that turns the light on or off. 1040 * cbRES3, byte0 Current setting of ALS value that turns the light on or off.
1040 * cbRES3, byte1 Current ALS reading 1041 * cbRES3, byte1 Current ALS reading
1041 * cbRES3, byte2 Current keyboard light level. 1042 * cbRES3, byte2 Current keyboard light level.
1043 * cbRES3, byte3 Current timeout on AC Power
1044 * bits 7:6 Timeout units indicator:
1045 * 00b Seconds
1046 * 01b Minutes
1047 * 10b Hours
1048 * 11b Days
1049 * Bits 5:0 Timeout value (0-63) in sec/min/hr/day
1050 * NOTE: A value of 0 means always on (no timeout) if any bits of RES3 byte2
1051 * are set upon return from the upon return from the [Get Feature information] call.
1042 * 1052 *
1043 * cbArg1 0x2 = Set New State 1053 * cbArg1 0x2 = Set New State
1044 * cbRES1 Standard return codes (0, -1, -2) 1054 * cbRES1 Standard return codes (0, -1, -2)
@@ -1061,7 +1071,7 @@ static void touchpad_led_exit(void)
1061 * bit 2 Pointing stick 1071 * bit 2 Pointing stick
1062 * bit 3 Any mouse 1072 * bit 3 Any mouse
1063 * bits 4-7 Reserved for future use 1073 * bits 4-7 Reserved for future use
1064 * cbArg2, byte3 Desired Timeout 1074 * cbArg2, byte3 Desired Timeout on battery
1065 * bits 7:6 Timeout units indicator: 1075 * bits 7:6 Timeout units indicator:
1066 * 00b Seconds 1076 * 00b Seconds
1067 * 01b Minutes 1077 * 01b Minutes
@@ -1070,6 +1080,13 @@ static void touchpad_led_exit(void)
1070 * bits 5:0 Timeout value (0-63) in sec/min/hr/day 1080 * bits 5:0 Timeout value (0-63) in sec/min/hr/day
1071 * cbArg3, byte0 Desired setting of ALS value that turns the light on or off. 1081 * cbArg3, byte0 Desired setting of ALS value that turns the light on or off.
1072 * cbArg3, byte2 Desired keyboard light level. 1082 * cbArg3, byte2 Desired keyboard light level.
1083 * cbArg3, byte3 Desired Timeout on AC power
1084 * bits 7:6 Timeout units indicator:
1085 * 00b Seconds
1086 * 01b Minutes
1087 * 10b Hours
1088 * 11b Days
1089 * bits 5:0 Timeout value (0-63) in sec/min/hr/day
1073 */ 1090 */
1074 1091
1075 1092
@@ -1115,6 +1132,8 @@ struct kbd_state {
1115 u8 triggers; 1132 u8 triggers;
1116 u8 timeout_value; 1133 u8 timeout_value;
1117 u8 timeout_unit; 1134 u8 timeout_unit;
1135 u8 timeout_value_ac;
1136 u8 timeout_unit_ac;
1118 u8 als_setting; 1137 u8 als_setting;
1119 u8 als_value; 1138 u8 als_value;
1120 u8 level; 1139 u8 level;
@@ -1134,6 +1153,7 @@ static u16 kbd_token_bits;
1134static struct kbd_info kbd_info; 1153static struct kbd_info kbd_info;
1135static bool kbd_als_supported; 1154static bool kbd_als_supported;
1136static bool kbd_triggers_supported; 1155static bool kbd_triggers_supported;
1156static bool kbd_timeout_ac_supported;
1137 1157
1138static u8 kbd_mode_levels[16]; 1158static u8 kbd_mode_levels[16];
1139static int kbd_mode_levels_count; 1159static int kbd_mode_levels_count;
@@ -1142,6 +1162,7 @@ static u8 kbd_previous_level;
1142static u8 kbd_previous_mode_bit; 1162static u8 kbd_previous_mode_bit;
1143 1163
1144static bool kbd_led_present; 1164static bool kbd_led_present;
1165static DEFINE_MUTEX(kbd_led_mutex);
1145 1166
1146/* 1167/*
1147 * NOTE: there are three ways to set the keyboard backlight level. 1168 * NOTE: there are three ways to set the keyboard backlight level.
@@ -1272,6 +1293,8 @@ static int kbd_get_state(struct kbd_state *state)
1272 state->als_setting = buffer->output[2] & 0xFF; 1293 state->als_setting = buffer->output[2] & 0xFF;
1273 state->als_value = (buffer->output[2] >> 8) & 0xFF; 1294 state->als_value = (buffer->output[2] >> 8) & 0xFF;
1274 state->level = (buffer->output[2] >> 16) & 0xFF; 1295 state->level = (buffer->output[2] >> 16) & 0xFF;
1296 state->timeout_value_ac = (buffer->output[2] >> 24) & 0x3F;
1297 state->timeout_unit_ac = (buffer->output[2] >> 30) & 0x3;
1275 1298
1276 out: 1299 out:
1277 dell_smbios_release_buffer(); 1300 dell_smbios_release_buffer();
@@ -1291,6 +1314,8 @@ static int kbd_set_state(struct kbd_state *state)
1291 buffer->input[1] |= (state->timeout_unit & 0x3) << 30; 1314 buffer->input[1] |= (state->timeout_unit & 0x3) << 30;
1292 buffer->input[2] = state->als_setting & 0xFF; 1315 buffer->input[2] = state->als_setting & 0xFF;
1293 buffer->input[2] |= (state->level & 0xFF) << 16; 1316 buffer->input[2] |= (state->level & 0xFF) << 16;
1317 buffer->input[2] |= (state->timeout_value_ac & 0x3F) << 24;
1318 buffer->input[2] |= (state->timeout_unit_ac & 0x3) << 30;
1294 dell_smbios_send_request(4, 11); 1319 dell_smbios_send_request(4, 11);
1295 ret = buffer->output[0]; 1320 ret = buffer->output[0];
1296 dell_smbios_release_buffer(); 1321 dell_smbios_release_buffer();
@@ -1397,6 +1422,13 @@ static inline int kbd_init_info(void)
1397 if (ret) 1422 if (ret)
1398 return ret; 1423 return ret;
1399 1424
1425 /* NOTE: Old models without KBD_LED_AC_TOKEN token supports only one
1426 * timeout value which is shared for both battery and AC power
1427 * settings. So do not try to set AC values on old models.
1428 */
1429 if (dell_smbios_find_token(KBD_LED_AC_TOKEN))
1430 kbd_timeout_ac_supported = true;
1431
1400 kbd_get_state(&state); 1432 kbd_get_state(&state);
1401 1433
1402 /* NOTE: timeout value is stored in 6 bits so max value is 63 */ 1434 /* NOTE: timeout value is stored in 6 bits so max value is 63 */
@@ -1571,35 +1603,56 @@ static ssize_t kbd_led_timeout_store(struct device *dev,
1571 } 1603 }
1572 } 1604 }
1573 1605
1606 mutex_lock(&kbd_led_mutex);
1607
1574 ret = kbd_get_state(&state); 1608 ret = kbd_get_state(&state);
1575 if (ret) 1609 if (ret)
1576 return ret; 1610 goto out;
1577 1611
1578 new_state = state; 1612 new_state = state;
1579 new_state.timeout_value = value; 1613
1580 new_state.timeout_unit = unit; 1614 if (kbd_timeout_ac_supported && power_supply_is_system_supplied() > 0) {
1615 new_state.timeout_value_ac = value;
1616 new_state.timeout_unit_ac = unit;
1617 } else {
1618 new_state.timeout_value = value;
1619 new_state.timeout_unit = unit;
1620 }
1581 1621
1582 ret = kbd_set_state_safe(&new_state, &state); 1622 ret = kbd_set_state_safe(&new_state, &state);
1583 if (ret) 1623 if (ret)
1584 return ret; 1624 goto out;
1585 1625
1586 return count; 1626 ret = count;
1627out:
1628 mutex_unlock(&kbd_led_mutex);
1629 return ret;
1587} 1630}
1588 1631
1589static ssize_t kbd_led_timeout_show(struct device *dev, 1632static ssize_t kbd_led_timeout_show(struct device *dev,
1590 struct device_attribute *attr, char *buf) 1633 struct device_attribute *attr, char *buf)
1591{ 1634{
1592 struct kbd_state state; 1635 struct kbd_state state;
1636 int value;
1593 int ret; 1637 int ret;
1594 int len; 1638 int len;
1639 u8 unit;
1595 1640
1596 ret = kbd_get_state(&state); 1641 ret = kbd_get_state(&state);
1597 if (ret) 1642 if (ret)
1598 return ret; 1643 return ret;
1599 1644
1600 len = sprintf(buf, "%d", state.timeout_value); 1645 if (kbd_timeout_ac_supported && power_supply_is_system_supplied() > 0) {
1646 value = state.timeout_value_ac;
1647 unit = state.timeout_unit_ac;
1648 } else {
1649 value = state.timeout_value;
1650 unit = state.timeout_unit;
1651 }
1652
1653 len = sprintf(buf, "%d", value);
1601 1654
1602 switch (state.timeout_unit) { 1655 switch (unit) {
1603 case KBD_TIMEOUT_SECONDS: 1656 case KBD_TIMEOUT_SECONDS:
1604 return len + sprintf(buf+len, "s\n"); 1657 return len + sprintf(buf+len, "s\n");
1605 case KBD_TIMEOUT_MINUTES: 1658 case KBD_TIMEOUT_MINUTES:
@@ -1643,9 +1696,11 @@ static ssize_t kbd_led_triggers_store(struct device *dev,
1643 if (trigger[0] != '+' && trigger[0] != '-') 1696 if (trigger[0] != '+' && trigger[0] != '-')
1644 return -EINVAL; 1697 return -EINVAL;
1645 1698
1699 mutex_lock(&kbd_led_mutex);
1700
1646 ret = kbd_get_state(&state); 1701 ret = kbd_get_state(&state);
1647 if (ret) 1702 if (ret)
1648 return ret; 1703 goto out;
1649 1704
1650 if (kbd_triggers_supported) 1705 if (kbd_triggers_supported)
1651 triggers_enabled = kbd_is_trigger_mode_bit(state.mode_bit); 1706 triggers_enabled = kbd_is_trigger_mode_bit(state.mode_bit);
@@ -1659,48 +1714,62 @@ static ssize_t kbd_led_triggers_store(struct device *dev,
1659 if (strcmp(trigger+1, kbd_led_triggers[i]) != 0) 1714 if (strcmp(trigger+1, kbd_led_triggers[i]) != 0)
1660 continue; 1715 continue;
1661 if (trigger[0] == '+' && 1716 if (trigger[0] == '+' &&
1662 triggers_enabled && (state.triggers & BIT(i))) 1717 triggers_enabled && (state.triggers & BIT(i))) {
1663 return count; 1718 ret = count;
1719 goto out;
1720 }
1664 if (trigger[0] == '-' && 1721 if (trigger[0] == '-' &&
1665 (!triggers_enabled || !(state.triggers & BIT(i)))) 1722 (!triggers_enabled || !(state.triggers & BIT(i)))) {
1666 return count; 1723 ret = count;
1724 goto out;
1725 }
1667 trigger_bit = i; 1726 trigger_bit = i;
1668 break; 1727 break;
1669 } 1728 }
1670 } 1729 }
1671 1730
1672 if (trigger_bit != -1) { 1731 if (trigger_bit == -1) {
1673 new_state = state; 1732 ret = -EINVAL;
1674 if (trigger[0] == '+') 1733 goto out;
1675 new_state.triggers |= BIT(trigger_bit);
1676 else {
1677 new_state.triggers &= ~BIT(trigger_bit);
1678 /* NOTE: trackstick bit (2) must be disabled when
1679 * disabling touchpad bit (1), otherwise touchpad
1680 * bit (1) will not be disabled */
1681 if (trigger_bit == 1)
1682 new_state.triggers &= ~BIT(2);
1683 }
1684 if ((kbd_info.triggers & new_state.triggers) !=
1685 new_state.triggers)
1686 return -EINVAL;
1687 if (new_state.triggers && !triggers_enabled) {
1688 new_state.mode_bit = KBD_MODE_BIT_TRIGGER;
1689 kbd_set_level(&new_state, kbd_previous_level);
1690 } else if (new_state.triggers == 0) {
1691 kbd_set_level(&new_state, 0);
1692 }
1693 if (!(kbd_info.modes & BIT(new_state.mode_bit)))
1694 return -EINVAL;
1695 ret = kbd_set_state_safe(&new_state, &state);
1696 if (ret)
1697 return ret;
1698 if (new_state.mode_bit != KBD_MODE_BIT_OFF)
1699 kbd_previous_mode_bit = new_state.mode_bit;
1700 return count;
1701 } 1734 }
1702 1735
1703 return -EINVAL; 1736 new_state = state;
1737 if (trigger[0] == '+')
1738 new_state.triggers |= BIT(trigger_bit);
1739 else {
1740 new_state.triggers &= ~BIT(trigger_bit);
1741 /*
1742 * NOTE: trackstick bit (2) must be disabled when
1743 * disabling touchpad bit (1), otherwise touchpad
1744 * bit (1) will not be disabled
1745 */
1746 if (trigger_bit == 1)
1747 new_state.triggers &= ~BIT(2);
1748 }
1749 if ((kbd_info.triggers & new_state.triggers) !=
1750 new_state.triggers) {
1751 ret = -EINVAL;
1752 goto out;
1753 }
1754 if (new_state.triggers && !triggers_enabled) {
1755 new_state.mode_bit = KBD_MODE_BIT_TRIGGER;
1756 kbd_set_level(&new_state, kbd_previous_level);
1757 } else if (new_state.triggers == 0) {
1758 kbd_set_level(&new_state, 0);
1759 }
1760 if (!(kbd_info.modes & BIT(new_state.mode_bit))) {
1761 ret = -EINVAL;
1762 goto out;
1763 }
1764 ret = kbd_set_state_safe(&new_state, &state);
1765 if (ret)
1766 goto out;
1767 if (new_state.mode_bit != KBD_MODE_BIT_OFF)
1768 kbd_previous_mode_bit = new_state.mode_bit;
1769 ret = count;
1770out:
1771 mutex_unlock(&kbd_led_mutex);
1772 return ret;
1704} 1773}
1705 1774
1706static ssize_t kbd_led_triggers_show(struct device *dev, 1775static ssize_t kbd_led_triggers_show(struct device *dev,
@@ -1757,12 +1826,16 @@ static ssize_t kbd_led_als_enabled_store(struct device *dev,
1757 if (ret) 1826 if (ret)
1758 return ret; 1827 return ret;
1759 1828
1829 mutex_lock(&kbd_led_mutex);
1830
1760 ret = kbd_get_state(&state); 1831 ret = kbd_get_state(&state);
1761 if (ret) 1832 if (ret)
1762 return ret; 1833 goto out;
1763 1834
1764 if (enable == kbd_is_als_mode_bit(state.mode_bit)) 1835 if (enable == kbd_is_als_mode_bit(state.mode_bit)) {
1765 return count; 1836 ret = count;
1837 goto out;
1838 }
1766 1839
1767 new_state = state; 1840 new_state = state;
1768 1841
@@ -1782,15 +1855,20 @@ static ssize_t kbd_led_als_enabled_store(struct device *dev,
1782 new_state.mode_bit = KBD_MODE_BIT_ON; 1855 new_state.mode_bit = KBD_MODE_BIT_ON;
1783 } 1856 }
1784 } 1857 }
1785 if (!(kbd_info.modes & BIT(new_state.mode_bit))) 1858 if (!(kbd_info.modes & BIT(new_state.mode_bit))) {
1786 return -EINVAL; 1859 ret = -EINVAL;
1860 goto out;
1861 }
1787 1862
1788 ret = kbd_set_state_safe(&new_state, &state); 1863 ret = kbd_set_state_safe(&new_state, &state);
1789 if (ret) 1864 if (ret)
1790 return ret; 1865 goto out;
1791 kbd_previous_mode_bit = new_state.mode_bit; 1866 kbd_previous_mode_bit = new_state.mode_bit;
1792 1867
1793 return count; 1868 ret = count;
1869out:
1870 mutex_unlock(&kbd_led_mutex);
1871 return ret;
1794} 1872}
1795 1873
1796static ssize_t kbd_led_als_enabled_show(struct device *dev, 1874static ssize_t kbd_led_als_enabled_show(struct device *dev,
@@ -1825,18 +1903,23 @@ static ssize_t kbd_led_als_setting_store(struct device *dev,
1825 if (ret) 1903 if (ret)
1826 return ret; 1904 return ret;
1827 1905
1906 mutex_lock(&kbd_led_mutex);
1907
1828 ret = kbd_get_state(&state); 1908 ret = kbd_get_state(&state);
1829 if (ret) 1909 if (ret)
1830 return ret; 1910 goto out;
1831 1911
1832 new_state = state; 1912 new_state = state;
1833 new_state.als_setting = setting; 1913 new_state.als_setting = setting;
1834 1914
1835 ret = kbd_set_state_safe(&new_state, &state); 1915 ret = kbd_set_state_safe(&new_state, &state);
1836 if (ret) 1916 if (ret)
1837 return ret; 1917 goto out;
1838 1918
1839 return count; 1919 ret = count;
1920out:
1921 mutex_unlock(&kbd_led_mutex);
1922 return ret;
1840} 1923}
1841 1924
1842static ssize_t kbd_led_als_setting_show(struct device *dev, 1925static ssize_t kbd_led_als_setting_show(struct device *dev,
@@ -1921,31 +2004,37 @@ static int kbd_led_level_set(struct led_classdev *led_cdev,
1921 u16 num; 2004 u16 num;
1922 int ret; 2005 int ret;
1923 2006
2007 mutex_lock(&kbd_led_mutex);
2008
1924 if (kbd_get_max_level()) { 2009 if (kbd_get_max_level()) {
1925 ret = kbd_get_state(&state); 2010 ret = kbd_get_state(&state);
1926 if (ret) 2011 if (ret)
1927 return ret; 2012 goto out;
1928 new_state = state; 2013 new_state = state;
1929 ret = kbd_set_level(&new_state, value); 2014 ret = kbd_set_level(&new_state, value);
1930 if (ret) 2015 if (ret)
1931 return ret; 2016 goto out;
1932 return kbd_set_state_safe(&new_state, &state); 2017 ret = kbd_set_state_safe(&new_state, &state);
1933 } 2018 } else if (kbd_get_valid_token_counts()) {
1934
1935 if (kbd_get_valid_token_counts()) {
1936 for (num = kbd_token_bits; num != 0 && value > 0; --value) 2019 for (num = kbd_token_bits; num != 0 && value > 0; --value)
1937 num &= num - 1; /* clear the first bit set */ 2020 num &= num - 1; /* clear the first bit set */
1938 if (num == 0) 2021 if (num == 0)
1939 return 0; 2022 ret = 0;
1940 return kbd_set_token_bit(ffs(num) - 1); 2023 else
2024 ret = kbd_set_token_bit(ffs(num) - 1);
2025 } else {
2026 pr_warn("Keyboard brightness level control not supported\n");
2027 ret = -ENXIO;
1941 } 2028 }
1942 2029
1943 pr_warn("Keyboard brightness level control not supported\n"); 2030out:
1944 return -ENXIO; 2031 mutex_unlock(&kbd_led_mutex);
2032 return ret;
1945} 2033}
1946 2034
1947static struct led_classdev kbd_led = { 2035static struct led_classdev kbd_led = {
1948 .name = "dell::kbd_backlight", 2036 .name = "dell::kbd_backlight",
2037 .flags = LED_BRIGHT_HW_CHANGED,
1949 .brightness_set_blocking = kbd_led_level_set, 2038 .brightness_set_blocking = kbd_led_level_set,
1950 .brightness_get = kbd_led_level_get, 2039 .brightness_get = kbd_led_level_get,
1951 .groups = kbd_led_groups, 2040 .groups = kbd_led_groups,
@@ -1953,6 +2042,8 @@ static struct led_classdev kbd_led = {
1953 2042
1954static int __init kbd_led_init(struct device *dev) 2043static int __init kbd_led_init(struct device *dev)
1955{ 2044{
2045 int ret;
2046
1956 kbd_init(); 2047 kbd_init();
1957 if (!kbd_led_present) 2048 if (!kbd_led_present)
1958 return -ENODEV; 2049 return -ENODEV;
@@ -1964,7 +2055,11 @@ static int __init kbd_led_init(struct device *dev)
1964 if (kbd_led.max_brightness) 2055 if (kbd_led.max_brightness)
1965 kbd_led.max_brightness--; 2056 kbd_led.max_brightness--;
1966 } 2057 }
1967 return led_classdev_register(dev, &kbd_led); 2058 ret = led_classdev_register(dev, &kbd_led);
2059 if (ret)
2060 kbd_led_present = false;
2061
2062 return ret;
1968} 2063}
1969 2064
1970static void brightness_set_exit(struct led_classdev *led_cdev, 2065static void brightness_set_exit(struct led_classdev *led_cdev,
@@ -1981,6 +2076,26 @@ static void kbd_led_exit(void)
1981 led_classdev_unregister(&kbd_led); 2076 led_classdev_unregister(&kbd_led);
1982} 2077}
1983 2078
2079static int dell_laptop_notifier_call(struct notifier_block *nb,
2080 unsigned long action, void *data)
2081{
2082 switch (action) {
2083 case DELL_LAPTOP_KBD_BACKLIGHT_BRIGHTNESS_CHANGED:
2084 if (!kbd_led_present)
2085 break;
2086
2087 led_classdev_notify_brightness_hw_changed(&kbd_led,
2088 kbd_led_level_get(&kbd_led));
2089 break;
2090 }
2091
2092 return NOTIFY_OK;
2093}
2094
2095static struct notifier_block dell_laptop_notifier = {
2096 .notifier_call = dell_laptop_notifier_call,
2097};
2098
1984int dell_micmute_led_set(int state) 2099int dell_micmute_led_set(int state)
1985{ 2100{
1986 struct calling_interface_buffer *buffer; 2101 struct calling_interface_buffer *buffer;
@@ -2049,6 +2164,8 @@ static int __init dell_init(void)
2049 debugfs_create_file("rfkill", 0444, dell_laptop_dir, NULL, 2164 debugfs_create_file("rfkill", 0444, dell_laptop_dir, NULL,
2050 &dell_debugfs_fops); 2165 &dell_debugfs_fops);
2051 2166
2167 dell_laptop_register_notifier(&dell_laptop_notifier);
2168
2052 if (acpi_video_get_backlight_type() != acpi_backlight_vendor) 2169 if (acpi_video_get_backlight_type() != acpi_backlight_vendor)
2053 return 0; 2170 return 0;
2054 2171
@@ -2081,11 +2198,17 @@ static int __init dell_init(void)
2081 2198
2082 dell_backlight_device->props.brightness = 2199 dell_backlight_device->props.brightness =
2083 dell_get_intensity(dell_backlight_device); 2200 dell_get_intensity(dell_backlight_device);
2201 if (dell_backlight_device->props.brightness < 0) {
2202 ret = dell_backlight_device->props.brightness;
2203 goto fail_get_brightness;
2204 }
2084 backlight_update_status(dell_backlight_device); 2205 backlight_update_status(dell_backlight_device);
2085 } 2206 }
2086 2207
2087 return 0; 2208 return 0;
2088 2209
2210fail_get_brightness:
2211 backlight_device_unregister(dell_backlight_device);
2089fail_backlight: 2212fail_backlight:
2090 dell_cleanup_rfkill(); 2213 dell_cleanup_rfkill();
2091fail_rfkill: 2214fail_rfkill:
@@ -2100,6 +2223,7 @@ fail_platform_driver:
2100 2223
2101static void __exit dell_exit(void) 2224static void __exit dell_exit(void)
2102{ 2225{
2226 dell_laptop_unregister_notifier(&dell_laptop_notifier);
2103 debugfs_remove_recursive(dell_laptop_dir); 2227 debugfs_remove_recursive(dell_laptop_dir);
2104 if (quirks && quirks->touchpad_led) 2228 if (quirks && quirks->touchpad_led)
2105 touchpad_led_exit(); 2229 touchpad_led_exit();
diff --git a/drivers/platform/x86/dell-smbios.c b/drivers/platform/x86/dell-smbios.c
index d2412ab097da..0a5723468bff 100644
--- a/drivers/platform/x86/dell-smbios.c
+++ b/drivers/platform/x86/dell-smbios.c
@@ -105,6 +105,26 @@ struct calling_interface_token *dell_smbios_find_token(int tokenid)
105} 105}
106EXPORT_SYMBOL_GPL(dell_smbios_find_token); 106EXPORT_SYMBOL_GPL(dell_smbios_find_token);
107 107
108static BLOCKING_NOTIFIER_HEAD(dell_laptop_chain_head);
109
110int dell_laptop_register_notifier(struct notifier_block *nb)
111{
112 return blocking_notifier_chain_register(&dell_laptop_chain_head, nb);
113}
114EXPORT_SYMBOL_GPL(dell_laptop_register_notifier);
115
116int dell_laptop_unregister_notifier(struct notifier_block *nb)
117{
118 return blocking_notifier_chain_unregister(&dell_laptop_chain_head, nb);
119}
120EXPORT_SYMBOL_GPL(dell_laptop_unregister_notifier);
121
122void dell_laptop_call_notifier(unsigned long action, void *data)
123{
124 blocking_notifier_call_chain(&dell_laptop_chain_head, action, data);
125}
126EXPORT_SYMBOL_GPL(dell_laptop_call_notifier);
127
108static void __init parse_da_table(const struct dmi_header *dm) 128static void __init parse_da_table(const struct dmi_header *dm)
109{ 129{
110 /* Final token is a terminator, so we don't want to copy it */ 130 /* Final token is a terminator, so we don't want to copy it */
diff --git a/drivers/platform/x86/dell-smbios.h b/drivers/platform/x86/dell-smbios.h
index ec7d40ae5e6e..45cbc2292cd3 100644
--- a/drivers/platform/x86/dell-smbios.h
+++ b/drivers/platform/x86/dell-smbios.h
@@ -16,6 +16,8 @@
16#ifndef _DELL_SMBIOS_H_ 16#ifndef _DELL_SMBIOS_H_
17#define _DELL_SMBIOS_H_ 17#define _DELL_SMBIOS_H_
18 18
19struct notifier_block;
20
19/* This structure will be modified by the firmware when we enter 21/* This structure will be modified by the firmware when we enter
20 * system management mode, hence the volatiles */ 22 * system management mode, hence the volatiles */
21 23
@@ -43,4 +45,13 @@ void dell_smbios_release_buffer(void);
43void dell_smbios_send_request(int class, int select); 45void dell_smbios_send_request(int class, int select);
44 46
45struct calling_interface_token *dell_smbios_find_token(int tokenid); 47struct calling_interface_token *dell_smbios_find_token(int tokenid);
48
49enum dell_laptop_notifier_actions {
50 DELL_LAPTOP_KBD_BACKLIGHT_BRIGHTNESS_CHANGED,
51};
52
53int dell_laptop_register_notifier(struct notifier_block *nb);
54int dell_laptop_unregister_notifier(struct notifier_block *nb);
55void dell_laptop_call_notifier(unsigned long action, void *data);
56
46#endif 57#endif
diff --git a/drivers/platform/x86/dell-wmi-aio.c b/drivers/platform/x86/dell-wmi-aio.c
index dbc97a33bbc8..50c2078715d6 100644
--- a/drivers/platform/x86/dell-wmi-aio.c
+++ b/drivers/platform/x86/dell-wmi-aio.c
@@ -152,12 +152,10 @@ static int __init dell_wmi_aio_input_setup(void)
152 err = input_register_device(dell_wmi_aio_input_dev); 152 err = input_register_device(dell_wmi_aio_input_dev);
153 if (err) { 153 if (err) {
154 pr_info("Unable to register input device\n"); 154 pr_info("Unable to register input device\n");
155 goto err_free_keymap; 155 goto err_free_dev;
156 } 156 }
157 return 0; 157 return 0;
158 158
159err_free_keymap:
160 sparse_keymap_free(dell_wmi_aio_input_dev);
161err_free_dev: 159err_free_dev:
162 input_free_device(dell_wmi_aio_input_dev); 160 input_free_device(dell_wmi_aio_input_dev);
163 return err; 161 return err;
@@ -192,7 +190,6 @@ static int __init dell_wmi_aio_init(void)
192 err = wmi_install_notify_handler(guid, dell_wmi_aio_notify, NULL); 190 err = wmi_install_notify_handler(guid, dell_wmi_aio_notify, NULL);
193 if (err) { 191 if (err) {
194 pr_err("Unable to register notify handler - %d\n", err); 192 pr_err("Unable to register notify handler - %d\n", err);
195 sparse_keymap_free(dell_wmi_aio_input_dev);
196 input_unregister_device(dell_wmi_aio_input_dev); 193 input_unregister_device(dell_wmi_aio_input_dev);
197 return err; 194 return err;
198 } 195 }
@@ -206,7 +203,6 @@ static void __exit dell_wmi_aio_exit(void)
206 203
207 guid = dell_wmi_aio_find(); 204 guid = dell_wmi_aio_find();
208 wmi_remove_notify_handler(guid); 205 wmi_remove_notify_handler(guid);
209 sparse_keymap_free(dell_wmi_aio_input_dev);
210 input_unregister_device(dell_wmi_aio_input_dev); 206 input_unregister_device(dell_wmi_aio_input_dev);
211} 207}
212 208
diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c
index 75e637047d36..8a64c7967753 100644
--- a/drivers/platform/x86/dell-wmi.c
+++ b/drivers/platform/x86/dell-wmi.c
@@ -329,6 +329,10 @@ static void dell_wmi_process_key(int type, int code)
329 if (type == 0x0000 && code == 0xe025 && !wmi_requires_smbios_request) 329 if (type == 0x0000 && code == 0xe025 && !wmi_requires_smbios_request)
330 return; 330 return;
331 331
332 if (key->keycode == KEY_KBDILLUMTOGGLE)
333 dell_laptop_call_notifier(
334 DELL_LAPTOP_KBD_BACKLIGHT_BRIGHTNESS_CHANGED, NULL);
335
332 sparse_keymap_report_entry(dell_wmi_input_dev, key, 1, true); 336 sparse_keymap_report_entry(dell_wmi_input_dev, key, 1, true);
333} 337}
334 338
@@ -603,23 +607,15 @@ static int __init dell_wmi_input_setup(void)
603 607
604 err = input_register_device(dell_wmi_input_dev); 608 err = input_register_device(dell_wmi_input_dev);
605 if (err) 609 if (err)
606 goto err_free_keymap; 610 goto err_free_dev;
607 611
608 return 0; 612 return 0;
609 613
610 err_free_keymap:
611 sparse_keymap_free(dell_wmi_input_dev);
612 err_free_dev: 614 err_free_dev:
613 input_free_device(dell_wmi_input_dev); 615 input_free_device(dell_wmi_input_dev);
614 return err; 616 return err;
615} 617}
616 618
617static void dell_wmi_input_destroy(void)
618{
619 sparse_keymap_free(dell_wmi_input_dev);
620 input_unregister_device(dell_wmi_input_dev);
621}
622
623/* 619/*
624 * Descriptor buffer is 128 byte long and contains: 620 * Descriptor buffer is 128 byte long and contains:
625 * 621 *
@@ -740,7 +736,7 @@ static int __init dell_wmi_init(void)
740 status = wmi_install_notify_handler(DELL_EVENT_GUID, 736 status = wmi_install_notify_handler(DELL_EVENT_GUID,
741 dell_wmi_notify, NULL); 737 dell_wmi_notify, NULL);
742 if (ACPI_FAILURE(status)) { 738 if (ACPI_FAILURE(status)) {
743 dell_wmi_input_destroy(); 739 input_unregister_device(dell_wmi_input_dev);
744 pr_err("Unable to register notify handler - %d\n", status); 740 pr_err("Unable to register notify handler - %d\n", status);
745 return -ENODEV; 741 return -ENODEV;
746 } 742 }
@@ -752,7 +748,7 @@ static int __init dell_wmi_init(void)
752 if (err) { 748 if (err) {
753 pr_err("Failed to enable WMI events\n"); 749 pr_err("Failed to enable WMI events\n");
754 wmi_remove_notify_handler(DELL_EVENT_GUID); 750 wmi_remove_notify_handler(DELL_EVENT_GUID);
755 dell_wmi_input_destroy(); 751 input_unregister_device(dell_wmi_input_dev);
756 return err; 752 return err;
757 } 753 }
758 } 754 }
@@ -766,6 +762,6 @@ static void __exit dell_wmi_exit(void)
766 if (wmi_requires_smbios_request) 762 if (wmi_requires_smbios_request)
767 dell_wmi_events_set_enabled(false); 763 dell_wmi_events_set_enabled(false);
768 wmi_remove_notify_handler(DELL_EVENT_GUID); 764 wmi_remove_notify_handler(DELL_EVENT_GUID);
769 dell_wmi_input_destroy(); 765 input_unregister_device(dell_wmi_input_dev);
770} 766}
771module_exit(dell_wmi_exit); 767module_exit(dell_wmi_exit);
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c
index 8cdf315f9730..2426399e1e04 100644
--- a/drivers/platform/x86/eeepc-laptop.c
+++ b/drivers/platform/x86/eeepc-laptop.c
@@ -150,6 +150,8 @@ static const struct key_entry eeepc_keymap[] = {
150 { KE_KEY, 0x32, { KEY_SWITCHVIDEOMODE } }, 150 { KE_KEY, 0x32, { KEY_SWITCHVIDEOMODE } },
151 { KE_KEY, 0x37, { KEY_F13 } }, /* Disable Touchpad */ 151 { KE_KEY, 0x37, { KEY_F13 } }, /* Disable Touchpad */
152 { KE_KEY, 0x38, { KEY_F14 } }, 152 { KE_KEY, 0x38, { KEY_F14 } },
153 { KE_IGNORE, 0x50, { KEY_RESERVED } }, /* AC plugged */
154 { KE_IGNORE, 0x51, { KEY_RESERVED } }, /* AC unplugged */
153 { KE_END, 0 }, 155 { KE_END, 0 },
154}; 156};
155 157
@@ -1205,14 +1207,12 @@ static int eeepc_input_init(struct eeepc_laptop *eeepc)
1205 error = input_register_device(input); 1207 error = input_register_device(input);
1206 if (error) { 1208 if (error) {
1207 pr_err("Unable to register input device\n"); 1209 pr_err("Unable to register input device\n");
1208 goto err_free_keymap; 1210 goto err_free_dev;
1209 } 1211 }
1210 1212
1211 eeepc->inputdev = input; 1213 eeepc->inputdev = input;
1212 return 0; 1214 return 0;
1213 1215
1214err_free_keymap:
1215 sparse_keymap_free(input);
1216err_free_dev: 1216err_free_dev:
1217 input_free_device(input); 1217 input_free_device(input);
1218 return error; 1218 return error;
@@ -1220,10 +1220,8 @@ err_free_dev:
1220 1220
1221static void eeepc_input_exit(struct eeepc_laptop *eeepc) 1221static void eeepc_input_exit(struct eeepc_laptop *eeepc)
1222{ 1222{
1223 if (eeepc->inputdev) { 1223 if (eeepc->inputdev)
1224 sparse_keymap_free(eeepc->inputdev);
1225 input_unregister_device(eeepc->inputdev); 1224 input_unregister_device(eeepc->inputdev);
1226 }
1227 eeepc->inputdev = NULL; 1225 eeepc->inputdev = NULL;
1228} 1226}
1229 1227
diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c
index e12cc3504d48..7f49d92914c9 100644
--- a/drivers/platform/x86/fujitsu-laptop.c
+++ b/drivers/platform/x86/fujitsu-laptop.c
@@ -32,18 +32,9 @@
32 * features made available on a range of Fujitsu laptops including the 32 * features made available on a range of Fujitsu laptops including the
33 * P2xxx/P5xxx/S6xxx/S7xxx series. 33 * P2xxx/P5xxx/S6xxx/S7xxx series.
34 * 34 *
35 * This driver exports a few files in /sys/devices/platform/fujitsu-laptop/; 35 * This driver implements a vendor-specific backlight control interface for
36 * others may be added at a later date. 36 * Fujitsu laptops and provides support for hotkeys present on certain Fujitsu
37 * 37 * laptops.
38 * lcd_level - Screen brightness: contains a single integer in the
39 * range 0..7. (rw)
40 *
41 * In addition to these platform device attributes the driver
42 * registers itself in the Linux backlight control subsystem and is
43 * available to userspace under /sys/class/backlight/fujitsu-laptop/.
44 *
45 * Hotkeys present on certain Fujitsu laptops (eg: the S6xxx series) are
46 * also supported by this driver.
47 * 38 *
48 * This driver has been tested on a Fujitsu Lifebook S6410, S7020 and 39 * This driver has been tested on a Fujitsu Lifebook S6410, S7020 and
49 * P8010. It should work on most P-series and S-series Lifebooks, but 40 * P8010. It should work on most P-series and S-series Lifebooks, but
@@ -66,12 +57,11 @@
66#include <linux/backlight.h> 57#include <linux/backlight.h>
67#include <linux/fb.h> 58#include <linux/fb.h>
68#include <linux/input.h> 59#include <linux/input.h>
60#include <linux/input/sparse-keymap.h>
69#include <linux/kfifo.h> 61#include <linux/kfifo.h>
62#include <linux/leds.h>
70#include <linux/platform_device.h> 63#include <linux/platform_device.h>
71#include <linux/slab.h> 64#include <linux/slab.h>
72#if IS_ENABLED(CONFIG_LEDS_CLASS)
73#include <linux/leds.h>
74#endif
75#include <acpi/video.h> 65#include <acpi/video.h>
76 66
77#define FUJITSU_DRIVER_VERSION "0.6.0" 67#define FUJITSU_DRIVER_VERSION "0.6.0"
@@ -102,7 +92,6 @@
102#define FLAG_LID 0x100 92#define FLAG_LID 0x100
103#define FLAG_DOCK 0x200 93#define FLAG_DOCK 0x200
104 94
105#if IS_ENABLED(CONFIG_LEDS_CLASS)
106/* FUNC interface - LED control */ 95/* FUNC interface - LED control */
107#define FUNC_LED_OFF 0x1 96#define FUNC_LED_OFF 0x1
108#define FUNC_LED_ON 0x30001 97#define FUNC_LED_ON 0x30001
@@ -112,7 +101,6 @@
112#define RADIO_LED_ON 0x20 101#define RADIO_LED_ON 0x20
113#define ECO_LED 0x10000 102#define ECO_LED 0x10000
114#define ECO_LED_ON 0x80000 103#define ECO_LED_ON 0x80000
115#endif
116 104
117/* Hotkey details */ 105/* Hotkey details */
118#define KEY1_CODE 0x410 /* codes for the keys in the GIRB register */ 106#define KEY1_CODE 0x410 /* codes for the keys in the GIRB register */
@@ -143,21 +131,16 @@
143/* Device controlling the backlight and associated keys */ 131/* Device controlling the backlight and associated keys */
144struct fujitsu_bl { 132struct fujitsu_bl {
145 acpi_handle acpi_handle; 133 acpi_handle acpi_handle;
146 struct acpi_device *dev;
147 struct input_dev *input; 134 struct input_dev *input;
148 char phys[32]; 135 char phys[32];
149 struct backlight_device *bl_device; 136 struct backlight_device *bl_device;
150 struct platform_device *pf_device;
151 int keycode1, keycode2, keycode3, keycode4, keycode5;
152
153 unsigned int max_brightness; 137 unsigned int max_brightness;
154 unsigned int brightness_changed;
155 unsigned int brightness_level; 138 unsigned int brightness_level;
156}; 139};
157 140
158static struct fujitsu_bl *fujitsu_bl; 141static struct fujitsu_bl *fujitsu_bl;
159static int use_alt_lcd_levels = -1; 142static int use_alt_lcd_levels = -1;
160static int disable_brightness_adjust = -1; 143static bool disable_brightness_adjust;
161 144
162/* Device used to access hotkeys and other features on the laptop */ 145/* Device used to access hotkeys and other features on the laptop */
163struct fujitsu_laptop { 146struct fujitsu_laptop {
@@ -170,247 +153,77 @@ struct fujitsu_laptop {
170 spinlock_t fifo_lock; 153 spinlock_t fifo_lock;
171 int flags_supported; 154 int flags_supported;
172 int flags_state; 155 int flags_state;
173 int logolamp_registered;
174 int kblamps_registered;
175 int radio_led_registered;
176 int eco_led_registered;
177}; 156};
178 157
179static struct fujitsu_laptop *fujitsu_laptop; 158static struct fujitsu_laptop *fujitsu_laptop;
180 159
181#if IS_ENABLED(CONFIG_LEDS_CLASS)
182static enum led_brightness logolamp_get(struct led_classdev *cdev);
183static int logolamp_set(struct led_classdev *cdev,
184 enum led_brightness brightness);
185
186static struct led_classdev logolamp_led = {
187 .name = "fujitsu::logolamp",
188 .brightness_get = logolamp_get,
189 .brightness_set_blocking = logolamp_set
190};
191
192static enum led_brightness kblamps_get(struct led_classdev *cdev);
193static int kblamps_set(struct led_classdev *cdev,
194 enum led_brightness brightness);
195
196static struct led_classdev kblamps_led = {
197 .name = "fujitsu::kblamps",
198 .brightness_get = kblamps_get,
199 .brightness_set_blocking = kblamps_set
200};
201
202static enum led_brightness radio_led_get(struct led_classdev *cdev);
203static int radio_led_set(struct led_classdev *cdev,
204 enum led_brightness brightness);
205
206static struct led_classdev radio_led = {
207 .name = "fujitsu::radio_led",
208 .default_trigger = "rfkill-any",
209 .brightness_get = radio_led_get,
210 .brightness_set_blocking = radio_led_set
211};
212
213static enum led_brightness eco_led_get(struct led_classdev *cdev);
214static int eco_led_set(struct led_classdev *cdev,
215 enum led_brightness brightness);
216
217static struct led_classdev eco_led = {
218 .name = "fujitsu::eco_led",
219 .brightness_get = eco_led_get,
220 .brightness_set_blocking = eco_led_set
221};
222#endif
223
224#ifdef CONFIG_FUJITSU_LAPTOP_DEBUG 160#ifdef CONFIG_FUJITSU_LAPTOP_DEBUG
225static u32 dbg_level = 0x03; 161static u32 dbg_level = 0x03;
226#endif 162#endif
227 163
228/* Fujitsu ACPI interface function */ 164/* Fujitsu ACPI interface function */
229 165
230static int call_fext_func(int cmd, int arg0, int arg1, int arg2) 166static int call_fext_func(int func, int op, int feature, int state)
231{ 167{
232 acpi_status status = AE_OK;
233 union acpi_object params[4] = { 168 union acpi_object params[4] = {
234 { .type = ACPI_TYPE_INTEGER }, 169 { .integer.type = ACPI_TYPE_INTEGER, .integer.value = func },
235 { .type = ACPI_TYPE_INTEGER }, 170 { .integer.type = ACPI_TYPE_INTEGER, .integer.value = op },
236 { .type = ACPI_TYPE_INTEGER }, 171 { .integer.type = ACPI_TYPE_INTEGER, .integer.value = feature },
237 { .type = ACPI_TYPE_INTEGER } 172 { .integer.type = ACPI_TYPE_INTEGER, .integer.value = state }
238 }; 173 };
239 struct acpi_object_list arg_list = { 4, &params[0] }; 174 struct acpi_object_list arg_list = { 4, params };
240 unsigned long long value; 175 unsigned long long value;
241 acpi_handle handle = NULL; 176 acpi_status status;
242
243 status = acpi_get_handle(fujitsu_laptop->acpi_handle, "FUNC", &handle);
244 if (ACPI_FAILURE(status)) {
245 vdbg_printk(FUJLAPTOP_DBG_ERROR,
246 "FUNC interface is not present\n");
247 return -ENODEV;
248 }
249 177
250 params[0].integer.value = cmd; 178 status = acpi_evaluate_integer(fujitsu_laptop->acpi_handle, "FUNC",
251 params[1].integer.value = arg0; 179 &arg_list, &value);
252 params[2].integer.value = arg1;
253 params[3].integer.value = arg2;
254
255 status = acpi_evaluate_integer(handle, NULL, &arg_list, &value);
256 if (ACPI_FAILURE(status)) { 180 if (ACPI_FAILURE(status)) {
257 vdbg_printk(FUJLAPTOP_DBG_WARN, 181 vdbg_printk(FUJLAPTOP_DBG_ERROR, "Failed to evaluate FUNC\n");
258 "FUNC 0x%x (args 0x%x, 0x%x, 0x%x) call failed\n",
259 cmd, arg0, arg1, arg2);
260 return -ENODEV; 182 return -ENODEV;
261 } 183 }
262 184
263 vdbg_printk(FUJLAPTOP_DBG_TRACE, 185 vdbg_printk(FUJLAPTOP_DBG_TRACE, "FUNC 0x%x (args 0x%x, 0x%x, 0x%x) returned 0x%x\n",
264 "FUNC 0x%x (args 0x%x, 0x%x, 0x%x) returned 0x%x\n", 186 func, op, feature, state, (int)value);
265 cmd, arg0, arg1, arg2, (int)value);
266 return value; 187 return value;
267} 188}
268 189
269#if IS_ENABLED(CONFIG_LEDS_CLASS)
270/* LED class callbacks */
271
272static int logolamp_set(struct led_classdev *cdev,
273 enum led_brightness brightness)
274{
275 int poweron = FUNC_LED_ON, always = FUNC_LED_ON;
276 int ret;
277
278 if (brightness < LED_HALF)
279 poweron = FUNC_LED_OFF;
280
281 if (brightness < LED_FULL)
282 always = FUNC_LED_OFF;
283
284 ret = call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_POWERON, poweron);
285 if (ret < 0)
286 return ret;
287
288 return call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_ALWAYS, always);
289}
290
291static int kblamps_set(struct led_classdev *cdev,
292 enum led_brightness brightness)
293{
294 if (brightness >= LED_FULL)
295 return call_fext_func(FUNC_LEDS, 0x1, KEYBOARD_LAMPS, FUNC_LED_ON);
296 else
297 return call_fext_func(FUNC_LEDS, 0x1, KEYBOARD_LAMPS, FUNC_LED_OFF);
298}
299
300static int radio_led_set(struct led_classdev *cdev,
301 enum led_brightness brightness)
302{
303 if (brightness >= LED_FULL)
304 return call_fext_func(FUNC_FLAGS, 0x5, RADIO_LED_ON, RADIO_LED_ON);
305 else
306 return call_fext_func(FUNC_FLAGS, 0x5, RADIO_LED_ON, 0x0);
307}
308
309static int eco_led_set(struct led_classdev *cdev,
310 enum led_brightness brightness)
311{
312 int curr;
313
314 curr = call_fext_func(FUNC_LEDS, 0x2, ECO_LED, 0x0);
315 if (brightness >= LED_FULL)
316 return call_fext_func(FUNC_LEDS, 0x1, ECO_LED, curr | ECO_LED_ON);
317 else
318 return call_fext_func(FUNC_LEDS, 0x1, ECO_LED, curr & ~ECO_LED_ON);
319}
320
321static enum led_brightness logolamp_get(struct led_classdev *cdev)
322{
323 int ret;
324
325 ret = call_fext_func(FUNC_LEDS, 0x2, LOGOLAMP_ALWAYS, 0x0);
326 if (ret == FUNC_LED_ON)
327 return LED_FULL;
328
329 ret = call_fext_func(FUNC_LEDS, 0x2, LOGOLAMP_POWERON, 0x0);
330 if (ret == FUNC_LED_ON)
331 return LED_HALF;
332
333 return LED_OFF;
334}
335
336static enum led_brightness kblamps_get(struct led_classdev *cdev)
337{
338 enum led_brightness brightness = LED_OFF;
339
340 if (call_fext_func(FUNC_LEDS, 0x2, KEYBOARD_LAMPS, 0x0) == FUNC_LED_ON)
341 brightness = LED_FULL;
342
343 return brightness;
344}
345
346static enum led_brightness radio_led_get(struct led_classdev *cdev)
347{
348 enum led_brightness brightness = LED_OFF;
349
350 if (call_fext_func(FUNC_FLAGS, 0x4, 0x0, 0x0) & RADIO_LED_ON)
351 brightness = LED_FULL;
352
353 return brightness;
354}
355
356static enum led_brightness eco_led_get(struct led_classdev *cdev)
357{
358 enum led_brightness brightness = LED_OFF;
359
360 if (call_fext_func(FUNC_LEDS, 0x2, ECO_LED, 0x0) & ECO_LED_ON)
361 brightness = LED_FULL;
362
363 return brightness;
364}
365#endif
366
367/* Hardware access for LCD brightness control */ 190/* Hardware access for LCD brightness control */
368 191
369static int set_lcd_level(int level) 192static int set_lcd_level(int level)
370{ 193{
371 acpi_status status = AE_OK; 194 acpi_status status;
372 acpi_handle handle = NULL; 195 char *method;
373
374 vdbg_printk(FUJLAPTOP_DBG_TRACE, "set lcd level via SBLL [%d]\n",
375 level);
376 196
377 if (level < 0 || level >= fujitsu_bl->max_brightness) 197 switch (use_alt_lcd_levels) {
378 return -EINVAL; 198 case -1:
379 199 if (acpi_has_method(fujitsu_bl->acpi_handle, "SBL2"))
380 status = acpi_get_handle(fujitsu_bl->acpi_handle, "SBLL", &handle); 200 method = "SBL2";
381 if (ACPI_FAILURE(status)) { 201 else
382 vdbg_printk(FUJLAPTOP_DBG_ERROR, "SBLL not present\n"); 202 method = "SBLL";
383 return -ENODEV; 203 break;
204 case 1:
205 method = "SBL2";
206 break;
207 default:
208 method = "SBLL";
209 break;
384 } 210 }
385 211
386 212 vdbg_printk(FUJLAPTOP_DBG_TRACE, "set lcd level via %s [%d]\n",
387 status = acpi_execute_simple_method(handle, NULL, level); 213 method, level);
388 if (ACPI_FAILURE(status))
389 return -ENODEV;
390
391 return 0;
392}
393
394static int set_lcd_level_alt(int level)
395{
396 acpi_status status = AE_OK;
397 acpi_handle handle = NULL;
398
399 vdbg_printk(FUJLAPTOP_DBG_TRACE, "set lcd level via SBL2 [%d]\n",
400 level);
401 214
402 if (level < 0 || level >= fujitsu_bl->max_brightness) 215 if (level < 0 || level >= fujitsu_bl->max_brightness)
403 return -EINVAL; 216 return -EINVAL;
404 217
405 status = acpi_get_handle(fujitsu_bl->acpi_handle, "SBL2", &handle); 218 status = acpi_execute_simple_method(fujitsu_bl->acpi_handle, method,
219 level);
406 if (ACPI_FAILURE(status)) { 220 if (ACPI_FAILURE(status)) {
407 vdbg_printk(FUJLAPTOP_DBG_ERROR, "SBL2 not present\n"); 221 vdbg_printk(FUJLAPTOP_DBG_ERROR, "Failed to evaluate %s\n",
222 method);
408 return -ENODEV; 223 return -ENODEV;
409 } 224 }
410 225
411 status = acpi_execute_simple_method(handle, NULL, level); 226 fujitsu_bl->brightness_level = level;
412 if (ACPI_FAILURE(status))
413 return -ENODEV;
414 227
415 return 0; 228 return 0;
416} 229}
@@ -429,11 +242,6 @@ static int get_lcd_level(void)
429 242
430 fujitsu_bl->brightness_level = state & 0x0fffffff; 243 fujitsu_bl->brightness_level = state & 0x0fffffff;
431 244
432 if (state & 0x80000000)
433 fujitsu_bl->brightness_changed = 1;
434 else
435 fujitsu_bl->brightness_changed = 0;
436
437 return fujitsu_bl->brightness_level; 245 return fujitsu_bl->brightness_level;
438} 246}
439 247
@@ -458,30 +266,17 @@ static int get_max_brightness(void)
458 266
459static int bl_get_brightness(struct backlight_device *b) 267static int bl_get_brightness(struct backlight_device *b)
460{ 268{
461 return get_lcd_level(); 269 return b->props.power == FB_BLANK_POWERDOWN ? 0 : get_lcd_level();
462} 270}
463 271
464static int bl_update_status(struct backlight_device *b) 272static int bl_update_status(struct backlight_device *b)
465{ 273{
466 int ret;
467 if (b->props.power == FB_BLANK_POWERDOWN) 274 if (b->props.power == FB_BLANK_POWERDOWN)
468 ret = call_fext_func(FUNC_BACKLIGHT, 0x1, 0x4, 0x3); 275 call_fext_func(FUNC_BACKLIGHT, 0x1, 0x4, 0x3);
469 else 276 else
470 ret = call_fext_func(FUNC_BACKLIGHT, 0x1, 0x4, 0x0); 277 call_fext_func(FUNC_BACKLIGHT, 0x1, 0x4, 0x0);
471 if (ret != 0) 278
472 vdbg_printk(FUJLAPTOP_DBG_ERROR, 279 return set_lcd_level(b->props.brightness);
473 "Unable to adjust backlight power, error code %i\n",
474 ret);
475
476 if (use_alt_lcd_levels)
477 ret = set_lcd_level_alt(b->props.brightness);
478 else
479 ret = set_lcd_level(b->props.brightness);
480 if (ret != 0)
481 vdbg_printk(FUJLAPTOP_DBG_ERROR,
482 "Unable to adjust LCD brightness, error code %i\n",
483 ret);
484 return ret;
485} 280}
486 281
487static const struct backlight_ops fujitsu_bl_ops = { 282static const struct backlight_ops fujitsu_bl_ops = {
@@ -489,84 +284,8 @@ static const struct backlight_ops fujitsu_bl_ops = {
489 .update_status = bl_update_status, 284 .update_status = bl_update_status,
490}; 285};
491 286
492/* Platform LCD brightness device */ 287static ssize_t lid_show(struct device *dev, struct device_attribute *attr,
493 288 char *buf)
494static ssize_t
495show_max_brightness(struct device *dev,
496 struct device_attribute *attr, char *buf)
497{
498
499 int ret;
500
501 ret = get_max_brightness();
502 if (ret < 0)
503 return ret;
504
505 return sprintf(buf, "%i\n", ret);
506}
507
508static ssize_t
509show_brightness_changed(struct device *dev,
510 struct device_attribute *attr, char *buf)
511{
512
513 int ret;
514
515 ret = fujitsu_bl->brightness_changed;
516 if (ret < 0)
517 return ret;
518
519 return sprintf(buf, "%i\n", ret);
520}
521
522static ssize_t show_lcd_level(struct device *dev,
523 struct device_attribute *attr, char *buf)
524{
525
526 int ret;
527
528 ret = get_lcd_level();
529 if (ret < 0)
530 return ret;
531
532 return sprintf(buf, "%i\n", ret);
533}
534
535static ssize_t store_lcd_level(struct device *dev,
536 struct device_attribute *attr, const char *buf,
537 size_t count)
538{
539
540 int level, ret;
541
542 if (sscanf(buf, "%i", &level) != 1
543 || (level < 0 || level >= fujitsu_bl->max_brightness))
544 return -EINVAL;
545
546 if (use_alt_lcd_levels)
547 ret = set_lcd_level_alt(level);
548 else
549 ret = set_lcd_level(level);
550 if (ret < 0)
551 return ret;
552
553 ret = get_lcd_level();
554 if (ret < 0)
555 return ret;
556
557 return count;
558}
559
560static ssize_t
561ignore_store(struct device *dev,
562 struct device_attribute *attr, const char *buf, size_t count)
563{
564 return count;
565}
566
567static ssize_t
568show_lid_state(struct device *dev,
569 struct device_attribute *attr, char *buf)
570{ 289{
571 if (!(fujitsu_laptop->flags_supported & FLAG_LID)) 290 if (!(fujitsu_laptop->flags_supported & FLAG_LID))
572 return sprintf(buf, "unknown\n"); 291 return sprintf(buf, "unknown\n");
@@ -576,9 +295,8 @@ show_lid_state(struct device *dev,
576 return sprintf(buf, "closed\n"); 295 return sprintf(buf, "closed\n");
577} 296}
578 297
579static ssize_t 298static ssize_t dock_show(struct device *dev, struct device_attribute *attr,
580show_dock_state(struct device *dev, 299 char *buf)
581 struct device_attribute *attr, char *buf)
582{ 300{
583 if (!(fujitsu_laptop->flags_supported & FLAG_DOCK)) 301 if (!(fujitsu_laptop->flags_supported & FLAG_DOCK))
584 return sprintf(buf, "unknown\n"); 302 return sprintf(buf, "unknown\n");
@@ -588,9 +306,8 @@ show_dock_state(struct device *dev,
588 return sprintf(buf, "undocked\n"); 306 return sprintf(buf, "undocked\n");
589} 307}
590 308
591static ssize_t 309static ssize_t radios_show(struct device *dev, struct device_attribute *attr,
592show_radios_state(struct device *dev, 310 char *buf)
593 struct device_attribute *attr, char *buf)
594{ 311{
595 if (!(fujitsu_laptop->flags_supported & FLAG_RFKILL)) 312 if (!(fujitsu_laptop->flags_supported & FLAG_RFKILL))
596 return sprintf(buf, "unknown\n"); 313 return sprintf(buf, "unknown\n");
@@ -600,18 +317,11 @@ show_radios_state(struct device *dev,
600 return sprintf(buf, "killed\n"); 317 return sprintf(buf, "killed\n");
601} 318}
602 319
603static DEVICE_ATTR(max_brightness, 0444, show_max_brightness, ignore_store); 320static DEVICE_ATTR_RO(lid);
604static DEVICE_ATTR(brightness_changed, 0444, show_brightness_changed, 321static DEVICE_ATTR_RO(dock);
605 ignore_store); 322static DEVICE_ATTR_RO(radios);
606static DEVICE_ATTR(lcd_level, 0644, show_lcd_level, store_lcd_level);
607static DEVICE_ATTR(lid, 0444, show_lid_state, ignore_store);
608static DEVICE_ATTR(dock, 0444, show_dock_state, ignore_store);
609static DEVICE_ATTR(radios, 0444, show_radios_state, ignore_store);
610 323
611static struct attribute *fujitsu_pf_attributes[] = { 324static struct attribute *fujitsu_pf_attributes[] = {
612 &dev_attr_brightness_changed.attr,
613 &dev_attr_max_brightness.attr,
614 &dev_attr_lcd_level.attr,
615 &dev_attr_lid.attr, 325 &dev_attr_lid.attr,
616 &dev_attr_dock.attr, 326 &dev_attr_dock.attr,
617 &dev_attr_radios.attr, 327 &dev_attr_radios.attr,
@@ -628,69 +338,66 @@ static struct platform_driver fujitsu_pf_driver = {
628 } 338 }
629}; 339};
630 340
631static void __init dmi_check_cb_common(const struct dmi_system_id *id) 341/* ACPI device for LCD brightness control */
632{
633 pr_info("Identified laptop model '%s'\n", id->ident);
634}
635 342
636static int __init dmi_check_cb_s6410(const struct dmi_system_id *id) 343static const struct key_entry keymap_backlight[] = {
637{ 344 { KE_KEY, true, { KEY_BRIGHTNESSUP } },
638 dmi_check_cb_common(id); 345 { KE_KEY, false, { KEY_BRIGHTNESSDOWN } },
639 fujitsu_bl->keycode1 = KEY_SCREENLOCK; /* "Lock" */ 346 { KE_END, 0 }
640 fujitsu_bl->keycode2 = KEY_HELP; /* "Mobility Center" */ 347};
641 return 1;
642}
643 348
644static int __init dmi_check_cb_s6420(const struct dmi_system_id *id) 349static int acpi_fujitsu_bl_input_setup(struct acpi_device *device)
645{ 350{
646 dmi_check_cb_common(id); 351 struct fujitsu_bl *fujitsu_bl = acpi_driver_data(device);
647 fujitsu_bl->keycode1 = KEY_SCREENLOCK; /* "Lock" */ 352 int ret;
648 fujitsu_bl->keycode2 = KEY_HELP; /* "Mobility Center" */ 353
649 return 1; 354 fujitsu_bl->input = devm_input_allocate_device(&device->dev);
355 if (!fujitsu_bl->input)
356 return -ENOMEM;
357
358 snprintf(fujitsu_bl->phys, sizeof(fujitsu_bl->phys),
359 "%s/video/input0", acpi_device_hid(device));
360
361 fujitsu_bl->input->name = acpi_device_name(device);
362 fujitsu_bl->input->phys = fujitsu_bl->phys;
363 fujitsu_bl->input->id.bustype = BUS_HOST;
364 fujitsu_bl->input->id.product = 0x06;
365
366 ret = sparse_keymap_setup(fujitsu_bl->input, keymap_backlight, NULL);
367 if (ret)
368 return ret;
369
370 return input_register_device(fujitsu_bl->input);
650} 371}
651 372
652static int __init dmi_check_cb_p8010(const struct dmi_system_id *id) 373static int fujitsu_backlight_register(struct acpi_device *device)
653{ 374{
654 dmi_check_cb_common(id); 375 const struct backlight_properties props = {
655 fujitsu_bl->keycode1 = KEY_HELP; /* "Support" */ 376 .brightness = fujitsu_bl->brightness_level,
656 fujitsu_bl->keycode3 = KEY_SWITCHVIDEOMODE; /* "Presentation" */ 377 .max_brightness = fujitsu_bl->max_brightness - 1,
657 fujitsu_bl->keycode4 = KEY_WWW; /* "Internet" */ 378 .type = BACKLIGHT_PLATFORM
658 return 1; 379 };
659} 380 struct backlight_device *bd;
660 381
661static const struct dmi_system_id fujitsu_dmi_table[] __initconst = { 382 bd = devm_backlight_device_register(&device->dev, "fujitsu-laptop",
662 { 383 &device->dev, NULL,
663 .ident = "Fujitsu Siemens S6410", 384 &fujitsu_bl_ops, &props);
664 .matches = { 385 if (IS_ERR(bd))
665 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), 386 return PTR_ERR(bd);
666 DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK S6410"),
667 },
668 .callback = dmi_check_cb_s6410},
669 {
670 .ident = "Fujitsu Siemens S6420",
671 .matches = {
672 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
673 DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK S6420"),
674 },
675 .callback = dmi_check_cb_s6420},
676 {
677 .ident = "Fujitsu LifeBook P8010",
678 .matches = {
679 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
680 DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook P8010"),
681 },
682 .callback = dmi_check_cb_p8010},
683 {}
684};
685 387
686/* ACPI device for LCD brightness control */ 388 fujitsu_bl->bl_device = bd;
389
390 return 0;
391}
687 392
688static int acpi_fujitsu_bl_add(struct acpi_device *device) 393static int acpi_fujitsu_bl_add(struct acpi_device *device)
689{ 394{
690 int state = 0; 395 int state = 0;
691 struct input_dev *input;
692 int error; 396 int error;
693 397
398 if (acpi_video_get_backlight_type() != acpi_backlight_vendor)
399 return -ENODEV;
400
694 if (!device) 401 if (!device)
695 return -EINVAL; 402 return -EINVAL;
696 403
@@ -699,41 +406,20 @@ static int acpi_fujitsu_bl_add(struct acpi_device *device)
699 sprintf(acpi_device_class(device), "%s", ACPI_FUJITSU_CLASS); 406 sprintf(acpi_device_class(device), "%s", ACPI_FUJITSU_CLASS);
700 device->driver_data = fujitsu_bl; 407 device->driver_data = fujitsu_bl;
701 408
702 fujitsu_bl->input = input = input_allocate_device(); 409 error = acpi_fujitsu_bl_input_setup(device);
703 if (!input) {
704 error = -ENOMEM;
705 goto err_stop;
706 }
707
708 snprintf(fujitsu_bl->phys, sizeof(fujitsu_bl->phys),
709 "%s/video/input0", acpi_device_hid(device));
710
711 input->name = acpi_device_name(device);
712 input->phys = fujitsu_bl->phys;
713 input->id.bustype = BUS_HOST;
714 input->id.product = 0x06;
715 input->dev.parent = &device->dev;
716 input->evbit[0] = BIT(EV_KEY);
717 set_bit(KEY_BRIGHTNESSUP, input->keybit);
718 set_bit(KEY_BRIGHTNESSDOWN, input->keybit);
719 set_bit(KEY_UNKNOWN, input->keybit);
720
721 error = input_register_device(input);
722 if (error) 410 if (error)
723 goto err_free_input_dev; 411 return error;
724 412
725 error = acpi_bus_update_power(fujitsu_bl->acpi_handle, &state); 413 error = acpi_bus_update_power(fujitsu_bl->acpi_handle, &state);
726 if (error) { 414 if (error) {
727 pr_err("Error reading power state\n"); 415 pr_err("Error reading power state\n");
728 goto err_unregister_input_dev; 416 return error;
729 } 417 }
730 418
731 pr_info("ACPI: %s [%s] (%s)\n", 419 pr_info("ACPI: %s [%s] (%s)\n",
732 acpi_device_name(device), acpi_device_bid(device), 420 acpi_device_name(device), acpi_device_bid(device),
733 !device->power.state ? "on" : "off"); 421 !device->power.state ? "on" : "off");
734 422
735 fujitsu_bl->dev = device;
736
737 if (acpi_has_method(device->handle, METHOD_NAME__INI)) { 423 if (acpi_has_method(device->handle, METHOD_NAME__INI)) {
738 vdbg_printk(FUJLAPTOP_DBG_INFO, "Invoking _INI\n"); 424 vdbg_printk(FUJLAPTOP_DBG_INFO, "Invoking _INI\n");
739 if (ACPI_FAILURE 425 if (ACPI_FAILURE
@@ -742,45 +428,13 @@ static int acpi_fujitsu_bl_add(struct acpi_device *device)
742 pr_err("_INI Method failed\n"); 428 pr_err("_INI Method failed\n");
743 } 429 }
744 430
745 if (use_alt_lcd_levels == -1) {
746 if (acpi_has_method(NULL, "\\_SB.PCI0.LPCB.FJEX.SBL2"))
747 use_alt_lcd_levels = 1;
748 else
749 use_alt_lcd_levels = 0;
750 vdbg_printk(FUJLAPTOP_DBG_TRACE, "auto-detected usealt as %i\n",
751 use_alt_lcd_levels);
752 }
753
754 /* do config (detect defaults) */
755 use_alt_lcd_levels = use_alt_lcd_levels == 1 ? 1 : 0;
756 disable_brightness_adjust = disable_brightness_adjust == 1 ? 1 : 0;
757 vdbg_printk(FUJLAPTOP_DBG_INFO,
758 "config: [alt interface: %d], [adjust disable: %d]\n",
759 use_alt_lcd_levels, disable_brightness_adjust);
760
761 if (get_max_brightness() <= 0) 431 if (get_max_brightness() <= 0)
762 fujitsu_bl->max_brightness = FUJITSU_LCD_N_LEVELS; 432 fujitsu_bl->max_brightness = FUJITSU_LCD_N_LEVELS;
763 get_lcd_level(); 433 get_lcd_level();
764 434
765 return 0; 435 error = fujitsu_backlight_register(device);
766 436 if (error)
767err_unregister_input_dev: 437 return error;
768 input_unregister_device(input);
769 input = NULL;
770err_free_input_dev:
771 input_free_device(input);
772err_stop:
773 return error;
774}
775
776static int acpi_fujitsu_bl_remove(struct acpi_device *device)
777{
778 struct fujitsu_bl *fujitsu_bl = acpi_driver_data(device);
779 struct input_dev *input = fujitsu_bl->input;
780
781 input_unregister_device(input);
782
783 fujitsu_bl->acpi_handle = NULL;
784 438
785 return 0; 439 return 0;
786} 440}
@@ -790,62 +444,332 @@ static int acpi_fujitsu_bl_remove(struct acpi_device *device)
790static void acpi_fujitsu_bl_notify(struct acpi_device *device, u32 event) 444static void acpi_fujitsu_bl_notify(struct acpi_device *device, u32 event)
791{ 445{
792 struct input_dev *input; 446 struct input_dev *input;
793 int keycode;
794 int oldb, newb; 447 int oldb, newb;
795 448
796 input = fujitsu_bl->input; 449 input = fujitsu_bl->input;
797 450
798 switch (event) { 451 if (event != ACPI_FUJITSU_NOTIFY_CODE1) {
799 case ACPI_FUJITSU_NOTIFY_CODE1:
800 keycode = 0;
801 oldb = fujitsu_bl->brightness_level;
802 get_lcd_level();
803 newb = fujitsu_bl->brightness_level;
804
805 vdbg_printk(FUJLAPTOP_DBG_TRACE,
806 "brightness button event [%i -> %i (%i)]\n",
807 oldb, newb, fujitsu_bl->brightness_changed);
808
809 if (oldb < newb) {
810 if (disable_brightness_adjust != 1) {
811 if (use_alt_lcd_levels)
812 set_lcd_level_alt(newb);
813 else
814 set_lcd_level(newb);
815 }
816 keycode = KEY_BRIGHTNESSUP;
817 } else if (oldb > newb) {
818 if (disable_brightness_adjust != 1) {
819 if (use_alt_lcd_levels)
820 set_lcd_level_alt(newb);
821 else
822 set_lcd_level(newb);
823 }
824 keycode = KEY_BRIGHTNESSDOWN;
825 }
826 break;
827 default:
828 keycode = KEY_UNKNOWN;
829 vdbg_printk(FUJLAPTOP_DBG_WARN, 452 vdbg_printk(FUJLAPTOP_DBG_WARN,
830 "unsupported event [0x%x]\n", event); 453 "unsupported event [0x%x]\n", event);
831 break; 454 sparse_keymap_report_event(input, -1, 1, true);
455 return;
832 } 456 }
833 457
834 if (keycode != 0) { 458 oldb = fujitsu_bl->brightness_level;
835 input_report_key(input, keycode, 1); 459 get_lcd_level();
836 input_sync(input); 460 newb = fujitsu_bl->brightness_level;
837 input_report_key(input, keycode, 0); 461
838 input_sync(input); 462 vdbg_printk(FUJLAPTOP_DBG_TRACE, "brightness button event [%i -> %i]\n",
839 } 463 oldb, newb);
464
465 if (oldb == newb)
466 return;
467
468 if (!disable_brightness_adjust)
469 set_lcd_level(newb);
470
471 sparse_keymap_report_event(input, oldb < newb, 1, true);
840} 472}
841 473
842/* ACPI device for hotkey handling */ 474/* ACPI device for hotkey handling */
843 475
476static const struct key_entry keymap_default[] = {
477 { KE_KEY, KEY1_CODE, { KEY_PROG1 } },
478 { KE_KEY, KEY2_CODE, { KEY_PROG2 } },
479 { KE_KEY, KEY3_CODE, { KEY_PROG3 } },
480 { KE_KEY, KEY4_CODE, { KEY_PROG4 } },
481 { KE_KEY, KEY5_CODE, { KEY_RFKILL } },
482 { KE_KEY, BIT(26), { KEY_TOUCHPAD_TOGGLE } },
483 { KE_END, 0 }
484};
485
486static const struct key_entry keymap_s64x0[] = {
487 { KE_KEY, KEY1_CODE, { KEY_SCREENLOCK } }, /* "Lock" */
488 { KE_KEY, KEY2_CODE, { KEY_HELP } }, /* "Mobility Center */
489 { KE_KEY, KEY3_CODE, { KEY_PROG3 } },
490 { KE_KEY, KEY4_CODE, { KEY_PROG4 } },
491 { KE_END, 0 }
492};
493
494static const struct key_entry keymap_p8010[] = {
495 { KE_KEY, KEY1_CODE, { KEY_HELP } }, /* "Support" */
496 { KE_KEY, KEY2_CODE, { KEY_PROG2 } },
497 { KE_KEY, KEY3_CODE, { KEY_SWITCHVIDEOMODE } }, /* "Presentation" */
498 { KE_KEY, KEY4_CODE, { KEY_WWW } }, /* "WWW" */
499 { KE_END, 0 }
500};
501
502static const struct key_entry *keymap = keymap_default;
503
504static int fujitsu_laptop_dmi_keymap_override(const struct dmi_system_id *id)
505{
506 pr_info("Identified laptop model '%s'\n", id->ident);
507 keymap = id->driver_data;
508 return 1;
509}
510
511static const struct dmi_system_id fujitsu_laptop_dmi_table[] = {
512 {
513 .callback = fujitsu_laptop_dmi_keymap_override,
514 .ident = "Fujitsu Siemens S6410",
515 .matches = {
516 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
517 DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK S6410"),
518 },
519 .driver_data = (void *)keymap_s64x0
520 },
521 {
522 .callback = fujitsu_laptop_dmi_keymap_override,
523 .ident = "Fujitsu Siemens S6420",
524 .matches = {
525 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
526 DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK S6420"),
527 },
528 .driver_data = (void *)keymap_s64x0
529 },
530 {
531 .callback = fujitsu_laptop_dmi_keymap_override,
532 .ident = "Fujitsu LifeBook P8010",
533 .matches = {
534 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
535 DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook P8010"),
536 },
537 .driver_data = (void *)keymap_p8010
538 },
539 {}
540};
541
542static int acpi_fujitsu_laptop_input_setup(struct acpi_device *device)
543{
544 struct fujitsu_laptop *fujitsu_laptop = acpi_driver_data(device);
545 int ret;
546
547 fujitsu_laptop->input = devm_input_allocate_device(&device->dev);
548 if (!fujitsu_laptop->input)
549 return -ENOMEM;
550
551 snprintf(fujitsu_laptop->phys, sizeof(fujitsu_laptop->phys),
552 "%s/video/input0", acpi_device_hid(device));
553
554 fujitsu_laptop->input->name = acpi_device_name(device);
555 fujitsu_laptop->input->phys = fujitsu_laptop->phys;
556 fujitsu_laptop->input->id.bustype = BUS_HOST;
557 fujitsu_laptop->input->id.product = 0x06;
558
559 dmi_check_system(fujitsu_laptop_dmi_table);
560 ret = sparse_keymap_setup(fujitsu_laptop->input, keymap, NULL);
561 if (ret)
562 return ret;
563
564 return input_register_device(fujitsu_laptop->input);
565}
566
567static int fujitsu_laptop_platform_add(void)
568{
569 int ret;
570
571 fujitsu_laptop->pf_device = platform_device_alloc("fujitsu-laptop", -1);
572 if (!fujitsu_laptop->pf_device)
573 return -ENOMEM;
574
575 ret = platform_device_add(fujitsu_laptop->pf_device);
576 if (ret)
577 goto err_put_platform_device;
578
579 ret = sysfs_create_group(&fujitsu_laptop->pf_device->dev.kobj,
580 &fujitsu_pf_attribute_group);
581 if (ret)
582 goto err_del_platform_device;
583
584 return 0;
585
586err_del_platform_device:
587 platform_device_del(fujitsu_laptop->pf_device);
588err_put_platform_device:
589 platform_device_put(fujitsu_laptop->pf_device);
590
591 return ret;
592}
593
594static void fujitsu_laptop_platform_remove(void)
595{
596 sysfs_remove_group(&fujitsu_laptop->pf_device->dev.kobj,
597 &fujitsu_pf_attribute_group);
598 platform_device_unregister(fujitsu_laptop->pf_device);
599}
600
601static int logolamp_set(struct led_classdev *cdev,
602 enum led_brightness brightness)
603{
604 int poweron = FUNC_LED_ON, always = FUNC_LED_ON;
605 int ret;
606
607 if (brightness < LED_HALF)
608 poweron = FUNC_LED_OFF;
609
610 if (brightness < LED_FULL)
611 always = FUNC_LED_OFF;
612
613 ret = call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_POWERON, poweron);
614 if (ret < 0)
615 return ret;
616
617 return call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_ALWAYS, always);
618}
619
620static enum led_brightness logolamp_get(struct led_classdev *cdev)
621{
622 int ret;
623
624 ret = call_fext_func(FUNC_LEDS, 0x2, LOGOLAMP_ALWAYS, 0x0);
625 if (ret == FUNC_LED_ON)
626 return LED_FULL;
627
628 ret = call_fext_func(FUNC_LEDS, 0x2, LOGOLAMP_POWERON, 0x0);
629 if (ret == FUNC_LED_ON)
630 return LED_HALF;
631
632 return LED_OFF;
633}
634
635static struct led_classdev logolamp_led = {
636 .name = "fujitsu::logolamp",
637 .brightness_set_blocking = logolamp_set,
638 .brightness_get = logolamp_get
639};
640
641static int kblamps_set(struct led_classdev *cdev,
642 enum led_brightness brightness)
643{
644 if (brightness >= LED_FULL)
645 return call_fext_func(FUNC_LEDS, 0x1, KEYBOARD_LAMPS,
646 FUNC_LED_ON);
647 else
648 return call_fext_func(FUNC_LEDS, 0x1, KEYBOARD_LAMPS,
649 FUNC_LED_OFF);
650}
651
652static enum led_brightness kblamps_get(struct led_classdev *cdev)
653{
654 enum led_brightness brightness = LED_OFF;
655
656 if (call_fext_func(FUNC_LEDS, 0x2, KEYBOARD_LAMPS, 0x0) == FUNC_LED_ON)
657 brightness = LED_FULL;
658
659 return brightness;
660}
661
662static struct led_classdev kblamps_led = {
663 .name = "fujitsu::kblamps",
664 .brightness_set_blocking = kblamps_set,
665 .brightness_get = kblamps_get
666};
667
668static int radio_led_set(struct led_classdev *cdev,
669 enum led_brightness brightness)
670{
671 if (brightness >= LED_FULL)
672 return call_fext_func(FUNC_FLAGS, 0x5, RADIO_LED_ON,
673 RADIO_LED_ON);
674 else
675 return call_fext_func(FUNC_FLAGS, 0x5, RADIO_LED_ON, 0x0);
676}
677
678static enum led_brightness radio_led_get(struct led_classdev *cdev)
679{
680 enum led_brightness brightness = LED_OFF;
681
682 if (call_fext_func(FUNC_FLAGS, 0x4, 0x0, 0x0) & RADIO_LED_ON)
683 brightness = LED_FULL;
684
685 return brightness;
686}
687
688static struct led_classdev radio_led = {
689 .name = "fujitsu::radio_led",
690 .brightness_set_blocking = radio_led_set,
691 .brightness_get = radio_led_get,
692 .default_trigger = "rfkill-any"
693};
694
695static int eco_led_set(struct led_classdev *cdev,
696 enum led_brightness brightness)
697{
698 int curr;
699
700 curr = call_fext_func(FUNC_LEDS, 0x2, ECO_LED, 0x0);
701 if (brightness >= LED_FULL)
702 return call_fext_func(FUNC_LEDS, 0x1, ECO_LED,
703 curr | ECO_LED_ON);
704 else
705 return call_fext_func(FUNC_LEDS, 0x1, ECO_LED,
706 curr & ~ECO_LED_ON);
707}
708
709static enum led_brightness eco_led_get(struct led_classdev *cdev)
710{
711 enum led_brightness brightness = LED_OFF;
712
713 if (call_fext_func(FUNC_LEDS, 0x2, ECO_LED, 0x0) & ECO_LED_ON)
714 brightness = LED_FULL;
715
716 return brightness;
717}
718
719static struct led_classdev eco_led = {
720 .name = "fujitsu::eco_led",
721 .brightness_set_blocking = eco_led_set,
722 .brightness_get = eco_led_get
723};
724
725static int acpi_fujitsu_laptop_leds_register(struct acpi_device *device)
726{
727 int result;
728
729 if (call_fext_func(FUNC_LEDS, 0x0, 0x0, 0x0) & LOGOLAMP_POWERON) {
730 result = devm_led_classdev_register(&device->dev,
731 &logolamp_led);
732 if (result)
733 return result;
734 }
735
736 if ((call_fext_func(FUNC_LEDS, 0x0, 0x0, 0x0) & KEYBOARD_LAMPS) &&
737 (call_fext_func(FUNC_BUTTONS, 0x0, 0x0, 0x0) == 0x0)) {
738 result = devm_led_classdev_register(&device->dev, &kblamps_led);
739 if (result)
740 return result;
741 }
742
743 /*
744 * BTNI bit 24 seems to indicate the presence of a radio toggle
745 * button in place of a slide switch, and all such machines appear
746 * to also have an RF LED. Therefore use bit 24 as an indicator
747 * that an RF LED is present.
748 */
749 if (call_fext_func(FUNC_BUTTONS, 0x0, 0x0, 0x0) & BIT(24)) {
750 result = devm_led_classdev_register(&device->dev, &radio_led);
751 if (result)
752 return result;
753 }
754
755 /* Support for eco led is not always signaled in bit corresponding
756 * to the bit used to control the led. According to the DSDT table,
757 * bit 14 seems to indicate presence of said led as well.
758 * Confirm by testing the status.
759 */
760 if ((call_fext_func(FUNC_LEDS, 0x0, 0x0, 0x0) & BIT(14)) &&
761 (call_fext_func(FUNC_LEDS, 0x2, ECO_LED, 0x0) != UNSUPPORTED_CMD)) {
762 result = devm_led_classdev_register(&device->dev, &eco_led);
763 if (result)
764 return result;
765 }
766
767 return 0;
768}
769
844static int acpi_fujitsu_laptop_add(struct acpi_device *device) 770static int acpi_fujitsu_laptop_add(struct acpi_device *device)
845{ 771{
846 int result = 0;
847 int state = 0; 772 int state = 0;
848 struct input_dev *input;
849 int error; 773 int error;
850 int i; 774 int i;
851 775
@@ -867,38 +791,14 @@ static int acpi_fujitsu_laptop_add(struct acpi_device *device)
867 goto err_stop; 791 goto err_stop;
868 } 792 }
869 793
870 fujitsu_laptop->input = input = input_allocate_device(); 794 error = acpi_fujitsu_laptop_input_setup(device);
871 if (!input) {
872 error = -ENOMEM;
873 goto err_free_fifo;
874 }
875
876 snprintf(fujitsu_laptop->phys, sizeof(fujitsu_laptop->phys),
877 "%s/video/input0", acpi_device_hid(device));
878
879 input->name = acpi_device_name(device);
880 input->phys = fujitsu_laptop->phys;
881 input->id.bustype = BUS_HOST;
882 input->id.product = 0x06;
883 input->dev.parent = &device->dev;
884
885 set_bit(EV_KEY, input->evbit);
886 set_bit(fujitsu_bl->keycode1, input->keybit);
887 set_bit(fujitsu_bl->keycode2, input->keybit);
888 set_bit(fujitsu_bl->keycode3, input->keybit);
889 set_bit(fujitsu_bl->keycode4, input->keybit);
890 set_bit(fujitsu_bl->keycode5, input->keybit);
891 set_bit(KEY_TOUCHPAD_TOGGLE, input->keybit);
892 set_bit(KEY_UNKNOWN, input->keybit);
893
894 error = input_register_device(input);
895 if (error) 795 if (error)
896 goto err_free_input_dev; 796 goto err_free_fifo;
897 797
898 error = acpi_bus_update_power(fujitsu_laptop->acpi_handle, &state); 798 error = acpi_bus_update_power(fujitsu_laptop->acpi_handle, &state);
899 if (error) { 799 if (error) {
900 pr_err("Error reading power state\n"); 800 pr_err("Error reading power state\n");
901 goto err_unregister_input_dev; 801 goto err_free_fifo;
902 } 802 }
903 803
904 pr_info("ACPI: %s [%s] (%s)\n", 804 pr_info("ACPI: %s [%s] (%s)\n",
@@ -936,72 +836,25 @@ static int acpi_fujitsu_laptop_add(struct acpi_device *device)
936 /* Suspect this is a keymap of the application panel, print it */ 836 /* Suspect this is a keymap of the application panel, print it */
937 pr_info("BTNI: [0x%x]\n", call_fext_func(FUNC_BUTTONS, 0x0, 0x0, 0x0)); 837 pr_info("BTNI: [0x%x]\n", call_fext_func(FUNC_BUTTONS, 0x0, 0x0, 0x0));
938 838
939#if IS_ENABLED(CONFIG_LEDS_CLASS) 839 /* Sync backlight power status */
940 if (call_fext_func(FUNC_LEDS, 0x0, 0x0, 0x0) & LOGOLAMP_POWERON) { 840 if (fujitsu_bl->bl_device &&
941 result = led_classdev_register(&fujitsu_bl->pf_device->dev, 841 acpi_video_get_backlight_type() == acpi_backlight_vendor) {
942 &logolamp_led); 842 if (call_fext_func(FUNC_BACKLIGHT, 0x2, 0x4, 0x0) == 3)
943 if (result == 0) { 843 fujitsu_bl->bl_device->props.power = FB_BLANK_POWERDOWN;
944 fujitsu_laptop->logolamp_registered = 1; 844 else
945 } else { 845 fujitsu_bl->bl_device->props.power = FB_BLANK_UNBLANK;
946 pr_err("Could not register LED handler for logo lamp, error %i\n",
947 result);
948 }
949 }
950
951 if ((call_fext_func(FUNC_LEDS, 0x0, 0x0, 0x0) & KEYBOARD_LAMPS) &&
952 (call_fext_func(FUNC_BUTTONS, 0x0, 0x0, 0x0) == 0x0)) {
953 result = led_classdev_register(&fujitsu_bl->pf_device->dev,
954 &kblamps_led);
955 if (result == 0) {
956 fujitsu_laptop->kblamps_registered = 1;
957 } else {
958 pr_err("Could not register LED handler for keyboard lamps, error %i\n",
959 result);
960 }
961 } 846 }
962 847
963 /* 848 error = acpi_fujitsu_laptop_leds_register(device);
964 * BTNI bit 24 seems to indicate the presence of a radio toggle 849 if (error)
965 * button in place of a slide switch, and all such machines appear 850 goto err_free_fifo;
966 * to also have an RF LED. Therefore use bit 24 as an indicator
967 * that an RF LED is present.
968 */
969 if (call_fext_func(FUNC_BUTTONS, 0x0, 0x0, 0x0) & BIT(24)) {
970 result = led_classdev_register(&fujitsu_bl->pf_device->dev,
971 &radio_led);
972 if (result == 0) {
973 fujitsu_laptop->radio_led_registered = 1;
974 } else {
975 pr_err("Could not register LED handler for radio LED, error %i\n",
976 result);
977 }
978 }
979 851
980 /* Support for eco led is not always signaled in bit corresponding 852 error = fujitsu_laptop_platform_add();
981 * to the bit used to control the led. According to the DSDT table, 853 if (error)
982 * bit 14 seems to indicate presence of said led as well. 854 goto err_free_fifo;
983 * Confirm by testing the status.
984 */
985 if ((call_fext_func(FUNC_LEDS, 0x0, 0x0, 0x0) & BIT(14)) &&
986 (call_fext_func(FUNC_LEDS, 0x2, ECO_LED, 0x0) != UNSUPPORTED_CMD)) {
987 result = led_classdev_register(&fujitsu_bl->pf_device->dev,
988 &eco_led);
989 if (result == 0) {
990 fujitsu_laptop->eco_led_registered = 1;
991 } else {
992 pr_err("Could not register LED handler for eco LED, error %i\n",
993 result);
994 }
995 }
996#endif
997 855
998 return result; 856 return 0;
999 857
1000err_unregister_input_dev:
1001 input_unregister_device(input);
1002 input = NULL;
1003err_free_input_dev:
1004 input_free_device(input);
1005err_free_fifo: 858err_free_fifo:
1006 kfifo_free(&fujitsu_laptop->fifo); 859 kfifo_free(&fujitsu_laptop->fifo);
1007err_stop: 860err_stop:
@@ -1011,86 +864,62 @@ err_stop:
1011static int acpi_fujitsu_laptop_remove(struct acpi_device *device) 864static int acpi_fujitsu_laptop_remove(struct acpi_device *device)
1012{ 865{
1013 struct fujitsu_laptop *fujitsu_laptop = acpi_driver_data(device); 866 struct fujitsu_laptop *fujitsu_laptop = acpi_driver_data(device);
1014 struct input_dev *input = fujitsu_laptop->input;
1015
1016#if IS_ENABLED(CONFIG_LEDS_CLASS)
1017 if (fujitsu_laptop->logolamp_registered)
1018 led_classdev_unregister(&logolamp_led);
1019
1020 if (fujitsu_laptop->kblamps_registered)
1021 led_classdev_unregister(&kblamps_led);
1022 867
1023 if (fujitsu_laptop->radio_led_registered) 868 fujitsu_laptop_platform_remove();
1024 led_classdev_unregister(&radio_led);
1025
1026 if (fujitsu_laptop->eco_led_registered)
1027 led_classdev_unregister(&eco_led);
1028#endif
1029
1030 input_unregister_device(input);
1031 869
1032 kfifo_free(&fujitsu_laptop->fifo); 870 kfifo_free(&fujitsu_laptop->fifo);
1033 871
1034 fujitsu_laptop->acpi_handle = NULL;
1035
1036 return 0; 872 return 0;
1037} 873}
1038 874
1039static void acpi_fujitsu_laptop_press(int keycode) 875static void acpi_fujitsu_laptop_press(int scancode)
1040{ 876{
1041 struct input_dev *input = fujitsu_laptop->input; 877 struct input_dev *input = fujitsu_laptop->input;
1042 int status; 878 int status;
1043 879
1044 status = kfifo_in_locked(&fujitsu_laptop->fifo, 880 status = kfifo_in_locked(&fujitsu_laptop->fifo,
1045 (unsigned char *)&keycode, sizeof(keycode), 881 (unsigned char *)&scancode, sizeof(scancode),
1046 &fujitsu_laptop->fifo_lock); 882 &fujitsu_laptop->fifo_lock);
1047 if (status != sizeof(keycode)) { 883 if (status != sizeof(scancode)) {
1048 vdbg_printk(FUJLAPTOP_DBG_WARN, 884 vdbg_printk(FUJLAPTOP_DBG_WARN,
1049 "Could not push keycode [0x%x]\n", keycode); 885 "Could not push scancode [0x%x]\n", scancode);
1050 return; 886 return;
1051 } 887 }
1052 input_report_key(input, keycode, 1); 888 sparse_keymap_report_event(input, scancode, 1, false);
1053 input_sync(input);
1054 vdbg_printk(FUJLAPTOP_DBG_TRACE, 889 vdbg_printk(FUJLAPTOP_DBG_TRACE,
1055 "Push keycode into ringbuffer [%d]\n", keycode); 890 "Push scancode into ringbuffer [0x%x]\n", scancode);
1056} 891}
1057 892
1058static void acpi_fujitsu_laptop_release(void) 893static void acpi_fujitsu_laptop_release(void)
1059{ 894{
1060 struct input_dev *input = fujitsu_laptop->input; 895 struct input_dev *input = fujitsu_laptop->input;
1061 int keycode, status; 896 int scancode, status;
1062 897
1063 while (true) { 898 while (true) {
1064 status = kfifo_out_locked(&fujitsu_laptop->fifo, 899 status = kfifo_out_locked(&fujitsu_laptop->fifo,
1065 (unsigned char *)&keycode, 900 (unsigned char *)&scancode,
1066 sizeof(keycode), 901 sizeof(scancode),
1067 &fujitsu_laptop->fifo_lock); 902 &fujitsu_laptop->fifo_lock);
1068 if (status != sizeof(keycode)) 903 if (status != sizeof(scancode))
1069 return; 904 return;
1070 input_report_key(input, keycode, 0); 905 sparse_keymap_report_event(input, scancode, 0, false);
1071 input_sync(input);
1072 vdbg_printk(FUJLAPTOP_DBG_TRACE, 906 vdbg_printk(FUJLAPTOP_DBG_TRACE,
1073 "Pop keycode from ringbuffer [%d]\n", keycode); 907 "Pop scancode from ringbuffer [0x%x]\n", scancode);
1074 } 908 }
1075} 909}
1076 910
1077static void acpi_fujitsu_laptop_notify(struct acpi_device *device, u32 event) 911static void acpi_fujitsu_laptop_notify(struct acpi_device *device, u32 event)
1078{ 912{
1079 struct input_dev *input; 913 struct input_dev *input;
1080 int keycode; 914 int scancode, i = 0;
1081 unsigned int irb = 1; 915 unsigned int irb;
1082 int i;
1083 916
1084 input = fujitsu_laptop->input; 917 input = fujitsu_laptop->input;
1085 918
1086 if (event != ACPI_FUJITSU_NOTIFY_CODE1) { 919 if (event != ACPI_FUJITSU_NOTIFY_CODE1) {
1087 keycode = KEY_UNKNOWN;
1088 vdbg_printk(FUJLAPTOP_DBG_WARN, 920 vdbg_printk(FUJLAPTOP_DBG_WARN,
1089 "Unsupported event [0x%x]\n", event); 921 "Unsupported event [0x%x]\n", event);
1090 input_report_key(input, keycode, 1); 922 sparse_keymap_report_event(input, -1, 1, true);
1091 input_sync(input);
1092 input_report_key(input, keycode, 0);
1093 input_sync(input);
1094 return; 923 return;
1095 } 924 }
1096 925
@@ -1098,40 +927,16 @@ static void acpi_fujitsu_laptop_notify(struct acpi_device *device, u32 event)
1098 fujitsu_laptop->flags_state = 927 fujitsu_laptop->flags_state =
1099 call_fext_func(FUNC_FLAGS, 0x4, 0x0, 0x0); 928 call_fext_func(FUNC_FLAGS, 0x4, 0x0, 0x0);
1100 929
1101 i = 0; 930 while ((irb = call_fext_func(FUNC_BUTTONS, 0x1, 0x0, 0x0)) != 0 &&
1102 while ((irb = 931 i++ < MAX_HOTKEY_RINGBUFFER_SIZE) {
1103 call_fext_func(FUNC_BUTTONS, 0x1, 0x0, 0x0)) != 0 932 scancode = irb & 0x4ff;
1104 && (i++) < MAX_HOTKEY_RINGBUFFER_SIZE) { 933 if (sparse_keymap_entry_from_scancode(input, scancode))
1105 switch (irb & 0x4ff) { 934 acpi_fujitsu_laptop_press(scancode);
1106 case KEY1_CODE: 935 else if (scancode == 0)
1107 keycode = fujitsu_bl->keycode1; 936 acpi_fujitsu_laptop_release();
1108 break; 937 else
1109 case KEY2_CODE:
1110 keycode = fujitsu_bl->keycode2;
1111 break;
1112 case KEY3_CODE:
1113 keycode = fujitsu_bl->keycode3;
1114 break;
1115 case KEY4_CODE:
1116 keycode = fujitsu_bl->keycode4;
1117 break;
1118 case KEY5_CODE:
1119 keycode = fujitsu_bl->keycode5;
1120 break;
1121 case 0:
1122 keycode = 0;
1123 break;
1124 default:
1125 vdbg_printk(FUJLAPTOP_DBG_WARN, 938 vdbg_printk(FUJLAPTOP_DBG_WARN,
1126 "Unknown GIRB result [%x]\n", irb); 939 "Unknown GIRB result [%x]\n", irb);
1127 keycode = -1;
1128 break;
1129 }
1130
1131 if (keycode > 0)
1132 acpi_fujitsu_laptop_press(keycode);
1133 else if (keycode == 0)
1134 acpi_fujitsu_laptop_release();
1135 } 940 }
1136 941
1137 /* On some models (first seen on the Skylake-based Lifebook 942 /* On some models (first seen on the Skylake-based Lifebook
@@ -1139,14 +944,8 @@ static void acpi_fujitsu_laptop_notify(struct acpi_device *device, u32 event)
1139 * handled in software; its state is queried using FUNC_FLAGS 944 * handled in software; its state is queried using FUNC_FLAGS
1140 */ 945 */
1141 if ((fujitsu_laptop->flags_supported & BIT(26)) && 946 if ((fujitsu_laptop->flags_supported & BIT(26)) &&
1142 (call_fext_func(FUNC_FLAGS, 0x1, 0x0, 0x0) & BIT(26))) { 947 (call_fext_func(FUNC_FLAGS, 0x1, 0x0, 0x0) & BIT(26)))
1143 keycode = KEY_TOUCHPAD_TOGGLE; 948 sparse_keymap_report_event(input, BIT(26), 1, true);
1144 input_report_key(input, keycode, 1);
1145 input_sync(input);
1146 input_report_key(input, keycode, 0);
1147 input_sync(input);
1148 }
1149
1150} 949}
1151 950
1152/* Initialization */ 951/* Initialization */
@@ -1162,7 +961,6 @@ static struct acpi_driver acpi_fujitsu_bl_driver = {
1162 .ids = fujitsu_bl_device_ids, 961 .ids = fujitsu_bl_device_ids,
1163 .ops = { 962 .ops = {
1164 .add = acpi_fujitsu_bl_add, 963 .add = acpi_fujitsu_bl_add,
1165 .remove = acpi_fujitsu_bl_remove,
1166 .notify = acpi_fujitsu_bl_notify, 964 .notify = acpi_fujitsu_bl_notify,
1167 }, 965 },
1168}; 966};
@@ -1192,7 +990,7 @@ MODULE_DEVICE_TABLE(acpi, fujitsu_ids);
1192 990
1193static int __init fujitsu_init(void) 991static int __init fujitsu_init(void)
1194{ 992{
1195 int ret, max_brightness; 993 int ret;
1196 994
1197 if (acpi_disabled) 995 if (acpi_disabled)
1198 return -ENODEV; 996 return -ENODEV;
@@ -1200,100 +998,40 @@ static int __init fujitsu_init(void)
1200 fujitsu_bl = kzalloc(sizeof(struct fujitsu_bl), GFP_KERNEL); 998 fujitsu_bl = kzalloc(sizeof(struct fujitsu_bl), GFP_KERNEL);
1201 if (!fujitsu_bl) 999 if (!fujitsu_bl)
1202 return -ENOMEM; 1000 return -ENOMEM;
1203 fujitsu_bl->keycode1 = KEY_PROG1;
1204 fujitsu_bl->keycode2 = KEY_PROG2;
1205 fujitsu_bl->keycode3 = KEY_PROG3;
1206 fujitsu_bl->keycode4 = KEY_PROG4;
1207 fujitsu_bl->keycode5 = KEY_RFKILL;
1208 dmi_check_system(fujitsu_dmi_table);
1209 1001
1210 ret = acpi_bus_register_driver(&acpi_fujitsu_bl_driver); 1002 ret = acpi_bus_register_driver(&acpi_fujitsu_bl_driver);
1211 if (ret) 1003 if (ret)
1212 goto fail_acpi; 1004 goto err_free_fujitsu_bl;
1213 1005
1214 /* Register platform stuff */ 1006 /* Register platform stuff */
1215 1007
1216 fujitsu_bl->pf_device = platform_device_alloc("fujitsu-laptop", -1);
1217 if (!fujitsu_bl->pf_device) {
1218 ret = -ENOMEM;
1219 goto fail_platform_driver;
1220 }
1221
1222 ret = platform_device_add(fujitsu_bl->pf_device);
1223 if (ret)
1224 goto fail_platform_device1;
1225
1226 ret =
1227 sysfs_create_group(&fujitsu_bl->pf_device->dev.kobj,
1228 &fujitsu_pf_attribute_group);
1229 if (ret)
1230 goto fail_platform_device2;
1231
1232 /* Register backlight stuff */
1233
1234 if (acpi_video_get_backlight_type() == acpi_backlight_vendor) {
1235 struct backlight_properties props;
1236
1237 memset(&props, 0, sizeof(struct backlight_properties));
1238 max_brightness = fujitsu_bl->max_brightness;
1239 props.type = BACKLIGHT_PLATFORM;
1240 props.max_brightness = max_brightness - 1;
1241 fujitsu_bl->bl_device = backlight_device_register("fujitsu-laptop",
1242 NULL, NULL,
1243 &fujitsu_bl_ops,
1244 &props);
1245 if (IS_ERR(fujitsu_bl->bl_device)) {
1246 ret = PTR_ERR(fujitsu_bl->bl_device);
1247 fujitsu_bl->bl_device = NULL;
1248 goto fail_sysfs_group;
1249 }
1250 fujitsu_bl->bl_device->props.brightness = fujitsu_bl->brightness_level;
1251 }
1252
1253 ret = platform_driver_register(&fujitsu_pf_driver); 1008 ret = platform_driver_register(&fujitsu_pf_driver);
1254 if (ret) 1009 if (ret)
1255 goto fail_backlight; 1010 goto err_unregister_acpi;
1256 1011
1257 /* Register laptop driver */ 1012 /* Register laptop driver */
1258 1013
1259 fujitsu_laptop = kzalloc(sizeof(struct fujitsu_laptop), GFP_KERNEL); 1014 fujitsu_laptop = kzalloc(sizeof(struct fujitsu_laptop), GFP_KERNEL);
1260 if (!fujitsu_laptop) { 1015 if (!fujitsu_laptop) {
1261 ret = -ENOMEM; 1016 ret = -ENOMEM;
1262 goto fail_laptop; 1017 goto err_unregister_platform_driver;
1263 } 1018 }
1264 1019
1265 ret = acpi_bus_register_driver(&acpi_fujitsu_laptop_driver); 1020 ret = acpi_bus_register_driver(&acpi_fujitsu_laptop_driver);
1266 if (ret) 1021 if (ret)
1267 goto fail_laptop1; 1022 goto err_free_fujitsu_laptop;
1268
1269 /* Sync backlight power status (needs FUJ02E3 device, hence deferred) */
1270 if (acpi_video_get_backlight_type() == acpi_backlight_vendor) {
1271 if (call_fext_func(FUNC_BACKLIGHT, 0x2, 0x4, 0x0) == 3)
1272 fujitsu_bl->bl_device->props.power = FB_BLANK_POWERDOWN;
1273 else
1274 fujitsu_bl->bl_device->props.power = FB_BLANK_UNBLANK;
1275 }
1276 1023
1277 pr_info("driver " FUJITSU_DRIVER_VERSION " successfully loaded\n"); 1024 pr_info("driver " FUJITSU_DRIVER_VERSION " successfully loaded\n");
1278 1025
1279 return 0; 1026 return 0;
1280 1027
1281fail_laptop1: 1028err_free_fujitsu_laptop:
1282 kfree(fujitsu_laptop); 1029 kfree(fujitsu_laptop);
1283fail_laptop: 1030err_unregister_platform_driver:
1284 platform_driver_unregister(&fujitsu_pf_driver); 1031 platform_driver_unregister(&fujitsu_pf_driver);
1285fail_backlight: 1032err_unregister_acpi:
1286 backlight_device_unregister(fujitsu_bl->bl_device);
1287fail_sysfs_group:
1288 sysfs_remove_group(&fujitsu_bl->pf_device->dev.kobj,
1289 &fujitsu_pf_attribute_group);
1290fail_platform_device2:
1291 platform_device_del(fujitsu_bl->pf_device);
1292fail_platform_device1:
1293 platform_device_put(fujitsu_bl->pf_device);
1294fail_platform_driver:
1295 acpi_bus_unregister_driver(&acpi_fujitsu_bl_driver); 1033 acpi_bus_unregister_driver(&acpi_fujitsu_bl_driver);
1296fail_acpi: 1034err_free_fujitsu_bl:
1297 kfree(fujitsu_bl); 1035 kfree(fujitsu_bl);
1298 1036
1299 return ret; 1037 return ret;
@@ -1307,13 +1045,6 @@ static void __exit fujitsu_cleanup(void)
1307 1045
1308 platform_driver_unregister(&fujitsu_pf_driver); 1046 platform_driver_unregister(&fujitsu_pf_driver);
1309 1047
1310 backlight_device_unregister(fujitsu_bl->bl_device);
1311
1312 sysfs_remove_group(&fujitsu_bl->pf_device->dev.kobj,
1313 &fujitsu_pf_attribute_group);
1314
1315 platform_device_unregister(fujitsu_bl->pf_device);
1316
1317 acpi_bus_unregister_driver(&acpi_fujitsu_bl_driver); 1048 acpi_bus_unregister_driver(&acpi_fujitsu_bl_driver);
1318 1049
1319 kfree(fujitsu_bl); 1050 kfree(fujitsu_bl);
@@ -1324,11 +1055,10 @@ static void __exit fujitsu_cleanup(void)
1324module_init(fujitsu_init); 1055module_init(fujitsu_init);
1325module_exit(fujitsu_cleanup); 1056module_exit(fujitsu_cleanup);
1326 1057
1327module_param(use_alt_lcd_levels, uint, 0644); 1058module_param(use_alt_lcd_levels, int, 0644);
1328MODULE_PARM_DESC(use_alt_lcd_levels, 1059MODULE_PARM_DESC(use_alt_lcd_levels, "Interface used for setting LCD brightness level (-1 = auto, 0 = force SBLL, 1 = force SBL2)");
1329 "Use alternative interface for lcd_levels (needed for Lifebook s6410)."); 1060module_param(disable_brightness_adjust, bool, 0644);
1330module_param(disable_brightness_adjust, uint, 0644); 1061MODULE_PARM_DESC(disable_brightness_adjust, "Disable LCD brightness adjustment");
1331MODULE_PARM_DESC(disable_brightness_adjust, "Disable brightness adjustment .");
1332#ifdef CONFIG_FUJITSU_LAPTOP_DEBUG 1062#ifdef CONFIG_FUJITSU_LAPTOP_DEBUG
1333module_param_named(debug, dbg_level, uint, 0644); 1063module_param_named(debug, dbg_level, uint, 0644);
1334MODULE_PARM_DESC(debug, "Sets debug level bit-mask"); 1064MODULE_PARM_DESC(debug, "Sets debug level bit-mask");
diff --git a/drivers/platform/x86/hp-wireless.c b/drivers/platform/x86/hp-wireless.c
index 988eedbd7c63..d6ea5e998fb8 100644
--- a/drivers/platform/x86/hp-wireless.c
+++ b/drivers/platform/x86/hp-wireless.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * hp-wireless button for Windows 8 2 * Airplane mode button for HP & Xiaomi laptops
3 * 3 *
4 * Copyright (C) 2014 Alex Hung <alex.hung@canonical.com> 4 * Copyright (C) 2014-2017 Alex Hung <alex.hung@canonical.com>
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by 7 * it under the terms of the GNU General Public License as published by
@@ -29,11 +29,13 @@
29MODULE_LICENSE("GPL"); 29MODULE_LICENSE("GPL");
30MODULE_AUTHOR("Alex Hung"); 30MODULE_AUTHOR("Alex Hung");
31MODULE_ALIAS("acpi*:HPQ6001:*"); 31MODULE_ALIAS("acpi*:HPQ6001:*");
32MODULE_ALIAS("acpi*:WSTADEF:*");
32 33
33static struct input_dev *hpwl_input_dev; 34static struct input_dev *hpwl_input_dev;
34 35
35static const struct acpi_device_id hpwl_ids[] = { 36static const struct acpi_device_id hpwl_ids[] = {
36 {"HPQ6001", 0}, 37 {"HPQ6001", 0},
38 {"WSTADEF", 0},
37 {"", 0}, 39 {"", 0},
38}; 40};
39 41
@@ -108,23 +110,4 @@ static struct acpi_driver hpwl_driver = {
108 }, 110 },
109}; 111};
110 112
111static int __init hpwl_init(void) 113module_acpi_driver(hpwl_driver);
112{
113 int err;
114
115 pr_info("Initializing HPQ6001 module\n");
116 err = acpi_bus_register_driver(&hpwl_driver);
117 if (err)
118 pr_err("Unable to register HP wireless control driver.\n");
119
120 return err;
121}
122
123static void __exit hpwl_exit(void)
124{
125 pr_info("Exiting HPQ6001 module\n");
126 acpi_bus_unregister_driver(&hpwl_driver);
127}
128
129module_init(hpwl_init);
130module_exit(hpwl_exit);
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c
index 96ffda493266..0df4209648d1 100644
--- a/drivers/platform/x86/hp-wmi.c
+++ b/drivers/platform/x86/hp-wmi.c
@@ -48,41 +48,29 @@ MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4");
48#define HPWMI_EVENT_GUID "95F24279-4D7B-4334-9387-ACCDC67EF61C" 48#define HPWMI_EVENT_GUID "95F24279-4D7B-4334-9387-ACCDC67EF61C"
49#define HPWMI_BIOS_GUID "5FB7F034-2C63-45e9-BE91-3D44E2C707E4" 49#define HPWMI_BIOS_GUID "5FB7F034-2C63-45e9-BE91-3D44E2C707E4"
50 50
51#define HPWMI_DISPLAY_QUERY 0x1
52#define HPWMI_HDDTEMP_QUERY 0x2
53#define HPWMI_ALS_QUERY 0x3
54#define HPWMI_HARDWARE_QUERY 0x4
55#define HPWMI_WIRELESS_QUERY 0x5
56#define HPWMI_BIOS_QUERY 0x9
57#define HPWMI_FEATURE_QUERY 0xb
58#define HPWMI_HOTKEY_QUERY 0xc
59#define HPWMI_FEATURE2_QUERY 0xd
60#define HPWMI_WIRELESS2_QUERY 0x1b
61#define HPWMI_POSTCODEERROR_QUERY 0x2a
62
63enum hp_wmi_radio { 51enum hp_wmi_radio {
64 HPWMI_WIFI = 0, 52 HPWMI_WIFI = 0x0,
65 HPWMI_BLUETOOTH = 1, 53 HPWMI_BLUETOOTH = 0x1,
66 HPWMI_WWAN = 2, 54 HPWMI_WWAN = 0x2,
67 HPWMI_GPS = 3, 55 HPWMI_GPS = 0x3,
68}; 56};
69 57
70enum hp_wmi_event_ids { 58enum hp_wmi_event_ids {
71 HPWMI_DOCK_EVENT = 1, 59 HPWMI_DOCK_EVENT = 0x01,
72 HPWMI_PARK_HDD = 2, 60 HPWMI_PARK_HDD = 0x02,
73 HPWMI_SMART_ADAPTER = 3, 61 HPWMI_SMART_ADAPTER = 0x03,
74 HPWMI_BEZEL_BUTTON = 4, 62 HPWMI_BEZEL_BUTTON = 0x04,
75 HPWMI_WIRELESS = 5, 63 HPWMI_WIRELESS = 0x05,
76 HPWMI_CPU_BATTERY_THROTTLE = 6, 64 HPWMI_CPU_BATTERY_THROTTLE = 0x06,
77 HPWMI_LOCK_SWITCH = 7, 65 HPWMI_LOCK_SWITCH = 0x07,
78 HPWMI_LID_SWITCH = 8, 66 HPWMI_LID_SWITCH = 0x08,
79 HPWMI_SCREEN_ROTATION = 9, 67 HPWMI_SCREEN_ROTATION = 0x09,
80 HPWMI_COOLSENSE_SYSTEM_MOBILE = 0x0A, 68 HPWMI_COOLSENSE_SYSTEM_MOBILE = 0x0A,
81 HPWMI_COOLSENSE_SYSTEM_HOT = 0x0B, 69 HPWMI_COOLSENSE_SYSTEM_HOT = 0x0B,
82 HPWMI_PROXIMITY_SENSOR = 0x0C, 70 HPWMI_PROXIMITY_SENSOR = 0x0C,
83 HPWMI_BACKLIT_KB_BRIGHTNESS = 0x0D, 71 HPWMI_BACKLIT_KB_BRIGHTNESS = 0x0D,
84 HPWMI_PEAKSHIFT_PERIOD = 0x0F, 72 HPWMI_PEAKSHIFT_PERIOD = 0x0F,
85 HPWMI_BATTERY_CHARGE_PERIOD = 0x10, 73 HPWMI_BATTERY_CHARGE_PERIOD = 0x10,
86}; 74};
87 75
88struct bios_args { 76struct bios_args {
@@ -93,6 +81,39 @@ struct bios_args {
93 u32 data; 81 u32 data;
94}; 82};
95 83
84enum hp_wmi_commandtype {
85 HPWMI_DISPLAY_QUERY = 0x01,
86 HPWMI_HDDTEMP_QUERY = 0x02,
87 HPWMI_ALS_QUERY = 0x03,
88 HPWMI_HARDWARE_QUERY = 0x04,
89 HPWMI_WIRELESS_QUERY = 0x05,
90 HPWMI_BATTERY_QUERY = 0x07,
91 HPWMI_BIOS_QUERY = 0x09,
92 HPWMI_FEATURE_QUERY = 0x0b,
93 HPWMI_HOTKEY_QUERY = 0x0c,
94 HPWMI_FEATURE2_QUERY = 0x0d,
95 HPWMI_WIRELESS2_QUERY = 0x1b,
96 HPWMI_POSTCODEERROR_QUERY = 0x2a,
97};
98
99enum hp_wmi_command {
100 HPWMI_READ = 0x01,
101 HPWMI_WRITE = 0x02,
102 HPWMI_ODM = 0x03,
103};
104
105enum hp_wmi_hardware_mask {
106 HPWMI_DOCK_MASK = 0x01,
107 HPWMI_TABLET_MASK = 0x04,
108};
109
110#define BIOS_ARGS_INIT(write, ctype, size) \
111 (struct bios_args) { .signature = 0x55434553, \
112 .command = (write) ? 0x2 : 0x1, \
113 .commandtype = (ctype), \
114 .datasize = (size), \
115 .data = 0 }
116
96struct bios_return { 117struct bios_return {
97 u32 sigpass; 118 u32 sigpass;
98 u32 return_code; 119 u32 return_code;
@@ -170,8 +191,8 @@ static struct rfkill2_device rfkill2[HPWMI_MAX_RFKILL2_DEVICES];
170/* 191/*
171 * hp_wmi_perform_query 192 * hp_wmi_perform_query
172 * 193 *
173 * query: The commandtype -> What should be queried 194 * query: The commandtype (enum hp_wmi_commandtype)
174 * write: The command -> 0 read, 1 write, 3 ODM specific 195 * write: The command (enum hp_wmi_command)
175 * buffer: Buffer used as input and/or output 196 * buffer: Buffer used as input and/or output
176 * insize: Size of input buffer 197 * insize: Size of input buffer
177 * outsize: Size of output buffer 198 * outsize: Size of output buffer
@@ -182,27 +203,27 @@ static struct rfkill2_device rfkill2[HPWMI_MAX_RFKILL2_DEVICES];
182 * -EINVAL if the output buffer size exceeds buffersize 203 * -EINVAL if the output buffer size exceeds buffersize
183 * 204 *
184 * Note: The buffersize must at least be the maximum of the input and output 205 * Note: The buffersize must at least be the maximum of the input and output
185 * size. E.g. Battery info query (0x7) is defined to have 1 byte input 206 * size. E.g. Battery info query is defined to have 1 byte input
186 * and 128 byte output. The caller would do: 207 * and 128 byte output. The caller would do:
187 * buffer = kzalloc(128, GFP_KERNEL); 208 * buffer = kzalloc(128, GFP_KERNEL);
188 * ret = hp_wmi_perform_query(0x7, 0, buffer, 1, 128) 209 * ret = hp_wmi_perform_query(HPWMI_BATTERY_QUERY, HPWMI_READ, buffer, 1, 128)
189 */ 210 */
190static int hp_wmi_perform_query(int query, int write, void *buffer, 211static int hp_wmi_perform_query(int query, enum hp_wmi_command command,
191 int insize, int outsize) 212 void *buffer, int insize, int outsize)
192{ 213{
193 struct bios_return *bios_return; 214 struct bios_return *bios_return;
194 int actual_outsize; 215 int actual_outsize;
195 union acpi_object *obj; 216 union acpi_object *obj;
196 struct bios_args args = { 217 struct bios_args args = {
197 .signature = 0x55434553, 218 .signature = 0x55434553,
198 .command = write ? 0x2 : 0x1, 219 .command = command,
199 .commandtype = query, 220 .commandtype = query,
200 .datasize = insize, 221 .datasize = insize,
201 .data = 0, 222 .data = 0,
202 }; 223 };
203 struct acpi_buffer input = { sizeof(struct bios_args), &args }; 224 struct acpi_buffer input = { sizeof(struct bios_args), &args };
204 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; 225 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
205 u32 rc; 226 int ret = 0;
206 227
207 if (WARN_ON(insize > sizeof(args.data))) 228 if (WARN_ON(insize > sizeof(args.data)))
208 return -EINVAL; 229 return -EINVAL;
@@ -214,91 +235,61 @@ static int hp_wmi_perform_query(int query, int write, void *buffer,
214 235
215 if (!obj) 236 if (!obj)
216 return -EINVAL; 237 return -EINVAL;
217 else if (obj->type != ACPI_TYPE_BUFFER) { 238
218 kfree(obj); 239 if (obj->type != ACPI_TYPE_BUFFER) {
219 return -EINVAL; 240 ret = -EINVAL;
241 goto out_free;
220 } 242 }
221 243
222 bios_return = (struct bios_return *)obj->buffer.pointer; 244 bios_return = (struct bios_return *)obj->buffer.pointer;
223 rc = bios_return->return_code; 245 ret = bios_return->return_code;
224 246
225 if (rc) { 247 if (ret) {
226 if (rc != HPWMI_RET_UNKNOWN_CMDTYPE) 248 if (ret != HPWMI_RET_UNKNOWN_CMDTYPE)
227 pr_warn("query 0x%x returned error 0x%x\n", query, rc); 249 pr_warn("query 0x%x returned error 0x%x\n", query, ret);
228 kfree(obj); 250 goto out_free;
229 return rc;
230 } 251 }
231 252
232 if (!outsize) { 253 /* Ignore output data of zero size */
233 /* ignore output data */ 254 if (!outsize)
234 kfree(obj); 255 goto out_free;
235 return 0;
236 }
237 256
238 actual_outsize = min(outsize, (int)(obj->buffer.length - sizeof(*bios_return))); 257 actual_outsize = min(outsize, (int)(obj->buffer.length - sizeof(*bios_return)));
239 memcpy(buffer, obj->buffer.pointer + sizeof(*bios_return), actual_outsize); 258 memcpy(buffer, obj->buffer.pointer + sizeof(*bios_return), actual_outsize);
240 memset(buffer + actual_outsize, 0, outsize - actual_outsize); 259 memset(buffer + actual_outsize, 0, outsize - actual_outsize);
260
261out_free:
241 kfree(obj); 262 kfree(obj);
242 return 0; 263 return ret;
243} 264}
244 265
245static int hp_wmi_display_state(void) 266static int hp_wmi_read_int(int query)
246{ 267{
247 int state = 0; 268 int val = 0, ret;
248 int ret = hp_wmi_perform_query(HPWMI_DISPLAY_QUERY, 0, &state,
249 sizeof(state), sizeof(state));
250 if (ret)
251 return -EINVAL;
252 return state;
253}
254 269
255static int hp_wmi_hddtemp_state(void) 270 ret = hp_wmi_perform_query(query, HPWMI_READ, &val,
256{ 271 sizeof(val), sizeof(val));
257 int state = 0;
258 int ret = hp_wmi_perform_query(HPWMI_HDDTEMP_QUERY, 0, &state,
259 sizeof(state), sizeof(state));
260 if (ret)
261 return -EINVAL;
262 return state;
263}
264 272
265static int hp_wmi_als_state(void)
266{
267 int state = 0;
268 int ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, 0, &state,
269 sizeof(state), sizeof(state));
270 if (ret) 273 if (ret)
271 return -EINVAL; 274 return ret < 0 ? ret : -EINVAL;
272 return state; 275
276 return val;
273} 277}
274 278
275static int hp_wmi_dock_state(void) 279static int hp_wmi_hw_state(int mask)
276{ 280{
277 int state = 0; 281 int state = hp_wmi_read_int(HPWMI_HARDWARE_QUERY);
278 int ret = hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, 0, &state,
279 sizeof(state), sizeof(state));
280 282
281 if (ret) 283 if (state < 0)
282 return -EINVAL; 284 return state;
283 285
284 return state & 0x1; 286 return state & 0x1;
285} 287}
286 288
287static int hp_wmi_tablet_state(void)
288{
289 int state = 0;
290 int ret = hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, 0, &state,
291 sizeof(state), sizeof(state));
292 if (ret)
293 return ret;
294
295 return (state & 0x4) ? 1 : 0;
296}
297
298static int __init hp_wmi_bios_2008_later(void) 289static int __init hp_wmi_bios_2008_later(void)
299{ 290{
300 int state = 0; 291 int state = 0;
301 int ret = hp_wmi_perform_query(HPWMI_FEATURE_QUERY, 0, &state, 292 int ret = hp_wmi_perform_query(HPWMI_FEATURE_QUERY, HPWMI_READ, &state,
302 sizeof(state), sizeof(state)); 293 sizeof(state), sizeof(state));
303 if (!ret) 294 if (!ret)
304 return 1; 295 return 1;
@@ -309,7 +300,7 @@ static int __init hp_wmi_bios_2008_later(void)
309static int __init hp_wmi_bios_2009_later(void) 300static int __init hp_wmi_bios_2009_later(void)
310{ 301{
311 int state = 0; 302 int state = 0;
312 int ret = hp_wmi_perform_query(HPWMI_FEATURE2_QUERY, 0, &state, 303 int ret = hp_wmi_perform_query(HPWMI_FEATURE2_QUERY, HPWMI_READ, &state,
313 sizeof(state), sizeof(state)); 304 sizeof(state), sizeof(state));
314 if (!ret) 305 if (!ret)
315 return 1; 306 return 1;
@@ -320,11 +311,10 @@ static int __init hp_wmi_bios_2009_later(void)
320static int __init hp_wmi_enable_hotkeys(void) 311static int __init hp_wmi_enable_hotkeys(void)
321{ 312{
322 int value = 0x6e; 313 int value = 0x6e;
323 int ret = hp_wmi_perform_query(HPWMI_BIOS_QUERY, 1, &value, 314 int ret = hp_wmi_perform_query(HPWMI_BIOS_QUERY, HPWMI_WRITE, &value,
324 sizeof(value), 0); 315 sizeof(value), 0);
325 if (ret) 316
326 return -EINVAL; 317 return ret <= 0 ? ret : -EINVAL;
327 return 0;
328} 318}
329 319
330static int hp_wmi_set_block(void *data, bool blocked) 320static int hp_wmi_set_block(void *data, bool blocked)
@@ -333,11 +323,10 @@ static int hp_wmi_set_block(void *data, bool blocked)
333 int query = BIT(r + 8) | ((!blocked) << r); 323 int query = BIT(r + 8) | ((!blocked) << r);
334 int ret; 324 int ret;
335 325
336 ret = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, 326 ret = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, HPWMI_WRITE,
337 &query, sizeof(query), 0); 327 &query, sizeof(query), 0);
338 if (ret) 328
339 return -EINVAL; 329 return ret <= 0 ? ret : -EINVAL;
340 return 0;
341} 330}
342 331
343static const struct rfkill_ops hp_wmi_rfkill_ops = { 332static const struct rfkill_ops hp_wmi_rfkill_ops = {
@@ -346,47 +335,38 @@ static const struct rfkill_ops hp_wmi_rfkill_ops = {
346 335
347static bool hp_wmi_get_sw_state(enum hp_wmi_radio r) 336static bool hp_wmi_get_sw_state(enum hp_wmi_radio r)
348{ 337{
349 int wireless = 0; 338 int mask = 0x200 << (r * 8);
350 int mask;
351 hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0,
352 &wireless, sizeof(wireless),
353 sizeof(wireless));
354 /* TBD: Pass error */
355 339
356 mask = 0x200 << (r * 8); 340 int wireless = hp_wmi_read_int(HPWMI_WIRELESS_QUERY);
357 341
358 if (wireless & mask) 342 /* TBD: Pass error */
359 return false; 343 WARN_ONCE(wireless < 0, "error executing HPWMI_WIRELESS_QUERY");
360 else 344
361 return true; 345 return !(wireless & mask);
362} 346}
363 347
364static bool hp_wmi_get_hw_state(enum hp_wmi_radio r) 348static bool hp_wmi_get_hw_state(enum hp_wmi_radio r)
365{ 349{
366 int wireless = 0; 350 int mask = 0x800 << (r * 8);
367 int mask;
368 hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0,
369 &wireless, sizeof(wireless),
370 sizeof(wireless));
371 /* TBD: Pass error */
372 351
373 mask = 0x800 << (r * 8); 352 int wireless = hp_wmi_read_int(HPWMI_WIRELESS_QUERY);
374 353
375 if (wireless & mask) 354 /* TBD: Pass error */
376 return false; 355 WARN_ONCE(wireless < 0, "error executing HPWMI_WIRELESS_QUERY");
377 else 356
378 return true; 357 return !(wireless & mask);
379} 358}
380 359
381static int hp_wmi_rfkill2_set_block(void *data, bool blocked) 360static int hp_wmi_rfkill2_set_block(void *data, bool blocked)
382{ 361{
383 int rfkill_id = (int)(long)data; 362 int rfkill_id = (int)(long)data;
384 char buffer[4] = { 0x01, 0x00, rfkill_id, !blocked }; 363 char buffer[4] = { 0x01, 0x00, rfkill_id, !blocked };
364 int ret;
385 365
386 if (hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, 1, 366 ret = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, HPWMI_WRITE,
387 buffer, sizeof(buffer), 0)) 367 buffer, sizeof(buffer), 0);
388 return -EINVAL; 368
389 return 0; 369 return ret <= 0 ? ret : -EINVAL;
390} 370}
391 371
392static const struct rfkill_ops hp_wmi_rfkill2_ops = { 372static const struct rfkill_ops hp_wmi_rfkill2_ops = {
@@ -395,10 +375,10 @@ static const struct rfkill_ops hp_wmi_rfkill2_ops = {
395 375
396static int hp_wmi_rfkill2_refresh(void) 376static int hp_wmi_rfkill2_refresh(void)
397{ 377{
398 int err, i;
399 struct bios_rfkill2_state state; 378 struct bios_rfkill2_state state;
379 int err, i;
400 380
401 err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, 0, &state, 381 err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, HPWMI_READ, &state,
402 0, sizeof(state)); 382 0, sizeof(state));
403 if (err) 383 if (err)
404 return err; 384 return err;
@@ -422,119 +402,113 @@ static int hp_wmi_rfkill2_refresh(void)
422 return 0; 402 return 0;
423} 403}
424 404
425static int hp_wmi_post_code_state(void) 405static ssize_t display_show(struct device *dev, struct device_attribute *attr,
426{
427 int state = 0;
428 int ret = hp_wmi_perform_query(HPWMI_POSTCODEERROR_QUERY, 0, &state,
429 sizeof(state), sizeof(state));
430 if (ret)
431 return -EINVAL;
432 return state;
433}
434
435static ssize_t show_display(struct device *dev, struct device_attribute *attr,
436 char *buf) 406 char *buf)
437{ 407{
438 int value = hp_wmi_display_state(); 408 int value = hp_wmi_read_int(HPWMI_DISPLAY_QUERY);
439 if (value < 0) 409 if (value < 0)
440 return -EINVAL; 410 return value;
441 return sprintf(buf, "%d\n", value); 411 return sprintf(buf, "%d\n", value);
442} 412}
443 413
444static ssize_t show_hddtemp(struct device *dev, struct device_attribute *attr, 414static ssize_t hddtemp_show(struct device *dev, struct device_attribute *attr,
445 char *buf) 415 char *buf)
446{ 416{
447 int value = hp_wmi_hddtemp_state(); 417 int value = hp_wmi_read_int(HPWMI_HDDTEMP_QUERY);
448 if (value < 0) 418 if (value < 0)
449 return -EINVAL; 419 return value;
450 return sprintf(buf, "%d\n", value); 420 return sprintf(buf, "%d\n", value);
451} 421}
452 422
453static ssize_t show_als(struct device *dev, struct device_attribute *attr, 423static ssize_t als_show(struct device *dev, struct device_attribute *attr,
454 char *buf) 424 char *buf)
455{ 425{
456 int value = hp_wmi_als_state(); 426 int value = hp_wmi_read_int(HPWMI_ALS_QUERY);
457 if (value < 0) 427 if (value < 0)
458 return -EINVAL; 428 return value;
459 return sprintf(buf, "%d\n", value); 429 return sprintf(buf, "%d\n", value);
460} 430}
461 431
462static ssize_t show_dock(struct device *dev, struct device_attribute *attr, 432static ssize_t dock_show(struct device *dev, struct device_attribute *attr,
463 char *buf) 433 char *buf)
464{ 434{
465 int value = hp_wmi_dock_state(); 435 int value = hp_wmi_hw_state(HPWMI_DOCK_MASK);
466 if (value < 0) 436 if (value < 0)
467 return -EINVAL; 437 return value;
468 return sprintf(buf, "%d\n", value); 438 return sprintf(buf, "%d\n", value);
469} 439}
470 440
471static ssize_t show_tablet(struct device *dev, struct device_attribute *attr, 441static ssize_t tablet_show(struct device *dev, struct device_attribute *attr,
472 char *buf) 442 char *buf)
473{ 443{
474 int value = hp_wmi_tablet_state(); 444 int value = hp_wmi_hw_state(HPWMI_TABLET_MASK);
475 if (value < 0) 445 if (value < 0)
476 return -EINVAL; 446 return value;
477 return sprintf(buf, "%d\n", value); 447 return sprintf(buf, "%d\n", value);
478} 448}
479 449
480static ssize_t show_postcode(struct device *dev, struct device_attribute *attr, 450static ssize_t postcode_show(struct device *dev, struct device_attribute *attr,
481 char *buf) 451 char *buf)
482{ 452{
483 /* Get the POST error code of previous boot failure. */ 453 /* Get the POST error code of previous boot failure. */
484 int value = hp_wmi_post_code_state(); 454 int value = hp_wmi_read_int(HPWMI_POSTCODEERROR_QUERY);
485 if (value < 0) 455 if (value < 0)
486 return -EINVAL; 456 return value;
487 return sprintf(buf, "0x%x\n", value); 457 return sprintf(buf, "0x%x\n", value);
488} 458}
489 459
490static ssize_t set_als(struct device *dev, struct device_attribute *attr, 460static ssize_t als_store(struct device *dev, struct device_attribute *attr,
491 const char *buf, size_t count) 461 const char *buf, size_t count)
492{ 462{
493 u32 tmp = simple_strtoul(buf, NULL, 10); 463 u32 tmp = simple_strtoul(buf, NULL, 10);
494 int ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, 1, &tmp, 464 int ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, HPWMI_WRITE, &tmp,
495 sizeof(tmp), sizeof(tmp)); 465 sizeof(tmp), sizeof(tmp));
496 if (ret) 466 if (ret)
497 return -EINVAL; 467 return ret < 0 ? ret : -EINVAL;
498 468
499 return count; 469 return count;
500} 470}
501 471
502static ssize_t set_postcode(struct device *dev, struct device_attribute *attr, 472static ssize_t postcode_store(struct device *dev, struct device_attribute *attr,
503 const char *buf, size_t count) 473 const char *buf, size_t count)
504{ 474{
475 long unsigned int tmp2;
505 int ret; 476 int ret;
506 u32 tmp; 477 u32 tmp;
507 long unsigned int tmp2;
508 478
509 ret = kstrtoul(buf, 10, &tmp2); 479 ret = kstrtoul(buf, 10, &tmp2);
510 if (ret || tmp2 != 1) 480 if (!ret && tmp2 != 1)
511 return -EINVAL; 481 ret = -EINVAL;
482 if (ret)
483 goto out;
512 484
513 /* Clear the POST error code. It is kept until until cleared. */ 485 /* Clear the POST error code. It is kept until until cleared. */
514 tmp = (u32) tmp2; 486 tmp = (u32) tmp2;
515 ret = hp_wmi_perform_query(HPWMI_POSTCODEERROR_QUERY, 1, &tmp, 487 ret = hp_wmi_perform_query(HPWMI_POSTCODEERROR_QUERY, HPWMI_WRITE, &tmp,
516 sizeof(tmp), sizeof(tmp)); 488 sizeof(tmp), sizeof(tmp));
489
490out:
517 if (ret) 491 if (ret)
518 return -EINVAL; 492 return ret < 0 ? ret : -EINVAL;
519 493
520 return count; 494 return count;
521} 495}
522 496
523static DEVICE_ATTR(display, S_IRUGO, show_display, NULL); 497static DEVICE_ATTR_RO(display);
524static DEVICE_ATTR(hddtemp, S_IRUGO, show_hddtemp, NULL); 498static DEVICE_ATTR_RO(hddtemp);
525static DEVICE_ATTR(als, S_IRUGO | S_IWUSR, show_als, set_als); 499static DEVICE_ATTR_RW(als);
526static DEVICE_ATTR(dock, S_IRUGO, show_dock, NULL); 500static DEVICE_ATTR_RO(dock);
527static DEVICE_ATTR(tablet, S_IRUGO, show_tablet, NULL); 501static DEVICE_ATTR_RO(tablet);
528static DEVICE_ATTR(postcode, S_IRUGO | S_IWUSR, show_postcode, set_postcode); 502static DEVICE_ATTR_RW(postcode);
529 503
530static void hp_wmi_notify(u32 value, void *context) 504static void hp_wmi_notify(u32 value, void *context)
531{ 505{
532 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; 506 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
533 union acpi_object *obj;
534 u32 event_id, event_data; 507 u32 event_id, event_data;
535 int key_code = 0, ret; 508 union acpi_object *obj;
536 u32 *location;
537 acpi_status status; 509 acpi_status status;
510 u32 *location;
511 int key_code;
538 512
539 status = wmi_get_event_data(value, &response); 513 status = wmi_get_event_data(value, &response);
540 if (status != AE_OK) { 514 if (status != AE_OK) {
@@ -572,10 +546,12 @@ static void hp_wmi_notify(u32 value, void *context)
572 546
573 switch (event_id) { 547 switch (event_id) {
574 case HPWMI_DOCK_EVENT: 548 case HPWMI_DOCK_EVENT:
575 input_report_switch(hp_wmi_input_dev, SW_DOCK, 549 if (test_bit(SW_DOCK, hp_wmi_input_dev->swbit))
576 hp_wmi_dock_state()); 550 input_report_switch(hp_wmi_input_dev, SW_DOCK,
577 input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, 551 hp_wmi_hw_state(HPWMI_DOCK_MASK));
578 hp_wmi_tablet_state()); 552 if (test_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit))
553 input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE,
554 hp_wmi_hw_state(HPWMI_TABLET_MASK));
579 input_sync(hp_wmi_input_dev); 555 input_sync(hp_wmi_input_dev);
580 break; 556 break;
581 case HPWMI_PARK_HDD: 557 case HPWMI_PARK_HDD:
@@ -583,11 +559,8 @@ static void hp_wmi_notify(u32 value, void *context)
583 case HPWMI_SMART_ADAPTER: 559 case HPWMI_SMART_ADAPTER:
584 break; 560 break;
585 case HPWMI_BEZEL_BUTTON: 561 case HPWMI_BEZEL_BUTTON:
586 ret = hp_wmi_perform_query(HPWMI_HOTKEY_QUERY, 0, 562 key_code = hp_wmi_read_int(HPWMI_HOTKEY_QUERY);
587 &key_code, 563 if (key_code < 0)
588 sizeof(key_code),
589 sizeof(key_code));
590 if (ret)
591 break; 564 break;
592 565
593 if (!sparse_keymap_report_event(hp_wmi_input_dev, 566 if (!sparse_keymap_report_event(hp_wmi_input_dev,
@@ -643,7 +616,7 @@ static void hp_wmi_notify(u32 value, void *context)
643static int __init hp_wmi_input_setup(void) 616static int __init hp_wmi_input_setup(void)
644{ 617{
645 acpi_status status; 618 acpi_status status;
646 int err; 619 int err, val;
647 620
648 hp_wmi_input_dev = input_allocate_device(); 621 hp_wmi_input_dev = input_allocate_device();
649 if (!hp_wmi_input_dev) 622 if (!hp_wmi_input_dev)
@@ -654,17 +627,26 @@ static int __init hp_wmi_input_setup(void)
654 hp_wmi_input_dev->id.bustype = BUS_HOST; 627 hp_wmi_input_dev->id.bustype = BUS_HOST;
655 628
656 __set_bit(EV_SW, hp_wmi_input_dev->evbit); 629 __set_bit(EV_SW, hp_wmi_input_dev->evbit);
657 __set_bit(SW_DOCK, hp_wmi_input_dev->swbit); 630
658 __set_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit); 631 /* Dock */
632 val = hp_wmi_hw_state(HPWMI_DOCK_MASK);
633 if (!(val < 0)) {
634 __set_bit(SW_DOCK, hp_wmi_input_dev->swbit);
635 input_report_switch(hp_wmi_input_dev, SW_DOCK, val);
636 }
637
638 /* Tablet mode */
639 val = hp_wmi_hw_state(HPWMI_TABLET_MASK);
640 if (!(val < 0)) {
641 __set_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit);
642 input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, val);
643 }
659 644
660 err = sparse_keymap_setup(hp_wmi_input_dev, hp_wmi_keymap, NULL); 645 err = sparse_keymap_setup(hp_wmi_input_dev, hp_wmi_keymap, NULL);
661 if (err) 646 if (err)
662 goto err_free_dev; 647 goto err_free_dev;
663 648
664 /* Set initial hardware state */ 649 /* Set initial hardware state */
665 input_report_switch(hp_wmi_input_dev, SW_DOCK, hp_wmi_dock_state());
666 input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE,
667 hp_wmi_tablet_state());
668 input_sync(hp_wmi_input_dev); 650 input_sync(hp_wmi_input_dev);
669 651
670 if (!hp_wmi_bios_2009_later() && hp_wmi_bios_2008_later()) 652 if (!hp_wmi_bios_2009_later() && hp_wmi_bios_2008_later())
@@ -673,7 +655,7 @@ static int __init hp_wmi_input_setup(void)
673 status = wmi_install_notify_handler(HPWMI_EVENT_GUID, hp_wmi_notify, NULL); 655 status = wmi_install_notify_handler(HPWMI_EVENT_GUID, hp_wmi_notify, NULL);
674 if (ACPI_FAILURE(status)) { 656 if (ACPI_FAILURE(status)) {
675 err = -EIO; 657 err = -EIO;
676 goto err_free_keymap; 658 goto err_free_dev;
677 } 659 }
678 660
679 err = input_register_device(hp_wmi_input_dev); 661 err = input_register_device(hp_wmi_input_dev);
@@ -684,8 +666,6 @@ static int __init hp_wmi_input_setup(void)
684 666
685 err_uninstall_notifier: 667 err_uninstall_notifier:
686 wmi_remove_notify_handler(HPWMI_EVENT_GUID); 668 wmi_remove_notify_handler(HPWMI_EVENT_GUID);
687 err_free_keymap:
688 sparse_keymap_free(hp_wmi_input_dev);
689 err_free_dev: 669 err_free_dev:
690 input_free_device(hp_wmi_input_dev); 670 input_free_device(hp_wmi_input_dev);
691 return err; 671 return err;
@@ -694,7 +674,6 @@ static int __init hp_wmi_input_setup(void)
694static void hp_wmi_input_destroy(void) 674static void hp_wmi_input_destroy(void)
695{ 675{
696 wmi_remove_notify_handler(HPWMI_EVENT_GUID); 676 wmi_remove_notify_handler(HPWMI_EVENT_GUID);
697 sparse_keymap_free(hp_wmi_input_dev);
698 input_unregister_device(hp_wmi_input_dev); 677 input_unregister_device(hp_wmi_input_dev);
699} 678}
700 679
@@ -710,15 +689,13 @@ static void cleanup_sysfs(struct platform_device *device)
710 689
711static int __init hp_wmi_rfkill_setup(struct platform_device *device) 690static int __init hp_wmi_rfkill_setup(struct platform_device *device)
712{ 691{
713 int err; 692 int err, wireless;
714 int wireless = 0;
715 693
716 err = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, &wireless, 694 wireless = hp_wmi_read_int(HPWMI_WIRELESS_QUERY);
717 sizeof(wireless), sizeof(wireless)); 695 if (wireless < 0)
718 if (err) 696 return wireless;
719 return err;
720 697
721 err = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, &wireless, 698 err = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, HPWMI_WRITE, &wireless,
722 sizeof(wireless), 0); 699 sizeof(wireless), 0);
723 if (err) 700 if (err)
724 return err; 701 return err;
@@ -795,12 +772,13 @@ register_wifi_error:
795 772
796static int __init hp_wmi_rfkill2_setup(struct platform_device *device) 773static int __init hp_wmi_rfkill2_setup(struct platform_device *device)
797{ 774{
798 int err, i;
799 struct bios_rfkill2_state state; 775 struct bios_rfkill2_state state;
800 err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, 0, &state, 776 int err, i;
777
778 err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, HPWMI_READ, &state,
801 0, sizeof(state)); 779 0, sizeof(state));
802 if (err) 780 if (err)
803 return err; 781 return err < 0 ? err : -EINVAL;
804 782
805 if (state.count > HPWMI_MAX_RFKILL2_DEVICES) { 783 if (state.count > HPWMI_MAX_RFKILL2_DEVICES) {
806 pr_warn("unable to parse 0x1b query output\n"); 784 pr_warn("unable to parse 0x1b query output\n");
@@ -950,10 +928,12 @@ static int hp_wmi_resume_handler(struct device *device)
950 * changed. 928 * changed.
951 */ 929 */
952 if (hp_wmi_input_dev) { 930 if (hp_wmi_input_dev) {
953 input_report_switch(hp_wmi_input_dev, SW_DOCK, 931 if (test_bit(SW_DOCK, hp_wmi_input_dev->swbit))
954 hp_wmi_dock_state()); 932 input_report_switch(hp_wmi_input_dev, SW_DOCK,
955 input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, 933 hp_wmi_hw_state(HPWMI_DOCK_MASK));
956 hp_wmi_tablet_state()); 934 if (test_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit))
935 input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE,
936 hp_wmi_hw_state(HPWMI_TABLET_MASK));
957 input_sync(hp_wmi_input_dev); 937 input_sync(hp_wmi_input_dev);
958 } 938 }
959 939
@@ -991,9 +971,9 @@ static struct platform_driver hp_wmi_driver = {
991 971
992static int __init hp_wmi_init(void) 972static int __init hp_wmi_init(void)
993{ 973{
994 int err;
995 int event_capable = wmi_has_guid(HPWMI_EVENT_GUID); 974 int event_capable = wmi_has_guid(HPWMI_EVENT_GUID);
996 int bios_capable = wmi_has_guid(HPWMI_BIOS_GUID); 975 int bios_capable = wmi_has_guid(HPWMI_BIOS_GUID);
976 int err;
997 977
998 if (!bios_capable && !event_capable) 978 if (!bios_capable && !event_capable)
999 return -ENODEV; 979 return -ENODEV;
diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
index f46ece2ce3c4..24ca9fbe31cc 100644
--- a/drivers/platform/x86/ideapad-laptop.c
+++ b/drivers/platform/x86/ideapad-laptop.c
@@ -604,14 +604,12 @@ static int ideapad_input_init(struct ideapad_private *priv)
604 error = input_register_device(inputdev); 604 error = input_register_device(inputdev);
605 if (error) { 605 if (error) {
606 pr_err("Unable to register input device\n"); 606 pr_err("Unable to register input device\n");
607 goto err_free_keymap; 607 goto err_free_dev;
608 } 608 }
609 609
610 priv->inputdev = inputdev; 610 priv->inputdev = inputdev;
611 return 0; 611 return 0;
612 612
613err_free_keymap:
614 sparse_keymap_free(inputdev);
615err_free_dev: 613err_free_dev:
616 input_free_device(inputdev); 614 input_free_device(inputdev);
617 return error; 615 return error;
@@ -619,7 +617,6 @@ err_free_dev:
619 617
620static void ideapad_input_exit(struct ideapad_private *priv) 618static void ideapad_input_exit(struct ideapad_private *priv)
621{ 619{
622 sparse_keymap_free(priv->inputdev);
623 input_unregister_device(priv->inputdev); 620 input_unregister_device(priv->inputdev);
624 priv->inputdev = NULL; 621 priv->inputdev = NULL;
625} 622}
@@ -872,6 +869,20 @@ static const struct dmi_system_id no_hw_rfkill_list[] = {
872 }, 869 },
873 }, 870 },
874 { 871 {
872 .ident = "Lenovo V310-15ISK",
873 .matches = {
874 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
875 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo V310-15ISK"),
876 },
877 },
878 {
879 .ident = "Lenovo ideapad 310-15IKB",
880 .matches = {
881 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
882 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad 310-15IKB"),
883 },
884 },
885 {
875 .ident = "Lenovo ideapad Y700-15ACZ", 886 .ident = "Lenovo ideapad Y700-15ACZ",
876 .matches = { 887 .matches = {
877 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 888 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
diff --git a/drivers/platform/x86/intel-hid.c b/drivers/platform/x86/intel-hid.c
index bcf438f38781..63ba2cbd04c2 100644
--- a/drivers/platform/x86/intel-hid.c
+++ b/drivers/platform/x86/intel-hid.c
@@ -77,14 +77,12 @@ struct intel_hid_priv {
77 struct input_dev *array; 77 struct input_dev *array;
78}; 78};
79 79
80static int intel_hid_set_enable(struct device *device, int enable) 80static int intel_hid_set_enable(struct device *device, bool enable)
81{ 81{
82 union acpi_object arg0 = { ACPI_TYPE_INTEGER };
83 struct acpi_object_list args = { 1, &arg0 };
84 acpi_status status; 82 acpi_status status;
85 83
86 arg0.integer.value = enable; 84 status = acpi_execute_simple_method(ACPI_HANDLE(device), "HDSM",
87 status = acpi_evaluate_object(ACPI_HANDLE(device), "HDSM", &args, NULL); 85 enable);
88 if (ACPI_FAILURE(status)) { 86 if (ACPI_FAILURE(status)) {
89 dev_warn(device, "failed to %sable hotkeys\n", 87 dev_warn(device, "failed to %sable hotkeys\n",
90 enable ? "en" : "dis"); 88 enable ? "en" : "dis");
@@ -120,7 +118,7 @@ static void intel_button_array_enable(struct device *device, bool enable)
120 118
121static int intel_hid_pl_suspend_handler(struct device *device) 119static int intel_hid_pl_suspend_handler(struct device *device)
122{ 120{
123 intel_hid_set_enable(device, 0); 121 intel_hid_set_enable(device, false);
124 intel_button_array_enable(device, false); 122 intel_button_array_enable(device, false);
125 123
126 return 0; 124 return 0;
@@ -128,7 +126,7 @@ static int intel_hid_pl_suspend_handler(struct device *device)
128 126
129static int intel_hid_pl_resume_handler(struct device *device) 127static int intel_hid_pl_resume_handler(struct device *device)
130{ 128{
131 intel_hid_set_enable(device, 1); 129 intel_hid_set_enable(device, true);
132 intel_button_array_enable(device, true); 130 intel_button_array_enable(device, true);
133 131
134 return 0; 132 return 0;
@@ -136,6 +134,7 @@ static int intel_hid_pl_resume_handler(struct device *device)
136 134
137static const struct dev_pm_ops intel_hid_pl_pm_ops = { 135static const struct dev_pm_ops intel_hid_pl_pm_ops = {
138 .freeze = intel_hid_pl_suspend_handler, 136 .freeze = intel_hid_pl_suspend_handler,
137 .thaw = intel_hid_pl_resume_handler,
139 .restore = intel_hid_pl_resume_handler, 138 .restore = intel_hid_pl_resume_handler,
140 .suspend = intel_hid_pl_suspend_handler, 139 .suspend = intel_hid_pl_suspend_handler,
141 .resume = intel_hid_pl_resume_handler, 140 .resume = intel_hid_pl_resume_handler,
@@ -146,28 +145,18 @@ static int intel_hid_input_setup(struct platform_device *device)
146 struct intel_hid_priv *priv = dev_get_drvdata(&device->dev); 145 struct intel_hid_priv *priv = dev_get_drvdata(&device->dev);
147 int ret; 146 int ret;
148 147
149 priv->input_dev = input_allocate_device(); 148 priv->input_dev = devm_input_allocate_device(&device->dev);
150 if (!priv->input_dev) 149 if (!priv->input_dev)
151 return -ENOMEM; 150 return -ENOMEM;
152 151
153 ret = sparse_keymap_setup(priv->input_dev, intel_hid_keymap, NULL); 152 ret = sparse_keymap_setup(priv->input_dev, intel_hid_keymap, NULL);
154 if (ret) 153 if (ret)
155 goto err_free_device; 154 return ret;
156 155
157 priv->input_dev->dev.parent = &device->dev;
158 priv->input_dev->name = "Intel HID events"; 156 priv->input_dev->name = "Intel HID events";
159 priv->input_dev->id.bustype = BUS_HOST; 157 priv->input_dev->id.bustype = BUS_HOST;
160 set_bit(KEY_RFKILL, priv->input_dev->keybit);
161
162 ret = input_register_device(priv->input_dev);
163 if (ret)
164 goto err_free_device;
165 158
166 return 0; 159 return input_register_device(priv->input_dev);
167
168err_free_device:
169 input_free_device(priv->input_dev);
170 return ret;
171} 160}
172 161
173static int intel_button_array_input_setup(struct platform_device *device) 162static int intel_button_array_input_setup(struct platform_device *device)
@@ -184,20 +173,12 @@ static int intel_button_array_input_setup(struct platform_device *device)
184 if (ret) 173 if (ret)
185 return ret; 174 return ret;
186 175
187 priv->array->dev.parent = &device->dev;
188 priv->array->name = "Intel HID 5 button array"; 176 priv->array->name = "Intel HID 5 button array";
189 priv->array->id.bustype = BUS_HOST; 177 priv->array->id.bustype = BUS_HOST;
190 178
191 return input_register_device(priv->array); 179 return input_register_device(priv->array);
192} 180}
193 181
194static void intel_hid_input_destroy(struct platform_device *device)
195{
196 struct intel_hid_priv *priv = dev_get_drvdata(&device->dev);
197
198 input_unregister_device(priv->input_dev);
199}
200
201static void notify_handler(acpi_handle handle, u32 event, void *context) 182static void notify_handler(acpi_handle handle, u32 event, void *context)
202{ 183{
203 struct platform_device *device = context; 184 struct platform_device *device = context;
@@ -272,12 +253,10 @@ static int intel_hid_probe(struct platform_device *device)
272 ACPI_DEVICE_NOTIFY, 253 ACPI_DEVICE_NOTIFY,
273 notify_handler, 254 notify_handler,
274 device); 255 device);
275 if (ACPI_FAILURE(status)) { 256 if (ACPI_FAILURE(status))
276 err = -EBUSY; 257 return -EBUSY;
277 goto err_remove_input;
278 }
279 258
280 err = intel_hid_set_enable(&device->dev, 1); 259 err = intel_hid_set_enable(&device->dev, true);
281 if (err) 260 if (err)
282 goto err_remove_notify; 261 goto err_remove_notify;
283 262
@@ -296,9 +275,6 @@ static int intel_hid_probe(struct platform_device *device)
296err_remove_notify: 275err_remove_notify:
297 acpi_remove_notify_handler(handle, ACPI_DEVICE_NOTIFY, notify_handler); 276 acpi_remove_notify_handler(handle, ACPI_DEVICE_NOTIFY, notify_handler);
298 277
299err_remove_input:
300 intel_hid_input_destroy(device);
301
302 return err; 278 return err;
303} 279}
304 280
@@ -307,8 +283,7 @@ static int intel_hid_remove(struct platform_device *device)
307 acpi_handle handle = ACPI_HANDLE(&device->dev); 283 acpi_handle handle = ACPI_HANDLE(&device->dev);
308 284
309 acpi_remove_notify_handler(handle, ACPI_DEVICE_NOTIFY, notify_handler); 285 acpi_remove_notify_handler(handle, ACPI_DEVICE_NOTIFY, notify_handler);
310 intel_hid_input_destroy(device); 286 intel_hid_set_enable(&device->dev, false);
311 intel_hid_set_enable(&device->dev, 0);
312 intel_button_array_enable(&device->dev, false); 287 intel_button_array_enable(&device->dev, false);
313 288
314 /* 289 /*
diff --git a/drivers/platform/x86/intel-vbtn.c b/drivers/platform/x86/intel-vbtn.c
index 554e82ebe83c..c2035e121ac2 100644
--- a/drivers/platform/x86/intel-vbtn.c
+++ b/drivers/platform/x86/intel-vbtn.c
@@ -37,6 +37,10 @@ static const struct acpi_device_id intel_vbtn_ids[] = {
37static const struct key_entry intel_vbtn_keymap[] = { 37static const struct key_entry intel_vbtn_keymap[] = {
38 { KE_IGNORE, 0xC0, { KEY_POWER } }, /* power key press */ 38 { KE_IGNORE, 0xC0, { KEY_POWER } }, /* power key press */
39 { KE_KEY, 0xC1, { KEY_POWER } }, /* power key release */ 39 { KE_KEY, 0xC1, { KEY_POWER } }, /* power key release */
40 { KE_KEY, 0xC4, { KEY_VOLUMEUP } }, /* volume-up key press */
41 { KE_IGNORE, 0xC5, { KEY_VOLUMEUP } }, /* volume-up key release */
42 { KE_KEY, 0xC6, { KEY_VOLUMEDOWN } }, /* volume-down key press */
43 { KE_IGNORE, 0xC7, { KEY_VOLUMEDOWN } }, /* volume-down key release */
40 { KE_END }, 44 { KE_END },
41}; 45};
42 46
diff --git a/drivers/platform/x86/intel_cht_int33fe.c b/drivers/platform/x86/intel_cht_int33fe.c
new file mode 100644
index 000000000000..6a1b2ca5b6fe
--- /dev/null
+++ b/drivers/platform/x86/intel_cht_int33fe.c
@@ -0,0 +1,143 @@
1/*
2 * Intel Cherry Trail ACPI INT33FE pseudo device driver
3 *
4 * Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * Some Intel Cherry Trail based device which ship with Windows 10, have
11 * this weird INT33FE ACPI device with a CRS table with 4 I2cSerialBusV2
12 * resources, for 4 different chips attached to various i2c busses:
13 * 1. The Whiskey Cove pmic, which is also described by the INT34D3 ACPI device
14 * 2. Maxim MAX17047 Fuel Gauge Controller
15 * 3. FUSB302 USB Type-C Controller
16 * 4. PI3USB30532 USB switch
17 *
18 * So this driver is a stub / pseudo driver whose only purpose is to
19 * instantiate i2c-clients for chips 2 - 4, so that standard i2c drivers
20 * for these chips can bind to the them.
21 */
22
23#include <linux/acpi.h>
24#include <linux/i2c.h>
25#include <linux/interrupt.h>
26#include <linux/module.h>
27#include <linux/slab.h>
28
29#define EXPECTED_PTYPE 4
30
31struct cht_int33fe_data {
32 struct i2c_client *max17047;
33 struct i2c_client *fusb302;
34 struct i2c_client *pi3usb30532;
35};
36
37static int cht_int33fe_probe(struct i2c_client *client)
38{
39 struct device *dev = &client->dev;
40 struct i2c_board_info board_info;
41 struct cht_int33fe_data *data;
42 unsigned long long ptyp;
43 acpi_status status;
44 int fusb302_irq;
45
46 status = acpi_evaluate_integer(ACPI_HANDLE(dev), "PTYP", NULL, &ptyp);
47 if (ACPI_FAILURE(status)) {
48 dev_err(dev, "Error getting PTYPE\n");
49 return -ENODEV;
50 }
51
52 /*
53 * The same ACPI HID is used for different configurations check PTYP
54 * to ensure that we are dealing with the expected config.
55 */
56 if (ptyp != EXPECTED_PTYPE)
57 return -ENODEV;
58
59 /* The FUSB302 uses the irq at index 1 and is the only irq user */
60 fusb302_irq = acpi_dev_gpio_irq_get(ACPI_COMPANION(dev), 1);
61 if (fusb302_irq < 0) {
62 if (fusb302_irq != -EPROBE_DEFER)
63 dev_err(dev, "Error getting FUSB302 irq\n");
64 return fusb302_irq;
65 }
66
67 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
68 if (!data)
69 return -ENOMEM;
70
71 memset(&board_info, 0, sizeof(board_info));
72 strlcpy(board_info.type, "max17047", I2C_NAME_SIZE);
73
74 data->max17047 = i2c_acpi_new_device(dev, 1, &board_info);
75 if (!data->max17047)
76 return -EPROBE_DEFER; /* Wait for the i2c-adapter to load */
77
78 memset(&board_info, 0, sizeof(board_info));
79 strlcpy(board_info.type, "fusb302", I2C_NAME_SIZE);
80 board_info.irq = fusb302_irq;
81
82 data->fusb302 = i2c_acpi_new_device(dev, 2, &board_info);
83 if (!data->fusb302)
84 goto out_unregister_max17047;
85
86 memset(&board_info, 0, sizeof(board_info));
87 strlcpy(board_info.type, "pi3usb30532", I2C_NAME_SIZE);
88
89 data->pi3usb30532 = i2c_acpi_new_device(dev, 3, &board_info);
90 if (!data->pi3usb30532)
91 goto out_unregister_fusb302;
92
93 i2c_set_clientdata(client, data);
94
95 return 0;
96
97out_unregister_fusb302:
98 i2c_unregister_device(data->fusb302);
99
100out_unregister_max17047:
101 i2c_unregister_device(data->max17047);
102
103 return -EPROBE_DEFER; /* Wait for the i2c-adapter to load */
104}
105
106static int cht_int33fe_remove(struct i2c_client *i2c)
107{
108 struct cht_int33fe_data *data = i2c_get_clientdata(i2c);
109
110 i2c_unregister_device(data->pi3usb30532);
111 i2c_unregister_device(data->fusb302);
112 i2c_unregister_device(data->max17047);
113
114 return 0;
115}
116
117static const struct i2c_device_id cht_int33fe_i2c_id[] = {
118 { }
119};
120MODULE_DEVICE_TABLE(i2c, cht_int33fe_i2c_id);
121
122static const struct acpi_device_id cht_int33fe_acpi_ids[] = {
123 { "INT33FE", },
124 { }
125};
126MODULE_DEVICE_TABLE(acpi, cht_int33fe_acpi_ids);
127
128static struct i2c_driver cht_int33fe_driver = {
129 .driver = {
130 .name = "Intel Cherry Trail ACPI INT33FE driver",
131 .acpi_match_table = ACPI_PTR(cht_int33fe_acpi_ids),
132 },
133 .probe_new = cht_int33fe_probe,
134 .remove = cht_int33fe_remove,
135 .id_table = cht_int33fe_i2c_id,
136 .disable_i2c_core_irq_mapping = true,
137};
138
139module_i2c_driver(cht_int33fe_driver);
140
141MODULE_DESCRIPTION("Intel Cherry Trail ACPI INT33FE pseudo device driver");
142MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
143MODULE_LICENSE("GPL");
diff --git a/drivers/platform/x86/intel_pmc_ipc.c b/drivers/platform/x86/intel_pmc_ipc.c
index 0651d47b8eeb..e4d4dfe3e1d1 100644
--- a/drivers/platform/x86/intel_pmc_ipc.c
+++ b/drivers/platform/x86/intel_pmc_ipc.c
@@ -57,10 +57,6 @@
57#define IPC_WRITE_BUFFER 0x80 57#define IPC_WRITE_BUFFER 0x80
58#define IPC_READ_BUFFER 0x90 58#define IPC_READ_BUFFER 0x90
59 59
60/* PMC Global Control Registers */
61#define GCR_TELEM_DEEP_S0IX_OFFSET 0x1078
62#define GCR_TELEM_SHLW_S0IX_OFFSET 0x1080
63
64/* Residency with clock rate at 19.2MHz to usecs */ 60/* Residency with clock rate at 19.2MHz to usecs */
65#define S0IX_RESIDENCY_IN_USECS(d, s) \ 61#define S0IX_RESIDENCY_IN_USECS(d, s) \
66({ \ 62({ \
@@ -82,7 +78,7 @@
82/* exported resources from IFWI */ 78/* exported resources from IFWI */
83#define PLAT_RESOURCE_IPC_INDEX 0 79#define PLAT_RESOURCE_IPC_INDEX 0
84#define PLAT_RESOURCE_IPC_SIZE 0x1000 80#define PLAT_RESOURCE_IPC_SIZE 0x1000
85#define PLAT_RESOURCE_GCR_OFFSET 0x1008 81#define PLAT_RESOURCE_GCR_OFFSET 0x1000
86#define PLAT_RESOURCE_GCR_SIZE 0x1000 82#define PLAT_RESOURCE_GCR_SIZE 0x1000
87#define PLAT_RESOURCE_BIOS_DATA_INDEX 1 83#define PLAT_RESOURCE_BIOS_DATA_INDEX 1
88#define PLAT_RESOURCE_BIOS_IFACE_INDEX 2 84#define PLAT_RESOURCE_BIOS_IFACE_INDEX 2
@@ -112,6 +108,13 @@
112#define TCO_PMC_OFFSET 0x8 108#define TCO_PMC_OFFSET 0x8
113#define TCO_PMC_SIZE 0x4 109#define TCO_PMC_SIZE 0x4
114 110
111/* PMC register bit definitions */
112
113/* PMC_CFG_REG bit masks */
114#define PMC_CFG_NO_REBOOT_MASK (1 << 4)
115#define PMC_CFG_NO_REBOOT_EN (1 << 4)
116#define PMC_CFG_NO_REBOOT_DIS (0 << 4)
117
115static struct intel_pmc_ipc_dev { 118static struct intel_pmc_ipc_dev {
116 struct device *dev; 119 struct device *dev;
117 void __iomem *ipc_base; 120 void __iomem *ipc_base;
@@ -126,8 +129,7 @@ static struct intel_pmc_ipc_dev {
126 struct platform_device *tco_dev; 129 struct platform_device *tco_dev;
127 130
128 /* gcr */ 131 /* gcr */
129 resource_size_t gcr_base; 132 void __iomem *gcr_mem_base;
130 int gcr_size;
131 bool has_gcr_regs; 133 bool has_gcr_regs;
132 134
133 /* punit */ 135 /* punit */
@@ -196,7 +198,128 @@ static inline u32 ipc_data_readl(u32 offset)
196 198
197static inline u64 gcr_data_readq(u32 offset) 199static inline u64 gcr_data_readq(u32 offset)
198{ 200{
199 return readq(ipcdev.ipc_base + offset); 201 return readq(ipcdev.gcr_mem_base + offset);
202}
203
204static inline int is_gcr_valid(u32 offset)
205{
206 if (!ipcdev.has_gcr_regs)
207 return -EACCES;
208
209 if (offset > PLAT_RESOURCE_GCR_SIZE)
210 return -EINVAL;
211
212 return 0;
213}
214
215/**
216 * intel_pmc_gcr_read() - Read PMC GCR register
217 * @offset: offset of GCR register from GCR address base
218 * @data: data pointer for storing the register output
219 *
220 * Reads the PMC GCR register of given offset.
221 *
222 * Return: negative value on error or 0 on success.
223 */
224int intel_pmc_gcr_read(u32 offset, u32 *data)
225{
226 int ret;
227
228 mutex_lock(&ipclock);
229
230 ret = is_gcr_valid(offset);
231 if (ret < 0) {
232 mutex_unlock(&ipclock);
233 return ret;
234 }
235
236 *data = readl(ipcdev.gcr_mem_base + offset);
237
238 mutex_unlock(&ipclock);
239
240 return 0;
241}
242EXPORT_SYMBOL_GPL(intel_pmc_gcr_read);
243
244/**
245 * intel_pmc_gcr_write() - Write PMC GCR register
246 * @offset: offset of GCR register from GCR address base
247 * @data: register update value
248 *
249 * Writes the PMC GCR register of given offset with given
250 * value.
251 *
252 * Return: negative value on error or 0 on success.
253 */
254int intel_pmc_gcr_write(u32 offset, u32 data)
255{
256 int ret;
257
258 mutex_lock(&ipclock);
259
260 ret = is_gcr_valid(offset);
261 if (ret < 0) {
262 mutex_unlock(&ipclock);
263 return ret;
264 }
265
266 writel(data, ipcdev.gcr_mem_base + offset);
267
268 mutex_unlock(&ipclock);
269
270 return 0;
271}
272EXPORT_SYMBOL_GPL(intel_pmc_gcr_write);
273
274/**
275 * intel_pmc_gcr_update() - Update PMC GCR register bits
276 * @offset: offset of GCR register from GCR address base
277 * @mask: bit mask for update operation
278 * @val: update value
279 *
280 * Updates the bits of given GCR register as specified by
281 * @mask and @val.
282 *
283 * Return: negative value on error or 0 on success.
284 */
285int intel_pmc_gcr_update(u32 offset, u32 mask, u32 val)
286{
287 u32 new_val;
288 int ret = 0;
289
290 mutex_lock(&ipclock);
291
292 ret = is_gcr_valid(offset);
293 if (ret < 0)
294 goto gcr_ipc_unlock;
295
296 new_val = readl(ipcdev.gcr_mem_base + offset);
297
298 new_val &= ~mask;
299 new_val |= val & mask;
300
301 writel(new_val, ipcdev.gcr_mem_base + offset);
302
303 new_val = readl(ipcdev.gcr_mem_base + offset);
304
305 /* check whether the bit update is successful */
306 if ((new_val & mask) != (val & mask)) {
307 ret = -EIO;
308 goto gcr_ipc_unlock;
309 }
310
311gcr_ipc_unlock:
312 mutex_unlock(&ipclock);
313 return ret;
314}
315EXPORT_SYMBOL_GPL(intel_pmc_gcr_update);
316
317static int update_no_reboot_bit(void *priv, bool set)
318{
319 u32 value = set ? PMC_CFG_NO_REBOOT_EN : PMC_CFG_NO_REBOOT_DIS;
320
321 return intel_pmc_gcr_update(PMC_GCR_PMC_CFG_REG,
322 PMC_CFG_NO_REBOOT_MASK, value);
200} 323}
201 324
202static int intel_pmc_ipc_check_status(void) 325static int intel_pmc_ipc_check_status(void)
@@ -516,15 +639,13 @@ static struct resource tco_res[] = {
516 { 639 {
517 .flags = IORESOURCE_IO, 640 .flags = IORESOURCE_IO,
518 }, 641 },
519 /* GCS */
520 {
521 .flags = IORESOURCE_MEM,
522 },
523}; 642};
524 643
525static struct itco_wdt_platform_data tco_info = { 644static struct itco_wdt_platform_data tco_info = {
526 .name = "Apollo Lake SoC", 645 .name = "Apollo Lake SoC",
527 .version = 5, 646 .version = 5,
647 .no_reboot_priv = &ipcdev,
648 .update_no_reboot_bit = update_no_reboot_bit,
528}; 649};
529 650
530#define TELEMETRY_RESOURCE_PUNIT_SSRAM 0 651#define TELEMETRY_RESOURCE_PUNIT_SSRAM 0
@@ -581,10 +702,6 @@ static int ipc_create_tco_device(void)
581 res->start = ipcdev.acpi_io_base + SMI_EN_OFFSET; 702 res->start = ipcdev.acpi_io_base + SMI_EN_OFFSET;
582 res->end = res->start + SMI_EN_SIZE - 1; 703 res->end = res->start + SMI_EN_SIZE - 1;
583 704
584 res = tco_res + TCO_RESOURCE_GCR_MEM;
585 res->start = ipcdev.gcr_base + TCO_PMC_OFFSET;
586 res->end = res->start + TCO_PMC_SIZE - 1;
587
588 pdev = platform_device_register_full(&pdevinfo); 705 pdev = platform_device_register_full(&pdevinfo);
589 if (IS_ERR(pdev)) 706 if (IS_ERR(pdev))
590 return PTR_ERR(pdev); 707 return PTR_ERR(pdev);
@@ -746,8 +863,7 @@ static int ipc_plat_get_res(struct platform_device *pdev)
746 } 863 }
747 ipcdev.ipc_base = addr; 864 ipcdev.ipc_base = addr;
748 865
749 ipcdev.gcr_base = res->start + PLAT_RESOURCE_GCR_OFFSET; 866 ipcdev.gcr_mem_base = addr + PLAT_RESOURCE_GCR_OFFSET;
750 ipcdev.gcr_size = PLAT_RESOURCE_GCR_SIZE;
751 dev_info(&pdev->dev, "ipc res: %pR\n", res); 867 dev_info(&pdev->dev, "ipc res: %pR\n", res);
752 868
753 ipcdev.telem_res_inval = 0; 869 ipcdev.telem_res_inval = 0;
@@ -782,8 +898,8 @@ int intel_pmc_s0ix_counter_read(u64 *data)
782 if (!ipcdev.has_gcr_regs) 898 if (!ipcdev.has_gcr_regs)
783 return -EACCES; 899 return -EACCES;
784 900
785 deep = gcr_data_readq(GCR_TELEM_DEEP_S0IX_OFFSET); 901 deep = gcr_data_readq(PMC_GCR_TELEM_DEEP_S0IX_REG);
786 shlw = gcr_data_readq(GCR_TELEM_SHLW_S0IX_OFFSET); 902 shlw = gcr_data_readq(PMC_GCR_TELEM_SHLW_S0IX_REG);
787 903
788 *data = S0IX_RESIDENCY_IN_USECS(deep, shlw); 904 *data = S0IX_RESIDENCY_IN_USECS(deep, shlw);
789 905
diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c
index e81daff65f62..f7cf981502cd 100644
--- a/drivers/platform/x86/intel_scu_ipc.c
+++ b/drivers/platform/x86/intel_scu_ipc.c
@@ -491,6 +491,69 @@ int intel_scu_ipc_command(int cmd, int sub, u32 *in, int inlen,
491} 491}
492EXPORT_SYMBOL(intel_scu_ipc_command); 492EXPORT_SYMBOL(intel_scu_ipc_command);
493 493
494#define IPC_SPTR 0x08
495#define IPC_DPTR 0x0C
496
497/**
498 * intel_scu_ipc_raw_command() - IPC command with data and pointers
499 * @cmd: IPC command code.
500 * @sub: IPC command sub type.
501 * @in: input data of this IPC command.
502 * @inlen: input data length in dwords.
503 * @out: output data of this IPC command.
504 * @outlen: output data length in dwords.
505 * @sptr: data writing to SPTR register.
506 * @dptr: data writing to DPTR register.
507 *
508 * Send an IPC command to SCU with input/output data and source/dest pointers.
509 *
510 * Return: an IPC error code or 0 on success.
511 */
512int intel_scu_ipc_raw_command(int cmd, int sub, u8 *in, int inlen,
513 u32 *out, int outlen, u32 dptr, u32 sptr)
514{
515 struct intel_scu_ipc_dev *scu = &ipcdev;
516 int inbuflen = DIV_ROUND_UP(inlen, 4);
517 u32 inbuf[4];
518 int i, err;
519
520 /* Up to 16 bytes */
521 if (inbuflen > 4)
522 return -EINVAL;
523
524 mutex_lock(&ipclock);
525 if (scu->dev == NULL) {
526 mutex_unlock(&ipclock);
527 return -ENODEV;
528 }
529
530 writel(dptr, scu->ipc_base + IPC_DPTR);
531 writel(sptr, scu->ipc_base + IPC_SPTR);
532
533 /*
534 * SRAM controller doesn't support 8-bit writes, it only
535 * supports 32-bit writes, so we have to copy input data into
536 * the temporary buffer, and SCU FW will use the inlen to
537 * determine the actual input data length in the temporary
538 * buffer.
539 */
540 memcpy(inbuf, in, inlen);
541
542 for (i = 0; i < inbuflen; i++)
543 ipc_data_writel(scu, inbuf[i], 4 * i);
544
545 ipc_command(scu, (inlen << 16) | (sub << 12) | cmd);
546 err = intel_scu_ipc_check_status(scu);
547 if (!err) {
548 for (i = 0; i < outlen; i++)
549 *out++ = ipc_data_readl(scu, 4 * i);
550 }
551
552 mutex_unlock(&ipclock);
553 return err;
554}
555EXPORT_SYMBOL_GPL(intel_scu_ipc_raw_command);
556
494/* I2C commands */ 557/* I2C commands */
495#define IPC_I2C_WRITE 1 /* I2C Write command */ 558#define IPC_I2C_WRITE 1 /* I2C Write command */
496#define IPC_I2C_READ 2 /* I2C Read command */ 559#define IPC_I2C_READ 2 /* I2C Read command */
@@ -566,21 +629,17 @@ static irqreturn_t ioc(int irq, void *dev_id)
566 */ 629 */
567static int ipc_probe(struct pci_dev *pdev, const struct pci_device_id *id) 630static int ipc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
568{ 631{
569 int platform; /* Platform type */
570 int err; 632 int err;
571 struct intel_scu_ipc_dev *scu = &ipcdev; 633 struct intel_scu_ipc_dev *scu = &ipcdev;
572 struct intel_scu_ipc_pdata_t *pdata; 634 struct intel_scu_ipc_pdata_t *pdata;
573 635
574 platform = intel_mid_identify_cpu();
575 if (platform == 0)
576 return -ENODEV;
577
578 if (scu->dev) /* We support only one SCU */ 636 if (scu->dev) /* We support only one SCU */
579 return -EBUSY; 637 return -EBUSY;
580 638
581 pdata = (struct intel_scu_ipc_pdata_t *)id->driver_data; 639 pdata = (struct intel_scu_ipc_pdata_t *)id->driver_data;
640 if (!pdata)
641 return -ENODEV;
582 642
583 scu->dev = &pdev->dev;
584 scu->irq_mode = pdata->irq_mode; 643 scu->irq_mode = pdata->irq_mode;
585 644
586 err = pcim_enable_device(pdev); 645 err = pcim_enable_device(pdev);
@@ -593,39 +652,34 @@ static int ipc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
593 652
594 init_completion(&scu->cmd_complete); 653 init_completion(&scu->cmd_complete);
595 654
596 err = devm_request_irq(&pdev->dev, pdev->irq, ioc, 0, "intel_scu_ipc",
597 scu);
598 if (err)
599 return err;
600
601 scu->ipc_base = pcim_iomap_table(pdev)[0]; 655 scu->ipc_base = pcim_iomap_table(pdev)[0];
602 656
603 scu->i2c_base = ioremap_nocache(pdata->i2c_base, pdata->i2c_len); 657 scu->i2c_base = ioremap_nocache(pdata->i2c_base, pdata->i2c_len);
604 if (!scu->i2c_base) 658 if (!scu->i2c_base)
605 return -ENOMEM; 659 return -ENOMEM;
606 660
661 err = devm_request_irq(&pdev->dev, pdev->irq, ioc, 0, "intel_scu_ipc",
662 scu);
663 if (err)
664 return err;
665
666 /* Assign device at last */
667 scu->dev = &pdev->dev;
668
607 intel_scu_devices_create(); 669 intel_scu_devices_create();
608 670
609 pci_set_drvdata(pdev, scu); 671 pci_set_drvdata(pdev, scu);
610 return 0; 672 return 0;
611} 673}
612 674
675#define SCU_DEVICE(id, pdata) {PCI_VDEVICE(INTEL, id), (kernel_ulong_t)&pdata}
676
613static const struct pci_device_id pci_ids[] = { 677static const struct pci_device_id pci_ids[] = {
614 { 678 SCU_DEVICE(PCI_DEVICE_ID_LINCROFT, intel_scu_ipc_lincroft_pdata),
615 PCI_VDEVICE(INTEL, PCI_DEVICE_ID_LINCROFT), 679 SCU_DEVICE(PCI_DEVICE_ID_PENWELL, intel_scu_ipc_penwell_pdata),
616 (kernel_ulong_t)&intel_scu_ipc_lincroft_pdata, 680 SCU_DEVICE(PCI_DEVICE_ID_CLOVERVIEW, intel_scu_ipc_penwell_pdata),
617 }, { 681 SCU_DEVICE(PCI_DEVICE_ID_TANGIER, intel_scu_ipc_tangier_pdata),
618 PCI_VDEVICE(INTEL, PCI_DEVICE_ID_PENWELL), 682 {}
619 (kernel_ulong_t)&intel_scu_ipc_penwell_pdata,
620 }, {
621 PCI_VDEVICE(INTEL, PCI_DEVICE_ID_CLOVERVIEW),
622 (kernel_ulong_t)&intel_scu_ipc_penwell_pdata,
623 }, {
624 PCI_VDEVICE(INTEL, PCI_DEVICE_ID_TANGIER),
625 (kernel_ulong_t)&intel_scu_ipc_tangier_pdata,
626 }, {
627 0,
628 }
629}; 683};
630 684
631static struct pci_driver ipc_driver = { 685static struct pci_driver ipc_driver = {
diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c
index 42317704629d..9e90827c176a 100644
--- a/drivers/platform/x86/msi-laptop.c
+++ b/drivers/platform/x86/msi-laptop.c
@@ -976,23 +976,15 @@ static int __init msi_laptop_input_setup(void)
976 976
977 err = input_register_device(msi_laptop_input_dev); 977 err = input_register_device(msi_laptop_input_dev);
978 if (err) 978 if (err)
979 goto err_free_keymap; 979 goto err_free_dev;
980 980
981 return 0; 981 return 0;
982 982
983err_free_keymap:
984 sparse_keymap_free(msi_laptop_input_dev);
985err_free_dev: 983err_free_dev:
986 input_free_device(msi_laptop_input_dev); 984 input_free_device(msi_laptop_input_dev);
987 return err; 985 return err;
988} 986}
989 987
990static void msi_laptop_input_destroy(void)
991{
992 sparse_keymap_free(msi_laptop_input_dev);
993 input_unregister_device(msi_laptop_input_dev);
994}
995
996static int __init load_scm_model_init(struct platform_device *sdev) 988static int __init load_scm_model_init(struct platform_device *sdev)
997{ 989{
998 u8 data; 990 u8 data;
@@ -1037,7 +1029,7 @@ static int __init load_scm_model_init(struct platform_device *sdev)
1037 return 0; 1029 return 0;
1038 1030
1039fail_filter: 1031fail_filter:
1040 msi_laptop_input_destroy(); 1032 input_unregister_device(msi_laptop_input_dev);
1041 1033
1042fail_input: 1034fail_input:
1043 rfkill_cleanup(); 1035 rfkill_cleanup();
@@ -1158,7 +1150,7 @@ static void __exit msi_cleanup(void)
1158{ 1150{
1159 if (quirks->load_scm_model) { 1151 if (quirks->load_scm_model) {
1160 i8042_remove_filter(msi_laptop_i8042_filter); 1152 i8042_remove_filter(msi_laptop_i8042_filter);
1161 msi_laptop_input_destroy(); 1153 input_unregister_device(msi_laptop_input_dev);
1162 cancel_delayed_work_sync(&msi_rfkill_dwork); 1154 cancel_delayed_work_sync(&msi_rfkill_dwork);
1163 cancel_work_sync(&msi_rfkill_work); 1155 cancel_work_sync(&msi_rfkill_work);
1164 rfkill_cleanup(); 1156 rfkill_cleanup();
diff --git a/drivers/platform/x86/msi-wmi.c b/drivers/platform/x86/msi-wmi.c
index 9a32f8627ecc..f6209b739ec0 100644
--- a/drivers/platform/x86/msi-wmi.c
+++ b/drivers/platform/x86/msi-wmi.c
@@ -281,14 +281,12 @@ static int __init msi_wmi_input_setup(void)
281 err = input_register_device(msi_wmi_input_dev); 281 err = input_register_device(msi_wmi_input_dev);
282 282
283 if (err) 283 if (err)
284 goto err_free_keymap; 284 goto err_free_dev;
285 285
286 last_pressed = 0; 286 last_pressed = 0;
287 287
288 return 0; 288 return 0;
289 289
290err_free_keymap:
291 sparse_keymap_free(msi_wmi_input_dev);
292err_free_dev: 290err_free_dev:
293 input_free_device(msi_wmi_input_dev); 291 input_free_device(msi_wmi_input_dev);
294 return err; 292 return err;
@@ -342,10 +340,8 @@ err_uninstall_handler:
342 if (event_wmi) 340 if (event_wmi)
343 wmi_remove_notify_handler(event_wmi->guid); 341 wmi_remove_notify_handler(event_wmi->guid);
344err_free_input: 342err_free_input:
345 if (event_wmi) { 343 if (event_wmi)
346 sparse_keymap_free(msi_wmi_input_dev);
347 input_unregister_device(msi_wmi_input_dev); 344 input_unregister_device(msi_wmi_input_dev);
348 }
349 return err; 345 return err;
350} 346}
351 347
@@ -353,7 +349,6 @@ static void __exit msi_wmi_exit(void)
353{ 349{
354 if (event_wmi) { 350 if (event_wmi) {
355 wmi_remove_notify_handler(event_wmi->guid); 351 wmi_remove_notify_handler(event_wmi->guid);
356 sparse_keymap_free(msi_wmi_input_dev);
357 input_unregister_device(msi_wmi_input_dev); 352 input_unregister_device(msi_wmi_input_dev);
358 } 353 }
359 backlight_device_unregister(backlight); 354 backlight_device_unregister(backlight);
diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c
index 59b8eb626dcc..975f4e100dbd 100644
--- a/drivers/platform/x86/panasonic-laptop.c
+++ b/drivers/platform/x86/panasonic-laptop.c
@@ -520,29 +520,17 @@ static int acpi_pcc_init_input(struct pcc_acpi *pcc)
520 if (error) { 520 if (error) {
521 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 521 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
522 "Unable to register input device\n")); 522 "Unable to register input device\n"));
523 goto err_free_keymap; 523 goto err_free_dev;
524 } 524 }
525 525
526 pcc->input_dev = input_dev; 526 pcc->input_dev = input_dev;
527 return 0; 527 return 0;
528 528
529 err_free_keymap:
530 sparse_keymap_free(input_dev);
531 err_free_dev: 529 err_free_dev:
532 input_free_device(input_dev); 530 input_free_device(input_dev);
533 return error; 531 return error;
534} 532}
535 533
536static void acpi_pcc_destroy_input(struct pcc_acpi *pcc)
537{
538 sparse_keymap_free(pcc->input_dev);
539 input_unregister_device(pcc->input_dev);
540 /*
541 * No need to input_free_device() since core input API refcounts
542 * and free()s the device.
543 */
544}
545
546/* kernel module interface */ 534/* kernel module interface */
547 535
548#ifdef CONFIG_PM_SLEEP 536#ifdef CONFIG_PM_SLEEP
@@ -640,7 +628,7 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
640out_backlight: 628out_backlight:
641 backlight_device_unregister(pcc->backlight); 629 backlight_device_unregister(pcc->backlight);
642out_input: 630out_input:
643 acpi_pcc_destroy_input(pcc); 631 input_unregister_device(pcc->input_dev);
644out_sinf: 632out_sinf:
645 kfree(pcc->sinf); 633 kfree(pcc->sinf);
646out_hotkey: 634out_hotkey:
@@ -660,7 +648,7 @@ static int acpi_pcc_hotkey_remove(struct acpi_device *device)
660 648
661 backlight_device_unregister(pcc->backlight); 649 backlight_device_unregister(pcc->backlight);
662 650
663 acpi_pcc_destroy_input(pcc); 651 input_unregister_device(pcc->input_dev);
664 652
665 kfree(pcc->sinf); 653 kfree(pcc->sinf);
666 kfree(pcc); 654 kfree(pcc);
diff --git a/drivers/platform/x86/silead_dmi.c b/drivers/platform/x86/silead_dmi.c
index 02e11fdbf375..a3a57d93cf06 100644
--- a/drivers/platform/x86/silead_dmi.c
+++ b/drivers/platform/x86/silead_dmi.c
@@ -22,10 +22,10 @@
22 22
23struct silead_ts_dmi_data { 23struct silead_ts_dmi_data {
24 const char *acpi_name; 24 const char *acpi_name;
25 struct property_entry *properties; 25 const struct property_entry *properties;
26}; 26};
27 27
28static struct property_entry cube_iwork8_air_props[] = { 28static const struct property_entry cube_iwork8_air_props[] = {
29 PROPERTY_ENTRY_U32("touchscreen-size-x", 1660), 29 PROPERTY_ENTRY_U32("touchscreen-size-x", 1660),
30 PROPERTY_ENTRY_U32("touchscreen-size-y", 900), 30 PROPERTY_ENTRY_U32("touchscreen-size-y", 900),
31 PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"), 31 PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
@@ -39,7 +39,7 @@ static const struct silead_ts_dmi_data cube_iwork8_air_data = {
39 .properties = cube_iwork8_air_props, 39 .properties = cube_iwork8_air_props,
40}; 40};
41 41
42static struct property_entry jumper_ezpad_mini3_props[] = { 42static const struct property_entry jumper_ezpad_mini3_props[] = {
43 PROPERTY_ENTRY_U32("touchscreen-size-x", 1700), 43 PROPERTY_ENTRY_U32("touchscreen-size-x", 1700),
44 PROPERTY_ENTRY_U32("touchscreen-size-y", 1150), 44 PROPERTY_ENTRY_U32("touchscreen-size-y", 1150),
45 PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"), 45 PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
@@ -53,6 +53,33 @@ static const struct silead_ts_dmi_data jumper_ezpad_mini3_data = {
53 .properties = jumper_ezpad_mini3_props, 53 .properties = jumper_ezpad_mini3_props,
54}; 54};
55 55
56static const struct property_entry dexp_ursus_7w_props[] = {
57 PROPERTY_ENTRY_U32("touchscreen-size-x", 890),
58 PROPERTY_ENTRY_U32("touchscreen-size-y", 630),
59 PROPERTY_ENTRY_STRING("firmware-name", "gsl1686-dexp-ursus-7w.fw"),
60 PROPERTY_ENTRY_U32("silead,max-fingers", 10),
61 { }
62};
63
64static const struct silead_ts_dmi_data dexp_ursus_7w_data = {
65 .acpi_name = "MSSL1680:00",
66 .properties = dexp_ursus_7w_props,
67};
68
69static const struct property_entry surftab_wintron70_st70416_6_props[] = {
70 PROPERTY_ENTRY_U32("touchscreen-size-x", 884),
71 PROPERTY_ENTRY_U32("touchscreen-size-y", 632),
72 PROPERTY_ENTRY_STRING("firmware-name",
73 "gsl1686-surftab-wintron70-st70416-6.fw"),
74 PROPERTY_ENTRY_U32("silead,max-fingers", 10),
75 { }
76};
77
78static const struct silead_ts_dmi_data surftab_wintron70_st70416_6_data = {
79 .acpi_name = "MSSL1680:00",
80 .properties = surftab_wintron70_st70416_6_props,
81};
82
56static const struct dmi_system_id silead_ts_dmi_table[] = { 83static const struct dmi_system_id silead_ts_dmi_table[] = {
57 { 84 {
58 /* CUBE iwork8 Air */ 85 /* CUBE iwork8 Air */
@@ -72,24 +99,37 @@ static const struct dmi_system_id silead_ts_dmi_table[] = {
72 DMI_MATCH(DMI_BIOS_VERSION, "jumperx.T87.KFBNEEA"), 99 DMI_MATCH(DMI_BIOS_VERSION, "jumperx.T87.KFBNEEA"),
73 }, 100 },
74 }, 101 },
102 {
103 /* DEXP Ursus 7W */
104 .driver_data = (void *)&dexp_ursus_7w_data,
105 .matches = {
106 DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
107 DMI_MATCH(DMI_PRODUCT_NAME, "7W"),
108 },
109 },
110 {
111 /* Trekstor Surftab Wintron 7.0 ST70416-6 */
112 .driver_data = (void *)&surftab_wintron70_st70416_6_data,
113 .matches = {
114 DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
115 DMI_MATCH(DMI_PRODUCT_NAME, "ST70416-6"),
116 /* Exact match, different versions need different fw */
117 DMI_MATCH(DMI_BIOS_VERSION, "TREK.G.WI71C.JGBMRBA04"),
118 },
119 },
75 { }, 120 { },
76}; 121};
77 122
78static void silead_ts_dmi_add_props(struct device *dev) 123static const struct silead_ts_dmi_data *silead_ts_data;
124
125static void silead_ts_dmi_add_props(struct i2c_client *client)
79{ 126{
80 struct i2c_client *client = to_i2c_client(dev); 127 struct device *dev = &client->dev;
81 const struct dmi_system_id *dmi_id;
82 const struct silead_ts_dmi_data *ts_data;
83 int error; 128 int error;
84 129
85 dmi_id = dmi_first_match(silead_ts_dmi_table);
86 if (!dmi_id)
87 return;
88
89 ts_data = dmi_id->driver_data;
90 if (has_acpi_companion(dev) && 130 if (has_acpi_companion(dev) &&
91 !strncmp(ts_data->acpi_name, client->name, I2C_NAME_SIZE)) { 131 !strncmp(silead_ts_data->acpi_name, client->name, I2C_NAME_SIZE)) {
92 error = device_add_properties(dev, ts_data->properties); 132 error = device_add_properties(dev, silead_ts_data->properties);
93 if (error) 133 if (error)
94 dev_err(dev, "failed to add properties: %d\n", error); 134 dev_err(dev, "failed to add properties: %d\n", error);
95 } 135 }
@@ -99,10 +139,13 @@ static int silead_ts_dmi_notifier_call(struct notifier_block *nb,
99 unsigned long action, void *data) 139 unsigned long action, void *data)
100{ 140{
101 struct device *dev = data; 141 struct device *dev = data;
142 struct i2c_client *client;
102 143
103 switch (action) { 144 switch (action) {
104 case BUS_NOTIFY_ADD_DEVICE: 145 case BUS_NOTIFY_ADD_DEVICE:
105 silead_ts_dmi_add_props(dev); 146 client = i2c_verify_client(dev);
147 if (client)
148 silead_ts_dmi_add_props(client);
106 break; 149 break;
107 150
108 default: 151 default:
@@ -118,8 +161,15 @@ static struct notifier_block silead_ts_dmi_notifier = {
118 161
119static int __init silead_ts_dmi_init(void) 162static int __init silead_ts_dmi_init(void)
120{ 163{
164 const struct dmi_system_id *dmi_id;
121 int error; 165 int error;
122 166
167 dmi_id = dmi_first_match(silead_ts_dmi_table);
168 if (!dmi_id)
169 return 0; /* Not an error */
170
171 silead_ts_data = dmi_id->driver_data;
172
123 error = bus_register_notifier(&i2c_bus_type, &silead_ts_dmi_notifier); 173 error = bus_register_notifier(&i2c_bus_type, &silead_ts_dmi_notifier);
124 if (error) 174 if (error)
125 pr_err("%s: failed to register i2c bus notifier: %d\n", 175 pr_err("%s: failed to register i2c bus notifier: %d\n",
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index 1d18b32628ec..7b6cb0c69b02 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -1922,7 +1922,9 @@ enum { /* hot key scan codes (derived from ACPI DSDT) */
1922 TP_ACPI_HOTKEYSCAN_UNK7, 1922 TP_ACPI_HOTKEYSCAN_UNK7,
1923 TP_ACPI_HOTKEYSCAN_UNK8, 1923 TP_ACPI_HOTKEYSCAN_UNK8,
1924 1924
1925 TP_ACPI_HOTKEYSCAN_MUTE2, 1925 /* Adaptive keyboard keycodes */
1926 TP_ACPI_HOTKEYSCAN_ADAPTIVE_START,
1927 TP_ACPI_HOTKEYSCAN_MUTE2 = TP_ACPI_HOTKEYSCAN_ADAPTIVE_START,
1926 TP_ACPI_HOTKEYSCAN_BRIGHTNESS_ZERO, 1928 TP_ACPI_HOTKEYSCAN_BRIGHTNESS_ZERO,
1927 TP_ACPI_HOTKEYSCAN_CLIPPING_TOOL, 1929 TP_ACPI_HOTKEYSCAN_CLIPPING_TOOL,
1928 TP_ACPI_HOTKEYSCAN_CLOUD, 1930 TP_ACPI_HOTKEYSCAN_CLOUD,
@@ -1943,6 +1945,15 @@ enum { /* hot key scan codes (derived from ACPI DSDT) */
1943 TP_ACPI_HOTKEYSCAN_CAMERA_MODE, 1945 TP_ACPI_HOTKEYSCAN_CAMERA_MODE,
1944 TP_ACPI_HOTKEYSCAN_ROTATE_DISPLAY, 1946 TP_ACPI_HOTKEYSCAN_ROTATE_DISPLAY,
1945 1947
1948 /* Lenovo extended keymap, starting at 0x1300 */
1949 TP_ACPI_HOTKEYSCAN_EXTENDED_START,
1950 /* first new observed key (star, favorites) is 0x1311 */
1951 TP_ACPI_HOTKEYSCAN_STAR = 69,
1952 TP_ACPI_HOTKEYSCAN_CLIPPING_TOOL2,
1953 TP_ACPI_HOTKEYSCAN_UNK25,
1954 TP_ACPI_HOTKEYSCAN_BLUETOOTH,
1955 TP_ACPI_HOTKEYSCAN_KEYBOARD,
1956
1946 /* Hotkey keymap size */ 1957 /* Hotkey keymap size */
1947 TPACPI_HOTKEY_MAP_LEN 1958 TPACPI_HOTKEY_MAP_LEN
1948}; 1959};
@@ -3250,6 +3261,15 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
3250 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, 3261 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
3251 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, 3262 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
3252 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, 3263 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
3264
3265 /* No assignment, used for newer Lenovo models */
3266 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
3267 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
3268 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
3269 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
3270 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
3271 KEY_UNKNOWN, KEY_UNKNOWN
3272
3253 }, 3273 },
3254 3274
3255 /* Generic keymap for Lenovo ThinkPads */ 3275 /* Generic keymap for Lenovo ThinkPads */
@@ -3335,6 +3355,29 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
3335 KEY_RESERVED, /* Microphone cancellation */ 3355 KEY_RESERVED, /* Microphone cancellation */
3336 KEY_RESERVED, /* Camera mode */ 3356 KEY_RESERVED, /* Camera mode */
3337 KEY_RESERVED, /* Rotate display, 0x116 */ 3357 KEY_RESERVED, /* Rotate display, 0x116 */
3358
3359 /*
3360 * These are found in 2017 models (e.g. T470s, X270).
3361 * The lowest known value is 0x311, which according to
3362 * the manual should launch a user defined favorite
3363 * application.
3364 *
3365 * The offset for these is TP_ACPI_HOTKEYSCAN_EXTENDED_START,
3366 * corresponding to 0x34.
3367 */
3368
3369 /* (assignments unknown, please report if found) */
3370 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
3371 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
3372 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
3373 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
3374 KEY_UNKNOWN,
3375
3376 KEY_FAVORITES, /* Favorite app, 0x311 */
3377 KEY_RESERVED, /* Clipping tool */
3378 KEY_RESERVED,
3379 KEY_BLUETOOTH, /* Bluetooth */
3380 KEY_KEYBOARD /* Keyboard, 0x315 */
3338 }, 3381 },
3339 }; 3382 };
3340 3383
@@ -3656,7 +3699,6 @@ static const int adaptive_keyboard_modes[] = {
3656#define DFR_CHANGE_ROW 0x101 3699#define DFR_CHANGE_ROW 0x101
3657#define DFR_SHOW_QUICKVIEW_ROW 0x102 3700#define DFR_SHOW_QUICKVIEW_ROW 0x102
3658#define FIRST_ADAPTIVE_KEY 0x103 3701#define FIRST_ADAPTIVE_KEY 0x103
3659#define ADAPTIVE_KEY_OFFSET 0x020
3660 3702
3661/* press Fn key a while second, it will switch to Function Mode. Then 3703/* press Fn key a while second, it will switch to Function Mode. Then
3662 * release Fn key, previous mode be restored. 3704 * release Fn key, previous mode be restored.
@@ -3746,13 +3788,15 @@ static bool adaptive_keyboard_hotkey_notify_hotkey(unsigned int scancode)
3746 3788
3747 default: 3789 default:
3748 if (scancode < FIRST_ADAPTIVE_KEY || 3790 if (scancode < FIRST_ADAPTIVE_KEY ||
3749 scancode >= FIRST_ADAPTIVE_KEY + TPACPI_HOTKEY_MAP_LEN - 3791 scancode >= FIRST_ADAPTIVE_KEY +
3750 ADAPTIVE_KEY_OFFSET) { 3792 TP_ACPI_HOTKEYSCAN_EXTENDED_START -
3793 TP_ACPI_HOTKEYSCAN_ADAPTIVE_START) {
3751 pr_info("Unhandled adaptive keyboard key: 0x%x\n", 3794 pr_info("Unhandled adaptive keyboard key: 0x%x\n",
3752 scancode); 3795 scancode);
3753 return false; 3796 return false;
3754 } 3797 }
3755 keycode = hotkey_keycode_map[scancode - FIRST_ADAPTIVE_KEY + ADAPTIVE_KEY_OFFSET]; 3798 keycode = hotkey_keycode_map[scancode - FIRST_ADAPTIVE_KEY +
3799 TP_ACPI_HOTKEYSCAN_ADAPTIVE_START];
3756 if (keycode != KEY_RESERVED) { 3800 if (keycode != KEY_RESERVED) {
3757 mutex_lock(&tpacpi_inputdev_send_mutex); 3801 mutex_lock(&tpacpi_inputdev_send_mutex);
3758 3802
@@ -3777,19 +3821,44 @@ static bool hotkey_notify_hotkey(const u32 hkey,
3777 *send_acpi_ev = true; 3821 *send_acpi_ev = true;
3778 *ignore_acpi_ev = false; 3822 *ignore_acpi_ev = false;
3779 3823
3780 /* HKEY event 0x1001 is scancode 0x00 */ 3824 /*
3781 if (scancode > 0 && scancode <= TPACPI_HOTKEY_MAP_LEN) { 3825 * Original events are in the 0x10XX range, the adaptive keyboard
3782 scancode--; 3826 * found in 2014 X1 Carbon emits events are of 0x11XX. In 2017
3783 if (!(hotkey_source_mask & (1 << scancode))) { 3827 * models, additional keys are emitted through 0x13XX.
3784 tpacpi_input_send_key_masked(scancode); 3828 */
3785 *send_acpi_ev = false; 3829 switch ((hkey >> 8) & 0xf) {
3786 } else { 3830 case 0:
3787 *ignore_acpi_ev = true; 3831 if (scancode > 0 &&
3832 scancode <= TP_ACPI_HOTKEYSCAN_ADAPTIVE_START) {
3833 /* HKEY event 0x1001 is scancode 0x00 */
3834 scancode--;
3835 if (!(hotkey_source_mask & (1 << scancode))) {
3836 tpacpi_input_send_key_masked(scancode);
3837 *send_acpi_ev = false;
3838 } else {
3839 *ignore_acpi_ev = true;
3840 }
3841 return true;
3788 } 3842 }
3789 return true; 3843 break;
3790 } else { 3844
3845 case 1:
3791 return adaptive_keyboard_hotkey_notify_hotkey(scancode); 3846 return adaptive_keyboard_hotkey_notify_hotkey(scancode);
3847
3848 case 3:
3849 /* Extended keycodes start at 0x300 and our offset into the map
3850 * TP_ACPI_HOTKEYSCAN_EXTENDED_START. The calculated scancode
3851 * will be positive, but might not be in the correct range.
3852 */
3853 scancode -= (0x300 - TP_ACPI_HOTKEYSCAN_EXTENDED_START);
3854 if (scancode >= TP_ACPI_HOTKEYSCAN_EXTENDED_START &&
3855 scancode < TPACPI_HOTKEY_MAP_LEN) {
3856 tpacpi_input_send_key(scancode);
3857 return true;
3858 }
3859 break;
3792 } 3860 }
3861
3793 return false; 3862 return false;
3794} 3863}
3795 3864
diff --git a/drivers/platform/x86/topstar-laptop.c b/drivers/platform/x86/topstar-laptop.c
index e597de05e6c2..70205d222da9 100644
--- a/drivers/platform/x86/topstar-laptop.c
+++ b/drivers/platform/x86/topstar-laptop.c
@@ -113,14 +113,12 @@ static int acpi_topstar_init_hkey(struct topstar_hkey *hkey)
113 error = input_register_device(input); 113 error = input_register_device(input);
114 if (error) { 114 if (error) {
115 pr_err("Unable to register input device\n"); 115 pr_err("Unable to register input device\n");
116 goto err_free_keymap; 116 goto err_free_dev;
117 } 117 }
118 118
119 hkey->inputdev = input; 119 hkey->inputdev = input;
120 return 0; 120 return 0;
121 121
122 err_free_keymap:
123 sparse_keymap_free(input);
124 err_free_dev: 122 err_free_dev:
125 input_free_device(input); 123 input_free_device(input);
126 return error; 124 return error;
@@ -157,7 +155,6 @@ static int acpi_topstar_remove(struct acpi_device *device)
157 155
158 acpi_topstar_fncx_switch(device, false); 156 acpi_topstar_fncx_switch(device, false);
159 157
160 sparse_keymap_free(tps_hkey->inputdev);
161 input_unregister_device(tps_hkey->inputdev); 158 input_unregister_device(tps_hkey->inputdev);
162 kfree(tps_hkey); 159 kfree(tps_hkey);
163 160
diff --git a/drivers/platform/x86/toshiba-wmi.c b/drivers/platform/x86/toshiba-wmi.c
index 2df07ee8f3c3..440528676170 100644
--- a/drivers/platform/x86/toshiba-wmi.c
+++ b/drivers/platform/x86/toshiba-wmi.c
@@ -96,7 +96,7 @@ static int __init toshiba_wmi_input_setup(void)
96 toshiba_wmi_notify, NULL); 96 toshiba_wmi_notify, NULL);
97 if (ACPI_FAILURE(status)) { 97 if (ACPI_FAILURE(status)) {
98 err = -EIO; 98 err = -EIO;
99 goto err_free_keymap; 99 goto err_free_dev;
100 } 100 }
101 101
102 err = input_register_device(toshiba_wmi_input_dev); 102 err = input_register_device(toshiba_wmi_input_dev);
@@ -107,8 +107,6 @@ static int __init toshiba_wmi_input_setup(void)
107 107
108 err_remove_notifier: 108 err_remove_notifier:
109 wmi_remove_notify_handler(WMI_EVENT_GUID); 109 wmi_remove_notify_handler(WMI_EVENT_GUID);
110 err_free_keymap:
111 sparse_keymap_free(toshiba_wmi_input_dev);
112 err_free_dev: 110 err_free_dev:
113 input_free_device(toshiba_wmi_input_dev); 111 input_free_device(toshiba_wmi_input_dev);
114 return err; 112 return err;
@@ -117,7 +115,6 @@ static int __init toshiba_wmi_input_setup(void)
117static void toshiba_wmi_input_destroy(void) 115static void toshiba_wmi_input_destroy(void)
118{ 116{
119 wmi_remove_notify_handler(WMI_EVENT_GUID); 117 wmi_remove_notify_handler(WMI_EVENT_GUID);
120 sparse_keymap_free(toshiba_wmi_input_dev);
121 input_unregister_device(toshiba_wmi_input_dev); 118 input_unregister_device(toshiba_wmi_input_dev);
122} 119}
123 120
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index 074bf2fa1c55..d0daf75cbed1 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -2849,7 +2849,7 @@ static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)
2849 error = i8042_install_filter(toshiba_acpi_i8042_filter); 2849 error = i8042_install_filter(toshiba_acpi_i8042_filter);
2850 if (error) { 2850 if (error) {
2851 pr_err("Error installing key filter\n"); 2851 pr_err("Error installing key filter\n");
2852 goto err_free_keymap; 2852 goto err_free_dev;
2853 } 2853 }
2854 2854
2855 dev->ntfy_supported = 1; 2855 dev->ntfy_supported = 1;
@@ -2880,8 +2880,6 @@ static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)
2880 err_remove_filter: 2880 err_remove_filter:
2881 if (dev->ntfy_supported) 2881 if (dev->ntfy_supported)
2882 i8042_remove_filter(toshiba_acpi_i8042_filter); 2882 i8042_remove_filter(toshiba_acpi_i8042_filter);
2883 err_free_keymap:
2884 sparse_keymap_free(dev->hotkey_dev);
2885 err_free_dev: 2883 err_free_dev:
2886 input_free_device(dev->hotkey_dev); 2884 input_free_device(dev->hotkey_dev);
2887 dev->hotkey_dev = NULL; 2885 dev->hotkey_dev = NULL;
@@ -3018,10 +3016,8 @@ static int toshiba_acpi_remove(struct acpi_device *acpi_dev)
3018 cancel_work_sync(&dev->hotkey_work); 3016 cancel_work_sync(&dev->hotkey_work);
3019 } 3017 }
3020 3018
3021 if (dev->hotkey_dev) { 3019 if (dev->hotkey_dev)
3022 input_unregister_device(dev->hotkey_dev); 3020 input_unregister_device(dev->hotkey_dev);
3023 sparse_keymap_free(dev->hotkey_dev);
3024 }
3025 3021
3026 backlight_device_unregister(dev->backlight_dev); 3022 backlight_device_unregister(dev->backlight_dev);
3027 3023
diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c
index 3d0abc0d59b4..347f0389b089 100644
--- a/drivers/watchdog/iTCO_wdt.c
+++ b/drivers/watchdog/iTCO_wdt.c
@@ -106,6 +106,10 @@ struct iTCO_wdt_private {
106 struct pci_dev *pci_dev; 106 struct pci_dev *pci_dev;
107 /* whether or not the watchdog has been suspended */ 107 /* whether or not the watchdog has been suspended */
108 bool suspended; 108 bool suspended;
109 /* no reboot API private data */
110 void *no_reboot_priv;
111 /* no reboot update function pointer */
112 int (*update_no_reboot_bit)(void *p, bool set);
109}; 113};
110 114
111/* module parameters */ 115/* module parameters */
@@ -170,46 +174,68 @@ static inline u32 no_reboot_bit(struct iTCO_wdt_private *p)
170 return enable_bit; 174 return enable_bit;
171} 175}
172 176
173static void iTCO_wdt_set_NO_REBOOT_bit(struct iTCO_wdt_private *p) 177static int update_no_reboot_bit_def(void *priv, bool set)
174{ 178{
175 u32 val32; 179 return 0;
180}
176 181
177 /* Set the NO_REBOOT bit: this disables reboots */ 182static int update_no_reboot_bit_pci(void *priv, bool set)
178 if (p->iTCO_version >= 2) { 183{
179 val32 = readl(p->gcs_pmc); 184 struct iTCO_wdt_private *p = priv;
180 val32 |= no_reboot_bit(p); 185 u32 val32 = 0, newval32 = 0;
181 writel(val32, p->gcs_pmc); 186
182 } else if (p->iTCO_version == 1) { 187 pci_read_config_dword(p->pci_dev, 0xd4, &val32);
183 pci_read_config_dword(p->pci_dev, 0xd4, &val32); 188 if (set)
184 val32 |= no_reboot_bit(p); 189 val32 |= no_reboot_bit(p);
185 pci_write_config_dword(p->pci_dev, 0xd4, val32); 190 else
186 } 191 val32 &= ~no_reboot_bit(p);
192 pci_write_config_dword(p->pci_dev, 0xd4, val32);
193 pci_read_config_dword(p->pci_dev, 0xd4, &newval32);
194
195 /* make sure the update is successful */
196 if (val32 != newval32)
197 return -EIO;
198
199 return 0;
187} 200}
188 201
189static int iTCO_wdt_unset_NO_REBOOT_bit(struct iTCO_wdt_private *p) 202static int update_no_reboot_bit_mem(void *priv, bool set)
190{ 203{
191 u32 enable_bit = no_reboot_bit(p); 204 struct iTCO_wdt_private *p = priv;
192 u32 val32 = 0; 205 u32 val32 = 0, newval32 = 0;
193 206
194 /* Unset the NO_REBOOT bit: this enables reboots */ 207 val32 = readl(p->gcs_pmc);
195 if (p->iTCO_version >= 2) { 208 if (set)
196 val32 = readl(p->gcs_pmc); 209 val32 |= no_reboot_bit(p);
197 val32 &= ~enable_bit; 210 else
198 writel(val32, p->gcs_pmc); 211 val32 &= ~no_reboot_bit(p);
212 writel(val32, p->gcs_pmc);
213 newval32 = readl(p->gcs_pmc);
199 214
200 val32 = readl(p->gcs_pmc); 215 /* make sure the update is successful */
201 } else if (p->iTCO_version == 1) { 216 if (val32 != newval32)
202 pci_read_config_dword(p->pci_dev, 0xd4, &val32); 217 return -EIO;
203 val32 &= ~enable_bit;
204 pci_write_config_dword(p->pci_dev, 0xd4, val32);
205 218
206 pci_read_config_dword(p->pci_dev, 0xd4, &val32); 219 return 0;
220}
221
222static void iTCO_wdt_no_reboot_bit_setup(struct iTCO_wdt_private *p,
223 struct itco_wdt_platform_data *pdata)
224{
225 if (pdata->update_no_reboot_bit) {
226 p->update_no_reboot_bit = pdata->update_no_reboot_bit;
227 p->no_reboot_priv = pdata->no_reboot_priv;
228 return;
207 } 229 }
208 230
209 if (val32 & enable_bit) 231 if (p->iTCO_version >= 2)
210 return -EIO; 232 p->update_no_reboot_bit = update_no_reboot_bit_mem;
233 else if (p->iTCO_version == 1)
234 p->update_no_reboot_bit = update_no_reboot_bit_pci;
235 else
236 p->update_no_reboot_bit = update_no_reboot_bit_def;
211 237
212 return 0; 238 p->no_reboot_priv = p;
213} 239}
214 240
215static int iTCO_wdt_start(struct watchdog_device *wd_dev) 241static int iTCO_wdt_start(struct watchdog_device *wd_dev)
@@ -222,7 +248,7 @@ static int iTCO_wdt_start(struct watchdog_device *wd_dev)
222 iTCO_vendor_pre_start(p->smi_res, wd_dev->timeout); 248 iTCO_vendor_pre_start(p->smi_res, wd_dev->timeout);
223 249
224 /* disable chipset's NO_REBOOT bit */ 250 /* disable chipset's NO_REBOOT bit */
225 if (iTCO_wdt_unset_NO_REBOOT_bit(p)) { 251 if (p->update_no_reboot_bit(p->no_reboot_priv, false)) {
226 spin_unlock(&p->io_lock); 252 spin_unlock(&p->io_lock);
227 pr_err("failed to reset NO_REBOOT flag, reboot disabled by hardware/BIOS\n"); 253 pr_err("failed to reset NO_REBOOT flag, reboot disabled by hardware/BIOS\n");
228 return -EIO; 254 return -EIO;
@@ -263,7 +289,7 @@ static int iTCO_wdt_stop(struct watchdog_device *wd_dev)
263 val = inw(TCO1_CNT(p)); 289 val = inw(TCO1_CNT(p));
264 290
265 /* Set the NO_REBOOT bit to prevent later reboots, just for sure */ 291 /* Set the NO_REBOOT bit to prevent later reboots, just for sure */
266 iTCO_wdt_set_NO_REBOOT_bit(p); 292 p->update_no_reboot_bit(p->no_reboot_priv, true);
267 293
268 spin_unlock(&p->io_lock); 294 spin_unlock(&p->io_lock);
269 295
@@ -428,11 +454,13 @@ static int iTCO_wdt_probe(struct platform_device *pdev)
428 p->iTCO_version = pdata->version; 454 p->iTCO_version = pdata->version;
429 p->pci_dev = to_pci_dev(dev->parent); 455 p->pci_dev = to_pci_dev(dev->parent);
430 456
457 iTCO_wdt_no_reboot_bit_setup(p, pdata);
458
431 /* 459 /*
432 * Get the Memory-Mapped GCS or PMC register, we need it for the 460 * Get the Memory-Mapped GCS or PMC register, we need it for the
433 * NO_REBOOT flag (TCO v2 and v3). 461 * NO_REBOOT flag (TCO v2 and v3).
434 */ 462 */
435 if (p->iTCO_version >= 2) { 463 if (p->iTCO_version >= 2 && !pdata->update_no_reboot_bit) {
436 p->gcs_pmc_res = platform_get_resource(pdev, 464 p->gcs_pmc_res = platform_get_resource(pdev,
437 IORESOURCE_MEM, 465 IORESOURCE_MEM,
438 ICH_RES_MEM_GCS_PMC); 466 ICH_RES_MEM_GCS_PMC);
@@ -442,14 +470,14 @@ static int iTCO_wdt_probe(struct platform_device *pdev)
442 } 470 }
443 471
444 /* Check chipset's NO_REBOOT bit */ 472 /* Check chipset's NO_REBOOT bit */
445 if (iTCO_wdt_unset_NO_REBOOT_bit(p) && 473 if (p->update_no_reboot_bit(p->no_reboot_priv, false) &&
446 iTCO_vendor_check_noreboot_on()) { 474 iTCO_vendor_check_noreboot_on()) {
447 pr_info("unable to reset NO_REBOOT flag, device disabled by hardware/BIOS\n"); 475 pr_info("unable to reset NO_REBOOT flag, device disabled by hardware/BIOS\n");
448 return -ENODEV; /* Cannot reset NO_REBOOT bit */ 476 return -ENODEV; /* Cannot reset NO_REBOOT bit */
449 } 477 }
450 478
451 /* Set the NO_REBOOT bit to prevent later reboots, just for sure */ 479 /* Set the NO_REBOOT bit to prevent later reboots, just for sure */
452 iTCO_wdt_set_NO_REBOOT_bit(p); 480 p->update_no_reboot_bit(p->no_reboot_priv, true);
453 481
454 /* The TCO logic uses the TCO_EN bit in the SMI_EN register */ 482 /* The TCO logic uses the TCO_EN bit in the SMI_EN register */
455 if (!devm_request_region(dev, p->smi_res->start, 483 if (!devm_request_region(dev, p->smi_res->start,
diff --git a/include/linux/platform_data/itco_wdt.h b/include/linux/platform_data/itco_wdt.h
index f16542c77ff7..0e95527edf25 100644
--- a/include/linux/platform_data/itco_wdt.h
+++ b/include/linux/platform_data/itco_wdt.h
@@ -14,6 +14,10 @@
14struct itco_wdt_platform_data { 14struct itco_wdt_platform_data {
15 char name[32]; 15 char name[32];
16 unsigned int version; 16 unsigned int version;
17 /* private data to be passed to update_no_reboot_bit API */
18 void *no_reboot_priv;
19 /* pointer for platform specific no reboot update function */
20 int (*update_no_reboot_bit)(void *priv, bool set);
17}; 21};
18 22
19#endif /* _ITCO_WDT_H_ */ 23#endif /* _ITCO_WDT_H_ */