aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/testing/sysfs-devices-system-ibm-rtl22
-rw-r--r--MAINTAINERS4
-rw-r--r--arch/x86/include/asm/olpc.h2
-rw-r--r--drivers/hwmon/Kconfig20
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/platform/x86/Kconfig53
-rw-r--r--drivers/platform/x86/Makefile6
-rw-r--r--drivers/platform/x86/acer-wmi.c2
-rw-r--r--drivers/platform/x86/asus-laptop.c171
-rw-r--r--drivers/platform/x86/dell-laptop.c77
-rw-r--r--drivers/platform/x86/dell-wmi.c256
-rw-r--r--drivers/platform/x86/eeepc-laptop.c16
-rw-r--r--drivers/platform/x86/eeepc-wmi.c56
-rw-r--r--drivers/platform/x86/hdaps.c (renamed from drivers/hwmon/hdaps.c)2
-rw-r--r--drivers/platform/x86/hp-wmi.c172
-rw-r--r--drivers/platform/x86/ibm_rtl.c341
-rw-r--r--drivers/platform/x86/ideapad-laptop.c (renamed from drivers/platform/x86/ideapad_acpi.c)238
-rw-r--r--drivers/platform/x86/intel_pmic_gpio.c26
-rw-r--r--drivers/platform/x86/intel_scu_ipc.c1
-rw-r--r--drivers/platform/x86/panasonic-laptop.c194
-rw-r--r--drivers/platform/x86/topstar-laptop.c161
-rw-r--r--drivers/platform/x86/toshiba_acpi.c191
-rw-r--r--drivers/platform/x86/wmi.c308
-rw-r--r--drivers/platform/x86/xo1-rfkill.c85
24 files changed, 1370 insertions, 1035 deletions
diff --git a/Documentation/ABI/testing/sysfs-devices-system-ibm-rtl b/Documentation/ABI/testing/sysfs-devices-system-ibm-rtl
new file mode 100644
index 000000000000..b82deeaec314
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-devices-system-ibm-rtl
@@ -0,0 +1,22 @@
1What: state
2Date: Sep 2010
3KernelVersion: 2.6.37
4Contact: Vernon Mauery <vernux@us.ibm.com>
5Description: The state file allows a means by which to change in and
6 out of Premium Real-Time Mode (PRTM), as well as the
7 ability to query the current state.
8 0 => PRTM off
9 1 => PRTM enabled
10Users: The ibm-prtm userspace daemon uses this interface.
11
12
13What: version
14Date: Sep 2010
15KernelVersion: 2.6.37
16Contact: Vernon Mauery <vernux@us.ibm.com>
17Description: The version file provides a means by which to query
18 the RTL table version that lives in the Extended
19 BIOS Data Area (EBDA).
20Users: The ibm-prtm userspace daemon uses this interface.
21
22
diff --git a/MAINTAINERS b/MAINTAINERS
index 69aa8fe060b3..3e95a81e71e0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2646,10 +2646,10 @@ F: drivers/net/greth*
2646 2646
2647HARD DRIVE ACTIVE PROTECTION SYSTEM (HDAPS) DRIVER 2647HARD DRIVE ACTIVE PROTECTION SYSTEM (HDAPS) DRIVER
2648M: Frank Seidel <frank@f-seidel.de> 2648M: Frank Seidel <frank@f-seidel.de>
2649L: lm-sensors@lm-sensors.org 2649L: platform-driver-x86@vger.kernel.org
2650W: http://www.kernel.org/pub/linux/kernel/people/fseidel/hdaps/ 2650W: http://www.kernel.org/pub/linux/kernel/people/fseidel/hdaps/
2651S: Maintained 2651S: Maintained
2652F: drivers/hwmon/hdaps.c 2652F: drivers/platform/x86/hdaps.c
2653 2653
2654HWPOISON MEMORY FAILURE HANDLING 2654HWPOISON MEMORY FAILURE HANDLING
2655M: Andi Kleen <andi@firstfloor.org> 2655M: Andi Kleen <andi@firstfloor.org>
diff --git a/arch/x86/include/asm/olpc.h b/arch/x86/include/asm/olpc.h
index 101229b0d8ed..42a978c0c1b3 100644
--- a/arch/x86/include/asm/olpc.h
+++ b/arch/x86/include/asm/olpc.h
@@ -89,6 +89,8 @@ extern int olpc_ec_mask_unset(uint8_t bits);
89/* EC commands */ 89/* EC commands */
90 90
91#define EC_FIRMWARE_REV 0x08 91#define EC_FIRMWARE_REV 0x08
92#define EC_WLAN_ENTER_RESET 0x35
93#define EC_WLAN_LEAVE_RESET 0x25
92 94
93/* SCI source values */ 95/* SCI source values */
94 96
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 97499d00615a..e382da3122b7 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1088,26 +1088,6 @@ config SENSORS_ULTRA45
1088 This driver provides support for the Ultra45 workstation environmental 1088 This driver provides support for the Ultra45 workstation environmental
1089 sensors. 1089 sensors.
1090 1090
1091config SENSORS_HDAPS
1092 tristate "IBM Hard Drive Active Protection System (hdaps)"
1093 depends on INPUT && X86
1094 select INPUT_POLLDEV
1095 default n
1096 help
1097 This driver provides support for the IBM Hard Drive Active Protection
1098 System (hdaps), which provides an accelerometer and other misc. data.
1099 ThinkPads starting with the R50, T41, and X40 are supported. The
1100 accelerometer data is readable via sysfs.
1101
1102 This driver also provides an absolute input class device, allowing
1103 the laptop to act as a pinball machine-esque joystick.
1104
1105 If your ThinkPad is not recognized by the driver, please update to latest
1106 BIOS. This is especially the case for some R52 ThinkPads.
1107
1108 Say Y here if you have an applicable laptop and want to experience
1109 the awesome power of hdaps.
1110
1111config SENSORS_LIS3_SPI 1091config SENSORS_LIS3_SPI
1112 tristate "STMicroeletronics LIS3LV02Dx three-axis digital accelerometer (SPI)" 1092 tristate "STMicroeletronics LIS3LV02Dx three-axis digital accelerometer (SPI)"
1113 depends on !ACPI && SPI_MASTER && INPUT 1093 depends on !ACPI && SPI_MASTER && INPUT
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index e3c2484f6c5f..ec9cb735c898 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -52,7 +52,6 @@ obj-$(CONFIG_SENSORS_G760A) += g760a.o
52obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o 52obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o
53obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o 53obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o
54obj-$(CONFIG_SENSORS_ULTRA45) += ultra45_env.o 54obj-$(CONFIG_SENSORS_ULTRA45) += ultra45_env.o
55obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o
56obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o 55obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o
57obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o 56obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o
58obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o 57obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index cff7cc2c1f02..faec777b1ed4 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -92,6 +92,7 @@ config DELL_WMI
92 tristate "Dell WMI extras" 92 tristate "Dell WMI extras"
93 depends on ACPI_WMI 93 depends on ACPI_WMI
94 depends on INPUT 94 depends on INPUT
95 select INPUT_SPARSEKMAP
95 ---help--- 96 ---help---
96 Say Y here if you want to support WMI-based hotkeys on Dell laptops. 97 Say Y here if you want to support WMI-based hotkeys on Dell laptops.
97 98
@@ -140,6 +141,7 @@ config HP_WMI
140 depends on ACPI_WMI 141 depends on ACPI_WMI
141 depends on INPUT 142 depends on INPUT
142 depends on RFKILL || RFKILL = n 143 depends on RFKILL || RFKILL = n
144 select INPUT_SPARSEKMAP
143 help 145 help
144 Say Y here if you want to support WMI-based hotkeys on HP laptops and 146 Say Y here if you want to support WMI-based hotkeys on HP laptops and
145 to read data from WMI such as docking or ambient light sensor state. 147 to read data from WMI such as docking or ambient light sensor state.
@@ -171,6 +173,7 @@ config PANASONIC_LAPTOP
171 tristate "Panasonic Laptop Extras" 173 tristate "Panasonic Laptop Extras"
172 depends on INPUT && ACPI 174 depends on INPUT && ACPI
173 depends on BACKLIGHT_CLASS_DEVICE 175 depends on BACKLIGHT_CLASS_DEVICE
176 select INPUT_SPARSEKMAP
174 ---help--- 177 ---help---
175 This driver adds support for access to backlight control and hotkeys 178 This driver adds support for access to backlight control and hotkeys
176 on Panasonic Let's Note laptops. 179 on Panasonic Let's Note laptops.
@@ -219,8 +222,8 @@ config SONYPI_COMPAT
219 ---help--- 222 ---help---
220 Build the sonypi driver compatibility code into the sony-laptop driver. 223 Build the sonypi driver compatibility code into the sony-laptop driver.
221 224
222config IDEAPAD_ACPI 225config IDEAPAD_LAPTOP
223 tristate "Lenovo IdeaPad ACPI Laptop Extras" 226 tristate "Lenovo IdeaPad Laptop Extras"
224 depends on ACPI 227 depends on ACPI
225 depends on RFKILL 228 depends on RFKILL
226 help 229 help
@@ -365,6 +368,26 @@ config THINKPAD_ACPI_HOTKEY_POLL
365 If you are not sure, say Y here. The driver enables polling only if 368 If you are not sure, say Y here. The driver enables polling only if
366 it is strictly necessary to do so. 369 it is strictly necessary to do so.
367 370
371config SENSORS_HDAPS
372 tristate "Thinkpad Hard Drive Active Protection System (hdaps)"
373 depends on INPUT && X86
374 select INPUT_POLLDEV
375 default n
376 help
377 This driver provides support for the IBM Hard Drive Active Protection
378 System (hdaps), which provides an accelerometer and other misc. data.
379 ThinkPads starting with the R50, T41, and X40 are supported. The
380 accelerometer data is readable via sysfs.
381
382 This driver also provides an absolute input class device, allowing
383 the laptop to act as a pinball machine-esque joystick.
384
385 If your ThinkPad is not recognized by the driver, please update to latest
386 BIOS. This is especially the case for some R52 ThinkPads.
387
388 Say Y here if you have an applicable laptop and want to experience
389 the awesome power of hdaps.
390
368config INTEL_MENLOW 391config INTEL_MENLOW
369 tristate "Thermal Management driver for Intel menlow platform" 392 tristate "Thermal Management driver for Intel menlow platform"
370 depends on ACPI_THERMAL 393 depends on ACPI_THERMAL
@@ -478,6 +501,7 @@ config TOPSTAR_LAPTOP
478 tristate "Topstar Laptop Extras" 501 tristate "Topstar Laptop Extras"
479 depends on ACPI 502 depends on ACPI
480 depends on INPUT 503 depends on INPUT
504 select INPUT_SPARSEKMAP
481 ---help--- 505 ---help---
482 This driver adds support for hotkeys found on Topstar laptops. 506 This driver adds support for hotkeys found on Topstar laptops.
483 507
@@ -492,6 +516,7 @@ config ACPI_TOSHIBA
492 depends on INPUT 516 depends on INPUT
493 depends on RFKILL || RFKILL = n 517 depends on RFKILL || RFKILL = n
494 select INPUT_POLLDEV 518 select INPUT_POLLDEV
519 select INPUT_SPARSEKMAP
495 ---help--- 520 ---help---
496 This driver adds support for access to certain system settings 521 This driver adds support for access to certain system settings
497 on "legacy free" Toshiba laptops. These laptops can be recognized by 522 on "legacy free" Toshiba laptops. These laptops can be recognized by
@@ -590,4 +615,28 @@ config INTEL_IPS
590 functionality. If in doubt, say Y here; it will only load on 615 functionality. If in doubt, say Y here; it will only load on
591 supported platforms. 616 supported platforms.
592 617
618config IBM_RTL
619 tristate "Device driver to enable PRTL support"
620 depends on X86 && PCI
621 ---help---
622 Enable support for IBM Premium Real Time Mode (PRTM).
623 This module will allow you the enter and exit PRTM in the BIOS via
624 sysfs on platforms that support this feature. System in PRTM will
625 not receive CPU-generated SMIs for recoverable errors. Use of this
626 feature without proper support may void your hardware warranty.
627
628 If the proper BIOS support is found the driver will load and create
629 /sys/devices/system/ibm_rtl/. The "state" variable will indicate
630 whether or not the BIOS is in PRTM.
631 state = 0 (BIOS SMIs on)
632 state = 1 (BIOS SMIs off)
633
634config XO1_RFKILL
635 tristate "OLPC XO-1 software RF kill switch"
636 depends on OLPC
637 depends on RFKILL
638 ---help---
639 Support for enabling/disabling the WLAN interface on the OLPC XO-1
640 laptop.
641
593endif # X86_PLATFORM_DEVICES 642endif # X86_PLATFORM_DEVICES
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index 85fb2b84f57e..9950ccc940b5 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -15,8 +15,9 @@ obj-$(CONFIG_ACERHDF) += acerhdf.o
15obj-$(CONFIG_HP_WMI) += hp-wmi.o 15obj-$(CONFIG_HP_WMI) += hp-wmi.o
16obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o 16obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o
17obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o 17obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o
18obj-$(CONFIG_IDEAPAD_ACPI) += ideapad_acpi.o 18obj-$(CONFIG_IDEAPAD_LAPTOP) += ideapad-laptop.o
19obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o 19obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o
20obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o
20obj-$(CONFIG_FUJITSU_LAPTOP) += fujitsu-laptop.o 21obj-$(CONFIG_FUJITSU_LAPTOP) += fujitsu-laptop.o
21obj-$(CONFIG_PANASONIC_LAPTOP) += panasonic-laptop.o 22obj-$(CONFIG_PANASONIC_LAPTOP) += panasonic-laptop.o
22obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o 23obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o
@@ -30,4 +31,5 @@ obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o
30obj-$(CONFIG_RAR_REGISTER) += intel_rar_register.o 31obj-$(CONFIG_RAR_REGISTER) += intel_rar_register.o
31obj-$(CONFIG_INTEL_IPS) += intel_ips.o 32obj-$(CONFIG_INTEL_IPS) += intel_ips.o
32obj-$(CONFIG_GPIO_INTEL_PMIC) += intel_pmic_gpio.o 33obj-$(CONFIG_GPIO_INTEL_PMIC) += intel_pmic_gpio.o
33 34obj-$(CONFIG_XO1_RFKILL) += xo1-rfkill.o
35obj-$(CONFIG_IBM_RTL) += ibm_rtl.o
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index 2badee2fdeed..c8c65375bfe2 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -1314,7 +1314,7 @@ static int __init acer_wmi_init(void)
1314 AMW0_find_mailled(); 1314 AMW0_find_mailled();
1315 1315
1316 if (!interface) { 1316 if (!interface) {
1317 printk(ACER_ERR "No or unsupported WMI interface, unable to " 1317 printk(ACER_INFO "No or unsupported WMI interface, unable to "
1318 "load\n"); 1318 "load\n");
1319 return -ENODEV; 1319 return -ENODEV;
1320 } 1320 }
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index b756e07d41b4..60a5a5c6b50a 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -236,7 +236,6 @@ struct asus_laptop {
236 u8 light_level; /* light sensor level */ 236 u8 light_level; /* light sensor level */
237 u8 light_switch; /* light sensor switch value */ 237 u8 light_switch; /* light sensor switch value */
238 u16 event_count[128]; /* count for each event TODO make this better */ 238 u16 event_count[128]; /* count for each event TODO make this better */
239 u16 *keycode_map;
240}; 239};
241 240
242static const struct key_entry asus_keymap[] = { 241static const struct key_entry asus_keymap[] = {
@@ -278,6 +277,7 @@ static const struct key_entry asus_keymap[] = {
278 {KE_KEY, 0x99, { KEY_PHONE } }, 277 {KE_KEY, 0x99, { KEY_PHONE } },
279 {KE_KEY, 0xc4, { KEY_KBDILLUMUP } }, 278 {KE_KEY, 0xc4, { KEY_KBDILLUMUP } },
280 {KE_KEY, 0xc5, { KEY_KBDILLUMDOWN } }, 279 {KE_KEY, 0xc5, { KEY_KBDILLUMDOWN } },
280 {KE_KEY, 0xb5, { KEY_CALC } },
281 {KE_END, 0}, 281 {KE_END, 0},
282}; 282};
283 283
@@ -639,29 +639,29 @@ static int asus_backlight_notify(struct asus_laptop *asus)
639static int asus_backlight_init(struct asus_laptop *asus) 639static int asus_backlight_init(struct asus_laptop *asus)
640{ 640{
641 struct backlight_device *bd; 641 struct backlight_device *bd;
642 struct device *dev = &asus->platform_device->dev;
643 struct backlight_properties props; 642 struct backlight_properties props;
644 643
645 if (!acpi_check_handle(asus->handle, METHOD_BRIGHTNESS_GET, NULL) && 644 if (acpi_check_handle(asus->handle, METHOD_BRIGHTNESS_GET, NULL) ||
646 !acpi_check_handle(asus->handle, METHOD_BRIGHTNESS_SET, NULL) && 645 acpi_check_handle(asus->handle, METHOD_BRIGHTNESS_SET, NULL) ||
647 lcd_switch_handle) { 646 !lcd_switch_handle)
648 memset(&props, 0, sizeof(struct backlight_properties)); 647 return 0;
649 props.max_brightness = 15;
650
651 bd = backlight_device_register(ASUS_LAPTOP_FILE, dev,
652 asus, &asusbl_ops, &props);
653 if (IS_ERR(bd)) {
654 pr_err("Could not register asus backlight device\n");
655 asus->backlight_device = NULL;
656 return PTR_ERR(bd);
657 }
658 648
659 asus->backlight_device = bd; 649 memset(&props, 0, sizeof(struct backlight_properties));
650 props.max_brightness = 15;
660 651
661 bd->props.power = FB_BLANK_UNBLANK; 652 bd = backlight_device_register(ASUS_LAPTOP_FILE,
662 bd->props.brightness = asus_read_brightness(bd); 653 &asus->platform_device->dev, asus,
663 backlight_update_status(bd); 654 &asusbl_ops, &props);
655 if (IS_ERR(bd)) {
656 pr_err("Could not register asus backlight device\n");
657 asus->backlight_device = NULL;
658 return PTR_ERR(bd);
664 } 659 }
660
661 asus->backlight_device = bd;
662 bd->props.brightness = asus_read_brightness(bd);
663 bd->props.power = FB_BLANK_UNBLANK;
664 backlight_update_status(bd);
665 return 0; 665 return 0;
666} 666}
667 667
@@ -1065,9 +1065,9 @@ static ssize_t store_gps(struct device *dev, struct device_attribute *attr,
1065 */ 1065 */
1066static int asus_gps_rfkill_set(void *data, bool blocked) 1066static int asus_gps_rfkill_set(void *data, bool blocked)
1067{ 1067{
1068 acpi_handle handle = data; 1068 struct asus_laptop *asus = data;
1069 1069
1070 return asus_gps_switch(handle, !blocked); 1070 return asus_gps_switch(asus, !blocked);
1071} 1071}
1072 1072
1073static const struct rfkill_ops asus_gps_rfkill_ops = { 1073static const struct rfkill_ops asus_gps_rfkill_ops = {
@@ -1094,7 +1094,7 @@ static int asus_rfkill_init(struct asus_laptop *asus)
1094 1094
1095 asus->gps_rfkill = rfkill_alloc("asus-gps", &asus->platform_device->dev, 1095 asus->gps_rfkill = rfkill_alloc("asus-gps", &asus->platform_device->dev,
1096 RFKILL_TYPE_GPS, 1096 RFKILL_TYPE_GPS,
1097 &asus_gps_rfkill_ops, NULL); 1097 &asus_gps_rfkill_ops, asus);
1098 if (!asus->gps_rfkill) 1098 if (!asus->gps_rfkill)
1099 return -EINVAL; 1099 return -EINVAL;
1100 1100
@@ -1130,7 +1130,6 @@ static int asus_input_init(struct asus_laptop *asus)
1130 input->phys = ASUS_LAPTOP_FILE "/input0"; 1130 input->phys = ASUS_LAPTOP_FILE "/input0";
1131 input->id.bustype = BUS_HOST; 1131 input->id.bustype = BUS_HOST;
1132 input->dev.parent = &asus->platform_device->dev; 1132 input->dev.parent = &asus->platform_device->dev;
1133 input_set_drvdata(input, asus);
1134 1133
1135 error = sparse_keymap_setup(input, asus_keymap, NULL); 1134 error = sparse_keymap_setup(input, asus_keymap, NULL);
1136 if (error) { 1135 if (error) {
@@ -1159,6 +1158,7 @@ static void asus_input_exit(struct asus_laptop *asus)
1159 sparse_keymap_free(asus->inputdev); 1158 sparse_keymap_free(asus->inputdev);
1160 input_unregister_device(asus->inputdev); 1159 input_unregister_device(asus->inputdev);
1161 } 1160 }
1161 asus->inputdev = NULL;
1162} 1162}
1163 1163
1164/* 1164/*
@@ -1200,111 +1200,100 @@ static void asus_acpi_notify(struct acpi_device *device, u32 event)
1200 1200
1201static DEVICE_ATTR(infos, S_IRUGO, show_infos, NULL); 1201static DEVICE_ATTR(infos, S_IRUGO, show_infos, NULL);
1202static DEVICE_ATTR(wlan, S_IRUGO | S_IWUSR, show_wlan, store_wlan); 1202static DEVICE_ATTR(wlan, S_IRUGO | S_IWUSR, show_wlan, store_wlan);
1203static DEVICE_ATTR(bluetooth, S_IRUGO | S_IWUSR, show_bluetooth, 1203static DEVICE_ATTR(bluetooth, S_IRUGO | S_IWUSR,
1204 store_bluetooth); 1204 show_bluetooth, store_bluetooth);
1205static DEVICE_ATTR(display, S_IRUGO | S_IWUSR, show_disp, store_disp); 1205static DEVICE_ATTR(display, S_IRUGO | S_IWUSR, show_disp, store_disp);
1206static DEVICE_ATTR(ledd, S_IRUGO | S_IWUSR, show_ledd, store_ledd); 1206static DEVICE_ATTR(ledd, S_IRUGO | S_IWUSR, show_ledd, store_ledd);
1207static DEVICE_ATTR(ls_level, S_IRUGO | S_IWUSR, show_lslvl, store_lslvl); 1207static DEVICE_ATTR(ls_level, S_IRUGO | S_IWUSR, show_lslvl, store_lslvl);
1208static DEVICE_ATTR(ls_switch, S_IRUGO | S_IWUSR, show_lssw, store_lssw); 1208static DEVICE_ATTR(ls_switch, S_IRUGO | S_IWUSR, show_lssw, store_lssw);
1209static DEVICE_ATTR(gps, S_IRUGO | S_IWUSR, show_gps, store_gps); 1209static DEVICE_ATTR(gps, S_IRUGO | S_IWUSR, show_gps, store_gps);
1210 1210
1211static void asus_sysfs_exit(struct asus_laptop *asus) 1211static struct attribute *asus_attributes[] = {
1212{ 1212 &dev_attr_infos.attr,
1213 struct platform_device *device = asus->platform_device; 1213 &dev_attr_wlan.attr,
1214 1214 &dev_attr_bluetooth.attr,
1215 device_remove_file(&device->dev, &dev_attr_infos); 1215 &dev_attr_display.attr,
1216 device_remove_file(&device->dev, &dev_attr_wlan); 1216 &dev_attr_ledd.attr,
1217 device_remove_file(&device->dev, &dev_attr_bluetooth); 1217 &dev_attr_ls_level.attr,
1218 device_remove_file(&device->dev, &dev_attr_display); 1218 &dev_attr_ls_switch.attr,
1219 device_remove_file(&device->dev, &dev_attr_ledd); 1219 &dev_attr_gps.attr,
1220 device_remove_file(&device->dev, &dev_attr_ls_switch); 1220 NULL
1221 device_remove_file(&device->dev, &dev_attr_ls_level); 1221};
1222 device_remove_file(&device->dev, &dev_attr_gps);
1223}
1224 1222
1225static int asus_sysfs_init(struct asus_laptop *asus) 1223static mode_t asus_sysfs_is_visible(struct kobject *kobj,
1224 struct attribute *attr,
1225 int idx)
1226{ 1226{
1227 struct platform_device *device = asus->platform_device; 1227 struct device *dev = container_of(kobj, struct device, kobj);
1228 int err; 1228 struct platform_device *pdev = to_platform_device(dev);
1229 struct asus_laptop *asus = platform_get_drvdata(pdev);
1230 acpi_handle handle = asus->handle;
1231 bool supported;
1229 1232
1230 err = device_create_file(&device->dev, &dev_attr_infos); 1233 if (attr == &dev_attr_wlan.attr) {
1231 if (err) 1234 supported = !acpi_check_handle(handle, METHOD_WLAN, NULL);
1232 return err;
1233 1235
1234 if (!acpi_check_handle(asus->handle, METHOD_WLAN, NULL)) { 1236 } else if (attr == &dev_attr_bluetooth.attr) {
1235 err = device_create_file(&device->dev, &dev_attr_wlan); 1237 supported = !acpi_check_handle(handle, METHOD_BLUETOOTH, NULL);
1236 if (err)
1237 return err;
1238 }
1239 1238
1240 if (!acpi_check_handle(asus->handle, METHOD_BLUETOOTH, NULL)) { 1239 } else if (attr == &dev_attr_display.attr) {
1241 err = device_create_file(&device->dev, &dev_attr_bluetooth); 1240 supported = !acpi_check_handle(handle, METHOD_SWITCH_DISPLAY, NULL);
1242 if (err)
1243 return err;
1244 }
1245 1241
1246 if (!acpi_check_handle(asus->handle, METHOD_SWITCH_DISPLAY, NULL)) { 1242 } else if (attr == &dev_attr_ledd.attr) {
1247 err = device_create_file(&device->dev, &dev_attr_display); 1243 supported = !acpi_check_handle(handle, METHOD_LEDD, NULL);
1248 if (err)
1249 return err;
1250 }
1251 1244
1252 if (!acpi_check_handle(asus->handle, METHOD_LEDD, NULL)) { 1245 } else if (attr == &dev_attr_ls_switch.attr ||
1253 err = device_create_file(&device->dev, &dev_attr_ledd); 1246 attr == &dev_attr_ls_level.attr) {
1254 if (err) 1247 supported = !acpi_check_handle(handle, METHOD_ALS_CONTROL, NULL) &&
1255 return err; 1248 !acpi_check_handle(handle, METHOD_ALS_LEVEL, NULL);
1256 }
1257
1258 if (!acpi_check_handle(asus->handle, METHOD_ALS_CONTROL, NULL) &&
1259 !acpi_check_handle(asus->handle, METHOD_ALS_LEVEL, NULL)) {
1260 err = device_create_file(&device->dev, &dev_attr_ls_switch);
1261 if (err)
1262 return err;
1263 err = device_create_file(&device->dev, &dev_attr_ls_level);
1264 if (err)
1265 return err;
1266 }
1267 1249
1268 if (!acpi_check_handle(asus->handle, METHOD_GPS_ON, NULL) && 1250 } else if (attr == &dev_attr_gps.attr) {
1269 !acpi_check_handle(asus->handle, METHOD_GPS_OFF, NULL) && 1251 supported = !acpi_check_handle(handle, METHOD_GPS_ON, NULL) &&
1270 !acpi_check_handle(asus->handle, METHOD_GPS_STATUS, NULL)) { 1252 !acpi_check_handle(handle, METHOD_GPS_OFF, NULL) &&
1271 err = device_create_file(&device->dev, &dev_attr_gps); 1253 !acpi_check_handle(handle, METHOD_GPS_STATUS, NULL);
1272 if (err) 1254 } else {
1273 return err; 1255 supported = true;
1274 } 1256 }
1275 1257
1276 return err; 1258 return supported ? attr->mode : 0;
1277} 1259}
1278 1260
1261
1262static const struct attribute_group asus_attr_group = {
1263 .is_visible = asus_sysfs_is_visible,
1264 .attrs = asus_attributes,
1265};
1266
1279static int asus_platform_init(struct asus_laptop *asus) 1267static int asus_platform_init(struct asus_laptop *asus)
1280{ 1268{
1281 int err; 1269 int result;
1282 1270
1283 asus->platform_device = platform_device_alloc(ASUS_LAPTOP_FILE, -1); 1271 asus->platform_device = platform_device_alloc(ASUS_LAPTOP_FILE, -1);
1284 if (!asus->platform_device) 1272 if (!asus->platform_device)
1285 return -ENOMEM; 1273 return -ENOMEM;
1286 platform_set_drvdata(asus->platform_device, asus); 1274 platform_set_drvdata(asus->platform_device, asus);
1287 1275
1288 err = platform_device_add(asus->platform_device); 1276 result = platform_device_add(asus->platform_device);
1289 if (err) 1277 if (result)
1290 goto fail_platform_device; 1278 goto fail_platform_device;
1291 1279
1292 err = asus_sysfs_init(asus); 1280 result = sysfs_create_group(&asus->platform_device->dev.kobj,
1293 if (err) 1281 &asus_attr_group);
1282 if (result)
1294 goto fail_sysfs; 1283 goto fail_sysfs;
1284
1295 return 0; 1285 return 0;
1296 1286
1297fail_sysfs: 1287fail_sysfs:
1298 asus_sysfs_exit(asus);
1299 platform_device_del(asus->platform_device); 1288 platform_device_del(asus->platform_device);
1300fail_platform_device: 1289fail_platform_device:
1301 platform_device_put(asus->platform_device); 1290 platform_device_put(asus->platform_device);
1302 return err; 1291 return result;
1303} 1292}
1304 1293
1305static void asus_platform_exit(struct asus_laptop *asus) 1294static void asus_platform_exit(struct asus_laptop *asus)
1306{ 1295{
1307 asus_sysfs_exit(asus); 1296 sysfs_remove_group(&asus->platform_device->dev.kobj, &asus_attr_group);
1308 platform_device_unregister(asus->platform_device); 1297 platform_device_unregister(asus->platform_device);
1309} 1298}
1310 1299
@@ -1428,8 +1417,6 @@ static int asus_laptop_get_info(struct asus_laptop *asus)
1428 return AE_OK; 1417 return AE_OK;
1429} 1418}
1430 1419
1431static bool asus_device_present;
1432
1433static int __devinit asus_acpi_init(struct asus_laptop *asus) 1420static int __devinit asus_acpi_init(struct asus_laptop *asus)
1434{ 1421{
1435 int result = 0; 1422 int result = 0;
@@ -1474,6 +1461,8 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus)
1474 return result; 1461 return result;
1475} 1462}
1476 1463
1464static bool asus_device_present;
1465
1477static int __devinit asus_acpi_add(struct acpi_device *device) 1466static int __devinit asus_acpi_add(struct acpi_device *device)
1478{ 1467{
1479 struct asus_laptop *asus; 1468 struct asus_laptop *asus;
diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
index 4413975912e0..cf8a89a0d8f5 100644
--- a/drivers/platform/x86/dell-laptop.c
+++ b/drivers/platform/x86/dell-laptop.c
@@ -25,6 +25,8 @@
25#include <linux/mm.h> 25#include <linux/mm.h>
26#include <linux/i8042.h> 26#include <linux/i8042.h>
27#include <linux/slab.h> 27#include <linux/slab.h>
28#include <linux/debugfs.h>
29#include <linux/seq_file.h>
28#include "../../firmware/dcdbas.h" 30#include "../../firmware/dcdbas.h"
29 31
30#define BRIGHTNESS_TOKEN 0x7d 32#define BRIGHTNESS_TOKEN 0x7d
@@ -325,6 +327,75 @@ static const struct rfkill_ops dell_rfkill_ops = {
325 .query = dell_rfkill_query, 327 .query = dell_rfkill_query,
326}; 328};
327 329
330static struct dentry *dell_laptop_dir;
331
332static int dell_debugfs_show(struct seq_file *s, void *data)
333{
334 int status;
335
336 get_buffer();
337 dell_send_request(buffer, 17, 11);
338 status = buffer->output[1];
339 release_buffer();
340
341 seq_printf(s, "status:\t0x%X\n", status);
342 seq_printf(s, "Bit 0 : Hardware switch supported: %lu\n",
343 status & BIT(0));
344 seq_printf(s, "Bit 1 : Wifi locator supported: %lu\n",
345 (status & BIT(1)) >> 1);
346 seq_printf(s, "Bit 2 : Wifi is supported: %lu\n",
347 (status & BIT(2)) >> 2);
348 seq_printf(s, "Bit 3 : Bluetooth is supported: %lu\n",
349 (status & BIT(3)) >> 3);
350 seq_printf(s, "Bit 4 : WWAN is supported: %lu\n",
351 (status & BIT(4)) >> 4);
352 seq_printf(s, "Bit 5 : Wireless keyboard supported: %lu\n",
353 (status & BIT(5)) >> 5);
354 seq_printf(s, "Bit 8 : Wifi is installed: %lu\n",
355 (status & BIT(8)) >> 8);
356 seq_printf(s, "Bit 9 : Bluetooth is installed: %lu\n",
357 (status & BIT(9)) >> 9);
358 seq_printf(s, "Bit 10: WWAN is installed: %lu\n",
359 (status & BIT(10)) >> 10);
360 seq_printf(s, "Bit 16: Hardware switch is on: %lu\n",
361 (status & BIT(16)) >> 16);
362 seq_printf(s, "Bit 17: Wifi is blocked: %lu\n",
363 (status & BIT(17)) >> 17);
364 seq_printf(s, "Bit 18: Bluetooth is blocked: %lu\n",
365 (status & BIT(18)) >> 18);
366 seq_printf(s, "Bit 19: WWAN is blocked: %lu\n",
367 (status & BIT(19)) >> 19);
368
369 seq_printf(s, "\nhwswitch_state:\t0x%X\n", hwswitch_state);
370 seq_printf(s, "Bit 0 : Wifi controlled by switch: %lu\n",
371 hwswitch_state & BIT(0));
372 seq_printf(s, "Bit 1 : Bluetooth controlled by switch: %lu\n",
373 (hwswitch_state & BIT(1)) >> 1);
374 seq_printf(s, "Bit 2 : WWAN controlled by switch: %lu\n",
375 (hwswitch_state & BIT(2)) >> 2);
376 seq_printf(s, "Bit 7 : Wireless switch config locked: %lu\n",
377 (hwswitch_state & BIT(7)) >> 7);
378 seq_printf(s, "Bit 8 : Wifi locator enabled: %lu\n",
379 (hwswitch_state & BIT(8)) >> 8);
380 seq_printf(s, "Bit 15: Wifi locator setting locked: %lu\n",
381 (hwswitch_state & BIT(15)) >> 15);
382
383 return 0;
384}
385
386static int dell_debugfs_open(struct inode *inode, struct file *file)
387{
388 return single_open(file, dell_debugfs_show, inode->i_private);
389}
390
391static const struct file_operations dell_debugfs_fops = {
392 .owner = THIS_MODULE,
393 .open = dell_debugfs_open,
394 .read = seq_read,
395 .llseek = seq_lseek,
396 .release = single_release,
397};
398
328static void dell_update_rfkill(struct work_struct *ignored) 399static void dell_update_rfkill(struct work_struct *ignored)
329{ 400{
330 if (wifi_rfkill) 401 if (wifi_rfkill)
@@ -556,6 +627,11 @@ static int __init dell_init(void)
556 goto fail_filter; 627 goto fail_filter;
557 } 628 }
558 629
630 dell_laptop_dir = debugfs_create_dir("dell_laptop", NULL);
631 if (dell_laptop_dir != NULL)
632 debugfs_create_file("rfkill", 0444, dell_laptop_dir, NULL,
633 &dell_debugfs_fops);
634
559#ifdef CONFIG_ACPI 635#ifdef CONFIG_ACPI
560 /* In the event of an ACPI backlight being available, don't 636 /* In the event of an ACPI backlight being available, don't
561 * register the platform controller. 637 * register the platform controller.
@@ -615,6 +691,7 @@ fail_platform_driver:
615 691
616static void __exit dell_exit(void) 692static void __exit dell_exit(void)
617{ 693{
694 debugfs_remove_recursive(dell_laptop_dir);
618 i8042_remove_filter(dell_laptop_i8042_filter); 695 i8042_remove_filter(dell_laptop_i8042_filter);
619 cancel_delayed_work_sync(&dell_rfkill_work); 696 cancel_delayed_work_sync(&dell_rfkill_work);
620 backlight_device_unregister(dell_backlight_device); 697 backlight_device_unregister(dell_backlight_device);
diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c
index 08fb70f6d9bf..77f1d55414c6 100644
--- a/drivers/platform/x86/dell-wmi.c
+++ b/drivers/platform/x86/dell-wmi.c
@@ -29,6 +29,7 @@
29#include <linux/slab.h> 29#include <linux/slab.h>
30#include <linux/types.h> 30#include <linux/types.h>
31#include <linux/input.h> 31#include <linux/input.h>
32#include <linux/input/sparse-keymap.h>
32#include <acpi/acpi_drivers.h> 33#include <acpi/acpi_drivers.h>
33#include <linux/acpi.h> 34#include <linux/acpi.h>
34#include <linux/string.h> 35#include <linux/string.h>
@@ -44,78 +45,70 @@ static int acpi_video;
44 45
45MODULE_ALIAS("wmi:"DELL_EVENT_GUID); 46MODULE_ALIAS("wmi:"DELL_EVENT_GUID);
46 47
47struct key_entry {
48 char type; /* See KE_* below */
49 u16 code;
50 u16 keycode;
51};
52
53enum { KE_KEY, KE_SW, KE_IGNORE, KE_END };
54
55/* 48/*
56 * Certain keys are flagged as KE_IGNORE. All of these are either 49 * Certain keys are flagged as KE_IGNORE. All of these are either
57 * notifications (rather than requests for change) or are also sent 50 * notifications (rather than requests for change) or are also sent
58 * via the keyboard controller so should not be sent again. 51 * via the keyboard controller so should not be sent again.
59 */ 52 */
60 53
61static struct key_entry dell_legacy_wmi_keymap[] = { 54static const struct key_entry dell_wmi_legacy_keymap[] __initconst = {
62 {KE_KEY, 0xe045, KEY_PROG1}, 55 { KE_KEY, 0xe045, { KEY_PROG1 } },
63 {KE_KEY, 0xe009, KEY_EJECTCD}, 56 { KE_KEY, 0xe009, { KEY_EJECTCD } },
64 57
65 /* These also contain the brightness level at offset 6 */ 58 /* These also contain the brightness level at offset 6 */
66 {KE_KEY, 0xe006, KEY_BRIGHTNESSUP}, 59 { KE_KEY, 0xe006, { KEY_BRIGHTNESSUP } },
67 {KE_KEY, 0xe005, KEY_BRIGHTNESSDOWN}, 60 { KE_KEY, 0xe005, { KEY_BRIGHTNESSDOWN } },
68 61
69 /* Battery health status button */ 62 /* Battery health status button */
70 {KE_KEY, 0xe007, KEY_BATTERY}, 63 { KE_KEY, 0xe007, { KEY_BATTERY } },
71 64
72 /* This is actually for all radios. Although physically a 65 /* This is actually for all radios. Although physically a
73 * switch, the notification does not provide an indication of 66 * switch, the notification does not provide an indication of
74 * state and so it should be reported as a key */ 67 * state and so it should be reported as a key */
75 {KE_KEY, 0xe008, KEY_WLAN}, 68 { KE_KEY, 0xe008, { KEY_WLAN } },
76 69
77 /* The next device is at offset 6, the active devices are at 70 /* The next device is at offset 6, the active devices are at
78 offset 8 and the attached devices at offset 10 */ 71 offset 8 and the attached devices at offset 10 */
79 {KE_KEY, 0xe00b, KEY_SWITCHVIDEOMODE}, 72 { KE_KEY, 0xe00b, { KEY_SWITCHVIDEOMODE } },
80 73
81 {KE_IGNORE, 0xe00c, KEY_KBDILLUMTOGGLE}, 74 { KE_IGNORE, 0xe00c, { KEY_KBDILLUMTOGGLE } },
82 75
83 /* BIOS error detected */ 76 /* BIOS error detected */
84 {KE_IGNORE, 0xe00d, KEY_RESERVED}, 77 { KE_IGNORE, 0xe00d, { KEY_RESERVED } },
85 78
86 /* Wifi Catcher */ 79 /* Wifi Catcher */
87 {KE_KEY, 0xe011, KEY_PROG2}, 80 { KE_KEY, 0xe011, {KEY_PROG2 } },
88 81
89 /* Ambient light sensor toggle */ 82 /* Ambient light sensor toggle */
90 {KE_IGNORE, 0xe013, KEY_RESERVED}, 83 { KE_IGNORE, 0xe013, { KEY_RESERVED } },
91 84
92 {KE_IGNORE, 0xe020, KEY_MUTE}, 85 { KE_IGNORE, 0xe020, { KEY_MUTE } },
93 {KE_IGNORE, 0xe02e, KEY_VOLUMEDOWN}, 86 { KE_IGNORE, 0xe02e, { KEY_VOLUMEDOWN } },
94 {KE_IGNORE, 0xe030, KEY_VOLUMEUP}, 87 { KE_IGNORE, 0xe030, { KEY_VOLUMEUP } },
95 {KE_IGNORE, 0xe033, KEY_KBDILLUMUP}, 88 { KE_IGNORE, 0xe033, { KEY_KBDILLUMUP } },
96 {KE_IGNORE, 0xe034, KEY_KBDILLUMDOWN}, 89 { KE_IGNORE, 0xe034, { KEY_KBDILLUMDOWN } },
97 {KE_IGNORE, 0xe03a, KEY_CAPSLOCK}, 90 { KE_IGNORE, 0xe03a, { KEY_CAPSLOCK } },
98 {KE_IGNORE, 0xe045, KEY_NUMLOCK}, 91 { KE_IGNORE, 0xe045, { KEY_NUMLOCK } },
99 {KE_IGNORE, 0xe046, KEY_SCROLLLOCK}, 92 { KE_IGNORE, 0xe046, { KEY_SCROLLLOCK } },
100 {KE_END, 0} 93 { KE_END, 0 }
101}; 94};
102 95
103static bool dell_new_hk_type; 96static bool dell_new_hk_type;
104 97
105struct dell_new_keymap_entry { 98struct dell_bios_keymap_entry {
106 u16 scancode; 99 u16 scancode;
107 u16 keycode; 100 u16 keycode;
108}; 101};
109 102
110struct dell_hotkey_table { 103struct dell_bios_hotkey_table {
111 struct dmi_header header; 104 struct dmi_header header;
112 struct dell_new_keymap_entry keymap[]; 105 struct dell_bios_keymap_entry keymap[];
113 106
114}; 107};
115 108
116static struct key_entry *dell_new_wmi_keymap; 109static const struct dell_bios_hotkey_table *dell_bios_hotkey_table;
117 110
118static u16 bios_to_linux_keycode[256] = { 111static const u16 bios_to_linux_keycode[256] __initconst = {
119 112
120 KEY_MEDIA, KEY_NEXTSONG, KEY_PLAYPAUSE, KEY_PREVIOUSSONG, 113 KEY_MEDIA, KEY_NEXTSONG, KEY_PLAYPAUSE, KEY_PREVIOUSSONG,
121 KEY_STOPCD, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, 114 KEY_STOPCD, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
@@ -138,68 +131,11 @@ static u16 bios_to_linux_keycode[256] = {
138 KEY_PROG3 131 KEY_PROG3
139}; 132};
140 133
141
142static struct key_entry *dell_wmi_keymap = dell_legacy_wmi_keymap;
143
144static struct input_dev *dell_wmi_input_dev; 134static struct input_dev *dell_wmi_input_dev;
145 135
146static struct key_entry *dell_wmi_get_entry_by_scancode(unsigned int code)
147{
148 struct key_entry *key;
149
150 for (key = dell_wmi_keymap; key->type != KE_END; key++)
151 if (code == key->code)
152 return key;
153
154 return NULL;
155}
156
157static struct key_entry *dell_wmi_get_entry_by_keycode(unsigned int keycode)
158{
159 struct key_entry *key;
160
161 for (key = dell_wmi_keymap; key->type != KE_END; key++)
162 if (key->type == KE_KEY && keycode == key->keycode)
163 return key;
164
165 return NULL;
166}
167
168static int dell_wmi_getkeycode(struct input_dev *dev,
169 unsigned int scancode, unsigned int *keycode)
170{
171 struct key_entry *key = dell_wmi_get_entry_by_scancode(scancode);
172
173 if (key && key->type == KE_KEY) {
174 *keycode = key->keycode;
175 return 0;
176 }
177
178 return -EINVAL;
179}
180
181static int dell_wmi_setkeycode(struct input_dev *dev,
182 unsigned int scancode, unsigned int keycode)
183{
184 struct key_entry *key;
185 unsigned int old_keycode;
186
187 key = dell_wmi_get_entry_by_scancode(scancode);
188 if (key && key->type == KE_KEY) {
189 old_keycode = key->keycode;
190 key->keycode = keycode;
191 set_bit(keycode, dev->keybit);
192 if (!dell_wmi_get_entry_by_keycode(old_keycode))
193 clear_bit(old_keycode, dev->keybit);
194 return 0;
195 }
196 return -EINVAL;
197}
198
199static void dell_wmi_notify(u32 value, void *context) 136static void dell_wmi_notify(u32 value, void *context)
200{ 137{
201 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; 138 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
202 static struct key_entry *key;
203 union acpi_object *obj; 139 union acpi_object *obj;
204 acpi_status status; 140 acpi_status status;
205 141
@@ -212,8 +148,10 @@ static void dell_wmi_notify(u32 value, void *context)
212 obj = (union acpi_object *)response.pointer; 148 obj = (union acpi_object *)response.pointer;
213 149
214 if (obj && obj->type == ACPI_TYPE_BUFFER) { 150 if (obj && obj->type == ACPI_TYPE_BUFFER) {
151 const struct key_entry *key;
215 int reported_key; 152 int reported_key;
216 u16 *buffer_entry = (u16 *)obj->buffer.pointer; 153 u16 *buffer_entry = (u16 *)obj->buffer.pointer;
154
217 if (dell_new_hk_type && (buffer_entry[1] != 0x10)) { 155 if (dell_new_hk_type && (buffer_entry[1] != 0x10)) {
218 printk(KERN_INFO "dell-wmi: Received unknown WMI event" 156 printk(KERN_INFO "dell-wmi: Received unknown WMI event"
219 " (0x%x)\n", buffer_entry[1]); 157 " (0x%x)\n", buffer_entry[1]);
@@ -226,8 +164,8 @@ static void dell_wmi_notify(u32 value, void *context)
226 else 164 else
227 reported_key = (int)buffer_entry[1] & 0xffff; 165 reported_key = (int)buffer_entry[1] & 0xffff;
228 166
229 key = dell_wmi_get_entry_by_scancode(reported_key); 167 key = sparse_keymap_entry_from_scancode(dell_wmi_input_dev,
230 168 reported_key);
231 if (!key) { 169 if (!key) {
232 printk(KERN_INFO "dell-wmi: Unknown key %x pressed\n", 170 printk(KERN_INFO "dell-wmi: Unknown key %x pressed\n",
233 reported_key); 171 reported_key);
@@ -237,92 +175,98 @@ static void dell_wmi_notify(u32 value, void *context)
237 * come via ACPI */ 175 * come via ACPI */
238 ; 176 ;
239 } else { 177 } else {
240 input_report_key(dell_wmi_input_dev, key->keycode, 1); 178 sparse_keymap_report_entry(dell_wmi_input_dev, key,
241 input_sync(dell_wmi_input_dev); 179 1, true);
242 input_report_key(dell_wmi_input_dev, key->keycode, 0);
243 input_sync(dell_wmi_input_dev);
244 } 180 }
245 } 181 }
246 kfree(obj); 182 kfree(obj);
247} 183}
248 184
249 185static const struct key_entry * __init dell_wmi_prepare_new_keymap(void)
250static void setup_new_hk_map(const struct dmi_header *dm)
251{ 186{
252 187 int hotkey_num = (dell_bios_hotkey_table->header.length - 4) /
188 sizeof(struct dell_bios_keymap_entry);
189 struct key_entry *keymap;
253 int i; 190 int i;
254 int hotkey_num = (dm->length-4)/sizeof(struct dell_new_keymap_entry);
255 struct dell_hotkey_table *table =
256 container_of(dm, struct dell_hotkey_table, header);
257 191
258 dell_new_wmi_keymap = kzalloc((hotkey_num+1) * 192 keymap = kcalloc(hotkey_num + 1, sizeof(struct key_entry), GFP_KERNEL);
259 sizeof(struct key_entry), GFP_KERNEL); 193 if (!keymap)
194 return NULL;
260 195
261 for (i = 0; i < hotkey_num; i++) { 196 for (i = 0; i < hotkey_num; i++) {
262 dell_new_wmi_keymap[i].type = KE_KEY; 197 const struct dell_bios_keymap_entry *bios_entry =
263 dell_new_wmi_keymap[i].code = table->keymap[i].scancode; 198 &dell_bios_hotkey_table->keymap[i];
264 dell_new_wmi_keymap[i].keycode = 199 keymap[i].type = KE_KEY;
265 (table->keymap[i].keycode > 255) ? 0 : 200 keymap[i].code = bios_entry->scancode;
266 bios_to_linux_keycode[table->keymap[i].keycode]; 201 keymap[i].keycode = bios_entry->keycode < 256 ?
202 bios_to_linux_keycode[bios_entry->keycode] :
203 KEY_RESERVED;
267 } 204 }
268 205
269 dell_new_wmi_keymap[i].type = KE_END; 206 keymap[hotkey_num].type = KE_END;
270 dell_new_wmi_keymap[i].code = 0;
271 dell_new_wmi_keymap[i].keycode = 0;
272
273 dell_wmi_keymap = dell_new_wmi_keymap;
274 207
208 return keymap;
275} 209}
276 210
277
278static void find_hk_type(const struct dmi_header *dm, void *dummy)
279{
280
281 if ((dm->type == 0xb2) && (dm->length > 6)) {
282 dell_new_hk_type = true;
283 setup_new_hk_map(dm);
284 }
285
286}
287
288
289static int __init dell_wmi_input_setup(void) 211static int __init dell_wmi_input_setup(void)
290{ 212{
291 struct key_entry *key;
292 int err; 213 int err;
293 214
294 dell_wmi_input_dev = input_allocate_device(); 215 dell_wmi_input_dev = input_allocate_device();
295
296 if (!dell_wmi_input_dev) 216 if (!dell_wmi_input_dev)
297 return -ENOMEM; 217 return -ENOMEM;
298 218
299 dell_wmi_input_dev->name = "Dell WMI hotkeys"; 219 dell_wmi_input_dev->name = "Dell WMI hotkeys";
300 dell_wmi_input_dev->phys = "wmi/input0"; 220 dell_wmi_input_dev->phys = "wmi/input0";
301 dell_wmi_input_dev->id.bustype = BUS_HOST; 221 dell_wmi_input_dev->id.bustype = BUS_HOST;
302 dell_wmi_input_dev->getkeycode = dell_wmi_getkeycode; 222
303 dell_wmi_input_dev->setkeycode = dell_wmi_setkeycode; 223 if (dell_new_hk_type) {
304 224 const struct key_entry *keymap = dell_wmi_prepare_new_keymap();
305 for (key = dell_wmi_keymap; key->type != KE_END; key++) { 225 if (!keymap) {
306 switch (key->type) { 226 err = -ENOMEM;
307 case KE_KEY: 227 goto err_free_dev;
308 set_bit(EV_KEY, dell_wmi_input_dev->evbit);
309 set_bit(key->keycode, dell_wmi_input_dev->keybit);
310 break;
311 case KE_SW:
312 set_bit(EV_SW, dell_wmi_input_dev->evbit);
313 set_bit(key->keycode, dell_wmi_input_dev->swbit);
314 break;
315 } 228 }
316 }
317 229
318 err = input_register_device(dell_wmi_input_dev); 230 err = sparse_keymap_setup(dell_wmi_input_dev, keymap, NULL);
319 231
320 if (err) { 232 /*
321 input_free_device(dell_wmi_input_dev); 233 * Sparse keymap library makes a copy of keymap so we
322 return err; 234 * don't need the original one that was allocated.
235 */
236 kfree(keymap);
237 } else {
238 err = sparse_keymap_setup(dell_wmi_input_dev,
239 dell_wmi_legacy_keymap, NULL);
323 } 240 }
241 if (err)
242 goto err_free_dev;
243
244 err = input_register_device(dell_wmi_input_dev);
245 if (err)
246 goto err_free_keymap;
324 247
325 return 0; 248 return 0;
249
250 err_free_keymap:
251 sparse_keymap_free(dell_wmi_input_dev);
252 err_free_dev:
253 input_free_device(dell_wmi_input_dev);
254 return err;
255}
256
257static void dell_wmi_input_destroy(void)
258{
259 sparse_keymap_free(dell_wmi_input_dev);
260 input_unregister_device(dell_wmi_input_dev);
261}
262
263static void __init find_hk_type(const struct dmi_header *dm, void *dummy)
264{
265 if (dm->type == 0xb2 && dm->length > 6) {
266 dell_new_hk_type = true;
267 dell_bios_hotkey_table =
268 container_of(dm, struct dell_bios_hotkey_table, header);
269 }
326} 270}
327 271
328static int __init dell_wmi_init(void) 272static int __init dell_wmi_init(void)
@@ -339,18 +283,13 @@ static int __init dell_wmi_init(void)
339 acpi_video = acpi_video_backlight_support(); 283 acpi_video = acpi_video_backlight_support();
340 284
341 err = dell_wmi_input_setup(); 285 err = dell_wmi_input_setup();
342 if (err) { 286 if (err)
343 if (dell_new_hk_type)
344 kfree(dell_wmi_keymap);
345 return err; 287 return err;
346 }
347 288
348 status = wmi_install_notify_handler(DELL_EVENT_GUID, 289 status = wmi_install_notify_handler(DELL_EVENT_GUID,
349 dell_wmi_notify, NULL); 290 dell_wmi_notify, NULL);
350 if (ACPI_FAILURE(status)) { 291 if (ACPI_FAILURE(status)) {
351 input_unregister_device(dell_wmi_input_dev); 292 dell_wmi_input_destroy();
352 if (dell_new_hk_type)
353 kfree(dell_wmi_keymap);
354 printk(KERN_ERR 293 printk(KERN_ERR
355 "dell-wmi: Unable to register notify handler - %d\n", 294 "dell-wmi: Unable to register notify handler - %d\n",
356 status); 295 status);
@@ -359,14 +298,11 @@ static int __init dell_wmi_init(void)
359 298
360 return 0; 299 return 0;
361} 300}
301module_init(dell_wmi_init);
362 302
363static void __exit dell_wmi_exit(void) 303static void __exit dell_wmi_exit(void)
364{ 304{
365 wmi_remove_notify_handler(DELL_EVENT_GUID); 305 wmi_remove_notify_handler(DELL_EVENT_GUID);
366 input_unregister_device(dell_wmi_input_dev); 306 dell_wmi_input_destroy();
367 if (dell_new_hk_type)
368 kfree(dell_wmi_keymap);
369} 307}
370
371module_init(dell_wmi_init);
372module_exit(dell_wmi_exit); 308module_exit(dell_wmi_exit);
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c
index 6b8e06206c46..b2edfdcdcb84 100644
--- a/drivers/platform/x86/eeepc-laptop.c
+++ b/drivers/platform/x86/eeepc-laptop.c
@@ -165,6 +165,7 @@ struct eeepc_laptop {
165 u16 event_count[128]; /* count for each event */ 165 u16 event_count[128]; /* count for each event */
166 166
167 struct platform_device *platform_device; 167 struct platform_device *platform_device;
168 struct acpi_device *device; /* the device we are in */
168 struct device *hwmon_device; 169 struct device *hwmon_device;
169 struct backlight_device *backlight_device; 170 struct backlight_device *backlight_device;
170 171
@@ -1193,9 +1194,9 @@ static int eeepc_input_init(struct eeepc_laptop *eeepc)
1193 eeepc->inputdev = input; 1194 eeepc->inputdev = input;
1194 return 0; 1195 return 0;
1195 1196
1196 err_free_keymap: 1197err_free_keymap:
1197 sparse_keymap_free(input); 1198 sparse_keymap_free(input);
1198 err_free_dev: 1199err_free_dev:
1199 input_free_device(input); 1200 input_free_device(input);
1200 return error; 1201 return error;
1201} 1202}
@@ -1206,6 +1207,7 @@ static void eeepc_input_exit(struct eeepc_laptop *eeepc)
1206 sparse_keymap_free(eeepc->inputdev); 1207 sparse_keymap_free(eeepc->inputdev);
1207 input_unregister_device(eeepc->inputdev); 1208 input_unregister_device(eeepc->inputdev);
1208 } 1209 }
1210 eeepc->inputdev = NULL;
1209} 1211}
1210 1212
1211/* 1213/*
@@ -1326,16 +1328,15 @@ static void cmsg_quirks(struct eeepc_laptop *eeepc)
1326 cmsg_quirk(eeepc, CM_ASL_TPD, "TPD"); 1328 cmsg_quirk(eeepc, CM_ASL_TPD, "TPD");
1327} 1329}
1328 1330
1329static int eeepc_acpi_init(struct eeepc_laptop *eeepc, 1331static int __devinit eeepc_acpi_init(struct eeepc_laptop *eeepc)
1330 struct acpi_device *device)
1331{ 1332{
1332 unsigned int init_flags; 1333 unsigned int init_flags;
1333 int result; 1334 int result;
1334 1335
1335 result = acpi_bus_get_status(device); 1336 result = acpi_bus_get_status(eeepc->device);
1336 if (result) 1337 if (result)
1337 return result; 1338 return result;
1338 if (!device->status.present) { 1339 if (!eeepc->device->status.present) {
1339 pr_err("Hotkey device not present, aborting\n"); 1340 pr_err("Hotkey device not present, aborting\n");
1340 return -ENODEV; 1341 return -ENODEV;
1341 } 1342 }
@@ -1384,12 +1385,13 @@ static int __devinit eeepc_acpi_add(struct acpi_device *device)
1384 strcpy(acpi_device_name(device), EEEPC_ACPI_DEVICE_NAME); 1385 strcpy(acpi_device_name(device), EEEPC_ACPI_DEVICE_NAME);
1385 strcpy(acpi_device_class(device), EEEPC_ACPI_CLASS); 1386 strcpy(acpi_device_class(device), EEEPC_ACPI_CLASS);
1386 device->driver_data = eeepc; 1387 device->driver_data = eeepc;
1388 eeepc->device = device;
1387 1389
1388 eeepc->hotplug_disabled = hotplug_disabled; 1390 eeepc->hotplug_disabled = hotplug_disabled;
1389 1391
1390 eeepc_dmi_check(eeepc); 1392 eeepc_dmi_check(eeepc);
1391 1393
1392 result = eeepc_acpi_init(eeepc, device); 1394 result = eeepc_acpi_init(eeepc);
1393 if (result) 1395 if (result)
1394 goto fail_platform; 1396 goto fail_platform;
1395 eeepc_enable_camera(eeepc); 1397 eeepc_enable_camera(eeepc);
diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c
index 9dc50fbf3d0b..462ceab93f87 100644
--- a/drivers/platform/x86/eeepc-wmi.c
+++ b/drivers/platform/x86/eeepc-wmi.c
@@ -57,6 +57,7 @@ MODULE_ALIAS("wmi:"EEEPC_WMI_MGMT_GUID);
57 57
58#define EEEPC_WMI_METHODID_DEVS 0x53564544 58#define EEEPC_WMI_METHODID_DEVS 0x53564544
59#define EEEPC_WMI_METHODID_DSTS 0x53544344 59#define EEEPC_WMI_METHODID_DSTS 0x53544344
60#define EEEPC_WMI_METHODID_CFVS 0x53564643
60 61
61#define EEEPC_WMI_DEVID_BACKLIGHT 0x00050012 62#define EEEPC_WMI_DEVID_BACKLIGHT 0x00050012
62 63
@@ -69,6 +70,11 @@ static const struct key_entry eeepc_wmi_keymap[] = {
69 { KE_IGNORE, NOTIFY_BRNDOWN_MIN, { KEY_BRIGHTNESSDOWN } }, 70 { KE_IGNORE, NOTIFY_BRNDOWN_MIN, { KEY_BRIGHTNESSDOWN } },
70 { KE_IGNORE, NOTIFY_BRNUP_MIN, { KEY_BRIGHTNESSUP } }, 71 { KE_IGNORE, NOTIFY_BRNUP_MIN, { KEY_BRIGHTNESSUP } },
71 { KE_KEY, 0xcc, { KEY_SWITCHVIDEOMODE } }, 72 { KE_KEY, 0xcc, { KEY_SWITCHVIDEOMODE } },
73 { KE_KEY, 0x6b, { KEY_F13 } }, /* Disable Touchpad */
74 { KE_KEY, 0xe1, { KEY_F14 } },
75 { KE_KEY, 0xe9, { KEY_DISPLAY_OFF } },
76 { KE_KEY, 0xe0, { KEY_PROG1 } },
77 { KE_KEY, 0x5c, { KEY_F15 } },
72 { KE_END, 0}, 78 { KE_END, 0},
73}; 79};
74 80
@@ -292,6 +298,49 @@ static void eeepc_wmi_notify(u32 value, void *context)
292 kfree(obj); 298 kfree(obj);
293} 299}
294 300
301static int store_cpufv(struct device *dev, struct device_attribute *attr,
302 const char *buf, size_t count)
303{
304 int value;
305 struct acpi_buffer input = { (acpi_size)sizeof(value), &value };
306 acpi_status status;
307
308 if (!count || sscanf(buf, "%i", &value) != 1)
309 return -EINVAL;
310 if (value < 0 || value > 2)
311 return -EINVAL;
312
313 status = wmi_evaluate_method(EEEPC_WMI_MGMT_GUID,
314 1, EEEPC_WMI_METHODID_CFVS, &input, NULL);
315
316 if (ACPI_FAILURE(status))
317 return -EIO;
318 else
319 return count;
320}
321
322static DEVICE_ATTR(cpufv, S_IRUGO | S_IWUSR, NULL, store_cpufv);
323
324static void eeepc_wmi_sysfs_exit(struct platform_device *device)
325{
326 device_remove_file(&device->dev, &dev_attr_cpufv);
327}
328
329static int eeepc_wmi_sysfs_init(struct platform_device *device)
330{
331 int retval = -ENOMEM;
332
333 retval = device_create_file(&device->dev, &dev_attr_cpufv);
334 if (retval)
335 goto error_sysfs;
336
337 return 0;
338
339error_sysfs:
340 eeepc_wmi_sysfs_exit(platform_device);
341 return retval;
342}
343
295static int __devinit eeepc_wmi_platform_probe(struct platform_device *device) 344static int __devinit eeepc_wmi_platform_probe(struct platform_device *device)
296{ 345{
297 struct eeepc_wmi *eeepc; 346 struct eeepc_wmi *eeepc;
@@ -387,8 +436,14 @@ static int __init eeepc_wmi_init(void)
387 goto del_dev; 436 goto del_dev;
388 } 437 }
389 438
439 err = eeepc_wmi_sysfs_init(platform_device);
440 if (err)
441 goto del_sysfs;
442
390 return 0; 443 return 0;
391 444
445del_sysfs:
446 eeepc_wmi_sysfs_exit(platform_device);
392del_dev: 447del_dev:
393 platform_device_del(platform_device); 448 platform_device_del(platform_device);
394put_dev: 449put_dev:
@@ -403,6 +458,7 @@ static void __exit eeepc_wmi_exit(void)
403{ 458{
404 struct eeepc_wmi *eeepc; 459 struct eeepc_wmi *eeepc;
405 460
461 eeepc_wmi_sysfs_exit(platform_device);
406 eeepc = platform_get_drvdata(platform_device); 462 eeepc = platform_get_drvdata(platform_device);
407 platform_driver_unregister(&platform_driver); 463 platform_driver_unregister(&platform_driver);
408 platform_device_unregister(platform_device); 464 platform_device_unregister(platform_device);
diff --git a/drivers/hwmon/hdaps.c b/drivers/platform/x86/hdaps.c
index bfd42f18924b..067bf36d32f3 100644
--- a/drivers/hwmon/hdaps.c
+++ b/drivers/platform/x86/hdaps.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * drivers/hwmon/hdaps.c - driver for IBM's Hard Drive Active Protection System 2 * hdaps.c - driver for IBM's Hard Drive Active Protection System
3 * 3 *
4 * Copyright (C) 2005 Robert Love <rml@novell.com> 4 * Copyright (C) 2005 Robert Love <rml@novell.com>
5 * Copyright (C) 2005 Jesper Juhl <jesper.juhl@gmail.com> 5 * Copyright (C) 2005 Jesper Juhl <jesper.juhl@gmail.com>
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c
index c1741142a4cb..1dac659b5e0c 100644
--- a/drivers/platform/x86/hp-wmi.c
+++ b/drivers/platform/x86/hp-wmi.c
@@ -29,6 +29,7 @@
29#include <linux/slab.h> 29#include <linux/slab.h>
30#include <linux/types.h> 30#include <linux/types.h>
31#include <linux/input.h> 31#include <linux/input.h>
32#include <linux/input/sparse-keymap.h>
32#include <linux/platform_device.h> 33#include <linux/platform_device.h>
33#include <linux/acpi.h> 34#include <linux/acpi.h>
34#include <linux/rfkill.h> 35#include <linux/rfkill.h>
@@ -88,24 +89,16 @@ struct bios_return {
88 u32 value; 89 u32 value;
89}; 90};
90 91
91struct key_entry { 92static const struct key_entry hp_wmi_keymap[] = {
92 char type; /* See KE_* below */ 93 { KE_KEY, 0x02, { KEY_BRIGHTNESSUP } },
93 u16 code; 94 { KE_KEY, 0x03, { KEY_BRIGHTNESSDOWN } },
94 u16 keycode; 95 { KE_KEY, 0x20e6, { KEY_PROG1 } },
95}; 96 { KE_KEY, 0x20e8, { KEY_MEDIA } },
96 97 { KE_KEY, 0x2142, { KEY_MEDIA } },
97enum { KE_KEY, KE_END }; 98 { KE_KEY, 0x213b, { KEY_INFO } },
98 99 { KE_KEY, 0x2169, { KEY_DIRECTION } },
99static struct key_entry hp_wmi_keymap[] = { 100 { KE_KEY, 0x231b, { KEY_HELP } },
100 {KE_KEY, 0x02, KEY_BRIGHTNESSUP}, 101 { KE_END, 0 }
101 {KE_KEY, 0x03, KEY_BRIGHTNESSDOWN},
102 {KE_KEY, 0x20e6, KEY_PROG1},
103 {KE_KEY, 0x20e8, KEY_MEDIA},
104 {KE_KEY, 0x2142, KEY_MEDIA},
105 {KE_KEY, 0x213b, KEY_INFO},
106 {KE_KEY, 0x2169, KEY_DIRECTION},
107 {KE_KEY, 0x231b, KEY_HELP},
108 {KE_END, 0}
109}; 102};
110 103
111static struct input_dev *hp_wmi_input_dev; 104static struct input_dev *hp_wmi_input_dev;
@@ -347,64 +340,9 @@ static DEVICE_ATTR(als, S_IRUGO | S_IWUSR, show_als, set_als);
347static DEVICE_ATTR(dock, S_IRUGO, show_dock, NULL); 340static DEVICE_ATTR(dock, S_IRUGO, show_dock, NULL);
348static DEVICE_ATTR(tablet, S_IRUGO, show_tablet, NULL); 341static DEVICE_ATTR(tablet, S_IRUGO, show_tablet, NULL);
349 342
350static struct key_entry *hp_wmi_get_entry_by_scancode(unsigned int code)
351{
352 struct key_entry *key;
353
354 for (key = hp_wmi_keymap; key->type != KE_END; key++)
355 if (code == key->code)
356 return key;
357
358 return NULL;
359}
360
361static struct key_entry *hp_wmi_get_entry_by_keycode(unsigned int keycode)
362{
363 struct key_entry *key;
364
365 for (key = hp_wmi_keymap; key->type != KE_END; key++)
366 if (key->type == KE_KEY && keycode == key->keycode)
367 return key;
368
369 return NULL;
370}
371
372static int hp_wmi_getkeycode(struct input_dev *dev,
373 unsigned int scancode, unsigned int *keycode)
374{
375 struct key_entry *key = hp_wmi_get_entry_by_scancode(scancode);
376
377 if (key && key->type == KE_KEY) {
378 *keycode = key->keycode;
379 return 0;
380 }
381
382 return -EINVAL;
383}
384
385static int hp_wmi_setkeycode(struct input_dev *dev,
386 unsigned int scancode, unsigned int keycode)
387{
388 struct key_entry *key;
389 unsigned int old_keycode;
390
391 key = hp_wmi_get_entry_by_scancode(scancode);
392 if (key && key->type == KE_KEY) {
393 old_keycode = key->keycode;
394 key->keycode = keycode;
395 set_bit(keycode, dev->keybit);
396 if (!hp_wmi_get_entry_by_keycode(old_keycode))
397 clear_bit(old_keycode, dev->keybit);
398 return 0;
399 }
400
401 return -EINVAL;
402}
403
404static void hp_wmi_notify(u32 value, void *context) 343static void hp_wmi_notify(u32 value, void *context)
405{ 344{
406 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; 345 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
407 static struct key_entry *key;
408 union acpi_object *obj; 346 union acpi_object *obj;
409 u32 event_id, event_data; 347 u32 event_id, event_data;
410 int key_code = 0, ret; 348 int key_code = 0, ret;
@@ -465,19 +403,9 @@ static void hp_wmi_notify(u32 value, void *context)
465 sizeof(key_code)); 403 sizeof(key_code));
466 if (ret) 404 if (ret)
467 break; 405 break;
468 key = hp_wmi_get_entry_by_scancode(key_code); 406
469 if (key) { 407 if (!sparse_keymap_report_event(hp_wmi_input_dev,
470 switch (key->type) { 408 key_code, 1, true))
471 case KE_KEY:
472 input_report_key(hp_wmi_input_dev,
473 key->keycode, 1);
474 input_sync(hp_wmi_input_dev);
475 input_report_key(hp_wmi_input_dev,
476 key->keycode, 0);
477 input_sync(hp_wmi_input_dev);
478 break;
479 }
480 } else
481 printk(KERN_INFO PREFIX "Unknown key code - 0x%x\n", 409 printk(KERN_INFO PREFIX "Unknown key code - 0x%x\n",
482 key_code); 410 key_code);
483 break; 411 break;
@@ -510,7 +438,7 @@ static void hp_wmi_notify(u32 value, void *context)
510 438
511static int __init hp_wmi_input_setup(void) 439static int __init hp_wmi_input_setup(void)
512{ 440{
513 struct key_entry *key; 441 acpi_status status;
514 int err; 442 int err;
515 443
516 hp_wmi_input_dev = input_allocate_device(); 444 hp_wmi_input_dev = input_allocate_device();
@@ -520,21 +448,14 @@ static int __init hp_wmi_input_setup(void)
520 hp_wmi_input_dev->name = "HP WMI hotkeys"; 448 hp_wmi_input_dev->name = "HP WMI hotkeys";
521 hp_wmi_input_dev->phys = "wmi/input0"; 449 hp_wmi_input_dev->phys = "wmi/input0";
522 hp_wmi_input_dev->id.bustype = BUS_HOST; 450 hp_wmi_input_dev->id.bustype = BUS_HOST;
523 hp_wmi_input_dev->getkeycode = hp_wmi_getkeycode;
524 hp_wmi_input_dev->setkeycode = hp_wmi_setkeycode;
525
526 for (key = hp_wmi_keymap; key->type != KE_END; key++) {
527 switch (key->type) {
528 case KE_KEY:
529 set_bit(EV_KEY, hp_wmi_input_dev->evbit);
530 set_bit(key->keycode, hp_wmi_input_dev->keybit);
531 break;
532 }
533 }
534 451
535 set_bit(EV_SW, hp_wmi_input_dev->evbit); 452 __set_bit(EV_SW, hp_wmi_input_dev->evbit);
536 set_bit(SW_DOCK, hp_wmi_input_dev->swbit); 453 __set_bit(SW_DOCK, hp_wmi_input_dev->swbit);
537 set_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit); 454 __set_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit);
455
456 err = sparse_keymap_setup(hp_wmi_input_dev, hp_wmi_keymap, NULL);
457 if (err)
458 goto err_free_dev;
538 459
539 /* Set initial hardware state */ 460 /* Set initial hardware state */
540 input_report_switch(hp_wmi_input_dev, SW_DOCK, hp_wmi_dock_state()); 461 input_report_switch(hp_wmi_input_dev, SW_DOCK, hp_wmi_dock_state());
@@ -542,14 +463,32 @@ static int __init hp_wmi_input_setup(void)
542 hp_wmi_tablet_state()); 463 hp_wmi_tablet_state());
543 input_sync(hp_wmi_input_dev); 464 input_sync(hp_wmi_input_dev);
544 465
545 err = input_register_device(hp_wmi_input_dev); 466 status = wmi_install_notify_handler(HPWMI_EVENT_GUID, hp_wmi_notify, NULL);
546 467 if (ACPI_FAILURE(status)) {
547 if (err) { 468 err = -EIO;
548 input_free_device(hp_wmi_input_dev); 469 goto err_free_keymap;
549 return err;
550 } 470 }
551 471
472 err = input_register_device(hp_wmi_input_dev);
473 if (err)
474 goto err_uninstall_notifier;
475
552 return 0; 476 return 0;
477
478 err_uninstall_notifier:
479 wmi_remove_notify_handler(HPWMI_EVENT_GUID);
480 err_free_keymap:
481 sparse_keymap_free(hp_wmi_input_dev);
482 err_free_dev:
483 input_free_device(hp_wmi_input_dev);
484 return err;
485}
486
487static void hp_wmi_input_destroy(void)
488{
489 wmi_remove_notify_handler(HPWMI_EVENT_GUID);
490 sparse_keymap_free(hp_wmi_input_dev);
491 input_unregister_device(hp_wmi_input_dev);
553} 492}
554 493
555static void cleanup_sysfs(struct platform_device *device) 494static void cleanup_sysfs(struct platform_device *device)
@@ -704,15 +643,9 @@ static int __init hp_wmi_init(void)
704 int bios_capable = wmi_has_guid(HPWMI_BIOS_GUID); 643 int bios_capable = wmi_has_guid(HPWMI_BIOS_GUID);
705 644
706 if (event_capable) { 645 if (event_capable) {
707 err = wmi_install_notify_handler(HPWMI_EVENT_GUID,
708 hp_wmi_notify, NULL);
709 if (ACPI_FAILURE(err))
710 return -EINVAL;
711 err = hp_wmi_input_setup(); 646 err = hp_wmi_input_setup();
712 if (err) { 647 if (err)
713 wmi_remove_notify_handler(HPWMI_EVENT_GUID);
714 return err; 648 return err;
715 }
716 } 649 }
717 650
718 if (bios_capable) { 651 if (bios_capable) {
@@ -739,20 +672,17 @@ err_device_add:
739err_device_alloc: 672err_device_alloc:
740 platform_driver_unregister(&hp_wmi_driver); 673 platform_driver_unregister(&hp_wmi_driver);
741err_driver_reg: 674err_driver_reg:
742 if (wmi_has_guid(HPWMI_EVENT_GUID)) { 675 if (event_capable)
743 input_unregister_device(hp_wmi_input_dev); 676 hp_wmi_input_destroy();
744 wmi_remove_notify_handler(HPWMI_EVENT_GUID);
745 }
746 677
747 return err; 678 return err;
748} 679}
749 680
750static void __exit hp_wmi_exit(void) 681static void __exit hp_wmi_exit(void)
751{ 682{
752 if (wmi_has_guid(HPWMI_EVENT_GUID)) { 683 if (wmi_has_guid(HPWMI_EVENT_GUID))
753 wmi_remove_notify_handler(HPWMI_EVENT_GUID); 684 hp_wmi_input_destroy();
754 input_unregister_device(hp_wmi_input_dev); 685
755 }
756 if (hp_wmi_platform_dev) { 686 if (hp_wmi_platform_dev) {
757 platform_device_unregister(hp_wmi_platform_dev); 687 platform_device_unregister(hp_wmi_platform_dev);
758 platform_driver_unregister(&hp_wmi_driver); 688 platform_driver_unregister(&hp_wmi_driver);
diff --git a/drivers/platform/x86/ibm_rtl.c b/drivers/platform/x86/ibm_rtl.c
new file mode 100644
index 000000000000..3c2c6b91ecb3
--- /dev/null
+++ b/drivers/platform/x86/ibm_rtl.c
@@ -0,0 +1,341 @@
1/*
2 * IBM Real-Time Linux driver
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 *
18 * Copyright (C) IBM Corporation, 2010
19 *
20 * Author: Keith Mannthey <kmannth@us.ibm.com>
21 * Vernon Mauery <vernux@us.ibm.com>
22 *
23 */
24
25#include <linux/kernel.h>
26#include <linux/delay.h>
27#include <linux/module.h>
28#include <linux/io.h>
29#include <linux/sysdev.h>
30#include <linux/dmi.h>
31#include <linux/mutex.h>
32#include <asm/bios_ebda.h>
33
34static bool force;
35module_param(force, bool, 0);
36MODULE_PARM_DESC(force, "Force driver load, ignore DMI data");
37
38static bool debug;
39module_param(debug, bool, 0644);
40MODULE_PARM_DESC(debug, "Show debug output");
41
42MODULE_LICENSE("GPL");
43MODULE_AUTHOR("Keith Mannthey <kmmanth@us.ibm.com>");
44MODULE_AUTHOR("Vernon Mauery <vernux@us.ibm.com>");
45
46#define RTL_ADDR_TYPE_IO 1
47#define RTL_ADDR_TYPE_MMIO 2
48
49#define RTL_CMD_ENTER_PRTM 1
50#define RTL_CMD_EXIT_PRTM 2
51
52/* The RTL table as presented by the EBDA: */
53struct ibm_rtl_table {
54 char signature[5]; /* signature should be "_RTL_" */
55 u8 version;
56 u8 rt_status;
57 u8 command;
58 u8 command_status;
59 u8 cmd_address_type;
60 u8 cmd_granularity;
61 u8 cmd_offset;
62 u16 reserve1;
63 u32 cmd_port_address; /* platform dependent address */
64 u32 cmd_port_value; /* platform dependent value */
65} __attribute__((packed));
66
67/* to locate "_RTL_" signature do a masked 5-byte integer compare */
68#define RTL_SIGNATURE 0x0000005f4c54525fULL
69#define RTL_MASK 0x000000ffffffffffULL
70
71#define RTL_DEBUG(A, ...) do { \
72 if (debug) \
73 pr_info("ibm-rtl: " A, ##__VA_ARGS__ ); \
74} while (0)
75
76static DEFINE_MUTEX(rtl_lock);
77static struct ibm_rtl_table __iomem *rtl_table;
78static void __iomem *ebda_map;
79static void __iomem *rtl_cmd_addr;
80static u8 rtl_cmd_type;
81static u8 rtl_cmd_width;
82
83static void __iomem *rtl_port_map(phys_addr_t addr, unsigned long len)
84{
85 if (rtl_cmd_type == RTL_ADDR_TYPE_MMIO)
86 return ioremap(addr, len);
87 return ioport_map(addr, len);
88}
89
90static void rtl_port_unmap(void __iomem *addr)
91{
92 if (addr && rtl_cmd_type == RTL_ADDR_TYPE_MMIO)
93 iounmap(addr);
94 else
95 ioport_unmap(addr);
96}
97
98static int ibm_rtl_write(u8 value)
99{
100 int ret = 0, count = 0;
101 static u32 cmd_port_val;
102
103 RTL_DEBUG("%s(%d)\n", __FUNCTION__, value);
104
105 value = value == 1 ? RTL_CMD_ENTER_PRTM : RTL_CMD_EXIT_PRTM;
106
107 mutex_lock(&rtl_lock);
108
109 if (ioread8(&rtl_table->rt_status) != value) {
110 iowrite8(value, &rtl_table->command);
111
112 switch (rtl_cmd_width) {
113 case 8:
114 cmd_port_val = ioread8(&rtl_table->cmd_port_value);
115 RTL_DEBUG("cmd_port_val = %u\n", cmd_port_val);
116 iowrite8((u8)cmd_port_val, rtl_cmd_addr);
117 break;
118 case 16:
119 cmd_port_val = ioread16(&rtl_table->cmd_port_value);
120 RTL_DEBUG("cmd_port_val = %u\n", cmd_port_val);
121 iowrite16((u16)cmd_port_val, rtl_cmd_addr);
122 break;
123 case 32:
124 cmd_port_val = ioread32(&rtl_table->cmd_port_value);
125 RTL_DEBUG("cmd_port_val = %u\n", cmd_port_val);
126 iowrite32(cmd_port_val, rtl_cmd_addr);
127 break;
128 }
129
130 while (ioread8(&rtl_table->command)) {
131 msleep(10);
132 if (count++ > 500) {
133 pr_err("ibm-rtl: Hardware not responding to "
134 "mode switch request\n");
135 ret = -EIO;
136 break;
137 }
138
139 }
140
141 if (ioread8(&rtl_table->command_status)) {
142 RTL_DEBUG("command_status reports failed command\n");
143 ret = -EIO;
144 }
145 }
146
147 mutex_unlock(&rtl_lock);
148 return ret;
149}
150
151static ssize_t rtl_show_version(struct sysdev_class * dev,
152 struct sysdev_class_attribute *attr,
153 char *buf)
154{
155 return sprintf(buf, "%d\n", (int)ioread8(&rtl_table->version));
156}
157
158static ssize_t rtl_show_state(struct sysdev_class *dev,
159 struct sysdev_class_attribute *attr,
160 char *buf)
161{
162 return sprintf(buf, "%d\n", ioread8(&rtl_table->rt_status));
163}
164
165static ssize_t rtl_set_state(struct sysdev_class *dev,
166 struct sysdev_class_attribute *attr,
167 const char *buf,
168 size_t count)
169{
170 ssize_t ret;
171
172 if (count < 1 || count > 2)
173 return -EINVAL;
174
175 switch (buf[0]) {
176 case '0':
177 ret = ibm_rtl_write(0);
178 break;
179 case '1':
180 ret = ibm_rtl_write(1);
181 break;
182 default:
183 ret = -EINVAL;
184 }
185 if (ret >= 0)
186 ret = count;
187
188 return ret;
189}
190
191static struct sysdev_class class_rtl = {
192 .name = "ibm_rtl",
193};
194
195static SYSDEV_CLASS_ATTR(version, S_IRUGO, rtl_show_version, NULL);
196static SYSDEV_CLASS_ATTR(state, 0600, rtl_show_state, rtl_set_state);
197
198static struct sysdev_class_attribute *rtl_attributes[] = {
199 &attr_version,
200 &attr_state,
201 NULL
202};
203
204
205static int rtl_setup_sysfs(void) {
206 int ret, i;
207 ret = sysdev_class_register(&class_rtl);
208
209 if (!ret) {
210 for (i = 0; rtl_attributes[i]; i ++)
211 sysdev_class_create_file(&class_rtl, rtl_attributes[i]);
212 }
213 return ret;
214}
215
216static void rtl_teardown_sysfs(void) {
217 int i;
218 for (i = 0; rtl_attributes[i]; i ++)
219 sysdev_class_remove_file(&class_rtl, rtl_attributes[i]);
220 sysdev_class_unregister(&class_rtl);
221}
222
223static int dmi_check_cb(const struct dmi_system_id *id)
224{
225 RTL_DEBUG("found IBM server '%s'\n", id->ident);
226 return 0;
227}
228
229#define ibm_dmi_entry(NAME, TYPE) \
230{ \
231 .ident = NAME, \
232 .matches = { \
233 DMI_MATCH(DMI_SYS_VENDOR, "IBM"), \
234 DMI_MATCH(DMI_PRODUCT_NAME, TYPE), \
235 }, \
236 .callback = dmi_check_cb \
237}
238
239static struct dmi_system_id __initdata ibm_rtl_dmi_table[] = {
240 ibm_dmi_entry("BladeCenter LS21", "7971"),
241 ibm_dmi_entry("BladeCenter LS22", "7901"),
242 ibm_dmi_entry("BladeCenter HS21 XM", "7995"),
243 ibm_dmi_entry("BladeCenter HS22", "7870"),
244 ibm_dmi_entry("BladeCenter HS22V", "7871"),
245 ibm_dmi_entry("System x3550 M2", "7946"),
246 ibm_dmi_entry("System x3650 M2", "7947"),
247 ibm_dmi_entry("System x3550 M3", "7944"),
248 ibm_dmi_entry("System x3650 M3", "7945"),
249 { }
250};
251
252static int __init ibm_rtl_init(void) {
253 unsigned long ebda_addr, ebda_size;
254 unsigned int ebda_kb;
255 int ret = -ENODEV, i;
256
257 if (force)
258 pr_warning("ibm-rtl: module loaded by force\n");
259 /* first ensure that we are running on IBM HW */
260 else if (!dmi_check_system(ibm_rtl_dmi_table))
261 return -ENODEV;
262
263 /* Get the address for the Extended BIOS Data Area */
264 ebda_addr = get_bios_ebda();
265 if (!ebda_addr) {
266 RTL_DEBUG("no BIOS EBDA found\n");
267 return -ENODEV;
268 }
269
270 ebda_map = ioremap(ebda_addr, 4);
271 if (!ebda_map)
272 return -ENOMEM;
273
274 /* First word in the EDBA is the Size in KB */
275 ebda_kb = ioread16(ebda_map);
276 RTL_DEBUG("EBDA is %d kB\n", ebda_kb);
277
278 if (ebda_kb == 0)
279 goto out;
280
281 iounmap(ebda_map);
282 ebda_size = ebda_kb*1024;
283
284 /* Remap the whole table */
285 ebda_map = ioremap(ebda_addr, ebda_size);
286 if (!ebda_map)
287 return -ENOMEM;
288
289 /* search for the _RTL_ signature at the start of the table */
290 for (i = 0 ; i < ebda_size/sizeof(unsigned int); i++) {
291 struct ibm_rtl_table __iomem * tmp;
292 tmp = (struct ibm_rtl_table __iomem *) (ebda_map+i);
293 if ((readq(&tmp->signature) & RTL_MASK) == RTL_SIGNATURE) {
294 phys_addr_t addr;
295 unsigned int plen;
296 RTL_DEBUG("found RTL_SIGNATURE at %#llx\n", (u64)tmp);
297 rtl_table = tmp;
298 /* The address, value, width and offset are platform
299 * dependent and found in the ibm_rtl_table */
300 rtl_cmd_width = ioread8(&rtl_table->cmd_granularity);
301 rtl_cmd_type = ioread8(&rtl_table->cmd_address_type);
302 RTL_DEBUG("rtl_cmd_width = %u, rtl_cmd_type = %u\n",
303 rtl_cmd_width, rtl_cmd_type);
304 addr = ioread32(&rtl_table->cmd_port_address);
305 RTL_DEBUG("addr = %#llx\n", addr);
306 plen = rtl_cmd_width/sizeof(char);
307 rtl_cmd_addr = rtl_port_map(addr, plen);
308 RTL_DEBUG("rtl_cmd_addr = %#llx\n", (u64)rtl_cmd_addr);
309 if (!rtl_cmd_addr) {
310 ret = -ENOMEM;
311 break;
312 }
313 ret = rtl_setup_sysfs();
314 break;
315 }
316 }
317
318out:
319 if (ret) {
320 iounmap(ebda_map);
321 rtl_port_unmap(rtl_cmd_addr);
322 }
323
324 return ret;
325}
326
327static void __exit ibm_rtl_exit(void)
328{
329 if (rtl_table) {
330 RTL_DEBUG("cleaning up");
331 /* do not leave the machine in SMI-free mode */
332 ibm_rtl_write(0);
333 /* unmap, unlink and remove all traces */
334 rtl_teardown_sysfs();
335 iounmap(ebda_map);
336 rtl_port_unmap(rtl_cmd_addr);
337 }
338}
339
340module_init(ibm_rtl_init);
341module_exit(ibm_rtl_exit);
diff --git a/drivers/platform/x86/ideapad_acpi.c b/drivers/platform/x86/ideapad-laptop.c
index 798496353e8c..5ff12205aa6b 100644
--- a/drivers/platform/x86/ideapad_acpi.c
+++ b/drivers/platform/x86/ideapad-laptop.c
@@ -35,112 +35,162 @@
35#define IDEAPAD_DEV_KILLSW 4 35#define IDEAPAD_DEV_KILLSW 4
36 36
37struct ideapad_private { 37struct ideapad_private {
38 acpi_handle handle;
38 struct rfkill *rfk[5]; 39 struct rfkill *rfk[5];
39}; 40} *ideapad_priv;
40 41
41static struct { 42static struct {
42 char *name; 43 char *name;
44 int cfgbit;
45 int opcode;
43 int type; 46 int type;
44} ideapad_rfk_data[] = { 47} ideapad_rfk_data[] = {
45 /* camera has no rfkill */ 48 { "ideapad_camera", 19, 0x1E, NUM_RFKILL_TYPES },
46 { "ideapad_wlan", RFKILL_TYPE_WLAN }, 49 { "ideapad_wlan", 18, 0x15, RFKILL_TYPE_WLAN },
47 { "ideapad_bluetooth", RFKILL_TYPE_BLUETOOTH }, 50 { "ideapad_bluetooth", 16, 0x17, RFKILL_TYPE_BLUETOOTH },
48 { "ideapad_3g", RFKILL_TYPE_WWAN }, 51 { "ideapad_3g", 17, 0x20, RFKILL_TYPE_WWAN },
49 { "ideapad_killsw", RFKILL_TYPE_WLAN } 52 { "ideapad_killsw", 0, 0, RFKILL_TYPE_WLAN }
50}; 53};
51 54
52static int ideapad_dev_exists(int device) 55static bool no_bt_rfkill;
53{ 56module_param(no_bt_rfkill, bool, 0444);
54 acpi_status status; 57MODULE_PARM_DESC(no_bt_rfkill, "No rfkill for bluetooth.");
55 union acpi_object in_param;
56 struct acpi_object_list input = { 1, &in_param };
57 struct acpi_buffer output;
58 union acpi_object out_obj;
59 58
60 output.length = sizeof(out_obj); 59/*
61 output.pointer = &out_obj; 60 * ACPI Helpers
61 */
62#define IDEAPAD_EC_TIMEOUT (100) /* in ms */
62 63
63 in_param.type = ACPI_TYPE_INTEGER; 64static int read_method_int(acpi_handle handle, const char *method, int *val)
64 in_param.integer.value = device + 1; 65{
66 acpi_status status;
67 unsigned long long result;
65 68
66 status = acpi_evaluate_object(NULL, "\\_SB_.DECN", &input, &output); 69 status = acpi_evaluate_integer(handle, (char *)method, NULL, &result);
67 if (ACPI_FAILURE(status)) { 70 if (ACPI_FAILURE(status)) {
68 printk(KERN_WARNING "IdeaPAD \\_SB_.DECN method failed %d. Is this an IdeaPAD?\n", status); 71 *val = -1;
69 return -ENODEV; 72 return -1;
70 } 73 } else {
71 if (out_obj.type != ACPI_TYPE_INTEGER) { 74 *val = result;
72 printk(KERN_WARNING "IdeaPAD \\_SB_.DECN method returned unexpected type\n"); 75 return 0;
73 return -ENODEV;
74 } 76 }
75 return out_obj.integer.value;
76} 77}
77 78
78static int ideapad_dev_get_state(int device) 79static int method_vpcr(acpi_handle handle, int cmd, int *ret)
79{ 80{
80 acpi_status status; 81 acpi_status status;
81 union acpi_object in_param; 82 unsigned long long result;
82 struct acpi_object_list input = { 1, &in_param }; 83 struct acpi_object_list params;
83 struct acpi_buffer output; 84 union acpi_object in_obj;
84 union acpi_object out_obj;
85 85
86 output.length = sizeof(out_obj); 86 params.count = 1;
87 output.pointer = &out_obj; 87 params.pointer = &in_obj;
88 in_obj.type = ACPI_TYPE_INTEGER;
89 in_obj.integer.value = cmd;
88 90
89 in_param.type = ACPI_TYPE_INTEGER; 91 status = acpi_evaluate_integer(handle, "VPCR", &params, &result);
90 in_param.integer.value = device + 1;
91 92
92 status = acpi_evaluate_object(NULL, "\\_SB_.GECN", &input, &output);
93 if (ACPI_FAILURE(status)) { 93 if (ACPI_FAILURE(status)) {
94 printk(KERN_WARNING "IdeaPAD \\_SB_.GECN method failed %d\n", status); 94 *ret = -1;
95 return -ENODEV; 95 return -1;
96 } 96 } else {
97 if (out_obj.type != ACPI_TYPE_INTEGER) { 97 *ret = result;
98 printk(KERN_WARNING "IdeaPAD \\_SB_.GECN method returned unexpected type\n"); 98 return 0;
99 return -ENODEV;
100 } 99 }
101 return out_obj.integer.value;
102} 100}
103 101
104static int ideapad_dev_set_state(int device, int state) 102static int method_vpcw(acpi_handle handle, int cmd, int data)
105{ 103{
104 struct acpi_object_list params;
105 union acpi_object in_obj[2];
106 acpi_status status; 106 acpi_status status;
107 union acpi_object in_params[2];
108 struct acpi_object_list input = { 2, in_params };
109 107
110 in_params[0].type = ACPI_TYPE_INTEGER; 108 params.count = 2;
111 in_params[0].integer.value = device + 1; 109 params.pointer = in_obj;
112 in_params[1].type = ACPI_TYPE_INTEGER; 110 in_obj[0].type = ACPI_TYPE_INTEGER;
113 in_params[1].integer.value = state; 111 in_obj[0].integer.value = cmd;
112 in_obj[1].type = ACPI_TYPE_INTEGER;
113 in_obj[1].integer.value = data;
114 114
115 status = acpi_evaluate_object(NULL, "\\_SB_.SECN", &input, NULL); 115 status = acpi_evaluate_object(handle, "VPCW", &params, NULL);
116 if (ACPI_FAILURE(status)) { 116 if (status != AE_OK)
117 printk(KERN_WARNING "IdeaPAD \\_SB_.SECN method failed %d\n", status); 117 return -1;
118 return -ENODEV;
119 }
120 return 0; 118 return 0;
121} 119}
120
121static int read_ec_data(acpi_handle handle, int cmd, unsigned long *data)
122{
123 int val;
124 unsigned long int end_jiffies;
125
126 if (method_vpcw(handle, 1, cmd))
127 return -1;
128
129 for (end_jiffies = jiffies+(HZ)*IDEAPAD_EC_TIMEOUT/1000+1;
130 time_before(jiffies, end_jiffies);) {
131 schedule();
132 if (method_vpcr(handle, 1, &val))
133 return -1;
134 if (val == 0) {
135 if (method_vpcr(handle, 0, &val))
136 return -1;
137 *data = val;
138 return 0;
139 }
140 }
141 pr_err("timeout in read_ec_cmd\n");
142 return -1;
143}
144
145static int write_ec_cmd(acpi_handle handle, int cmd, unsigned long data)
146{
147 int val;
148 unsigned long int end_jiffies;
149
150 if (method_vpcw(handle, 0, data))
151 return -1;
152 if (method_vpcw(handle, 1, cmd))
153 return -1;
154
155 for (end_jiffies = jiffies+(HZ)*IDEAPAD_EC_TIMEOUT/1000+1;
156 time_before(jiffies, end_jiffies);) {
157 schedule();
158 if (method_vpcr(handle, 1, &val))
159 return -1;
160 if (val == 0)
161 return 0;
162 }
163 pr_err("timeout in write_ec_cmd\n");
164 return -1;
165}
166/* the above is ACPI helpers */
167
122static ssize_t show_ideapad_cam(struct device *dev, 168static ssize_t show_ideapad_cam(struct device *dev,
123 struct device_attribute *attr, 169 struct device_attribute *attr,
124 char *buf) 170 char *buf)
125{ 171{
126 int state = ideapad_dev_get_state(IDEAPAD_DEV_CAMERA); 172 struct ideapad_private *priv = dev_get_drvdata(dev);
127 if (state < 0) 173 acpi_handle handle = priv->handle;
128 return state; 174 unsigned long result;
129 175
130 return sprintf(buf, "%d\n", state); 176 if (read_ec_data(handle, 0x1D, &result))
177 return sprintf(buf, "-1\n");
178 return sprintf(buf, "%lu\n", result);
131} 179}
132 180
133static ssize_t store_ideapad_cam(struct device *dev, 181static ssize_t store_ideapad_cam(struct device *dev,
134 struct device_attribute *attr, 182 struct device_attribute *attr,
135 const char *buf, size_t count) 183 const char *buf, size_t count)
136{ 184{
185 struct ideapad_private *priv = dev_get_drvdata(dev);
186 acpi_handle handle = priv->handle;
137 int ret, state; 187 int ret, state;
138 188
139 if (!count) 189 if (!count)
140 return 0; 190 return 0;
141 if (sscanf(buf, "%i", &state) != 1) 191 if (sscanf(buf, "%i", &state) != 1)
142 return -EINVAL; 192 return -EINVAL;
143 ret = ideapad_dev_set_state(IDEAPAD_DEV_CAMERA, !!state); 193 ret = write_ec_cmd(handle, 0x1E, state);
144 if (ret < 0) 194 if (ret < 0)
145 return ret; 195 return ret;
146 return count; 196 return count;
@@ -154,7 +204,10 @@ static int ideapad_rfk_set(void *data, bool blocked)
154 204
155 if (device == IDEAPAD_DEV_KILLSW) 205 if (device == IDEAPAD_DEV_KILLSW)
156 return -EINVAL; 206 return -EINVAL;
157 return ideapad_dev_set_state(device, !blocked); 207
208 return write_ec_cmd(ideapad_priv->handle,
209 ideapad_rfk_data[device].opcode,
210 !blocked);
158} 211}
159 212
160static struct rfkill_ops ideapad_rfk_ops = { 213static struct rfkill_ops ideapad_rfk_ops = {
@@ -164,32 +217,47 @@ static struct rfkill_ops ideapad_rfk_ops = {
164static void ideapad_sync_rfk_state(struct acpi_device *adevice) 217static void ideapad_sync_rfk_state(struct acpi_device *adevice)
165{ 218{
166 struct ideapad_private *priv = dev_get_drvdata(&adevice->dev); 219 struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
167 int hw_blocked = !ideapad_dev_get_state(IDEAPAD_DEV_KILLSW); 220 acpi_handle handle = priv->handle;
221 unsigned long hw_blocked;
168 int i; 222 int i;
169 223
170 rfkill_set_hw_state(priv->rfk[IDEAPAD_DEV_KILLSW], hw_blocked); 224 if (read_ec_data(handle, 0x23, &hw_blocked))
171 for (i = IDEAPAD_DEV_WLAN; i < IDEAPAD_DEV_KILLSW; i++)
172 if (priv->rfk[i])
173 rfkill_set_hw_state(priv->rfk[i], hw_blocked);
174 if (hw_blocked)
175 return; 225 return;
226 hw_blocked = !hw_blocked;
176 227
177 for (i = IDEAPAD_DEV_WLAN; i < IDEAPAD_DEV_KILLSW; i++) 228 for (i = IDEAPAD_DEV_WLAN; i <= IDEAPAD_DEV_KILLSW; i++)
178 if (priv->rfk[i]) 229 if (priv->rfk[i])
179 rfkill_set_sw_state(priv->rfk[i], !ideapad_dev_get_state(i)); 230 rfkill_set_hw_state(priv->rfk[i], hw_blocked);
180} 231}
181 232
182static int ideapad_register_rfkill(struct acpi_device *adevice, int dev) 233static int ideapad_register_rfkill(struct acpi_device *adevice, int dev)
183{ 234{
184 struct ideapad_private *priv = dev_get_drvdata(&adevice->dev); 235 struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
185 int ret; 236 int ret;
237 unsigned long sw_blocked;
238
239 if (no_bt_rfkill &&
240 (ideapad_rfk_data[dev].type == RFKILL_TYPE_BLUETOOTH)) {
241 /* Force to enable bluetooth when no_bt_rfkill=1 */
242 write_ec_cmd(ideapad_priv->handle,
243 ideapad_rfk_data[dev].opcode, 1);
244 return 0;
245 }
186 246
187 priv->rfk[dev] = rfkill_alloc(ideapad_rfk_data[dev-1].name, &adevice->dev, 247 priv->rfk[dev] = rfkill_alloc(ideapad_rfk_data[dev].name, &adevice->dev,
188 ideapad_rfk_data[dev-1].type, &ideapad_rfk_ops, 248 ideapad_rfk_data[dev].type, &ideapad_rfk_ops,
189 (void *)(long)dev); 249 (void *)(long)dev);
190 if (!priv->rfk[dev]) 250 if (!priv->rfk[dev])
191 return -ENOMEM; 251 return -ENOMEM;
192 252
253 if (read_ec_data(ideapad_priv->handle, ideapad_rfk_data[dev].opcode-1,
254 &sw_blocked)) {
255 rfkill_init_sw_state(priv->rfk[dev], 0);
256 } else {
257 sw_blocked = !sw_blocked;
258 rfkill_init_sw_state(priv->rfk[dev], sw_blocked);
259 }
260
193 ret = rfkill_register(priv->rfk[dev]); 261 ret = rfkill_register(priv->rfk[dev]);
194 if (ret) { 262 if (ret) {
195 rfkill_destroy(priv->rfk[dev]); 263 rfkill_destroy(priv->rfk[dev]);
@@ -217,14 +285,18 @@ MODULE_DEVICE_TABLE(acpi, ideapad_device_ids);
217 285
218static int ideapad_acpi_add(struct acpi_device *adevice) 286static int ideapad_acpi_add(struct acpi_device *adevice)
219{ 287{
220 int i; 288 int i, cfg;
221 int devs_present[5]; 289 int devs_present[5];
222 struct ideapad_private *priv; 290 struct ideapad_private *priv;
223 291
292 if (read_method_int(adevice->handle, "_CFG", &cfg))
293 return -ENODEV;
294
224 for (i = IDEAPAD_DEV_CAMERA; i < IDEAPAD_DEV_KILLSW; i++) { 295 for (i = IDEAPAD_DEV_CAMERA; i < IDEAPAD_DEV_KILLSW; i++) {
225 devs_present[i] = ideapad_dev_exists(i); 296 if (test_bit(ideapad_rfk_data[i].cfgbit, (unsigned long *)&cfg))
226 if (devs_present[i] < 0) 297 devs_present[i] = 1;
227 return devs_present[i]; 298 else
299 devs_present[i] = 0;
228 } 300 }
229 301
230 /* The hardware switch is always present */ 302 /* The hardware switch is always present */
@@ -242,7 +314,9 @@ static int ideapad_acpi_add(struct acpi_device *adevice)
242 } 314 }
243 } 315 }
244 316
317 priv->handle = adevice->handle;
245 dev_set_drvdata(&adevice->dev, priv); 318 dev_set_drvdata(&adevice->dev, priv);
319 ideapad_priv = priv;
246 for (i = IDEAPAD_DEV_WLAN; i <= IDEAPAD_DEV_KILLSW; i++) { 320 for (i = IDEAPAD_DEV_WLAN; i <= IDEAPAD_DEV_KILLSW; i++) {
247 if (!devs_present[i]) 321 if (!devs_present[i])
248 continue; 322 continue;
@@ -270,7 +344,21 @@ static int ideapad_acpi_remove(struct acpi_device *adevice, int type)
270 344
271static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event) 345static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event)
272{ 346{
273 ideapad_sync_rfk_state(adevice); 347 acpi_handle handle = adevice->handle;
348 unsigned long vpc1, vpc2, vpc_bit;
349
350 if (read_ec_data(handle, 0x10, &vpc1))
351 return;
352 if (read_ec_data(handle, 0x1A, &vpc2))
353 return;
354
355 vpc1 = (vpc2 << 8) | vpc1;
356 for (vpc_bit = 0; vpc_bit < 16; vpc_bit++) {
357 if (test_bit(vpc_bit, &vpc1)) {
358 if (vpc_bit == 9)
359 ideapad_sync_rfk_state(adevice);
360 }
361 }
274} 362}
275 363
276static struct acpi_driver ideapad_acpi_driver = { 364static struct acpi_driver ideapad_acpi_driver = {
diff --git a/drivers/platform/x86/intel_pmic_gpio.c b/drivers/platform/x86/intel_pmic_gpio.c
index 5cdcff653918..f540ff96c53f 100644
--- a/drivers/platform/x86/intel_pmic_gpio.c
+++ b/drivers/platform/x86/intel_pmic_gpio.c
@@ -142,16 +142,16 @@ static int pmic_gpio_direction_output(struct gpio_chip *chip,
142 142
143 if (offset < 8)/* it is GPIO */ 143 if (offset < 8)/* it is GPIO */
144 rc = intel_scu_ipc_update_register(GPIO0 + offset, 144 rc = intel_scu_ipc_update_register(GPIO0 + offset,
145 GPIO_DRV | GPIO_DOU | GPIO_DIR, 145 GPIO_DRV | (value ? GPIO_DOU : 0),
146 GPIO_DRV | (value ? GPIO_DOU : 0)); 146 GPIO_DRV | GPIO_DOU | GPIO_DIR);
147 else if (offset < 16)/* it is GPOSW */ 147 else if (offset < 16)/* it is GPOSW */
148 rc = intel_scu_ipc_update_register(GPOSWCTL0 + offset - 8, 148 rc = intel_scu_ipc_update_register(GPOSWCTL0 + offset - 8,
149 GPOSW_DRV | GPOSW_DOU | GPOSW_RDRV, 149 GPOSW_DRV | (value ? GPOSW_DOU : 0),
150 GPOSW_DRV | (value ? GPOSW_DOU : 0)); 150 GPOSW_DRV | GPOSW_DOU | GPOSW_RDRV);
151 else if (offset > 15 && offset < 24)/* it is GPO */ 151 else if (offset > 15 && offset < 24)/* it is GPO */
152 rc = intel_scu_ipc_update_register(GPO, 152 rc = intel_scu_ipc_update_register(GPO,
153 1 << (offset - 16), 153 value ? 1 << (offset - 16) : 0,
154 value ? 1 << (offset - 16) : 0); 154 1 << (offset - 16));
155 else { 155 else {
156 printk(KERN_ERR 156 printk(KERN_ERR
157 "%s: invalid PMIC GPIO pin %d!\n", __func__, offset); 157 "%s: invalid PMIC GPIO pin %d!\n", __func__, offset);
@@ -179,16 +179,16 @@ static void pmic_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
179{ 179{
180 if (offset < 8)/* it is GPIO */ 180 if (offset < 8)/* it is GPIO */
181 intel_scu_ipc_update_register(GPIO0 + offset, 181 intel_scu_ipc_update_register(GPIO0 + offset,
182 GPIO_DRV | GPIO_DOU, 182 GPIO_DRV | (value ? GPIO_DOU : 0),
183 GPIO_DRV | (value ? GPIO_DOU : 0)); 183 GPIO_DRV | GPIO_DOU);
184 else if (offset < 16)/* it is GPOSW */ 184 else if (offset < 16)/* it is GPOSW */
185 intel_scu_ipc_update_register(GPOSWCTL0 + offset - 8, 185 intel_scu_ipc_update_register(GPOSWCTL0 + offset - 8,
186 GPOSW_DRV | GPOSW_DOU | GPOSW_RDRV, 186 GPOSW_DRV | (value ? GPOSW_DOU : 0),
187 GPOSW_DRV | (value ? GPOSW_DOU : 0)); 187 GPOSW_DRV | GPOSW_DOU | GPOSW_RDRV);
188 else if (offset > 15 && offset < 24) /* it is GPO */ 188 else if (offset > 15 && offset < 24) /* it is GPO */
189 intel_scu_ipc_update_register(GPO, 189 intel_scu_ipc_update_register(GPO,
190 1 << (offset - 16), 190 value ? 1 << (offset - 16) : 0,
191 value ? 1 << (offset - 16) : 0); 191 1 << (offset - 16));
192} 192}
193 193
194static int pmic_irq_type(unsigned irq, unsigned type) 194static int pmic_irq_type(unsigned irq, unsigned type)
@@ -197,7 +197,7 @@ static int pmic_irq_type(unsigned irq, unsigned type)
197 u32 gpio = irq - pg->irq_base; 197 u32 gpio = irq - pg->irq_base;
198 unsigned long flags; 198 unsigned long flags;
199 199
200 if (gpio > pg->chip.ngpio) 200 if (gpio >= pg->chip.ngpio)
201 return -EINVAL; 201 return -EINVAL;
202 202
203 spin_lock_irqsave(&pg->irqtypes.lock, flags); 203 spin_lock_irqsave(&pg->irqtypes.lock, flags);
diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c
index 6abe18e638e9..41a9e34899ac 100644
--- a/drivers/platform/x86/intel_scu_ipc.c
+++ b/drivers/platform/x86/intel_scu_ipc.c
@@ -23,6 +23,7 @@
23#include <linux/pm.h> 23#include <linux/pm.h>
24#include <linux/pci.h> 24#include <linux/pci.h>
25#include <linux/interrupt.h> 25#include <linux/interrupt.h>
26#include <linux/sfi.h>
26#include <asm/mrst.h> 27#include <asm/mrst.h>
27#include <asm/intel_scu_ipc.h> 28#include <asm/intel_scu_ipc.h>
28 29
diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c
index ec01c3d8fc5a..cc1e0ba104d7 100644
--- a/drivers/platform/x86/panasonic-laptop.c
+++ b/drivers/platform/x86/panasonic-laptop.c
@@ -128,6 +128,7 @@
128#include <acpi/acpi_bus.h> 128#include <acpi/acpi_bus.h>
129#include <acpi/acpi_drivers.h> 129#include <acpi/acpi_drivers.h>
130#include <linux/input.h> 130#include <linux/input.h>
131#include <linux/input/sparse-keymap.h>
131 132
132 133
133#ifndef ACPI_HOTKEY_COMPONENT 134#ifndef ACPI_HOTKEY_COMPONENT
@@ -200,30 +201,29 @@ static struct acpi_driver acpi_pcc_driver = {
200 }, 201 },
201}; 202};
202 203
203#define KEYMAP_SIZE 11 204static const struct key_entry panasonic_keymap[] = {
204static const unsigned int initial_keymap[KEYMAP_SIZE] = { 205 { KE_KEY, 0, { KEY_RESERVED } },
205 /* 0 */ KEY_RESERVED, 206 { KE_KEY, 1, { KEY_BRIGHTNESSDOWN } },
206 /* 1 */ KEY_BRIGHTNESSDOWN, 207 { KE_KEY, 2, { KEY_BRIGHTNESSUP } },
207 /* 2 */ KEY_BRIGHTNESSUP, 208 { KE_KEY, 3, { KEY_DISPLAYTOGGLE } },
208 /* 3 */ KEY_DISPLAYTOGGLE, 209 { KE_KEY, 4, { KEY_MUTE } },
209 /* 4 */ KEY_MUTE, 210 { KE_KEY, 5, { KEY_VOLUMEDOWN } },
210 /* 5 */ KEY_VOLUMEDOWN, 211 { KE_KEY, 6, { KEY_VOLUMEUP } },
211 /* 6 */ KEY_VOLUMEUP, 212 { KE_KEY, 7, { KEY_SLEEP } },
212 /* 7 */ KEY_SLEEP, 213 { KE_KEY, 8, { KEY_PROG1 } }, /* Change CPU boost */
213 /* 8 */ KEY_PROG1, /* Change CPU boost */ 214 { KE_KEY, 9, { KEY_BATTERY } },
214 /* 9 */ KEY_BATTERY, 215 { KE_KEY, 10, { KEY_SUSPEND } },
215 /* 10 */ KEY_SUSPEND, 216 { KE_END, 0 }
216}; 217};
217 218
218struct pcc_acpi { 219struct pcc_acpi {
219 acpi_handle handle; 220 acpi_handle handle;
220 unsigned long num_sifr; 221 unsigned long num_sifr;
221 int sticky_mode; 222 int sticky_mode;
222 u32 *sinf; 223 u32 *sinf;
223 struct acpi_device *device; 224 struct acpi_device *device;
224 struct input_dev *input_dev; 225 struct input_dev *input_dev;
225 struct backlight_device *backlight; 226 struct backlight_device *backlight;
226 unsigned int keymap[KEYMAP_SIZE];
227}; 227};
228 228
229struct pcc_keyinput { 229struct pcc_keyinput {
@@ -267,7 +267,7 @@ static inline int acpi_pcc_get_sqty(struct acpi_device *device)
267 } 267 }
268} 268}
269 269
270static int acpi_pcc_retrieve_biosdata(struct pcc_acpi *pcc, u32 *sinf) 270static int acpi_pcc_retrieve_biosdata(struct pcc_acpi *pcc)
271{ 271{
272 acpi_status status; 272 acpi_status status;
273 struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; 273 struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
@@ -285,6 +285,7 @@ static int acpi_pcc_retrieve_biosdata(struct pcc_acpi *pcc, u32 *sinf)
285 hkey = buffer.pointer; 285 hkey = buffer.pointer;
286 if (!hkey || (hkey->type != ACPI_TYPE_PACKAGE)) { 286 if (!hkey || (hkey->type != ACPI_TYPE_PACKAGE)) {
287 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid HKEY.SINF\n")); 287 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid HKEY.SINF\n"));
288 status = AE_ERROR;
288 goto end; 289 goto end;
289 } 290 }
290 291
@@ -298,12 +299,12 @@ static int acpi_pcc_retrieve_biosdata(struct pcc_acpi *pcc, u32 *sinf)
298 for (i = 0; i < hkey->package.count; i++) { 299 for (i = 0; i < hkey->package.count; i++) {
299 union acpi_object *element = &(hkey->package.elements[i]); 300 union acpi_object *element = &(hkey->package.elements[i]);
300 if (likely(element->type == ACPI_TYPE_INTEGER)) { 301 if (likely(element->type == ACPI_TYPE_INTEGER)) {
301 sinf[i] = element->integer.value; 302 pcc->sinf[i] = element->integer.value;
302 } else 303 } else
303 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 304 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
304 "Invalid HKEY.SINF data\n")); 305 "Invalid HKEY.SINF data\n"));
305 } 306 }
306 sinf[hkey->package.count] = -1; 307 pcc->sinf[hkey->package.count] = -1;
307 308
308end: 309end:
309 kfree(buffer.pointer); 310 kfree(buffer.pointer);
@@ -321,7 +322,7 @@ static int bl_get(struct backlight_device *bd)
321{ 322{
322 struct pcc_acpi *pcc = bl_get_data(bd); 323 struct pcc_acpi *pcc = bl_get_data(bd);
323 324
324 if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) 325 if (!acpi_pcc_retrieve_biosdata(pcc))
325 return -EIO; 326 return -EIO;
326 327
327 return pcc->sinf[SINF_AC_CUR_BRIGHT]; 328 return pcc->sinf[SINF_AC_CUR_BRIGHT];
@@ -333,7 +334,7 @@ static int bl_set_status(struct backlight_device *bd)
333 int bright = bd->props.brightness; 334 int bright = bd->props.brightness;
334 int rc; 335 int rc;
335 336
336 if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) 337 if (!acpi_pcc_retrieve_biosdata(pcc))
337 return -EIO; 338 return -EIO;
338 339
339 if (bright < pcc->sinf[SINF_AC_MIN_BRIGHT]) 340 if (bright < pcc->sinf[SINF_AC_MIN_BRIGHT])
@@ -367,7 +368,7 @@ static ssize_t show_numbatt(struct device *dev, struct device_attribute *attr,
367 struct acpi_device *acpi = to_acpi_device(dev); 368 struct acpi_device *acpi = to_acpi_device(dev);
368 struct pcc_acpi *pcc = acpi_driver_data(acpi); 369 struct pcc_acpi *pcc = acpi_driver_data(acpi);
369 370
370 if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) 371 if (!acpi_pcc_retrieve_biosdata(pcc))
371 return -EIO; 372 return -EIO;
372 373
373 return snprintf(buf, PAGE_SIZE, "%u\n", pcc->sinf[SINF_NUM_BATTERIES]); 374 return snprintf(buf, PAGE_SIZE, "%u\n", pcc->sinf[SINF_NUM_BATTERIES]);
@@ -379,7 +380,7 @@ static ssize_t show_lcdtype(struct device *dev, struct device_attribute *attr,
379 struct acpi_device *acpi = to_acpi_device(dev); 380 struct acpi_device *acpi = to_acpi_device(dev);
380 struct pcc_acpi *pcc = acpi_driver_data(acpi); 381 struct pcc_acpi *pcc = acpi_driver_data(acpi);
381 382
382 if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) 383 if (!acpi_pcc_retrieve_biosdata(pcc))
383 return -EIO; 384 return -EIO;
384 385
385 return snprintf(buf, PAGE_SIZE, "%u\n", pcc->sinf[SINF_LCD_TYPE]); 386 return snprintf(buf, PAGE_SIZE, "%u\n", pcc->sinf[SINF_LCD_TYPE]);
@@ -391,7 +392,7 @@ static ssize_t show_mute(struct device *dev, struct device_attribute *attr,
391 struct acpi_device *acpi = to_acpi_device(dev); 392 struct acpi_device *acpi = to_acpi_device(dev);
392 struct pcc_acpi *pcc = acpi_driver_data(acpi); 393 struct pcc_acpi *pcc = acpi_driver_data(acpi);
393 394
394 if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) 395 if (!acpi_pcc_retrieve_biosdata(pcc))
395 return -EIO; 396 return -EIO;
396 397
397 return snprintf(buf, PAGE_SIZE, "%u\n", pcc->sinf[SINF_MUTE]); 398 return snprintf(buf, PAGE_SIZE, "%u\n", pcc->sinf[SINF_MUTE]);
@@ -403,7 +404,7 @@ static ssize_t show_sticky(struct device *dev, struct device_attribute *attr,
403 struct acpi_device *acpi = to_acpi_device(dev); 404 struct acpi_device *acpi = to_acpi_device(dev);
404 struct pcc_acpi *pcc = acpi_driver_data(acpi); 405 struct pcc_acpi *pcc = acpi_driver_data(acpi);
405 406
406 if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) 407 if (!acpi_pcc_retrieve_biosdata(pcc))
407 return -EIO; 408 return -EIO;
408 409
409 return snprintf(buf, PAGE_SIZE, "%u\n", pcc->sinf[SINF_STICKY_KEY]); 410 return snprintf(buf, PAGE_SIZE, "%u\n", pcc->sinf[SINF_STICKY_KEY]);
@@ -446,56 +447,10 @@ static struct attribute_group pcc_attr_group = {
446 447
447/* hotkey input device driver */ 448/* hotkey input device driver */
448 449
449static int pcc_getkeycode(struct input_dev *dev,
450 unsigned int scancode, unsigned int *keycode)
451{
452 struct pcc_acpi *pcc = input_get_drvdata(dev);
453
454 if (scancode >= ARRAY_SIZE(pcc->keymap))
455 return -EINVAL;
456
457 *keycode = pcc->keymap[scancode];
458
459 return 0;
460}
461
462static int keymap_get_by_keycode(struct pcc_acpi *pcc, unsigned int keycode)
463{
464 int i;
465
466 for (i = 0; i < ARRAY_SIZE(pcc->keymap); i++) {
467 if (pcc->keymap[i] == keycode)
468 return i+1;
469 }
470
471 return 0;
472}
473
474static int pcc_setkeycode(struct input_dev *dev,
475 unsigned int scancode, unsigned int keycode)
476{
477 struct pcc_acpi *pcc = input_get_drvdata(dev);
478 int oldkeycode;
479
480 if (scancode >= ARRAY_SIZE(pcc->keymap))
481 return -EINVAL;
482
483 oldkeycode = pcc->keymap[scancode];
484 pcc->keymap[scancode] = keycode;
485
486 set_bit(keycode, dev->keybit);
487
488 if (!keymap_get_by_keycode(pcc, oldkeycode))
489 clear_bit(oldkeycode, dev->keybit);
490
491 return 0;
492}
493
494static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc) 450static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc)
495{ 451{
496 struct input_dev *hotk_input_dev = pcc->input_dev; 452 struct input_dev *hotk_input_dev = pcc->input_dev;
497 int rc; 453 int rc;
498 int key_code, hkey_num;
499 unsigned long long result; 454 unsigned long long result;
500 455
501 rc = acpi_evaluate_integer(pcc->handle, METHOD_HKEY_QUERY, 456 rc = acpi_evaluate_integer(pcc->handle, METHOD_HKEY_QUERY,
@@ -508,25 +463,10 @@ static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc)
508 463
509 acpi_bus_generate_proc_event(pcc->device, HKEY_NOTIFY, result); 464 acpi_bus_generate_proc_event(pcc->device, HKEY_NOTIFY, result);
510 465
511 hkey_num = result & 0xf; 466 if (!sparse_keymap_report_event(hotk_input_dev,
512 467 result & 0xf, result & 0x80, false))
513 if (hkey_num < 0 || hkey_num >= ARRAY_SIZE(pcc->keymap)) {
514 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 468 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
515 "hotkey number out of range: %d\n", 469 "Unknown hotkey event: %d\n", result));
516 hkey_num));
517 return;
518 }
519
520 key_code = pcc->keymap[hkey_num];
521
522 if (key_code != KEY_RESERVED) {
523 int pushed = (result & 0x80) ? TRUE : FALSE;
524
525 input_report_key(hotk_input_dev, key_code, pushed);
526 input_sync(hotk_input_dev);
527 }
528
529 return;
530} 470}
531 471
532static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event) 472static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event)
@@ -545,40 +485,55 @@ static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event)
545 485
546static int acpi_pcc_init_input(struct pcc_acpi *pcc) 486static int acpi_pcc_init_input(struct pcc_acpi *pcc)
547{ 487{
548 int i, rc; 488 struct input_dev *input_dev;
489 int error;
549 490
550 pcc->input_dev = input_allocate_device(); 491 input_dev = input_allocate_device();
551 if (!pcc->input_dev) { 492 if (!input_dev) {
552 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 493 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
553 "Couldn't allocate input device for hotkey")); 494 "Couldn't allocate input device for hotkey"));
554 return -ENOMEM; 495 return -ENOMEM;
555 } 496 }
556 497
557 pcc->input_dev->evbit[0] = BIT(EV_KEY); 498 input_dev->name = ACPI_PCC_DRIVER_NAME;
558 499 input_dev->phys = ACPI_PCC_INPUT_PHYS;
559 pcc->input_dev->name = ACPI_PCC_DRIVER_NAME; 500 input_dev->id.bustype = BUS_HOST;
560 pcc->input_dev->phys = ACPI_PCC_INPUT_PHYS; 501 input_dev->id.vendor = 0x0001;
561 pcc->input_dev->id.bustype = BUS_HOST; 502 input_dev->id.product = 0x0001;
562 pcc->input_dev->id.vendor = 0x0001; 503 input_dev->id.version = 0x0100;
563 pcc->input_dev->id.product = 0x0001;
564 pcc->input_dev->id.version = 0x0100;
565 pcc->input_dev->getkeycode = pcc_getkeycode;
566 pcc->input_dev->setkeycode = pcc_setkeycode;
567 504
568 /* load initial keymap */ 505 error = sparse_keymap_setup(input_dev, panasonic_keymap, NULL);
569 memcpy(pcc->keymap, initial_keymap, sizeof(pcc->keymap)); 506 if (error) {
507 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
508 "Unable to setup input device keymap\n"));
509 goto err_free_dev;
510 }
570 511
571 for (i = 0; i < ARRAY_SIZE(pcc->keymap); i++) 512 error = input_register_device(input_dev);
572 __set_bit(pcc->keymap[i], pcc->input_dev->keybit); 513 if (error) {
573 __clear_bit(KEY_RESERVED, pcc->input_dev->keybit); 514 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
515 "Unable to register input device\n"));
516 goto err_free_keymap;
517 }
574 518
575 input_set_drvdata(pcc->input_dev, pcc); 519 pcc->input_dev = input_dev;
520 return 0;
576 521
577 rc = input_register_device(pcc->input_dev); 522 err_free_keymap:
578 if (rc < 0) 523 sparse_keymap_free(input_dev);
579 input_free_device(pcc->input_dev); 524 err_free_dev:
525 input_free_device(input_dev);
526 return error;
527}
580 528
581 return rc; 529static void acpi_pcc_destroy_input(struct pcc_acpi *pcc)
530{
531 sparse_keymap_free(pcc->input_dev);
532 input_unregister_device(pcc->input_dev);
533 /*
534 * No need to input_free_device() since core input API refcounts
535 * and free()s the device.
536 */
582} 537}
583 538
584/* kernel module interface */ 539/* kernel module interface */
@@ -636,12 +591,13 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
636 if (result) { 591 if (result) {
637 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 592 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
638 "Error installing keyinput handler\n")); 593 "Error installing keyinput handler\n"));
639 goto out_hotkey; 594 goto out_sinf;
640 } 595 }
641 596
642 if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) { 597 if (!acpi_pcc_retrieve_biosdata(pcc)) {
643 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 598 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
644 "Couldn't retrieve BIOS data\n")); 599 "Couldn't retrieve BIOS data\n"));
600 result = -EIO;
645 goto out_input; 601 goto out_input;
646 } 602 }
647 /* initialize backlight */ 603 /* initialize backlight */
@@ -651,7 +607,7 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
651 &pcc_backlight_ops, &props); 607 &pcc_backlight_ops, &props);
652 if (IS_ERR(pcc->backlight)) { 608 if (IS_ERR(pcc->backlight)) {
653 result = PTR_ERR(pcc->backlight); 609 result = PTR_ERR(pcc->backlight);
654 goto out_sinf; 610 goto out_input;
655 } 611 }
656 612
657 /* read the initial brightness setting from the hardware */ 613 /* read the initial brightness setting from the hardware */
@@ -669,12 +625,10 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
669 625
670out_backlight: 626out_backlight:
671 backlight_device_unregister(pcc->backlight); 627 backlight_device_unregister(pcc->backlight);
628out_input:
629 acpi_pcc_destroy_input(pcc);
672out_sinf: 630out_sinf:
673 kfree(pcc->sinf); 631 kfree(pcc->sinf);
674out_input:
675 input_unregister_device(pcc->input_dev);
676 /* no need to input_free_device() since core input API refcount and
677 * free()s the device */
678out_hotkey: 632out_hotkey:
679 kfree(pcc); 633 kfree(pcc);
680 634
@@ -709,9 +663,7 @@ static int acpi_pcc_hotkey_remove(struct acpi_device *device, int type)
709 663
710 backlight_device_unregister(pcc->backlight); 664 backlight_device_unregister(pcc->backlight);
711 665
712 input_unregister_device(pcc->input_dev); 666 acpi_pcc_destroy_input(pcc);
713 /* no need to input_free_device() since core input API refcount and
714 * free()s the device */
715 667
716 kfree(pcc->sinf); 668 kfree(pcc->sinf);
717 kfree(pcc); 669 kfree(pcc);
diff --git a/drivers/platform/x86/topstar-laptop.c b/drivers/platform/x86/topstar-laptop.c
index ff4b476f1950..1d07d6d09f27 100644
--- a/drivers/platform/x86/topstar-laptop.c
+++ b/drivers/platform/x86/topstar-laptop.c
@@ -19,6 +19,7 @@
19#include <linux/slab.h> 19#include <linux/slab.h>
20#include <linux/acpi.h> 20#include <linux/acpi.h>
21#include <linux/input.h> 21#include <linux/input.h>
22#include <linux/input/sparse-keymap.h>
22 23
23#define ACPI_TOPSTAR_CLASS "topstar" 24#define ACPI_TOPSTAR_CLASS "topstar"
24 25
@@ -26,52 +27,37 @@ struct topstar_hkey {
26 struct input_dev *inputdev; 27 struct input_dev *inputdev;
27}; 28};
28 29
29struct tps_key_entry { 30static const struct key_entry topstar_keymap[] = {
30 u8 code; 31 { KE_KEY, 0x80, { KEY_BRIGHTNESSUP } },
31 u16 keycode; 32 { KE_KEY, 0x81, { KEY_BRIGHTNESSDOWN } },
32}; 33 { KE_KEY, 0x83, { KEY_VOLUMEUP } },
33 34 { KE_KEY, 0x84, { KEY_VOLUMEDOWN } },
34static struct tps_key_entry topstar_keymap[] = { 35 { KE_KEY, 0x85, { KEY_MUTE } },
35 { 0x80, KEY_BRIGHTNESSUP }, 36 { KE_KEY, 0x86, { KEY_SWITCHVIDEOMODE } },
36 { 0x81, KEY_BRIGHTNESSDOWN }, 37 { KE_KEY, 0x87, { KEY_F13 } }, /* touchpad enable/disable key */
37 { 0x83, KEY_VOLUMEUP }, 38 { KE_KEY, 0x88, { KEY_WLAN } },
38 { 0x84, KEY_VOLUMEDOWN }, 39 { KE_KEY, 0x8a, { KEY_WWW } },
39 { 0x85, KEY_MUTE }, 40 { KE_KEY, 0x8b, { KEY_MAIL } },
40 { 0x86, KEY_SWITCHVIDEOMODE }, 41 { KE_KEY, 0x8c, { KEY_MEDIA } },
41 { 0x87, KEY_F13 }, /* touchpad enable/disable key */
42 { 0x88, KEY_WLAN },
43 { 0x8a, KEY_WWW },
44 { 0x8b, KEY_MAIL },
45 { 0x8c, KEY_MEDIA },
46 { 0x96, KEY_F14 }, /* G key? */
47 { }
48};
49
50static struct tps_key_entry *tps_get_key_by_scancode(unsigned int code)
51{
52 struct tps_key_entry *key;
53
54 for (key = topstar_keymap; key->code; key++)
55 if (code == key->code)
56 return key;
57 42
58 return NULL; 43 /* Known non hotkey events don't handled or that we don't care yet */
59} 44 { KE_IGNORE, 0x8e, },
60 45 { KE_IGNORE, 0x8f, },
61static struct tps_key_entry *tps_get_key_by_keycode(unsigned int code) 46 { KE_IGNORE, 0x90, },
62{
63 struct tps_key_entry *key;
64 47
65 for (key = topstar_keymap; key->code; key++) 48 /*
66 if (code == key->keycode) 49 * 'G key' generate two event codes, convert to only
67 return key; 50 * one event/key code for now, consider replacing by
51 * a switch (3G switch - SW_3G?)
52 */
53 { KE_KEY, 0x96, { KEY_F14 } },
54 { KE_KEY, 0x97, { KEY_F14 } },
68 55
69 return NULL; 56 { KE_END, 0 }
70} 57};
71 58
72static void acpi_topstar_notify(struct acpi_device *device, u32 event) 59static void acpi_topstar_notify(struct acpi_device *device, u32 event)
73{ 60{
74 struct tps_key_entry *key;
75 static bool dup_evnt[2]; 61 static bool dup_evnt[2];
76 bool *dup; 62 bool *dup;
77 struct topstar_hkey *hkey = acpi_driver_data(device); 63 struct topstar_hkey *hkey = acpi_driver_data(device);
@@ -86,27 +72,8 @@ static void acpi_topstar_notify(struct acpi_device *device, u32 event)
86 *dup = true; 72 *dup = true;
87 } 73 }
88 74
89 /* 75 if (!sparse_keymap_report_event(hkey->inputdev, event, 1, true))
90 * 'G key' generate two event codes, convert to only 76 pr_info("unknown event = 0x%02x\n", event);
91 * one event/key code for now (3G switch?)
92 */
93 if (event == 0x97)
94 event = 0x96;
95
96 key = tps_get_key_by_scancode(event);
97 if (key) {
98 input_report_key(hkey->inputdev, key->keycode, 1);
99 input_sync(hkey->inputdev);
100 input_report_key(hkey->inputdev, key->keycode, 0);
101 input_sync(hkey->inputdev);
102 return;
103 }
104
105 /* Known non hotkey events don't handled or that we don't care yet */
106 if (event == 0x8e || event == 0x8f || event == 0x90)
107 return;
108
109 pr_info("unknown event = 0x%02x\n", event);
110} 77}
111 78
112static int acpi_topstar_fncx_switch(struct acpi_device *device, bool state) 79static int acpi_topstar_fncx_switch(struct acpi_device *device, bool state)
@@ -127,62 +94,41 @@ static int acpi_topstar_fncx_switch(struct acpi_device *device, bool state)
127 return 0; 94 return 0;
128} 95}
129 96
130static int topstar_getkeycode(struct input_dev *dev,
131 unsigned int scancode, unsigned int *keycode)
132{
133 struct tps_key_entry *key = tps_get_key_by_scancode(scancode);
134
135 if (!key)
136 return -EINVAL;
137
138 *keycode = key->keycode;
139 return 0;
140}
141
142static int topstar_setkeycode(struct input_dev *dev,
143 unsigned int scancode, unsigned int keycode)
144{
145 struct tps_key_entry *key;
146 int old_keycode;
147
148 key = tps_get_key_by_scancode(scancode);
149
150 if (!key)
151 return -EINVAL;
152
153 old_keycode = key->keycode;
154 key->keycode = keycode;
155 set_bit(keycode, dev->keybit);
156 if (!tps_get_key_by_keycode(old_keycode))
157 clear_bit(old_keycode, dev->keybit);
158 return 0;
159}
160
161static int acpi_topstar_init_hkey(struct topstar_hkey *hkey) 97static int acpi_topstar_init_hkey(struct topstar_hkey *hkey)
162{ 98{
163 struct tps_key_entry *key; 99 struct input_dev *input;
100 int error;
164 101
165 hkey->inputdev = input_allocate_device(); 102 input = input_allocate_device();
166 if (!hkey->inputdev) { 103 if (!input) {
167 pr_err("Unable to allocate input device\n"); 104 pr_err("Unable to allocate input device\n");
168 return -ENODEV; 105 return -ENOMEM;
169 } 106 }
170 hkey->inputdev->name = "Topstar Laptop extra buttons"; 107
171 hkey->inputdev->phys = "topstar/input0"; 108 input->name = "Topstar Laptop extra buttons";
172 hkey->inputdev->id.bustype = BUS_HOST; 109 input->phys = "topstar/input0";
173 hkey->inputdev->getkeycode = topstar_getkeycode; 110 input->id.bustype = BUS_HOST;
174 hkey->inputdev->setkeycode = topstar_setkeycode; 111
175 for (key = topstar_keymap; key->code; key++) { 112 error = sparse_keymap_setup(input, topstar_keymap, NULL);
176 set_bit(EV_KEY, hkey->inputdev->evbit); 113 if (error) {
177 set_bit(key->keycode, hkey->inputdev->keybit); 114 pr_err("Unable to setup input device keymap\n");
115 goto err_free_dev;
178 } 116 }
179 if (input_register_device(hkey->inputdev)) { 117
118 error = input_register_device(input);
119 if (error) {
180 pr_err("Unable to register input device\n"); 120 pr_err("Unable to register input device\n");
181 input_free_device(hkey->inputdev); 121 goto err_free_keymap;
182 return -ENODEV;
183 } 122 }
184 123
124 hkey->inputdev = input;
185 return 0; 125 return 0;
126
127 err_free_keymap:
128 sparse_keymap_free(input);
129 err_free_dev:
130 input_free_device(input);
131 return error;
186} 132}
187 133
188static int acpi_topstar_add(struct acpi_device *device) 134static int acpi_topstar_add(struct acpi_device *device)
@@ -216,6 +162,7 @@ static int acpi_topstar_remove(struct acpi_device *device, int type)
216 162
217 acpi_topstar_fncx_switch(device, false); 163 acpi_topstar_fncx_switch(device, false);
218 164
165 sparse_keymap_free(tps_hkey->inputdev);
219 input_unregister_device(tps_hkey->inputdev); 166 input_unregister_device(tps_hkey->inputdev);
220 kfree(tps_hkey); 167 kfree(tps_hkey);
221 168
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index 7d67a45bb2b0..06f304f46e02 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -48,6 +48,7 @@
48#include <linux/platform_device.h> 48#include <linux/platform_device.h>
49#include <linux/rfkill.h> 49#include <linux/rfkill.h>
50#include <linux/input.h> 50#include <linux/input.h>
51#include <linux/input/sparse-keymap.h>
51#include <linux/leds.h> 52#include <linux/leds.h>
52#include <linux/slab.h> 53#include <linux/slab.h>
53 54
@@ -121,36 +122,28 @@ static const struct acpi_device_id toshiba_device_ids[] = {
121}; 122};
122MODULE_DEVICE_TABLE(acpi, toshiba_device_ids); 123MODULE_DEVICE_TABLE(acpi, toshiba_device_ids);
123 124
124struct key_entry { 125static const struct key_entry toshiba_acpi_keymap[] __initconst = {
125 char type; 126 { KE_KEY, 0x101, { KEY_MUTE } },
126 u16 code; 127 { KE_KEY, 0x102, { KEY_ZOOMOUT } },
127 u16 keycode; 128 { KE_KEY, 0x103, { KEY_ZOOMIN } },
128}; 129 { KE_KEY, 0x13b, { KEY_COFFEE } },
129 130 { KE_KEY, 0x13c, { KEY_BATTERY } },
130enum {KE_KEY, KE_END}; 131 { KE_KEY, 0x13d, { KEY_SLEEP } },
131 132 { KE_KEY, 0x13e, { KEY_SUSPEND } },
132static struct key_entry toshiba_acpi_keymap[] = { 133 { KE_KEY, 0x13f, { KEY_SWITCHVIDEOMODE } },
133 {KE_KEY, 0x101, KEY_MUTE}, 134 { KE_KEY, 0x140, { KEY_BRIGHTNESSDOWN } },
134 {KE_KEY, 0x102, KEY_ZOOMOUT}, 135 { KE_KEY, 0x141, { KEY_BRIGHTNESSUP } },
135 {KE_KEY, 0x103, KEY_ZOOMIN}, 136 { KE_KEY, 0x142, { KEY_WLAN } },
136 {KE_KEY, 0x13b, KEY_COFFEE}, 137 { KE_KEY, 0x143, { KEY_PROG1 } },
137 {KE_KEY, 0x13c, KEY_BATTERY}, 138 { KE_KEY, 0xb05, { KEY_PROG2 } },
138 {KE_KEY, 0x13d, KEY_SLEEP}, 139 { KE_KEY, 0xb06, { KEY_WWW } },
139 {KE_KEY, 0x13e, KEY_SUSPEND}, 140 { KE_KEY, 0xb07, { KEY_MAIL } },
140 {KE_KEY, 0x13f, KEY_SWITCHVIDEOMODE}, 141 { KE_KEY, 0xb30, { KEY_STOP } },
141 {KE_KEY, 0x140, KEY_BRIGHTNESSDOWN}, 142 { KE_KEY, 0xb31, { KEY_PREVIOUSSONG } },
142 {KE_KEY, 0x141, KEY_BRIGHTNESSUP}, 143 { KE_KEY, 0xb32, { KEY_NEXTSONG } },
143 {KE_KEY, 0x142, KEY_WLAN}, 144 { KE_KEY, 0xb33, { KEY_PLAYPAUSE } },
144 {KE_KEY, 0x143, KEY_PROG1}, 145 { KE_KEY, 0xb5a, { KEY_MEDIA } },
145 {KE_KEY, 0xb05, KEY_PROG2}, 146 { KE_END, 0 },
146 {KE_KEY, 0xb06, KEY_WWW},
147 {KE_KEY, 0xb07, KEY_MAIL},
148 {KE_KEY, 0xb30, KEY_STOP},
149 {KE_KEY, 0xb31, KEY_PREVIOUSSONG},
150 {KE_KEY, 0xb32, KEY_NEXTSONG},
151 {KE_KEY, 0xb33, KEY_PLAYPAUSE},
152 {KE_KEY, 0xb5a, KEY_MEDIA},
153 {KE_END, 0, 0},
154}; 147};
155 148
156/* utility 149/* utility
@@ -852,64 +845,9 @@ static struct backlight_ops toshiba_backlight_data = {
852 .update_status = set_lcd_status, 845 .update_status = set_lcd_status,
853}; 846};
854 847
855static struct key_entry *toshiba_acpi_get_entry_by_scancode(unsigned int code)
856{
857 struct key_entry *key;
858
859 for (key = toshiba_acpi_keymap; key->type != KE_END; key++)
860 if (code == key->code)
861 return key;
862
863 return NULL;
864}
865
866static struct key_entry *toshiba_acpi_get_entry_by_keycode(unsigned int code)
867{
868 struct key_entry *key;
869
870 for (key = toshiba_acpi_keymap; key->type != KE_END; key++)
871 if (code == key->keycode && key->type == KE_KEY)
872 return key;
873
874 return NULL;
875}
876
877static int toshiba_acpi_getkeycode(struct input_dev *dev,
878 unsigned int scancode, unsigned int *keycode)
879{
880 struct key_entry *key = toshiba_acpi_get_entry_by_scancode(scancode);
881
882 if (key && key->type == KE_KEY) {
883 *keycode = key->keycode;
884 return 0;
885 }
886
887 return -EINVAL;
888}
889
890static int toshiba_acpi_setkeycode(struct input_dev *dev,
891 unsigned int scancode, unsigned int keycode)
892{
893 struct key_entry *key;
894 unsigned int old_keycode;
895
896 key = toshiba_acpi_get_entry_by_scancode(scancode);
897 if (key && key->type == KE_KEY) {
898 old_keycode = key->keycode;
899 key->keycode = keycode;
900 set_bit(keycode, dev->keybit);
901 if (!toshiba_acpi_get_entry_by_keycode(old_keycode))
902 clear_bit(old_keycode, dev->keybit);
903 return 0;
904 }
905
906 return -EINVAL;
907}
908
909static void toshiba_acpi_notify(acpi_handle handle, u32 event, void *context) 848static void toshiba_acpi_notify(acpi_handle handle, u32 event, void *context)
910{ 849{
911 u32 hci_result, value; 850 u32 hci_result, value;
912 struct key_entry *key;
913 851
914 if (event != 0x80) 852 if (event != 0x80)
915 return; 853 return;
@@ -922,19 +860,11 @@ static void toshiba_acpi_notify(acpi_handle handle, u32 event, void *context)
922 if (value & 0x80) 860 if (value & 0x80)
923 continue; 861 continue;
924 862
925 key = toshiba_acpi_get_entry_by_scancode 863 if (!sparse_keymap_report_event(toshiba_acpi.hotkey_dev,
926 (value); 864 value, 1, true)) {
927 if (!key) {
928 printk(MY_INFO "Unknown key %x\n", 865 printk(MY_INFO "Unknown key %x\n",
929 value); 866 value);
930 continue;
931 } 867 }
932 input_report_key(toshiba_acpi.hotkey_dev,
933 key->keycode, 1);
934 input_sync(toshiba_acpi.hotkey_dev);
935 input_report_key(toshiba_acpi.hotkey_dev,
936 key->keycode, 0);
937 input_sync(toshiba_acpi.hotkey_dev);
938 } else if (hci_result == HCI_NOT_SUPPORTED) { 868 } else if (hci_result == HCI_NOT_SUPPORTED) {
939 /* This is a workaround for an unresolved issue on 869 /* This is a workaround for an unresolved issue on
940 * some machines where system events sporadically 870 * some machines where system events sporadically
@@ -945,34 +875,17 @@ static void toshiba_acpi_notify(acpi_handle handle, u32 event, void *context)
945 } while (hci_result != HCI_EMPTY); 875 } while (hci_result != HCI_EMPTY);
946} 876}
947 877
948static int toshiba_acpi_setup_keyboard(char *device) 878static int __init toshiba_acpi_setup_keyboard(char *device)
949{ 879{
950 acpi_status status; 880 acpi_status status;
951 acpi_handle handle; 881 int error;
952 int result;
953 const struct key_entry *key;
954 882
955 status = acpi_get_handle(NULL, device, &handle); 883 status = acpi_get_handle(NULL, device, &toshiba_acpi.handle);
956 if (ACPI_FAILURE(status)) { 884 if (ACPI_FAILURE(status)) {
957 printk(MY_INFO "Unable to get notification device\n"); 885 printk(MY_INFO "Unable to get notification device\n");
958 return -ENODEV; 886 return -ENODEV;
959 } 887 }
960 888
961 toshiba_acpi.handle = handle;
962
963 status = acpi_evaluate_object(handle, "ENAB", NULL, NULL);
964 if (ACPI_FAILURE(status)) {
965 printk(MY_INFO "Unable to enable hotkeys\n");
966 return -ENODEV;
967 }
968
969 status = acpi_install_notify_handler(handle, ACPI_DEVICE_NOTIFY,
970 toshiba_acpi_notify, NULL);
971 if (ACPI_FAILURE(status)) {
972 printk(MY_INFO "Unable to install hotkey notification\n");
973 return -ENODEV;
974 }
975
976 toshiba_acpi.hotkey_dev = input_allocate_device(); 889 toshiba_acpi.hotkey_dev = input_allocate_device();
977 if (!toshiba_acpi.hotkey_dev) { 890 if (!toshiba_acpi.hotkey_dev) {
978 printk(MY_INFO "Unable to register input device\n"); 891 printk(MY_INFO "Unable to register input device\n");
@@ -982,27 +895,54 @@ static int toshiba_acpi_setup_keyboard(char *device)
982 toshiba_acpi.hotkey_dev->name = "Toshiba input device"; 895 toshiba_acpi.hotkey_dev->name = "Toshiba input device";
983 toshiba_acpi.hotkey_dev->phys = device; 896 toshiba_acpi.hotkey_dev->phys = device;
984 toshiba_acpi.hotkey_dev->id.bustype = BUS_HOST; 897 toshiba_acpi.hotkey_dev->id.bustype = BUS_HOST;
985 toshiba_acpi.hotkey_dev->getkeycode = toshiba_acpi_getkeycode;
986 toshiba_acpi.hotkey_dev->setkeycode = toshiba_acpi_setkeycode;
987 898
988 for (key = toshiba_acpi_keymap; key->type != KE_END; key++) { 899 error = sparse_keymap_setup(toshiba_acpi.hotkey_dev,
989 set_bit(EV_KEY, toshiba_acpi.hotkey_dev->evbit); 900 toshiba_acpi_keymap, NULL);
990 set_bit(key->keycode, toshiba_acpi.hotkey_dev->keybit); 901 if (error)
902 goto err_free_dev;
903
904 status = acpi_install_notify_handler(toshiba_acpi.handle,
905 ACPI_DEVICE_NOTIFY, toshiba_acpi_notify, NULL);
906 if (ACPI_FAILURE(status)) {
907 printk(MY_INFO "Unable to install hotkey notification\n");
908 error = -ENODEV;
909 goto err_free_keymap;
910 }
911
912 status = acpi_evaluate_object(toshiba_acpi.handle, "ENAB", NULL, NULL);
913 if (ACPI_FAILURE(status)) {
914 printk(MY_INFO "Unable to enable hotkeys\n");
915 error = -ENODEV;
916 goto err_remove_notify;
991 } 917 }
992 918
993 result = input_register_device(toshiba_acpi.hotkey_dev); 919 error = input_register_device(toshiba_acpi.hotkey_dev);
994 if (result) { 920 if (error) {
995 printk(MY_INFO "Unable to register input device\n"); 921 printk(MY_INFO "Unable to register input device\n");
996 return result; 922 goto err_remove_notify;
997 } 923 }
998 924
999 return 0; 925 return 0;
926
927 err_remove_notify:
928 acpi_remove_notify_handler(toshiba_acpi.handle,
929 ACPI_DEVICE_NOTIFY, toshiba_acpi_notify);
930 err_free_keymap:
931 sparse_keymap_free(toshiba_acpi.hotkey_dev);
932 err_free_dev:
933 input_free_device(toshiba_acpi.hotkey_dev);
934 toshiba_acpi.hotkey_dev = NULL;
935 return error;
1000} 936}
1001 937
1002static void toshiba_acpi_exit(void) 938static void toshiba_acpi_exit(void)
1003{ 939{
1004 if (toshiba_acpi.hotkey_dev) 940 if (toshiba_acpi.hotkey_dev) {
941 acpi_remove_notify_handler(toshiba_acpi.handle,
942 ACPI_DEVICE_NOTIFY, toshiba_acpi_notify);
943 sparse_keymap_free(toshiba_acpi.hotkey_dev);
1005 input_unregister_device(toshiba_acpi.hotkey_dev); 944 input_unregister_device(toshiba_acpi.hotkey_dev);
945 }
1006 946
1007 if (toshiba_acpi.bt_rfk) { 947 if (toshiba_acpi.bt_rfk) {
1008 rfkill_unregister(toshiba_acpi.bt_rfk); 948 rfkill_unregister(toshiba_acpi.bt_rfk);
@@ -1017,9 +957,6 @@ static void toshiba_acpi_exit(void)
1017 if (toshiba_proc_dir) 957 if (toshiba_proc_dir)
1018 remove_proc_entry(PROC_TOSHIBA, acpi_root_dir); 958 remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
1019 959
1020 acpi_remove_notify_handler(toshiba_acpi.handle, ACPI_DEVICE_NOTIFY,
1021 toshiba_acpi_notify);
1022
1023 if (toshiba_acpi.illumination_installed) 960 if (toshiba_acpi.illumination_installed)
1024 led_classdev_unregister(&toshiba_led); 961 led_classdev_unregister(&toshiba_led);
1025 962
diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c
index b2978a04317f..104b77c87ef5 100644
--- a/drivers/platform/x86/wmi.c
+++ b/drivers/platform/x86/wmi.c
@@ -27,6 +27,8 @@
27 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 27 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
28 */ 28 */
29 29
30#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
31
30#include <linux/kernel.h> 32#include <linux/kernel.h>
31#include <linux/init.h> 33#include <linux/init.h>
32#include <linux/types.h> 34#include <linux/types.h>
@@ -44,9 +46,8 @@ MODULE_LICENSE("GPL");
44 46
45#define ACPI_WMI_CLASS "wmi" 47#define ACPI_WMI_CLASS "wmi"
46 48
47#define PREFIX "ACPI: WMI: "
48
49static DEFINE_MUTEX(wmi_data_lock); 49static DEFINE_MUTEX(wmi_data_lock);
50static LIST_HEAD(wmi_block_list);
50 51
51struct guid_block { 52struct guid_block {
52 char guid[16]; 53 char guid[16];
@@ -67,10 +68,9 @@ struct wmi_block {
67 acpi_handle handle; 68 acpi_handle handle;
68 wmi_notify_handler handler; 69 wmi_notify_handler handler;
69 void *handler_data; 70 void *handler_data;
70 struct device *dev; 71 struct device dev;
71}; 72};
72 73
73static struct wmi_block wmi_blocks;
74 74
75/* 75/*
76 * If the GUID data block is marked as expensive, we must enable and 76 * If the GUID data block is marked as expensive, we must enable and
@@ -110,7 +110,7 @@ static struct acpi_driver acpi_wmi_driver = {
110 .add = acpi_wmi_add, 110 .add = acpi_wmi_add,
111 .remove = acpi_wmi_remove, 111 .remove = acpi_wmi_remove,
112 .notify = acpi_wmi_notify, 112 .notify = acpi_wmi_notify,
113 }, 113 },
114}; 114};
115 115
116/* 116/*
@@ -128,30 +128,18 @@ static struct acpi_driver acpi_wmi_driver = {
128 */ 128 */
129static int wmi_parse_hexbyte(const u8 *src) 129static int wmi_parse_hexbyte(const u8 *src)
130{ 130{
131 unsigned int x; /* For correct wrapping */
132 int h; 131 int h;
132 int value;
133 133
134 /* high part */ 134 /* high part */
135 x = src[0]; 135 h = value = hex_to_bin(src[0]);
136 if (x - '0' <= '9' - '0') { 136 if (value < 0)
137 h = x - '0';
138 } else if (x - 'a' <= 'f' - 'a') {
139 h = x - 'a' + 10;
140 } else if (x - 'A' <= 'F' - 'A') {
141 h = x - 'A' + 10;
142 } else {
143 return -1; 137 return -1;
144 }
145 h <<= 4;
146 138
147 /* low part */ 139 /* low part */
148 x = src[1]; 140 value = hex_to_bin(src[1]);
149 if (x - '0' <= '9' - '0') 141 if (value >= 0)
150 return h | (x - '0'); 142 return (h << 4) | value;
151 if (x - 'a' <= 'f' - 'a')
152 return h | (x - 'a' + 10);
153 if (x - 'A' <= 'F' - 'A')
154 return h | (x - 'A' + 10);
155 return -1; 143 return -1;
156} 144}
157 145
@@ -232,7 +220,7 @@ static int wmi_gtoa(const char *in, char *out)
232 for (i = 10; i <= 15; i++) 220 for (i = 10; i <= 15; i++)
233 out += sprintf(out, "%02X", in[i] & 0xFF); 221 out += sprintf(out, "%02X", in[i] & 0xFF);
234 222
235 out = '\0'; 223 *out = '\0';
236 return 0; 224 return 0;
237} 225}
238 226
@@ -246,7 +234,7 @@ static bool find_guid(const char *guid_string, struct wmi_block **out)
246 wmi_parse_guid(guid_string, tmp); 234 wmi_parse_guid(guid_string, tmp);
247 wmi_swap_bytes(tmp, guid_input); 235 wmi_swap_bytes(tmp, guid_input);
248 236
249 list_for_each(p, &wmi_blocks.list) { 237 list_for_each(p, &wmi_block_list) {
250 wblock = list_entry(p, struct wmi_block, list); 238 wblock = list_entry(p, struct wmi_block, list);
251 block = &wblock->gblock; 239 block = &wblock->gblock;
252 240
@@ -487,30 +475,29 @@ const struct acpi_buffer *in)
487} 475}
488EXPORT_SYMBOL_GPL(wmi_set_block); 476EXPORT_SYMBOL_GPL(wmi_set_block);
489 477
490static void wmi_dump_wdg(struct guid_block *g) 478static void wmi_dump_wdg(const struct guid_block *g)
491{ 479{
492 char guid_string[37]; 480 char guid_string[37];
493 481
494 wmi_gtoa(g->guid, guid_string); 482 wmi_gtoa(g->guid, guid_string);
495 printk(KERN_INFO PREFIX "%s:\n", guid_string); 483
496 printk(KERN_INFO PREFIX "\tobject_id: %c%c\n", 484 pr_info("%s:\n", guid_string);
497 g->object_id[0], g->object_id[1]); 485 pr_info("\tobject_id: %c%c\n", g->object_id[0], g->object_id[1]);
498 printk(KERN_INFO PREFIX "\tnotify_id: %02X\n", g->notify_id); 486 pr_info("\tnotify_id: %02X\n", g->notify_id);
499 printk(KERN_INFO PREFIX "\treserved: %02X\n", g->reserved); 487 pr_info("\treserved: %02X\n", g->reserved);
500 printk(KERN_INFO PREFIX "\tinstance_count: %d\n", g->instance_count); 488 pr_info("\tinstance_count: %d\n", g->instance_count);
501 printk(KERN_INFO PREFIX "\tflags: %#x", g->flags); 489 pr_info("\tflags: %#x ", g->flags);
502 if (g->flags) { 490 if (g->flags) {
503 printk(" ");
504 if (g->flags & ACPI_WMI_EXPENSIVE) 491 if (g->flags & ACPI_WMI_EXPENSIVE)
505 printk("ACPI_WMI_EXPENSIVE "); 492 pr_cont("ACPI_WMI_EXPENSIVE ");
506 if (g->flags & ACPI_WMI_METHOD) 493 if (g->flags & ACPI_WMI_METHOD)
507 printk("ACPI_WMI_METHOD "); 494 pr_cont("ACPI_WMI_METHOD ");
508 if (g->flags & ACPI_WMI_STRING) 495 if (g->flags & ACPI_WMI_STRING)
509 printk("ACPI_WMI_STRING "); 496 pr_cont("ACPI_WMI_STRING ");
510 if (g->flags & ACPI_WMI_EVENT) 497 if (g->flags & ACPI_WMI_EVENT)
511 printk("ACPI_WMI_EVENT "); 498 pr_cont("ACPI_WMI_EVENT ");
512 } 499 }
513 printk("\n"); 500 pr_cont("\n");
514 501
515} 502}
516 503
@@ -522,7 +509,7 @@ static void wmi_notify_debug(u32 value, void *context)
522 509
523 status = wmi_get_event_data(value, &response); 510 status = wmi_get_event_data(value, &response);
524 if (status != AE_OK) { 511 if (status != AE_OK) {
525 printk(KERN_INFO "wmi: bad event status 0x%x\n", status); 512 pr_info("bad event status 0x%x\n", status);
526 return; 513 return;
527 } 514 }
528 515
@@ -531,22 +518,22 @@ static void wmi_notify_debug(u32 value, void *context)
531 if (!obj) 518 if (!obj)
532 return; 519 return;
533 520
534 printk(KERN_INFO PREFIX "DEBUG Event "); 521 pr_info("DEBUG Event ");
535 switch(obj->type) { 522 switch(obj->type) {
536 case ACPI_TYPE_BUFFER: 523 case ACPI_TYPE_BUFFER:
537 printk("BUFFER_TYPE - length %d\n", obj->buffer.length); 524 pr_cont("BUFFER_TYPE - length %d\n", obj->buffer.length);
538 break; 525 break;
539 case ACPI_TYPE_STRING: 526 case ACPI_TYPE_STRING:
540 printk("STRING_TYPE - %s\n", obj->string.pointer); 527 pr_cont("STRING_TYPE - %s\n", obj->string.pointer);
541 break; 528 break;
542 case ACPI_TYPE_INTEGER: 529 case ACPI_TYPE_INTEGER:
543 printk("INTEGER_TYPE - %llu\n", obj->integer.value); 530 pr_cont("INTEGER_TYPE - %llu\n", obj->integer.value);
544 break; 531 break;
545 case ACPI_TYPE_PACKAGE: 532 case ACPI_TYPE_PACKAGE:
546 printk("PACKAGE_TYPE - %d elements\n", obj->package.count); 533 pr_cont("PACKAGE_TYPE - %d elements\n", obj->package.count);
547 break; 534 break;
548 default: 535 default:
549 printk("object type 0x%X\n", obj->type); 536 pr_cont("object type 0x%X\n", obj->type);
550 } 537 }
551 kfree(obj); 538 kfree(obj);
552} 539}
@@ -633,7 +620,7 @@ acpi_status wmi_get_event_data(u32 event, struct acpi_buffer *out)
633 params[0].type = ACPI_TYPE_INTEGER; 620 params[0].type = ACPI_TYPE_INTEGER;
634 params[0].integer.value = event; 621 params[0].integer.value = event;
635 622
636 list_for_each(p, &wmi_blocks.list) { 623 list_for_each(p, &wmi_block_list) {
637 wblock = list_entry(p, struct wmi_block, list); 624 wblock = list_entry(p, struct wmi_block, list);
638 gblock = &wblock->gblock; 625 gblock = &wblock->gblock;
639 626
@@ -662,7 +649,7 @@ EXPORT_SYMBOL_GPL(wmi_has_guid);
662/* 649/*
663 * sysfs interface 650 * sysfs interface
664 */ 651 */
665static ssize_t show_modalias(struct device *dev, struct device_attribute *attr, 652static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
666 char *buf) 653 char *buf)
667{ 654{
668 char guid_string[37]; 655 char guid_string[37];
@@ -676,7 +663,11 @@ static ssize_t show_modalias(struct device *dev, struct device_attribute *attr,
676 663
677 return sprintf(buf, "wmi:%s\n", guid_string); 664 return sprintf(buf, "wmi:%s\n", guid_string);
678} 665}
679static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL); 666
667static struct device_attribute wmi_dev_attrs[] = {
668 __ATTR_RO(modalias),
669 __ATTR_NULL
670};
680 671
681static int wmi_dev_uevent(struct device *dev, struct kobj_uevent_env *env) 672static int wmi_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
682{ 673{
@@ -702,108 +693,71 @@ static int wmi_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
702 693
703static void wmi_dev_free(struct device *dev) 694static void wmi_dev_free(struct device *dev)
704{ 695{
705 kfree(dev); 696 struct wmi_block *wmi_block = container_of(dev, struct wmi_block, dev);
697
698 kfree(wmi_block);
706} 699}
707 700
708static struct class wmi_class = { 701static struct class wmi_class = {
709 .name = "wmi", 702 .name = "wmi",
710 .dev_release = wmi_dev_free, 703 .dev_release = wmi_dev_free,
711 .dev_uevent = wmi_dev_uevent, 704 .dev_uevent = wmi_dev_uevent,
705 .dev_attrs = wmi_dev_attrs,
712}; 706};
713 707
714static int wmi_create_devs(void) 708static struct wmi_block *wmi_create_device(const struct guid_block *gblock,
709 acpi_handle handle)
715{ 710{
716 int result;
717 char guid_string[37];
718 struct guid_block *gblock;
719 struct wmi_block *wblock; 711 struct wmi_block *wblock;
720 struct list_head *p; 712 int error;
721 struct device *guid_dev; 713 char guid_string[37];
722
723 /* Create devices for all the GUIDs */
724 list_for_each(p, &wmi_blocks.list) {
725 wblock = list_entry(p, struct wmi_block, list);
726
727 guid_dev = kzalloc(sizeof(struct device), GFP_KERNEL);
728 if (!guid_dev)
729 return -ENOMEM;
730
731 wblock->dev = guid_dev;
732
733 guid_dev->class = &wmi_class;
734 dev_set_drvdata(guid_dev, wblock);
735
736 gblock = &wblock->gblock;
737
738 wmi_gtoa(gblock->guid, guid_string);
739 dev_set_name(guid_dev, guid_string);
740
741 result = device_register(guid_dev);
742 if (result)
743 return result;
744 714
745 result = device_create_file(guid_dev, &dev_attr_modalias); 715 wblock = kzalloc(sizeof(struct wmi_block), GFP_KERNEL);
746 if (result) 716 if (!wblock) {
747 return result; 717 error = -ENOMEM;
718 goto err_out;
748 } 719 }
749 720
750 return 0; 721 wblock->handle = handle;
751} 722 wblock->gblock = *gblock;
752 723
753static void wmi_remove_devs(void) 724 wblock->dev.class = &wmi_class;
754{
755 struct guid_block *gblock;
756 struct wmi_block *wblock;
757 struct list_head *p;
758 struct device *guid_dev;
759 725
760 /* Delete devices for all the GUIDs */ 726 wmi_gtoa(gblock->guid, guid_string);
761 list_for_each(p, &wmi_blocks.list) { 727 dev_set_name(&wblock->dev, guid_string);
762 wblock = list_entry(p, struct wmi_block, list);
763 728
764 guid_dev = wblock->dev; 729 dev_set_drvdata(&wblock->dev, wblock);
765 gblock = &wblock->gblock;
766 730
767 device_remove_file(guid_dev, &dev_attr_modalias); 731 error = device_register(&wblock->dev);
732 if (error)
733 goto err_free;
768 734
769 device_unregister(guid_dev); 735 list_add_tail(&wblock->list, &wmi_block_list);
770 } 736 return wblock;
771}
772 737
773static void wmi_class_exit(void) 738err_free:
774{ 739 kfree(wblock);
775 wmi_remove_devs(); 740err_out:
776 class_unregister(&wmi_class); 741 return ERR_PTR(error);
777} 742}
778 743
779static int wmi_class_init(void) 744static void wmi_free_devices(void)
780{ 745{
781 int ret; 746 struct wmi_block *wblock, *next;
782
783 ret = class_register(&wmi_class);
784 if (ret)
785 return ret;
786 747
787 ret = wmi_create_devs(); 748 /* Delete devices for all the GUIDs */
788 if (ret) 749 list_for_each_entry_safe(wblock, next, &wmi_block_list, list)
789 wmi_class_exit(); 750 device_unregister(&wblock->dev);
790
791 return ret;
792} 751}
793 752
794static bool guid_already_parsed(const char *guid_string) 753static bool guid_already_parsed(const char *guid_string)
795{ 754{
796 struct guid_block *gblock;
797 struct wmi_block *wblock; 755 struct wmi_block *wblock;
798 struct list_head *p;
799 756
800 list_for_each(p, &wmi_blocks.list) { 757 list_for_each_entry(wblock, &wmi_block_list, list)
801 wblock = list_entry(p, struct wmi_block, list); 758 if (strncmp(wblock->gblock.guid, guid_string, 16) == 0)
802 gblock = &wblock->gblock;
803
804 if (strncmp(gblock->guid, guid_string, 16) == 0)
805 return true; 759 return true;
806 } 760
807 return false; 761 return false;
808} 762}
809 763
@@ -814,30 +768,29 @@ static acpi_status parse_wdg(acpi_handle handle)
814{ 768{
815 struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL}; 769 struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL};
816 union acpi_object *obj; 770 union acpi_object *obj;
817 struct guid_block *gblock; 771 const struct guid_block *gblock;
818 struct wmi_block *wblock; 772 struct wmi_block *wblock;
819 char guid_string[37]; 773 char guid_string[37];
820 acpi_status status; 774 acpi_status status;
775 int retval;
821 u32 i, total; 776 u32 i, total;
822 777
823 status = acpi_evaluate_object(handle, "_WDG", NULL, &out); 778 status = acpi_evaluate_object(handle, "_WDG", NULL, &out);
824
825 if (ACPI_FAILURE(status)) 779 if (ACPI_FAILURE(status))
826 return status; 780 return -ENXIO;
827 781
828 obj = (union acpi_object *) out.pointer; 782 obj = (union acpi_object *) out.pointer;
783 if (!obj)
784 return -ENXIO;
829 785
830 if (obj->type != ACPI_TYPE_BUFFER) 786 if (obj->type != ACPI_TYPE_BUFFER) {
831 return AE_ERROR; 787 retval = -ENXIO;
832
833 total = obj->buffer.length / sizeof(struct guid_block);
834
835 gblock = kmemdup(obj->buffer.pointer, obj->buffer.length, GFP_KERNEL);
836 if (!gblock) {
837 status = AE_NO_MEMORY;
838 goto out_free_pointer; 788 goto out_free_pointer;
839 } 789 }
840 790
791 gblock = (const struct guid_block *)obj->buffer.pointer;
792 total = obj->buffer.length / sizeof(struct guid_block);
793
841 for (i = 0; i < total; i++) { 794 for (i = 0; i < total; i++) {
842 /* 795 /*
843 Some WMI devices, like those for nVidia hooks, have a 796 Some WMI devices, like those for nVidia hooks, have a
@@ -848,34 +801,32 @@ static acpi_status parse_wdg(acpi_handle handle)
848 */ 801 */
849 if (guid_already_parsed(gblock[i].guid) == true) { 802 if (guid_already_parsed(gblock[i].guid) == true) {
850 wmi_gtoa(gblock[i].guid, guid_string); 803 wmi_gtoa(gblock[i].guid, guid_string);
851 printk(KERN_INFO PREFIX "Skipping duplicate GUID %s\n", 804 pr_info("Skipping duplicate GUID %s\n", guid_string);
852 guid_string);
853 continue; 805 continue;
854 } 806 }
807
855 if (debug_dump_wdg) 808 if (debug_dump_wdg)
856 wmi_dump_wdg(&gblock[i]); 809 wmi_dump_wdg(&gblock[i]);
857 810
858 wblock = kzalloc(sizeof(struct wmi_block), GFP_KERNEL); 811 wblock = wmi_create_device(&gblock[i], handle);
859 if (!wblock) { 812 if (IS_ERR(wblock)) {
860 status = AE_NO_MEMORY; 813 retval = PTR_ERR(wblock);
861 goto out_free_gblock; 814 wmi_free_devices();
815 break;
862 } 816 }
863 817
864 wblock->gblock = gblock[i];
865 wblock->handle = handle;
866 if (debug_event) { 818 if (debug_event) {
867 wblock->handler = wmi_notify_debug; 819 wblock->handler = wmi_notify_debug;
868 status = wmi_method_enable(wblock, 1); 820 wmi_method_enable(wblock, 1);
869 } 821 }
870 list_add_tail(&wblock->list, &wmi_blocks.list);
871 } 822 }
872 823
873out_free_gblock: 824 retval = 0;
874 kfree(gblock); 825
875out_free_pointer: 826out_free_pointer:
876 kfree(out.pointer); 827 kfree(out.pointer);
877 828
878 return status; 829 return retval;
879} 830}
880 831
881/* 832/*
@@ -929,7 +880,7 @@ static void acpi_wmi_notify(struct acpi_device *device, u32 event)
929 struct list_head *p; 880 struct list_head *p;
930 char guid_string[37]; 881 char guid_string[37];
931 882
932 list_for_each(p, &wmi_blocks.list) { 883 list_for_each(p, &wmi_block_list) {
933 wblock = list_entry(p, struct wmi_block, list); 884 wblock = list_entry(p, struct wmi_block, list);
934 block = &wblock->gblock; 885 block = &wblock->gblock;
935 886
@@ -939,8 +890,7 @@ static void acpi_wmi_notify(struct acpi_device *device, u32 event)
939 wblock->handler(event, wblock->handler_data); 890 wblock->handler(event, wblock->handler_data);
940 if (debug_event) { 891 if (debug_event) {
941 wmi_gtoa(wblock->gblock.guid, guid_string); 892 wmi_gtoa(wblock->gblock.guid, guid_string);
942 printk(KERN_INFO PREFIX "DEBUG Event GUID:" 893 pr_info("DEBUG Event GUID: %s\n", guid_string);
943 " %s\n", guid_string);
944 } 894 }
945 895
946 acpi_bus_generate_netlink_event( 896 acpi_bus_generate_netlink_event(
@@ -955,6 +905,7 @@ static int acpi_wmi_remove(struct acpi_device *device, int type)
955{ 905{
956 acpi_remove_address_space_handler(device->handle, 906 acpi_remove_address_space_handler(device->handle,
957 ACPI_ADR_SPACE_EC, &acpi_wmi_ec_space_handler); 907 ACPI_ADR_SPACE_EC, &acpi_wmi_ec_space_handler);
908 wmi_free_devices();
958 909
959 return 0; 910 return 0;
960} 911}
@@ -962,68 +913,57 @@ static int acpi_wmi_remove(struct acpi_device *device, int type)
962static int acpi_wmi_add(struct acpi_device *device) 913static int acpi_wmi_add(struct acpi_device *device)
963{ 914{
964 acpi_status status; 915 acpi_status status;
965 int result = 0; 916 int error;
966 917
967 status = acpi_install_address_space_handler(device->handle, 918 status = acpi_install_address_space_handler(device->handle,
968 ACPI_ADR_SPACE_EC, 919 ACPI_ADR_SPACE_EC,
969 &acpi_wmi_ec_space_handler, 920 &acpi_wmi_ec_space_handler,
970 NULL, NULL); 921 NULL, NULL);
971 if (ACPI_FAILURE(status))
972 return -ENODEV;
973
974 status = parse_wdg(device->handle);
975 if (ACPI_FAILURE(status)) { 922 if (ACPI_FAILURE(status)) {
976 printk(KERN_ERR PREFIX "Error installing EC region handler\n"); 923 pr_err("Error installing EC region handler\n");
977 return -ENODEV; 924 return -ENODEV;
978 } 925 }
979 926
980 return result; 927 error = parse_wdg(device->handle);
928 if (error) {
929 acpi_remove_address_space_handler(device->handle,
930 ACPI_ADR_SPACE_EC,
931 &acpi_wmi_ec_space_handler);
932 pr_err("Failed to parse WDG method\n");
933 return error;
934 }
935
936 return 0;
981} 937}
982 938
983static int __init acpi_wmi_init(void) 939static int __init acpi_wmi_init(void)
984{ 940{
985 int result; 941 int error;
986
987 INIT_LIST_HEAD(&wmi_blocks.list);
988 942
989 if (acpi_disabled) 943 if (acpi_disabled)
990 return -ENODEV; 944 return -ENODEV;
991 945
992 result = acpi_bus_register_driver(&acpi_wmi_driver); 946 error = class_register(&wmi_class);
947 if (error)
948 return error;
993 949
994 if (result < 0) { 950 error = acpi_bus_register_driver(&acpi_wmi_driver);
995 printk(KERN_INFO PREFIX "Error loading mapper\n"); 951 if (error) {
996 return -ENODEV; 952 pr_err("Error loading mapper\n");
953 class_unregister(&wmi_class);
954 return error;
997 } 955 }
998 956
999 result = wmi_class_init(); 957 pr_info("Mapper loaded\n");
1000 if (result) { 958 return 0;
1001 acpi_bus_unregister_driver(&acpi_wmi_driver);
1002 return result;
1003 }
1004
1005 printk(KERN_INFO PREFIX "Mapper loaded\n");
1006
1007 return result;
1008} 959}
1009 960
1010static void __exit acpi_wmi_exit(void) 961static void __exit acpi_wmi_exit(void)
1011{ 962{
1012 struct list_head *p, *tmp;
1013 struct wmi_block *wblock;
1014
1015 wmi_class_exit();
1016
1017 acpi_bus_unregister_driver(&acpi_wmi_driver); 963 acpi_bus_unregister_driver(&acpi_wmi_driver);
964 class_unregister(&wmi_class);
1018 965
1019 list_for_each_safe(p, tmp, &wmi_blocks.list) { 966 pr_info("Mapper unloaded\n");
1020 wblock = list_entry(p, struct wmi_block, list);
1021
1022 list_del(p);
1023 kfree(wblock);
1024 }
1025
1026 printk(KERN_INFO PREFIX "Mapper unloaded\n");
1027} 967}
1028 968
1029subsys_initcall(acpi_wmi_init); 969subsys_initcall(acpi_wmi_init);
diff --git a/drivers/platform/x86/xo1-rfkill.c b/drivers/platform/x86/xo1-rfkill.c
new file mode 100644
index 000000000000..e549eeeda121
--- /dev/null
+++ b/drivers/platform/x86/xo1-rfkill.c
@@ -0,0 +1,85 @@
1/*
2 * Support for rfkill through the OLPC XO-1 laptop embedded controller
3 *
4 * Copyright (C) 2010 One Laptop per Child
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 as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#include <linux/module.h>
13#include <linux/platform_device.h>
14#include <linux/rfkill.h>
15
16#include <asm/olpc.h>
17
18static int rfkill_set_block(void *data, bool blocked)
19{
20 unsigned char cmd;
21 if (blocked)
22 cmd = EC_WLAN_ENTER_RESET;
23 else
24 cmd = EC_WLAN_LEAVE_RESET;
25
26 return olpc_ec_cmd(cmd, NULL, 0, NULL, 0);
27}
28
29static const struct rfkill_ops rfkill_ops = {
30 .set_block = rfkill_set_block,
31};
32
33static int __devinit xo1_rfkill_probe(struct platform_device *pdev)
34{
35 struct rfkill *rfk;
36 int r;
37
38 rfk = rfkill_alloc(pdev->name, &pdev->dev, RFKILL_TYPE_WLAN,
39 &rfkill_ops, NULL);
40 if (!rfk)
41 return -ENOMEM;
42
43 r = rfkill_register(rfk);
44 if (r) {
45 rfkill_destroy(rfk);
46 return r;
47 }
48
49 platform_set_drvdata(pdev, rfk);
50 return 0;
51}
52
53static int __devexit xo1_rfkill_remove(struct platform_device *pdev)
54{
55 struct rfkill *rfk = platform_get_drvdata(pdev);
56 rfkill_unregister(rfk);
57 rfkill_destroy(rfk);
58 return 0;
59}
60
61static struct platform_driver xo1_rfkill_driver = {
62 .driver = {
63 .name = "xo1-rfkill",
64 .owner = THIS_MODULE,
65 },
66 .probe = xo1_rfkill_probe,
67 .remove = __devexit_p(xo1_rfkill_remove),
68};
69
70static int __init xo1_rfkill_init(void)
71{
72 return platform_driver_register(&xo1_rfkill_driver);
73}
74
75static void __exit xo1_rfkill_exit(void)
76{
77 platform_driver_unregister(&xo1_rfkill_driver);
78}
79
80MODULE_AUTHOR("Daniel Drake <dsd@laptop.org>");
81MODULE_LICENSE("GPL");
82MODULE_ALIAS("platform:xo1-rfkill");
83
84module_init(xo1_rfkill_init);
85module_exit(xo1_rfkill_exit);