aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/platform')
-rw-r--r--drivers/platform/x86/Kconfig211
-rw-r--r--drivers/platform/x86/Makefile17
-rw-r--r--drivers/platform/x86/acer-wmi.c671
-rw-r--r--drivers/platform/x86/acerhdf.c4
-rw-r--r--drivers/platform/x86/asus-laptop.c463
-rw-r--r--drivers/platform/x86/asus-nb-wmi.c98
-rw-r--r--drivers/platform/x86/asus-wmi.c1657
-rw-r--r--drivers/platform/x86/asus-wmi.h58
-rw-r--r--drivers/platform/x86/asus_acpi.c88
-rw-r--r--drivers/platform/x86/classmate-laptop.c20
-rw-r--r--drivers/platform/x86/compal-laptop.c55
-rw-r--r--drivers/platform/x86/dell-laptop.c98
-rw-r--r--drivers/platform/x86/dell-wmi-aio.c172
-rw-r--r--drivers/platform/x86/dell-wmi.c273
-rw-r--r--drivers/platform/x86/eeepc-laptop.c108
-rw-r--r--drivers/platform/x86/eeepc-wmi.c405
-rw-r--r--drivers/platform/x86/fujitsu-laptop.c48
-rw-r--r--drivers/platform/x86/hdaps.c638
-rw-r--r--drivers/platform/x86/hp-wmi.c502
-rw-r--r--drivers/platform/x86/hp_accel.c404
-rw-r--r--drivers/platform/x86/ibm_rtl.c339
-rw-r--r--drivers/platform/x86/ideapad-laptop.c497
-rw-r--r--drivers/platform/x86/ideapad_acpi.c306
-rw-r--r--drivers/platform/x86/intel_ips.c51
-rw-r--r--drivers/platform/x86/intel_ips.h21
-rw-r--r--drivers/platform/x86/intel_menlow.c5
-rw-r--r--drivers/platform/x86/intel_mid_powerbtn.c136
-rw-r--r--drivers/platform/x86/intel_mid_thermal.c571
-rw-r--r--drivers/platform/x86/intel_oaktrail.c397
-rw-r--r--drivers/platform/x86/intel_pmic_gpio.c168
-rw-r--r--drivers/platform/x86/intel_rar_register.c2
-rw-r--r--drivers/platform/x86/intel_scu_ipc.c18
-rw-r--r--drivers/platform/x86/intel_scu_ipcutil.c133
-rw-r--r--drivers/platform/x86/msi-laptop.c111
-rw-r--r--drivers/platform/x86/msi-wmi.c62
-rw-r--r--drivers/platform/x86/mxm-wmi.c111
-rw-r--r--drivers/platform/x86/panasonic-laptop.c195
-rw-r--r--drivers/platform/x86/samsung-laptop.c843
-rw-r--r--drivers/platform/x86/sony-laptop.c660
-rw-r--r--drivers/platform/x86/tc1100-wmi.c9
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c588
-rw-r--r--drivers/platform/x86/topstar-laptop.c163
-rw-r--r--drivers/platform/x86/toshiba_acpi.c250
-rw-r--r--drivers/platform/x86/toshiba_bluetooth.c11
-rw-r--r--drivers/platform/x86/wmi.c385
-rw-r--r--drivers/platform/x86/xo1-rfkill.c85
-rw-r--r--drivers/platform/x86/xo15-ebook.c181
47 files changed, 9636 insertions, 2652 deletions
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index cff7cc2c1f02..45e0191c35dd 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -18,12 +18,14 @@ if X86_PLATFORM_DEVICES
18config ACER_WMI 18config ACER_WMI
19 tristate "Acer WMI Laptop Extras" 19 tristate "Acer WMI Laptop Extras"
20 depends on ACPI 20 depends on ACPI
21 depends on LEDS_CLASS 21 select LEDS_CLASS
22 depends on NEW_LEDS 22 select NEW_LEDS
23 depends on BACKLIGHT_CLASS_DEVICE 23 depends on BACKLIGHT_CLASS_DEVICE
24 depends on SERIO_I8042 24 depends on SERIO_I8042
25 depends on INPUT
25 depends on RFKILL || RFKILL = n 26 depends on RFKILL || RFKILL = n
26 select ACPI_WMI 27 depends on ACPI_WMI
28 select INPUT_SPARSEKMAP
27 ---help--- 29 ---help---
28 This is a driver for newer Acer (and Wistron) laptops. It adds 30 This is a driver for newer Acer (and Wistron) laptops. It adds
29 wireless radio and bluetooth control, and on some laptops, 31 wireless radio and bluetooth control, and on some laptops,
@@ -37,7 +39,7 @@ config ACER_WMI
37 39
38config ACERHDF 40config ACERHDF
39 tristate "Acer Aspire One temperature and fan driver" 41 tristate "Acer Aspire One temperature and fan driver"
40 depends on THERMAL && THERMAL_HWMON && ACPI 42 depends on THERMAL && ACPI
41 ---help--- 43 ---help---
42 This is a driver for Acer Aspire One netbooks. It allows to access 44 This is a driver for Acer Aspire One netbooks. It allows to access
43 the temperature sensor and to control the fan. 45 the temperature sensor and to control the fan.
@@ -92,12 +94,26 @@ config DELL_WMI
92 tristate "Dell WMI extras" 94 tristate "Dell WMI extras"
93 depends on ACPI_WMI 95 depends on ACPI_WMI
94 depends on INPUT 96 depends on INPUT
97 select INPUT_SPARSEKMAP
95 ---help--- 98 ---help---
96 Say Y here if you want to support WMI-based hotkeys on Dell laptops. 99 Say Y here if you want to support WMI-based hotkeys on Dell laptops.
97 100
98 To compile this driver as a module, choose M here: the module will 101 To compile this driver as a module, choose M here: the module will
99 be called dell-wmi. 102 be called dell-wmi.
100 103
104config DELL_WMI_AIO
105 tristate "WMI Hotkeys for Dell All-In-One series"
106 depends on ACPI_WMI
107 depends on INPUT
108 select INPUT_SPARSEKMAP
109 ---help---
110 Say Y here if you want to support WMI-based hotkeys on Dell
111 All-In-One machines.
112
113 To compile this driver as a module, choose M here: the module will
114 be called dell-wmi-aio.
115
116
101config FUJITSU_LAPTOP 117config FUJITSU_LAPTOP
102 tristate "Fujitsu Laptop Extras" 118 tristate "Fujitsu Laptop Extras"
103 depends on ACPI 119 depends on ACPI
@@ -130,16 +146,35 @@ config TC1100_WMI
130 depends on !X86_64 146 depends on !X86_64
131 depends on EXPERIMENTAL 147 depends on EXPERIMENTAL
132 depends on ACPI 148 depends on ACPI
133 select ACPI_WMI 149 depends on ACPI_WMI
134 ---help--- 150 ---help---
135 This is a driver for the WMI extensions (wireless and bluetooth power 151 This is a driver for the WMI extensions (wireless and bluetooth power
136 control) of the HP Compaq TC1100 tablet. 152 control) of the HP Compaq TC1100 tablet.
137 153
154config HP_ACCEL
155 tristate "HP laptop accelerometer"
156 depends on INPUT && ACPI
157 select SENSORS_LIS3LV02D
158 select NEW_LEDS
159 select LEDS_CLASS
160 help
161 This driver provides support for the "Mobile Data Protection System 3D"
162 or "3D DriveGuard" feature of HP laptops. On such systems the driver
163 should load automatically (via ACPI alias).
164
165 Support for a led indicating disk protection will be provided as
166 hp::hddprotect. For more information on the feature, refer to
167 Documentation/hwmon/lis3lv02d.
168
169 To compile this driver as a module, choose M here: the module will
170 be called hp_accel.
171
138config HP_WMI 172config HP_WMI
139 tristate "HP WMI extras" 173 tristate "HP WMI extras"
140 depends on ACPI_WMI 174 depends on ACPI_WMI
141 depends on INPUT 175 depends on INPUT
142 depends on RFKILL || RFKILL = n 176 depends on RFKILL || RFKILL = n
177 select INPUT_SPARSEKMAP
143 help 178 help
144 Say Y here if you want to support WMI-based hotkeys on HP laptops and 179 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. 180 to read data from WMI such as docking or ambient light sensor state.
@@ -152,7 +187,8 @@ config MSI_LAPTOP
152 depends on ACPI 187 depends on ACPI
153 depends on BACKLIGHT_CLASS_DEVICE 188 depends on BACKLIGHT_CLASS_DEVICE
154 depends on RFKILL 189 depends on RFKILL
155 depends on SERIO_I8042 190 depends on INPUT && SERIO_I8042
191 select INPUT_SPARSEKMAP
156 ---help--- 192 ---help---
157 This is a driver for laptops built by MSI (MICRO-STAR 193 This is a driver for laptops built by MSI (MICRO-STAR
158 INTERNATIONAL): 194 INTERNATIONAL):
@@ -171,6 +207,7 @@ config PANASONIC_LAPTOP
171 tristate "Panasonic Laptop Extras" 207 tristate "Panasonic Laptop Extras"
172 depends on INPUT && ACPI 208 depends on INPUT && ACPI
173 depends on BACKLIGHT_CLASS_DEVICE 209 depends on BACKLIGHT_CLASS_DEVICE
210 select INPUT_SPARSEKMAP
174 ---help--- 211 ---help---
175 This driver adds support for access to backlight control and hotkeys 212 This driver adds support for access to backlight control and hotkeys
176 on Panasonic Let's Note laptops. 213 on Panasonic Let's Note laptops.
@@ -219,10 +256,11 @@ config SONYPI_COMPAT
219 ---help--- 256 ---help---
220 Build the sonypi driver compatibility code into the sony-laptop driver. 257 Build the sonypi driver compatibility code into the sony-laptop driver.
221 258
222config IDEAPAD_ACPI 259config IDEAPAD_LAPTOP
223 tristate "Lenovo IdeaPad ACPI Laptop Extras" 260 tristate "Lenovo IdeaPad Laptop Extras"
224 depends on ACPI 261 depends on ACPI
225 depends on RFKILL 262 depends on RFKILL && INPUT
263 select INPUT_SPARSEKMAP
226 help 264 help
227 This is a driver for the rfkill switches on Lenovo IdeaPad netbooks. 265 This is a driver for the rfkill switches on Lenovo IdeaPad netbooks.
228 266
@@ -365,6 +403,26 @@ config THINKPAD_ACPI_HOTKEY_POLL
365 If you are not sure, say Y here. The driver enables polling only if 403 If you are not sure, say Y here. The driver enables polling only if
366 it is strictly necessary to do so. 404 it is strictly necessary to do so.
367 405
406config SENSORS_HDAPS
407 tristate "Thinkpad Hard Drive Active Protection System (hdaps)"
408 depends on INPUT && X86
409 select INPUT_POLLDEV
410 default n
411 help
412 This driver provides support for the IBM Hard Drive Active Protection
413 System (hdaps), which provides an accelerometer and other misc. data.
414 ThinkPads starting with the R50, T41, and X40 are supported. The
415 accelerometer data is readable via sysfs.
416
417 This driver also provides an absolute input class device, allowing
418 the laptop to act as a pinball machine-esque joystick.
419
420 If your ThinkPad is not recognized by the driver, please update to latest
421 BIOS. This is especially the case for some R52 ThinkPads.
422
423 Say Y here if you have an applicable laptop and want to experience
424 the awesome power of hdaps.
425
368config INTEL_MENLOW 426config INTEL_MENLOW
369 tristate "Thermal Management driver for Intel menlow platform" 427 tristate "Thermal Management driver for Intel menlow platform"
370 depends on ACPI_THERMAL 428 depends on ACPI_THERMAL
@@ -394,20 +452,53 @@ config EEEPC_LAPTOP
394 Bluetooth, backlight and allows powering on/off some other 452 Bluetooth, backlight and allows powering on/off some other
395 devices. 453 devices.
396 454
397 If you have an Eee PC laptop, say Y or M here. 455 If you have an Eee PC laptop, say Y or M here. If this driver
456 doesn't work on your Eee PC, try eeepc-wmi instead.
398 457
399config EEEPC_WMI 458config ASUS_WMI
400 tristate "Eee PC WMI Hotkey Driver (EXPERIMENTAL)" 459 tristate "ASUS WMI Driver (EXPERIMENTAL)"
401 depends on ACPI_WMI 460 depends on ACPI_WMI
402 depends on INPUT 461 depends on INPUT
462 depends on HWMON
403 depends on EXPERIMENTAL 463 depends on EXPERIMENTAL
404 depends on BACKLIGHT_CLASS_DEVICE 464 depends on BACKLIGHT_CLASS_DEVICE
465 depends on RFKILL || RFKILL = n
466 depends on HOTPLUG_PCI
405 select INPUT_SPARSEKMAP 467 select INPUT_SPARSEKMAP
468 select LEDS_CLASS
469 select NEW_LEDS
406 ---help--- 470 ---help---
407 Say Y here if you want to support WMI-based hotkeys on Eee PC laptops. 471 Say Y here if you have a WMI aware Asus laptop (like Eee PCs or new
472 Asus Notebooks).
408 473
409 To compile this driver as a module, choose M here: the module will 474 To compile this driver as a module, choose M here: the module will
410 be called eeepc-wmi. 475 be called asus-wmi.
476
477config ASUS_NB_WMI
478 tristate "Asus Notebook WMI Driver (EXPERIMENTAL)"
479 depends on ASUS_WMI
480 ---help---
481 This is a driver for newer Asus notebooks. It adds extra features
482 like wireless radio and bluetooth control, leds, hotkeys, backlight...
483
484 For more informations, see
485 <file:Documentation/ABI/testing/sysfs-platform-asus-wmi>
486
487 If you have an ACPI-WMI compatible Asus Notebook, say Y or M
488 here.
489
490config EEEPC_WMI
491 tristate "Eee PC WMI Driver (EXPERIMENTAL)"
492 depends on ASUS_WMI
493 ---help---
494 This is a driver for newer Eee PC laptops. It adds extra features
495 like wireless radio and bluetooth control, leds, hotkeys, backlight...
496
497 For more informations, see
498 <file:Documentation/ABI/testing/sysfs-platform-asus-wmi>
499
500 If you have an ACPI-WMI compatible Eee PC laptop (>= 1000), say Y or M
501 here.
411 502
412config ACPI_WMI 503config ACPI_WMI
413 tristate "WMI" 504 tristate "WMI"
@@ -478,6 +569,7 @@ config TOPSTAR_LAPTOP
478 tristate "Topstar Laptop Extras" 569 tristate "Topstar Laptop Extras"
479 depends on ACPI 570 depends on ACPI
480 depends on INPUT 571 depends on INPUT
572 select INPUT_SPARSEKMAP
481 ---help--- 573 ---help---
482 This driver adds support for hotkeys found on Topstar laptops. 574 This driver adds support for hotkeys found on Topstar laptops.
483 575
@@ -486,12 +578,13 @@ config TOPSTAR_LAPTOP
486config ACPI_TOSHIBA 578config ACPI_TOSHIBA
487 tristate "Toshiba Laptop Extras" 579 tristate "Toshiba Laptop Extras"
488 depends on ACPI 580 depends on ACPI
489 depends on LEDS_CLASS 581 select LEDS_CLASS
490 depends on NEW_LEDS 582 select NEW_LEDS
491 depends on BACKLIGHT_CLASS_DEVICE 583 depends on BACKLIGHT_CLASS_DEVICE
492 depends on INPUT 584 depends on INPUT
493 depends on RFKILL || RFKILL = n 585 depends on RFKILL || RFKILL = n
494 select INPUT_POLLDEV 586 select INPUT_POLLDEV
587 select INPUT_SPARSEKMAP
495 ---help--- 588 ---help---
496 This driver adds support for access to certain system settings 589 This driver adds support for access to certain system settings
497 on "legacy free" Toshiba laptops. These laptops can be recognized by 590 on "legacy free" Toshiba laptops. These laptops can be recognized by
@@ -551,6 +644,15 @@ config INTEL_SCU_IPC
551 some embedded Intel x86 platforms. This is not needed for PC-type 644 some embedded Intel x86 platforms. This is not needed for PC-type
552 machines. 645 machines.
553 646
647config INTEL_SCU_IPC_UTIL
648 tristate "Intel SCU IPC utility driver"
649 depends on INTEL_SCU_IPC
650 default y
651 ---help---
652 The IPC Util driver provides an interface with the SCU enabling
653 low level access for debug work and updating the firmware. Say
654 N unless you will be doing this on an Intel MID platform.
655
554config GPIO_INTEL_PMIC 656config GPIO_INTEL_PMIC
555 bool "Intel PMIC GPIO support" 657 bool "Intel PMIC GPIO support"
556 depends on INTEL_SCU_IPC && GPIOLIB 658 depends on INTEL_SCU_IPC && GPIOLIB
@@ -558,6 +660,21 @@ config GPIO_INTEL_PMIC
558 Say Y here to support GPIO via the SCU IPC interface 660 Say Y here to support GPIO via the SCU IPC interface
559 on Intel MID platforms. 661 on Intel MID platforms.
560 662
663config INTEL_MID_POWER_BUTTON
664 tristate "power button driver for Intel MID platforms"
665 depends on INTEL_SCU_IPC && INPUT
666 help
667 This driver handles the power button on the Intel MID platforms.
668
669 If unsure, say N.
670
671config INTEL_MFLD_THERMAL
672 tristate "Thermal driver for Intel Medfield platform"
673 depends on INTEL_SCU_IPC && THERMAL
674 help
675 Say Y here to enable thermal driver support for the Intel Medfield
676 platform.
677
561config RAR_REGISTER 678config RAR_REGISTER
562 bool "Restricted Access Region Register Driver" 679 bool "Restricted Access Region Register Driver"
563 depends on PCI && X86_MRST 680 depends on PCI && X86_MRST
@@ -590,4 +707,66 @@ config INTEL_IPS
590 functionality. If in doubt, say Y here; it will only load on 707 functionality. If in doubt, say Y here; it will only load on
591 supported platforms. 708 supported platforms.
592 709
710config IBM_RTL
711 tristate "Device driver to enable PRTL support"
712 depends on X86 && PCI
713 ---help---
714 Enable support for IBM Premium Real Time Mode (PRTM).
715 This module will allow you the enter and exit PRTM in the BIOS via
716 sysfs on platforms that support this feature. System in PRTM will
717 not receive CPU-generated SMIs for recoverable errors. Use of this
718 feature without proper support may void your hardware warranty.
719
720 If the proper BIOS support is found the driver will load and create
721 /sys/devices/system/ibm_rtl/. The "state" variable will indicate
722 whether or not the BIOS is in PRTM.
723 state = 0 (BIOS SMIs on)
724 state = 1 (BIOS SMIs off)
725
726config XO1_RFKILL
727 tristate "OLPC XO-1 software RF kill switch"
728 depends on OLPC
729 depends on RFKILL
730 ---help---
731 Support for enabling/disabling the WLAN interface on the OLPC XO-1
732 laptop.
733
734config XO15_EBOOK
735 tristate "OLPC XO-1.5 ebook switch"
736 depends on ACPI && INPUT
737 ---help---
738 Support for the ebook switch on the OLPC XO-1.5 laptop.
739
740 This switch is triggered as the screen is rotated and folded down to
741 convert the device into ebook form.
742
743config SAMSUNG_LAPTOP
744 tristate "Samsung Laptop driver"
745 depends on RFKILL && BACKLIGHT_CLASS_DEVICE && X86
746 ---help---
747 This module implements a driver for a wide range of different
748 Samsung laptops. It offers control over the different
749 function keys, wireless LED, LCD backlight level, and
750 sometimes provides a "performance_control" sysfs file to allow
751 the performance level of the laptop to be changed.
752
753 To compile this driver as a module, choose M here: the module
754 will be called samsung-laptop.
755
756config MXM_WMI
757 tristate "WMI support for MXM Laptop Graphics"
758 depends on ACPI_WMI
759 ---help---
760 MXM is a standard for laptop graphics cards, the WMI interface
761 is required for switchable nvidia graphics machines
762
763config INTEL_OAKTRAIL
764 tristate "Intel Oaktrail Platform Extras"
765 depends on ACPI
766 depends on RFKILL && BACKLIGHT_CLASS_DEVICE && ACPI
767 ---help---
768 Intel Oaktrail platform need this driver to provide interfaces to
769 enable/disable the Camera, WiFi, BT etc. devices. If in doubt, say Y
770 here; it will only load on supported platforms.
771
593endif # X86_PLATFORM_DEVICES 772endif # X86_PLATFORM_DEVICES
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index 85fb2b84f57e..afc1f832aa67 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -3,6 +3,8 @@
3# x86 Platform-Specific Drivers 3# x86 Platform-Specific Drivers
4# 4#
5obj-$(CONFIG_ASUS_LAPTOP) += asus-laptop.o 5obj-$(CONFIG_ASUS_LAPTOP) += asus-laptop.o
6obj-$(CONFIG_ASUS_WMI) += asus-wmi.o
7obj-$(CONFIG_ASUS_NB_WMI) += asus-nb-wmi.o
6obj-$(CONFIG_EEEPC_LAPTOP) += eeepc-laptop.o 8obj-$(CONFIG_EEEPC_LAPTOP) += eeepc-laptop.o
7obj-$(CONFIG_EEEPC_WMI) += eeepc-wmi.o 9obj-$(CONFIG_EEEPC_WMI) += eeepc-wmi.o
8obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o 10obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o
@@ -10,13 +12,16 @@ obj-$(CONFIG_ACPI_CMPC) += classmate-laptop.o
10obj-$(CONFIG_COMPAL_LAPTOP) += compal-laptop.o 12obj-$(CONFIG_COMPAL_LAPTOP) += compal-laptop.o
11obj-$(CONFIG_DELL_LAPTOP) += dell-laptop.o 13obj-$(CONFIG_DELL_LAPTOP) += dell-laptop.o
12obj-$(CONFIG_DELL_WMI) += dell-wmi.o 14obj-$(CONFIG_DELL_WMI) += dell-wmi.o
15obj-$(CONFIG_DELL_WMI_AIO) += dell-wmi-aio.o
13obj-$(CONFIG_ACER_WMI) += acer-wmi.o 16obj-$(CONFIG_ACER_WMI) += acer-wmi.o
14obj-$(CONFIG_ACERHDF) += acerhdf.o 17obj-$(CONFIG_ACERHDF) += acerhdf.o
18obj-$(CONFIG_HP_ACCEL) += hp_accel.o
15obj-$(CONFIG_HP_WMI) += hp-wmi.o 19obj-$(CONFIG_HP_WMI) += hp-wmi.o
16obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o 20obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o
17obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o 21obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o
18obj-$(CONFIG_IDEAPAD_ACPI) += ideapad_acpi.o 22obj-$(CONFIG_IDEAPAD_LAPTOP) += ideapad-laptop.o
19obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o 23obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o
24obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o
20obj-$(CONFIG_FUJITSU_LAPTOP) += fujitsu-laptop.o 25obj-$(CONFIG_FUJITSU_LAPTOP) += fujitsu-laptop.o
21obj-$(CONFIG_PANASONIC_LAPTOP) += panasonic-laptop.o 26obj-$(CONFIG_PANASONIC_LAPTOP) += panasonic-laptop.o
22obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o 27obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o
@@ -27,7 +32,15 @@ obj-$(CONFIG_TOPSTAR_LAPTOP) += topstar-laptop.o
27obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o 32obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o
28obj-$(CONFIG_TOSHIBA_BT_RFKILL) += toshiba_bluetooth.o 33obj-$(CONFIG_TOSHIBA_BT_RFKILL) += toshiba_bluetooth.o
29obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o 34obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o
35obj-$(CONFIG_INTEL_SCU_IPC_UTIL) += intel_scu_ipcutil.o
36obj-$(CONFIG_INTEL_MFLD_THERMAL) += intel_mid_thermal.o
30obj-$(CONFIG_RAR_REGISTER) += intel_rar_register.o 37obj-$(CONFIG_RAR_REGISTER) += intel_rar_register.o
31obj-$(CONFIG_INTEL_IPS) += intel_ips.o 38obj-$(CONFIG_INTEL_IPS) += intel_ips.o
32obj-$(CONFIG_GPIO_INTEL_PMIC) += intel_pmic_gpio.o 39obj-$(CONFIG_GPIO_INTEL_PMIC) += intel_pmic_gpio.o
33 40obj-$(CONFIG_XO1_RFKILL) += xo1-rfkill.o
41obj-$(CONFIG_XO15_EBOOK) += xo15-ebook.o
42obj-$(CONFIG_IBM_RTL) += ibm_rtl.o
43obj-$(CONFIG_SAMSUNG_LAPTOP) += samsung-laptop.o
44obj-$(CONFIG_MXM_WMI) += mxm-wmi.o
45obj-$(CONFIG_INTEL_MID_POWER_BUTTON) += intel_mid_powerbtn.o
46obj-$(CONFIG_INTEL_OAKTRAIL) += intel_oaktrail.o
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index 2badee2fdeed..e1c4938b301b 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -22,6 +22,8 @@
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */ 23 */
24 24
25#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
26
25#include <linux/kernel.h> 27#include <linux/kernel.h>
26#include <linux/module.h> 28#include <linux/module.h>
27#include <linux/init.h> 29#include <linux/init.h>
@@ -37,6 +39,8 @@
37#include <linux/workqueue.h> 39#include <linux/workqueue.h>
38#include <linux/debugfs.h> 40#include <linux/debugfs.h>
39#include <linux/slab.h> 41#include <linux/slab.h>
42#include <linux/input.h>
43#include <linux/input/sparse-keymap.h>
40 44
41#include <acpi/acpi_drivers.h> 45#include <acpi/acpi_drivers.h>
42 46
@@ -44,11 +48,6 @@ MODULE_AUTHOR("Carlos Corbacho");
44MODULE_DESCRIPTION("Acer Laptop WMI Extras Driver"); 48MODULE_DESCRIPTION("Acer Laptop WMI Extras Driver");
45MODULE_LICENSE("GPL"); 49MODULE_LICENSE("GPL");
46 50
47#define ACER_LOGPREFIX "acer-wmi: "
48#define ACER_ERR KERN_ERR ACER_LOGPREFIX
49#define ACER_NOTICE KERN_NOTICE ACER_LOGPREFIX
50#define ACER_INFO KERN_INFO ACER_LOGPREFIX
51
52/* 51/*
53 * Magic Number 52 * Magic Number
54 * Meaning is unknown - this number is required for writing to ACPI for AMW0 53 * Meaning is unknown - this number is required for writing to ACPI for AMW0
@@ -80,11 +79,98 @@ MODULE_LICENSE("GPL");
80 */ 79 */
81#define AMW0_GUID1 "67C3371D-95A3-4C37-BB61-DD47B491DAAB" 80#define AMW0_GUID1 "67C3371D-95A3-4C37-BB61-DD47B491DAAB"
82#define AMW0_GUID2 "431F16ED-0C2B-444C-B267-27DEB140CF9C" 81#define AMW0_GUID2 "431F16ED-0C2B-444C-B267-27DEB140CF9C"
83#define WMID_GUID1 "6AF4F258-B401-42fd-BE91-3D4AC2D7C0D3" 82#define WMID_GUID1 "6AF4F258-B401-42FD-BE91-3D4AC2D7C0D3"
84#define WMID_GUID2 "95764E09-FB56-4e83-B31A-37761F60994A" 83#define WMID_GUID2 "95764E09-FB56-4E83-B31A-37761F60994A"
84#define WMID_GUID3 "61EF69EA-865C-4BC3-A502-A0DEBA0CB531"
85
86/*
87 * Acer ACPI event GUIDs
88 */
89#define ACERWMID_EVENT_GUID "676AA15E-6A47-4D9F-A2CC-1E6D18D14026"
85 90
86MODULE_ALIAS("wmi:67C3371D-95A3-4C37-BB61-DD47B491DAAB"); 91MODULE_ALIAS("wmi:67C3371D-95A3-4C37-BB61-DD47B491DAAB");
87MODULE_ALIAS("wmi:6AF4F258-B401-42fd-BE91-3D4AC2D7C0D3"); 92MODULE_ALIAS("wmi:6AF4F258-B401-42FD-BE91-3D4AC2D7C0D3");
93MODULE_ALIAS("wmi:676AA15E-6A47-4D9F-A2CC-1E6D18D14026");
94
95enum acer_wmi_event_ids {
96 WMID_HOTKEY_EVENT = 0x1,
97};
98
99static const struct key_entry acer_wmi_keymap[] = {
100 {KE_KEY, 0x01, {KEY_WLAN} }, /* WiFi */
101 {KE_KEY, 0x03, {KEY_WLAN} }, /* WiFi */
102 {KE_KEY, 0x12, {KEY_BLUETOOTH} }, /* BT */
103 {KE_KEY, 0x21, {KEY_PROG1} }, /* Backup */
104 {KE_KEY, 0x22, {KEY_PROG2} }, /* Arcade */
105 {KE_KEY, 0x23, {KEY_PROG3} }, /* P_Key */
106 {KE_KEY, 0x24, {KEY_PROG4} }, /* Social networking_Key */
107 {KE_IGNORE, 0x41, {KEY_MUTE} },
108 {KE_IGNORE, 0x42, {KEY_PREVIOUSSONG} },
109 {KE_IGNORE, 0x43, {KEY_NEXTSONG} },
110 {KE_IGNORE, 0x44, {KEY_PLAYPAUSE} },
111 {KE_IGNORE, 0x45, {KEY_STOP} },
112 {KE_IGNORE, 0x48, {KEY_VOLUMEUP} },
113 {KE_IGNORE, 0x49, {KEY_VOLUMEDOWN} },
114 {KE_IGNORE, 0x61, {KEY_SWITCHVIDEOMODE} },
115 {KE_IGNORE, 0x62, {KEY_BRIGHTNESSUP} },
116 {KE_IGNORE, 0x63, {KEY_BRIGHTNESSDOWN} },
117 {KE_KEY, 0x64, {KEY_SWITCHVIDEOMODE} }, /* Display Switch */
118 {KE_IGNORE, 0x81, {KEY_SLEEP} },
119 {KE_KEY, 0x82, {KEY_TOUCHPAD_TOGGLE} }, /* Touch Pad On/Off */
120 {KE_IGNORE, 0x83, {KEY_TOUCHPAD_TOGGLE} },
121 {KE_END, 0}
122};
123
124static struct input_dev *acer_wmi_input_dev;
125
126struct event_return_value {
127 u8 function;
128 u8 key_num;
129 u16 device_state;
130 u32 reserved;
131} __attribute__((packed));
132
133/*
134 * GUID3 Get Device Status device flags
135 */
136#define ACER_WMID3_GDS_WIRELESS (1<<0) /* WiFi */
137#define ACER_WMID3_GDS_THREEG (1<<6) /* 3G */
138#define ACER_WMID3_GDS_WIMAX (1<<7) /* WiMAX */
139#define ACER_WMID3_GDS_BLUETOOTH (1<<11) /* BT */
140
141struct lm_input_params {
142 u8 function_num; /* Function Number */
143 u16 commun_devices; /* Communication type devices default status */
144 u16 devices; /* Other type devices default status */
145 u8 lm_status; /* Launch Manager Status */
146 u16 reserved;
147} __attribute__((packed));
148
149struct lm_return_value {
150 u8 error_code; /* Error Code */
151 u8 ec_return_value; /* EC Return Value */
152 u16 reserved;
153} __attribute__((packed));
154
155struct wmid3_gds_input_param { /* Get Device Status input parameter */
156 u8 function_num; /* Function Number */
157 u8 hotkey_number; /* Hotkey Number */
158 u16 devices; /* Get Device */
159} __attribute__((packed));
160
161struct wmid3_gds_return_value { /* Get Device Status return value*/
162 u8 error_code; /* Error Code */
163 u8 ec_return_value; /* EC Return Value */
164 u16 devices; /* Current Device Status */
165 u32 reserved;
166} __attribute__((packed));
167
168struct hotkey_function_type_aa {
169 u8 type;
170 u8 length;
171 u16 handle;
172 u16 commun_func_bitmap;
173} __attribute__((packed));
88 174
89/* 175/*
90 * Interface capability flags 176 * Interface capability flags
@@ -116,15 +202,19 @@ static int mailled = -1;
116static int brightness = -1; 202static int brightness = -1;
117static int threeg = -1; 203static int threeg = -1;
118static int force_series; 204static int force_series;
205static bool ec_raw_mode;
206static bool has_type_aa;
119 207
120module_param(mailled, int, 0444); 208module_param(mailled, int, 0444);
121module_param(brightness, int, 0444); 209module_param(brightness, int, 0444);
122module_param(threeg, int, 0444); 210module_param(threeg, int, 0444);
123module_param(force_series, int, 0444); 211module_param(force_series, int, 0444);
212module_param(ec_raw_mode, bool, 0444);
124MODULE_PARM_DESC(mailled, "Set initial state of Mail LED"); 213MODULE_PARM_DESC(mailled, "Set initial state of Mail LED");
125MODULE_PARM_DESC(brightness, "Set initial LCD backlight brightness"); 214MODULE_PARM_DESC(brightness, "Set initial LCD backlight brightness");
126MODULE_PARM_DESC(threeg, "Set initial state of 3G hardware"); 215MODULE_PARM_DESC(threeg, "Set initial state of 3G hardware");
127MODULE_PARM_DESC(force_series, "Force a different laptop series"); 216MODULE_PARM_DESC(force_series, "Force a different laptop series");
217MODULE_PARM_DESC(ec_raw_mode, "Enable EC raw mode");
128 218
129struct acer_data { 219struct acer_data {
130 int mailled; 220 int mailled;
@@ -140,6 +230,8 @@ struct acer_debug {
140 230
141static struct rfkill *wireless_rfkill; 231static struct rfkill *wireless_rfkill;
142static struct rfkill *bluetooth_rfkill; 232static struct rfkill *bluetooth_rfkill;
233static struct rfkill *threeg_rfkill;
234static bool rfkill_inited;
143 235
144/* Each low-level interface must define at least some of the following */ 236/* Each low-level interface must define at least some of the following */
145struct wmi_interface { 237struct wmi_interface {
@@ -659,8 +751,11 @@ WMI_execute_u32(u32 method_id, u32 in, u32 *out)
659 751
660 obj = (union acpi_object *) result.pointer; 752 obj = (union acpi_object *) result.pointer;
661 if (obj && obj->type == ACPI_TYPE_BUFFER && 753 if (obj && obj->type == ACPI_TYPE_BUFFER &&
662 obj->buffer.length == sizeof(u32)) { 754 (obj->buffer.length == sizeof(u32) ||
755 obj->buffer.length == sizeof(u64))) {
663 tmp = *((u32 *) obj->buffer.pointer); 756 tmp = *((u32 *) obj->buffer.pointer);
757 } else if (obj->type == ACPI_TYPE_INTEGER) {
758 tmp = (u32) obj->integer.value;
664 } else { 759 } else {
665 tmp = 0; 760 tmp = 0;
666 } 761 }
@@ -753,6 +848,28 @@ static acpi_status WMID_set_u32(u32 value, u32 cap, struct wmi_interface *iface)
753 return WMI_execute_u32(method_id, (u32)value, NULL); 848 return WMI_execute_u32(method_id, (u32)value, NULL);
754} 849}
755 850
851static void type_aa_dmi_decode(const struct dmi_header *header, void *dummy)
852{
853 struct hotkey_function_type_aa *type_aa;
854
855 /* We are looking for OEM-specific Type AAh */
856 if (header->type != 0xAA)
857 return;
858
859 has_type_aa = true;
860 type_aa = (struct hotkey_function_type_aa *) header;
861
862 pr_info("Function bitmap for Communication Button: 0x%x\n",
863 type_aa->commun_func_bitmap);
864
865 if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_WIRELESS)
866 interface->capability |= ACER_CAP_WIRELESS;
867 if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_THREEG)
868 interface->capability |= ACER_CAP_THREEG;
869 if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_BLUETOOTH)
870 interface->capability |= ACER_CAP_BLUETOOTH;
871}
872
756static acpi_status WMID_set_capabilities(void) 873static acpi_status WMID_set_capabilities(void)
757{ 874{
758 struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL}; 875 struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL};
@@ -766,23 +883,28 @@ static acpi_status WMID_set_capabilities(void)
766 883
767 obj = (union acpi_object *) out.pointer; 884 obj = (union acpi_object *) out.pointer;
768 if (obj && obj->type == ACPI_TYPE_BUFFER && 885 if (obj && obj->type == ACPI_TYPE_BUFFER &&
769 obj->buffer.length == sizeof(u32)) { 886 (obj->buffer.length == sizeof(u32) ||
887 obj->buffer.length == sizeof(u64))) {
770 devices = *((u32 *) obj->buffer.pointer); 888 devices = *((u32 *) obj->buffer.pointer);
889 } else if (obj->type == ACPI_TYPE_INTEGER) {
890 devices = (u32) obj->integer.value;
771 } else { 891 } else {
772 kfree(out.pointer); 892 kfree(out.pointer);
773 return AE_ERROR; 893 return AE_ERROR;
774 } 894 }
775 895
776 /* Not sure on the meaning of the relevant bits yet to detect these */ 896 dmi_walk(type_aa_dmi_decode, NULL);
777 interface->capability |= ACER_CAP_WIRELESS; 897 if (!has_type_aa) {
778 interface->capability |= ACER_CAP_THREEG; 898 interface->capability |= ACER_CAP_WIRELESS;
899 if (devices & 0x40)
900 interface->capability |= ACER_CAP_THREEG;
901 if (devices & 0x10)
902 interface->capability |= ACER_CAP_BLUETOOTH;
903 }
779 904
780 /* WMID always provides brightness methods */ 905 /* WMID always provides brightness methods */
781 interface->capability |= ACER_CAP_BRIGHTNESS; 906 interface->capability |= ACER_CAP_BRIGHTNESS;
782 907
783 if (devices & 0x10)
784 interface->capability |= ACER_CAP_BLUETOOTH;
785
786 if (!(devices & 0x20)) 908 if (!(devices & 0x20))
787 max_brightness = 0x9; 909 max_brightness = 0x9;
788 910
@@ -860,9 +982,12 @@ static void __init acer_commandline_init(void)
860 * These will all fail silently if the value given is invalid, or the 982 * These will all fail silently if the value given is invalid, or the
861 * capability isn't available on the given interface 983 * capability isn't available on the given interface
862 */ 984 */
863 set_u32(mailled, ACER_CAP_MAILLED); 985 if (mailled >= 0)
864 set_u32(threeg, ACER_CAP_THREEG); 986 set_u32(mailled, ACER_CAP_MAILLED);
865 set_u32(brightness, ACER_CAP_BRIGHTNESS); 987 if (!has_type_aa && threeg >= 0)
988 set_u32(threeg, ACER_CAP_THREEG);
989 if (brightness >= 0)
990 set_u32(brightness, ACER_CAP_BRIGHTNESS);
866} 991}
867 992
868/* 993/*
@@ -886,6 +1011,7 @@ static int __devinit acer_led_init(struct device *dev)
886 1011
887static void acer_led_exit(void) 1012static void acer_led_exit(void)
888{ 1013{
1014 set_u32(LED_OFF, ACER_CAP_MAILLED);
889 led_classdev_unregister(&mail_led); 1015 led_classdev_unregister(&mail_led);
890} 1016}
891 1017
@@ -915,7 +1041,7 @@ static int update_bl_status(struct backlight_device *bd)
915 return 0; 1041 return 0;
916} 1042}
917 1043
918static struct backlight_ops acer_bl_ops = { 1044static const struct backlight_ops acer_bl_ops = {
919 .get_brightness = read_brightness, 1045 .get_brightness = read_brightness,
920 .update_status = update_bl_status, 1046 .update_status = update_bl_status,
921}; 1047};
@@ -926,11 +1052,12 @@ static int __devinit acer_backlight_init(struct device *dev)
926 struct backlight_device *bd; 1052 struct backlight_device *bd;
927 1053
928 memset(&props, 0, sizeof(struct backlight_properties)); 1054 memset(&props, 0, sizeof(struct backlight_properties));
1055 props.type = BACKLIGHT_PLATFORM;
929 props.max_brightness = max_brightness; 1056 props.max_brightness = max_brightness;
930 bd = backlight_device_register("acer-wmi", dev, NULL, &acer_bl_ops, 1057 bd = backlight_device_register("acer-wmi", dev, NULL, &acer_bl_ops,
931 &props); 1058 &props);
932 if (IS_ERR(bd)) { 1059 if (IS_ERR(bd)) {
933 printk(ACER_ERR "Could not register Acer backlight device\n"); 1060 pr_err("Could not register Acer backlight device\n");
934 acer_backlight_device = NULL; 1061 acer_backlight_device = NULL;
935 return PTR_ERR(bd); 1062 return PTR_ERR(bd);
936 } 1063 }
@@ -948,6 +1075,186 @@ static void acer_backlight_exit(void)
948 backlight_device_unregister(acer_backlight_device); 1075 backlight_device_unregister(acer_backlight_device);
949} 1076}
950 1077
1078static acpi_status wmid3_get_device_status(u32 *value, u16 device)
1079{
1080 struct wmid3_gds_return_value return_value;
1081 acpi_status status;
1082 union acpi_object *obj;
1083 struct wmid3_gds_input_param params = {
1084 .function_num = 0x1,
1085 .hotkey_number = 0x01,
1086 .devices = device,
1087 };
1088 struct acpi_buffer input = {
1089 sizeof(struct wmid3_gds_input_param),
1090 &params
1091 };
1092 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
1093
1094 status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
1095 if (ACPI_FAILURE(status))
1096 return status;
1097
1098 obj = output.pointer;
1099
1100 if (!obj)
1101 return AE_ERROR;
1102 else if (obj->type != ACPI_TYPE_BUFFER) {
1103 kfree(obj);
1104 return AE_ERROR;
1105 }
1106 if (obj->buffer.length != 8) {
1107 pr_warn("Unknown buffer length %d\n", obj->buffer.length);
1108 kfree(obj);
1109 return AE_ERROR;
1110 }
1111
1112 return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
1113 kfree(obj);
1114
1115 if (return_value.error_code || return_value.ec_return_value)
1116 pr_warn("Get Device Status failed: 0x%x - 0x%x\n",
1117 return_value.error_code,
1118 return_value.ec_return_value);
1119 else
1120 *value = !!(return_value.devices & device);
1121
1122 return status;
1123}
1124
1125static acpi_status get_device_status(u32 *value, u32 cap)
1126{
1127 if (wmi_has_guid(WMID_GUID3)) {
1128 u16 device;
1129
1130 switch (cap) {
1131 case ACER_CAP_WIRELESS:
1132 device = ACER_WMID3_GDS_WIRELESS;
1133 break;
1134 case ACER_CAP_BLUETOOTH:
1135 device = ACER_WMID3_GDS_BLUETOOTH;
1136 break;
1137 case ACER_CAP_THREEG:
1138 device = ACER_WMID3_GDS_THREEG;
1139 break;
1140 default:
1141 return AE_ERROR;
1142 }
1143 return wmid3_get_device_status(value, device);
1144
1145 } else {
1146 return get_u32(value, cap);
1147 }
1148}
1149
1150static acpi_status wmid3_set_device_status(u32 value, u16 device)
1151{
1152 struct wmid3_gds_return_value return_value;
1153 acpi_status status;
1154 union acpi_object *obj;
1155 u16 devices;
1156 struct wmid3_gds_input_param params = {
1157 .function_num = 0x1,
1158 .hotkey_number = 0x01,
1159 .devices = ACER_WMID3_GDS_WIRELESS |
1160 ACER_WMID3_GDS_THREEG |
1161 ACER_WMID3_GDS_WIMAX |
1162 ACER_WMID3_GDS_BLUETOOTH,
1163 };
1164 struct acpi_buffer input = {
1165 sizeof(struct wmid3_gds_input_param),
1166 &params
1167 };
1168 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
1169 struct acpi_buffer output2 = { ACPI_ALLOCATE_BUFFER, NULL };
1170
1171 status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
1172 if (ACPI_FAILURE(status))
1173 return status;
1174
1175 obj = output.pointer;
1176
1177 if (!obj)
1178 return AE_ERROR;
1179 else if (obj->type != ACPI_TYPE_BUFFER) {
1180 kfree(obj);
1181 return AE_ERROR;
1182 }
1183 if (obj->buffer.length != 8) {
1184 pr_warning("Unknown buffer length %d\n", obj->buffer.length);
1185 kfree(obj);
1186 return AE_ERROR;
1187 }
1188
1189 return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
1190 kfree(obj);
1191
1192 if (return_value.error_code || return_value.ec_return_value) {
1193 pr_warning("Get Current Device Status failed: "
1194 "0x%x - 0x%x\n", return_value.error_code,
1195 return_value.ec_return_value);
1196 return status;
1197 }
1198
1199 devices = return_value.devices;
1200 params.function_num = 0x2;
1201 params.hotkey_number = 0x01;
1202 params.devices = (value) ? (devices | device) : (devices & ~device);
1203
1204 status = wmi_evaluate_method(WMID_GUID3, 0, 0x1, &input, &output2);
1205 if (ACPI_FAILURE(status))
1206 return status;
1207
1208 obj = output2.pointer;
1209
1210 if (!obj)
1211 return AE_ERROR;
1212 else if (obj->type != ACPI_TYPE_BUFFER) {
1213 kfree(obj);
1214 return AE_ERROR;
1215 }
1216 if (obj->buffer.length != 4) {
1217 pr_warning("Unknown buffer length %d\n", obj->buffer.length);
1218 kfree(obj);
1219 return AE_ERROR;
1220 }
1221
1222 return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
1223 kfree(obj);
1224
1225 if (return_value.error_code || return_value.ec_return_value)
1226 pr_warning("Set Device Status failed: "
1227 "0x%x - 0x%x\n", return_value.error_code,
1228 return_value.ec_return_value);
1229
1230 return status;
1231}
1232
1233static acpi_status set_device_status(u32 value, u32 cap)
1234{
1235 if (wmi_has_guid(WMID_GUID3)) {
1236 u16 device;
1237
1238 switch (cap) {
1239 case ACER_CAP_WIRELESS:
1240 device = ACER_WMID3_GDS_WIRELESS;
1241 break;
1242 case ACER_CAP_BLUETOOTH:
1243 device = ACER_WMID3_GDS_BLUETOOTH;
1244 break;
1245 case ACER_CAP_THREEG:
1246 device = ACER_WMID3_GDS_THREEG;
1247 break;
1248 default:
1249 return AE_ERROR;
1250 }
1251 return wmid3_set_device_status(value, device);
1252
1253 } else {
1254 return set_u32(value, cap);
1255 }
1256}
1257
951/* 1258/*
952 * Rfkill devices 1259 * Rfkill devices
953 */ 1260 */
@@ -968,6 +1275,13 @@ static void acer_rfkill_update(struct work_struct *ignored)
968 rfkill_set_sw_state(bluetooth_rfkill, !state); 1275 rfkill_set_sw_state(bluetooth_rfkill, !state);
969 } 1276 }
970 1277
1278 if (has_cap(ACER_CAP_THREEG) && wmi_has_guid(WMID_GUID3)) {
1279 status = wmid3_get_device_status(&state,
1280 ACER_WMID3_GDS_THREEG);
1281 if (ACPI_SUCCESS(status))
1282 rfkill_set_sw_state(threeg_rfkill, !state);
1283 }
1284
971 schedule_delayed_work(&acer_rfkill_work, round_jiffies_relative(HZ)); 1285 schedule_delayed_work(&acer_rfkill_work, round_jiffies_relative(HZ));
972} 1286}
973 1287
@@ -975,9 +1289,13 @@ static int acer_rfkill_set(void *data, bool blocked)
975{ 1289{
976 acpi_status status; 1290 acpi_status status;
977 u32 cap = (unsigned long)data; 1291 u32 cap = (unsigned long)data;
978 status = set_u32(!blocked, cap); 1292
979 if (ACPI_FAILURE(status)) 1293 if (rfkill_inited) {
980 return -ENODEV; 1294 status = set_device_status(!blocked, cap);
1295 if (ACPI_FAILURE(status))
1296 return -ENODEV;
1297 }
1298
981 return 0; 1299 return 0;
982} 1300}
983 1301
@@ -991,6 +1309,8 @@ static struct rfkill *acer_rfkill_register(struct device *dev,
991{ 1309{
992 int err; 1310 int err;
993 struct rfkill *rfkill_dev; 1311 struct rfkill *rfkill_dev;
1312 u32 state;
1313 acpi_status status;
994 1314
995 rfkill_dev = rfkill_alloc(name, dev, type, 1315 rfkill_dev = rfkill_alloc(name, dev, type,
996 &acer_rfkill_ops, 1316 &acer_rfkill_ops,
@@ -998,11 +1318,17 @@ static struct rfkill *acer_rfkill_register(struct device *dev,
998 if (!rfkill_dev) 1318 if (!rfkill_dev)
999 return ERR_PTR(-ENOMEM); 1319 return ERR_PTR(-ENOMEM);
1000 1320
1321 status = get_device_status(&state, cap);
1322
1001 err = rfkill_register(rfkill_dev); 1323 err = rfkill_register(rfkill_dev);
1002 if (err) { 1324 if (err) {
1003 rfkill_destroy(rfkill_dev); 1325 rfkill_destroy(rfkill_dev);
1004 return ERR_PTR(err); 1326 return ERR_PTR(err);
1005 } 1327 }
1328
1329 if (ACPI_SUCCESS(status))
1330 rfkill_set_sw_state(rfkill_dev, !state);
1331
1006 return rfkill_dev; 1332 return rfkill_dev;
1007} 1333}
1008 1334
@@ -1024,14 +1350,32 @@ static int acer_rfkill_init(struct device *dev)
1024 } 1350 }
1025 } 1351 }
1026 1352
1027 schedule_delayed_work(&acer_rfkill_work, round_jiffies_relative(HZ)); 1353 if (has_cap(ACER_CAP_THREEG)) {
1354 threeg_rfkill = acer_rfkill_register(dev,
1355 RFKILL_TYPE_WWAN, "acer-threeg",
1356 ACER_CAP_THREEG);
1357 if (IS_ERR(threeg_rfkill)) {
1358 rfkill_unregister(wireless_rfkill);
1359 rfkill_destroy(wireless_rfkill);
1360 rfkill_unregister(bluetooth_rfkill);
1361 rfkill_destroy(bluetooth_rfkill);
1362 return PTR_ERR(threeg_rfkill);
1363 }
1364 }
1365
1366 rfkill_inited = true;
1367
1368 if (ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID))
1369 schedule_delayed_work(&acer_rfkill_work,
1370 round_jiffies_relative(HZ));
1028 1371
1029 return 0; 1372 return 0;
1030} 1373}
1031 1374
1032static void acer_rfkill_exit(void) 1375static void acer_rfkill_exit(void)
1033{ 1376{
1034 cancel_delayed_work_sync(&acer_rfkill_work); 1377 if (ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID))
1378 cancel_delayed_work_sync(&acer_rfkill_work);
1035 1379
1036 rfkill_unregister(wireless_rfkill); 1380 rfkill_unregister(wireless_rfkill);
1037 rfkill_destroy(wireless_rfkill); 1381 rfkill_destroy(wireless_rfkill);
@@ -1040,6 +1384,11 @@ static void acer_rfkill_exit(void)
1040 rfkill_unregister(bluetooth_rfkill); 1384 rfkill_unregister(bluetooth_rfkill);
1041 rfkill_destroy(bluetooth_rfkill); 1385 rfkill_destroy(bluetooth_rfkill);
1042 } 1386 }
1387
1388 if (has_cap(ACER_CAP_THREEG)) {
1389 rfkill_unregister(threeg_rfkill);
1390 rfkill_destroy(threeg_rfkill);
1391 }
1043 return; 1392 return;
1044} 1393}
1045 1394
@@ -1050,7 +1399,12 @@ static ssize_t show_bool_threeg(struct device *dev,
1050 struct device_attribute *attr, char *buf) 1399 struct device_attribute *attr, char *buf)
1051{ 1400{
1052 u32 result; \ 1401 u32 result; \
1053 acpi_status status = get_u32(&result, ACER_CAP_THREEG); 1402 acpi_status status;
1403 if (wmi_has_guid(WMID_GUID3))
1404 status = wmid3_get_device_status(&result,
1405 ACER_WMID3_GDS_THREEG);
1406 else
1407 status = get_u32(&result, ACER_CAP_THREEG);
1054 if (ACPI_SUCCESS(status)) 1408 if (ACPI_SUCCESS(status))
1055 return sprintf(buf, "%u\n", result); 1409 return sprintf(buf, "%u\n", result);
1056 return sprintf(buf, "Read error\n"); 1410 return sprintf(buf, "Read error\n");
@@ -1065,7 +1419,7 @@ static ssize_t set_bool_threeg(struct device *dev,
1065 return -EINVAL; 1419 return -EINVAL;
1066 return count; 1420 return count;
1067} 1421}
1068static DEVICE_ATTR(threeg, S_IWUGO | S_IRUGO | S_IWUSR, show_bool_threeg, 1422static DEVICE_ATTR(threeg, S_IRUGO | S_IWUSR, show_bool_threeg,
1069 set_bool_threeg); 1423 set_bool_threeg);
1070 1424
1071static ssize_t show_interface(struct device *dev, struct device_attribute *attr, 1425static ssize_t show_interface(struct device *dev, struct device_attribute *attr,
@@ -1085,6 +1439,199 @@ static ssize_t show_interface(struct device *dev, struct device_attribute *attr,
1085 1439
1086static DEVICE_ATTR(interface, S_IRUGO, show_interface, NULL); 1440static DEVICE_ATTR(interface, S_IRUGO, show_interface, NULL);
1087 1441
1442static void acer_wmi_notify(u32 value, void *context)
1443{
1444 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
1445 union acpi_object *obj;
1446 struct event_return_value return_value;
1447 acpi_status status;
1448 u16 device_state;
1449 const struct key_entry *key;
1450
1451 status = wmi_get_event_data(value, &response);
1452 if (status != AE_OK) {
1453 pr_warn("bad event status 0x%x\n", status);
1454 return;
1455 }
1456
1457 obj = (union acpi_object *)response.pointer;
1458
1459 if (!obj)
1460 return;
1461 if (obj->type != ACPI_TYPE_BUFFER) {
1462 pr_warn("Unknown response received %d\n", obj->type);
1463 kfree(obj);
1464 return;
1465 }
1466 if (obj->buffer.length != 8) {
1467 pr_warn("Unknown buffer length %d\n", obj->buffer.length);
1468 kfree(obj);
1469 return;
1470 }
1471
1472 return_value = *((struct event_return_value *)obj->buffer.pointer);
1473 kfree(obj);
1474
1475 switch (return_value.function) {
1476 case WMID_HOTKEY_EVENT:
1477 device_state = return_value.device_state;
1478 pr_debug("device state: 0x%x\n", device_state);
1479
1480 key = sparse_keymap_entry_from_scancode(acer_wmi_input_dev,
1481 return_value.key_num);
1482 if (!key) {
1483 pr_warn("Unknown key number - 0x%x\n",
1484 return_value.key_num);
1485 } else {
1486 switch (key->keycode) {
1487 case KEY_WLAN:
1488 case KEY_BLUETOOTH:
1489 if (has_cap(ACER_CAP_WIRELESS))
1490 rfkill_set_sw_state(wireless_rfkill,
1491 !(device_state & ACER_WMID3_GDS_WIRELESS));
1492 if (has_cap(ACER_CAP_THREEG))
1493 rfkill_set_sw_state(threeg_rfkill,
1494 !(device_state & ACER_WMID3_GDS_THREEG));
1495 if (has_cap(ACER_CAP_BLUETOOTH))
1496 rfkill_set_sw_state(bluetooth_rfkill,
1497 !(device_state & ACER_WMID3_GDS_BLUETOOTH));
1498 break;
1499 }
1500 sparse_keymap_report_entry(acer_wmi_input_dev, key,
1501 1, true);
1502 }
1503 break;
1504 default:
1505 pr_warn("Unknown function number - %d - %d\n",
1506 return_value.function, return_value.key_num);
1507 break;
1508 }
1509}
1510
1511static acpi_status
1512wmid3_set_lm_mode(struct lm_input_params *params,
1513 struct lm_return_value *return_value)
1514{
1515 acpi_status status;
1516 union acpi_object *obj;
1517
1518 struct acpi_buffer input = { sizeof(struct lm_input_params), params };
1519 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
1520
1521 status = wmi_evaluate_method(WMID_GUID3, 0, 0x1, &input, &output);
1522 if (ACPI_FAILURE(status))
1523 return status;
1524
1525 obj = output.pointer;
1526
1527 if (!obj)
1528 return AE_ERROR;
1529 else if (obj->type != ACPI_TYPE_BUFFER) {
1530 kfree(obj);
1531 return AE_ERROR;
1532 }
1533 if (obj->buffer.length != 4) {
1534 pr_warn("Unknown buffer length %d\n", obj->buffer.length);
1535 kfree(obj);
1536 return AE_ERROR;
1537 }
1538
1539 *return_value = *((struct lm_return_value *)obj->buffer.pointer);
1540 kfree(obj);
1541
1542 return status;
1543}
1544
1545static int acer_wmi_enable_ec_raw(void)
1546{
1547 struct lm_return_value return_value;
1548 acpi_status status;
1549 struct lm_input_params params = {
1550 .function_num = 0x1,
1551 .commun_devices = 0xFFFF,
1552 .devices = 0xFFFF,
1553 .lm_status = 0x00, /* Launch Manager Deactive */
1554 };
1555
1556 status = wmid3_set_lm_mode(&params, &return_value);
1557
1558 if (return_value.error_code || return_value.ec_return_value)
1559 pr_warn("Enabling EC raw mode failed: 0x%x - 0x%x\n",
1560 return_value.error_code,
1561 return_value.ec_return_value);
1562 else
1563 pr_info("Enabled EC raw mode\n");
1564
1565 return status;
1566}
1567
1568static int acer_wmi_enable_lm(void)
1569{
1570 struct lm_return_value return_value;
1571 acpi_status status;
1572 struct lm_input_params params = {
1573 .function_num = 0x1,
1574 .commun_devices = 0xFFFF,
1575 .devices = 0xFFFF,
1576 .lm_status = 0x01, /* Launch Manager Active */
1577 };
1578
1579 status = wmid3_set_lm_mode(&params, &return_value);
1580
1581 if (return_value.error_code || return_value.ec_return_value)
1582 pr_warn("Enabling Launch Manager failed: 0x%x - 0x%x\n",
1583 return_value.error_code,
1584 return_value.ec_return_value);
1585
1586 return status;
1587}
1588
1589static int __init acer_wmi_input_setup(void)
1590{
1591 acpi_status status;
1592 int err;
1593
1594 acer_wmi_input_dev = input_allocate_device();
1595 if (!acer_wmi_input_dev)
1596 return -ENOMEM;
1597
1598 acer_wmi_input_dev->name = "Acer WMI hotkeys";
1599 acer_wmi_input_dev->phys = "wmi/input0";
1600 acer_wmi_input_dev->id.bustype = BUS_HOST;
1601
1602 err = sparse_keymap_setup(acer_wmi_input_dev, acer_wmi_keymap, NULL);
1603 if (err)
1604 goto err_free_dev;
1605
1606 status = wmi_install_notify_handler(ACERWMID_EVENT_GUID,
1607 acer_wmi_notify, NULL);
1608 if (ACPI_FAILURE(status)) {
1609 err = -EIO;
1610 goto err_free_keymap;
1611 }
1612
1613 err = input_register_device(acer_wmi_input_dev);
1614 if (err)
1615 goto err_uninstall_notifier;
1616
1617 return 0;
1618
1619err_uninstall_notifier:
1620 wmi_remove_notify_handler(ACERWMID_EVENT_GUID);
1621err_free_keymap:
1622 sparse_keymap_free(acer_wmi_input_dev);
1623err_free_dev:
1624 input_free_device(acer_wmi_input_dev);
1625 return err;
1626}
1627
1628static void acer_wmi_input_destroy(void)
1629{
1630 wmi_remove_notify_handler(ACERWMID_EVENT_GUID);
1631 sparse_keymap_free(acer_wmi_input_dev);
1632 input_unregister_device(acer_wmi_input_dev);
1633}
1634
1088/* 1635/*
1089 * debugfs functions 1636 * debugfs functions
1090 */ 1637 */
@@ -1101,8 +1648,11 @@ static u32 get_wmid_devices(void)
1101 1648
1102 obj = (union acpi_object *) out.pointer; 1649 obj = (union acpi_object *) out.pointer;
1103 if (obj && obj->type == ACPI_TYPE_BUFFER && 1650 if (obj && obj->type == ACPI_TYPE_BUFFER &&
1104 obj->buffer.length == sizeof(u32)) { 1651 (obj->buffer.length == sizeof(u32) ||
1652 obj->buffer.length == sizeof(u64))) {
1105 devices = *((u32 *) obj->buffer.pointer); 1653 devices = *((u32 *) obj->buffer.pointer);
1654 } else if (obj->type == ACPI_TYPE_INTEGER) {
1655 devices = (u32) obj->integer.value;
1106 } 1656 }
1107 1657
1108 kfree(out.pointer); 1658 kfree(out.pointer);
@@ -1166,6 +1716,7 @@ pm_message_t state)
1166 1716
1167 if (has_cap(ACER_CAP_MAILLED)) { 1717 if (has_cap(ACER_CAP_MAILLED)) {
1168 get_u32(&value, ACER_CAP_MAILLED); 1718 get_u32(&value, ACER_CAP_MAILLED);
1719 set_u32(LED_OFF, ACER_CAP_MAILLED);
1169 data->mailled = value; 1720 data->mailled = value;
1170 } 1721 }
1171 1722
@@ -1193,6 +1744,17 @@ static int acer_platform_resume(struct platform_device *device)
1193 return 0; 1744 return 0;
1194} 1745}
1195 1746
1747static void acer_platform_shutdown(struct platform_device *device)
1748{
1749 struct acer_data *data = &interface->data;
1750
1751 if (!data)
1752 return;
1753
1754 if (has_cap(ACER_CAP_MAILLED))
1755 set_u32(LED_OFF, ACER_CAP_MAILLED);
1756}
1757
1196static struct platform_driver acer_platform_driver = { 1758static struct platform_driver acer_platform_driver = {
1197 .driver = { 1759 .driver = {
1198 .name = "acer-wmi", 1760 .name = "acer-wmi",
@@ -1202,6 +1764,7 @@ static struct platform_driver acer_platform_driver = {
1202 .remove = acer_platform_remove, 1764 .remove = acer_platform_remove,
1203 .suspend = acer_platform_suspend, 1765 .suspend = acer_platform_suspend,
1204 .resume = acer_platform_resume, 1766 .resume = acer_platform_resume,
1767 .shutdown = acer_platform_shutdown,
1205}; 1768};
1206 1769
1207static struct platform_device *acer_platform_device; 1770static struct platform_device *acer_platform_device;
@@ -1249,7 +1812,7 @@ static int create_debugfs(void)
1249{ 1812{
1250 interface->debug.root = debugfs_create_dir("acer-wmi", NULL); 1813 interface->debug.root = debugfs_create_dir("acer-wmi", NULL);
1251 if (!interface->debug.root) { 1814 if (!interface->debug.root) {
1252 printk(ACER_ERR "Failed to create debugfs directory"); 1815 pr_err("Failed to create debugfs directory");
1253 return -ENOMEM; 1816 return -ENOMEM;
1254 } 1817 }
1255 1818
@@ -1270,11 +1833,10 @@ static int __init acer_wmi_init(void)
1270{ 1833{
1271 int err; 1834 int err;
1272 1835
1273 printk(ACER_INFO "Acer Laptop ACPI-WMI Extras\n"); 1836 pr_info("Acer Laptop ACPI-WMI Extras\n");
1274 1837
1275 if (dmi_check_system(acer_blacklist)) { 1838 if (dmi_check_system(acer_blacklist)) {
1276 printk(ACER_INFO "Blacklisted hardware detected - " 1839 pr_info("Blacklisted hardware detected - not loading\n");
1277 "not loading\n");
1278 return -ENODEV; 1840 return -ENODEV;
1279 } 1841 }
1280 1842
@@ -1291,12 +1853,11 @@ static int __init acer_wmi_init(void)
1291 1853
1292 if (wmi_has_guid(WMID_GUID2) && interface) { 1854 if (wmi_has_guid(WMID_GUID2) && interface) {
1293 if (ACPI_FAILURE(WMID_set_capabilities())) { 1855 if (ACPI_FAILURE(WMID_set_capabilities())) {
1294 printk(ACER_ERR "Unable to detect available WMID " 1856 pr_err("Unable to detect available WMID devices\n");
1295 "devices\n");
1296 return -ENODEV; 1857 return -ENODEV;
1297 } 1858 }
1298 } else if (!wmi_has_guid(WMID_GUID2) && interface) { 1859 } else if (!wmi_has_guid(WMID_GUID2) && interface) {
1299 printk(ACER_ERR "No WMID device detection method found\n"); 1860 pr_err("No WMID device detection method found\n");
1300 return -ENODEV; 1861 return -ENODEV;
1301 } 1862 }
1302 1863
@@ -1304,8 +1865,7 @@ static int __init acer_wmi_init(void)
1304 interface = &AMW0_interface; 1865 interface = &AMW0_interface;
1305 1866
1306 if (ACPI_FAILURE(AMW0_set_capabilities())) { 1867 if (ACPI_FAILURE(AMW0_set_capabilities())) {
1307 printk(ACER_ERR "Unable to detect available AMW0 " 1868 pr_err("Unable to detect available AMW0 devices\n");
1308 "devices\n");
1309 return -ENODEV; 1869 return -ENODEV;
1310 } 1870 }
1311 } 1871 }
@@ -1314,8 +1874,7 @@ static int __init acer_wmi_init(void)
1314 AMW0_find_mailled(); 1874 AMW0_find_mailled();
1315 1875
1316 if (!interface) { 1876 if (!interface) {
1317 printk(ACER_ERR "No or unsupported WMI interface, unable to " 1877 pr_err("No or unsupported WMI interface, unable to load\n");
1318 "load\n");
1319 return -ENODEV; 1878 return -ENODEV;
1320 } 1879 }
1321 1880
@@ -1323,13 +1882,33 @@ static int __init acer_wmi_init(void)
1323 1882
1324 if (acpi_video_backlight_support() && has_cap(ACER_CAP_BRIGHTNESS)) { 1883 if (acpi_video_backlight_support() && has_cap(ACER_CAP_BRIGHTNESS)) {
1325 interface->capability &= ~ACER_CAP_BRIGHTNESS; 1884 interface->capability &= ~ACER_CAP_BRIGHTNESS;
1326 printk(ACER_INFO "Brightness must be controlled by " 1885 pr_info("Brightness must be controlled by "
1327 "generic video driver\n"); 1886 "generic video driver\n");
1328 } 1887 }
1329 1888
1889 if (wmi_has_guid(WMID_GUID3)) {
1890 if (ec_raw_mode) {
1891 if (ACPI_FAILURE(acer_wmi_enable_ec_raw())) {
1892 pr_err("Cannot enable EC raw mode\n");
1893 return -ENODEV;
1894 }
1895 } else if (ACPI_FAILURE(acer_wmi_enable_lm())) {
1896 pr_err("Cannot enable Launch Manager mode\n");
1897 return -ENODEV;
1898 }
1899 } else if (ec_raw_mode) {
1900 pr_info("No WMID EC raw mode enable method\n");
1901 }
1902
1903 if (wmi_has_guid(ACERWMID_EVENT_GUID)) {
1904 err = acer_wmi_input_setup();
1905 if (err)
1906 return err;
1907 }
1908
1330 err = platform_driver_register(&acer_platform_driver); 1909 err = platform_driver_register(&acer_platform_driver);
1331 if (err) { 1910 if (err) {
1332 printk(ACER_ERR "Unable to register platform driver.\n"); 1911 pr_err("Unable to register platform driver.\n");
1333 goto error_platform_register; 1912 goto error_platform_register;
1334 } 1913 }
1335 1914
@@ -1368,17 +1947,23 @@ error_device_add:
1368error_device_alloc: 1947error_device_alloc:
1369 platform_driver_unregister(&acer_platform_driver); 1948 platform_driver_unregister(&acer_platform_driver);
1370error_platform_register: 1949error_platform_register:
1950 if (wmi_has_guid(ACERWMID_EVENT_GUID))
1951 acer_wmi_input_destroy();
1952
1371 return err; 1953 return err;
1372} 1954}
1373 1955
1374static void __exit acer_wmi_exit(void) 1956static void __exit acer_wmi_exit(void)
1375{ 1957{
1958 if (wmi_has_guid(ACERWMID_EVENT_GUID))
1959 acer_wmi_input_destroy();
1960
1376 remove_sysfs(acer_platform_device); 1961 remove_sysfs(acer_platform_device);
1377 remove_debugfs(); 1962 remove_debugfs();
1378 platform_device_unregister(acer_platform_device); 1963 platform_device_unregister(acer_platform_device);
1379 platform_driver_unregister(&acer_platform_driver); 1964 platform_driver_unregister(&acer_platform_driver);
1380 1965
1381 printk(ACER_INFO "Acer Laptop WMI Extras unloaded\n"); 1966 pr_info("Acer Laptop WMI Extras unloaded\n");
1382 return; 1967 return;
1383} 1968}
1384 1969
diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c
index 60f9cfcac93f..fca3489218b7 100644
--- a/drivers/platform/x86/acerhdf.c
+++ b/drivers/platform/x86/acerhdf.c
@@ -35,10 +35,8 @@
35 35
36#include <linux/kernel.h> 36#include <linux/kernel.h>
37#include <linux/module.h> 37#include <linux/module.h>
38#include <linux/fs.h>
39#include <linux/dmi.h> 38#include <linux/dmi.h>
40#include <acpi/acpi_drivers.h> 39#include <linux/acpi.h>
41#include <linux/sched.h>
42#include <linux/thermal.h> 40#include <linux/thermal.h>
43#include <linux/platform_device.h> 41#include <linux/platform_device.h>
44 42
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index b756e07d41b4..d65df92e2acc 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -29,7 +29,7 @@
29 * John Belmonte - ACPI code for Toshiba laptop was a good starting point. 29 * John Belmonte - ACPI code for Toshiba laptop was a good starting point.
30 * Eric Burghard - LED display support for W1N 30 * Eric Burghard - LED display support for W1N
31 * Josh Green - Light Sens support 31 * Josh Green - Light Sens support
32 * Thomas Tuttle - His first patch for led support was very helpfull 32 * Thomas Tuttle - His first patch for led support was very helpful
33 * Sam Lin - GPS support 33 * Sam Lin - GPS support
34 */ 34 */
35 35
@@ -50,6 +50,7 @@
50#include <linux/input/sparse-keymap.h> 50#include <linux/input/sparse-keymap.h>
51#include <linux/rfkill.h> 51#include <linux/rfkill.h>
52#include <linux/slab.h> 52#include <linux/slab.h>
53#include <linux/dmi.h>
53#include <acpi/acpi_drivers.h> 54#include <acpi/acpi_drivers.h>
54#include <acpi/acpi_bus.h> 55#include <acpi/acpi_bus.h>
55 56
@@ -81,6 +82,8 @@ MODULE_PARM_DESC(wapf, "WAPF value");
81 82
82static int wlan_status = 1; 83static int wlan_status = 1;
83static int bluetooth_status = 1; 84static int bluetooth_status = 1;
85static int wimax_status = -1;
86static int wwan_status = -1;
84 87
85module_param(wlan_status, int, 0444); 88module_param(wlan_status, int, 0444);
86MODULE_PARM_DESC(wlan_status, "Set the wireless status on boot " 89MODULE_PARM_DESC(wlan_status, "Set the wireless status on boot "
@@ -92,6 +95,16 @@ MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot "
92 "(0 = disabled, 1 = enabled, -1 = don't do anything). " 95 "(0 = disabled, 1 = enabled, -1 = don't do anything). "
93 "default is 1"); 96 "default is 1");
94 97
98module_param(wimax_status, int, 0444);
99MODULE_PARM_DESC(wimax_status, "Set the wireless status on boot "
100 "(0 = disabled, 1 = enabled, -1 = don't do anything). "
101 "default is 1");
102
103module_param(wwan_status, int, 0444);
104MODULE_PARM_DESC(wwan_status, "Set the wireless status on boot "
105 "(0 = disabled, 1 = enabled, -1 = don't do anything). "
106 "default is 1");
107
95/* 108/*
96 * Some events we use, same for all Asus 109 * Some events we use, same for all Asus
97 */ 110 */
@@ -114,6 +127,8 @@ MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot "
114 */ 127 */
115#define WL_RSTS 0x01 /* internal Wifi */ 128#define WL_RSTS 0x01 /* internal Wifi */
116#define BT_RSTS 0x02 /* internal Bluetooth */ 129#define BT_RSTS 0x02 /* internal Bluetooth */
130#define WM_RSTS 0x08 /* internal wimax */
131#define WW_RSTS 0x20 /* internal wwan */
117 132
118/* LED */ 133/* LED */
119#define METHOD_MLED "MLED" 134#define METHOD_MLED "MLED"
@@ -132,52 +147,20 @@ MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot "
132 */ 147 */
133#define METHOD_WLAN "WLED" 148#define METHOD_WLAN "WLED"
134#define METHOD_BLUETOOTH "BLED" 149#define METHOD_BLUETOOTH "BLED"
150
151/* WWAN and WIMAX */
152#define METHOD_WWAN "GSMC"
153#define METHOD_WIMAX "WMXC"
154
135#define METHOD_WL_STATUS "RSTS" 155#define METHOD_WL_STATUS "RSTS"
136 156
137/* Brightness */ 157/* Brightness */
138#define METHOD_BRIGHTNESS_SET "SPLV" 158#define METHOD_BRIGHTNESS_SET "SPLV"
139#define METHOD_BRIGHTNESS_GET "GPLV" 159#define METHOD_BRIGHTNESS_GET "GPLV"
140 160
141/* Backlight */
142static acpi_handle lcd_switch_handle;
143static char *lcd_switch_paths[] = {
144 "\\_SB.PCI0.SBRG.EC0._Q10", /* All new models */
145 "\\_SB.PCI0.ISA.EC0._Q10", /* A1x */
146 "\\_SB.PCI0.PX40.ECD0._Q10", /* L3C */
147 "\\_SB.PCI0.PX40.EC0.Q10", /* M1A */
148 "\\_SB.PCI0.LPCB.EC0._Q10", /* P30 */
149 "\\_SB.PCI0.LPCB.EC0._Q0E", /* P30/P35 */
150 "\\_SB.PCI0.PX40.Q10", /* S1x */
151 "\\Q10"}; /* A2x, L2D, L3D, M2E */
152
153/* Display */ 161/* Display */
154#define METHOD_SWITCH_DISPLAY "SDSP" 162#define METHOD_SWITCH_DISPLAY "SDSP"
155 163
156static acpi_handle display_get_handle;
157static char *display_get_paths[] = {
158 /* A6B, A6K A6R A7D F3JM L4R M6R A3G M6A M6V VX-1 V6J V6V W3Z */
159 "\\_SB.PCI0.P0P1.VGA.GETD",
160 /* A3E A4K, A4D A4L A6J A7J A8J Z71V M9V S5A M5A z33A W1Jc W2V G1 */
161 "\\_SB.PCI0.P0P2.VGA.GETD",
162 /* A6V A6Q */
163 "\\_SB.PCI0.P0P3.VGA.GETD",
164 /* A6T, A6M */
165 "\\_SB.PCI0.P0PA.VGA.GETD",
166 /* L3C */
167 "\\_SB.PCI0.PCI1.VGAC.NMAP",
168 /* Z96F */
169 "\\_SB.PCI0.VGA.GETD",
170 /* A2D */
171 "\\ACTD",
172 /* A4G Z71A W1N W5A W5F M2N M3N M5N M6N S1N S5N */
173 "\\ADVG",
174 /* P30 */
175 "\\DNXT",
176 /* A2H D1 L2D L3D L3H L2E L5D L5C M1A M2E L4L W3V */
177 "\\INFB",
178 /* A3F A6F A3N A3L M6N W3N W6A */
179 "\\SSTE"};
180
181#define METHOD_ALS_CONTROL "ALSC" /* Z71A Z71V */ 164#define METHOD_ALS_CONTROL "ALSC" /* Z71A Z71V */
182#define METHOD_ALS_LEVEL "ALSL" /* Z71A Z71V */ 165#define METHOD_ALS_LEVEL "ALSL" /* Z71A Z71V */
183 166
@@ -227,7 +210,6 @@ struct asus_laptop {
227 210
228 int wireless_status; 211 int wireless_status;
229 bool have_rsts; 212 bool have_rsts;
230 int lcd_state;
231 213
232 struct rfkill *gps_rfkill; 214 struct rfkill *gps_rfkill;
233 215
@@ -236,7 +218,6 @@ struct asus_laptop {
236 u8 light_level; /* light sensor level */ 218 u8 light_level; /* light sensor level */
237 u8 light_switch; /* light sensor switch value */ 219 u8 light_switch; /* light sensor switch value */
238 u16 event_count[128]; /* count for each event TODO make this better */ 220 u16 event_count[128]; /* count for each event TODO make this better */
239 u16 *keycode_map;
240}; 221};
241 222
242static const struct key_entry asus_keymap[] = { 223static const struct key_entry asus_keymap[] = {
@@ -278,6 +259,7 @@ static const struct key_entry asus_keymap[] = {
278 {KE_KEY, 0x99, { KEY_PHONE } }, 259 {KE_KEY, 0x99, { KEY_PHONE } },
279 {KE_KEY, 0xc4, { KEY_KBDILLUMUP } }, 260 {KE_KEY, 0xc4, { KEY_KBDILLUMUP } },
280 {KE_KEY, 0xc5, { KEY_KBDILLUMDOWN } }, 261 {KE_KEY, 0xc5, { KEY_KBDILLUMDOWN } },
262 {KE_KEY, 0xb5, { KEY_CALC } },
281 {KE_END, 0}, 263 {KE_END, 0},
282}; 264};
283 265
@@ -336,7 +318,7 @@ static int acpi_check_handle(acpi_handle handle, const char *method,
336 318
337 if (status != AE_OK) { 319 if (status != AE_OK) {
338 if (ret) 320 if (ret)
339 pr_warning("Error finding %s\n", method); 321 pr_warn("Error finding %s\n", method);
340 return -ENODEV; 322 return -ENODEV;
341 } 323 }
342 return 0; 324 return 0;
@@ -401,7 +383,7 @@ static int asus_kled_lvl(struct asus_laptop *asus)
401 rv = acpi_evaluate_integer(asus->handle, METHOD_KBD_LIGHT_GET, 383 rv = acpi_evaluate_integer(asus->handle, METHOD_KBD_LIGHT_GET,
402 &params, &kblv); 384 &params, &kblv);
403 if (ACPI_FAILURE(rv)) { 385 if (ACPI_FAILURE(rv)) {
404 pr_warning("Error reading kled level\n"); 386 pr_warn("Error reading kled level\n");
405 return -ENODEV; 387 return -ENODEV;
406 } 388 }
407 return kblv; 389 return kblv;
@@ -415,7 +397,7 @@ static int asus_kled_set(struct asus_laptop *asus, int kblv)
415 kblv = 0; 397 kblv = 0;
416 398
417 if (write_acpi_int(asus->handle, METHOD_KBD_LIGHT_SET, kblv)) { 399 if (write_acpi_int(asus->handle, METHOD_KBD_LIGHT_SET, kblv)) {
418 pr_warning("Keyboard LED display write failed\n"); 400 pr_warn("Keyboard LED display write failed\n");
419 return -EINVAL; 401 return -EINVAL;
420 } 402 }
421 return 0; 403 return 0;
@@ -540,48 +522,6 @@ error:
540/* 522/*
541 * Backlight device 523 * Backlight device
542 */ 524 */
543static int asus_lcd_status(struct asus_laptop *asus)
544{
545 return asus->lcd_state;
546}
547
548static int asus_lcd_set(struct asus_laptop *asus, int value)
549{
550 int lcd = 0;
551 acpi_status status = 0;
552
553 lcd = !!value;
554
555 if (lcd == asus_lcd_status(asus))
556 return 0;
557
558 if (!lcd_switch_handle)
559 return -ENODEV;
560
561 status = acpi_evaluate_object(lcd_switch_handle,
562 NULL, NULL, NULL);
563
564 if (ACPI_FAILURE(status)) {
565 pr_warning("Error switching LCD\n");
566 return -ENODEV;
567 }
568
569 asus->lcd_state = lcd;
570 return 0;
571}
572
573static void lcd_blank(struct asus_laptop *asus, int blank)
574{
575 struct backlight_device *bd = asus->backlight_device;
576
577 asus->lcd_state = (blank == FB_BLANK_UNBLANK);
578
579 if (bd) {
580 bd->props.power = blank;
581 backlight_update_status(bd);
582 }
583}
584
585static int asus_read_brightness(struct backlight_device *bd) 525static int asus_read_brightness(struct backlight_device *bd)
586{ 526{
587 struct asus_laptop *asus = bl_get_data(bd); 527 struct asus_laptop *asus = bl_get_data(bd);
@@ -591,7 +531,7 @@ static int asus_read_brightness(struct backlight_device *bd)
591 rv = acpi_evaluate_integer(asus->handle, METHOD_BRIGHTNESS_GET, 531 rv = acpi_evaluate_integer(asus->handle, METHOD_BRIGHTNESS_GET,
592 NULL, &value); 532 NULL, &value);
593 if (ACPI_FAILURE(rv)) 533 if (ACPI_FAILURE(rv))
594 pr_warning("Error reading brightness\n"); 534 pr_warn("Error reading brightness\n");
595 535
596 return value; 536 return value;
597} 537}
@@ -601,7 +541,7 @@ static int asus_set_brightness(struct backlight_device *bd, int value)
601 struct asus_laptop *asus = bl_get_data(bd); 541 struct asus_laptop *asus = bl_get_data(bd);
602 542
603 if (write_acpi_int(asus->handle, METHOD_BRIGHTNESS_SET, value)) { 543 if (write_acpi_int(asus->handle, METHOD_BRIGHTNESS_SET, value)) {
604 pr_warning("Error changing brightness\n"); 544 pr_warn("Error changing brightness\n");
605 return -EIO; 545 return -EIO;
606 } 546 }
607 return 0; 547 return 0;
@@ -609,19 +549,12 @@ static int asus_set_brightness(struct backlight_device *bd, int value)
609 549
610static int update_bl_status(struct backlight_device *bd) 550static int update_bl_status(struct backlight_device *bd)
611{ 551{
612 struct asus_laptop *asus = bl_get_data(bd);
613 int rv;
614 int value = bd->props.brightness; 552 int value = bd->props.brightness;
615 553
616 rv = asus_set_brightness(bd, value); 554 return asus_set_brightness(bd, value);
617 if (rv)
618 return rv;
619
620 value = (bd->props.power == FB_BLANK_UNBLANK) ? 1 : 0;
621 return asus_lcd_set(asus, value);
622} 555}
623 556
624static struct backlight_ops asusbl_ops = { 557static const struct backlight_ops asusbl_ops = {
625 .get_brightness = asus_read_brightness, 558 .get_brightness = asus_read_brightness,
626 .update_status = update_bl_status, 559 .update_status = update_bl_status,
627}; 560};
@@ -639,29 +572,29 @@ static int asus_backlight_notify(struct asus_laptop *asus)
639static int asus_backlight_init(struct asus_laptop *asus) 572static int asus_backlight_init(struct asus_laptop *asus)
640{ 573{
641 struct backlight_device *bd; 574 struct backlight_device *bd;
642 struct device *dev = &asus->platform_device->dev;
643 struct backlight_properties props; 575 struct backlight_properties props;
644 576
645 if (!acpi_check_handle(asus->handle, METHOD_BRIGHTNESS_GET, NULL) && 577 if (acpi_check_handle(asus->handle, METHOD_BRIGHTNESS_GET, NULL) ||
646 !acpi_check_handle(asus->handle, METHOD_BRIGHTNESS_SET, NULL) && 578 acpi_check_handle(asus->handle, METHOD_BRIGHTNESS_SET, NULL))
647 lcd_switch_handle) { 579 return 0;
648 memset(&props, 0, sizeof(struct backlight_properties));
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
659 asus->backlight_device = bd;
660 580
661 bd->props.power = FB_BLANK_UNBLANK; 581 memset(&props, 0, sizeof(struct backlight_properties));
662 bd->props.brightness = asus_read_brightness(bd); 582 props.max_brightness = 15;
663 backlight_update_status(bd); 583 props.type = BACKLIGHT_PLATFORM;
584
585 bd = backlight_device_register(ASUS_LAPTOP_FILE,
586 &asus->platform_device->dev, asus,
587 &asusbl_ops, &props);
588 if (IS_ERR(bd)) {
589 pr_err("Could not register asus backlight device\n");
590 asus->backlight_device = NULL;
591 return PTR_ERR(bd);
664 } 592 }
593
594 asus->backlight_device = bd;
595 bd->props.brightness = asus_read_brightness(bd);
596 bd->props.power = FB_BLANK_UNBLANK;
597 backlight_update_status(bd);
665 return 0; 598 return 0;
666} 599}
667 600
@@ -797,7 +730,7 @@ static ssize_t store_ledd(struct device *dev, struct device_attribute *attr,
797 rv = parse_arg(buf, count, &value); 730 rv = parse_arg(buf, count, &value);
798 if (rv > 0) { 731 if (rv > 0) {
799 if (write_acpi_int(asus->handle, METHOD_LEDD, value)) { 732 if (write_acpi_int(asus->handle, METHOD_LEDD, value)) {
800 pr_warning("LED display write failed\n"); 733 pr_warn("LED display write failed\n");
801 return -ENODEV; 734 return -ENODEV;
802 } 735 }
803 asus->ledd_status = (u32) value; 736 asus->ledd_status = (u32) value;
@@ -819,7 +752,7 @@ static int asus_wireless_status(struct asus_laptop *asus, int mask)
819 rv = acpi_evaluate_integer(asus->handle, METHOD_WL_STATUS, 752 rv = acpi_evaluate_integer(asus->handle, METHOD_WL_STATUS,
820 NULL, &status); 753 NULL, &status);
821 if (ACPI_FAILURE(rv)) { 754 if (ACPI_FAILURE(rv)) {
822 pr_warning("Error reading Wireless status\n"); 755 pr_warn("Error reading Wireless status\n");
823 return -EINVAL; 756 return -EINVAL;
824 } 757 }
825 return !!(status & mask); 758 return !!(status & mask);
@@ -831,7 +764,7 @@ static int asus_wireless_status(struct asus_laptop *asus, int mask)
831static int asus_wlan_set(struct asus_laptop *asus, int status) 764static int asus_wlan_set(struct asus_laptop *asus, int status)
832{ 765{
833 if (write_acpi_int(asus->handle, METHOD_WLAN, !!status)) { 766 if (write_acpi_int(asus->handle, METHOD_WLAN, !!status)) {
834 pr_warning("Error setting wlan status to %d", status); 767 pr_warn("Error setting wlan status to %d\n", status);
835 return -EIO; 768 return -EIO;
836 } 769 }
837 return 0; 770 return 0;
@@ -859,7 +792,7 @@ static ssize_t store_wlan(struct device *dev, struct device_attribute *attr,
859static int asus_bluetooth_set(struct asus_laptop *asus, int status) 792static int asus_bluetooth_set(struct asus_laptop *asus, int status)
860{ 793{
861 if (write_acpi_int(asus->handle, METHOD_BLUETOOTH, !!status)) { 794 if (write_acpi_int(asus->handle, METHOD_BLUETOOTH, !!status)) {
862 pr_warning("Error setting bluetooth status to %d", status); 795 pr_warn("Error setting bluetooth status to %d\n", status);
863 return -EIO; 796 return -EIO;
864 } 797 }
865 return 0; 798 return 0;
@@ -883,49 +816,72 @@ static ssize_t store_bluetooth(struct device *dev,
883} 816}
884 817
885/* 818/*
886 * Display 819 * Wimax
887 */ 820 */
888static void asus_set_display(struct asus_laptop *asus, int value) 821static int asus_wimax_set(struct asus_laptop *asus, int status)
889{ 822{
890 /* no sanity check needed for now */ 823 if (write_acpi_int(asus->handle, METHOD_WIMAX, !!status)) {
891 if (write_acpi_int(asus->handle, METHOD_SWITCH_DISPLAY, value)) 824 pr_warn("Error setting wimax status to %d\n", status);
892 pr_warning("Error setting display\n"); 825 return -EIO;
893 return; 826 }
827 return 0;
894} 828}
895 829
896static int read_display(struct asus_laptop *asus) 830static ssize_t show_wimax(struct device *dev,
831 struct device_attribute *attr, char *buf)
897{ 832{
898 unsigned long long value = 0; 833 struct asus_laptop *asus = dev_get_drvdata(dev);
899 acpi_status rv = AE_OK;
900 834
901 /* 835 return sprintf(buf, "%d\n", asus_wireless_status(asus, WM_RSTS));
902 * In most of the case, we know how to set the display, but sometime 836}
903 * we can't read it
904 */
905 if (display_get_handle) {
906 rv = acpi_evaluate_integer(display_get_handle, NULL,
907 NULL, &value);
908 if (ACPI_FAILURE(rv))
909 pr_warning("Error reading display status\n");
910 }
911 837
912 value &= 0x0F; /* needed for some models, shouldn't hurt others */ 838static ssize_t store_wimax(struct device *dev,
839 struct device_attribute *attr, const char *buf,
840 size_t count)
841{
842 struct asus_laptop *asus = dev_get_drvdata(dev);
913 843
914 return value; 844 return sysfs_acpi_set(asus, buf, count, METHOD_WIMAX);
915} 845}
916 846
917/* 847/*
918 * Now, *this* one could be more user-friendly, but so far, no-one has 848 * Wwan
919 * complained. The significance of bits is the same as in store_disp()
920 */ 849 */
921static ssize_t show_disp(struct device *dev, 850static int asus_wwan_set(struct asus_laptop *asus, int status)
922 struct device_attribute *attr, char *buf) 851{
852 if (write_acpi_int(asus->handle, METHOD_WWAN, !!status)) {
853 pr_warn("Error setting wwan status to %d\n", status);
854 return -EIO;
855 }
856 return 0;
857}
858
859static ssize_t show_wwan(struct device *dev,
860 struct device_attribute *attr, char *buf)
923{ 861{
924 struct asus_laptop *asus = dev_get_drvdata(dev); 862 struct asus_laptop *asus = dev_get_drvdata(dev);
925 863
926 if (!display_get_handle) 864 return sprintf(buf, "%d\n", asus_wireless_status(asus, WW_RSTS));
927 return -ENODEV; 865}
928 return sprintf(buf, "%d\n", read_display(asus)); 866
867static ssize_t store_wwan(struct device *dev,
868 struct device_attribute *attr, const char *buf,
869 size_t count)
870{
871 struct asus_laptop *asus = dev_get_drvdata(dev);
872
873 return sysfs_acpi_set(asus, buf, count, METHOD_WWAN);
874}
875
876/*
877 * Display
878 */
879static void asus_set_display(struct asus_laptop *asus, int value)
880{
881 /* no sanity check needed for now */
882 if (write_acpi_int(asus->handle, METHOD_SWITCH_DISPLAY, value))
883 pr_warn("Error setting display\n");
884 return;
929} 885}
930 886
931/* 887/*
@@ -953,7 +909,7 @@ static ssize_t store_disp(struct device *dev, struct device_attribute *attr,
953static void asus_als_switch(struct asus_laptop *asus, int value) 909static void asus_als_switch(struct asus_laptop *asus, int value)
954{ 910{
955 if (write_acpi_int(asus->handle, METHOD_ALS_CONTROL, value)) 911 if (write_acpi_int(asus->handle, METHOD_ALS_CONTROL, value))
956 pr_warning("Error setting light sensor switch\n"); 912 pr_warn("Error setting light sensor switch\n");
957 asus->light_switch = value; 913 asus->light_switch = value;
958} 914}
959 915
@@ -981,7 +937,7 @@ static ssize_t store_lssw(struct device *dev, struct device_attribute *attr,
981static void asus_als_level(struct asus_laptop *asus, int value) 937static void asus_als_level(struct asus_laptop *asus, int value)
982{ 938{
983 if (write_acpi_int(asus->handle, METHOD_ALS_LEVEL, value)) 939 if (write_acpi_int(asus->handle, METHOD_ALS_LEVEL, value))
984 pr_warning("Error setting light sensor level\n"); 940 pr_warn("Error setting light sensor level\n");
985 asus->light_level = value; 941 asus->light_level = value;
986} 942}
987 943
@@ -1020,7 +976,7 @@ static int asus_gps_status(struct asus_laptop *asus)
1020 rv = acpi_evaluate_integer(asus->handle, METHOD_GPS_STATUS, 976 rv = acpi_evaluate_integer(asus->handle, METHOD_GPS_STATUS,
1021 NULL, &status); 977 NULL, &status);
1022 if (ACPI_FAILURE(rv)) { 978 if (ACPI_FAILURE(rv)) {
1023 pr_warning("Error reading GPS status\n"); 979 pr_warn("Error reading GPS status\n");
1024 return -ENODEV; 980 return -ENODEV;
1025 } 981 }
1026 return !!status; 982 return !!status;
@@ -1065,9 +1021,9 @@ static ssize_t store_gps(struct device *dev, struct device_attribute *attr,
1065 */ 1021 */
1066static int asus_gps_rfkill_set(void *data, bool blocked) 1022static int asus_gps_rfkill_set(void *data, bool blocked)
1067{ 1023{
1068 acpi_handle handle = data; 1024 struct asus_laptop *asus = data;
1069 1025
1070 return asus_gps_switch(handle, !blocked); 1026 return asus_gps_switch(asus, !blocked);
1071} 1027}
1072 1028
1073static const struct rfkill_ops asus_gps_rfkill_ops = { 1029static const struct rfkill_ops asus_gps_rfkill_ops = {
@@ -1094,7 +1050,7 @@ static int asus_rfkill_init(struct asus_laptop *asus)
1094 1050
1095 asus->gps_rfkill = rfkill_alloc("asus-gps", &asus->platform_device->dev, 1051 asus->gps_rfkill = rfkill_alloc("asus-gps", &asus->platform_device->dev,
1096 RFKILL_TYPE_GPS, 1052 RFKILL_TYPE_GPS,
1097 &asus_gps_rfkill_ops, NULL); 1053 &asus_gps_rfkill_ops, asus);
1098 if (!asus->gps_rfkill) 1054 if (!asus->gps_rfkill)
1099 return -EINVAL; 1055 return -EINVAL;
1100 1056
@@ -1130,7 +1086,6 @@ static int asus_input_init(struct asus_laptop *asus)
1130 input->phys = ASUS_LAPTOP_FILE "/input0"; 1086 input->phys = ASUS_LAPTOP_FILE "/input0";
1131 input->id.bustype = BUS_HOST; 1087 input->id.bustype = BUS_HOST;
1132 input->dev.parent = &asus->platform_device->dev; 1088 input->dev.parent = &asus->platform_device->dev;
1133 input_set_drvdata(input, asus);
1134 1089
1135 error = sparse_keymap_setup(input, asus_keymap, NULL); 1090 error = sparse_keymap_setup(input, asus_keymap, NULL);
1136 if (error) { 1091 if (error) {
@@ -1159,6 +1114,7 @@ static void asus_input_exit(struct asus_laptop *asus)
1159 sparse_keymap_free(asus->inputdev); 1114 sparse_keymap_free(asus->inputdev);
1160 input_unregister_device(asus->inputdev); 1115 input_unregister_device(asus->inputdev);
1161 } 1116 }
1117 asus->inputdev = NULL;
1162} 1118}
1163 1119
1164/* 1120/*
@@ -1169,15 +1125,6 @@ static void asus_acpi_notify(struct acpi_device *device, u32 event)
1169 struct asus_laptop *asus = acpi_driver_data(device); 1125 struct asus_laptop *asus = acpi_driver_data(device);
1170 u16 count; 1126 u16 count;
1171 1127
1172 /*
1173 * We need to tell the backlight device when the backlight power is
1174 * switched
1175 */
1176 if (event == ATKD_LCD_ON)
1177 lcd_blank(asus, FB_BLANK_UNBLANK);
1178 else if (event == ATKD_LCD_OFF)
1179 lcd_blank(asus, FB_BLANK_POWERDOWN);
1180
1181 /* TODO Find a better way to handle events count. */ 1128 /* TODO Find a better way to handle events count. */
1182 count = asus->event_count[event % 128]++; 1129 count = asus->event_count[event % 128]++;
1183 acpi_bus_generate_proc_event(asus->device, event, count); 1130 acpi_bus_generate_proc_event(asus->device, event, count);
@@ -1200,111 +1147,111 @@ static void asus_acpi_notify(struct acpi_device *device, u32 event)
1200 1147
1201static DEVICE_ATTR(infos, S_IRUGO, show_infos, NULL); 1148static DEVICE_ATTR(infos, S_IRUGO, show_infos, NULL);
1202static DEVICE_ATTR(wlan, S_IRUGO | S_IWUSR, show_wlan, store_wlan); 1149static DEVICE_ATTR(wlan, S_IRUGO | S_IWUSR, show_wlan, store_wlan);
1203static DEVICE_ATTR(bluetooth, S_IRUGO | S_IWUSR, show_bluetooth, 1150static DEVICE_ATTR(bluetooth, S_IRUGO | S_IWUSR,
1204 store_bluetooth); 1151 show_bluetooth, store_bluetooth);
1205static DEVICE_ATTR(display, S_IRUGO | S_IWUSR, show_disp, store_disp); 1152static DEVICE_ATTR(wimax, S_IRUGO | S_IWUSR, show_wimax, store_wimax);
1153static DEVICE_ATTR(wwan, S_IRUGO | S_IWUSR, show_wwan, store_wwan);
1154static DEVICE_ATTR(display, S_IWUSR, NULL, store_disp);
1206static DEVICE_ATTR(ledd, S_IRUGO | S_IWUSR, show_ledd, store_ledd); 1155static DEVICE_ATTR(ledd, S_IRUGO | S_IWUSR, show_ledd, store_ledd);
1207static DEVICE_ATTR(ls_level, S_IRUGO | S_IWUSR, show_lslvl, store_lslvl); 1156static 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); 1157static DEVICE_ATTR(ls_switch, S_IRUGO | S_IWUSR, show_lssw, store_lssw);
1209static DEVICE_ATTR(gps, S_IRUGO | S_IWUSR, show_gps, store_gps); 1158static DEVICE_ATTR(gps, S_IRUGO | S_IWUSR, show_gps, store_gps);
1210 1159
1211static void asus_sysfs_exit(struct asus_laptop *asus) 1160static struct attribute *asus_attributes[] = {
1212{ 1161 &dev_attr_infos.attr,
1213 struct platform_device *device = asus->platform_device; 1162 &dev_attr_wlan.attr,
1214 1163 &dev_attr_bluetooth.attr,
1215 device_remove_file(&device->dev, &dev_attr_infos); 1164 &dev_attr_wimax.attr,
1216 device_remove_file(&device->dev, &dev_attr_wlan); 1165 &dev_attr_wwan.attr,
1217 device_remove_file(&device->dev, &dev_attr_bluetooth); 1166 &dev_attr_display.attr,
1218 device_remove_file(&device->dev, &dev_attr_display); 1167 &dev_attr_ledd.attr,
1219 device_remove_file(&device->dev, &dev_attr_ledd); 1168 &dev_attr_ls_level.attr,
1220 device_remove_file(&device->dev, &dev_attr_ls_switch); 1169 &dev_attr_ls_switch.attr,
1221 device_remove_file(&device->dev, &dev_attr_ls_level); 1170 &dev_attr_gps.attr,
1222 device_remove_file(&device->dev, &dev_attr_gps); 1171 NULL
1223} 1172};
1224 1173
1225static int asus_sysfs_init(struct asus_laptop *asus) 1174static mode_t asus_sysfs_is_visible(struct kobject *kobj,
1175 struct attribute *attr,
1176 int idx)
1226{ 1177{
1227 struct platform_device *device = asus->platform_device; 1178 struct device *dev = container_of(kobj, struct device, kobj);
1228 int err; 1179 struct platform_device *pdev = to_platform_device(dev);
1180 struct asus_laptop *asus = platform_get_drvdata(pdev);
1181 acpi_handle handle = asus->handle;
1182 bool supported;
1229 1183
1230 err = device_create_file(&device->dev, &dev_attr_infos); 1184 if (attr == &dev_attr_wlan.attr) {
1231 if (err) 1185 supported = !acpi_check_handle(handle, METHOD_WLAN, NULL);
1232 return err;
1233 1186
1234 if (!acpi_check_handle(asus->handle, METHOD_WLAN, NULL)) { 1187 } else if (attr == &dev_attr_bluetooth.attr) {
1235 err = device_create_file(&device->dev, &dev_attr_wlan); 1188 supported = !acpi_check_handle(handle, METHOD_BLUETOOTH, NULL);
1236 if (err)
1237 return err;
1238 }
1239 1189
1240 if (!acpi_check_handle(asus->handle, METHOD_BLUETOOTH, NULL)) { 1190 } else if (attr == &dev_attr_display.attr) {
1241 err = device_create_file(&device->dev, &dev_attr_bluetooth); 1191 supported = !acpi_check_handle(handle, METHOD_SWITCH_DISPLAY, NULL);
1242 if (err)
1243 return err;
1244 }
1245 1192
1246 if (!acpi_check_handle(asus->handle, METHOD_SWITCH_DISPLAY, NULL)) { 1193 } else if (attr == &dev_attr_wimax.attr) {
1247 err = device_create_file(&device->dev, &dev_attr_display); 1194 supported =
1248 if (err) 1195 !acpi_check_handle(asus->handle, METHOD_WIMAX, NULL);
1249 return err;
1250 }
1251 1196
1252 if (!acpi_check_handle(asus->handle, METHOD_LEDD, NULL)) { 1197 } else if (attr == &dev_attr_wwan.attr) {
1253 err = device_create_file(&device->dev, &dev_attr_ledd); 1198 supported = !acpi_check_handle(asus->handle, METHOD_WWAN, NULL);
1254 if (err)
1255 return err;
1256 }
1257 1199
1258 if (!acpi_check_handle(asus->handle, METHOD_ALS_CONTROL, NULL) && 1200 } else if (attr == &dev_attr_ledd.attr) {
1259 !acpi_check_handle(asus->handle, METHOD_ALS_LEVEL, NULL)) { 1201 supported = !acpi_check_handle(handle, METHOD_LEDD, NULL);
1260 err = device_create_file(&device->dev, &dev_attr_ls_switch); 1202
1261 if (err) 1203 } else if (attr == &dev_attr_ls_switch.attr ||
1262 return err; 1204 attr == &dev_attr_ls_level.attr) {
1263 err = device_create_file(&device->dev, &dev_attr_ls_level); 1205 supported = !acpi_check_handle(handle, METHOD_ALS_CONTROL, NULL) &&
1264 if (err) 1206 !acpi_check_handle(handle, METHOD_ALS_LEVEL, NULL);
1265 return err;
1266 }
1267 1207
1268 if (!acpi_check_handle(asus->handle, METHOD_GPS_ON, NULL) && 1208 } else if (attr == &dev_attr_gps.attr) {
1269 !acpi_check_handle(asus->handle, METHOD_GPS_OFF, NULL) && 1209 supported = !acpi_check_handle(handle, METHOD_GPS_ON, NULL) &&
1270 !acpi_check_handle(asus->handle, METHOD_GPS_STATUS, NULL)) { 1210 !acpi_check_handle(handle, METHOD_GPS_OFF, NULL) &&
1271 err = device_create_file(&device->dev, &dev_attr_gps); 1211 !acpi_check_handle(handle, METHOD_GPS_STATUS, NULL);
1272 if (err) 1212 } else {
1273 return err; 1213 supported = true;
1274 } 1214 }
1275 1215
1276 return err; 1216 return supported ? attr->mode : 0;
1277} 1217}
1278 1218
1219
1220static const struct attribute_group asus_attr_group = {
1221 .is_visible = asus_sysfs_is_visible,
1222 .attrs = asus_attributes,
1223};
1224
1279static int asus_platform_init(struct asus_laptop *asus) 1225static int asus_platform_init(struct asus_laptop *asus)
1280{ 1226{
1281 int err; 1227 int result;
1282 1228
1283 asus->platform_device = platform_device_alloc(ASUS_LAPTOP_FILE, -1); 1229 asus->platform_device = platform_device_alloc(ASUS_LAPTOP_FILE, -1);
1284 if (!asus->platform_device) 1230 if (!asus->platform_device)
1285 return -ENOMEM; 1231 return -ENOMEM;
1286 platform_set_drvdata(asus->platform_device, asus); 1232 platform_set_drvdata(asus->platform_device, asus);
1287 1233
1288 err = platform_device_add(asus->platform_device); 1234 result = platform_device_add(asus->platform_device);
1289 if (err) 1235 if (result)
1290 goto fail_platform_device; 1236 goto fail_platform_device;
1291 1237
1292 err = asus_sysfs_init(asus); 1238 result = sysfs_create_group(&asus->platform_device->dev.kobj,
1293 if (err) 1239 &asus_attr_group);
1240 if (result)
1294 goto fail_sysfs; 1241 goto fail_sysfs;
1242
1295 return 0; 1243 return 0;
1296 1244
1297fail_sysfs: 1245fail_sysfs:
1298 asus_sysfs_exit(asus);
1299 platform_device_del(asus->platform_device); 1246 platform_device_del(asus->platform_device);
1300fail_platform_device: 1247fail_platform_device:
1301 platform_device_put(asus->platform_device); 1248 platform_device_put(asus->platform_device);
1302 return err; 1249 return result;
1303} 1250}
1304 1251
1305static void asus_platform_exit(struct asus_laptop *asus) 1252static void asus_platform_exit(struct asus_laptop *asus)
1306{ 1253{
1307 asus_sysfs_exit(asus); 1254 sysfs_remove_group(&asus->platform_device->dev.kobj, &asus_attr_group);
1308 platform_device_unregister(asus->platform_device); 1255 platform_device_unregister(asus->platform_device);
1309} 1256}
1310 1257
@@ -1315,26 +1262,6 @@ static struct platform_driver platform_driver = {
1315 } 1262 }
1316}; 1263};
1317 1264
1318static int asus_handle_init(char *name, acpi_handle * handle,
1319 char **paths, int num_paths)
1320{
1321 int i;
1322 acpi_status status;
1323
1324 for (i = 0; i < num_paths; i++) {
1325 status = acpi_get_handle(NULL, paths[i], handle);
1326 if (ACPI_SUCCESS(status))
1327 return 0;
1328 }
1329
1330 *handle = NULL;
1331 return -ENODEV;
1332}
1333
1334#define ASUS_HANDLE_INIT(object) \
1335 asus_handle_init(#object, &object##_handle, object##_paths, \
1336 ARRAY_SIZE(object##_paths))
1337
1338/* 1265/*
1339 * This function is used to initialize the context with right values. In this 1266 * This function is used to initialize the context with right values. In this
1340 * method, we can make all the detection we want, and modify the asus_laptop 1267 * method, we can make all the detection we want, and modify the asus_laptop
@@ -1357,7 +1284,7 @@ static int asus_laptop_get_info(struct asus_laptop *asus)
1357 */ 1284 */
1358 status = acpi_get_table(ACPI_SIG_DSDT, 1, &asus->dsdt_info); 1285 status = acpi_get_table(ACPI_SIG_DSDT, 1, &asus->dsdt_info);
1359 if (ACPI_FAILURE(status)) 1286 if (ACPI_FAILURE(status))
1360 pr_warning("Couldn't get the DSDT table header\n"); 1287 pr_warn("Couldn't get the DSDT table header\n");
1361 1288
1362 /* We have to write 0 on init this far for all ASUS models */ 1289 /* We have to write 0 on init this far for all ASUS models */
1363 if (write_acpi_int_ret(asus->handle, "INIT", 0, &buffer)) { 1290 if (write_acpi_int_ret(asus->handle, "INIT", 0, &buffer)) {
@@ -1369,7 +1296,7 @@ static int asus_laptop_get_info(struct asus_laptop *asus)
1369 status = 1296 status =
1370 acpi_evaluate_integer(asus->handle, "BSTS", NULL, &bsts_result); 1297 acpi_evaluate_integer(asus->handle, "BSTS", NULL, &bsts_result);
1371 if (ACPI_FAILURE(status)) 1298 if (ACPI_FAILURE(status))
1372 pr_warning("Error calling BSTS\n"); 1299 pr_warn("Error calling BSTS\n");
1373 else if (bsts_result) 1300 else if (bsts_result)
1374 pr_notice("BSTS called, 0x%02x returned\n", 1301 pr_notice("BSTS called, 0x%02x returned\n",
1375 (uint) bsts_result); 1302 (uint) bsts_result);
@@ -1408,7 +1335,8 @@ static int asus_laptop_get_info(struct asus_laptop *asus)
1408 1335
1409 /* 1336 /*
1410 * The HWRS method return informations about the hardware. 1337 * The HWRS method return informations about the hardware.
1411 * 0x80 bit is for WLAN, 0x100 for Bluetooth. 1338 * 0x80 bit is for WLAN, 0x100 for Bluetooth,
1339 * 0x40 for WWAN, 0x10 for WIMAX.
1412 * The significance of others is yet to be found. 1340 * The significance of others is yet to be found.
1413 */ 1341 */
1414 status = 1342 status =
@@ -1419,17 +1347,11 @@ static int asus_laptop_get_info(struct asus_laptop *asus)
1419 if (!acpi_check_handle(asus->handle, METHOD_WL_STATUS, NULL)) 1347 if (!acpi_check_handle(asus->handle, METHOD_WL_STATUS, NULL))
1420 asus->have_rsts = true; 1348 asus->have_rsts = true;
1421 1349
1422 /* Scheduled for removal */
1423 ASUS_HANDLE_INIT(lcd_switch);
1424 ASUS_HANDLE_INIT(display_get);
1425
1426 kfree(model); 1350 kfree(model);
1427 1351
1428 return AE_OK; 1352 return AE_OK;
1429} 1353}
1430 1354
1431static bool asus_device_present;
1432
1433static int __devinit asus_acpi_init(struct asus_laptop *asus) 1355static int __devinit asus_acpi_init(struct asus_laptop *asus)
1434{ 1356{
1435 int result = 0; 1357 int result = 0;
@@ -1453,6 +1375,12 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus)
1453 if (wlan_status >= 0) 1375 if (wlan_status >= 0)
1454 asus_wlan_set(asus, !!wlan_status); 1376 asus_wlan_set(asus, !!wlan_status);
1455 1377
1378 if (wimax_status >= 0)
1379 asus_wimax_set(asus, !!wimax_status);
1380
1381 if (wwan_status >= 0)
1382 asus_wwan_set(asus, !!wwan_status);
1383
1456 /* Keyboard Backlight is on by default */ 1384 /* Keyboard Backlight is on by default */
1457 if (!acpi_check_handle(asus->handle, METHOD_KBD_LIGHT_SET, NULL)) 1385 if (!acpi_check_handle(asus->handle, METHOD_KBD_LIGHT_SET, NULL))
1458 asus_kled_set(asus, 1); 1386 asus_kled_set(asus, 1);
@@ -1470,10 +1398,25 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus)
1470 asus_als_level(asus, asus->light_level); 1398 asus_als_level(asus, asus->light_level);
1471 } 1399 }
1472 1400
1473 asus->lcd_state = 1; /* LCD should be on when the module load */
1474 return result; 1401 return result;
1475} 1402}
1476 1403
1404static void __devinit asus_dmi_check(void)
1405{
1406 const char *model;
1407
1408 model = dmi_get_system_info(DMI_PRODUCT_NAME);
1409 if (!model)
1410 return;
1411
1412 /* On L1400B WLED control the sound card, don't mess with it ... */
1413 if (strncmp(model, "L1400B", 6) == 0) {
1414 wlan_status = -1;
1415 }
1416}
1417
1418static bool asus_device_present;
1419
1477static int __devinit asus_acpi_add(struct acpi_device *device) 1420static int __devinit asus_acpi_add(struct acpi_device *device)
1478{ 1421{
1479 struct asus_laptop *asus; 1422 struct asus_laptop *asus;
@@ -1490,6 +1433,8 @@ static int __devinit asus_acpi_add(struct acpi_device *device)
1490 device->driver_data = asus; 1433 device->driver_data = asus;
1491 asus->device = device; 1434 asus->device = device;
1492 1435
1436 asus_dmi_check();
1437
1493 result = asus_acpi_init(asus); 1438 result = asus_acpi_init(asus);
1494 if (result) 1439 if (result)
1495 goto fail_platform; 1440 goto fail_platform;
diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c
new file mode 100644
index 000000000000..0580d99b0798
--- /dev/null
+++ b/drivers/platform/x86/asus-nb-wmi.c
@@ -0,0 +1,98 @@
1/*
2 * Asus Notebooks WMI hotkey driver
3 *
4 * Copyright(C) 2010 Corentin Chary <corentin.chary@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
22
23#include <linux/kernel.h>
24#include <linux/module.h>
25#include <linux/init.h>
26#include <linux/input.h>
27#include <linux/input/sparse-keymap.h>
28
29#include "asus-wmi.h"
30
31#define ASUS_NB_WMI_FILE "asus-nb-wmi"
32
33MODULE_AUTHOR("Corentin Chary <corentincj@iksaif.net>");
34MODULE_DESCRIPTION("Asus Notebooks WMI Hotkey Driver");
35MODULE_LICENSE("GPL");
36
37#define ASUS_NB_WMI_EVENT_GUID "0B3CBB35-E3C2-45ED-91C2-4C5A6D195D1C"
38
39MODULE_ALIAS("wmi:"ASUS_NB_WMI_EVENT_GUID);
40
41static const struct key_entry asus_nb_wmi_keymap[] = {
42 { KE_KEY, 0x30, { KEY_VOLUMEUP } },
43 { KE_KEY, 0x31, { KEY_VOLUMEDOWN } },
44 { KE_KEY, 0x32, { KEY_MUTE } },
45 { KE_KEY, 0x33, { KEY_DISPLAYTOGGLE } }, /* LCD on */
46 { KE_KEY, 0x34, { KEY_DISPLAY_OFF } }, /* LCD off */
47 { KE_KEY, 0x40, { KEY_PREVIOUSSONG } },
48 { KE_KEY, 0x41, { KEY_NEXTSONG } },
49 { KE_KEY, 0x43, { KEY_STOPCD } },
50 { KE_KEY, 0x45, { KEY_PLAYPAUSE } },
51 { KE_KEY, 0x4c, { KEY_MEDIA } },
52 { KE_KEY, 0x50, { KEY_EMAIL } },
53 { KE_KEY, 0x51, { KEY_WWW } },
54 { KE_KEY, 0x55, { KEY_CALC } },
55 { KE_KEY, 0x5C, { KEY_F15 } }, /* Power Gear key */
56 { KE_KEY, 0x5D, { KEY_WLAN } },
57 { KE_KEY, 0x5E, { KEY_WLAN } },
58 { KE_KEY, 0x5F, { KEY_WLAN } },
59 { KE_KEY, 0x60, { KEY_SWITCHVIDEOMODE } },
60 { KE_KEY, 0x61, { KEY_SWITCHVIDEOMODE } },
61 { KE_KEY, 0x62, { KEY_SWITCHVIDEOMODE } },
62 { KE_KEY, 0x63, { KEY_SWITCHVIDEOMODE } },
63 { KE_KEY, 0x6B, { KEY_TOUCHPAD_TOGGLE } },
64 { KE_KEY, 0x7E, { KEY_BLUETOOTH } },
65 { KE_KEY, 0x7D, { KEY_BLUETOOTH } },
66 { KE_KEY, 0x82, { KEY_CAMERA } },
67 { KE_KEY, 0x88, { KEY_RFKILL } },
68 { KE_KEY, 0x8A, { KEY_PROG1 } },
69 { KE_KEY, 0x95, { KEY_MEDIA } },
70 { KE_KEY, 0x99, { KEY_PHONE } },
71 { KE_KEY, 0xb5, { KEY_CALC } },
72 { KE_KEY, 0xc4, { KEY_KBDILLUMUP } },
73 { KE_KEY, 0xc5, { KEY_KBDILLUMDOWN } },
74 { KE_END, 0},
75};
76
77static struct asus_wmi_driver asus_nb_wmi_driver = {
78 .name = ASUS_NB_WMI_FILE,
79 .owner = THIS_MODULE,
80 .event_guid = ASUS_NB_WMI_EVENT_GUID,
81 .keymap = asus_nb_wmi_keymap,
82 .input_name = "Asus WMI hotkeys",
83 .input_phys = ASUS_NB_WMI_FILE "/input0",
84};
85
86
87static int __init asus_nb_wmi_init(void)
88{
89 return asus_wmi_register_driver(&asus_nb_wmi_driver);
90}
91
92static void __exit asus_nb_wmi_exit(void)
93{
94 asus_wmi_unregister_driver(&asus_nb_wmi_driver);
95}
96
97module_init(asus_nb_wmi_init);
98module_exit(asus_nb_wmi_exit);
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
new file mode 100644
index 000000000000..3c7857c71a23
--- /dev/null
+++ b/drivers/platform/x86/asus-wmi.c
@@ -0,0 +1,1657 @@
1/*
2 * Asus PC WMI hotkey driver
3 *
4 * Copyright(C) 2010 Intel Corporation.
5 * Copyright(C) 2010-2011 Corentin Chary <corentin.chary@gmail.com>
6 *
7 * Portions based on wistron_btns.c:
8 * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz>
9 * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org>
10 * Copyright (C) 2005 Dmitry Torokhov <dtor@mail.ru>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 */
26
27#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
28
29#include <linux/kernel.h>
30#include <linux/module.h>
31#include <linux/init.h>
32#include <linux/types.h>
33#include <linux/slab.h>
34#include <linux/input.h>
35#include <linux/input/sparse-keymap.h>
36#include <linux/fb.h>
37#include <linux/backlight.h>
38#include <linux/leds.h>
39#include <linux/rfkill.h>
40#include <linux/pci.h>
41#include <linux/pci_hotplug.h>
42#include <linux/hwmon.h>
43#include <linux/hwmon-sysfs.h>
44#include <linux/debugfs.h>
45#include <linux/seq_file.h>
46#include <linux/platform_device.h>
47#include <acpi/acpi_bus.h>
48#include <acpi/acpi_drivers.h>
49
50#include "asus-wmi.h"
51
52MODULE_AUTHOR("Corentin Chary <corentincj@iksaif.net>, "
53 "Yong Wang <yong.y.wang@intel.com>");
54MODULE_DESCRIPTION("Asus Generic WMI Driver");
55MODULE_LICENSE("GPL");
56
57#define to_platform_driver(drv) \
58 (container_of((drv), struct platform_driver, driver))
59
60#define to_asus_wmi_driver(pdrv) \
61 (container_of((pdrv), struct asus_wmi_driver, platform_driver))
62
63#define ASUS_WMI_MGMT_GUID "97845ED0-4E6D-11DE-8A39-0800200C9A66"
64
65#define NOTIFY_BRNUP_MIN 0x11
66#define NOTIFY_BRNUP_MAX 0x1f
67#define NOTIFY_BRNDOWN_MIN 0x20
68#define NOTIFY_BRNDOWN_MAX 0x2e
69
70/* WMI Methods */
71#define ASUS_WMI_METHODID_SPEC 0x43455053 /* BIOS SPECification */
72#define ASUS_WMI_METHODID_SFBD 0x44424653 /* Set First Boot Device */
73#define ASUS_WMI_METHODID_GLCD 0x44434C47 /* Get LCD status */
74#define ASUS_WMI_METHODID_GPID 0x44495047 /* Get Panel ID?? (Resol) */
75#define ASUS_WMI_METHODID_QMOD 0x444F4D51 /* Quiet MODe */
76#define ASUS_WMI_METHODID_SPLV 0x4C425053 /* Set Panel Light Value */
77#define ASUS_WMI_METHODID_SFUN 0x4E554653 /* FUNCtionalities */
78#define ASUS_WMI_METHODID_SDSP 0x50534453 /* Set DiSPlay output */
79#define ASUS_WMI_METHODID_GDSP 0x50534447 /* Get DiSPlay output */
80#define ASUS_WMI_METHODID_DEVP 0x50564544 /* DEVice Policy */
81#define ASUS_WMI_METHODID_OSVR 0x5256534F /* OS VeRsion */
82#define ASUS_WMI_METHODID_DSTS 0x53544344 /* Device STatuS */
83#define ASUS_WMI_METHODID_DSTS2 0x53545344 /* Device STatuS #2*/
84#define ASUS_WMI_METHODID_BSTS 0x53545342 /* Bios STatuS ? */
85#define ASUS_WMI_METHODID_DEVS 0x53564544 /* DEVice Set */
86#define ASUS_WMI_METHODID_CFVS 0x53564643 /* CPU Frequency Volt Set */
87#define ASUS_WMI_METHODID_KBFT 0x5446424B /* KeyBoard FilTer */
88#define ASUS_WMI_METHODID_INIT 0x54494E49 /* INITialize */
89#define ASUS_WMI_METHODID_HKEY 0x59454B48 /* Hot KEY ?? */
90
91#define ASUS_WMI_UNSUPPORTED_METHOD 0xFFFFFFFE
92
93/* Wireless */
94#define ASUS_WMI_DEVID_HW_SWITCH 0x00010001
95#define ASUS_WMI_DEVID_WIRELESS_LED 0x00010002
96#define ASUS_WMI_DEVID_WLAN 0x00010011
97#define ASUS_WMI_DEVID_BLUETOOTH 0x00010013
98#define ASUS_WMI_DEVID_GPS 0x00010015
99#define ASUS_WMI_DEVID_WIMAX 0x00010017
100#define ASUS_WMI_DEVID_WWAN3G 0x00010019
101#define ASUS_WMI_DEVID_UWB 0x00010021
102
103/* Leds */
104/* 0x000200XX and 0x000400XX */
105
106/* Backlight and Brightness */
107#define ASUS_WMI_DEVID_BACKLIGHT 0x00050011
108#define ASUS_WMI_DEVID_BRIGHTNESS 0x00050012
109#define ASUS_WMI_DEVID_KBD_BACKLIGHT 0x00050021
110#define ASUS_WMI_DEVID_LIGHT_SENSOR 0x00050022 /* ?? */
111
112/* Misc */
113#define ASUS_WMI_DEVID_CAMERA 0x00060013
114
115/* Storage */
116#define ASUS_WMI_DEVID_CARDREADER 0x00080013
117
118/* Input */
119#define ASUS_WMI_DEVID_TOUCHPAD 0x00100011
120#define ASUS_WMI_DEVID_TOUCHPAD_LED 0x00100012
121
122/* Fan, Thermal */
123#define ASUS_WMI_DEVID_THERMAL_CTRL 0x00110011
124#define ASUS_WMI_DEVID_FAN_CTRL 0x00110012
125
126/* Power */
127#define ASUS_WMI_DEVID_PROCESSOR_STATE 0x00120012
128
129/* DSTS masks */
130#define ASUS_WMI_DSTS_STATUS_BIT 0x00000001
131#define ASUS_WMI_DSTS_UNKNOWN_BIT 0x00000002
132#define ASUS_WMI_DSTS_PRESENCE_BIT 0x00010000
133#define ASUS_WMI_DSTS_USER_BIT 0x00020000
134#define ASUS_WMI_DSTS_BIOS_BIT 0x00040000
135#define ASUS_WMI_DSTS_BRIGHTNESS_MASK 0x000000FF
136#define ASUS_WMI_DSTS_MAX_BRIGTH_MASK 0x0000FF00
137
138struct bios_args {
139 u32 arg0;
140 u32 arg1;
141} __packed;
142
143/*
144 * <platform>/ - debugfs root directory
145 * dev_id - current dev_id
146 * ctrl_param - current ctrl_param
147 * method_id - current method_id
148 * devs - call DEVS(dev_id, ctrl_param) and print result
149 * dsts - call DSTS(dev_id) and print result
150 * call - call method_id(dev_id, ctrl_param) and print result
151 */
152struct asus_wmi_debug {
153 struct dentry *root;
154 u32 method_id;
155 u32 dev_id;
156 u32 ctrl_param;
157};
158
159struct asus_rfkill {
160 struct asus_wmi *asus;
161 struct rfkill *rfkill;
162 u32 dev_id;
163};
164
165struct asus_wmi {
166 int dsts_id;
167 int spec;
168 int sfun;
169
170 struct input_dev *inputdev;
171 struct backlight_device *backlight_device;
172 struct device *hwmon_device;
173 struct platform_device *platform_device;
174
175 struct led_classdev tpd_led;
176 int tpd_led_wk;
177 struct workqueue_struct *led_workqueue;
178 struct work_struct tpd_led_work;
179
180 struct asus_rfkill wlan;
181 struct asus_rfkill bluetooth;
182 struct asus_rfkill wimax;
183 struct asus_rfkill wwan3g;
184
185 struct hotplug_slot *hotplug_slot;
186 struct mutex hotplug_lock;
187 struct mutex wmi_lock;
188 struct workqueue_struct *hotplug_workqueue;
189 struct work_struct hotplug_work;
190
191 struct asus_wmi_debug debug;
192
193 struct asus_wmi_driver *driver;
194};
195
196static int asus_wmi_input_init(struct asus_wmi *asus)
197{
198 int err;
199
200 asus->inputdev = input_allocate_device();
201 if (!asus->inputdev)
202 return -ENOMEM;
203
204 asus->inputdev->name = asus->driver->input_name;
205 asus->inputdev->phys = asus->driver->input_phys;
206 asus->inputdev->id.bustype = BUS_HOST;
207 asus->inputdev->dev.parent = &asus->platform_device->dev;
208
209 err = sparse_keymap_setup(asus->inputdev, asus->driver->keymap, NULL);
210 if (err)
211 goto err_free_dev;
212
213 err = input_register_device(asus->inputdev);
214 if (err)
215 goto err_free_keymap;
216
217 return 0;
218
219err_free_keymap:
220 sparse_keymap_free(asus->inputdev);
221err_free_dev:
222 input_free_device(asus->inputdev);
223 return err;
224}
225
226static void asus_wmi_input_exit(struct asus_wmi *asus)
227{
228 if (asus->inputdev) {
229 sparse_keymap_free(asus->inputdev);
230 input_unregister_device(asus->inputdev);
231 }
232
233 asus->inputdev = NULL;
234}
235
236static int asus_wmi_evaluate_method(u32 method_id, u32 arg0, u32 arg1,
237 u32 *retval)
238{
239 struct bios_args args = {
240 .arg0 = arg0,
241 .arg1 = arg1,
242 };
243 struct acpi_buffer input = { (acpi_size) sizeof(args), &args };
244 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
245 acpi_status status;
246 union acpi_object *obj;
247 u32 tmp;
248
249 status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID, 1, method_id,
250 &input, &output);
251
252 if (ACPI_FAILURE(status))
253 goto exit;
254
255 obj = (union acpi_object *)output.pointer;
256 if (obj && obj->type == ACPI_TYPE_INTEGER)
257 tmp = (u32) obj->integer.value;
258 else
259 tmp = 0;
260
261 if (retval)
262 *retval = tmp;
263
264 kfree(obj);
265
266exit:
267 if (ACPI_FAILURE(status))
268 return -EIO;
269
270 if (tmp == ASUS_WMI_UNSUPPORTED_METHOD)
271 return -ENODEV;
272
273 return 0;
274}
275
276static int asus_wmi_get_devstate(struct asus_wmi *asus, u32 dev_id, u32 *retval)
277{
278 return asus_wmi_evaluate_method(asus->dsts_id, dev_id, 0, retval);
279}
280
281static int asus_wmi_set_devstate(u32 dev_id, u32 ctrl_param,
282 u32 *retval)
283{
284 return asus_wmi_evaluate_method(ASUS_WMI_METHODID_DEVS, dev_id,
285 ctrl_param, retval);
286}
287
288/* Helper for special devices with magic return codes */
289static int asus_wmi_get_devstate_bits(struct asus_wmi *asus,
290 u32 dev_id, u32 mask)
291{
292 u32 retval = 0;
293 int err;
294
295 err = asus_wmi_get_devstate(asus, dev_id, &retval);
296
297 if (err < 0)
298 return err;
299
300 if (!(retval & ASUS_WMI_DSTS_PRESENCE_BIT))
301 return -ENODEV;
302
303 if (mask == ASUS_WMI_DSTS_STATUS_BIT) {
304 if (retval & ASUS_WMI_DSTS_UNKNOWN_BIT)
305 return -ENODEV;
306 }
307
308 return retval & mask;
309}
310
311static int asus_wmi_get_devstate_simple(struct asus_wmi *asus, u32 dev_id)
312{
313 return asus_wmi_get_devstate_bits(asus, dev_id,
314 ASUS_WMI_DSTS_STATUS_BIT);
315}
316
317/*
318 * LEDs
319 */
320/*
321 * These functions actually update the LED's, and are called from a
322 * workqueue. By doing this as separate work rather than when the LED
323 * subsystem asks, we avoid messing with the Asus ACPI stuff during a
324 * potentially bad time, such as a timer interrupt.
325 */
326static void tpd_led_update(struct work_struct *work)
327{
328 int ctrl_param;
329 struct asus_wmi *asus;
330
331 asus = container_of(work, struct asus_wmi, tpd_led_work);
332
333 ctrl_param = asus->tpd_led_wk;
334 asus_wmi_set_devstate(ASUS_WMI_DEVID_TOUCHPAD_LED, ctrl_param, NULL);
335}
336
337static void tpd_led_set(struct led_classdev *led_cdev,
338 enum led_brightness value)
339{
340 struct asus_wmi *asus;
341
342 asus = container_of(led_cdev, struct asus_wmi, tpd_led);
343
344 asus->tpd_led_wk = !!value;
345 queue_work(asus->led_workqueue, &asus->tpd_led_work);
346}
347
348static int read_tpd_led_state(struct asus_wmi *asus)
349{
350 return asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_TOUCHPAD_LED);
351}
352
353static enum led_brightness tpd_led_get(struct led_classdev *led_cdev)
354{
355 struct asus_wmi *asus;
356
357 asus = container_of(led_cdev, struct asus_wmi, tpd_led);
358
359 return read_tpd_led_state(asus);
360}
361
362static int asus_wmi_led_init(struct asus_wmi *asus)
363{
364 int rv;
365
366 if (read_tpd_led_state(asus) < 0)
367 return 0;
368
369 asus->led_workqueue = create_singlethread_workqueue("led_workqueue");
370 if (!asus->led_workqueue)
371 return -ENOMEM;
372 INIT_WORK(&asus->tpd_led_work, tpd_led_update);
373
374 asus->tpd_led.name = "asus::touchpad";
375 asus->tpd_led.brightness_set = tpd_led_set;
376 asus->tpd_led.brightness_get = tpd_led_get;
377 asus->tpd_led.max_brightness = 1;
378
379 rv = led_classdev_register(&asus->platform_device->dev, &asus->tpd_led);
380 if (rv) {
381 destroy_workqueue(asus->led_workqueue);
382 return rv;
383 }
384
385 return 0;
386}
387
388static void asus_wmi_led_exit(struct asus_wmi *asus)
389{
390 if (asus->tpd_led.dev)
391 led_classdev_unregister(&asus->tpd_led);
392 if (asus->led_workqueue)
393 destroy_workqueue(asus->led_workqueue);
394}
395
396/*
397 * PCI hotplug (for wlan rfkill)
398 */
399static bool asus_wlan_rfkill_blocked(struct asus_wmi *asus)
400{
401 int result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WLAN);
402
403 if (result < 0)
404 return false;
405 return !result;
406}
407
408static void asus_rfkill_hotplug(struct asus_wmi *asus)
409{
410 struct pci_dev *dev;
411 struct pci_bus *bus;
412 bool blocked;
413 bool absent;
414 u32 l;
415
416 mutex_lock(&asus->wmi_lock);
417 blocked = asus_wlan_rfkill_blocked(asus);
418 mutex_unlock(&asus->wmi_lock);
419
420 mutex_lock(&asus->hotplug_lock);
421
422 if (asus->wlan.rfkill)
423 rfkill_set_sw_state(asus->wlan.rfkill, blocked);
424
425 if (asus->hotplug_slot) {
426 bus = pci_find_bus(0, 1);
427 if (!bus) {
428 pr_warn("Unable to find PCI bus 1?\n");
429 goto out_unlock;
430 }
431
432 if (pci_bus_read_config_dword(bus, 0, PCI_VENDOR_ID, &l)) {
433 pr_err("Unable to read PCI config space?\n");
434 goto out_unlock;
435 }
436 absent = (l == 0xffffffff);
437
438 if (blocked != absent) {
439 pr_warn("BIOS says wireless lan is %s, "
440 "but the pci device is %s\n",
441 blocked ? "blocked" : "unblocked",
442 absent ? "absent" : "present");
443 pr_warn("skipped wireless hotplug as probably "
444 "inappropriate for this model\n");
445 goto out_unlock;
446 }
447
448 if (!blocked) {
449 dev = pci_get_slot(bus, 0);
450 if (dev) {
451 /* Device already present */
452 pci_dev_put(dev);
453 goto out_unlock;
454 }
455 dev = pci_scan_single_device(bus, 0);
456 if (dev) {
457 pci_bus_assign_resources(bus);
458 if (pci_bus_add_device(dev))
459 pr_err("Unable to hotplug wifi\n");
460 }
461 } else {
462 dev = pci_get_slot(bus, 0);
463 if (dev) {
464 pci_remove_bus_device(dev);
465 pci_dev_put(dev);
466 }
467 }
468 }
469
470out_unlock:
471 mutex_unlock(&asus->hotplug_lock);
472}
473
474static void asus_rfkill_notify(acpi_handle handle, u32 event, void *data)
475{
476 struct asus_wmi *asus = data;
477
478 if (event != ACPI_NOTIFY_BUS_CHECK)
479 return;
480
481 /*
482 * We can't call directly asus_rfkill_hotplug because most
483 * of the time WMBC is still being executed and not reetrant.
484 * There is currently no way to tell ACPICA that we want this
485 * method to be serialized, we schedule a asus_rfkill_hotplug
486 * call later, in a safer context.
487 */
488 queue_work(asus->hotplug_workqueue, &asus->hotplug_work);
489}
490
491static int asus_register_rfkill_notifier(struct asus_wmi *asus, char *node)
492{
493 acpi_status status;
494 acpi_handle handle;
495
496 status = acpi_get_handle(NULL, node, &handle);
497
498 if (ACPI_SUCCESS(status)) {
499 status = acpi_install_notify_handler(handle,
500 ACPI_SYSTEM_NOTIFY,
501 asus_rfkill_notify, asus);
502 if (ACPI_FAILURE(status))
503 pr_warn("Failed to register notify on %s\n", node);
504 } else
505 return -ENODEV;
506
507 return 0;
508}
509
510static void asus_unregister_rfkill_notifier(struct asus_wmi *asus, char *node)
511{
512 acpi_status status = AE_OK;
513 acpi_handle handle;
514
515 status = acpi_get_handle(NULL, node, &handle);
516
517 if (ACPI_SUCCESS(status)) {
518 status = acpi_remove_notify_handler(handle,
519 ACPI_SYSTEM_NOTIFY,
520 asus_rfkill_notify);
521 if (ACPI_FAILURE(status))
522 pr_err("Error removing rfkill notify handler %s\n",
523 node);
524 }
525}
526
527static int asus_get_adapter_status(struct hotplug_slot *hotplug_slot,
528 u8 *value)
529{
530 struct asus_wmi *asus = hotplug_slot->private;
531 int result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WLAN);
532
533 if (result < 0)
534 return result;
535
536 *value = !!result;
537 return 0;
538}
539
540static void asus_cleanup_pci_hotplug(struct hotplug_slot *hotplug_slot)
541{
542 kfree(hotplug_slot->info);
543 kfree(hotplug_slot);
544}
545
546static struct hotplug_slot_ops asus_hotplug_slot_ops = {
547 .owner = THIS_MODULE,
548 .get_adapter_status = asus_get_adapter_status,
549 .get_power_status = asus_get_adapter_status,
550};
551
552static void asus_hotplug_work(struct work_struct *work)
553{
554 struct asus_wmi *asus;
555
556 asus = container_of(work, struct asus_wmi, hotplug_work);
557 asus_rfkill_hotplug(asus);
558}
559
560static int asus_setup_pci_hotplug(struct asus_wmi *asus)
561{
562 int ret = -ENOMEM;
563 struct pci_bus *bus = pci_find_bus(0, 1);
564
565 if (!bus) {
566 pr_err("Unable to find wifi PCI bus\n");
567 return -ENODEV;
568 }
569
570 asus->hotplug_workqueue =
571 create_singlethread_workqueue("hotplug_workqueue");
572 if (!asus->hotplug_workqueue)
573 goto error_workqueue;
574
575 INIT_WORK(&asus->hotplug_work, asus_hotplug_work);
576
577 asus->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
578 if (!asus->hotplug_slot)
579 goto error_slot;
580
581 asus->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info),
582 GFP_KERNEL);
583 if (!asus->hotplug_slot->info)
584 goto error_info;
585
586 asus->hotplug_slot->private = asus;
587 asus->hotplug_slot->release = &asus_cleanup_pci_hotplug;
588 asus->hotplug_slot->ops = &asus_hotplug_slot_ops;
589 asus_get_adapter_status(asus->hotplug_slot,
590 &asus->hotplug_slot->info->adapter_status);
591
592 ret = pci_hp_register(asus->hotplug_slot, bus, 0, "asus-wifi");
593 if (ret) {
594 pr_err("Unable to register hotplug slot - %d\n", ret);
595 goto error_register;
596 }
597
598 return 0;
599
600error_register:
601 kfree(asus->hotplug_slot->info);
602error_info:
603 kfree(asus->hotplug_slot);
604 asus->hotplug_slot = NULL;
605error_slot:
606 destroy_workqueue(asus->hotplug_workqueue);
607error_workqueue:
608 return ret;
609}
610
611/*
612 * Rfkill devices
613 */
614static int asus_rfkill_set(void *data, bool blocked)
615{
616 struct asus_rfkill *priv = data;
617 u32 ctrl_param = !blocked;
618
619 return asus_wmi_set_devstate(priv->dev_id, ctrl_param, NULL);
620}
621
622static void asus_rfkill_query(struct rfkill *rfkill, void *data)
623{
624 struct asus_rfkill *priv = data;
625 int result;
626
627 result = asus_wmi_get_devstate_simple(priv->asus, priv->dev_id);
628
629 if (result < 0)
630 return;
631
632 rfkill_set_sw_state(priv->rfkill, !result);
633}
634
635static int asus_rfkill_wlan_set(void *data, bool blocked)
636{
637 struct asus_rfkill *priv = data;
638 struct asus_wmi *asus = priv->asus;
639 int ret;
640
641 /*
642 * This handler is enabled only if hotplug is enabled.
643 * In this case, the asus_wmi_set_devstate() will
644 * trigger a wmi notification and we need to wait
645 * this call to finish before being able to call
646 * any wmi method
647 */
648 mutex_lock(&asus->wmi_lock);
649 ret = asus_rfkill_set(data, blocked);
650 mutex_unlock(&asus->wmi_lock);
651 return ret;
652}
653
654static const struct rfkill_ops asus_rfkill_wlan_ops = {
655 .set_block = asus_rfkill_wlan_set,
656 .query = asus_rfkill_query,
657};
658
659static const struct rfkill_ops asus_rfkill_ops = {
660 .set_block = asus_rfkill_set,
661 .query = asus_rfkill_query,
662};
663
664static int asus_new_rfkill(struct asus_wmi *asus,
665 struct asus_rfkill *arfkill,
666 const char *name, enum rfkill_type type, int dev_id)
667{
668 int result = asus_wmi_get_devstate_simple(asus, dev_id);
669 struct rfkill **rfkill = &arfkill->rfkill;
670
671 if (result < 0)
672 return result;
673
674 arfkill->dev_id = dev_id;
675 arfkill->asus = asus;
676
677 if (dev_id == ASUS_WMI_DEVID_WLAN && asus->driver->hotplug_wireless)
678 *rfkill = rfkill_alloc(name, &asus->platform_device->dev, type,
679 &asus_rfkill_wlan_ops, arfkill);
680 else
681 *rfkill = rfkill_alloc(name, &asus->platform_device->dev, type,
682 &asus_rfkill_ops, arfkill);
683
684 if (!*rfkill)
685 return -EINVAL;
686
687 rfkill_init_sw_state(*rfkill, !result);
688 result = rfkill_register(*rfkill);
689 if (result) {
690 rfkill_destroy(*rfkill);
691 *rfkill = NULL;
692 return result;
693 }
694 return 0;
695}
696
697static void asus_wmi_rfkill_exit(struct asus_wmi *asus)
698{
699 asus_unregister_rfkill_notifier(asus, "\\_SB.PCI0.P0P5");
700 asus_unregister_rfkill_notifier(asus, "\\_SB.PCI0.P0P6");
701 asus_unregister_rfkill_notifier(asus, "\\_SB.PCI0.P0P7");
702 if (asus->wlan.rfkill) {
703 rfkill_unregister(asus->wlan.rfkill);
704 rfkill_destroy(asus->wlan.rfkill);
705 asus->wlan.rfkill = NULL;
706 }
707 /*
708 * Refresh pci hotplug in case the rfkill state was changed after
709 * asus_unregister_rfkill_notifier()
710 */
711 asus_rfkill_hotplug(asus);
712 if (asus->hotplug_slot)
713 pci_hp_deregister(asus->hotplug_slot);
714 if (asus->hotplug_workqueue)
715 destroy_workqueue(asus->hotplug_workqueue);
716
717 if (asus->bluetooth.rfkill) {
718 rfkill_unregister(asus->bluetooth.rfkill);
719 rfkill_destroy(asus->bluetooth.rfkill);
720 asus->bluetooth.rfkill = NULL;
721 }
722 if (asus->wimax.rfkill) {
723 rfkill_unregister(asus->wimax.rfkill);
724 rfkill_destroy(asus->wimax.rfkill);
725 asus->wimax.rfkill = NULL;
726 }
727 if (asus->wwan3g.rfkill) {
728 rfkill_unregister(asus->wwan3g.rfkill);
729 rfkill_destroy(asus->wwan3g.rfkill);
730 asus->wwan3g.rfkill = NULL;
731 }
732}
733
734static int asus_wmi_rfkill_init(struct asus_wmi *asus)
735{
736 int result = 0;
737
738 mutex_init(&asus->hotplug_lock);
739 mutex_init(&asus->wmi_lock);
740
741 result = asus_new_rfkill(asus, &asus->wlan, "asus-wlan",
742 RFKILL_TYPE_WLAN, ASUS_WMI_DEVID_WLAN);
743
744 if (result && result != -ENODEV)
745 goto exit;
746
747 result = asus_new_rfkill(asus, &asus->bluetooth,
748 "asus-bluetooth", RFKILL_TYPE_BLUETOOTH,
749 ASUS_WMI_DEVID_BLUETOOTH);
750
751 if (result && result != -ENODEV)
752 goto exit;
753
754 result = asus_new_rfkill(asus, &asus->wimax, "asus-wimax",
755 RFKILL_TYPE_WIMAX, ASUS_WMI_DEVID_WIMAX);
756
757 if (result && result != -ENODEV)
758 goto exit;
759
760 result = asus_new_rfkill(asus, &asus->wwan3g, "asus-wwan3g",
761 RFKILL_TYPE_WWAN, ASUS_WMI_DEVID_WWAN3G);
762
763 if (result && result != -ENODEV)
764 goto exit;
765
766 if (!asus->driver->hotplug_wireless)
767 goto exit;
768
769 result = asus_setup_pci_hotplug(asus);
770 /*
771 * If we get -EBUSY then something else is handling the PCI hotplug -
772 * don't fail in this case
773 */
774 if (result == -EBUSY)
775 result = 0;
776
777 asus_register_rfkill_notifier(asus, "\\_SB.PCI0.P0P5");
778 asus_register_rfkill_notifier(asus, "\\_SB.PCI0.P0P6");
779 asus_register_rfkill_notifier(asus, "\\_SB.PCI0.P0P7");
780 /*
781 * Refresh pci hotplug in case the rfkill state was changed during
782 * setup.
783 */
784 asus_rfkill_hotplug(asus);
785
786exit:
787 if (result && result != -ENODEV)
788 asus_wmi_rfkill_exit(asus);
789
790 if (result == -ENODEV)
791 result = 0;
792
793 return result;
794}
795
796/*
797 * Hwmon device
798 */
799static ssize_t asus_hwmon_pwm1(struct device *dev,
800 struct device_attribute *attr,
801 char *buf)
802{
803 struct asus_wmi *asus = dev_get_drvdata(dev);
804 u32 value;
805 int err;
806
807 err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_FAN_CTRL, &value);
808
809 if (err < 0)
810 return err;
811
812 value |= 0xFF;
813
814 if (value == 1) /* Low Speed */
815 value = 85;
816 else if (value == 2)
817 value = 170;
818 else if (value == 3)
819 value = 255;
820 else if (value != 0) {
821 pr_err("Unknown fan speed %#x", value);
822 value = -1;
823 }
824
825 return sprintf(buf, "%d\n", value);
826}
827
828static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO, asus_hwmon_pwm1, NULL, 0);
829
830static ssize_t
831show_name(struct device *dev, struct device_attribute *attr, char *buf)
832{
833 return sprintf(buf, "asus\n");
834}
835static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0);
836
837static struct attribute *hwmon_attributes[] = {
838 &sensor_dev_attr_pwm1.dev_attr.attr,
839 &sensor_dev_attr_name.dev_attr.attr,
840 NULL
841};
842
843static mode_t asus_hwmon_sysfs_is_visible(struct kobject *kobj,
844 struct attribute *attr, int idx)
845{
846 struct device *dev = container_of(kobj, struct device, kobj);
847 struct platform_device *pdev = to_platform_device(dev->parent);
848 struct asus_wmi *asus = platform_get_drvdata(pdev);
849 bool ok = true;
850 int dev_id = -1;
851 u32 value = ASUS_WMI_UNSUPPORTED_METHOD;
852
853 if (attr == &sensor_dev_attr_pwm1.dev_attr.attr)
854 dev_id = ASUS_WMI_DEVID_FAN_CTRL;
855
856 if (dev_id != -1) {
857 int err = asus_wmi_get_devstate(asus, dev_id, &value);
858
859 if (err < 0)
860 return err;
861 }
862
863 if (dev_id == ASUS_WMI_DEVID_FAN_CTRL) {
864 /*
865 * We need to find a better way, probably using sfun,
866 * bits or spec ...
867 * Currently we disable it if:
868 * - ASUS_WMI_UNSUPPORTED_METHOD is returned
869 * - reverved bits are non-zero
870 * - sfun and presence bit are not set
871 */
872 if (value != ASUS_WMI_UNSUPPORTED_METHOD || value & 0xFFF80000
873 || (!asus->sfun && !(value & ASUS_WMI_DSTS_PRESENCE_BIT)))
874 ok = false;
875 }
876
877 return ok ? attr->mode : 0;
878}
879
880static struct attribute_group hwmon_attribute_group = {
881 .is_visible = asus_hwmon_sysfs_is_visible,
882 .attrs = hwmon_attributes
883};
884
885static void asus_wmi_hwmon_exit(struct asus_wmi *asus)
886{
887 struct device *hwmon;
888
889 hwmon = asus->hwmon_device;
890 if (!hwmon)
891 return;
892 sysfs_remove_group(&hwmon->kobj, &hwmon_attribute_group);
893 hwmon_device_unregister(hwmon);
894 asus->hwmon_device = NULL;
895}
896
897static int asus_wmi_hwmon_init(struct asus_wmi *asus)
898{
899 struct device *hwmon;
900 int result;
901
902 hwmon = hwmon_device_register(&asus->platform_device->dev);
903 if (IS_ERR(hwmon)) {
904 pr_err("Could not register asus hwmon device\n");
905 return PTR_ERR(hwmon);
906 }
907 asus->hwmon_device = hwmon;
908 result = sysfs_create_group(&hwmon->kobj, &hwmon_attribute_group);
909 if (result)
910 asus_wmi_hwmon_exit(asus);
911 return result;
912}
913
914/*
915 * Backlight
916 */
917static int read_backlight_power(struct asus_wmi *asus)
918{
919 int ret = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_BACKLIGHT);
920
921 if (ret < 0)
922 return ret;
923
924 return ret ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
925}
926
927static int read_brightness_max(struct asus_wmi *asus)
928{
929 u32 retval;
930 int err;
931
932 err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_BRIGHTNESS, &retval);
933
934 if (err < 0)
935 return err;
936
937 retval = retval & ASUS_WMI_DSTS_MAX_BRIGTH_MASK;
938 retval >>= 8;
939
940 if (!retval)
941 return -ENODEV;
942
943 return retval;
944}
945
946static int read_brightness(struct backlight_device *bd)
947{
948 struct asus_wmi *asus = bl_get_data(bd);
949 u32 retval;
950 int err;
951
952 err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_BRIGHTNESS, &retval);
953
954 if (err < 0)
955 return err;
956
957 return retval & ASUS_WMI_DSTS_BRIGHTNESS_MASK;
958}
959
960static int update_bl_status(struct backlight_device *bd)
961{
962 struct asus_wmi *asus = bl_get_data(bd);
963 u32 ctrl_param;
964 int power, err;
965
966 ctrl_param = bd->props.brightness;
967
968 err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BRIGHTNESS,
969 ctrl_param, NULL);
970
971 if (err < 0)
972 return err;
973
974 power = read_backlight_power(asus);
975 if (power != -ENODEV && bd->props.power != power) {
976 ctrl_param = !!(bd->props.power == FB_BLANK_UNBLANK);
977 err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BACKLIGHT,
978 ctrl_param, NULL);
979 }
980 return err;
981}
982
983static const struct backlight_ops asus_wmi_bl_ops = {
984 .get_brightness = read_brightness,
985 .update_status = update_bl_status,
986};
987
988static int asus_wmi_backlight_notify(struct asus_wmi *asus, int code)
989{
990 struct backlight_device *bd = asus->backlight_device;
991 int old = bd->props.brightness;
992 int new = old;
993
994 if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX)
995 new = code - NOTIFY_BRNUP_MIN + 1;
996 else if (code >= NOTIFY_BRNDOWN_MIN && code <= NOTIFY_BRNDOWN_MAX)
997 new = code - NOTIFY_BRNDOWN_MIN;
998
999 bd->props.brightness = new;
1000 backlight_update_status(bd);
1001 backlight_force_update(bd, BACKLIGHT_UPDATE_HOTKEY);
1002
1003 return old;
1004}
1005
1006static int asus_wmi_backlight_init(struct asus_wmi *asus)
1007{
1008 struct backlight_device *bd;
1009 struct backlight_properties props;
1010 int max;
1011 int power;
1012
1013 max = read_brightness_max(asus);
1014
1015 if (max == -ENODEV)
1016 max = 0;
1017 else if (max < 0)
1018 return max;
1019
1020 power = read_backlight_power(asus);
1021
1022 if (power == -ENODEV)
1023 power = FB_BLANK_UNBLANK;
1024 else if (power < 0)
1025 return power;
1026
1027 memset(&props, 0, sizeof(struct backlight_properties));
1028 props.type = BACKLIGHT_PLATFORM;
1029 props.max_brightness = max;
1030 bd = backlight_device_register(asus->driver->name,
1031 &asus->platform_device->dev, asus,
1032 &asus_wmi_bl_ops, &props);
1033 if (IS_ERR(bd)) {
1034 pr_err("Could not register backlight device\n");
1035 return PTR_ERR(bd);
1036 }
1037
1038 asus->backlight_device = bd;
1039
1040 bd->props.brightness = read_brightness(bd);
1041 bd->props.power = power;
1042 backlight_update_status(bd);
1043
1044 return 0;
1045}
1046
1047static void asus_wmi_backlight_exit(struct asus_wmi *asus)
1048{
1049 if (asus->backlight_device)
1050 backlight_device_unregister(asus->backlight_device);
1051
1052 asus->backlight_device = NULL;
1053}
1054
1055static void asus_wmi_notify(u32 value, void *context)
1056{
1057 struct asus_wmi *asus = context;
1058 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
1059 union acpi_object *obj;
1060 acpi_status status;
1061 int code;
1062 int orig_code;
1063
1064 status = wmi_get_event_data(value, &response);
1065 if (status != AE_OK) {
1066 pr_err("bad event status 0x%x\n", status);
1067 return;
1068 }
1069
1070 obj = (union acpi_object *)response.pointer;
1071
1072 if (!obj || obj->type != ACPI_TYPE_INTEGER)
1073 goto exit;
1074
1075 code = obj->integer.value;
1076 orig_code = code;
1077
1078 if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX)
1079 code = NOTIFY_BRNUP_MIN;
1080 else if (code >= NOTIFY_BRNDOWN_MIN &&
1081 code <= NOTIFY_BRNDOWN_MAX)
1082 code = NOTIFY_BRNDOWN_MIN;
1083
1084 if (code == NOTIFY_BRNUP_MIN || code == NOTIFY_BRNDOWN_MIN) {
1085 if (!acpi_video_backlight_support())
1086 asus_wmi_backlight_notify(asus, orig_code);
1087 } else if (!sparse_keymap_report_event(asus->inputdev, code, 1, true))
1088 pr_info("Unknown key %x pressed\n", code);
1089
1090exit:
1091 kfree(obj);
1092}
1093
1094/*
1095 * Sys helpers
1096 */
1097static int parse_arg(const char *buf, unsigned long count, int *val)
1098{
1099 if (!count)
1100 return 0;
1101 if (sscanf(buf, "%i", val) != 1)
1102 return -EINVAL;
1103 return count;
1104}
1105
1106static ssize_t store_sys_wmi(struct asus_wmi *asus, int devid,
1107 const char *buf, size_t count)
1108{
1109 u32 retval;
1110 int rv, err, value;
1111
1112 value = asus_wmi_get_devstate_simple(asus, devid);
1113 if (value == -ENODEV) /* Check device presence */
1114 return value;
1115
1116 rv = parse_arg(buf, count, &value);
1117 err = asus_wmi_set_devstate(devid, value, &retval);
1118
1119 if (err < 0)
1120 return err;
1121
1122 return rv;
1123}
1124
1125static ssize_t show_sys_wmi(struct asus_wmi *asus, int devid, char *buf)
1126{
1127 int value = asus_wmi_get_devstate_simple(asus, devid);
1128
1129 if (value < 0)
1130 return value;
1131
1132 return sprintf(buf, "%d\n", value);
1133}
1134
1135#define ASUS_WMI_CREATE_DEVICE_ATTR(_name, _mode, _cm) \
1136 static ssize_t show_##_name(struct device *dev, \
1137 struct device_attribute *attr, \
1138 char *buf) \
1139 { \
1140 struct asus_wmi *asus = dev_get_drvdata(dev); \
1141 \
1142 return show_sys_wmi(asus, _cm, buf); \
1143 } \
1144 static ssize_t store_##_name(struct device *dev, \
1145 struct device_attribute *attr, \
1146 const char *buf, size_t count) \
1147 { \
1148 struct asus_wmi *asus = dev_get_drvdata(dev); \
1149 \
1150 return store_sys_wmi(asus, _cm, buf, count); \
1151 } \
1152 static struct device_attribute dev_attr_##_name = { \
1153 .attr = { \
1154 .name = __stringify(_name), \
1155 .mode = _mode }, \
1156 .show = show_##_name, \
1157 .store = store_##_name, \
1158 }
1159
1160ASUS_WMI_CREATE_DEVICE_ATTR(touchpad, 0644, ASUS_WMI_DEVID_TOUCHPAD);
1161ASUS_WMI_CREATE_DEVICE_ATTR(camera, 0644, ASUS_WMI_DEVID_CAMERA);
1162ASUS_WMI_CREATE_DEVICE_ATTR(cardr, 0644, ASUS_WMI_DEVID_CARDREADER);
1163
1164static ssize_t store_cpufv(struct device *dev, struct device_attribute *attr,
1165 const char *buf, size_t count)
1166{
1167 int value;
1168
1169 if (!count || sscanf(buf, "%i", &value) != 1)
1170 return -EINVAL;
1171 if (value < 0 || value > 2)
1172 return -EINVAL;
1173
1174 return asus_wmi_evaluate_method(ASUS_WMI_METHODID_CFVS, value, 0, NULL);
1175}
1176
1177static DEVICE_ATTR(cpufv, S_IRUGO | S_IWUSR, NULL, store_cpufv);
1178
1179static struct attribute *platform_attributes[] = {
1180 &dev_attr_cpufv.attr,
1181 &dev_attr_camera.attr,
1182 &dev_attr_cardr.attr,
1183 &dev_attr_touchpad.attr,
1184 NULL
1185};
1186
1187static mode_t asus_sysfs_is_visible(struct kobject *kobj,
1188 struct attribute *attr, int idx)
1189{
1190 struct device *dev = container_of(kobj, struct device, kobj);
1191 struct platform_device *pdev = to_platform_device(dev);
1192 struct asus_wmi *asus = platform_get_drvdata(pdev);
1193 bool ok = true;
1194 int devid = -1;
1195
1196 if (attr == &dev_attr_camera.attr)
1197 devid = ASUS_WMI_DEVID_CAMERA;
1198 else if (attr == &dev_attr_cardr.attr)
1199 devid = ASUS_WMI_DEVID_CARDREADER;
1200 else if (attr == &dev_attr_touchpad.attr)
1201 devid = ASUS_WMI_DEVID_TOUCHPAD;
1202
1203 if (devid != -1)
1204 ok = !(asus_wmi_get_devstate_simple(asus, devid) < 0);
1205
1206 return ok ? attr->mode : 0;
1207}
1208
1209static struct attribute_group platform_attribute_group = {
1210 .is_visible = asus_sysfs_is_visible,
1211 .attrs = platform_attributes
1212};
1213
1214static void asus_wmi_sysfs_exit(struct platform_device *device)
1215{
1216 sysfs_remove_group(&device->dev.kobj, &platform_attribute_group);
1217}
1218
1219static int asus_wmi_sysfs_init(struct platform_device *device)
1220{
1221 return sysfs_create_group(&device->dev.kobj, &platform_attribute_group);
1222}
1223
1224/*
1225 * Platform device
1226 */
1227static int asus_wmi_platform_init(struct asus_wmi *asus)
1228{
1229 int rv;
1230
1231 /* INIT enable hotkeys on some models */
1232 if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_INIT, 0, 0, &rv))
1233 pr_info("Initialization: %#x", rv);
1234
1235 /* We don't know yet what to do with this version... */
1236 if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_SPEC, 0, 0x9, &rv)) {
1237 pr_info("BIOS WMI version: %d.%d", rv >> 8, rv & 0xFF);
1238 asus->spec = rv;
1239 }
1240
1241 /*
1242 * The SFUN method probably allows the original driver to get the list
1243 * of features supported by a given model. For now, 0x0100 or 0x0800
1244 * bit signifies that the laptop is equipped with a Wi-Fi MiniPCI card.
1245 * The significance of others is yet to be found.
1246 */
1247 if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_SFUN, 0, 0, &rv)) {
1248 pr_info("SFUN value: %#x", rv);
1249 asus->sfun = rv;
1250 }
1251
1252 /*
1253 * Eee PC and Notebooks seems to have different method_id for DSTS,
1254 * but it may also be related to the BIOS's SPEC.
1255 * Note, on most Eeepc, there is no way to check if a method exist
1256 * or note, while on notebooks, they returns 0xFFFFFFFE on failure,
1257 * but once again, SPEC may probably be used for that kind of things.
1258 */
1259 if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS, 0, 0, NULL))
1260 asus->dsts_id = ASUS_WMI_METHODID_DSTS;
1261 else if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS2, 0, 0, NULL))
1262 asus->dsts_id = ASUS_WMI_METHODID_DSTS2;
1263
1264 if (!asus->dsts_id) {
1265 pr_err("Can't find DSTS");
1266 return -ENODEV;
1267 }
1268
1269 return asus_wmi_sysfs_init(asus->platform_device);
1270}
1271
1272static void asus_wmi_platform_exit(struct asus_wmi *asus)
1273{
1274 asus_wmi_sysfs_exit(asus->platform_device);
1275}
1276
1277/*
1278 * debugfs
1279 */
1280struct asus_wmi_debugfs_node {
1281 struct asus_wmi *asus;
1282 char *name;
1283 int (*show) (struct seq_file *m, void *data);
1284};
1285
1286static int show_dsts(struct seq_file *m, void *data)
1287{
1288 struct asus_wmi *asus = m->private;
1289 int err;
1290 u32 retval = -1;
1291
1292 err = asus_wmi_get_devstate(asus, asus->debug.dev_id, &retval);
1293
1294 if (err < 0)
1295 return err;
1296
1297 seq_printf(m, "DSTS(%#x) = %#x\n", asus->debug.dev_id, retval);
1298
1299 return 0;
1300}
1301
1302static int show_devs(struct seq_file *m, void *data)
1303{
1304 struct asus_wmi *asus = m->private;
1305 int err;
1306 u32 retval = -1;
1307
1308 err = asus_wmi_set_devstate(asus->debug.dev_id, asus->debug.ctrl_param,
1309 &retval);
1310
1311 if (err < 0)
1312 return err;
1313
1314 seq_printf(m, "DEVS(%#x, %#x) = %#x\n", asus->debug.dev_id,
1315 asus->debug.ctrl_param, retval);
1316
1317 return 0;
1318}
1319
1320static int show_call(struct seq_file *m, void *data)
1321{
1322 struct asus_wmi *asus = m->private;
1323 struct bios_args args = {
1324 .arg0 = asus->debug.dev_id,
1325 .arg1 = asus->debug.ctrl_param,
1326 };
1327 struct acpi_buffer input = { (acpi_size) sizeof(args), &args };
1328 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
1329 union acpi_object *obj;
1330 acpi_status status;
1331
1332 status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID,
1333 1, asus->debug.method_id,
1334 &input, &output);
1335
1336 if (ACPI_FAILURE(status))
1337 return -EIO;
1338
1339 obj = (union acpi_object *)output.pointer;
1340 if (obj && obj->type == ACPI_TYPE_INTEGER)
1341 seq_printf(m, "%#x(%#x, %#x) = %#x\n", asus->debug.method_id,
1342 asus->debug.dev_id, asus->debug.ctrl_param,
1343 (u32) obj->integer.value);
1344 else
1345 seq_printf(m, "%#x(%#x, %#x) = t:%d\n", asus->debug.method_id,
1346 asus->debug.dev_id, asus->debug.ctrl_param,
1347 obj ? obj->type : -1);
1348
1349 kfree(obj);
1350
1351 return 0;
1352}
1353
1354static struct asus_wmi_debugfs_node asus_wmi_debug_files[] = {
1355 {NULL, "devs", show_devs},
1356 {NULL, "dsts", show_dsts},
1357 {NULL, "call", show_call},
1358};
1359
1360static int asus_wmi_debugfs_open(struct inode *inode, struct file *file)
1361{
1362 struct asus_wmi_debugfs_node *node = inode->i_private;
1363
1364 return single_open(file, node->show, node->asus);
1365}
1366
1367static const struct file_operations asus_wmi_debugfs_io_ops = {
1368 .owner = THIS_MODULE,
1369 .open = asus_wmi_debugfs_open,
1370 .read = seq_read,
1371 .llseek = seq_lseek,
1372 .release = single_release,
1373};
1374
1375static void asus_wmi_debugfs_exit(struct asus_wmi *asus)
1376{
1377 debugfs_remove_recursive(asus->debug.root);
1378}
1379
1380static int asus_wmi_debugfs_init(struct asus_wmi *asus)
1381{
1382 struct dentry *dent;
1383 int i;
1384
1385 asus->debug.root = debugfs_create_dir(asus->driver->name, NULL);
1386 if (!asus->debug.root) {
1387 pr_err("failed to create debugfs directory");
1388 goto error_debugfs;
1389 }
1390
1391 dent = debugfs_create_x32("method_id", S_IRUGO | S_IWUSR,
1392 asus->debug.root, &asus->debug.method_id);
1393 if (!dent)
1394 goto error_debugfs;
1395
1396 dent = debugfs_create_x32("dev_id", S_IRUGO | S_IWUSR,
1397 asus->debug.root, &asus->debug.dev_id);
1398 if (!dent)
1399 goto error_debugfs;
1400
1401 dent = debugfs_create_x32("ctrl_param", S_IRUGO | S_IWUSR,
1402 asus->debug.root, &asus->debug.ctrl_param);
1403 if (!dent)
1404 goto error_debugfs;
1405
1406 for (i = 0; i < ARRAY_SIZE(asus_wmi_debug_files); i++) {
1407 struct asus_wmi_debugfs_node *node = &asus_wmi_debug_files[i];
1408
1409 node->asus = asus;
1410 dent = debugfs_create_file(node->name, S_IFREG | S_IRUGO,
1411 asus->debug.root, node,
1412 &asus_wmi_debugfs_io_ops);
1413 if (!dent) {
1414 pr_err("failed to create debug file: %s\n", node->name);
1415 goto error_debugfs;
1416 }
1417 }
1418
1419 return 0;
1420
1421error_debugfs:
1422 asus_wmi_debugfs_exit(asus);
1423 return -ENOMEM;
1424}
1425
1426/*
1427 * WMI Driver
1428 */
1429static int asus_wmi_add(struct platform_device *pdev)
1430{
1431 struct platform_driver *pdrv = to_platform_driver(pdev->dev.driver);
1432 struct asus_wmi_driver *wdrv = to_asus_wmi_driver(pdrv);
1433 struct asus_wmi *asus;
1434 acpi_status status;
1435 int err;
1436
1437 asus = kzalloc(sizeof(struct asus_wmi), GFP_KERNEL);
1438 if (!asus)
1439 return -ENOMEM;
1440
1441 asus->driver = wdrv;
1442 asus->platform_device = pdev;
1443 wdrv->platform_device = pdev;
1444 platform_set_drvdata(asus->platform_device, asus);
1445
1446 if (wdrv->quirks)
1447 wdrv->quirks(asus->driver);
1448
1449 err = asus_wmi_platform_init(asus);
1450 if (err)
1451 goto fail_platform;
1452
1453 err = asus_wmi_input_init(asus);
1454 if (err)
1455 goto fail_input;
1456
1457 err = asus_wmi_hwmon_init(asus);
1458 if (err)
1459 goto fail_hwmon;
1460
1461 err = asus_wmi_led_init(asus);
1462 if (err)
1463 goto fail_leds;
1464
1465 err = asus_wmi_rfkill_init(asus);
1466 if (err)
1467 goto fail_rfkill;
1468
1469 if (!acpi_video_backlight_support()) {
1470 err = asus_wmi_backlight_init(asus);
1471 if (err && err != -ENODEV)
1472 goto fail_backlight;
1473 } else
1474 pr_info("Backlight controlled by ACPI video driver\n");
1475
1476 status = wmi_install_notify_handler(asus->driver->event_guid,
1477 asus_wmi_notify, asus);
1478 if (ACPI_FAILURE(status)) {
1479 pr_err("Unable to register notify handler - %d\n", status);
1480 err = -ENODEV;
1481 goto fail_wmi_handler;
1482 }
1483
1484 err = asus_wmi_debugfs_init(asus);
1485 if (err)
1486 goto fail_debugfs;
1487
1488 return 0;
1489
1490fail_debugfs:
1491 wmi_remove_notify_handler(asus->driver->event_guid);
1492fail_wmi_handler:
1493 asus_wmi_backlight_exit(asus);
1494fail_backlight:
1495 asus_wmi_rfkill_exit(asus);
1496fail_rfkill:
1497 asus_wmi_led_exit(asus);
1498fail_leds:
1499 asus_wmi_hwmon_exit(asus);
1500fail_hwmon:
1501 asus_wmi_input_exit(asus);
1502fail_input:
1503 asus_wmi_platform_exit(asus);
1504fail_platform:
1505 kfree(asus);
1506 return err;
1507}
1508
1509static int asus_wmi_remove(struct platform_device *device)
1510{
1511 struct asus_wmi *asus;
1512
1513 asus = platform_get_drvdata(device);
1514 wmi_remove_notify_handler(asus->driver->event_guid);
1515 asus_wmi_backlight_exit(asus);
1516 asus_wmi_input_exit(asus);
1517 asus_wmi_hwmon_exit(asus);
1518 asus_wmi_led_exit(asus);
1519 asus_wmi_rfkill_exit(asus);
1520 asus_wmi_debugfs_exit(asus);
1521 asus_wmi_platform_exit(asus);
1522
1523 kfree(asus);
1524 return 0;
1525}
1526
1527/*
1528 * Platform driver - hibernate/resume callbacks
1529 */
1530static int asus_hotk_thaw(struct device *device)
1531{
1532 struct asus_wmi *asus = dev_get_drvdata(device);
1533
1534 if (asus->wlan.rfkill) {
1535 bool wlan;
1536
1537 /*
1538 * Work around bios bug - acpi _PTS turns off the wireless led
1539 * during suspend. Normally it restores it on resume, but
1540 * we should kick it ourselves in case hibernation is aborted.
1541 */
1542 wlan = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WLAN);
1543 asus_wmi_set_devstate(ASUS_WMI_DEVID_WLAN, wlan, NULL);
1544 }
1545
1546 return 0;
1547}
1548
1549static int asus_hotk_restore(struct device *device)
1550{
1551 struct asus_wmi *asus = dev_get_drvdata(device);
1552 int bl;
1553
1554 /* Refresh both wlan rfkill state and pci hotplug */
1555 if (asus->wlan.rfkill)
1556 asus_rfkill_hotplug(asus);
1557
1558 if (asus->bluetooth.rfkill) {
1559 bl = !asus_wmi_get_devstate_simple(asus,
1560 ASUS_WMI_DEVID_BLUETOOTH);
1561 rfkill_set_sw_state(asus->bluetooth.rfkill, bl);
1562 }
1563 if (asus->wimax.rfkill) {
1564 bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WIMAX);
1565 rfkill_set_sw_state(asus->wimax.rfkill, bl);
1566 }
1567 if (asus->wwan3g.rfkill) {
1568 bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WWAN3G);
1569 rfkill_set_sw_state(asus->wwan3g.rfkill, bl);
1570 }
1571
1572 return 0;
1573}
1574
1575static const struct dev_pm_ops asus_pm_ops = {
1576 .thaw = asus_hotk_thaw,
1577 .restore = asus_hotk_restore,
1578};
1579
1580static int asus_wmi_probe(struct platform_device *pdev)
1581{
1582 struct platform_driver *pdrv = to_platform_driver(pdev->dev.driver);
1583 struct asus_wmi_driver *wdrv = to_asus_wmi_driver(pdrv);
1584 int ret;
1585
1586 if (!wmi_has_guid(ASUS_WMI_MGMT_GUID)) {
1587 pr_warn("Management GUID not found\n");
1588 return -ENODEV;
1589 }
1590
1591 if (wdrv->event_guid && !wmi_has_guid(wdrv->event_guid)) {
1592 pr_warn("Event GUID not found\n");
1593 return -ENODEV;
1594 }
1595
1596 if (wdrv->probe) {
1597 ret = wdrv->probe(pdev);
1598 if (ret)
1599 return ret;
1600 }
1601
1602 return asus_wmi_add(pdev);
1603}
1604
1605static bool used;
1606
1607int asus_wmi_register_driver(struct asus_wmi_driver *driver)
1608{
1609 struct platform_driver *platform_driver;
1610 struct platform_device *platform_device;
1611
1612 if (used)
1613 return -EBUSY;
1614
1615 platform_driver = &driver->platform_driver;
1616 platform_driver->remove = asus_wmi_remove;
1617 platform_driver->driver.owner = driver->owner;
1618 platform_driver->driver.name = driver->name;
1619 platform_driver->driver.pm = &asus_pm_ops;
1620
1621 platform_device = platform_create_bundle(platform_driver,
1622 asus_wmi_probe,
1623 NULL, 0, NULL, 0);
1624 if (IS_ERR(platform_device))
1625 return PTR_ERR(platform_device);
1626
1627 used = true;
1628 return 0;
1629}
1630EXPORT_SYMBOL_GPL(asus_wmi_register_driver);
1631
1632void asus_wmi_unregister_driver(struct asus_wmi_driver *driver)
1633{
1634 platform_device_unregister(driver->platform_device);
1635 platform_driver_unregister(&driver->platform_driver);
1636 used = false;
1637}
1638EXPORT_SYMBOL_GPL(asus_wmi_unregister_driver);
1639
1640static int __init asus_wmi_init(void)
1641{
1642 if (!wmi_has_guid(ASUS_WMI_MGMT_GUID)) {
1643 pr_info("Asus Management GUID not found");
1644 return -ENODEV;
1645 }
1646
1647 pr_info("ASUS WMI generic driver loaded");
1648 return 0;
1649}
1650
1651static void __exit asus_wmi_exit(void)
1652{
1653 pr_info("ASUS WMI generic driver unloaded");
1654}
1655
1656module_init(asus_wmi_init);
1657module_exit(asus_wmi_exit);
diff --git a/drivers/platform/x86/asus-wmi.h b/drivers/platform/x86/asus-wmi.h
new file mode 100644
index 000000000000..c044522c8766
--- /dev/null
+++ b/drivers/platform/x86/asus-wmi.h
@@ -0,0 +1,58 @@
1/*
2 * Asus PC WMI hotkey driver
3 *
4 * Copyright(C) 2010 Intel Corporation.
5 * Copyright(C) 2010-2011 Corentin Chary <corentin.chary@gmail.com>
6 *
7 * Portions based on wistron_btns.c:
8 * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz>
9 * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org>
10 * Copyright (C) 2005 Dmitry Torokhov <dtor@mail.ru>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 */
26
27#ifndef _ASUS_WMI_H_
28#define _ASUS_WMI_H_
29
30#include <linux/platform_device.h>
31
32struct module;
33struct key_entry;
34struct asus_wmi;
35
36struct asus_wmi_driver {
37 bool hotplug_wireless;
38
39 const char *name;
40 struct module *owner;
41
42 const char *event_guid;
43
44 const struct key_entry *keymap;
45 const char *input_name;
46 const char *input_phys;
47
48 int (*probe) (struct platform_device *device);
49 void (*quirks) (struct asus_wmi_driver *driver);
50
51 struct platform_driver platform_driver;
52 struct platform_device *platform_device;
53};
54
55int asus_wmi_register_driver(struct asus_wmi_driver *driver);
56void asus_wmi_unregister_driver(struct asus_wmi_driver *driver);
57
58#endif /* !_ASUS_WMI_H_ */
diff --git a/drivers/platform/x86/asus_acpi.c b/drivers/platform/x86/asus_acpi.c
index ca05aefd03bf..d9312b3073e5 100644
--- a/drivers/platform/x86/asus_acpi.c
+++ b/drivers/platform/x86/asus_acpi.c
@@ -30,6 +30,8 @@
30 * 30 *
31 */ 31 */
32 32
33#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
34
33#include <linux/kernel.h> 35#include <linux/kernel.h>
34#include <linux/module.h> 36#include <linux/module.h>
35#include <linux/slab.h> 37#include <linux/slab.h>
@@ -581,8 +583,7 @@ static int read_led(const char *ledname, int ledmask)
581 if (read_acpi_int(NULL, ledname, &led_status)) 583 if (read_acpi_int(NULL, ledname, &led_status))
582 return led_status; 584 return led_status;
583 else 585 else
584 printk(KERN_WARNING "Asus ACPI: Error reading LED " 586 pr_warn("Error reading LED status\n");
585 "status\n");
586 } 587 }
587 return (hotk->status & ledmask) ? 1 : 0; 588 return (hotk->status & ledmask) ? 1 : 0;
588} 589}
@@ -621,8 +622,7 @@ write_led(const char __user *buffer, unsigned long count,
621 led_out = !led_out; 622 led_out = !led_out;
622 623
623 if (!write_acpi_int(hotk->handle, ledname, led_out, NULL)) 624 if (!write_acpi_int(hotk->handle, ledname, led_out, NULL))
624 printk(KERN_WARNING "Asus ACPI: LED (%s) write failed\n", 625 pr_warn("LED (%s) write failed\n", ledname);
625 ledname);
626 626
627 return rv; 627 return rv;
628} 628}
@@ -679,8 +679,7 @@ static ssize_t ledd_proc_write(struct file *file, const char __user *buffer,
679 if (rv > 0) { 679 if (rv > 0) {
680 if (!write_acpi_int 680 if (!write_acpi_int
681 (hotk->handle, hotk->methods->mt_ledd, value, NULL)) 681 (hotk->handle, hotk->methods->mt_ledd, value, NULL))
682 printk(KERN_WARNING 682 pr_warn("LED display write failed\n");
683 "Asus ACPI: LED display write failed\n");
684 else 683 else
685 hotk->ledd_status = (u32) value; 684 hotk->ledd_status = (u32) value;
686 } 685 }
@@ -838,8 +837,7 @@ static int get_lcd_state(void)
838 } else { 837 } else {
839 /* We don't have to check anything if we are here */ 838 /* We don't have to check anything if we are here */
840 if (!read_acpi_int(NULL, hotk->methods->lcd_status, &lcd)) 839 if (!read_acpi_int(NULL, hotk->methods->lcd_status, &lcd))
841 printk(KERN_WARNING 840 pr_warn("Error reading LCD status\n");
842 "Asus ACPI: Error reading LCD status\n");
843 841
844 if (hotk->model == L2D) 842 if (hotk->model == L2D)
845 lcd = ~lcd; 843 lcd = ~lcd;
@@ -871,7 +869,7 @@ static int set_lcd_state(int value)
871 the exact behaviour is simulated here */ 869 the exact behaviour is simulated here */
872 } 870 }
873 if (ACPI_FAILURE(status)) 871 if (ACPI_FAILURE(status))
874 printk(KERN_WARNING "Asus ACPI: Error switching LCD\n"); 872 pr_warn("Error switching LCD\n");
875 } 873 }
876 return 0; 874 return 0;
877 875
@@ -915,13 +913,11 @@ static int read_brightness(struct backlight_device *bd)
915 if (hotk->methods->brightness_get) { /* SPLV/GPLV laptop */ 913 if (hotk->methods->brightness_get) { /* SPLV/GPLV laptop */
916 if (!read_acpi_int(hotk->handle, hotk->methods->brightness_get, 914 if (!read_acpi_int(hotk->handle, hotk->methods->brightness_get,
917 &value)) 915 &value))
918 printk(KERN_WARNING 916 pr_warn("Error reading brightness\n");
919 "Asus ACPI: Error reading brightness\n");
920 } else if (hotk->methods->brightness_status) { /* For D1 for example */ 917 } else if (hotk->methods->brightness_status) { /* For D1 for example */
921 if (!read_acpi_int(NULL, hotk->methods->brightness_status, 918 if (!read_acpi_int(NULL, hotk->methods->brightness_status,
922 &value)) 919 &value))
923 printk(KERN_WARNING 920 pr_warn("Error reading brightness\n");
924 "Asus ACPI: Error reading brightness\n");
925 } else /* No GPLV method */ 921 } else /* No GPLV method */
926 value = hotk->brightness; 922 value = hotk->brightness;
927 return value; 923 return value;
@@ -939,8 +935,7 @@ static int set_brightness(int value)
939 if (hotk->methods->brightness_set) { 935 if (hotk->methods->brightness_set) {
940 if (!write_acpi_int(hotk->handle, hotk->methods->brightness_set, 936 if (!write_acpi_int(hotk->handle, hotk->methods->brightness_set,
941 value, NULL)) { 937 value, NULL)) {
942 printk(KERN_WARNING 938 pr_warn("Error changing brightness\n");
943 "Asus ACPI: Error changing brightness\n");
944 ret = -EIO; 939 ret = -EIO;
945 } 940 }
946 goto out; 941 goto out;
@@ -955,8 +950,7 @@ static int set_brightness(int value)
955 NULL, NULL); 950 NULL, NULL);
956 (value > 0) ? value-- : value++; 951 (value > 0) ? value-- : value++;
957 if (ACPI_FAILURE(status)) { 952 if (ACPI_FAILURE(status)) {
958 printk(KERN_WARNING 953 pr_warn("Error changing brightness\n");
959 "Asus ACPI: Error changing brightness\n");
960 ret = -EIO; 954 ret = -EIO;
961 } 955 }
962 } 956 }
@@ -1008,7 +1002,7 @@ static void set_display(int value)
1008 /* no sanity check needed for now */ 1002 /* no sanity check needed for now */
1009 if (!write_acpi_int(hotk->handle, hotk->methods->display_set, 1003 if (!write_acpi_int(hotk->handle, hotk->methods->display_set,
1010 value, NULL)) 1004 value, NULL))
1011 printk(KERN_WARNING "Asus ACPI: Error setting display\n"); 1005 pr_warn("Error setting display\n");
1012 return; 1006 return;
1013} 1007}
1014 1008
@@ -1021,8 +1015,7 @@ static int disp_proc_show(struct seq_file *m, void *v)
1021 int value = 0; 1015 int value = 0;
1022 1016
1023 if (!read_acpi_int(hotk->handle, hotk->methods->display_get, &value)) 1017 if (!read_acpi_int(hotk->handle, hotk->methods->display_get, &value))
1024 printk(KERN_WARNING 1018 pr_warn("Error reading display status\n");
1025 "Asus ACPI: Error reading display status\n");
1026 value &= 0x07; /* needed for some models, shouldn't hurt others */ 1019 value &= 0x07; /* needed for some models, shouldn't hurt others */
1027 seq_printf(m, "%d\n", value); 1020 seq_printf(m, "%d\n", value);
1028 return 0; 1021 return 0;
@@ -1068,7 +1061,7 @@ asus_proc_add(char *name, const struct file_operations *proc_fops, mode_t mode,
1068 proc = proc_create_data(name, mode, acpi_device_dir(device), 1061 proc = proc_create_data(name, mode, acpi_device_dir(device),
1069 proc_fops, acpi_driver_data(device)); 1062 proc_fops, acpi_driver_data(device));
1070 if (!proc) { 1063 if (!proc) {
1071 printk(KERN_WARNING " Unable to create %s fs entry\n", name); 1064 pr_warn(" Unable to create %s fs entry\n", name);
1072 return -1; 1065 return -1;
1073 } 1066 }
1074 proc->uid = asus_uid; 1067 proc->uid = asus_uid;
@@ -1081,18 +1074,12 @@ static int asus_hotk_add_fs(struct acpi_device *device)
1081 struct proc_dir_entry *proc; 1074 struct proc_dir_entry *proc;
1082 mode_t mode; 1075 mode_t mode;
1083 1076
1084 /*
1085 * If parameter uid or gid is not changed, keep the default setting for
1086 * our proc entries (-rw-rw-rw-) else, it means we care about security,
1087 * and then set to -rw-rw----
1088 */
1089
1090 if ((asus_uid == 0) && (asus_gid == 0)) { 1077 if ((asus_uid == 0) && (asus_gid == 0)) {
1091 mode = S_IFREG | S_IRUGO | S_IWUGO; 1078 mode = S_IFREG | S_IRUGO | S_IWUSR | S_IWGRP;
1092 } else { 1079 } else {
1093 mode = S_IFREG | S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP; 1080 mode = S_IFREG | S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP;
1094 printk(KERN_WARNING " asus_uid and asus_gid parameters are " 1081 pr_warn(" asus_uid and asus_gid parameters are "
1095 "deprecated, use chown and chmod instead!\n"); 1082 "deprecated, use chown and chmod instead!\n");
1096 } 1083 }
1097 1084
1098 acpi_device_dir(device) = asus_proc_dir; 1085 acpi_device_dir(device) = asus_proc_dir;
@@ -1105,8 +1092,7 @@ static int asus_hotk_add_fs(struct acpi_device *device)
1105 proc->uid = asus_uid; 1092 proc->uid = asus_uid;
1106 proc->gid = asus_gid; 1093 proc->gid = asus_gid;
1107 } else { 1094 } else {
1108 printk(KERN_WARNING " Unable to create " PROC_INFO 1095 pr_warn(" Unable to create " PROC_INFO " fs entry\n");
1109 " fs entry\n");
1110 } 1096 }
1111 1097
1112 if (hotk->methods->mt_wled) { 1098 if (hotk->methods->mt_wled) {
@@ -1289,20 +1275,19 @@ static int asus_hotk_get_info(void)
1289 */ 1275 */
1290 status = acpi_get_table(ACPI_SIG_DSDT, 1, &asus_info); 1276 status = acpi_get_table(ACPI_SIG_DSDT, 1, &asus_info);
1291 if (ACPI_FAILURE(status)) 1277 if (ACPI_FAILURE(status))
1292 printk(KERN_WARNING " Couldn't get the DSDT table header\n"); 1278 pr_warn(" Couldn't get the DSDT table header\n");
1293 1279
1294 /* We have to write 0 on init this far for all ASUS models */ 1280 /* We have to write 0 on init this far for all ASUS models */
1295 if (!write_acpi_int(hotk->handle, "INIT", 0, &buffer)) { 1281 if (!write_acpi_int(hotk->handle, "INIT", 0, &buffer)) {
1296 printk(KERN_ERR " Hotkey initialization failed\n"); 1282 pr_err(" Hotkey initialization failed\n");
1297 return -ENODEV; 1283 return -ENODEV;
1298 } 1284 }
1299 1285
1300 /* This needs to be called for some laptops to init properly */ 1286 /* This needs to be called for some laptops to init properly */
1301 if (!read_acpi_int(hotk->handle, "BSTS", &bsts_result)) 1287 if (!read_acpi_int(hotk->handle, "BSTS", &bsts_result))
1302 printk(KERN_WARNING " Error calling BSTS\n"); 1288 pr_warn(" Error calling BSTS\n");
1303 else if (bsts_result) 1289 else if (bsts_result)
1304 printk(KERN_NOTICE " BSTS called, 0x%02x returned\n", 1290 pr_notice(" BSTS called, 0x%02x returned\n", bsts_result);
1305 bsts_result);
1306 1291
1307 /* 1292 /*
1308 * Try to match the object returned by INIT to the specific model. 1293 * Try to match the object returned by INIT to the specific model.
@@ -1330,23 +1315,21 @@ static int asus_hotk_get_info(void)
1330 if (asus_info && 1315 if (asus_info &&
1331 strncmp(asus_info->oem_table_id, "ODEM", 4) == 0) { 1316 strncmp(asus_info->oem_table_id, "ODEM", 4) == 0) {
1332 hotk->model = P30; 1317 hotk->model = P30;
1333 printk(KERN_NOTICE 1318 pr_notice(" Samsung P30 detected, supported\n");
1334 " Samsung P30 detected, supported\n");
1335 hotk->methods = &model_conf[hotk->model]; 1319 hotk->methods = &model_conf[hotk->model];
1336 kfree(model); 1320 kfree(model);
1337 return 0; 1321 return 0;
1338 } else { 1322 } else {
1339 hotk->model = M2E; 1323 hotk->model = M2E;
1340 printk(KERN_NOTICE " unsupported model %s, trying " 1324 pr_notice(" unsupported model %s, trying default values\n",
1341 "default values\n", string); 1325 string);
1342 printk(KERN_NOTICE 1326 pr_notice(" send /proc/acpi/dsdt to the developers\n");
1343 " send /proc/acpi/dsdt to the developers\n");
1344 kfree(model); 1327 kfree(model);
1345 return -ENODEV; 1328 return -ENODEV;
1346 } 1329 }
1347 } 1330 }
1348 hotk->methods = &model_conf[hotk->model]; 1331 hotk->methods = &model_conf[hotk->model];
1349 printk(KERN_NOTICE " %s model detected, supported\n", string); 1332 pr_notice(" %s model detected, supported\n", string);
1350 1333
1351 /* Sort of per-model blacklist */ 1334 /* Sort of per-model blacklist */
1352 if (strncmp(string, "L2B", 3) == 0) 1335 if (strncmp(string, "L2B", 3) == 0)
@@ -1391,7 +1374,7 @@ static int asus_hotk_check(void)
1391 if (hotk->device->status.present) { 1374 if (hotk->device->status.present) {
1392 result = asus_hotk_get_info(); 1375 result = asus_hotk_get_info();
1393 } else { 1376 } else {
1394 printk(KERN_ERR " Hotkey device not present, aborting\n"); 1377 pr_err(" Hotkey device not present, aborting\n");
1395 return -EINVAL; 1378 return -EINVAL;
1396 } 1379 }
1397 1380
@@ -1405,8 +1388,7 @@ static int asus_hotk_add(struct acpi_device *device)
1405 acpi_status status = AE_OK; 1388 acpi_status status = AE_OK;
1406 int result; 1389 int result;
1407 1390
1408 printk(KERN_NOTICE "Asus Laptop ACPI Extras version %s\n", 1391 pr_notice("Asus Laptop ACPI Extras version %s\n", ASUS_ACPI_VERSION);
1409 ASUS_ACPI_VERSION);
1410 1392
1411 hotk = kzalloc(sizeof(struct asus_hotk), GFP_KERNEL); 1393 hotk = kzalloc(sizeof(struct asus_hotk), GFP_KERNEL);
1412 if (!hotk) 1394 if (!hotk)
@@ -1434,15 +1416,14 @@ static int asus_hotk_add(struct acpi_device *device)
1434 acpi_evaluate_object(NULL, hotk->methods->brightness_down, 1416 acpi_evaluate_object(NULL, hotk->methods->brightness_down,
1435 NULL, NULL); 1417 NULL, NULL);
1436 if (ACPI_FAILURE(status)) 1418 if (ACPI_FAILURE(status))
1437 printk(KERN_WARNING " Error changing brightness\n"); 1419 pr_warn(" Error changing brightness\n");
1438 else { 1420 else {
1439 status = 1421 status =
1440 acpi_evaluate_object(NULL, 1422 acpi_evaluate_object(NULL,
1441 hotk->methods->brightness_up, 1423 hotk->methods->brightness_up,
1442 NULL, NULL); 1424 NULL, NULL);
1443 if (ACPI_FAILURE(status)) 1425 if (ACPI_FAILURE(status))
1444 printk(KERN_WARNING " Strange, error changing" 1426 pr_warn(" Strange, error changing brightness\n");
1445 " brightness\n");
1446 } 1427 }
1447 } 1428 }
1448 1429
@@ -1467,7 +1448,7 @@ static int asus_hotk_remove(struct acpi_device *device, int type)
1467 return 0; 1448 return 0;
1468} 1449}
1469 1450
1470static struct backlight_ops asus_backlight_data = { 1451static const struct backlight_ops asus_backlight_data = {
1471 .get_brightness = read_brightness, 1452 .get_brightness = read_brightness,
1472 .update_status = set_brightness_status, 1453 .update_status = set_brightness_status,
1473}; 1454};
@@ -1494,7 +1475,7 @@ static int __init asus_acpi_init(void)
1494 1475
1495 asus_proc_dir = proc_mkdir(PROC_ASUS, acpi_root_dir); 1476 asus_proc_dir = proc_mkdir(PROC_ASUS, acpi_root_dir);
1496 if (!asus_proc_dir) { 1477 if (!asus_proc_dir) {
1497 printk(KERN_ERR "Asus ACPI: Unable to create /proc entry\n"); 1478 pr_err("Unable to create /proc entry\n");
1498 acpi_bus_unregister_driver(&asus_hotk_driver); 1479 acpi_bus_unregister_driver(&asus_hotk_driver);
1499 return -ENODEV; 1480 return -ENODEV;
1500 } 1481 }
@@ -1513,12 +1494,13 @@ static int __init asus_acpi_init(void)
1513 } 1494 }
1514 1495
1515 memset(&props, 0, sizeof(struct backlight_properties)); 1496 memset(&props, 0, sizeof(struct backlight_properties));
1497 props.type = BACKLIGHT_PLATFORM;
1516 props.max_brightness = 15; 1498 props.max_brightness = 15;
1517 asus_backlight_device = backlight_device_register("asus", NULL, NULL, 1499 asus_backlight_device = backlight_device_register("asus", NULL, NULL,
1518 &asus_backlight_data, 1500 &asus_backlight_data,
1519 &props); 1501 &props);
1520 if (IS_ERR(asus_backlight_device)) { 1502 if (IS_ERR(asus_backlight_device)) {
1521 printk(KERN_ERR "Could not register asus backlight device\n"); 1503 pr_err("Could not register asus backlight device\n");
1522 asus_backlight_device = NULL; 1504 asus_backlight_device = NULL;
1523 asus_acpi_exit(); 1505 asus_acpi_exit();
1524 return -ENODEV; 1506 return -ENODEV;
diff --git a/drivers/platform/x86/classmate-laptop.c b/drivers/platform/x86/classmate-laptop.c
index 341cbfef93ee..94f93b621d7b 100644
--- a/drivers/platform/x86/classmate-laptop.c
+++ b/drivers/platform/x86/classmate-laptop.c
@@ -522,18 +522,20 @@ static int cmpc_rfkill_block(void *data, bool blocked)
522 acpi_status status; 522 acpi_status status;
523 acpi_handle handle; 523 acpi_handle handle;
524 unsigned long long state; 524 unsigned long long state;
525 bool is_blocked;
525 526
526 handle = data; 527 handle = data;
527 status = cmpc_get_rfkill_wlan(handle, &state); 528 status = cmpc_get_rfkill_wlan(handle, &state);
528 if (ACPI_FAILURE(status)) 529 if (ACPI_FAILURE(status))
529 return -ENODEV; 530 return -ENODEV;
530 if (blocked) 531 /* Check if we really need to call cmpc_set_rfkill_wlan */
531 state &= ~1; 532 is_blocked = state & 1 ? false : true;
532 else 533 if (is_blocked != blocked) {
533 state |= 1; 534 state = blocked ? 0 : 1;
534 status = cmpc_set_rfkill_wlan(handle, state); 535 status = cmpc_set_rfkill_wlan(handle, state);
535 if (ACPI_FAILURE(status)) 536 if (ACPI_FAILURE(status))
536 return -ENODEV; 537 return -ENODEV;
538 }
537 return 0; 539 return 0;
538} 540}
539 541
@@ -562,6 +564,7 @@ static int cmpc_ipml_add(struct acpi_device *acpi)
562 return -ENOMEM; 564 return -ENOMEM;
563 565
564 memset(&props, 0, sizeof(struct backlight_properties)); 566 memset(&props, 0, sizeof(struct backlight_properties));
567 props.type = BACKLIGHT_PLATFORM;
565 props.max_brightness = 7; 568 props.max_brightness = 7;
566 ipml->bd = backlight_device_register("cmpc_bl", &acpi->dev, 569 ipml->bd = backlight_device_register("cmpc_bl", &acpi->dev,
567 acpi->handle, &cmpc_bl_ops, 570 acpi->handle, &cmpc_bl_ops,
@@ -653,8 +656,9 @@ static void cmpc_keys_handler(struct acpi_device *dev, u32 event)
653 656
654 if ((event & 0x0F) < ARRAY_SIZE(cmpc_keys_codes)) 657 if ((event & 0x0F) < ARRAY_SIZE(cmpc_keys_codes))
655 code = cmpc_keys_codes[event & 0x0F]; 658 code = cmpc_keys_codes[event & 0x0F];
656 inputdev = dev_get_drvdata(&dev->dev);; 659 inputdev = dev_get_drvdata(&dev->dev);
657 input_report_key(inputdev, code, !(event & 0x10)); 660 input_report_key(inputdev, code, !(event & 0x10));
661 input_sync(inputdev);
658} 662}
659 663
660static void cmpc_keys_idev_init(struct input_dev *inputdev) 664static void cmpc_keys_idev_init(struct input_dev *inputdev)
diff --git a/drivers/platform/x86/compal-laptop.c b/drivers/platform/x86/compal-laptop.c
index 097083cac413..8877b836d27c 100644
--- a/drivers/platform/x86/compal-laptop.c
+++ b/drivers/platform/x86/compal-laptop.c
@@ -68,6 +68,8 @@
68 * only enabled on a JHL90 board until it is verified that they work on the 68 * only enabled on a JHL90 board until it is verified that they work on the
69 * other boards too. See the extra_features variable. */ 69 * other boards too. See the extra_features variable. */
70 70
71#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
72
71#include <linux/module.h> 73#include <linux/module.h>
72#include <linux/kernel.h> 74#include <linux/kernel.h>
73#include <linux/init.h> 75#include <linux/init.h>
@@ -200,8 +202,8 @@ static bool extra_features;
200 * watching the output of address 0x4F (do an ec_transaction writing 0x33 202 * watching the output of address 0x4F (do an ec_transaction writing 0x33
201 * into 0x4F and read a few bytes from the output, like so: 203 * into 0x4F and read a few bytes from the output, like so:
202 * u8 writeData = 0x33; 204 * u8 writeData = 0x33;
203 * ec_transaction(0x4F, &writeData, 1, buffer, 32, 0); 205 * ec_transaction(0x4F, &writeData, 1, buffer, 32);
204 * That address is labled "fan1 table information" in the service manual. 206 * That address is labeled "fan1 table information" in the service manual.
205 * It should be clear which value in 'buffer' changes). This seems to be 207 * It should be clear which value in 'buffer' changes). This seems to be
206 * related to fan speed. It isn't a proper 'realtime' fan speed value 208 * related to fan speed. It isn't a proper 'realtime' fan speed value
207 * though, because physically stopping or speeding up the fan doesn't 209 * though, because physically stopping or speeding up the fan doesn't
@@ -275,7 +277,7 @@ static int set_backlight_level(int level)
275 277
276 ec_write(BACKLIGHT_LEVEL_ADDR, level); 278 ec_write(BACKLIGHT_LEVEL_ADDR, level);
277 279
278 return 1; 280 return 0;
279} 281}
280 282
281static int get_backlight_level(void) 283static int get_backlight_level(void)
@@ -286,7 +288,7 @@ static int get_backlight_level(void)
286static void set_backlight_state(bool on) 288static void set_backlight_state(bool on)
287{ 289{
288 u8 data = on ? BACKLIGHT_STATE_ON_DATA : BACKLIGHT_STATE_OFF_DATA; 290 u8 data = on ? BACKLIGHT_STATE_ON_DATA : BACKLIGHT_STATE_OFF_DATA;
289 ec_transaction(BACKLIGHT_STATE_ADDR, &data, 1, NULL, 0, 0); 291 ec_transaction(BACKLIGHT_STATE_ADDR, &data, 1, NULL, 0);
290} 292}
291 293
292 294
@@ -294,24 +296,24 @@ static void set_backlight_state(bool on)
294static void pwm_enable_control(void) 296static void pwm_enable_control(void)
295{ 297{
296 unsigned char writeData = PWM_ENABLE_DATA; 298 unsigned char writeData = PWM_ENABLE_DATA;
297 ec_transaction(PWM_ENABLE_ADDR, &writeData, 1, NULL, 0, 0); 299 ec_transaction(PWM_ENABLE_ADDR, &writeData, 1, NULL, 0);
298} 300}
299 301
300static void pwm_disable_control(void) 302static void pwm_disable_control(void)
301{ 303{
302 unsigned char writeData = PWM_DISABLE_DATA; 304 unsigned char writeData = PWM_DISABLE_DATA;
303 ec_transaction(PWM_DISABLE_ADDR, &writeData, 1, NULL, 0, 0); 305 ec_transaction(PWM_DISABLE_ADDR, &writeData, 1, NULL, 0);
304} 306}
305 307
306static void set_pwm(int pwm) 308static void set_pwm(int pwm)
307{ 309{
308 ec_transaction(PWM_ADDRESS, &pwm_lookup_table[pwm], 1, NULL, 0, 0); 310 ec_transaction(PWM_ADDRESS, &pwm_lookup_table[pwm], 1, NULL, 0);
309} 311}
310 312
311static int get_fan_rpm(void) 313static int get_fan_rpm(void)
312{ 314{
313 u8 value, data = FAN_DATA; 315 u8 value, data = FAN_DATA;
314 ec_transaction(FAN_ADDRESS, &data, 1, &value, 1, 0); 316 ec_transaction(FAN_ADDRESS, &data, 1, &value, 1);
315 return 100 * (int)value; 317 return 100 * (int)value;
316} 318}
317 319
@@ -760,19 +762,17 @@ static struct rfkill *bt_rfkill;
760 762
761static int dmi_check_cb(const struct dmi_system_id *id) 763static int dmi_check_cb(const struct dmi_system_id *id)
762{ 764{
763 printk(KERN_INFO DRIVER_NAME": Identified laptop model '%s'\n", 765 pr_info("Identified laptop model '%s'\n", id->ident);
764 id->ident);
765 extra_features = false; 766 extra_features = false;
766 return 0; 767 return 1;
767} 768}
768 769
769static int dmi_check_cb_extra(const struct dmi_system_id *id) 770static int dmi_check_cb_extra(const struct dmi_system_id *id)
770{ 771{
771 printk(KERN_INFO DRIVER_NAME": Identified laptop model '%s', " 772 pr_info("Identified laptop model '%s', enabling extra features\n",
772 "enabling extra features\n",
773 id->ident); 773 id->ident);
774 extra_features = true; 774 extra_features = true;
775 return 0; 775 return 1;
776} 776}
777 777
778static struct dmi_system_id __initdata compal_dmi_table[] = { 778static struct dmi_system_id __initdata compal_dmi_table[] = {
@@ -872,6 +872,14 @@ static struct dmi_system_id __initdata compal_dmi_table[] = {
872 }, 872 },
873 .callback = dmi_check_cb_extra 873 .callback = dmi_check_cb_extra
874 }, 874 },
875 {
876 .ident = "KHLB2",
877 .matches = {
878 DMI_MATCH(DMI_BOARD_NAME, "KHLB2"),
879 DMI_MATCH(DMI_BOARD_VERSION, "REFERENCE"),
880 },
881 .callback = dmi_check_cb_extra
882 },
875 { } 883 { }
876}; 884};
877 885
@@ -948,20 +956,19 @@ static int __init compal_init(void)
948 int ret; 956 int ret;
949 957
950 if (acpi_disabled) { 958 if (acpi_disabled) {
951 printk(KERN_ERR DRIVER_NAME": ACPI needs to be enabled for " 959 pr_err("ACPI needs to be enabled for this driver to work!\n");
952 "this driver to work!\n");
953 return -ENODEV; 960 return -ENODEV;
954 } 961 }
955 962
956 if (!force && !dmi_check_system(compal_dmi_table)) { 963 if (!force && !dmi_check_system(compal_dmi_table)) {
957 printk(KERN_ERR DRIVER_NAME": Motherboard not recognized (You " 964 pr_err("Motherboard not recognized (You could try the module's force-parameter)\n");
958 "could try the module's force-parameter)");
959 return -ENODEV; 965 return -ENODEV;
960 } 966 }
961 967
962 if (!acpi_video_backlight_support()) { 968 if (!acpi_video_backlight_support()) {
963 struct backlight_properties props; 969 struct backlight_properties props;
964 memset(&props, 0, sizeof(struct backlight_properties)); 970 memset(&props, 0, sizeof(struct backlight_properties));
971 props.type = BACKLIGHT_PLATFORM;
965 props.max_brightness = BACKLIGHT_LEVEL_MAX; 972 props.max_brightness = BACKLIGHT_LEVEL_MAX;
966 compalbl_device = backlight_device_register(DRIVER_NAME, 973 compalbl_device = backlight_device_register(DRIVER_NAME,
967 NULL, NULL, 974 NULL, NULL,
@@ -989,8 +996,7 @@ static int __init compal_init(void)
989 if (ret) 996 if (ret)
990 goto err_rfkill; 997 goto err_rfkill;
991 998
992 printk(KERN_INFO DRIVER_NAME": Driver "DRIVER_VERSION 999 pr_info("Driver " DRIVER_VERSION " successfully loaded\n");
993 " successfully loaded\n");
994 return 0; 1000 return 0;
995 1001
996err_rfkill: 1002err_rfkill:
@@ -1024,8 +1030,10 @@ static int __devinit compal_probe(struct platform_device *pdev)
1024 initialize_fan_control_data(data); 1030 initialize_fan_control_data(data);
1025 1031
1026 err = sysfs_create_group(&pdev->dev.kobj, &compal_attribute_group); 1032 err = sysfs_create_group(&pdev->dev.kobj, &compal_attribute_group);
1027 if (err) 1033 if (err) {
1034 kfree(data);
1028 return err; 1035 return err;
1036 }
1029 1037
1030 data->hwmon_dev = hwmon_device_register(&pdev->dev); 1038 data->hwmon_dev = hwmon_device_register(&pdev->dev);
1031 if (IS_ERR(data->hwmon_dev)) { 1039 if (IS_ERR(data->hwmon_dev)) {
@@ -1055,7 +1063,7 @@ static void __exit compal_cleanup(void)
1055 rfkill_destroy(wifi_rfkill); 1063 rfkill_destroy(wifi_rfkill);
1056 rfkill_destroy(bt_rfkill); 1064 rfkill_destroy(bt_rfkill);
1057 1065
1058 printk(KERN_INFO DRIVER_NAME": Driver unloaded\n"); 1066 pr_info("Driver unloaded\n");
1059} 1067}
1060 1068
1061static int __devexit compal_remove(struct platform_device *pdev) 1069static int __devexit compal_remove(struct platform_device *pdev)
@@ -1065,8 +1073,7 @@ static int __devexit compal_remove(struct platform_device *pdev)
1065 if (!extra_features) 1073 if (!extra_features)
1066 return 0; 1074 return 0;
1067 1075
1068 printk(KERN_INFO DRIVER_NAME": Unloading: resetting fan control " 1076 pr_info("Unloading: resetting fan control to motherboard\n");
1069 "to motherboard\n");
1070 pwm_disable_control(); 1077 pwm_disable_control();
1071 1078
1072 data = platform_get_drvdata(pdev); 1079 data = platform_get_drvdata(pdev);
diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
index 4413975912e0..e39ab1d3ed87 100644
--- a/drivers/platform/x86/dell-laptop.c
+++ b/drivers/platform/x86/dell-laptop.c
@@ -11,6 +11,8 @@
11 * published by the Free Software Foundation. 11 * published by the Free Software Foundation.
12 */ 12 */
13 13
14#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
15
14#include <linux/module.h> 16#include <linux/module.h>
15#include <linux/kernel.h> 17#include <linux/kernel.h>
16#include <linux/init.h> 18#include <linux/init.h>
@@ -25,6 +27,8 @@
25#include <linux/mm.h> 27#include <linux/mm.h>
26#include <linux/i8042.h> 28#include <linux/i8042.h>
27#include <linux/slab.h> 29#include <linux/slab.h>
30#include <linux/debugfs.h>
31#include <linux/seq_file.h>
28#include "../../firmware/dcdbas.h" 32#include "../../firmware/dcdbas.h"
29 33
30#define BRIGHTNESS_TOKEN 0x7d 34#define BRIGHTNESS_TOKEN 0x7d
@@ -325,6 +329,75 @@ static const struct rfkill_ops dell_rfkill_ops = {
325 .query = dell_rfkill_query, 329 .query = dell_rfkill_query,
326}; 330};
327 331
332static struct dentry *dell_laptop_dir;
333
334static int dell_debugfs_show(struct seq_file *s, void *data)
335{
336 int status;
337
338 get_buffer();
339 dell_send_request(buffer, 17, 11);
340 status = buffer->output[1];
341 release_buffer();
342
343 seq_printf(s, "status:\t0x%X\n", status);
344 seq_printf(s, "Bit 0 : Hardware switch supported: %lu\n",
345 status & BIT(0));
346 seq_printf(s, "Bit 1 : Wifi locator supported: %lu\n",
347 (status & BIT(1)) >> 1);
348 seq_printf(s, "Bit 2 : Wifi is supported: %lu\n",
349 (status & BIT(2)) >> 2);
350 seq_printf(s, "Bit 3 : Bluetooth is supported: %lu\n",
351 (status & BIT(3)) >> 3);
352 seq_printf(s, "Bit 4 : WWAN is supported: %lu\n",
353 (status & BIT(4)) >> 4);
354 seq_printf(s, "Bit 5 : Wireless keyboard supported: %lu\n",
355 (status & BIT(5)) >> 5);
356 seq_printf(s, "Bit 8 : Wifi is installed: %lu\n",
357 (status & BIT(8)) >> 8);
358 seq_printf(s, "Bit 9 : Bluetooth is installed: %lu\n",
359 (status & BIT(9)) >> 9);
360 seq_printf(s, "Bit 10: WWAN is installed: %lu\n",
361 (status & BIT(10)) >> 10);
362 seq_printf(s, "Bit 16: Hardware switch is on: %lu\n",
363 (status & BIT(16)) >> 16);
364 seq_printf(s, "Bit 17: Wifi is blocked: %lu\n",
365 (status & BIT(17)) >> 17);
366 seq_printf(s, "Bit 18: Bluetooth is blocked: %lu\n",
367 (status & BIT(18)) >> 18);
368 seq_printf(s, "Bit 19: WWAN is blocked: %lu\n",
369 (status & BIT(19)) >> 19);
370
371 seq_printf(s, "\nhwswitch_state:\t0x%X\n", hwswitch_state);
372 seq_printf(s, "Bit 0 : Wifi controlled by switch: %lu\n",
373 hwswitch_state & BIT(0));
374 seq_printf(s, "Bit 1 : Bluetooth controlled by switch: %lu\n",
375 (hwswitch_state & BIT(1)) >> 1);
376 seq_printf(s, "Bit 2 : WWAN controlled by switch: %lu\n",
377 (hwswitch_state & BIT(2)) >> 2);
378 seq_printf(s, "Bit 7 : Wireless switch config locked: %lu\n",
379 (hwswitch_state & BIT(7)) >> 7);
380 seq_printf(s, "Bit 8 : Wifi locator enabled: %lu\n",
381 (hwswitch_state & BIT(8)) >> 8);
382 seq_printf(s, "Bit 15: Wifi locator setting locked: %lu\n",
383 (hwswitch_state & BIT(15)) >> 15);
384
385 return 0;
386}
387
388static int dell_debugfs_open(struct inode *inode, struct file *file)
389{
390 return single_open(file, dell_debugfs_show, inode->i_private);
391}
392
393static const struct file_operations dell_debugfs_fops = {
394 .owner = THIS_MODULE,
395 .open = dell_debugfs_open,
396 .read = seq_read,
397 .llseek = seq_lseek,
398 .release = single_release,
399};
400
328static void dell_update_rfkill(struct work_struct *ignored) 401static void dell_update_rfkill(struct work_struct *ignored)
329{ 402{
330 if (wifi_rfkill) 403 if (wifi_rfkill)
@@ -343,8 +416,7 @@ static int __init dell_setup_rfkill(void)
343 int ret; 416 int ret;
344 417
345 if (dmi_check_system(dell_blacklist)) { 418 if (dmi_check_system(dell_blacklist)) {
346 printk(KERN_INFO "dell-laptop: Blacklisted hardware detected - " 419 pr_info("Blacklisted hardware detected - not enabling rfkill\n");
347 "not enabling rfkill\n");
348 return 0; 420 return 0;
349 } 421 }
350 422
@@ -468,14 +540,14 @@ static int dell_get_intensity(struct backlight_device *bd)
468 else 540 else
469 dell_send_request(buffer, 0, 1); 541 dell_send_request(buffer, 0, 1);
470 542
543 ret = buffer->output[1];
544
471out: 545out:
472 release_buffer(); 546 release_buffer();
473 if (ret) 547 return ret;
474 return ret;
475 return buffer->output[1];
476} 548}
477 549
478static struct backlight_ops dell_ops = { 550static const struct backlight_ops dell_ops = {
479 .get_brightness = dell_get_intensity, 551 .get_brightness = dell_get_intensity,
480 .update_status = dell_send_intensity, 552 .update_status = dell_send_intensity,
481}; 553};
@@ -515,7 +587,7 @@ static int __init dell_init(void)
515 dmi_walk(find_tokens, NULL); 587 dmi_walk(find_tokens, NULL);
516 588
517 if (!da_tokens) { 589 if (!da_tokens) {
518 printk(KERN_INFO "dell-laptop: Unable to find dmi tokens\n"); 590 pr_info("Unable to find dmi tokens\n");
519 return -ENODEV; 591 return -ENODEV;
520 } 592 }
521 593
@@ -545,17 +617,21 @@ static int __init dell_init(void)
545 ret = dell_setup_rfkill(); 617 ret = dell_setup_rfkill();
546 618
547 if (ret) { 619 if (ret) {
548 printk(KERN_WARNING "dell-laptop: Unable to setup rfkill\n"); 620 pr_warn("Unable to setup rfkill\n");
549 goto fail_rfkill; 621 goto fail_rfkill;
550 } 622 }
551 623
552 ret = i8042_install_filter(dell_laptop_i8042_filter); 624 ret = i8042_install_filter(dell_laptop_i8042_filter);
553 if (ret) { 625 if (ret) {
554 printk(KERN_WARNING 626 pr_warn("Unable to install key filter\n");
555 "dell-laptop: Unable to install key filter\n");
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.
@@ -575,6 +651,7 @@ static int __init dell_init(void)
575 if (max_intensity) { 651 if (max_intensity) {
576 struct backlight_properties props; 652 struct backlight_properties props;
577 memset(&props, 0, sizeof(struct backlight_properties)); 653 memset(&props, 0, sizeof(struct backlight_properties));
654 props.type = BACKLIGHT_PLATFORM;
578 props.max_brightness = max_intensity; 655 props.max_brightness = max_intensity;
579 dell_backlight_device = backlight_device_register("dell_backlight", 656 dell_backlight_device = backlight_device_register("dell_backlight",
580 &platform_device->dev, 657 &platform_device->dev,
@@ -615,6 +692,7 @@ fail_platform_driver:
615 692
616static void __exit dell_exit(void) 693static void __exit dell_exit(void)
617{ 694{
695 debugfs_remove_recursive(dell_laptop_dir);
618 i8042_remove_filter(dell_laptop_i8042_filter); 696 i8042_remove_filter(dell_laptop_i8042_filter);
619 cancel_delayed_work_sync(&dell_rfkill_work); 697 cancel_delayed_work_sync(&dell_rfkill_work);
620 backlight_device_unregister(dell_backlight_device); 698 backlight_device_unregister(dell_backlight_device);
diff --git a/drivers/platform/x86/dell-wmi-aio.c b/drivers/platform/x86/dell-wmi-aio.c
new file mode 100644
index 000000000000..3f945457f71c
--- /dev/null
+++ b/drivers/platform/x86/dell-wmi-aio.c
@@ -0,0 +1,172 @@
1/*
2 * WMI hotkeys support for Dell All-In-One series
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
19#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
20
21#include <linux/kernel.h>
22#include <linux/module.h>
23#include <linux/init.h>
24#include <linux/types.h>
25#include <linux/input.h>
26#include <linux/input/sparse-keymap.h>
27#include <acpi/acpi_drivers.h>
28#include <linux/acpi.h>
29#include <linux/string.h>
30
31MODULE_DESCRIPTION("WMI hotkeys driver for Dell All-In-One series");
32MODULE_LICENSE("GPL");
33
34#define EVENT_GUID1 "284A0E6B-380E-472A-921F-E52786257FB4"
35#define EVENT_GUID2 "02314822-307C-4F66-BF0E-48AEAEB26CC8"
36
37static const char *dell_wmi_aio_guids[] = {
38 EVENT_GUID1,
39 EVENT_GUID2,
40 NULL
41};
42
43MODULE_ALIAS("wmi:"EVENT_GUID1);
44MODULE_ALIAS("wmi:"EVENT_GUID2);
45
46static const struct key_entry dell_wmi_aio_keymap[] = {
47 { KE_KEY, 0xc0, { KEY_VOLUMEUP } },
48 { KE_KEY, 0xc1, { KEY_VOLUMEDOWN } },
49 { KE_END, 0 }
50};
51
52static struct input_dev *dell_wmi_aio_input_dev;
53
54static void dell_wmi_aio_notify(u32 value, void *context)
55{
56 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
57 union acpi_object *obj;
58 acpi_status status;
59
60 status = wmi_get_event_data(value, &response);
61 if (status != AE_OK) {
62 pr_info("bad event status 0x%x\n", status);
63 return;
64 }
65
66 obj = (union acpi_object *)response.pointer;
67 if (obj) {
68 unsigned int scancode;
69
70 switch (obj->type) {
71 case ACPI_TYPE_INTEGER:
72 /* Most All-In-One correctly return integer scancode */
73 scancode = obj->integer.value;
74 sparse_keymap_report_event(dell_wmi_aio_input_dev,
75 scancode, 1, true);
76 break;
77 case ACPI_TYPE_BUFFER:
78 /* Broken machines return the scancode in a buffer */
79 if (obj->buffer.pointer && obj->buffer.length > 0) {
80 scancode = obj->buffer.pointer[0];
81 sparse_keymap_report_event(
82 dell_wmi_aio_input_dev,
83 scancode, 1, true);
84 }
85 break;
86 }
87 }
88 kfree(obj);
89}
90
91static int __init dell_wmi_aio_input_setup(void)
92{
93 int err;
94
95 dell_wmi_aio_input_dev = input_allocate_device();
96
97 if (!dell_wmi_aio_input_dev)
98 return -ENOMEM;
99
100 dell_wmi_aio_input_dev->name = "Dell AIO WMI hotkeys";
101 dell_wmi_aio_input_dev->phys = "wmi/input0";
102 dell_wmi_aio_input_dev->id.bustype = BUS_HOST;
103
104 err = sparse_keymap_setup(dell_wmi_aio_input_dev,
105 dell_wmi_aio_keymap, NULL);
106 if (err) {
107 pr_err("Unable to setup input device keymap\n");
108 goto err_free_dev;
109 }
110 err = input_register_device(dell_wmi_aio_input_dev);
111 if (err) {
112 pr_info("Unable to register input device\n");
113 goto err_free_keymap;
114 }
115 return 0;
116
117err_free_keymap:
118 sparse_keymap_free(dell_wmi_aio_input_dev);
119err_free_dev:
120 input_free_device(dell_wmi_aio_input_dev);
121 return err;
122}
123
124static const char *dell_wmi_aio_find(void)
125{
126 int i;
127
128 for (i = 0; dell_wmi_aio_guids[i] != NULL; i++)
129 if (wmi_has_guid(dell_wmi_aio_guids[i]))
130 return dell_wmi_aio_guids[i];
131
132 return NULL;
133}
134
135static int __init dell_wmi_aio_init(void)
136{
137 int err;
138 const char *guid;
139
140 guid = dell_wmi_aio_find();
141 if (!guid) {
142 pr_warn("No known WMI GUID found\n");
143 return -ENXIO;
144 }
145
146 err = dell_wmi_aio_input_setup();
147 if (err)
148 return err;
149
150 err = wmi_install_notify_handler(guid, dell_wmi_aio_notify, NULL);
151 if (err) {
152 pr_err("Unable to register notify handler - %d\n", err);
153 sparse_keymap_free(dell_wmi_aio_input_dev);
154 input_unregister_device(dell_wmi_aio_input_dev);
155 return err;
156 }
157
158 return 0;
159}
160
161static void __exit dell_wmi_aio_exit(void)
162{
163 const char *guid;
164
165 guid = dell_wmi_aio_find();
166 wmi_remove_notify_handler(guid);
167 sparse_keymap_free(dell_wmi_aio_input_dev);
168 input_unregister_device(dell_wmi_aio_input_dev);
169}
170
171module_init(dell_wmi_aio_init);
172module_exit(dell_wmi_aio_exit);
diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c
index 08fb70f6d9bf..ce790827e199 100644
--- a/drivers/platform/x86/dell-wmi.c
+++ b/drivers/platform/x86/dell-wmi.c
@@ -23,12 +23,15 @@
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */ 24 */
25 25
26#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
27
26#include <linux/kernel.h> 28#include <linux/kernel.h>
27#include <linux/module.h> 29#include <linux/module.h>
28#include <linux/init.h> 30#include <linux/init.h>
29#include <linux/slab.h> 31#include <linux/slab.h>
30#include <linux/types.h> 32#include <linux/types.h>
31#include <linux/input.h> 33#include <linux/input.h>
34#include <linux/input/sparse-keymap.h>
32#include <acpi/acpi_drivers.h> 35#include <acpi/acpi_drivers.h>
33#include <linux/acpi.h> 36#include <linux/acpi.h>
34#include <linux/string.h> 37#include <linux/string.h>
@@ -44,78 +47,70 @@ static int acpi_video;
44 47
45MODULE_ALIAS("wmi:"DELL_EVENT_GUID); 48MODULE_ALIAS("wmi:"DELL_EVENT_GUID);
46 49
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/* 50/*
56 * Certain keys are flagged as KE_IGNORE. All of these are either 51 * Certain keys are flagged as KE_IGNORE. All of these are either
57 * notifications (rather than requests for change) or are also sent 52 * notifications (rather than requests for change) or are also sent
58 * via the keyboard controller so should not be sent again. 53 * via the keyboard controller so should not be sent again.
59 */ 54 */
60 55
61static struct key_entry dell_legacy_wmi_keymap[] = { 56static const struct key_entry dell_wmi_legacy_keymap[] __initconst = {
62 {KE_KEY, 0xe045, KEY_PROG1}, 57 { KE_KEY, 0xe045, { KEY_PROG1 } },
63 {KE_KEY, 0xe009, KEY_EJECTCD}, 58 { KE_KEY, 0xe009, { KEY_EJECTCD } },
64 59
65 /* These also contain the brightness level at offset 6 */ 60 /* These also contain the brightness level at offset 6 */
66 {KE_KEY, 0xe006, KEY_BRIGHTNESSUP}, 61 { KE_KEY, 0xe006, { KEY_BRIGHTNESSUP } },
67 {KE_KEY, 0xe005, KEY_BRIGHTNESSDOWN}, 62 { KE_KEY, 0xe005, { KEY_BRIGHTNESSDOWN } },
68 63
69 /* Battery health status button */ 64 /* Battery health status button */
70 {KE_KEY, 0xe007, KEY_BATTERY}, 65 { KE_KEY, 0xe007, { KEY_BATTERY } },
71 66
72 /* This is actually for all radios. Although physically a 67 /* This is actually for all radios. Although physically a
73 * switch, the notification does not provide an indication of 68 * switch, the notification does not provide an indication of
74 * state and so it should be reported as a key */ 69 * state and so it should be reported as a key */
75 {KE_KEY, 0xe008, KEY_WLAN}, 70 { KE_KEY, 0xe008, { KEY_WLAN } },
76 71
77 /* The next device is at offset 6, the active devices are at 72 /* The next device is at offset 6, the active devices are at
78 offset 8 and the attached devices at offset 10 */ 73 offset 8 and the attached devices at offset 10 */
79 {KE_KEY, 0xe00b, KEY_SWITCHVIDEOMODE}, 74 { KE_KEY, 0xe00b, { KEY_SWITCHVIDEOMODE } },
80 75
81 {KE_IGNORE, 0xe00c, KEY_KBDILLUMTOGGLE}, 76 { KE_IGNORE, 0xe00c, { KEY_KBDILLUMTOGGLE } },
82 77
83 /* BIOS error detected */ 78 /* BIOS error detected */
84 {KE_IGNORE, 0xe00d, KEY_RESERVED}, 79 { KE_IGNORE, 0xe00d, { KEY_RESERVED } },
85 80
86 /* Wifi Catcher */ 81 /* Wifi Catcher */
87 {KE_KEY, 0xe011, KEY_PROG2}, 82 { KE_KEY, 0xe011, {KEY_PROG2 } },
88 83
89 /* Ambient light sensor toggle */ 84 /* Ambient light sensor toggle */
90 {KE_IGNORE, 0xe013, KEY_RESERVED}, 85 { KE_IGNORE, 0xe013, { KEY_RESERVED } },
91 86
92 {KE_IGNORE, 0xe020, KEY_MUTE}, 87 { KE_IGNORE, 0xe020, { KEY_MUTE } },
93 {KE_IGNORE, 0xe02e, KEY_VOLUMEDOWN}, 88 { KE_IGNORE, 0xe02e, { KEY_VOLUMEDOWN } },
94 {KE_IGNORE, 0xe030, KEY_VOLUMEUP}, 89 { KE_IGNORE, 0xe030, { KEY_VOLUMEUP } },
95 {KE_IGNORE, 0xe033, KEY_KBDILLUMUP}, 90 { KE_IGNORE, 0xe033, { KEY_KBDILLUMUP } },
96 {KE_IGNORE, 0xe034, KEY_KBDILLUMDOWN}, 91 { KE_IGNORE, 0xe034, { KEY_KBDILLUMDOWN } },
97 {KE_IGNORE, 0xe03a, KEY_CAPSLOCK}, 92 { KE_IGNORE, 0xe03a, { KEY_CAPSLOCK } },
98 {KE_IGNORE, 0xe045, KEY_NUMLOCK}, 93 { KE_IGNORE, 0xe045, { KEY_NUMLOCK } },
99 {KE_IGNORE, 0xe046, KEY_SCROLLLOCK}, 94 { KE_IGNORE, 0xe046, { KEY_SCROLLLOCK } },
100 {KE_END, 0} 95 { KE_END, 0 }
101}; 96};
102 97
103static bool dell_new_hk_type; 98static bool dell_new_hk_type;
104 99
105struct dell_new_keymap_entry { 100struct dell_bios_keymap_entry {
106 u16 scancode; 101 u16 scancode;
107 u16 keycode; 102 u16 keycode;
108}; 103};
109 104
110struct dell_hotkey_table { 105struct dell_bios_hotkey_table {
111 struct dmi_header header; 106 struct dmi_header header;
112 struct dell_new_keymap_entry keymap[]; 107 struct dell_bios_keymap_entry keymap[];
113 108
114}; 109};
115 110
116static struct key_entry *dell_new_wmi_keymap; 111static const struct dell_bios_hotkey_table *dell_bios_hotkey_table;
117 112
118static u16 bios_to_linux_keycode[256] = { 113static const u16 bios_to_linux_keycode[256] __initconst = {
119 114
120 KEY_MEDIA, KEY_NEXTSONG, KEY_PLAYPAUSE, KEY_PREVIOUSSONG, 115 KEY_MEDIA, KEY_NEXTSONG, KEY_PLAYPAUSE, KEY_PREVIOUSSONG,
121 KEY_STOPCD, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, 116 KEY_STOPCD, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
@@ -138,85 +133,30 @@ static u16 bios_to_linux_keycode[256] = {
138 KEY_PROG3 133 KEY_PROG3
139}; 134};
140 135
141
142static struct key_entry *dell_wmi_keymap = dell_legacy_wmi_keymap;
143
144static struct input_dev *dell_wmi_input_dev; 136static struct input_dev *dell_wmi_input_dev;
145 137
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) 138static void dell_wmi_notify(u32 value, void *context)
200{ 139{
201 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; 140 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
202 static struct key_entry *key;
203 union acpi_object *obj; 141 union acpi_object *obj;
204 acpi_status status; 142 acpi_status status;
205 143
206 status = wmi_get_event_data(value, &response); 144 status = wmi_get_event_data(value, &response);
207 if (status != AE_OK) { 145 if (status != AE_OK) {
208 printk(KERN_INFO "dell-wmi: bad event status 0x%x\n", status); 146 pr_info("bad event status 0x%x\n", status);
209 return; 147 return;
210 } 148 }
211 149
212 obj = (union acpi_object *)response.pointer; 150 obj = (union acpi_object *)response.pointer;
213 151
214 if (obj && obj->type == ACPI_TYPE_BUFFER) { 152 if (obj && obj->type == ACPI_TYPE_BUFFER) {
153 const struct key_entry *key;
215 int reported_key; 154 int reported_key;
216 u16 *buffer_entry = (u16 *)obj->buffer.pointer; 155 u16 *buffer_entry = (u16 *)obj->buffer.pointer;
156
217 if (dell_new_hk_type && (buffer_entry[1] != 0x10)) { 157 if (dell_new_hk_type && (buffer_entry[1] != 0x10)) {
218 printk(KERN_INFO "dell-wmi: Received unknown WMI event" 158 pr_info("Received unknown WMI event (0x%x)\n",
219 " (0x%x)\n", buffer_entry[1]); 159 buffer_entry[1]);
220 kfree(obj); 160 kfree(obj);
221 return; 161 return;
222 } 162 }
@@ -226,103 +166,108 @@ static void dell_wmi_notify(u32 value, void *context)
226 else 166 else
227 reported_key = (int)buffer_entry[1] & 0xffff; 167 reported_key = (int)buffer_entry[1] & 0xffff;
228 168
229 key = dell_wmi_get_entry_by_scancode(reported_key); 169 key = sparse_keymap_entry_from_scancode(dell_wmi_input_dev,
230 170 reported_key);
231 if (!key) { 171 if (!key) {
232 printk(KERN_INFO "dell-wmi: Unknown key %x pressed\n", 172 pr_info("Unknown key %x pressed\n", reported_key);
233 reported_key);
234 } else if ((key->keycode == KEY_BRIGHTNESSUP || 173 } else if ((key->keycode == KEY_BRIGHTNESSUP ||
235 key->keycode == KEY_BRIGHTNESSDOWN) && acpi_video) { 174 key->keycode == KEY_BRIGHTNESSDOWN) && acpi_video) {
236 /* Don't report brightness notifications that will also 175 /* Don't report brightness notifications that will also
237 * come via ACPI */ 176 * come via ACPI */
238 ; 177 ;
239 } else { 178 } else {
240 input_report_key(dell_wmi_input_dev, key->keycode, 1); 179 sparse_keymap_report_entry(dell_wmi_input_dev, key,
241 input_sync(dell_wmi_input_dev); 180 1, true);
242 input_report_key(dell_wmi_input_dev, key->keycode, 0);
243 input_sync(dell_wmi_input_dev);
244 } 181 }
245 } 182 }
246 kfree(obj); 183 kfree(obj);
247} 184}
248 185
249 186static const struct key_entry * __init dell_wmi_prepare_new_keymap(void)
250static void setup_new_hk_map(const struct dmi_header *dm)
251{ 187{
252 188 int hotkey_num = (dell_bios_hotkey_table->header.length - 4) /
189 sizeof(struct dell_bios_keymap_entry);
190 struct key_entry *keymap;
253 int i; 191 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 192
258 dell_new_wmi_keymap = kzalloc((hotkey_num+1) * 193 keymap = kcalloc(hotkey_num + 1, sizeof(struct key_entry), GFP_KERNEL);
259 sizeof(struct key_entry), GFP_KERNEL); 194 if (!keymap)
195 return NULL;
260 196
261 for (i = 0; i < hotkey_num; i++) { 197 for (i = 0; i < hotkey_num; i++) {
262 dell_new_wmi_keymap[i].type = KE_KEY; 198 const struct dell_bios_keymap_entry *bios_entry =
263 dell_new_wmi_keymap[i].code = table->keymap[i].scancode; 199 &dell_bios_hotkey_table->keymap[i];
264 dell_new_wmi_keymap[i].keycode = 200 keymap[i].type = KE_KEY;
265 (table->keymap[i].keycode > 255) ? 0 : 201 keymap[i].code = bios_entry->scancode;
266 bios_to_linux_keycode[table->keymap[i].keycode]; 202 keymap[i].keycode = bios_entry->keycode < 256 ?
203 bios_to_linux_keycode[bios_entry->keycode] :
204 KEY_RESERVED;
267 } 205 }
268 206
269 dell_new_wmi_keymap[i].type = KE_END; 207 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 208
209 return keymap;
275} 210}
276 211
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) 212static int __init dell_wmi_input_setup(void)
290{ 213{
291 struct key_entry *key;
292 int err; 214 int err;
293 215
294 dell_wmi_input_dev = input_allocate_device(); 216 dell_wmi_input_dev = input_allocate_device();
295
296 if (!dell_wmi_input_dev) 217 if (!dell_wmi_input_dev)
297 return -ENOMEM; 218 return -ENOMEM;
298 219
299 dell_wmi_input_dev->name = "Dell WMI hotkeys"; 220 dell_wmi_input_dev->name = "Dell WMI hotkeys";
300 dell_wmi_input_dev->phys = "wmi/input0"; 221 dell_wmi_input_dev->phys = "wmi/input0";
301 dell_wmi_input_dev->id.bustype = BUS_HOST; 222 dell_wmi_input_dev->id.bustype = BUS_HOST;
302 dell_wmi_input_dev->getkeycode = dell_wmi_getkeycode; 223
303 dell_wmi_input_dev->setkeycode = dell_wmi_setkeycode; 224 if (dell_new_hk_type) {
304 225 const struct key_entry *keymap = dell_wmi_prepare_new_keymap();
305 for (key = dell_wmi_keymap; key->type != KE_END; key++) { 226 if (!keymap) {
306 switch (key->type) { 227 err = -ENOMEM;
307 case KE_KEY: 228 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 } 229 }
316 }
317 230
318 err = input_register_device(dell_wmi_input_dev); 231 err = sparse_keymap_setup(dell_wmi_input_dev, keymap, NULL);
319 232
320 if (err) { 233 /*
321 input_free_device(dell_wmi_input_dev); 234 * Sparse keymap library makes a copy of keymap so we
322 return err; 235 * don't need the original one that was allocated.
236 */
237 kfree(keymap);
238 } else {
239 err = sparse_keymap_setup(dell_wmi_input_dev,
240 dell_wmi_legacy_keymap, NULL);
323 } 241 }
242 if (err)
243 goto err_free_dev;
244
245 err = input_register_device(dell_wmi_input_dev);
246 if (err)
247 goto err_free_keymap;
324 248
325 return 0; 249 return 0;
250
251 err_free_keymap:
252 sparse_keymap_free(dell_wmi_input_dev);
253 err_free_dev:
254 input_free_device(dell_wmi_input_dev);
255 return err;
256}
257
258static void dell_wmi_input_destroy(void)
259{
260 sparse_keymap_free(dell_wmi_input_dev);
261 input_unregister_device(dell_wmi_input_dev);
262}
263
264static void __init find_hk_type(const struct dmi_header *dm, void *dummy)
265{
266 if (dm->type == 0xb2 && dm->length > 6) {
267 dell_new_hk_type = true;
268 dell_bios_hotkey_table =
269 container_of(dm, struct dell_bios_hotkey_table, header);
270 }
326} 271}
327 272
328static int __init dell_wmi_init(void) 273static int __init dell_wmi_init(void)
@@ -331,7 +276,7 @@ static int __init dell_wmi_init(void)
331 acpi_status status; 276 acpi_status status;
332 277
333 if (!wmi_has_guid(DELL_EVENT_GUID)) { 278 if (!wmi_has_guid(DELL_EVENT_GUID)) {
334 printk(KERN_WARNING "dell-wmi: No known WMI GUID found\n"); 279 pr_warn("No known WMI GUID found\n");
335 return -ENODEV; 280 return -ENODEV;
336 } 281 }
337 282
@@ -339,34 +284,24 @@ static int __init dell_wmi_init(void)
339 acpi_video = acpi_video_backlight_support(); 284 acpi_video = acpi_video_backlight_support();
340 285
341 err = dell_wmi_input_setup(); 286 err = dell_wmi_input_setup();
342 if (err) { 287 if (err)
343 if (dell_new_hk_type)
344 kfree(dell_wmi_keymap);
345 return err; 288 return err;
346 }
347 289
348 status = wmi_install_notify_handler(DELL_EVENT_GUID, 290 status = wmi_install_notify_handler(DELL_EVENT_GUID,
349 dell_wmi_notify, NULL); 291 dell_wmi_notify, NULL);
350 if (ACPI_FAILURE(status)) { 292 if (ACPI_FAILURE(status)) {
351 input_unregister_device(dell_wmi_input_dev); 293 dell_wmi_input_destroy();
352 if (dell_new_hk_type) 294 pr_err("Unable to register notify handler - %d\n", status);
353 kfree(dell_wmi_keymap);
354 printk(KERN_ERR
355 "dell-wmi: Unable to register notify handler - %d\n",
356 status);
357 return -ENODEV; 295 return -ENODEV;
358 } 296 }
359 297
360 return 0; 298 return 0;
361} 299}
300module_init(dell_wmi_init);
362 301
363static void __exit dell_wmi_exit(void) 302static void __exit dell_wmi_exit(void)
364{ 303{
365 wmi_remove_notify_handler(DELL_EVENT_GUID); 304 wmi_remove_notify_handler(DELL_EVENT_GUID);
366 input_unregister_device(dell_wmi_input_dev); 305 dell_wmi_input_destroy();
367 if (dell_new_hk_type)
368 kfree(dell_wmi_keymap);
369} 306}
370
371module_init(dell_wmi_init);
372module_exit(dell_wmi_exit); 307module_exit(dell_wmi_exit);
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c
index 6b8e06206c46..1c45d92e2163 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
@@ -227,7 +228,7 @@ static int set_acpi(struct eeepc_laptop *eeepc, int cm, int value)
227 return -ENODEV; 228 return -ENODEV;
228 229
229 if (write_acpi_int(eeepc->handle, method, value)) 230 if (write_acpi_int(eeepc->handle, method, value))
230 pr_warning("Error writing %s\n", method); 231 pr_warn("Error writing %s\n", method);
231 return 0; 232 return 0;
232} 233}
233 234
@@ -242,7 +243,7 @@ static int get_acpi(struct eeepc_laptop *eeepc, int cm)
242 return -ENODEV; 243 return -ENODEV;
243 244
244 if (read_acpi_int(eeepc->handle, method, &value)) 245 if (read_acpi_int(eeepc->handle, method, &value))
245 pr_warning("Error reading %s\n", method); 246 pr_warn("Error reading %s\n", method);
246 return value; 247 return value;
247} 248}
248 249
@@ -260,7 +261,7 @@ static int acpi_setter_handle(struct eeepc_laptop *eeepc, int cm,
260 status = acpi_get_handle(eeepc->handle, (char *)method, 261 status = acpi_get_handle(eeepc->handle, (char *)method,
261 handle); 262 handle);
262 if (status != AE_OK) { 263 if (status != AE_OK) {
263 pr_warning("Error finding %s\n", method); 264 pr_warn("Error finding %s\n", method);
264 return -ENODEV; 265 return -ENODEV;
265 } 266 }
266 return 0; 267 return 0;
@@ -416,7 +417,7 @@ static ssize_t store_cpufv_disabled(struct device *dev,
416 switch (value) { 417 switch (value) {
417 case 0: 418 case 0:
418 if (eeepc->cpufv_disabled) 419 if (eeepc->cpufv_disabled)
419 pr_warning("cpufv enabled (not officially supported " 420 pr_warn("cpufv enabled (not officially supported "
420 "on this model)\n"); 421 "on this model)\n");
421 eeepc->cpufv_disabled = false; 422 eeepc->cpufv_disabled = false;
422 return rv; 423 return rv;
@@ -528,6 +529,15 @@ static void tpd_led_set(struct led_classdev *led_cdev,
528 queue_work(eeepc->led_workqueue, &eeepc->tpd_led_work); 529 queue_work(eeepc->led_workqueue, &eeepc->tpd_led_work);
529} 530}
530 531
532static enum led_brightness tpd_led_get(struct led_classdev *led_cdev)
533{
534 struct eeepc_laptop *eeepc;
535
536 eeepc = container_of(led_cdev, struct eeepc_laptop, tpd_led);
537
538 return get_acpi(eeepc, CM_ASL_TPD);
539}
540
531static int eeepc_led_init(struct eeepc_laptop *eeepc) 541static int eeepc_led_init(struct eeepc_laptop *eeepc)
532{ 542{
533 int rv; 543 int rv;
@@ -542,6 +552,8 @@ static int eeepc_led_init(struct eeepc_laptop *eeepc)
542 552
543 eeepc->tpd_led.name = "eeepc::touchpad"; 553 eeepc->tpd_led.name = "eeepc::touchpad";
544 eeepc->tpd_led.brightness_set = tpd_led_set; 554 eeepc->tpd_led.brightness_set = tpd_led_set;
555 if (get_acpi(eeepc, CM_ASL_TPD) >= 0) /* if method is available */
556 eeepc->tpd_led.brightness_get = tpd_led_get;
545 eeepc->tpd_led.max_brightness = 1; 557 eeepc->tpd_led.max_brightness = 1;
546 558
547 rv = led_classdev_register(&eeepc->platform_device->dev, 559 rv = led_classdev_register(&eeepc->platform_device->dev,
@@ -573,8 +585,9 @@ static bool eeepc_wlan_rfkill_blocked(struct eeepc_laptop *eeepc)
573 return true; 585 return true;
574} 586}
575 587
576static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc) 588static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc, acpi_handle handle)
577{ 589{
590 struct pci_dev *port;
578 struct pci_dev *dev; 591 struct pci_dev *dev;
579 struct pci_bus *bus; 592 struct pci_bus *bus;
580 bool blocked = eeepc_wlan_rfkill_blocked(eeepc); 593 bool blocked = eeepc_wlan_rfkill_blocked(eeepc);
@@ -587,9 +600,16 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc)
587 mutex_lock(&eeepc->hotplug_lock); 600 mutex_lock(&eeepc->hotplug_lock);
588 601
589 if (eeepc->hotplug_slot) { 602 if (eeepc->hotplug_slot) {
590 bus = pci_find_bus(0, 1); 603 port = acpi_get_pci_dev(handle);
604 if (!port) {
605 pr_warning("Unable to find port\n");
606 goto out_unlock;
607 }
608
609 bus = port->subordinate;
610
591 if (!bus) { 611 if (!bus) {
592 pr_warning("Unable to find PCI bus 1?\n"); 612 pr_warn("Unable to find PCI bus 1?\n");
593 goto out_unlock; 613 goto out_unlock;
594 } 614 }
595 615
@@ -597,15 +617,16 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc)
597 pr_err("Unable to read PCI config space?\n"); 617 pr_err("Unable to read PCI config space?\n");
598 goto out_unlock; 618 goto out_unlock;
599 } 619 }
620
600 absent = (l == 0xffffffff); 621 absent = (l == 0xffffffff);
601 622
602 if (blocked != absent) { 623 if (blocked != absent) {
603 pr_warning("BIOS says wireless lan is %s, " 624 pr_warn("BIOS says wireless lan is %s, "
604 "but the pci device is %s\n", 625 "but the pci device is %s\n",
605 blocked ? "blocked" : "unblocked", 626 blocked ? "blocked" : "unblocked",
606 absent ? "absent" : "present"); 627 absent ? "absent" : "present");
607 pr_warning("skipped wireless hotplug as probably " 628 pr_warn("skipped wireless hotplug as probably "
608 "inappropriate for this model\n"); 629 "inappropriate for this model\n");
609 goto out_unlock; 630 goto out_unlock;
610 } 631 }
611 632
@@ -635,6 +656,17 @@ out_unlock:
635 mutex_unlock(&eeepc->hotplug_lock); 656 mutex_unlock(&eeepc->hotplug_lock);
636} 657}
637 658
659static void eeepc_rfkill_hotplug_update(struct eeepc_laptop *eeepc, char *node)
660{
661 acpi_status status = AE_OK;
662 acpi_handle handle;
663
664 status = acpi_get_handle(NULL, node, &handle);
665
666 if (ACPI_SUCCESS(status))
667 eeepc_rfkill_hotplug(eeepc, handle);
668}
669
638static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) 670static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
639{ 671{
640 struct eeepc_laptop *eeepc = data; 672 struct eeepc_laptop *eeepc = data;
@@ -642,7 +674,7 @@ static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
642 if (event != ACPI_NOTIFY_BUS_CHECK) 674 if (event != ACPI_NOTIFY_BUS_CHECK)
643 return; 675 return;
644 676
645 eeepc_rfkill_hotplug(eeepc); 677 eeepc_rfkill_hotplug(eeepc, handle);
646} 678}
647 679
648static int eeepc_register_rfkill_notifier(struct eeepc_laptop *eeepc, 680static int eeepc_register_rfkill_notifier(struct eeepc_laptop *eeepc,
@@ -659,7 +691,13 @@ static int eeepc_register_rfkill_notifier(struct eeepc_laptop *eeepc,
659 eeepc_rfkill_notify, 691 eeepc_rfkill_notify,
660 eeepc); 692 eeepc);
661 if (ACPI_FAILURE(status)) 693 if (ACPI_FAILURE(status))
662 pr_warning("Failed to register notify on %s\n", node); 694 pr_warn("Failed to register notify on %s\n", node);
695
696 /*
697 * Refresh pci hotplug in case the rfkill state was
698 * changed during setup.
699 */
700 eeepc_rfkill_hotplug(eeepc, handle);
663 } else 701 } else
664 return -ENODEV; 702 return -ENODEV;
665 703
@@ -681,6 +719,12 @@ static void eeepc_unregister_rfkill_notifier(struct eeepc_laptop *eeepc,
681 if (ACPI_FAILURE(status)) 719 if (ACPI_FAILURE(status))
682 pr_err("Error removing rfkill notify handler %s\n", 720 pr_err("Error removing rfkill notify handler %s\n",
683 node); 721 node);
722 /*
723 * Refresh pci hotplug in case the rfkill
724 * state was changed after
725 * eeepc_unregister_rfkill_notifier()
726 */
727 eeepc_rfkill_hotplug(eeepc, handle);
684 } 728 }
685} 729}
686 730
@@ -804,11 +848,7 @@ static void eeepc_rfkill_exit(struct eeepc_laptop *eeepc)
804 rfkill_destroy(eeepc->wlan_rfkill); 848 rfkill_destroy(eeepc->wlan_rfkill);
805 eeepc->wlan_rfkill = NULL; 849 eeepc->wlan_rfkill = NULL;
806 } 850 }
807 /* 851
808 * Refresh pci hotplug in case the rfkill state was changed after
809 * eeepc_unregister_rfkill_notifier()
810 */
811 eeepc_rfkill_hotplug(eeepc);
812 if (eeepc->hotplug_slot) 852 if (eeepc->hotplug_slot)
813 pci_hp_deregister(eeepc->hotplug_slot); 853 pci_hp_deregister(eeepc->hotplug_slot);
814 854
@@ -877,11 +917,6 @@ static int eeepc_rfkill_init(struct eeepc_laptop *eeepc)
877 eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P5"); 917 eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P5");
878 eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P6"); 918 eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P6");
879 eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P7"); 919 eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P7");
880 /*
881 * Refresh pci hotplug in case the rfkill state was changed during
882 * setup.
883 */
884 eeepc_rfkill_hotplug(eeepc);
885 920
886exit: 921exit:
887 if (result && result != -ENODEV) 922 if (result && result != -ENODEV)
@@ -916,8 +951,11 @@ static int eeepc_hotk_restore(struct device *device)
916 struct eeepc_laptop *eeepc = dev_get_drvdata(device); 951 struct eeepc_laptop *eeepc = dev_get_drvdata(device);
917 952
918 /* Refresh both wlan rfkill state and pci hotplug */ 953 /* Refresh both wlan rfkill state and pci hotplug */
919 if (eeepc->wlan_rfkill) 954 if (eeepc->wlan_rfkill) {
920 eeepc_rfkill_hotplug(eeepc); 955 eeepc_rfkill_hotplug_update(eeepc, "\\_SB.PCI0.P0P5");
956 eeepc_rfkill_hotplug_update(eeepc, "\\_SB.PCI0.P0P6");
957 eeepc_rfkill_hotplug_update(eeepc, "\\_SB.PCI0.P0P7");
958 }
921 959
922 if (eeepc->bluetooth_rfkill) 960 if (eeepc->bluetooth_rfkill)
923 rfkill_set_sw_state(eeepc->bluetooth_rfkill, 961 rfkill_set_sw_state(eeepc->bluetooth_rfkill,
@@ -1114,7 +1152,7 @@ static int update_bl_status(struct backlight_device *bd)
1114 return set_brightness(bd, bd->props.brightness); 1152 return set_brightness(bd, bd->props.brightness);
1115} 1153}
1116 1154
1117static struct backlight_ops eeepcbl_ops = { 1155static const struct backlight_ops eeepcbl_ops = {
1118 .get_brightness = read_brightness, 1156 .get_brightness = read_brightness,
1119 .update_status = update_bl_status, 1157 .update_status = update_bl_status,
1120}; 1158};
@@ -1135,6 +1173,7 @@ static int eeepc_backlight_init(struct eeepc_laptop *eeepc)
1135 struct backlight_device *bd; 1173 struct backlight_device *bd;
1136 1174
1137 memset(&props, 0, sizeof(struct backlight_properties)); 1175 memset(&props, 0, sizeof(struct backlight_properties));
1176 props.type = BACKLIGHT_PLATFORM;
1138 props.max_brightness = 15; 1177 props.max_brightness = 15;
1139 bd = backlight_device_register(EEEPC_LAPTOP_FILE, 1178 bd = backlight_device_register(EEEPC_LAPTOP_FILE,
1140 &eeepc->platform_device->dev, eeepc, 1179 &eeepc->platform_device->dev, eeepc,
@@ -1193,9 +1232,9 @@ static int eeepc_input_init(struct eeepc_laptop *eeepc)
1193 eeepc->inputdev = input; 1232 eeepc->inputdev = input;
1194 return 0; 1233 return 0;
1195 1234
1196 err_free_keymap: 1235err_free_keymap:
1197 sparse_keymap_free(input); 1236 sparse_keymap_free(input);
1198 err_free_dev: 1237err_free_dev:
1199 input_free_device(input); 1238 input_free_device(input);
1200 return error; 1239 return error;
1201} 1240}
@@ -1206,6 +1245,7 @@ static void eeepc_input_exit(struct eeepc_laptop *eeepc)
1206 sparse_keymap_free(eeepc->inputdev); 1245 sparse_keymap_free(eeepc->inputdev);
1207 input_unregister_device(eeepc->inputdev); 1246 input_unregister_device(eeepc->inputdev);
1208 } 1247 }
1248 eeepc->inputdev = NULL;
1209} 1249}
1210 1250
1211/* 1251/*
@@ -1308,7 +1348,7 @@ static void cmsg_quirk(struct eeepc_laptop *eeepc, int cm, const char *name)
1308{ 1348{
1309 int dummy; 1349 int dummy;
1310 1350
1311 /* Some BIOSes do not report cm although it is avaliable. 1351 /* Some BIOSes do not report cm although it is available.
1312 Check if cm_getv[cm] works and, if yes, assume cm should be set. */ 1352 Check if cm_getv[cm] works and, if yes, assume cm should be set. */
1313 if (!(eeepc->cm_supported & (1 << cm)) 1353 if (!(eeepc->cm_supported & (1 << cm))
1314 && !read_acpi_int(eeepc->handle, cm_getv[cm], &dummy)) { 1354 && !read_acpi_int(eeepc->handle, cm_getv[cm], &dummy)) {
@@ -1326,16 +1366,15 @@ static void cmsg_quirks(struct eeepc_laptop *eeepc)
1326 cmsg_quirk(eeepc, CM_ASL_TPD, "TPD"); 1366 cmsg_quirk(eeepc, CM_ASL_TPD, "TPD");
1327} 1367}
1328 1368
1329static int eeepc_acpi_init(struct eeepc_laptop *eeepc, 1369static int __devinit eeepc_acpi_init(struct eeepc_laptop *eeepc)
1330 struct acpi_device *device)
1331{ 1370{
1332 unsigned int init_flags; 1371 unsigned int init_flags;
1333 int result; 1372 int result;
1334 1373
1335 result = acpi_bus_get_status(device); 1374 result = acpi_bus_get_status(eeepc->device);
1336 if (result) 1375 if (result)
1337 return result; 1376 return result;
1338 if (!device->status.present) { 1377 if (!eeepc->device->status.present) {
1339 pr_err("Hotkey device not present, aborting\n"); 1378 pr_err("Hotkey device not present, aborting\n");
1340 return -ENODEV; 1379 return -ENODEV;
1341 } 1380 }
@@ -1384,12 +1423,13 @@ static int __devinit eeepc_acpi_add(struct acpi_device *device)
1384 strcpy(acpi_device_name(device), EEEPC_ACPI_DEVICE_NAME); 1423 strcpy(acpi_device_name(device), EEEPC_ACPI_DEVICE_NAME);
1385 strcpy(acpi_device_class(device), EEEPC_ACPI_CLASS); 1424 strcpy(acpi_device_class(device), EEEPC_ACPI_CLASS);
1386 device->driver_data = eeepc; 1425 device->driver_data = eeepc;
1426 eeepc->device = device;
1387 1427
1388 eeepc->hotplug_disabled = hotplug_disabled; 1428 eeepc->hotplug_disabled = hotplug_disabled;
1389 1429
1390 eeepc_dmi_check(eeepc); 1430 eeepc_dmi_check(eeepc);
1391 1431
1392 result = eeepc_acpi_init(eeepc, device); 1432 result = eeepc_acpi_init(eeepc);
1393 if (result) 1433 if (result)
1394 goto fail_platform; 1434 goto fail_platform;
1395 eeepc_enable_camera(eeepc); 1435 eeepc_enable_camera(eeepc);
diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c
index 9dc50fbf3d0b..4aa867a9b88b 100644
--- a/drivers/platform/x86/eeepc-wmi.c
+++ b/drivers/platform/x86/eeepc-wmi.c
@@ -2,6 +2,7 @@
2 * Eee PC WMI hotkey driver 2 * Eee PC WMI hotkey driver
3 * 3 *
4 * Copyright(C) 2010 Intel Corporation. 4 * Copyright(C) 2010 Intel Corporation.
5 * Copyright(C) 2010-2011 Corentin Chary <corentin.chary@gmail.com>
5 * 6 *
6 * Portions based on wistron_btns.c: 7 * Portions based on wistron_btns.c:
7 * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz> 8 * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz>
@@ -28,385 +29,141 @@
28#include <linux/kernel.h> 29#include <linux/kernel.h>
29#include <linux/module.h> 30#include <linux/module.h>
30#include <linux/init.h> 31#include <linux/init.h>
31#include <linux/types.h>
32#include <linux/slab.h>
33#include <linux/input.h> 32#include <linux/input.h>
34#include <linux/input/sparse-keymap.h> 33#include <linux/input/sparse-keymap.h>
35#include <linux/fb.h> 34#include <linux/dmi.h>
36#include <linux/backlight.h>
37#include <linux/platform_device.h>
38#include <acpi/acpi_bus.h> 35#include <acpi/acpi_bus.h>
39#include <acpi/acpi_drivers.h> 36
37#include "asus-wmi.h"
40 38
41#define EEEPC_WMI_FILE "eeepc-wmi" 39#define EEEPC_WMI_FILE "eeepc-wmi"
42 40
43MODULE_AUTHOR("Yong Wang <yong.y.wang@intel.com>"); 41MODULE_AUTHOR("Corentin Chary <corentincj@iksaif.net>");
44MODULE_DESCRIPTION("Eee PC WMI Hotkey Driver"); 42MODULE_DESCRIPTION("Eee PC WMI Hotkey Driver");
45MODULE_LICENSE("GPL"); 43MODULE_LICENSE("GPL");
46 44
45#define EEEPC_ACPI_HID "ASUS010" /* old _HID used in eeepc-laptop */
46
47#define EEEPC_WMI_EVENT_GUID "ABBC0F72-8EA1-11D1-00A0-C90629100000" 47#define EEEPC_WMI_EVENT_GUID "ABBC0F72-8EA1-11D1-00A0-C90629100000"
48#define EEEPC_WMI_MGMT_GUID "97845ED0-4E6D-11DE-8A39-0800200C9A66"
49 48
50MODULE_ALIAS("wmi:"EEEPC_WMI_EVENT_GUID); 49MODULE_ALIAS("wmi:"EEEPC_WMI_EVENT_GUID);
51MODULE_ALIAS("wmi:"EEEPC_WMI_MGMT_GUID);
52 50
53#define NOTIFY_BRNUP_MIN 0x11 51static bool hotplug_wireless;
54#define NOTIFY_BRNUP_MAX 0x1f
55#define NOTIFY_BRNDOWN_MIN 0x20
56#define NOTIFY_BRNDOWN_MAX 0x2e
57 52
58#define EEEPC_WMI_METHODID_DEVS 0x53564544 53module_param(hotplug_wireless, bool, 0444);
59#define EEEPC_WMI_METHODID_DSTS 0x53544344 54MODULE_PARM_DESC(hotplug_wireless,
60 55 "Enable hotplug for wireless device. "
61#define EEEPC_WMI_DEVID_BACKLIGHT 0x00050012 56 "If your laptop needs that, please report to "
57 "acpi4asus-user@lists.sourceforge.net.");
62 58
63static const struct key_entry eeepc_wmi_keymap[] = { 59static const struct key_entry eeepc_wmi_keymap[] = {
64 /* Sleep already handled via generic ACPI code */ 60 /* Sleep already handled via generic ACPI code */
65 { KE_KEY, 0x5d, { KEY_WLAN } },
66 { KE_KEY, 0x32, { KEY_MUTE } },
67 { KE_KEY, 0x31, { KEY_VOLUMEDOWN } },
68 { KE_KEY, 0x30, { KEY_VOLUMEUP } }, 61 { KE_KEY, 0x30, { KEY_VOLUMEUP } },
69 { KE_IGNORE, NOTIFY_BRNDOWN_MIN, { KEY_BRIGHTNESSDOWN } }, 62 { KE_KEY, 0x31, { KEY_VOLUMEDOWN } },
70 { KE_IGNORE, NOTIFY_BRNUP_MIN, { KEY_BRIGHTNESSUP } }, 63 { KE_KEY, 0x32, { KEY_MUTE } },
64 { KE_KEY, 0x5c, { KEY_F15 } }, /* Power Gear key */
65 { KE_KEY, 0x5d, { KEY_WLAN } },
66 { KE_KEY, 0x6b, { KEY_TOUCHPAD_TOGGLE } }, /* Toggle Touchpad */
67 { KE_KEY, 0x82, { KEY_CAMERA } },
68 { KE_KEY, 0x83, { KEY_CAMERA_ZOOMIN } },
69 { KE_KEY, 0x88, { KEY_WLAN } },
70 { KE_KEY, 0xbd, { KEY_CAMERA } },
71 { KE_KEY, 0xcc, { KEY_SWITCHVIDEOMODE } }, 71 { KE_KEY, 0xcc, { KEY_SWITCHVIDEOMODE } },
72 { KE_KEY, 0xe0, { KEY_PROG1 } }, /* Task Manager */
73 { KE_KEY, 0xe1, { KEY_F14 } }, /* Change Resolution */
74 { KE_KEY, 0xe8, { KEY_SCREENLOCK } },
75 { KE_KEY, 0xe9, { KEY_BRIGHTNESS_ZERO } },
76 { KE_KEY, 0xeb, { KEY_CAMERA_ZOOMOUT } },
77 { KE_KEY, 0xec, { KEY_CAMERA_UP } },
78 { KE_KEY, 0xed, { KEY_CAMERA_DOWN } },
79 { KE_KEY, 0xee, { KEY_CAMERA_LEFT } },
80 { KE_KEY, 0xef, { KEY_CAMERA_RIGHT } },
72 { KE_END, 0}, 81 { KE_END, 0},
73}; 82};
74 83
75struct bios_args { 84static acpi_status eeepc_wmi_parse_device(acpi_handle handle, u32 level,
76 u32 dev_id; 85 void *context, void **retval)
77 u32 ctrl_param;
78};
79
80struct eeepc_wmi {
81 struct input_dev *inputdev;
82 struct backlight_device *backlight_device;
83};
84
85static struct platform_device *platform_device;
86
87static int eeepc_wmi_input_init(struct eeepc_wmi *eeepc)
88{ 86{
89 int err; 87 pr_warn("Found legacy ATKD device (%s)\n", EEEPC_ACPI_HID);
90 88 *(bool *)context = true;
91 eeepc->inputdev = input_allocate_device(); 89 return AE_CTRL_TERMINATE;
92 if (!eeepc->inputdev)
93 return -ENOMEM;
94
95 eeepc->inputdev->name = "Eee PC WMI hotkeys";
96 eeepc->inputdev->phys = EEEPC_WMI_FILE "/input0";
97 eeepc->inputdev->id.bustype = BUS_HOST;
98 eeepc->inputdev->dev.parent = &platform_device->dev;
99
100 err = sparse_keymap_setup(eeepc->inputdev, eeepc_wmi_keymap, NULL);
101 if (err)
102 goto err_free_dev;
103
104 err = input_register_device(eeepc->inputdev);
105 if (err)
106 goto err_free_keymap;
107
108 return 0;
109
110err_free_keymap:
111 sparse_keymap_free(eeepc->inputdev);
112err_free_dev:
113 input_free_device(eeepc->inputdev);
114 return err;
115} 90}
116 91
117static void eeepc_wmi_input_exit(struct eeepc_wmi *eeepc) 92static int eeepc_wmi_check_atkd(void)
118{ 93{
119 if (eeepc->inputdev) {
120 sparse_keymap_free(eeepc->inputdev);
121 input_unregister_device(eeepc->inputdev);
122 }
123
124 eeepc->inputdev = NULL;
125}
126
127static acpi_status eeepc_wmi_get_devstate(u32 dev_id, u32 *ctrl_param)
128{
129 struct acpi_buffer input = { (acpi_size)sizeof(u32), &dev_id };
130 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
131 union acpi_object *obj;
132 acpi_status status; 94 acpi_status status;
133 u32 tmp; 95 bool found = false;
134
135 status = wmi_evaluate_method(EEEPC_WMI_MGMT_GUID,
136 1, EEEPC_WMI_METHODID_DSTS, &input, &output);
137 96
138 if (ACPI_FAILURE(status)) 97 status = acpi_get_devices(EEEPC_ACPI_HID, eeepc_wmi_parse_device,
139 return status; 98 &found, NULL);
140 99
141 obj = (union acpi_object *)output.pointer; 100 if (ACPI_FAILURE(status) || !found)
142 if (obj && obj->type == ACPI_TYPE_INTEGER)
143 tmp = (u32)obj->integer.value;
144 else
145 tmp = 0;
146
147 if (ctrl_param)
148 *ctrl_param = tmp;
149
150 kfree(obj);
151
152 return status;
153
154}
155
156static acpi_status eeepc_wmi_set_devstate(u32 dev_id, u32 ctrl_param)
157{
158 struct bios_args args = {
159 .dev_id = dev_id,
160 .ctrl_param = ctrl_param,
161 };
162 struct acpi_buffer input = { (acpi_size)sizeof(args), &args };
163 acpi_status status;
164
165 status = wmi_evaluate_method(EEEPC_WMI_MGMT_GUID,
166 1, EEEPC_WMI_METHODID_DEVS, &input, NULL);
167
168 return status;
169}
170
171static int read_brightness(struct backlight_device *bd)
172{
173 static u32 ctrl_param;
174 acpi_status status;
175
176 status = eeepc_wmi_get_devstate(EEEPC_WMI_DEVID_BACKLIGHT, &ctrl_param);
177
178 if (ACPI_FAILURE(status))
179 return -1;
180 else
181 return ctrl_param & 0xFF;
182}
183
184static int update_bl_status(struct backlight_device *bd)
185{
186
187 static u32 ctrl_param;
188 acpi_status status;
189
190 ctrl_param = bd->props.brightness;
191
192 status = eeepc_wmi_set_devstate(EEEPC_WMI_DEVID_BACKLIGHT, ctrl_param);
193
194 if (ACPI_FAILURE(status))
195 return -1;
196 else
197 return 0; 101 return 0;
102 return -1;
198} 103}
199 104
200static const struct backlight_ops eeepc_wmi_bl_ops = { 105static int eeepc_wmi_probe(struct platform_device *pdev)
201 .get_brightness = read_brightness,
202 .update_status = update_bl_status,
203};
204
205static int eeepc_wmi_backlight_notify(struct eeepc_wmi *eeepc, int code)
206{ 106{
207 struct backlight_device *bd = eeepc->backlight_device; 107 if (eeepc_wmi_check_atkd()) {
208 int old = bd->props.brightness; 108 pr_warn("WMI device present, but legacy ATKD device is also "
209 int new = old; 109 "present and enabled\n");
210 110 pr_warn("You probably booted with acpi_osi=\"Linux\" or "
211 if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX) 111 "acpi_osi=\"!Windows 2009\"\n");
212 new = code - NOTIFY_BRNUP_MIN + 1; 112 pr_warn("Can't load eeepc-wmi, use default acpi_osi "
213 else if (code >= NOTIFY_BRNDOWN_MIN && code <= NOTIFY_BRNDOWN_MAX) 113 "(preferred) or eeepc-laptop\n");
214 new = code - NOTIFY_BRNDOWN_MIN; 114 return -EBUSY;
215
216 bd->props.brightness = new;
217 backlight_update_status(bd);
218 backlight_force_update(bd, BACKLIGHT_UPDATE_HOTKEY);
219
220 return old;
221}
222
223static int eeepc_wmi_backlight_init(struct eeepc_wmi *eeepc)
224{
225 struct backlight_device *bd;
226 struct backlight_properties props;
227
228 memset(&props, 0, sizeof(struct backlight_properties));
229 props.max_brightness = 15;
230 bd = backlight_device_register(EEEPC_WMI_FILE,
231 &platform_device->dev, eeepc,
232 &eeepc_wmi_bl_ops, &props);
233 if (IS_ERR(bd)) {
234 pr_err("Could not register backlight device\n");
235 return PTR_ERR(bd);
236 } 115 }
237
238 eeepc->backlight_device = bd;
239
240 bd->props.brightness = read_brightness(bd);
241 bd->props.power = FB_BLANK_UNBLANK;
242 backlight_update_status(bd);
243
244 return 0; 116 return 0;
245} 117}
246 118
247static void eeepc_wmi_backlight_exit(struct eeepc_wmi *eeepc) 119static void eeepc_dmi_check(struct asus_wmi_driver *driver)
248{
249 if (eeepc->backlight_device)
250 backlight_device_unregister(eeepc->backlight_device);
251
252 eeepc->backlight_device = NULL;
253}
254
255static void eeepc_wmi_notify(u32 value, void *context)
256{ 120{
257 struct eeepc_wmi *eeepc = context; 121 const char *model;
258 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
259 union acpi_object *obj;
260 acpi_status status;
261 int code;
262 int orig_code;
263 122
264 status = wmi_get_event_data(value, &response); 123 model = dmi_get_system_info(DMI_PRODUCT_NAME);
265 if (status != AE_OK) { 124 if (!model)
266 pr_err("bad event status 0x%x\n", status);
267 return; 125 return;
268 }
269
270 obj = (union acpi_object *)response.pointer;
271
272 if (obj && obj->type == ACPI_TYPE_INTEGER) {
273 code = obj->integer.value;
274 orig_code = code;
275
276 if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX)
277 code = NOTIFY_BRNUP_MIN;
278 else if (code >= NOTIFY_BRNDOWN_MIN &&
279 code <= NOTIFY_BRNDOWN_MAX)
280 code = NOTIFY_BRNDOWN_MIN;
281
282 if (code == NOTIFY_BRNUP_MIN || code == NOTIFY_BRNDOWN_MIN) {
283 if (!acpi_video_backlight_support())
284 eeepc_wmi_backlight_notify(eeepc, orig_code);
285 }
286
287 if (!sparse_keymap_report_event(eeepc->inputdev,
288 code, 1, true))
289 pr_info("Unknown key %x pressed\n", code);
290 }
291
292 kfree(obj);
293}
294
295static int __devinit eeepc_wmi_platform_probe(struct platform_device *device)
296{
297 struct eeepc_wmi *eeepc;
298 int err;
299 acpi_status status;
300
301 eeepc = platform_get_drvdata(device);
302
303 err = eeepc_wmi_input_init(eeepc);
304 if (err)
305 goto error_input;
306
307 if (!acpi_video_backlight_support()) {
308 err = eeepc_wmi_backlight_init(eeepc);
309 if (err)
310 goto error_backlight;
311 } else
312 pr_info("Backlight controlled by ACPI video driver\n");
313 126
314 status = wmi_install_notify_handler(EEEPC_WMI_EVENT_GUID, 127 /*
315 eeepc_wmi_notify, eeepc); 128 * Whitelist for wlan hotplug
316 if (ACPI_FAILURE(status)) { 129 *
317 pr_err("Unable to register notify handler - %d\n", 130 * Asus 1000H needs the current hotplug code to handle
318 status); 131 * Fn+F2 correctly. We may add other Asus here later, but
319 err = -ENODEV; 132 * it seems that most of the laptops supported by asus-wmi
320 goto error_wmi; 133 * don't need to be on this list
134 */
135 if (strcmp(model, "1000H") == 0) {
136 driver->hotplug_wireless = true;
137 pr_info("wlan hotplug enabled\n");
321 } 138 }
322
323 return 0;
324
325error_wmi:
326 eeepc_wmi_backlight_exit(eeepc);
327error_backlight:
328 eeepc_wmi_input_exit(eeepc);
329error_input:
330 return err;
331} 139}
332 140
333static int __devexit eeepc_wmi_platform_remove(struct platform_device *device) 141static void eeepc_wmi_quirks(struct asus_wmi_driver *driver)
334{ 142{
335 struct eeepc_wmi *eeepc; 143 driver->hotplug_wireless = hotplug_wireless;
336 144 eeepc_dmi_check(driver);
337 eeepc = platform_get_drvdata(device);
338 wmi_remove_notify_handler(EEEPC_WMI_EVENT_GUID);
339 eeepc_wmi_backlight_exit(eeepc);
340 eeepc_wmi_input_exit(eeepc);
341
342 return 0;
343} 145}
344 146
345static struct platform_driver platform_driver = { 147static struct asus_wmi_driver asus_wmi_driver = {
346 .driver = { 148 .name = EEEPC_WMI_FILE,
347 .name = EEEPC_WMI_FILE, 149 .owner = THIS_MODULE,
348 .owner = THIS_MODULE, 150 .event_guid = EEEPC_WMI_EVENT_GUID,
349 }, 151 .keymap = eeepc_wmi_keymap,
350 .probe = eeepc_wmi_platform_probe, 152 .input_name = "Eee PC WMI hotkeys",
351 .remove = __devexit_p(eeepc_wmi_platform_remove), 153 .input_phys = EEEPC_WMI_FILE "/input0",
154 .probe = eeepc_wmi_probe,
155 .quirks = eeepc_wmi_quirks,
352}; 156};
353 157
158
354static int __init eeepc_wmi_init(void) 159static int __init eeepc_wmi_init(void)
355{ 160{
356 struct eeepc_wmi *eeepc; 161 return asus_wmi_register_driver(&asus_wmi_driver);
357 int err;
358
359 if (!wmi_has_guid(EEEPC_WMI_EVENT_GUID) ||
360 !wmi_has_guid(EEEPC_WMI_MGMT_GUID)) {
361 pr_warning("No known WMI GUID found\n");
362 return -ENODEV;
363 }
364
365 eeepc = kzalloc(sizeof(struct eeepc_wmi), GFP_KERNEL);
366 if (!eeepc)
367 return -ENOMEM;
368
369 platform_device = platform_device_alloc(EEEPC_WMI_FILE, -1);
370 if (!platform_device) {
371 pr_warning("Unable to allocate platform device\n");
372 err = -ENOMEM;
373 goto fail_platform;
374 }
375
376 err = platform_device_add(platform_device);
377 if (err) {
378 pr_warning("Unable to add platform device\n");
379 goto put_dev;
380 }
381
382 platform_set_drvdata(platform_device, eeepc);
383
384 err = platform_driver_register(&platform_driver);
385 if (err) {
386 pr_warning("Unable to register platform driver\n");
387 goto del_dev;
388 }
389
390 return 0;
391
392del_dev:
393 platform_device_del(platform_device);
394put_dev:
395 platform_device_put(platform_device);
396fail_platform:
397 kfree(eeepc);
398
399 return err;
400} 162}
401 163
402static void __exit eeepc_wmi_exit(void) 164static void __exit eeepc_wmi_exit(void)
403{ 165{
404 struct eeepc_wmi *eeepc; 166 asus_wmi_unregister_driver(&asus_wmi_driver);
405
406 eeepc = platform_get_drvdata(platform_device);
407 platform_driver_unregister(&platform_driver);
408 platform_device_unregister(platform_device);
409 kfree(eeepc);
410} 167}
411 168
412module_init(eeepc_wmi_init); 169module_init(eeepc_wmi_init);
diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c
index f44cd2620ff9..6b26666b37f2 100644
--- a/drivers/platform/x86/fujitsu-laptop.c
+++ b/drivers/platform/x86/fujitsu-laptop.c
@@ -56,6 +56,8 @@
56 * 56 *
57 */ 57 */
58 58
59#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
60
59#include <linux/module.h> 61#include <linux/module.h>
60#include <linux/kernel.h> 62#include <linux/kernel.h>
61#include <linux/init.h> 63#include <linux/init.h>
@@ -437,7 +439,7 @@ static int bl_update_status(struct backlight_device *b)
437 return ret; 439 return ret;
438} 440}
439 441
440static struct backlight_ops fujitsubl_ops = { 442static const struct backlight_ops fujitsubl_ops = {
441 .get_brightness = bl_get_brightness, 443 .get_brightness = bl_get_brightness,
442 .update_status = bl_update_status, 444 .update_status = bl_update_status,
443}; 445};
@@ -585,8 +587,7 @@ static struct platform_driver fujitsupf_driver = {
585static void dmi_check_cb_common(const struct dmi_system_id *id) 587static void dmi_check_cb_common(const struct dmi_system_id *id)
586{ 588{
587 acpi_handle handle; 589 acpi_handle handle;
588 printk(KERN_INFO "fujitsu-laptop: Identified laptop model '%s'.\n", 590 pr_info("Identified laptop model '%s'\n", id->ident);
589 id->ident);
590 if (use_alt_lcd_levels == -1) { 591 if (use_alt_lcd_levels == -1) {
591 if (ACPI_SUCCESS(acpi_get_handle(NULL, 592 if (ACPI_SUCCESS(acpi_get_handle(NULL,
592 "\\_SB.PCI0.LPCB.FJEX.SBL2", &handle))) 593 "\\_SB.PCI0.LPCB.FJEX.SBL2", &handle)))
@@ -689,13 +690,13 @@ static int acpi_fujitsu_add(struct acpi_device *device)
689 if (error) 690 if (error)
690 goto err_free_input_dev; 691 goto err_free_input_dev;
691 692
692 result = acpi_bus_get_power(fujitsu->acpi_handle, &state); 693 result = acpi_bus_update_power(fujitsu->acpi_handle, &state);
693 if (result) { 694 if (result) {
694 printk(KERN_ERR "Error reading power state\n"); 695 pr_err("Error reading power state\n");
695 goto err_unregister_input_dev; 696 goto err_unregister_input_dev;
696 } 697 }
697 698
698 printk(KERN_INFO "ACPI: %s [%s] (%s)\n", 699 pr_info("ACPI: %s [%s] (%s)\n",
699 acpi_device_name(device), acpi_device_bid(device), 700 acpi_device_name(device), acpi_device_bid(device),
700 !device->power.state ? "on" : "off"); 701 !device->power.state ? "on" : "off");
701 702
@@ -707,7 +708,7 @@ static int acpi_fujitsu_add(struct acpi_device *device)
707 if (ACPI_FAILURE 708 if (ACPI_FAILURE
708 (acpi_evaluate_object 709 (acpi_evaluate_object
709 (device->handle, METHOD_NAME__INI, NULL, NULL))) 710 (device->handle, METHOD_NAME__INI, NULL, NULL)))
710 printk(KERN_ERR "_INI Method failed\n"); 711 pr_err("_INI Method failed\n");
711 } 712 }
712 713
713 /* do config (detect defaults) */ 714 /* do config (detect defaults) */
@@ -827,7 +828,7 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
827 error = kfifo_alloc(&fujitsu_hotkey->fifo, RINGBUFFERSIZE * sizeof(int), 828 error = kfifo_alloc(&fujitsu_hotkey->fifo, RINGBUFFERSIZE * sizeof(int),
828 GFP_KERNEL); 829 GFP_KERNEL);
829 if (error) { 830 if (error) {
830 printk(KERN_ERR "kfifo_alloc failed\n"); 831 pr_err("kfifo_alloc failed\n");
831 goto err_stop; 832 goto err_stop;
832 } 833 }
833 834
@@ -857,15 +858,15 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
857 if (error) 858 if (error)
858 goto err_free_input_dev; 859 goto err_free_input_dev;
859 860
860 result = acpi_bus_get_power(fujitsu_hotkey->acpi_handle, &state); 861 result = acpi_bus_update_power(fujitsu_hotkey->acpi_handle, &state);
861 if (result) { 862 if (result) {
862 printk(KERN_ERR "Error reading power state\n"); 863 pr_err("Error reading power state\n");
863 goto err_unregister_input_dev; 864 goto err_unregister_input_dev;
864 } 865 }
865 866
866 printk(KERN_INFO "ACPI: %s [%s] (%s)\n", 867 pr_info("ACPI: %s [%s] (%s)\n",
867 acpi_device_name(device), acpi_device_bid(device), 868 acpi_device_name(device), acpi_device_bid(device),
868 !device->power.state ? "on" : "off"); 869 !device->power.state ? "on" : "off");
869 870
870 fujitsu_hotkey->dev = device; 871 fujitsu_hotkey->dev = device;
871 872
@@ -875,7 +876,7 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
875 if (ACPI_FAILURE 876 if (ACPI_FAILURE
876 (acpi_evaluate_object 877 (acpi_evaluate_object
877 (device->handle, METHOD_NAME__INI, NULL, NULL))) 878 (device->handle, METHOD_NAME__INI, NULL, NULL)))
878 printk(KERN_ERR "_INI Method failed\n"); 879 pr_err("_INI Method failed\n");
879 } 880 }
880 881
881 i = 0; 882 i = 0;
@@ -897,8 +898,7 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
897 call_fext_func(FUNC_RFKILL, 0x4, 0x0, 0x0); 898 call_fext_func(FUNC_RFKILL, 0x4, 0x0, 0x0);
898 899
899 /* Suspect this is a keymap of the application panel, print it */ 900 /* Suspect this is a keymap of the application panel, print it */
900 printk(KERN_INFO "fujitsu-laptop: BTNI: [0x%x]\n", 901 pr_info("BTNI: [0x%x]\n", call_fext_func(FUNC_BUTTONS, 0x0, 0x0, 0x0));
901 call_fext_func(FUNC_BUTTONS, 0x0, 0x0, 0x0));
902 902
903#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE) 903#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE)
904 if (call_fext_func(FUNC_LEDS, 0x0, 0x0, 0x0) & LOGOLAMP_POWERON) { 904 if (call_fext_func(FUNC_LEDS, 0x0, 0x0, 0x0) & LOGOLAMP_POWERON) {
@@ -907,8 +907,8 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
907 if (result == 0) { 907 if (result == 0) {
908 fujitsu_hotkey->logolamp_registered = 1; 908 fujitsu_hotkey->logolamp_registered = 1;
909 } else { 909 } else {
910 printk(KERN_ERR "fujitsu-laptop: Could not register " 910 pr_err("Could not register LED handler for logo lamp, error %i\n",
911 "LED handler for logo lamp, error %i\n", result); 911 result);
912 } 912 }
913 } 913 }
914 914
@@ -919,8 +919,8 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
919 if (result == 0) { 919 if (result == 0) {
920 fujitsu_hotkey->kblamps_registered = 1; 920 fujitsu_hotkey->kblamps_registered = 1;
921 } else { 921 } else {
922 printk(KERN_ERR "fujitsu-laptop: Could not register " 922 pr_err("Could not register LED handler for keyboard lamps, error %i\n",
923 "LED handler for keyboard lamps, error %i\n", result); 923 result);
924 } 924 }
925 } 925 }
926#endif 926#endif
@@ -1128,6 +1128,7 @@ static int __init fujitsu_init(void)
1128 1128
1129 memset(&props, 0, sizeof(struct backlight_properties)); 1129 memset(&props, 0, sizeof(struct backlight_properties));
1130 max_brightness = fujitsu->max_brightness; 1130 max_brightness = fujitsu->max_brightness;
1131 props.type = BACKLIGHT_PLATFORM;
1131 props.max_brightness = max_brightness - 1; 1132 props.max_brightness = max_brightness - 1;
1132 fujitsu->bl_device = backlight_device_register("fujitsu-laptop", 1133 fujitsu->bl_device = backlight_device_register("fujitsu-laptop",
1133 NULL, NULL, 1134 NULL, NULL,
@@ -1168,8 +1169,7 @@ static int __init fujitsu_init(void)
1168 fujitsu->bl_device->props.power = 0; 1169 fujitsu->bl_device->props.power = 0;
1169 } 1170 }
1170 1171
1171 printk(KERN_INFO "fujitsu-laptop: driver " FUJITSU_DRIVER_VERSION 1172 pr_info("driver " FUJITSU_DRIVER_VERSION " successfully loaded\n");
1172 " successfully loaded.\n");
1173 1173
1174 return 0; 1174 return 0;
1175 1175
@@ -1215,7 +1215,7 @@ static void __exit fujitsu_cleanup(void)
1215 1215
1216 kfree(fujitsu); 1216 kfree(fujitsu);
1217 1217
1218 printk(KERN_INFO "fujitsu-laptop: driver unloaded.\n"); 1218 pr_info("driver unloaded\n");
1219} 1219}
1220 1220
1221module_init(fujitsu_init); 1221module_init(fujitsu_init);
@@ -1240,7 +1240,7 @@ MODULE_ALIAS("dmi:*:svnFUJITSUSIEMENS:*:pvr:rvnFUJITSU:rnFJNB1D3:*:cvrS6410:*");
1240MODULE_ALIAS("dmi:*:svnFUJITSUSIEMENS:*:pvr:rvnFUJITSU:rnFJNB1E6:*:cvrS6420:*"); 1240MODULE_ALIAS("dmi:*:svnFUJITSUSIEMENS:*:pvr:rvnFUJITSU:rnFJNB1E6:*:cvrS6420:*");
1241MODULE_ALIAS("dmi:*:svnFUJITSU:*:pvr:rvnFUJITSU:rnFJNB19C:*:cvrS7020:*"); 1241MODULE_ALIAS("dmi:*:svnFUJITSU:*:pvr:rvnFUJITSU:rnFJNB19C:*:cvrS7020:*");
1242 1242
1243static struct pnp_device_id pnp_ids[] = { 1243static struct pnp_device_id pnp_ids[] __used = {
1244 {.id = "FUJ02bf"}, 1244 {.id = "FUJ02bf"},
1245 {.id = "FUJ02B1"}, 1245 {.id = "FUJ02B1"},
1246 {.id = "FUJ02E3"}, 1246 {.id = "FUJ02E3"},
diff --git a/drivers/platform/x86/hdaps.c b/drivers/platform/x86/hdaps.c
new file mode 100644
index 000000000000..5a34973dc164
--- /dev/null
+++ b/drivers/platform/x86/hdaps.c
@@ -0,0 +1,638 @@
1/*
2 * hdaps.c - driver for IBM's Hard Drive Active Protection System
3 *
4 * Copyright (C) 2005 Robert Love <rml@novell.com>
5 * Copyright (C) 2005 Jesper Juhl <jesper.juhl@gmail.com>
6 *
7 * The HardDisk Active Protection System (hdaps) is present in IBM ThinkPads
8 * starting with the R40, T41, and X40. It provides a basic two-axis
9 * accelerometer and other data, such as the device's temperature.
10 *
11 * This driver is based on the document by Mark A. Smith available at
12 * http://www.almaden.ibm.com/cs/people/marksmith/tpaps.html and a lot of trial
13 * and error.
14 *
15 * This program is free software; you can redistribute it and/or modify it
16 * under the terms of the GNU General Public License v2 as published by the
17 * Free Software Foundation.
18 *
19 * This program is distributed in the hope that it will be useful, but WITHOUT
20 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
22 * more details.
23 *
24 * You should have received a copy of the GNU General Public License along with
25 * this program; if not, write to the Free Software Foundation, Inc.,
26 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
27 */
28
29#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
30
31#include <linux/delay.h>
32#include <linux/platform_device.h>
33#include <linux/input-polldev.h>
34#include <linux/kernel.h>
35#include <linux/mutex.h>
36#include <linux/module.h>
37#include <linux/timer.h>
38#include <linux/dmi.h>
39#include <linux/jiffies.h>
40#include <linux/io.h>
41
42#define HDAPS_LOW_PORT 0x1600 /* first port used by hdaps */
43#define HDAPS_NR_PORTS 0x30 /* number of ports: 0x1600 - 0x162f */
44
45#define HDAPS_PORT_STATE 0x1611 /* device state */
46#define HDAPS_PORT_YPOS 0x1612 /* y-axis position */
47#define HDAPS_PORT_XPOS 0x1614 /* x-axis position */
48#define HDAPS_PORT_TEMP1 0x1616 /* device temperature, in Celsius */
49#define HDAPS_PORT_YVAR 0x1617 /* y-axis variance (what is this?) */
50#define HDAPS_PORT_XVAR 0x1619 /* x-axis variance (what is this?) */
51#define HDAPS_PORT_TEMP2 0x161b /* device temperature (again?) */
52#define HDAPS_PORT_UNKNOWN 0x161c /* what is this? */
53#define HDAPS_PORT_KMACT 0x161d /* keyboard or mouse activity */
54
55#define STATE_FRESH 0x50 /* accelerometer data is fresh */
56
57#define KEYBD_MASK 0x20 /* set if keyboard activity */
58#define MOUSE_MASK 0x40 /* set if mouse activity */
59#define KEYBD_ISSET(n) (!! (n & KEYBD_MASK)) /* keyboard used? */
60#define MOUSE_ISSET(n) (!! (n & MOUSE_MASK)) /* mouse used? */
61
62#define INIT_TIMEOUT_MSECS 4000 /* wait up to 4s for device init ... */
63#define INIT_WAIT_MSECS 200 /* ... in 200ms increments */
64
65#define HDAPS_POLL_INTERVAL 50 /* poll for input every 1/20s (50 ms)*/
66#define HDAPS_INPUT_FUZZ 4 /* input event threshold */
67#define HDAPS_INPUT_FLAT 4
68
69#define HDAPS_X_AXIS (1 << 0)
70#define HDAPS_Y_AXIS (1 << 1)
71#define HDAPS_BOTH_AXES (HDAPS_X_AXIS | HDAPS_Y_AXIS)
72
73static struct platform_device *pdev;
74static struct input_polled_dev *hdaps_idev;
75static unsigned int hdaps_invert;
76static u8 km_activity;
77static int rest_x;
78static int rest_y;
79
80static DEFINE_MUTEX(hdaps_mtx);
81
82/*
83 * __get_latch - Get the value from a given port. Callers must hold hdaps_mtx.
84 */
85static inline u8 __get_latch(u16 port)
86{
87 return inb(port) & 0xff;
88}
89
90/*
91 * __check_latch - Check a port latch for a given value. Returns zero if the
92 * port contains the given value. Callers must hold hdaps_mtx.
93 */
94static inline int __check_latch(u16 port, u8 val)
95{
96 if (__get_latch(port) == val)
97 return 0;
98 return -EINVAL;
99}
100
101/*
102 * __wait_latch - Wait up to 100us for a port latch to get a certain value,
103 * returning zero if the value is obtained. Callers must hold hdaps_mtx.
104 */
105static int __wait_latch(u16 port, u8 val)
106{
107 unsigned int i;
108
109 for (i = 0; i < 20; i++) {
110 if (!__check_latch(port, val))
111 return 0;
112 udelay(5);
113 }
114
115 return -EIO;
116}
117
118/*
119 * __device_refresh - request a refresh from the accelerometer. Does not wait
120 * for refresh to complete. Callers must hold hdaps_mtx.
121 */
122static void __device_refresh(void)
123{
124 udelay(200);
125 if (inb(0x1604) != STATE_FRESH) {
126 outb(0x11, 0x1610);
127 outb(0x01, 0x161f);
128 }
129}
130
131/*
132 * __device_refresh_sync - request a synchronous refresh from the
133 * accelerometer. We wait for the refresh to complete. Returns zero if
134 * successful and nonzero on error. Callers must hold hdaps_mtx.
135 */
136static int __device_refresh_sync(void)
137{
138 __device_refresh();
139 return __wait_latch(0x1604, STATE_FRESH);
140}
141
142/*
143 * __device_complete - indicate to the accelerometer that we are done reading
144 * data, and then initiate an async refresh. Callers must hold hdaps_mtx.
145 */
146static inline void __device_complete(void)
147{
148 inb(0x161f);
149 inb(0x1604);
150 __device_refresh();
151}
152
153/*
154 * hdaps_readb_one - reads a byte from a single I/O port, placing the value in
155 * the given pointer. Returns zero on success or a negative error on failure.
156 * Can sleep.
157 */
158static int hdaps_readb_one(unsigned int port, u8 *val)
159{
160 int ret;
161
162 mutex_lock(&hdaps_mtx);
163
164 /* do a sync refresh -- we need to be sure that we read fresh data */
165 ret = __device_refresh_sync();
166 if (ret)
167 goto out;
168
169 *val = inb(port);
170 __device_complete();
171
172out:
173 mutex_unlock(&hdaps_mtx);
174 return ret;
175}
176
177/* __hdaps_read_pair - internal lockless helper for hdaps_read_pair(). */
178static int __hdaps_read_pair(unsigned int port1, unsigned int port2,
179 int *x, int *y)
180{
181 /* do a sync refresh -- we need to be sure that we read fresh data */
182 if (__device_refresh_sync())
183 return -EIO;
184
185 *y = inw(port2);
186 *x = inw(port1);
187 km_activity = inb(HDAPS_PORT_KMACT);
188 __device_complete();
189
190 /* hdaps_invert is a bitvector to negate the axes */
191 if (hdaps_invert & HDAPS_X_AXIS)
192 *x = -*x;
193 if (hdaps_invert & HDAPS_Y_AXIS)
194 *y = -*y;
195
196 return 0;
197}
198
199/*
200 * hdaps_read_pair - reads the values from a pair of ports, placing the values
201 * in the given pointers. Returns zero on success. Can sleep.
202 */
203static int hdaps_read_pair(unsigned int port1, unsigned int port2,
204 int *val1, int *val2)
205{
206 int ret;
207
208 mutex_lock(&hdaps_mtx);
209 ret = __hdaps_read_pair(port1, port2, val1, val2);
210 mutex_unlock(&hdaps_mtx);
211
212 return ret;
213}
214
215/*
216 * hdaps_device_init - initialize the accelerometer. Returns zero on success
217 * and negative error code on failure. Can sleep.
218 */
219static int hdaps_device_init(void)
220{
221 int total, ret = -ENXIO;
222
223 mutex_lock(&hdaps_mtx);
224
225 outb(0x13, 0x1610);
226 outb(0x01, 0x161f);
227 if (__wait_latch(0x161f, 0x00))
228 goto out;
229
230 /*
231 * Most ThinkPads return 0x01.
232 *
233 * Others--namely the R50p, T41p, and T42p--return 0x03. These laptops
234 * have "inverted" axises.
235 *
236 * The 0x02 value occurs when the chip has been previously initialized.
237 */
238 if (__check_latch(0x1611, 0x03) &&
239 __check_latch(0x1611, 0x02) &&
240 __check_latch(0x1611, 0x01))
241 goto out;
242
243 printk(KERN_DEBUG "hdaps: initial latch check good (0x%02x)\n",
244 __get_latch(0x1611));
245
246 outb(0x17, 0x1610);
247 outb(0x81, 0x1611);
248 outb(0x01, 0x161f);
249 if (__wait_latch(0x161f, 0x00))
250 goto out;
251 if (__wait_latch(0x1611, 0x00))
252 goto out;
253 if (__wait_latch(0x1612, 0x60))
254 goto out;
255 if (__wait_latch(0x1613, 0x00))
256 goto out;
257 outb(0x14, 0x1610);
258 outb(0x01, 0x1611);
259 outb(0x01, 0x161f);
260 if (__wait_latch(0x161f, 0x00))
261 goto out;
262 outb(0x10, 0x1610);
263 outb(0xc8, 0x1611);
264 outb(0x00, 0x1612);
265 outb(0x02, 0x1613);
266 outb(0x01, 0x161f);
267 if (__wait_latch(0x161f, 0x00))
268 goto out;
269 if (__device_refresh_sync())
270 goto out;
271 if (__wait_latch(0x1611, 0x00))
272 goto out;
273
274 /* we have done our dance, now let's wait for the applause */
275 for (total = INIT_TIMEOUT_MSECS; total > 0; total -= INIT_WAIT_MSECS) {
276 int x, y;
277
278 /* a read of the device helps push it into action */
279 __hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y);
280 if (!__wait_latch(0x1611, 0x02)) {
281 ret = 0;
282 break;
283 }
284
285 msleep(INIT_WAIT_MSECS);
286 }
287
288out:
289 mutex_unlock(&hdaps_mtx);
290 return ret;
291}
292
293
294/* Device model stuff */
295
296static int hdaps_probe(struct platform_device *dev)
297{
298 int ret;
299
300 ret = hdaps_device_init();
301 if (ret)
302 return ret;
303
304 pr_info("device successfully initialized\n");
305 return 0;
306}
307
308static int hdaps_resume(struct platform_device *dev)
309{
310 return hdaps_device_init();
311}
312
313static struct platform_driver hdaps_driver = {
314 .probe = hdaps_probe,
315 .resume = hdaps_resume,
316 .driver = {
317 .name = "hdaps",
318 .owner = THIS_MODULE,
319 },
320};
321
322/*
323 * hdaps_calibrate - Set our "resting" values. Callers must hold hdaps_mtx.
324 */
325static void hdaps_calibrate(void)
326{
327 __hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &rest_x, &rest_y);
328}
329
330static void hdaps_mousedev_poll(struct input_polled_dev *dev)
331{
332 struct input_dev *input_dev = dev->input;
333 int x, y;
334
335 mutex_lock(&hdaps_mtx);
336
337 if (__hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y))
338 goto out;
339
340 input_report_abs(input_dev, ABS_X, x - rest_x);
341 input_report_abs(input_dev, ABS_Y, y - rest_y);
342 input_sync(input_dev);
343
344out:
345 mutex_unlock(&hdaps_mtx);
346}
347
348
349/* Sysfs Files */
350
351static ssize_t hdaps_position_show(struct device *dev,
352 struct device_attribute *attr, char *buf)
353{
354 int ret, x, y;
355
356 ret = hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y);
357 if (ret)
358 return ret;
359
360 return sprintf(buf, "(%d,%d)\n", x, y);
361}
362
363static ssize_t hdaps_variance_show(struct device *dev,
364 struct device_attribute *attr, char *buf)
365{
366 int ret, x, y;
367
368 ret = hdaps_read_pair(HDAPS_PORT_XVAR, HDAPS_PORT_YVAR, &x, &y);
369 if (ret)
370 return ret;
371
372 return sprintf(buf, "(%d,%d)\n", x, y);
373}
374
375static ssize_t hdaps_temp1_show(struct device *dev,
376 struct device_attribute *attr, char *buf)
377{
378 u8 temp;
379 int ret;
380
381 ret = hdaps_readb_one(HDAPS_PORT_TEMP1, &temp);
382 if (ret < 0)
383 return ret;
384
385 return sprintf(buf, "%u\n", temp);
386}
387
388static ssize_t hdaps_temp2_show(struct device *dev,
389 struct device_attribute *attr, char *buf)
390{
391 u8 temp;
392 int ret;
393
394 ret = hdaps_readb_one(HDAPS_PORT_TEMP2, &temp);
395 if (ret < 0)
396 return ret;
397
398 return sprintf(buf, "%u\n", temp);
399}
400
401static ssize_t hdaps_keyboard_activity_show(struct device *dev,
402 struct device_attribute *attr,
403 char *buf)
404{
405 return sprintf(buf, "%u\n", KEYBD_ISSET(km_activity));
406}
407
408static ssize_t hdaps_mouse_activity_show(struct device *dev,
409 struct device_attribute *attr,
410 char *buf)
411{
412 return sprintf(buf, "%u\n", MOUSE_ISSET(km_activity));
413}
414
415static ssize_t hdaps_calibrate_show(struct device *dev,
416 struct device_attribute *attr, char *buf)
417{
418 return sprintf(buf, "(%d,%d)\n", rest_x, rest_y);
419}
420
421static ssize_t hdaps_calibrate_store(struct device *dev,
422 struct device_attribute *attr,
423 const char *buf, size_t count)
424{
425 mutex_lock(&hdaps_mtx);
426 hdaps_calibrate();
427 mutex_unlock(&hdaps_mtx);
428
429 return count;
430}
431
432static ssize_t hdaps_invert_show(struct device *dev,
433 struct device_attribute *attr, char *buf)
434{
435 return sprintf(buf, "%u\n", hdaps_invert);
436}
437
438static ssize_t hdaps_invert_store(struct device *dev,
439 struct device_attribute *attr,
440 const char *buf, size_t count)
441{
442 int invert;
443
444 if (sscanf(buf, "%d", &invert) != 1 ||
445 invert < 0 || invert > HDAPS_BOTH_AXES)
446 return -EINVAL;
447
448 hdaps_invert = invert;
449 hdaps_calibrate();
450
451 return count;
452}
453
454static DEVICE_ATTR(position, 0444, hdaps_position_show, NULL);
455static DEVICE_ATTR(variance, 0444, hdaps_variance_show, NULL);
456static DEVICE_ATTR(temp1, 0444, hdaps_temp1_show, NULL);
457static DEVICE_ATTR(temp2, 0444, hdaps_temp2_show, NULL);
458static DEVICE_ATTR(keyboard_activity, 0444, hdaps_keyboard_activity_show, NULL);
459static DEVICE_ATTR(mouse_activity, 0444, hdaps_mouse_activity_show, NULL);
460static DEVICE_ATTR(calibrate, 0644, hdaps_calibrate_show,hdaps_calibrate_store);
461static DEVICE_ATTR(invert, 0644, hdaps_invert_show, hdaps_invert_store);
462
463static struct attribute *hdaps_attributes[] = {
464 &dev_attr_position.attr,
465 &dev_attr_variance.attr,
466 &dev_attr_temp1.attr,
467 &dev_attr_temp2.attr,
468 &dev_attr_keyboard_activity.attr,
469 &dev_attr_mouse_activity.attr,
470 &dev_attr_calibrate.attr,
471 &dev_attr_invert.attr,
472 NULL,
473};
474
475static struct attribute_group hdaps_attribute_group = {
476 .attrs = hdaps_attributes,
477};
478
479
480/* Module stuff */
481
482/* hdaps_dmi_match - found a match. return one, short-circuiting the hunt. */
483static int __init hdaps_dmi_match(const struct dmi_system_id *id)
484{
485 pr_info("%s detected\n", id->ident);
486 return 1;
487}
488
489/* hdaps_dmi_match_invert - found an inverted match. */
490static int __init hdaps_dmi_match_invert(const struct dmi_system_id *id)
491{
492 hdaps_invert = (unsigned long)id->driver_data;
493 pr_info("inverting axis (%u) readings\n", hdaps_invert);
494 return hdaps_dmi_match(id);
495}
496
497#define HDAPS_DMI_MATCH_INVERT(vendor, model, axes) { \
498 .ident = vendor " " model, \
499 .callback = hdaps_dmi_match_invert, \
500 .driver_data = (void *)axes, \
501 .matches = { \
502 DMI_MATCH(DMI_BOARD_VENDOR, vendor), \
503 DMI_MATCH(DMI_PRODUCT_VERSION, model) \
504 } \
505}
506
507#define HDAPS_DMI_MATCH_NORMAL(vendor, model) \
508 HDAPS_DMI_MATCH_INVERT(vendor, model, 0)
509
510/* Note that HDAPS_DMI_MATCH_NORMAL("ThinkPad T42") would match
511 "ThinkPad T42p", so the order of the entries matters.
512 If your ThinkPad is not recognized, please update to latest
513 BIOS. This is especially the case for some R52 ThinkPads. */
514static struct dmi_system_id __initdata hdaps_whitelist[] = {
515 HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad R50p", HDAPS_BOTH_AXES),
516 HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R50"),
517 HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R51"),
518 HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R52"),
519 HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad R61i", HDAPS_BOTH_AXES),
520 HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad R61", HDAPS_BOTH_AXES),
521 HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad T41p", HDAPS_BOTH_AXES),
522 HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T41"),
523 HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad T42p", HDAPS_BOTH_AXES),
524 HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T42"),
525 HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T43"),
526 HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T400", HDAPS_BOTH_AXES),
527 HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T60", HDAPS_BOTH_AXES),
528 HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T61p", HDAPS_BOTH_AXES),
529 HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T61", HDAPS_BOTH_AXES),
530 HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad X40"),
531 HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad X41", HDAPS_Y_AXIS),
532 HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad X60", HDAPS_BOTH_AXES),
533 HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad X61s", HDAPS_BOTH_AXES),
534 HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad X61", HDAPS_BOTH_AXES),
535 HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad Z60m"),
536 HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad Z61m", HDAPS_BOTH_AXES),
537 HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad Z61p", HDAPS_BOTH_AXES),
538 { .ident = NULL }
539};
540
541static int __init hdaps_init(void)
542{
543 struct input_dev *idev;
544 int ret;
545
546 if (!dmi_check_system(hdaps_whitelist)) {
547 pr_warn("supported laptop not found!\n");
548 ret = -ENODEV;
549 goto out;
550 }
551
552 if (!request_region(HDAPS_LOW_PORT, HDAPS_NR_PORTS, "hdaps")) {
553 ret = -ENXIO;
554 goto out;
555 }
556
557 ret = platform_driver_register(&hdaps_driver);
558 if (ret)
559 goto out_region;
560
561 pdev = platform_device_register_simple("hdaps", -1, NULL, 0);
562 if (IS_ERR(pdev)) {
563 ret = PTR_ERR(pdev);
564 goto out_driver;
565 }
566
567 ret = sysfs_create_group(&pdev->dev.kobj, &hdaps_attribute_group);
568 if (ret)
569 goto out_device;
570
571 hdaps_idev = input_allocate_polled_device();
572 if (!hdaps_idev) {
573 ret = -ENOMEM;
574 goto out_group;
575 }
576
577 hdaps_idev->poll = hdaps_mousedev_poll;
578 hdaps_idev->poll_interval = HDAPS_POLL_INTERVAL;
579
580 /* initial calibrate for the input device */
581 hdaps_calibrate();
582
583 /* initialize the input class */
584 idev = hdaps_idev->input;
585 idev->name = "hdaps";
586 idev->phys = "isa1600/input0";
587 idev->id.bustype = BUS_ISA;
588 idev->dev.parent = &pdev->dev;
589 idev->evbit[0] = BIT_MASK(EV_ABS);
590 input_set_abs_params(idev, ABS_X,
591 -256, 256, HDAPS_INPUT_FUZZ, HDAPS_INPUT_FLAT);
592 input_set_abs_params(idev, ABS_Y,
593 -256, 256, HDAPS_INPUT_FUZZ, HDAPS_INPUT_FLAT);
594
595 ret = input_register_polled_device(hdaps_idev);
596 if (ret)
597 goto out_idev;
598
599 pr_info("driver successfully loaded\n");
600 return 0;
601
602out_idev:
603 input_free_polled_device(hdaps_idev);
604out_group:
605 sysfs_remove_group(&pdev->dev.kobj, &hdaps_attribute_group);
606out_device:
607 platform_device_unregister(pdev);
608out_driver:
609 platform_driver_unregister(&hdaps_driver);
610out_region:
611 release_region(HDAPS_LOW_PORT, HDAPS_NR_PORTS);
612out:
613 pr_warn("driver init failed (ret=%d)!\n", ret);
614 return ret;
615}
616
617static void __exit hdaps_exit(void)
618{
619 input_unregister_polled_device(hdaps_idev);
620 input_free_polled_device(hdaps_idev);
621 sysfs_remove_group(&pdev->dev.kobj, &hdaps_attribute_group);
622 platform_device_unregister(pdev);
623 platform_driver_unregister(&hdaps_driver);
624 release_region(HDAPS_LOW_PORT, HDAPS_NR_PORTS);
625
626 pr_info("driver unloaded\n");
627}
628
629module_init(hdaps_init);
630module_exit(hdaps_exit);
631
632module_param_named(invert, hdaps_invert, int, 0);
633MODULE_PARM_DESC(invert, "invert data along each axis. 1 invert x-axis, "
634 "2 invert y-axis, 3 invert both axes.");
635
636MODULE_AUTHOR("Robert Love");
637MODULE_DESCRIPTION("IBM Hard Drive Active Protection System (HDAPS) driver");
638MODULE_LICENSE("GPL v2");
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c
index c1741142a4cb..e2faa3cbb792 100644
--- a/drivers/platform/x86/hp-wmi.c
+++ b/drivers/platform/x86/hp-wmi.c
@@ -2,6 +2,7 @@
2 * HP WMI hotkeys 2 * HP WMI hotkeys
3 * 3 *
4 * Copyright (C) 2008 Red Hat <mjg@redhat.com> 4 * Copyright (C) 2008 Red Hat <mjg@redhat.com>
5 * Copyright (C) 2010, 2011 Anssi Hannula <anssi.hannula@iki.fi>
5 * 6 *
6 * Portions based on wistron_btns.c: 7 * Portions based on wistron_btns.c:
7 * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz> 8 * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz>
@@ -23,12 +24,15 @@
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */ 25 */
25 26
27#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
28
26#include <linux/kernel.h> 29#include <linux/kernel.h>
27#include <linux/module.h> 30#include <linux/module.h>
28#include <linux/init.h> 31#include <linux/init.h>
29#include <linux/slab.h> 32#include <linux/slab.h>
30#include <linux/types.h> 33#include <linux/types.h>
31#include <linux/input.h> 34#include <linux/input.h>
35#include <linux/input/sparse-keymap.h>
32#include <linux/platform_device.h> 36#include <linux/platform_device.h>
33#include <linux/acpi.h> 37#include <linux/acpi.h>
34#include <linux/rfkill.h> 38#include <linux/rfkill.h>
@@ -50,9 +54,7 @@ MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4");
50#define HPWMI_HARDWARE_QUERY 0x4 54#define HPWMI_HARDWARE_QUERY 0x4
51#define HPWMI_WIRELESS_QUERY 0x5 55#define HPWMI_WIRELESS_QUERY 0x5
52#define HPWMI_HOTKEY_QUERY 0xc 56#define HPWMI_HOTKEY_QUERY 0xc
53 57#define HPWMI_WIRELESS2_QUERY 0x1b
54#define PREFIX "HP WMI: "
55#define UNIMP "Unimplemented "
56 58
57enum hp_wmi_radio { 59enum hp_wmi_radio {
58 HPWMI_WIFI = 0, 60 HPWMI_WIFI = 0,
@@ -85,27 +87,58 @@ struct bios_args {
85struct bios_return { 87struct bios_return {
86 u32 sigpass; 88 u32 sigpass;
87 u32 return_code; 89 u32 return_code;
88 u32 value;
89}; 90};
90 91
91struct key_entry { 92enum hp_return_value {
92 char type; /* See KE_* below */ 93 HPWMI_RET_WRONG_SIGNATURE = 0x02,
93 u16 code; 94 HPWMI_RET_UNKNOWN_COMMAND = 0x03,
94 u16 keycode; 95 HPWMI_RET_UNKNOWN_CMDTYPE = 0x04,
96 HPWMI_RET_INVALID_PARAMETERS = 0x05,
97};
98
99enum hp_wireless2_bits {
100 HPWMI_POWER_STATE = 0x01,
101 HPWMI_POWER_SOFT = 0x02,
102 HPWMI_POWER_BIOS = 0x04,
103 HPWMI_POWER_HARD = 0x08,
95}; 104};
96 105
97enum { KE_KEY, KE_END }; 106#define IS_HWBLOCKED(x) ((x & (HPWMI_POWER_BIOS | HPWMI_POWER_HARD)) \
98 107 != (HPWMI_POWER_BIOS | HPWMI_POWER_HARD))
99static struct key_entry hp_wmi_keymap[] = { 108#define IS_SWBLOCKED(x) !(x & HPWMI_POWER_SOFT)
100 {KE_KEY, 0x02, KEY_BRIGHTNESSUP}, 109
101 {KE_KEY, 0x03, KEY_BRIGHTNESSDOWN}, 110struct bios_rfkill2_device_state {
102 {KE_KEY, 0x20e6, KEY_PROG1}, 111 u8 radio_type;
103 {KE_KEY, 0x20e8, KEY_MEDIA}, 112 u8 bus_type;
104 {KE_KEY, 0x2142, KEY_MEDIA}, 113 u16 vendor_id;
105 {KE_KEY, 0x213b, KEY_INFO}, 114 u16 product_id;
106 {KE_KEY, 0x2169, KEY_DIRECTION}, 115 u16 subsys_vendor_id;
107 {KE_KEY, 0x231b, KEY_HELP}, 116 u16 subsys_product_id;
108 {KE_END, 0} 117 u8 rfkill_id;
118 u8 power;
119 u8 unknown[4];
120};
121
122/* 7 devices fit into the 128 byte buffer */
123#define HPWMI_MAX_RFKILL2_DEVICES 7
124
125struct bios_rfkill2_state {
126 u8 unknown[7];
127 u8 count;
128 u8 pad[8];
129 struct bios_rfkill2_device_state device[HPWMI_MAX_RFKILL2_DEVICES];
130};
131
132static const struct key_entry hp_wmi_keymap[] = {
133 { KE_KEY, 0x02, { KEY_BRIGHTNESSUP } },
134 { KE_KEY, 0x03, { KEY_BRIGHTNESSDOWN } },
135 { KE_KEY, 0x20e6, { KEY_PROG1 } },
136 { KE_KEY, 0x20e8, { KEY_MEDIA } },
137 { KE_KEY, 0x2142, { KEY_MEDIA } },
138 { KE_KEY, 0x213b, { KEY_INFO } },
139 { KE_KEY, 0x2169, { KEY_DIRECTION } },
140 { KE_KEY, 0x231b, { KEY_HELP } },
141 { KE_END, 0 }
109}; 142};
110 143
111static struct input_dev *hp_wmi_input_dev; 144static struct input_dev *hp_wmi_input_dev;
@@ -115,6 +148,15 @@ static struct rfkill *wifi_rfkill;
115static struct rfkill *bluetooth_rfkill; 148static struct rfkill *bluetooth_rfkill;
116static struct rfkill *wwan_rfkill; 149static struct rfkill *wwan_rfkill;
117 150
151struct rfkill2_device {
152 u8 id;
153 int num;
154 struct rfkill *rfkill;
155};
156
157static int rfkill2_count;
158static struct rfkill2_device rfkill2[HPWMI_MAX_RFKILL2_DEVICES];
159
118static const struct dev_pm_ops hp_wmi_pm_ops = { 160static const struct dev_pm_ops hp_wmi_pm_ops = {
119 .resume = hp_wmi_resume_handler, 161 .resume = hp_wmi_resume_handler,
120 .restore = hp_wmi_resume_handler, 162 .restore = hp_wmi_resume_handler,
@@ -136,7 +178,8 @@ static struct platform_driver hp_wmi_driver = {
136 * query: The commandtype -> What should be queried 178 * query: The commandtype -> What should be queried
137 * write: The command -> 0 read, 1 write, 3 ODM specific 179 * write: The command -> 0 read, 1 write, 3 ODM specific
138 * buffer: Buffer used as input and/or output 180 * buffer: Buffer used as input and/or output
139 * buffersize: Size of buffer 181 * insize: Size of input buffer
182 * outsize: Size of output buffer
140 * 183 *
141 * returns zero on success 184 * returns zero on success
142 * an HP WMI query specific error code (which is positive) 185 * an HP WMI query specific error code (which is positive)
@@ -147,25 +190,30 @@ static struct platform_driver hp_wmi_driver = {
147 * size. E.g. Battery info query (0x7) is defined to have 1 byte input 190 * size. E.g. Battery info query (0x7) is defined to have 1 byte input
148 * and 128 byte output. The caller would do: 191 * and 128 byte output. The caller would do:
149 * buffer = kzalloc(128, GFP_KERNEL); 192 * buffer = kzalloc(128, GFP_KERNEL);
150 * ret = hp_wmi_perform_query(0x7, 0, buffer, 128) 193 * ret = hp_wmi_perform_query(0x7, 0, buffer, 1, 128)
151 */ 194 */
152static int hp_wmi_perform_query(int query, int write, u32 *buffer, 195static int hp_wmi_perform_query(int query, int write, void *buffer,
153 int buffersize) 196 int insize, int outsize)
154{ 197{
155 struct bios_return bios_return; 198 struct bios_return *bios_return;
156 acpi_status status; 199 int actual_outsize;
157 union acpi_object *obj; 200 union acpi_object *obj;
158 struct bios_args args = { 201 struct bios_args args = {
159 .signature = 0x55434553, 202 .signature = 0x55434553,
160 .command = write ? 0x2 : 0x1, 203 .command = write ? 0x2 : 0x1,
161 .commandtype = query, 204 .commandtype = query,
162 .datasize = buffersize, 205 .datasize = insize,
163 .data = *buffer, 206 .data = 0,
164 }; 207 };
165 struct acpi_buffer input = { sizeof(struct bios_args), &args }; 208 struct acpi_buffer input = { sizeof(struct bios_args), &args };
166 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; 209 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
210 u32 rc;
211
212 if (WARN_ON(insize > sizeof(args.data)))
213 return -EINVAL;
214 memcpy(&args.data, buffer, insize);
167 215
168 status = wmi_evaluate_method(HPWMI_BIOS_GUID, 0, 0x3, &input, &output); 216 wmi_evaluate_method(HPWMI_BIOS_GUID, 0, 0x3, &input, &output);
169 217
170 obj = output.pointer; 218 obj = output.pointer;
171 219
@@ -176,9 +224,26 @@ static int hp_wmi_perform_query(int query, int write, u32 *buffer,
176 return -EINVAL; 224 return -EINVAL;
177 } 225 }
178 226
179 bios_return = *((struct bios_return *)obj->buffer.pointer); 227 bios_return = (struct bios_return *)obj->buffer.pointer;
228 rc = bios_return->return_code;
229
230 if (rc) {
231 if (rc != HPWMI_RET_UNKNOWN_CMDTYPE)
232 pr_warn("query 0x%x returned error 0x%x\n", query, rc);
233 kfree(obj);
234 return rc;
235 }
236
237 if (!outsize) {
238 /* ignore output data */
239 kfree(obj);
240 return 0;
241 }
180 242
181 memcpy(buffer, &bios_return.value, sizeof(bios_return.value)); 243 actual_outsize = min(outsize, (int)(obj->buffer.length - sizeof(*bios_return)));
244 memcpy(buffer, obj->buffer.pointer + sizeof(*bios_return), actual_outsize);
245 memset(buffer + actual_outsize, 0, outsize - actual_outsize);
246 kfree(obj);
182 return 0; 247 return 0;
183} 248}
184 249
@@ -186,7 +251,7 @@ static int hp_wmi_display_state(void)
186{ 251{
187 int state = 0; 252 int state = 0;
188 int ret = hp_wmi_perform_query(HPWMI_DISPLAY_QUERY, 0, &state, 253 int ret = hp_wmi_perform_query(HPWMI_DISPLAY_QUERY, 0, &state,
189 sizeof(state)); 254 sizeof(state), sizeof(state));
190 if (ret) 255 if (ret)
191 return -EINVAL; 256 return -EINVAL;
192 return state; 257 return state;
@@ -196,7 +261,7 @@ static int hp_wmi_hddtemp_state(void)
196{ 261{
197 int state = 0; 262 int state = 0;
198 int ret = hp_wmi_perform_query(HPWMI_HDDTEMP_QUERY, 0, &state, 263 int ret = hp_wmi_perform_query(HPWMI_HDDTEMP_QUERY, 0, &state,
199 sizeof(state)); 264 sizeof(state), sizeof(state));
200 if (ret) 265 if (ret)
201 return -EINVAL; 266 return -EINVAL;
202 return state; 267 return state;
@@ -206,7 +271,7 @@ static int hp_wmi_als_state(void)
206{ 271{
207 int state = 0; 272 int state = 0;
208 int ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, 0, &state, 273 int ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, 0, &state,
209 sizeof(state)); 274 sizeof(state), sizeof(state));
210 if (ret) 275 if (ret)
211 return -EINVAL; 276 return -EINVAL;
212 return state; 277 return state;
@@ -216,7 +281,7 @@ static int hp_wmi_dock_state(void)
216{ 281{
217 int state = 0; 282 int state = 0;
218 int ret = hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, 0, &state, 283 int ret = hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, 0, &state,
219 sizeof(state)); 284 sizeof(state), sizeof(state));
220 285
221 if (ret) 286 if (ret)
222 return -EINVAL; 287 return -EINVAL;
@@ -228,7 +293,7 @@ static int hp_wmi_tablet_state(void)
228{ 293{
229 int state = 0; 294 int state = 0;
230 int ret = hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, 0, &state, 295 int ret = hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, 0, &state,
231 sizeof(state)); 296 sizeof(state), sizeof(state));
232 if (ret) 297 if (ret)
233 return ret; 298 return ret;
234 299
@@ -242,7 +307,7 @@ static int hp_wmi_set_block(void *data, bool blocked)
242 int ret; 307 int ret;
243 308
244 ret = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, 309 ret = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1,
245 &query, sizeof(query)); 310 &query, sizeof(query), 0);
246 if (ret) 311 if (ret)
247 return -EINVAL; 312 return -EINVAL;
248 return 0; 313 return 0;
@@ -257,7 +322,8 @@ static bool hp_wmi_get_sw_state(enum hp_wmi_radio r)
257 int wireless = 0; 322 int wireless = 0;
258 int mask; 323 int mask;
259 hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 324 hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0,
260 &wireless, sizeof(wireless)); 325 &wireless, sizeof(wireless),
326 sizeof(wireless));
261 /* TBD: Pass error */ 327 /* TBD: Pass error */
262 328
263 mask = 0x200 << (r * 8); 329 mask = 0x200 << (r * 8);
@@ -273,7 +339,8 @@ static bool hp_wmi_get_hw_state(enum hp_wmi_radio r)
273 int wireless = 0; 339 int wireless = 0;
274 int mask; 340 int mask;
275 hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 341 hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0,
276 &wireless, sizeof(wireless)); 342 &wireless, sizeof(wireless),
343 sizeof(wireless));
277 /* TBD: Pass error */ 344 /* TBD: Pass error */
278 345
279 mask = 0x800 << (r * 8); 346 mask = 0x800 << (r * 8);
@@ -284,6 +351,50 @@ static bool hp_wmi_get_hw_state(enum hp_wmi_radio r)
284 return true; 351 return true;
285} 352}
286 353
354static int hp_wmi_rfkill2_set_block(void *data, bool blocked)
355{
356 int rfkill_id = (int)(long)data;
357 char buffer[4] = { 0x01, 0x00, rfkill_id, !blocked };
358
359 if (hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, 1,
360 buffer, sizeof(buffer), 0))
361 return -EINVAL;
362 return 0;
363}
364
365static const struct rfkill_ops hp_wmi_rfkill2_ops = {
366 .set_block = hp_wmi_rfkill2_set_block,
367};
368
369static int hp_wmi_rfkill2_refresh(void)
370{
371 int err, i;
372 struct bios_rfkill2_state state;
373
374 err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, 0, &state,
375 0, sizeof(state));
376 if (err)
377 return err;
378
379 for (i = 0; i < rfkill2_count; i++) {
380 int num = rfkill2[i].num;
381 struct bios_rfkill2_device_state *devstate;
382 devstate = &state.device[num];
383
384 if (num >= state.count ||
385 devstate->rfkill_id != rfkill2[i].id) {
386 pr_warn("power configuration of the wireless devices unexpectedly changed\n");
387 continue;
388 }
389
390 rfkill_set_states(rfkill2[i].rfkill,
391 IS_SWBLOCKED(devstate->power),
392 IS_HWBLOCKED(devstate->power));
393 }
394
395 return 0;
396}
397
287static ssize_t show_display(struct device *dev, struct device_attribute *attr, 398static ssize_t show_display(struct device *dev, struct device_attribute *attr,
288 char *buf) 399 char *buf)
289{ 400{
@@ -334,7 +445,7 @@ static ssize_t set_als(struct device *dev, struct device_attribute *attr,
334{ 445{
335 u32 tmp = simple_strtoul(buf, NULL, 10); 446 u32 tmp = simple_strtoul(buf, NULL, 10);
336 int ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, 1, &tmp, 447 int ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, 1, &tmp,
337 sizeof(tmp)); 448 sizeof(tmp), sizeof(tmp));
338 if (ret) 449 if (ret)
339 return -EINVAL; 450 return -EINVAL;
340 451
@@ -347,64 +458,9 @@ static DEVICE_ATTR(als, S_IRUGO | S_IWUSR, show_als, set_als);
347static DEVICE_ATTR(dock, S_IRUGO, show_dock, NULL); 458static DEVICE_ATTR(dock, S_IRUGO, show_dock, NULL);
348static DEVICE_ATTR(tablet, S_IRUGO, show_tablet, NULL); 459static DEVICE_ATTR(tablet, S_IRUGO, show_tablet, NULL);
349 460
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) 461static void hp_wmi_notify(u32 value, void *context)
405{ 462{
406 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; 463 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
407 static struct key_entry *key;
408 union acpi_object *obj; 464 union acpi_object *obj;
409 u32 event_id, event_data; 465 u32 event_id, event_data;
410 int key_code = 0, ret; 466 int key_code = 0, ret;
@@ -413,7 +469,7 @@ static void hp_wmi_notify(u32 value, void *context)
413 469
414 status = wmi_get_event_data(value, &response); 470 status = wmi_get_event_data(value, &response);
415 if (status != AE_OK) { 471 if (status != AE_OK) {
416 printk(KERN_INFO PREFIX "bad event status 0x%x\n", status); 472 pr_info("bad event status 0x%x\n", status);
417 return; 473 return;
418 } 474 }
419 475
@@ -422,8 +478,7 @@ static void hp_wmi_notify(u32 value, void *context)
422 if (!obj) 478 if (!obj)
423 return; 479 return;
424 if (obj->type != ACPI_TYPE_BUFFER) { 480 if (obj->type != ACPI_TYPE_BUFFER) {
425 printk(KERN_INFO "hp-wmi: Unknown response received %d\n", 481 pr_info("Unknown response received %d\n", obj->type);
426 obj->type);
427 kfree(obj); 482 kfree(obj);
428 return; 483 return;
429 } 484 }
@@ -440,8 +495,7 @@ static void hp_wmi_notify(u32 value, void *context)
440 event_id = *location; 495 event_id = *location;
441 event_data = *(location + 2); 496 event_data = *(location + 2);
442 } else { 497 } else {
443 printk(KERN_INFO "hp-wmi: Unknown buffer length %d\n", 498 pr_info("Unknown buffer length %d\n", obj->buffer.length);
444 obj->buffer.length);
445 kfree(obj); 499 kfree(obj);
446 return; 500 return;
447 } 501 }
@@ -462,26 +516,21 @@ static void hp_wmi_notify(u32 value, void *context)
462 case HPWMI_BEZEL_BUTTON: 516 case HPWMI_BEZEL_BUTTON:
463 ret = hp_wmi_perform_query(HPWMI_HOTKEY_QUERY, 0, 517 ret = hp_wmi_perform_query(HPWMI_HOTKEY_QUERY, 0,
464 &key_code, 518 &key_code,
519 sizeof(key_code),
465 sizeof(key_code)); 520 sizeof(key_code));
466 if (ret) 521 if (ret)
467 break; 522 break;
468 key = hp_wmi_get_entry_by_scancode(key_code); 523
469 if (key) { 524 if (!sparse_keymap_report_event(hp_wmi_input_dev,
470 switch (key->type) { 525 key_code, 1, true))
471 case KE_KEY: 526 pr_info("Unknown key code - 0x%x\n", key_code);
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",
482 key_code);
483 break; 527 break;
484 case HPWMI_WIRELESS: 528 case HPWMI_WIRELESS:
529 if (rfkill2_count) {
530 hp_wmi_rfkill2_refresh();
531 break;
532 }
533
485 if (wifi_rfkill) 534 if (wifi_rfkill)
486 rfkill_set_states(wifi_rfkill, 535 rfkill_set_states(wifi_rfkill,
487 hp_wmi_get_sw_state(HPWMI_WIFI), 536 hp_wmi_get_sw_state(HPWMI_WIFI),
@@ -496,21 +545,19 @@ static void hp_wmi_notify(u32 value, void *context)
496 hp_wmi_get_hw_state(HPWMI_WWAN)); 545 hp_wmi_get_hw_state(HPWMI_WWAN));
497 break; 546 break;
498 case HPWMI_CPU_BATTERY_THROTTLE: 547 case HPWMI_CPU_BATTERY_THROTTLE:
499 printk(KERN_INFO PREFIX UNIMP "CPU throttle because of 3 Cell" 548 pr_info("Unimplemented CPU throttle because of 3 Cell battery event detected\n");
500 " battery event detected\n");
501 break; 549 break;
502 case HPWMI_LOCK_SWITCH: 550 case HPWMI_LOCK_SWITCH:
503 break; 551 break;
504 default: 552 default:
505 printk(KERN_INFO PREFIX "Unknown event_id - %d - 0x%x\n", 553 pr_info("Unknown event_id - %d - 0x%x\n", event_id, event_data);
506 event_id, event_data);
507 break; 554 break;
508 } 555 }
509} 556}
510 557
511static int __init hp_wmi_input_setup(void) 558static int __init hp_wmi_input_setup(void)
512{ 559{
513 struct key_entry *key; 560 acpi_status status;
514 int err; 561 int err;
515 562
516 hp_wmi_input_dev = input_allocate_device(); 563 hp_wmi_input_dev = input_allocate_device();
@@ -520,21 +567,14 @@ static int __init hp_wmi_input_setup(void)
520 hp_wmi_input_dev->name = "HP WMI hotkeys"; 567 hp_wmi_input_dev->name = "HP WMI hotkeys";
521 hp_wmi_input_dev->phys = "wmi/input0"; 568 hp_wmi_input_dev->phys = "wmi/input0";
522 hp_wmi_input_dev->id.bustype = BUS_HOST; 569 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 570
535 set_bit(EV_SW, hp_wmi_input_dev->evbit); 571 __set_bit(EV_SW, hp_wmi_input_dev->evbit);
536 set_bit(SW_DOCK, hp_wmi_input_dev->swbit); 572 __set_bit(SW_DOCK, hp_wmi_input_dev->swbit);
537 set_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit); 573 __set_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit);
574
575 err = sparse_keymap_setup(hp_wmi_input_dev, hp_wmi_keymap, NULL);
576 if (err)
577 goto err_free_dev;
538 578
539 /* Set initial hardware state */ 579 /* Set initial hardware state */
540 input_report_switch(hp_wmi_input_dev, SW_DOCK, hp_wmi_dock_state()); 580 input_report_switch(hp_wmi_input_dev, SW_DOCK, hp_wmi_dock_state());
@@ -542,14 +582,32 @@ static int __init hp_wmi_input_setup(void)
542 hp_wmi_tablet_state()); 582 hp_wmi_tablet_state());
543 input_sync(hp_wmi_input_dev); 583 input_sync(hp_wmi_input_dev);
544 584
545 err = input_register_device(hp_wmi_input_dev); 585 status = wmi_install_notify_handler(HPWMI_EVENT_GUID, hp_wmi_notify, NULL);
546 586 if (ACPI_FAILURE(status)) {
547 if (err) { 587 err = -EIO;
548 input_free_device(hp_wmi_input_dev); 588 goto err_free_keymap;
549 return err;
550 } 589 }
551 590
591 err = input_register_device(hp_wmi_input_dev);
592 if (err)
593 goto err_uninstall_notifier;
594
552 return 0; 595 return 0;
596
597 err_uninstall_notifier:
598 wmi_remove_notify_handler(HPWMI_EVENT_GUID);
599 err_free_keymap:
600 sparse_keymap_free(hp_wmi_input_dev);
601 err_free_dev:
602 input_free_device(hp_wmi_input_dev);
603 return err;
604}
605
606static void hp_wmi_input_destroy(void)
607{
608 wmi_remove_notify_handler(HPWMI_EVENT_GUID);
609 sparse_keymap_free(hp_wmi_input_dev);
610 input_unregister_device(hp_wmi_input_dev);
553} 611}
554 612
555static void cleanup_sysfs(struct platform_device *device) 613static void cleanup_sysfs(struct platform_device *device)
@@ -561,32 +619,16 @@ static void cleanup_sysfs(struct platform_device *device)
561 device_remove_file(&device->dev, &dev_attr_tablet); 619 device_remove_file(&device->dev, &dev_attr_tablet);
562} 620}
563 621
564static int __devinit hp_wmi_bios_setup(struct platform_device *device) 622static int __devinit hp_wmi_rfkill_setup(struct platform_device *device)
565{ 623{
566 int err; 624 int err;
567 int wireless = 0; 625 int wireless = 0;
568 626
569 err = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, &wireless, 627 err = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, &wireless,
570 sizeof(wireless)); 628 sizeof(wireless), sizeof(wireless));
571 if (err) 629 if (err)
572 return err; 630 return err;
573 631
574 err = device_create_file(&device->dev, &dev_attr_display);
575 if (err)
576 goto add_sysfs_error;
577 err = device_create_file(&device->dev, &dev_attr_hddtemp);
578 if (err)
579 goto add_sysfs_error;
580 err = device_create_file(&device->dev, &dev_attr_als);
581 if (err)
582 goto add_sysfs_error;
583 err = device_create_file(&device->dev, &dev_attr_dock);
584 if (err)
585 goto add_sysfs_error;
586 err = device_create_file(&device->dev, &dev_attr_tablet);
587 if (err)
588 goto add_sysfs_error;
589
590 if (wireless & 0x1) { 632 if (wireless & 0x1) {
591 wifi_rfkill = rfkill_alloc("hp-wifi", &device->dev, 633 wifi_rfkill = rfkill_alloc("hp-wifi", &device->dev,
592 RFKILL_TYPE_WLAN, 634 RFKILL_TYPE_WLAN,
@@ -632,14 +674,130 @@ static int __devinit hp_wmi_bios_setup(struct platform_device *device)
632 return 0; 674 return 0;
633register_wwan_err: 675register_wwan_err:
634 rfkill_destroy(wwan_rfkill); 676 rfkill_destroy(wwan_rfkill);
677 wwan_rfkill = NULL;
635 if (bluetooth_rfkill) 678 if (bluetooth_rfkill)
636 rfkill_unregister(bluetooth_rfkill); 679 rfkill_unregister(bluetooth_rfkill);
637register_bluetooth_error: 680register_bluetooth_error:
638 rfkill_destroy(bluetooth_rfkill); 681 rfkill_destroy(bluetooth_rfkill);
682 bluetooth_rfkill = NULL;
639 if (wifi_rfkill) 683 if (wifi_rfkill)
640 rfkill_unregister(wifi_rfkill); 684 rfkill_unregister(wifi_rfkill);
641register_wifi_error: 685register_wifi_error:
642 rfkill_destroy(wifi_rfkill); 686 rfkill_destroy(wifi_rfkill);
687 wifi_rfkill = NULL;
688 return err;
689}
690
691static int __devinit hp_wmi_rfkill2_setup(struct platform_device *device)
692{
693 int err, i;
694 struct bios_rfkill2_state state;
695 err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, 0, &state,
696 0, sizeof(state));
697 if (err)
698 return err;
699
700 if (state.count > HPWMI_MAX_RFKILL2_DEVICES) {
701 pr_warn("unable to parse 0x1b query output\n");
702 return -EINVAL;
703 }
704
705 for (i = 0; i < state.count; i++) {
706 struct rfkill *rfkill;
707 enum rfkill_type type;
708 char *name;
709 switch (state.device[i].radio_type) {
710 case HPWMI_WIFI:
711 type = RFKILL_TYPE_WLAN;
712 name = "hp-wifi";
713 break;
714 case HPWMI_BLUETOOTH:
715 type = RFKILL_TYPE_BLUETOOTH;
716 name = "hp-bluetooth";
717 break;
718 case HPWMI_WWAN:
719 type = RFKILL_TYPE_WWAN;
720 name = "hp-wwan";
721 break;
722 default:
723 pr_warn("unknown device type 0x%x\n",
724 state.device[i].radio_type);
725 continue;
726 }
727
728 if (!state.device[i].vendor_id) {
729 pr_warn("zero device %d while %d reported\n",
730 i, state.count);
731 continue;
732 }
733
734 rfkill = rfkill_alloc(name, &device->dev, type,
735 &hp_wmi_rfkill2_ops, (void *)(long)i);
736 if (!rfkill) {
737 err = -ENOMEM;
738 goto fail;
739 }
740
741 rfkill2[rfkill2_count].id = state.device[i].rfkill_id;
742 rfkill2[rfkill2_count].num = i;
743 rfkill2[rfkill2_count].rfkill = rfkill;
744
745 rfkill_init_sw_state(rfkill,
746 IS_SWBLOCKED(state.device[i].power));
747 rfkill_set_hw_state(rfkill,
748 IS_HWBLOCKED(state.device[i].power));
749
750 if (!(state.device[i].power & HPWMI_POWER_BIOS))
751 pr_info("device %s blocked by BIOS\n", name);
752
753 err = rfkill_register(rfkill);
754 if (err) {
755 rfkill_destroy(rfkill);
756 goto fail;
757 }
758
759 rfkill2_count++;
760 }
761
762 return 0;
763fail:
764 for (; rfkill2_count > 0; rfkill2_count--) {
765 rfkill_unregister(rfkill2[rfkill2_count - 1].rfkill);
766 rfkill_destroy(rfkill2[rfkill2_count - 1].rfkill);
767 }
768 return err;
769}
770
771static int __devinit hp_wmi_bios_setup(struct platform_device *device)
772{
773 int err;
774
775 /* clear detected rfkill devices */
776 wifi_rfkill = NULL;
777 bluetooth_rfkill = NULL;
778 wwan_rfkill = NULL;
779 rfkill2_count = 0;
780
781 if (hp_wmi_rfkill_setup(device))
782 hp_wmi_rfkill2_setup(device);
783
784 err = device_create_file(&device->dev, &dev_attr_display);
785 if (err)
786 goto add_sysfs_error;
787 err = device_create_file(&device->dev, &dev_attr_hddtemp);
788 if (err)
789 goto add_sysfs_error;
790 err = device_create_file(&device->dev, &dev_attr_als);
791 if (err)
792 goto add_sysfs_error;
793 err = device_create_file(&device->dev, &dev_attr_dock);
794 if (err)
795 goto add_sysfs_error;
796 err = device_create_file(&device->dev, &dev_attr_tablet);
797 if (err)
798 goto add_sysfs_error;
799 return 0;
800
643add_sysfs_error: 801add_sysfs_error:
644 cleanup_sysfs(device); 802 cleanup_sysfs(device);
645 return err; 803 return err;
@@ -647,8 +805,14 @@ add_sysfs_error:
647 805
648static int __exit hp_wmi_bios_remove(struct platform_device *device) 806static int __exit hp_wmi_bios_remove(struct platform_device *device)
649{ 807{
808 int i;
650 cleanup_sysfs(device); 809 cleanup_sysfs(device);
651 810
811 for (i = 0; i < rfkill2_count; i++) {
812 rfkill_unregister(rfkill2[i].rfkill);
813 rfkill_destroy(rfkill2[i].rfkill);
814 }
815
652 if (wifi_rfkill) { 816 if (wifi_rfkill) {
653 rfkill_unregister(wifi_rfkill); 817 rfkill_unregister(wifi_rfkill);
654 rfkill_destroy(wifi_rfkill); 818 rfkill_destroy(wifi_rfkill);
@@ -681,6 +845,9 @@ static int hp_wmi_resume_handler(struct device *device)
681 input_sync(hp_wmi_input_dev); 845 input_sync(hp_wmi_input_dev);
682 } 846 }
683 847
848 if (rfkill2_count)
849 hp_wmi_rfkill2_refresh();
850
684 if (wifi_rfkill) 851 if (wifi_rfkill)
685 rfkill_set_states(wifi_rfkill, 852 rfkill_set_states(wifi_rfkill,
686 hp_wmi_get_sw_state(HPWMI_WIFI), 853 hp_wmi_get_sw_state(HPWMI_WIFI),
@@ -704,15 +871,9 @@ static int __init hp_wmi_init(void)
704 int bios_capable = wmi_has_guid(HPWMI_BIOS_GUID); 871 int bios_capable = wmi_has_guid(HPWMI_BIOS_GUID);
705 872
706 if (event_capable) { 873 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(); 874 err = hp_wmi_input_setup();
712 if (err) { 875 if (err)
713 wmi_remove_notify_handler(HPWMI_EVENT_GUID);
714 return err; 876 return err;
715 }
716 } 877 }
717 878
718 if (bios_capable) { 879 if (bios_capable) {
@@ -739,20 +900,17 @@ err_device_add:
739err_device_alloc: 900err_device_alloc:
740 platform_driver_unregister(&hp_wmi_driver); 901 platform_driver_unregister(&hp_wmi_driver);
741err_driver_reg: 902err_driver_reg:
742 if (wmi_has_guid(HPWMI_EVENT_GUID)) { 903 if (event_capable)
743 input_unregister_device(hp_wmi_input_dev); 904 hp_wmi_input_destroy();
744 wmi_remove_notify_handler(HPWMI_EVENT_GUID);
745 }
746 905
747 return err; 906 return err;
748} 907}
749 908
750static void __exit hp_wmi_exit(void) 909static void __exit hp_wmi_exit(void)
751{ 910{
752 if (wmi_has_guid(HPWMI_EVENT_GUID)) { 911 if (wmi_has_guid(HPWMI_EVENT_GUID))
753 wmi_remove_notify_handler(HPWMI_EVENT_GUID); 912 hp_wmi_input_destroy();
754 input_unregister_device(hp_wmi_input_dev); 913
755 }
756 if (hp_wmi_platform_dev) { 914 if (hp_wmi_platform_dev) {
757 platform_device_unregister(hp_wmi_platform_dev); 915 platform_device_unregister(hp_wmi_platform_dev);
758 platform_driver_unregister(&hp_wmi_driver); 916 platform_driver_unregister(&hp_wmi_driver);
diff --git a/drivers/platform/x86/hp_accel.c b/drivers/platform/x86/hp_accel.c
new file mode 100644
index 000000000000..1b52d00e2f90
--- /dev/null
+++ b/drivers/platform/x86/hp_accel.c
@@ -0,0 +1,404 @@
1/*
2 * hp_accel.c - Interface between LIS3LV02DL driver and HP ACPI BIOS
3 *
4 * Copyright (C) 2007-2008 Yan Burman
5 * Copyright (C) 2008 Eric Piel
6 * Copyright (C) 2008-2009 Pavel Machek
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
24
25#include <linux/kernel.h>
26#include <linux/init.h>
27#include <linux/dmi.h>
28#include <linux/module.h>
29#include <linux/types.h>
30#include <linux/platform_device.h>
31#include <linux/interrupt.h>
32#include <linux/delay.h>
33#include <linux/wait.h>
34#include <linux/poll.h>
35#include <linux/freezer.h>
36#include <linux/uaccess.h>
37#include <linux/leds.h>
38#include <linux/atomic.h>
39#include <acpi/acpi_drivers.h>
40#include "../../misc/lis3lv02d/lis3lv02d.h"
41
42#define DRIVER_NAME "hp_accel"
43#define ACPI_MDPS_CLASS "accelerometer"
44
45/* Delayed LEDs infrastructure ------------------------------------ */
46
47/* Special LED class that can defer work */
48struct delayed_led_classdev {
49 struct led_classdev led_classdev;
50 struct work_struct work;
51 enum led_brightness new_brightness;
52
53 unsigned int led; /* For driver */
54 void (*set_brightness)(struct delayed_led_classdev *data, enum led_brightness value);
55};
56
57static inline void delayed_set_status_worker(struct work_struct *work)
58{
59 struct delayed_led_classdev *data =
60 container_of(work, struct delayed_led_classdev, work);
61
62 data->set_brightness(data, data->new_brightness);
63}
64
65static inline void delayed_sysfs_set(struct led_classdev *led_cdev,
66 enum led_brightness brightness)
67{
68 struct delayed_led_classdev *data = container_of(led_cdev,
69 struct delayed_led_classdev, led_classdev);
70 data->new_brightness = brightness;
71 schedule_work(&data->work);
72}
73
74/* HP-specific accelerometer driver ------------------------------------ */
75
76/* For automatic insertion of the module */
77static struct acpi_device_id lis3lv02d_device_ids[] = {
78 {"HPQ0004", 0}, /* HP Mobile Data Protection System PNP */
79 {"", 0},
80};
81MODULE_DEVICE_TABLE(acpi, lis3lv02d_device_ids);
82
83
84/**
85 * lis3lv02d_acpi_init - ACPI _INI method: initialize the device.
86 * @lis3: pointer to the device struct
87 *
88 * Returns 0 on success.
89 */
90int lis3lv02d_acpi_init(struct lis3lv02d *lis3)
91{
92 struct acpi_device *dev = lis3->bus_priv;
93 if (acpi_evaluate_object(dev->handle, METHOD_NAME__INI,
94 NULL, NULL) != AE_OK)
95 return -EINVAL;
96
97 return 0;
98}
99
100/**
101 * lis3lv02d_acpi_read - ACPI ALRD method: read a register
102 * @lis3: pointer to the device struct
103 * @reg: the register to read
104 * @ret: result of the operation
105 *
106 * Returns 0 on success.
107 */
108int lis3lv02d_acpi_read(struct lis3lv02d *lis3, int reg, u8 *ret)
109{
110 struct acpi_device *dev = lis3->bus_priv;
111 union acpi_object arg0 = { ACPI_TYPE_INTEGER };
112 struct acpi_object_list args = { 1, &arg0 };
113 unsigned long long lret;
114 acpi_status status;
115
116 arg0.integer.value = reg;
117
118 status = acpi_evaluate_integer(dev->handle, "ALRD", &args, &lret);
119 *ret = lret;
120 return (status != AE_OK) ? -EINVAL : 0;
121}
122
123/**
124 * lis3lv02d_acpi_write - ACPI ALWR method: write to a register
125 * @lis3: pointer to the device struct
126 * @reg: the register to write to
127 * @val: the value to write
128 *
129 * Returns 0 on success.
130 */
131int lis3lv02d_acpi_write(struct lis3lv02d *lis3, int reg, u8 val)
132{
133 struct acpi_device *dev = lis3->bus_priv;
134 unsigned long long ret; /* Not used when writting */
135 union acpi_object in_obj[2];
136 struct acpi_object_list args = { 2, in_obj };
137
138 in_obj[0].type = ACPI_TYPE_INTEGER;
139 in_obj[0].integer.value = reg;
140 in_obj[1].type = ACPI_TYPE_INTEGER;
141 in_obj[1].integer.value = val;
142
143 if (acpi_evaluate_integer(dev->handle, "ALWR", &args, &ret) != AE_OK)
144 return -EINVAL;
145
146 return 0;
147}
148
149static int lis3lv02d_dmi_matched(const struct dmi_system_id *dmi)
150{
151 lis3_dev.ac = *((union axis_conversion *)dmi->driver_data);
152 pr_info("hardware type %s found\n", dmi->ident);
153
154 return 1;
155}
156
157/* Represents, for each axis seen by userspace, the corresponding hw axis (+1).
158 * If the value is negative, the opposite of the hw value is used. */
159#define DEFINE_CONV(name, x, y, z) \
160 static union axis_conversion lis3lv02d_axis_##name = \
161 { .as_array = { x, y, z } }
162DEFINE_CONV(normal, 1, 2, 3);
163DEFINE_CONV(y_inverted, 1, -2, 3);
164DEFINE_CONV(x_inverted, -1, 2, 3);
165DEFINE_CONV(z_inverted, 1, 2, -3);
166DEFINE_CONV(xy_swap, 2, 1, 3);
167DEFINE_CONV(xy_rotated_left, -2, 1, 3);
168DEFINE_CONV(xy_rotated_left_usd, -2, 1, -3);
169DEFINE_CONV(xy_swap_inverted, -2, -1, 3);
170DEFINE_CONV(xy_rotated_right, 2, -1, 3);
171DEFINE_CONV(xy_swap_yz_inverted, 2, -1, -3);
172
173#define AXIS_DMI_MATCH(_ident, _name, _axis) { \
174 .ident = _ident, \
175 .callback = lis3lv02d_dmi_matched, \
176 .matches = { \
177 DMI_MATCH(DMI_PRODUCT_NAME, _name) \
178 }, \
179 .driver_data = &lis3lv02d_axis_##_axis \
180}
181
182#define AXIS_DMI_MATCH2(_ident, _class1, _name1, \
183 _class2, _name2, \
184 _axis) { \
185 .ident = _ident, \
186 .callback = lis3lv02d_dmi_matched, \
187 .matches = { \
188 DMI_MATCH(DMI_##_class1, _name1), \
189 DMI_MATCH(DMI_##_class2, _name2), \
190 }, \
191 .driver_data = &lis3lv02d_axis_##_axis \
192}
193static struct dmi_system_id lis3lv02d_dmi_ids[] = {
194 /* product names are truncated to match all kinds of a same model */
195 AXIS_DMI_MATCH("NC64x0", "HP Compaq nc64", x_inverted),
196 AXIS_DMI_MATCH("NC84x0", "HP Compaq nc84", z_inverted),
197 AXIS_DMI_MATCH("NX9420", "HP Compaq nx9420", x_inverted),
198 AXIS_DMI_MATCH("NW9440", "HP Compaq nw9440", x_inverted),
199 AXIS_DMI_MATCH("NC2510", "HP Compaq 2510", y_inverted),
200 AXIS_DMI_MATCH("NC2710", "HP Compaq 2710", xy_swap),
201 AXIS_DMI_MATCH("NC8510", "HP Compaq 8510", xy_swap_inverted),
202 AXIS_DMI_MATCH("HP2133", "HP 2133", xy_rotated_left),
203 AXIS_DMI_MATCH("HP2140", "HP 2140", xy_swap_inverted),
204 AXIS_DMI_MATCH("NC653x", "HP Compaq 653", xy_rotated_left_usd),
205 AXIS_DMI_MATCH("NC6730b", "HP Compaq 6730b", xy_rotated_left_usd),
206 AXIS_DMI_MATCH("NC6730s", "HP Compaq 6730s", xy_swap),
207 AXIS_DMI_MATCH("NC651xx", "HP Compaq 651", xy_rotated_right),
208 AXIS_DMI_MATCH("NC6710x", "HP Compaq 6710", xy_swap_yz_inverted),
209 AXIS_DMI_MATCH("NC6715x", "HP Compaq 6715", y_inverted),
210 AXIS_DMI_MATCH("NC693xx", "HP EliteBook 693", xy_rotated_right),
211 AXIS_DMI_MATCH("NC693xx", "HP EliteBook 853", xy_swap),
212 /* Intel-based HP Pavilion dv5 */
213 AXIS_DMI_MATCH2("HPDV5_I",
214 PRODUCT_NAME, "HP Pavilion dv5",
215 BOARD_NAME, "3603",
216 x_inverted),
217 /* AMD-based HP Pavilion dv5 */
218 AXIS_DMI_MATCH2("HPDV5_A",
219 PRODUCT_NAME, "HP Pavilion dv5",
220 BOARD_NAME, "3600",
221 y_inverted),
222 AXIS_DMI_MATCH("DV7", "HP Pavilion dv7", x_inverted),
223 AXIS_DMI_MATCH("HP8710", "HP Compaq 8710", y_inverted),
224 AXIS_DMI_MATCH("HDX18", "HP HDX 18", x_inverted),
225 AXIS_DMI_MATCH("HPB432x", "HP ProBook 432", xy_rotated_left),
226 AXIS_DMI_MATCH("HPB442x", "HP ProBook 442", xy_rotated_left),
227 AXIS_DMI_MATCH("HPB452x", "HP ProBook 452", y_inverted),
228 AXIS_DMI_MATCH("HPB522x", "HP ProBook 522", xy_swap),
229 AXIS_DMI_MATCH("HPB532x", "HP ProBook 532", y_inverted),
230 AXIS_DMI_MATCH("Mini510x", "HP Mini 510", xy_rotated_left_usd),
231 { NULL, }
232/* Laptop models without axis info (yet):
233 * "NC6910" "HP Compaq 6910"
234 * "NC2400" "HP Compaq nc2400"
235 * "NX74x0" "HP Compaq nx74"
236 * "NX6325" "HP Compaq nx6325"
237 * "NC4400" "HP Compaq nc4400"
238 */
239};
240
241static void hpled_set(struct delayed_led_classdev *led_cdev, enum led_brightness value)
242{
243 struct acpi_device *dev = lis3_dev.bus_priv;
244 unsigned long long ret; /* Not used when writing */
245 union acpi_object in_obj[1];
246 struct acpi_object_list args = { 1, in_obj };
247
248 in_obj[0].type = ACPI_TYPE_INTEGER;
249 in_obj[0].integer.value = !!value;
250
251 acpi_evaluate_integer(dev->handle, "ALED", &args, &ret);
252}
253
254static struct delayed_led_classdev hpled_led = {
255 .led_classdev = {
256 .name = "hp::hddprotect",
257 .default_trigger = "none",
258 .brightness_set = delayed_sysfs_set,
259 .flags = LED_CORE_SUSPENDRESUME,
260 },
261 .set_brightness = hpled_set,
262};
263
264static acpi_status
265lis3lv02d_get_resource(struct acpi_resource *resource, void *context)
266{
267 if (resource->type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ) {
268 struct acpi_resource_extended_irq *irq;
269 u32 *device_irq = context;
270
271 irq = &resource->data.extended_irq;
272 *device_irq = irq->interrupts[0];
273 }
274
275 return AE_OK;
276}
277
278static void lis3lv02d_enum_resources(struct acpi_device *device)
279{
280 acpi_status status;
281
282 status = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
283 lis3lv02d_get_resource, &lis3_dev.irq);
284 if (ACPI_FAILURE(status))
285 printk(KERN_DEBUG DRIVER_NAME ": Error getting resources\n");
286}
287
288static int lis3lv02d_add(struct acpi_device *device)
289{
290 int ret;
291
292 if (!device)
293 return -EINVAL;
294
295 lis3_dev.bus_priv = device;
296 lis3_dev.init = lis3lv02d_acpi_init;
297 lis3_dev.read = lis3lv02d_acpi_read;
298 lis3_dev.write = lis3lv02d_acpi_write;
299 strcpy(acpi_device_name(device), DRIVER_NAME);
300 strcpy(acpi_device_class(device), ACPI_MDPS_CLASS);
301 device->driver_data = &lis3_dev;
302
303 /* obtain IRQ number of our device from ACPI */
304 lis3lv02d_enum_resources(device);
305
306 /* If possible use a "standard" axes order */
307 if (lis3_dev.ac.x && lis3_dev.ac.y && lis3_dev.ac.z) {
308 pr_info("Using custom axes %d,%d,%d\n",
309 lis3_dev.ac.x, lis3_dev.ac.y, lis3_dev.ac.z);
310 } else if (dmi_check_system(lis3lv02d_dmi_ids) == 0) {
311 pr_info("laptop model unknown, using default axes configuration\n");
312 lis3_dev.ac = lis3lv02d_axis_normal;
313 }
314
315 /* call the core layer do its init */
316 ret = lis3lv02d_init_device(&lis3_dev);
317 if (ret)
318 return ret;
319
320 INIT_WORK(&hpled_led.work, delayed_set_status_worker);
321 ret = led_classdev_register(NULL, &hpled_led.led_classdev);
322 if (ret) {
323 lis3lv02d_joystick_disable();
324 lis3lv02d_poweroff(&lis3_dev);
325 flush_work(&hpled_led.work);
326 return ret;
327 }
328
329 return ret;
330}
331
332static int lis3lv02d_remove(struct acpi_device *device, int type)
333{
334 if (!device)
335 return -EINVAL;
336
337 lis3lv02d_joystick_disable();
338 lis3lv02d_poweroff(&lis3_dev);
339
340 led_classdev_unregister(&hpled_led.led_classdev);
341 flush_work(&hpled_led.work);
342
343 return lis3lv02d_remove_fs(&lis3_dev);
344}
345
346
347#ifdef CONFIG_PM
348static int lis3lv02d_suspend(struct acpi_device *device, pm_message_t state)
349{
350 /* make sure the device is off when we suspend */
351 lis3lv02d_poweroff(&lis3_dev);
352 return 0;
353}
354
355static int lis3lv02d_resume(struct acpi_device *device)
356{
357 lis3lv02d_poweron(&lis3_dev);
358 return 0;
359}
360#else
361#define lis3lv02d_suspend NULL
362#define lis3lv02d_resume NULL
363#endif
364
365/* For the HP MDPS aka 3D Driveguard */
366static struct acpi_driver lis3lv02d_driver = {
367 .name = DRIVER_NAME,
368 .class = ACPI_MDPS_CLASS,
369 .ids = lis3lv02d_device_ids,
370 .ops = {
371 .add = lis3lv02d_add,
372 .remove = lis3lv02d_remove,
373 .suspend = lis3lv02d_suspend,
374 .resume = lis3lv02d_resume,
375 }
376};
377
378static int __init lis3lv02d_init_module(void)
379{
380 int ret;
381
382 if (acpi_disabled)
383 return -ENODEV;
384
385 ret = acpi_bus_register_driver(&lis3lv02d_driver);
386 if (ret < 0)
387 return ret;
388
389 pr_info("driver loaded\n");
390
391 return 0;
392}
393
394static void __exit lis3lv02d_exit_module(void)
395{
396 acpi_bus_unregister_driver(&lis3lv02d_driver);
397}
398
399MODULE_DESCRIPTION("Glue between LIS3LV02Dx and HP ACPI BIOS and support for disk protection LED.");
400MODULE_AUTHOR("Yan Burman, Eric Piel, Pavel Machek");
401MODULE_LICENSE("GPL");
402
403module_init(lis3lv02d_init_module);
404module_exit(lis3lv02d_exit_module);
diff --git a/drivers/platform/x86/ibm_rtl.c b/drivers/platform/x86/ibm_rtl.c
new file mode 100644
index 000000000000..811d436cd677
--- /dev/null
+++ b/drivers/platform/x86/ibm_rtl.c
@@ -0,0 +1,339 @@
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#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
26
27#include <linux/kernel.h>
28#include <linux/delay.h>
29#include <linux/module.h>
30#include <linux/io.h>
31#include <linux/sysdev.h>
32#include <linux/dmi.h>
33#include <linux/efi.h>
34#include <linux/mutex.h>
35#include <asm/bios_ebda.h>
36
37static bool force;
38module_param(force, bool, 0);
39MODULE_PARM_DESC(force, "Force driver load, ignore DMI data");
40
41static bool debug;
42module_param(debug, bool, 0644);
43MODULE_PARM_DESC(debug, "Show debug output");
44
45MODULE_LICENSE("GPL");
46MODULE_AUTHOR("Keith Mannthey <kmmanth@us.ibm.com>");
47MODULE_AUTHOR("Vernon Mauery <vernux@us.ibm.com>");
48
49#define RTL_ADDR_TYPE_IO 1
50#define RTL_ADDR_TYPE_MMIO 2
51
52#define RTL_CMD_ENTER_PRTM 1
53#define RTL_CMD_EXIT_PRTM 2
54
55/* The RTL table as presented by the EBDA: */
56struct ibm_rtl_table {
57 char signature[5]; /* signature should be "_RTL_" */
58 u8 version;
59 u8 rt_status;
60 u8 command;
61 u8 command_status;
62 u8 cmd_address_type;
63 u8 cmd_granularity;
64 u8 cmd_offset;
65 u16 reserve1;
66 u32 cmd_port_address; /* platform dependent address */
67 u32 cmd_port_value; /* platform dependent value */
68} __attribute__((packed));
69
70/* to locate "_RTL_" signature do a masked 5-byte integer compare */
71#define RTL_SIGNATURE 0x0000005f4c54525fULL
72#define RTL_MASK 0x000000ffffffffffULL
73
74#define RTL_DEBUG(fmt, ...) \
75do { \
76 if (debug) \
77 pr_info(fmt, ##__VA_ARGS__); \
78} while (0)
79
80static DEFINE_MUTEX(rtl_lock);
81static struct ibm_rtl_table __iomem *rtl_table;
82static void __iomem *ebda_map;
83static void __iomem *rtl_cmd_addr;
84static u8 rtl_cmd_type;
85static u8 rtl_cmd_width;
86
87#ifndef readq
88static inline __u64 readq(const volatile void __iomem *addr)
89{
90 const volatile u32 __iomem *p = addr;
91 u32 low, high;
92
93 low = readl(p);
94 high = readl(p + 1);
95
96 return low + ((u64)high << 32);
97}
98#endif
99
100static void __iomem *rtl_port_map(phys_addr_t addr, unsigned long len)
101{
102 if (rtl_cmd_type == RTL_ADDR_TYPE_MMIO)
103 return ioremap(addr, len);
104 return ioport_map(addr, len);
105}
106
107static void rtl_port_unmap(void __iomem *addr)
108{
109 if (addr && rtl_cmd_type == RTL_ADDR_TYPE_MMIO)
110 iounmap(addr);
111 else
112 ioport_unmap(addr);
113}
114
115static int ibm_rtl_write(u8 value)
116{
117 int ret = 0, count = 0;
118 static u32 cmd_port_val;
119
120 RTL_DEBUG("%s(%d)\n", __func__, value);
121
122 value = value == 1 ? RTL_CMD_ENTER_PRTM : RTL_CMD_EXIT_PRTM;
123
124 mutex_lock(&rtl_lock);
125
126 if (ioread8(&rtl_table->rt_status) != value) {
127 iowrite8(value, &rtl_table->command);
128
129 switch (rtl_cmd_width) {
130 case 8:
131 cmd_port_val = ioread8(&rtl_table->cmd_port_value);
132 RTL_DEBUG("cmd_port_val = %u\n", cmd_port_val);
133 iowrite8((u8)cmd_port_val, rtl_cmd_addr);
134 break;
135 case 16:
136 cmd_port_val = ioread16(&rtl_table->cmd_port_value);
137 RTL_DEBUG("cmd_port_val = %u\n", cmd_port_val);
138 iowrite16((u16)cmd_port_val, rtl_cmd_addr);
139 break;
140 case 32:
141 cmd_port_val = ioread32(&rtl_table->cmd_port_value);
142 RTL_DEBUG("cmd_port_val = %u\n", cmd_port_val);
143 iowrite32(cmd_port_val, rtl_cmd_addr);
144 break;
145 }
146
147 while (ioread8(&rtl_table->command)) {
148 msleep(10);
149 if (count++ > 500) {
150 pr_err("Hardware not responding to "
151 "mode switch request\n");
152 ret = -EIO;
153 break;
154 }
155
156 }
157
158 if (ioread8(&rtl_table->command_status)) {
159 RTL_DEBUG("command_status reports failed command\n");
160 ret = -EIO;
161 }
162 }
163
164 mutex_unlock(&rtl_lock);
165 return ret;
166}
167
168static ssize_t rtl_show_version(struct sysdev_class * dev,
169 struct sysdev_class_attribute *attr,
170 char *buf)
171{
172 return sprintf(buf, "%d\n", (int)ioread8(&rtl_table->version));
173}
174
175static ssize_t rtl_show_state(struct sysdev_class *dev,
176 struct sysdev_class_attribute *attr,
177 char *buf)
178{
179 return sprintf(buf, "%d\n", ioread8(&rtl_table->rt_status));
180}
181
182static ssize_t rtl_set_state(struct sysdev_class *dev,
183 struct sysdev_class_attribute *attr,
184 const char *buf,
185 size_t count)
186{
187 ssize_t ret;
188
189 if (count < 1 || count > 2)
190 return -EINVAL;
191
192 switch (buf[0]) {
193 case '0':
194 ret = ibm_rtl_write(0);
195 break;
196 case '1':
197 ret = ibm_rtl_write(1);
198 break;
199 default:
200 ret = -EINVAL;
201 }
202 if (ret >= 0)
203 ret = count;
204
205 return ret;
206}
207
208static struct sysdev_class class_rtl = {
209 .name = "ibm_rtl",
210};
211
212static SYSDEV_CLASS_ATTR(version, S_IRUGO, rtl_show_version, NULL);
213static SYSDEV_CLASS_ATTR(state, 0600, rtl_show_state, rtl_set_state);
214
215static struct sysdev_class_attribute *rtl_attributes[] = {
216 &attr_version,
217 &attr_state,
218 NULL
219};
220
221
222static int rtl_setup_sysfs(void) {
223 int ret, i;
224 ret = sysdev_class_register(&class_rtl);
225
226 if (!ret) {
227 for (i = 0; rtl_attributes[i]; i ++)
228 sysdev_class_create_file(&class_rtl, rtl_attributes[i]);
229 }
230 return ret;
231}
232
233static void rtl_teardown_sysfs(void) {
234 int i;
235 for (i = 0; rtl_attributes[i]; i ++)
236 sysdev_class_remove_file(&class_rtl, rtl_attributes[i]);
237 sysdev_class_unregister(&class_rtl);
238}
239
240
241static struct dmi_system_id __initdata ibm_rtl_dmi_table[] = {
242 { \
243 .matches = { \
244 DMI_MATCH(DMI_SYS_VENDOR, "IBM"), \
245 }, \
246 },
247 { }
248};
249
250static int __init ibm_rtl_init(void) {
251 unsigned long ebda_addr, ebda_size;
252 unsigned int ebda_kb;
253 int ret = -ENODEV, i;
254
255 if (force)
256 pr_warn("module loaded by force\n");
257 /* first ensure that we are running on IBM HW */
258 else if (efi_enabled || !dmi_check_system(ibm_rtl_dmi_table))
259 return -ENODEV;
260
261 /* Get the address for the Extended BIOS Data Area */
262 ebda_addr = get_bios_ebda();
263 if (!ebda_addr) {
264 RTL_DEBUG("no BIOS EBDA found\n");
265 return -ENODEV;
266 }
267
268 ebda_map = ioremap(ebda_addr, 4);
269 if (!ebda_map)
270 return -ENOMEM;
271
272 /* First word in the EDBA is the Size in KB */
273 ebda_kb = ioread16(ebda_map);
274 RTL_DEBUG("EBDA is %d kB\n", ebda_kb);
275
276 if (ebda_kb == 0)
277 goto out;
278
279 iounmap(ebda_map);
280 ebda_size = ebda_kb*1024;
281
282 /* Remap the whole table */
283 ebda_map = ioremap(ebda_addr, ebda_size);
284 if (!ebda_map)
285 return -ENOMEM;
286
287 /* search for the _RTL_ signature at the start of the table */
288 for (i = 0 ; i < ebda_size/sizeof(unsigned int); i++) {
289 struct ibm_rtl_table __iomem * tmp;
290 tmp = (struct ibm_rtl_table __iomem *) (ebda_map+i);
291 if ((readq(&tmp->signature) & RTL_MASK) == RTL_SIGNATURE) {
292 phys_addr_t addr;
293 unsigned int plen;
294 RTL_DEBUG("found RTL_SIGNATURE at %p\n", tmp);
295 rtl_table = tmp;
296 /* The address, value, width and offset are platform
297 * dependent and found in the ibm_rtl_table */
298 rtl_cmd_width = ioread8(&rtl_table->cmd_granularity);
299 rtl_cmd_type = ioread8(&rtl_table->cmd_address_type);
300 RTL_DEBUG("rtl_cmd_width = %u, rtl_cmd_type = %u\n",
301 rtl_cmd_width, rtl_cmd_type);
302 addr = ioread32(&rtl_table->cmd_port_address);
303 RTL_DEBUG("addr = %#llx\n", (unsigned long long)addr);
304 plen = rtl_cmd_width/sizeof(char);
305 rtl_cmd_addr = rtl_port_map(addr, plen);
306 RTL_DEBUG("rtl_cmd_addr = %p\n", rtl_cmd_addr);
307 if (!rtl_cmd_addr) {
308 ret = -ENOMEM;
309 break;
310 }
311 ret = rtl_setup_sysfs();
312 break;
313 }
314 }
315
316out:
317 if (ret) {
318 iounmap(ebda_map);
319 rtl_port_unmap(rtl_cmd_addr);
320 }
321
322 return ret;
323}
324
325static void __exit ibm_rtl_exit(void)
326{
327 if (rtl_table) {
328 RTL_DEBUG("cleaning up");
329 /* do not leave the machine in SMI-free mode */
330 ibm_rtl_write(0);
331 /* unmap, unlink and remove all traces */
332 rtl_teardown_sysfs();
333 iounmap(ebda_map);
334 rtl_port_unmap(rtl_cmd_addr);
335 }
336}
337
338module_init(ibm_rtl_init);
339module_exit(ibm_rtl_exit);
diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
new file mode 100644
index 000000000000..bfdda33feb26
--- /dev/null
+++ b/drivers/platform/x86/ideapad-laptop.c
@@ -0,0 +1,497 @@
1/*
2 * ideapad-laptop.c - Lenovo IdeaPad ACPI Extras
3 *
4 * Copyright © 2010 Intel Corporation
5 * Copyright © 2010 David Woodhouse <dwmw2@infradead.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 * 02110-1301, USA.
21 */
22
23#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
24
25#include <linux/kernel.h>
26#include <linux/module.h>
27#include <linux/init.h>
28#include <linux/types.h>
29#include <acpi/acpi_bus.h>
30#include <acpi/acpi_drivers.h>
31#include <linux/rfkill.h>
32#include <linux/platform_device.h>
33#include <linux/input.h>
34#include <linux/input/sparse-keymap.h>
35
36#define IDEAPAD_RFKILL_DEV_NUM (3)
37
38struct ideapad_private {
39 struct rfkill *rfk[IDEAPAD_RFKILL_DEV_NUM];
40 struct platform_device *platform_device;
41 struct input_dev *inputdev;
42};
43
44static acpi_handle ideapad_handle;
45static bool no_bt_rfkill;
46module_param(no_bt_rfkill, bool, 0444);
47MODULE_PARM_DESC(no_bt_rfkill, "No rfkill for bluetooth.");
48
49/*
50 * ACPI Helpers
51 */
52#define IDEAPAD_EC_TIMEOUT (100) /* in ms */
53
54static int read_method_int(acpi_handle handle, const char *method, int *val)
55{
56 acpi_status status;
57 unsigned long long result;
58
59 status = acpi_evaluate_integer(handle, (char *)method, NULL, &result);
60 if (ACPI_FAILURE(status)) {
61 *val = -1;
62 return -1;
63 } else {
64 *val = result;
65 return 0;
66 }
67}
68
69static int method_vpcr(acpi_handle handle, int cmd, int *ret)
70{
71 acpi_status status;
72 unsigned long long result;
73 struct acpi_object_list params;
74 union acpi_object in_obj;
75
76 params.count = 1;
77 params.pointer = &in_obj;
78 in_obj.type = ACPI_TYPE_INTEGER;
79 in_obj.integer.value = cmd;
80
81 status = acpi_evaluate_integer(handle, "VPCR", &params, &result);
82
83 if (ACPI_FAILURE(status)) {
84 *ret = -1;
85 return -1;
86 } else {
87 *ret = result;
88 return 0;
89 }
90}
91
92static int method_vpcw(acpi_handle handle, int cmd, int data)
93{
94 struct acpi_object_list params;
95 union acpi_object in_obj[2];
96 acpi_status status;
97
98 params.count = 2;
99 params.pointer = in_obj;
100 in_obj[0].type = ACPI_TYPE_INTEGER;
101 in_obj[0].integer.value = cmd;
102 in_obj[1].type = ACPI_TYPE_INTEGER;
103 in_obj[1].integer.value = data;
104
105 status = acpi_evaluate_object(handle, "VPCW", &params, NULL);
106 if (status != AE_OK)
107 return -1;
108 return 0;
109}
110
111static int read_ec_data(acpi_handle handle, int cmd, unsigned long *data)
112{
113 int val;
114 unsigned long int end_jiffies;
115
116 if (method_vpcw(handle, 1, cmd))
117 return -1;
118
119 for (end_jiffies = jiffies+(HZ)*IDEAPAD_EC_TIMEOUT/1000+1;
120 time_before(jiffies, end_jiffies);) {
121 schedule();
122 if (method_vpcr(handle, 1, &val))
123 return -1;
124 if (val == 0) {
125 if (method_vpcr(handle, 0, &val))
126 return -1;
127 *data = val;
128 return 0;
129 }
130 }
131 pr_err("timeout in read_ec_cmd\n");
132 return -1;
133}
134
135static int write_ec_cmd(acpi_handle handle, int cmd, unsigned long data)
136{
137 int val;
138 unsigned long int end_jiffies;
139
140 if (method_vpcw(handle, 0, data))
141 return -1;
142 if (method_vpcw(handle, 1, cmd))
143 return -1;
144
145 for (end_jiffies = jiffies+(HZ)*IDEAPAD_EC_TIMEOUT/1000+1;
146 time_before(jiffies, end_jiffies);) {
147 schedule();
148 if (method_vpcr(handle, 1, &val))
149 return -1;
150 if (val == 0)
151 return 0;
152 }
153 pr_err("timeout in write_ec_cmd\n");
154 return -1;
155}
156
157/*
158 * camera power
159 */
160static ssize_t show_ideapad_cam(struct device *dev,
161 struct device_attribute *attr,
162 char *buf)
163{
164 unsigned long result;
165
166 if (read_ec_data(ideapad_handle, 0x1D, &result))
167 return sprintf(buf, "-1\n");
168 return sprintf(buf, "%lu\n", result);
169}
170
171static ssize_t store_ideapad_cam(struct device *dev,
172 struct device_attribute *attr,
173 const char *buf, size_t count)
174{
175 int ret, state;
176
177 if (!count)
178 return 0;
179 if (sscanf(buf, "%i", &state) != 1)
180 return -EINVAL;
181 ret = write_ec_cmd(ideapad_handle, 0x1E, state);
182 if (ret < 0)
183 return ret;
184 return count;
185}
186
187static DEVICE_ATTR(camera_power, 0644, show_ideapad_cam, store_ideapad_cam);
188
189/*
190 * Rfkill
191 */
192struct ideapad_rfk_data {
193 char *name;
194 int cfgbit;
195 int opcode;
196 int type;
197};
198
199const struct ideapad_rfk_data ideapad_rfk_data[] = {
200 { "ideapad_wlan", 18, 0x15, RFKILL_TYPE_WLAN },
201 { "ideapad_bluetooth", 16, 0x17, RFKILL_TYPE_BLUETOOTH },
202 { "ideapad_3g", 17, 0x20, RFKILL_TYPE_WWAN },
203};
204
205static int ideapad_rfk_set(void *data, bool blocked)
206{
207 unsigned long opcode = (unsigned long)data;
208
209 return write_ec_cmd(ideapad_handle, opcode, !blocked);
210}
211
212static struct rfkill_ops ideapad_rfk_ops = {
213 .set_block = ideapad_rfk_set,
214};
215
216static void ideapad_sync_rfk_state(struct acpi_device *adevice)
217{
218 struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
219 unsigned long hw_blocked;
220 int i;
221
222 if (read_ec_data(ideapad_handle, 0x23, &hw_blocked))
223 return;
224 hw_blocked = !hw_blocked;
225
226 for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
227 if (priv->rfk[i])
228 rfkill_set_hw_state(priv->rfk[i], hw_blocked);
229}
230
231static int __devinit ideapad_register_rfkill(struct acpi_device *adevice,
232 int dev)
233{
234 struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
235 int ret;
236 unsigned long sw_blocked;
237
238 if (no_bt_rfkill &&
239 (ideapad_rfk_data[dev].type == RFKILL_TYPE_BLUETOOTH)) {
240 /* Force to enable bluetooth when no_bt_rfkill=1 */
241 write_ec_cmd(ideapad_handle,
242 ideapad_rfk_data[dev].opcode, 1);
243 return 0;
244 }
245
246 priv->rfk[dev] = rfkill_alloc(ideapad_rfk_data[dev].name, &adevice->dev,
247 ideapad_rfk_data[dev].type, &ideapad_rfk_ops,
248 (void *)(long)dev);
249 if (!priv->rfk[dev])
250 return -ENOMEM;
251
252 if (read_ec_data(ideapad_handle, ideapad_rfk_data[dev].opcode-1,
253 &sw_blocked)) {
254 rfkill_init_sw_state(priv->rfk[dev], 0);
255 } else {
256 sw_blocked = !sw_blocked;
257 rfkill_init_sw_state(priv->rfk[dev], sw_blocked);
258 }
259
260 ret = rfkill_register(priv->rfk[dev]);
261 if (ret) {
262 rfkill_destroy(priv->rfk[dev]);
263 return ret;
264 }
265 return 0;
266}
267
268static void __devexit ideapad_unregister_rfkill(struct acpi_device *adevice,
269 int dev)
270{
271 struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
272
273 if (!priv->rfk[dev])
274 return;
275
276 rfkill_unregister(priv->rfk[dev]);
277 rfkill_destroy(priv->rfk[dev]);
278}
279
280/*
281 * Platform device
282 */
283static struct attribute *ideapad_attributes[] = {
284 &dev_attr_camera_power.attr,
285 NULL
286};
287
288static struct attribute_group ideapad_attribute_group = {
289 .attrs = ideapad_attributes
290};
291
292static int __devinit ideapad_platform_init(struct ideapad_private *priv)
293{
294 int result;
295
296 priv->platform_device = platform_device_alloc("ideapad", -1);
297 if (!priv->platform_device)
298 return -ENOMEM;
299 platform_set_drvdata(priv->platform_device, priv);
300
301 result = platform_device_add(priv->platform_device);
302 if (result)
303 goto fail_platform_device;
304
305 result = sysfs_create_group(&priv->platform_device->dev.kobj,
306 &ideapad_attribute_group);
307 if (result)
308 goto fail_sysfs;
309 return 0;
310
311fail_sysfs:
312 platform_device_del(priv->platform_device);
313fail_platform_device:
314 platform_device_put(priv->platform_device);
315 return result;
316}
317
318static void ideapad_platform_exit(struct ideapad_private *priv)
319{
320 sysfs_remove_group(&priv->platform_device->dev.kobj,
321 &ideapad_attribute_group);
322 platform_device_unregister(priv->platform_device);
323}
324
325/*
326 * input device
327 */
328static const struct key_entry ideapad_keymap[] = {
329 { KE_KEY, 0x06, { KEY_SWITCHVIDEOMODE } },
330 { KE_KEY, 0x0D, { KEY_WLAN } },
331 { KE_END, 0 },
332};
333
334static int __devinit ideapad_input_init(struct ideapad_private *priv)
335{
336 struct input_dev *inputdev;
337 int error;
338
339 inputdev = input_allocate_device();
340 if (!inputdev) {
341 pr_info("Unable to allocate input device\n");
342 return -ENOMEM;
343 }
344
345 inputdev->name = "Ideapad extra buttons";
346 inputdev->phys = "ideapad/input0";
347 inputdev->id.bustype = BUS_HOST;
348 inputdev->dev.parent = &priv->platform_device->dev;
349
350 error = sparse_keymap_setup(inputdev, ideapad_keymap, NULL);
351 if (error) {
352 pr_err("Unable to setup input device keymap\n");
353 goto err_free_dev;
354 }
355
356 error = input_register_device(inputdev);
357 if (error) {
358 pr_err("Unable to register input device\n");
359 goto err_free_keymap;
360 }
361
362 priv->inputdev = inputdev;
363 return 0;
364
365err_free_keymap:
366 sparse_keymap_free(inputdev);
367err_free_dev:
368 input_free_device(inputdev);
369 return error;
370}
371
372static void __devexit ideapad_input_exit(struct ideapad_private *priv)
373{
374 sparse_keymap_free(priv->inputdev);
375 input_unregister_device(priv->inputdev);
376 priv->inputdev = NULL;
377}
378
379static void ideapad_input_report(struct ideapad_private *priv,
380 unsigned long scancode)
381{
382 sparse_keymap_report_event(priv->inputdev, scancode, 1, true);
383}
384
385/*
386 * module init/exit
387 */
388static const struct acpi_device_id ideapad_device_ids[] = {
389 { "VPC2004", 0},
390 { "", 0},
391};
392MODULE_DEVICE_TABLE(acpi, ideapad_device_ids);
393
394static int __devinit ideapad_acpi_add(struct acpi_device *adevice)
395{
396 int ret, i, cfg;
397 struct ideapad_private *priv;
398
399 if (read_method_int(adevice->handle, "_CFG", &cfg))
400 return -ENODEV;
401
402 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
403 if (!priv)
404 return -ENOMEM;
405 dev_set_drvdata(&adevice->dev, priv);
406 ideapad_handle = adevice->handle;
407
408 ret = ideapad_platform_init(priv);
409 if (ret)
410 goto platform_failed;
411
412 ret = ideapad_input_init(priv);
413 if (ret)
414 goto input_failed;
415
416 for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) {
417 if (test_bit(ideapad_rfk_data[i].cfgbit, (unsigned long *)&cfg))
418 ideapad_register_rfkill(adevice, i);
419 else
420 priv->rfk[i] = NULL;
421 }
422 ideapad_sync_rfk_state(adevice);
423
424 return 0;
425
426input_failed:
427 ideapad_platform_exit(priv);
428platform_failed:
429 kfree(priv);
430 return ret;
431}
432
433static int __devexit ideapad_acpi_remove(struct acpi_device *adevice, int type)
434{
435 struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
436 int i;
437
438 for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
439 ideapad_unregister_rfkill(adevice, i);
440 ideapad_input_exit(priv);
441 ideapad_platform_exit(priv);
442 dev_set_drvdata(&adevice->dev, NULL);
443 kfree(priv);
444
445 return 0;
446}
447
448static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event)
449{
450 struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
451 acpi_handle handle = adevice->handle;
452 unsigned long vpc1, vpc2, vpc_bit;
453
454 if (read_ec_data(handle, 0x10, &vpc1))
455 return;
456 if (read_ec_data(handle, 0x1A, &vpc2))
457 return;
458
459 vpc1 = (vpc2 << 8) | vpc1;
460 for (vpc_bit = 0; vpc_bit < 16; vpc_bit++) {
461 if (test_bit(vpc_bit, &vpc1)) {
462 if (vpc_bit == 9)
463 ideapad_sync_rfk_state(adevice);
464 else if (vpc_bit == 4)
465 read_ec_data(handle, 0x12, &vpc2);
466 else
467 ideapad_input_report(priv, vpc_bit);
468 }
469 }
470}
471
472static struct acpi_driver ideapad_acpi_driver = {
473 .name = "ideapad_acpi",
474 .class = "IdeaPad",
475 .ids = ideapad_device_ids,
476 .ops.add = ideapad_acpi_add,
477 .ops.remove = ideapad_acpi_remove,
478 .ops.notify = ideapad_acpi_notify,
479 .owner = THIS_MODULE,
480};
481
482static int __init ideapad_acpi_module_init(void)
483{
484 return acpi_bus_register_driver(&ideapad_acpi_driver);
485}
486
487static void __exit ideapad_acpi_module_exit(void)
488{
489 acpi_bus_unregister_driver(&ideapad_acpi_driver);
490}
491
492MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
493MODULE_DESCRIPTION("IdeaPad ACPI Extras");
494MODULE_LICENSE("GPL");
495
496module_init(ideapad_acpi_module_init);
497module_exit(ideapad_acpi_module_exit);
diff --git a/drivers/platform/x86/ideapad_acpi.c b/drivers/platform/x86/ideapad_acpi.c
deleted file mode 100644
index 798496353e8c..000000000000
--- a/drivers/platform/x86/ideapad_acpi.c
+++ /dev/null
@@ -1,306 +0,0 @@
1/*
2 * ideapad_acpi.c - Lenovo IdeaPad ACPI Extras
3 *
4 * Copyright © 2010 Intel Corporation
5 * Copyright © 2010 David Woodhouse <dwmw2@infradead.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 * 02110-1301, USA.
21 */
22
23#include <linux/kernel.h>
24#include <linux/module.h>
25#include <linux/init.h>
26#include <linux/types.h>
27#include <acpi/acpi_bus.h>
28#include <acpi/acpi_drivers.h>
29#include <linux/rfkill.h>
30
31#define IDEAPAD_DEV_CAMERA 0
32#define IDEAPAD_DEV_WLAN 1
33#define IDEAPAD_DEV_BLUETOOTH 2
34#define IDEAPAD_DEV_3G 3
35#define IDEAPAD_DEV_KILLSW 4
36
37struct ideapad_private {
38 struct rfkill *rfk[5];
39};
40
41static struct {
42 char *name;
43 int type;
44} ideapad_rfk_data[] = {
45 /* camera has no rfkill */
46 { "ideapad_wlan", RFKILL_TYPE_WLAN },
47 { "ideapad_bluetooth", RFKILL_TYPE_BLUETOOTH },
48 { "ideapad_3g", RFKILL_TYPE_WWAN },
49 { "ideapad_killsw", RFKILL_TYPE_WLAN }
50};
51
52static int ideapad_dev_exists(int device)
53{
54 acpi_status status;
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
60 output.length = sizeof(out_obj);
61 output.pointer = &out_obj;
62
63 in_param.type = ACPI_TYPE_INTEGER;
64 in_param.integer.value = device + 1;
65
66 status = acpi_evaluate_object(NULL, "\\_SB_.DECN", &input, &output);
67 if (ACPI_FAILURE(status)) {
68 printk(KERN_WARNING "IdeaPAD \\_SB_.DECN method failed %d. Is this an IdeaPAD?\n", status);
69 return -ENODEV;
70 }
71 if (out_obj.type != ACPI_TYPE_INTEGER) {
72 printk(KERN_WARNING "IdeaPAD \\_SB_.DECN method returned unexpected type\n");
73 return -ENODEV;
74 }
75 return out_obj.integer.value;
76}
77
78static int ideapad_dev_get_state(int device)
79{
80 acpi_status status;
81 union acpi_object in_param;
82 struct acpi_object_list input = { 1, &in_param };
83 struct acpi_buffer output;
84 union acpi_object out_obj;
85
86 output.length = sizeof(out_obj);
87 output.pointer = &out_obj;
88
89 in_param.type = ACPI_TYPE_INTEGER;
90 in_param.integer.value = device + 1;
91
92 status = acpi_evaluate_object(NULL, "\\_SB_.GECN", &input, &output);
93 if (ACPI_FAILURE(status)) {
94 printk(KERN_WARNING "IdeaPAD \\_SB_.GECN method failed %d\n", status);
95 return -ENODEV;
96 }
97 if (out_obj.type != ACPI_TYPE_INTEGER) {
98 printk(KERN_WARNING "IdeaPAD \\_SB_.GECN method returned unexpected type\n");
99 return -ENODEV;
100 }
101 return out_obj.integer.value;
102}
103
104static int ideapad_dev_set_state(int device, int state)
105{
106 acpi_status status;
107 union acpi_object in_params[2];
108 struct acpi_object_list input = { 2, in_params };
109
110 in_params[0].type = ACPI_TYPE_INTEGER;
111 in_params[0].integer.value = device + 1;
112 in_params[1].type = ACPI_TYPE_INTEGER;
113 in_params[1].integer.value = state;
114
115 status = acpi_evaluate_object(NULL, "\\_SB_.SECN", &input, NULL);
116 if (ACPI_FAILURE(status)) {
117 printk(KERN_WARNING "IdeaPAD \\_SB_.SECN method failed %d\n", status);
118 return -ENODEV;
119 }
120 return 0;
121}
122static ssize_t show_ideapad_cam(struct device *dev,
123 struct device_attribute *attr,
124 char *buf)
125{
126 int state = ideapad_dev_get_state(IDEAPAD_DEV_CAMERA);
127 if (state < 0)
128 return state;
129
130 return sprintf(buf, "%d\n", state);
131}
132
133static ssize_t store_ideapad_cam(struct device *dev,
134 struct device_attribute *attr,
135 const char *buf, size_t count)
136{
137 int ret, state;
138
139 if (!count)
140 return 0;
141 if (sscanf(buf, "%i", &state) != 1)
142 return -EINVAL;
143 ret = ideapad_dev_set_state(IDEAPAD_DEV_CAMERA, !!state);
144 if (ret < 0)
145 return ret;
146 return count;
147}
148
149static DEVICE_ATTR(camera_power, 0644, show_ideapad_cam, store_ideapad_cam);
150
151static int ideapad_rfk_set(void *data, bool blocked)
152{
153 int device = (unsigned long)data;
154
155 if (device == IDEAPAD_DEV_KILLSW)
156 return -EINVAL;
157 return ideapad_dev_set_state(device, !blocked);
158}
159
160static struct rfkill_ops ideapad_rfk_ops = {
161 .set_block = ideapad_rfk_set,
162};
163
164static void ideapad_sync_rfk_state(struct acpi_device *adevice)
165{
166 struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
167 int hw_blocked = !ideapad_dev_get_state(IDEAPAD_DEV_KILLSW);
168 int i;
169
170 rfkill_set_hw_state(priv->rfk[IDEAPAD_DEV_KILLSW], 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;
176
177 for (i = IDEAPAD_DEV_WLAN; i < IDEAPAD_DEV_KILLSW; i++)
178 if (priv->rfk[i])
179 rfkill_set_sw_state(priv->rfk[i], !ideapad_dev_get_state(i));
180}
181
182static int ideapad_register_rfkill(struct acpi_device *adevice, int dev)
183{
184 struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
185 int ret;
186
187 priv->rfk[dev] = rfkill_alloc(ideapad_rfk_data[dev-1].name, &adevice->dev,
188 ideapad_rfk_data[dev-1].type, &ideapad_rfk_ops,
189 (void *)(long)dev);
190 if (!priv->rfk[dev])
191 return -ENOMEM;
192
193 ret = rfkill_register(priv->rfk[dev]);
194 if (ret) {
195 rfkill_destroy(priv->rfk[dev]);
196 return ret;
197 }
198 return 0;
199}
200
201static void ideapad_unregister_rfkill(struct acpi_device *adevice, int dev)
202{
203 struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
204
205 if (!priv->rfk[dev])
206 return;
207
208 rfkill_unregister(priv->rfk[dev]);
209 rfkill_destroy(priv->rfk[dev]);
210}
211
212static const struct acpi_device_id ideapad_device_ids[] = {
213 { "VPC2004", 0},
214 { "", 0},
215};
216MODULE_DEVICE_TABLE(acpi, ideapad_device_ids);
217
218static int ideapad_acpi_add(struct acpi_device *adevice)
219{
220 int i;
221 int devs_present[5];
222 struct ideapad_private *priv;
223
224 for (i = IDEAPAD_DEV_CAMERA; i < IDEAPAD_DEV_KILLSW; i++) {
225 devs_present[i] = ideapad_dev_exists(i);
226 if (devs_present[i] < 0)
227 return devs_present[i];
228 }
229
230 /* The hardware switch is always present */
231 devs_present[IDEAPAD_DEV_KILLSW] = 1;
232
233 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
234 if (!priv)
235 return -ENOMEM;
236
237 if (devs_present[IDEAPAD_DEV_CAMERA]) {
238 int ret = device_create_file(&adevice->dev, &dev_attr_camera_power);
239 if (ret) {
240 kfree(priv);
241 return ret;
242 }
243 }
244
245 dev_set_drvdata(&adevice->dev, priv);
246 for (i = IDEAPAD_DEV_WLAN; i <= IDEAPAD_DEV_KILLSW; i++) {
247 if (!devs_present[i])
248 continue;
249
250 ideapad_register_rfkill(adevice, i);
251 }
252 ideapad_sync_rfk_state(adevice);
253 return 0;
254}
255
256static int ideapad_acpi_remove(struct acpi_device *adevice, int type)
257{
258 struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
259 int i;
260
261 device_remove_file(&adevice->dev, &dev_attr_camera_power);
262
263 for (i = IDEAPAD_DEV_WLAN; i <= IDEAPAD_DEV_KILLSW; i++)
264 ideapad_unregister_rfkill(adevice, i);
265
266 dev_set_drvdata(&adevice->dev, NULL);
267 kfree(priv);
268 return 0;
269}
270
271static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event)
272{
273 ideapad_sync_rfk_state(adevice);
274}
275
276static struct acpi_driver ideapad_acpi_driver = {
277 .name = "ideapad_acpi",
278 .class = "IdeaPad",
279 .ids = ideapad_device_ids,
280 .ops.add = ideapad_acpi_add,
281 .ops.remove = ideapad_acpi_remove,
282 .ops.notify = ideapad_acpi_notify,
283 .owner = THIS_MODULE,
284};
285
286
287static int __init ideapad_acpi_module_init(void)
288{
289 acpi_bus_register_driver(&ideapad_acpi_driver);
290
291 return 0;
292}
293
294
295static void __exit ideapad_acpi_module_exit(void)
296{
297 acpi_bus_unregister_driver(&ideapad_acpi_driver);
298
299}
300
301MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
302MODULE_DESCRIPTION("IdeaPad ACPI Extras");
303MODULE_LICENSE("GPL");
304
305module_init(ideapad_acpi_module_init);
306module_exit(ideapad_acpi_module_exit);
diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c
index c44a5e8b8b82..5ffe7c398148 100644
--- a/drivers/platform/x86/intel_ips.c
+++ b/drivers/platform/x86/intel_ips.c
@@ -75,6 +75,7 @@
75#include <drm/i915_drm.h> 75#include <drm/i915_drm.h>
76#include <asm/msr.h> 76#include <asm/msr.h>
77#include <asm/processor.h> 77#include <asm/processor.h>
78#include "intel_ips.h"
78 79
79#define PCI_DEVICE_ID_INTEL_THERMAL_SENSOR 0x3b32 80#define PCI_DEVICE_ID_INTEL_THERMAL_SENSOR 0x3b32
80 81
@@ -245,6 +246,7 @@
245#define thm_writel(off, val) writel((val), ips->regmap + (off)) 246#define thm_writel(off, val) writel((val), ips->regmap + (off))
246 247
247static const int IPS_ADJUST_PERIOD = 5000; /* ms */ 248static const int IPS_ADJUST_PERIOD = 5000; /* ms */
249static bool late_i915_load = false;
248 250
249/* For initial average collection */ 251/* For initial average collection */
250static const int IPS_SAMPLE_PERIOD = 200; /* ms */ 252static const int IPS_SAMPLE_PERIOD = 200; /* ms */
@@ -339,6 +341,22 @@ struct ips_driver {
339 u64 orig_turbo_ratios; 341 u64 orig_turbo_ratios;
340}; 342};
341 343
344static bool
345ips_gpu_turbo_enabled(struct ips_driver *ips);
346
347#ifndef readq
348static inline __u64 readq(const volatile void __iomem *addr)
349{
350 const volatile u32 __iomem *p = addr;
351 u32 low, high;
352
353 low = readl(p);
354 high = readl(p + 1);
355
356 return low + ((u64)high << 32);
357}
358#endif
359
342/** 360/**
343 * ips_cpu_busy - is CPU busy? 361 * ips_cpu_busy - is CPU busy?
344 * @ips: IPS driver struct 362 * @ips: IPS driver struct
@@ -517,7 +535,7 @@ static void ips_disable_cpu_turbo(struct ips_driver *ips)
517 */ 535 */
518static bool ips_gpu_busy(struct ips_driver *ips) 536static bool ips_gpu_busy(struct ips_driver *ips)
519{ 537{
520 if (!ips->gpu_turbo_enabled) 538 if (!ips_gpu_turbo_enabled(ips))
521 return false; 539 return false;
522 540
523 return ips->gpu_busy(); 541 return ips->gpu_busy();
@@ -532,7 +550,7 @@ static bool ips_gpu_busy(struct ips_driver *ips)
532 */ 550 */
533static void ips_gpu_raise(struct ips_driver *ips) 551static void ips_gpu_raise(struct ips_driver *ips)
534{ 552{
535 if (!ips->gpu_turbo_enabled) 553 if (!ips_gpu_turbo_enabled(ips))
536 return; 554 return;
537 555
538 if (!ips->gpu_raise()) 556 if (!ips->gpu_raise())
@@ -549,7 +567,7 @@ static void ips_gpu_raise(struct ips_driver *ips)
549 */ 567 */
550static void ips_gpu_lower(struct ips_driver *ips) 568static void ips_gpu_lower(struct ips_driver *ips)
551{ 569{
552 if (!ips->gpu_turbo_enabled) 570 if (!ips_gpu_turbo_enabled(ips))
553 return; 571 return;
554 572
555 if (!ips->gpu_lower()) 573 if (!ips->gpu_lower())
@@ -1106,7 +1124,7 @@ static int ips_monitor(void *data)
1106 last_msecs = jiffies_to_msecs(jiffies); 1124 last_msecs = jiffies_to_msecs(jiffies);
1107 expire = jiffies + msecs_to_jiffies(IPS_SAMPLE_PERIOD); 1125 expire = jiffies + msecs_to_jiffies(IPS_SAMPLE_PERIOD);
1108 1126
1109 __set_current_state(TASK_UNINTERRUPTIBLE); 1127 __set_current_state(TASK_INTERRUPTIBLE);
1110 mod_timer(&timer, expire); 1128 mod_timer(&timer, expire);
1111 schedule(); 1129 schedule();
1112 1130
@@ -1454,6 +1472,31 @@ out_err:
1454 return false; 1472 return false;
1455} 1473}
1456 1474
1475static bool
1476ips_gpu_turbo_enabled(struct ips_driver *ips)
1477{
1478 if (!ips->gpu_busy && late_i915_load) {
1479 if (ips_get_i915_syms(ips)) {
1480 dev_info(&ips->dev->dev,
1481 "i915 driver attached, reenabling gpu turbo\n");
1482 ips->gpu_turbo_enabled = !(thm_readl(THM_HTS) & HTS_GTD_DIS);
1483 }
1484 }
1485
1486 return ips->gpu_turbo_enabled;
1487}
1488
1489void
1490ips_link_to_i915_driver(void)
1491{
1492 /* We can't cleanly get at the various ips_driver structs from
1493 * this caller (the i915 driver), so just set a flag saying
1494 * that it's time to try getting the symbols again.
1495 */
1496 late_i915_load = true;
1497}
1498EXPORT_SYMBOL_GPL(ips_link_to_i915_driver);
1499
1457static DEFINE_PCI_DEVICE_TABLE(ips_id_table) = { 1500static DEFINE_PCI_DEVICE_TABLE(ips_id_table) = {
1458 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 1501 { PCI_DEVICE(PCI_VENDOR_ID_INTEL,
1459 PCI_DEVICE_ID_INTEL_THERMAL_SENSOR), }, 1502 PCI_DEVICE_ID_INTEL_THERMAL_SENSOR), },
diff --git a/drivers/platform/x86/intel_ips.h b/drivers/platform/x86/intel_ips.h
new file mode 100644
index 000000000000..73299beff5b3
--- /dev/null
+++ b/drivers/platform/x86/intel_ips.h
@@ -0,0 +1,21 @@
1/*
2 * Copyright (c) 2010 Intel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
16 *
17 * The full GNU General Public License is included in this distribution in
18 * the file called "COPYING".
19 */
20
21void ips_link_to_i915_driver(void);
diff --git a/drivers/platform/x86/intel_menlow.c b/drivers/platform/x86/intel_menlow.c
index eacd5da7dd24..809adea4965f 100644
--- a/drivers/platform/x86/intel_menlow.c
+++ b/drivers/platform/x86/intel_menlow.c
@@ -27,6 +27,8 @@
27 * to get/set bandwidth. 27 * to get/set bandwidth.
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/module.h> 33#include <linux/module.h>
32#include <linux/init.h> 34#include <linux/init.h>
@@ -135,8 +137,7 @@ static int memory_set_cur_bandwidth(struct thermal_cooling_device *cdev,
135 acpi_evaluate_integer(handle, MEMORY_SET_BANDWIDTH, &arg_list, 137 acpi_evaluate_integer(handle, MEMORY_SET_BANDWIDTH, &arg_list,
136 &temp); 138 &temp);
137 139
138 printk(KERN_INFO 140 pr_info("Bandwidth value was %ld: status is %d\n", state, status);
139 "Bandwidth value was %ld: status is %d\n", state, status);
140 if (ACPI_FAILURE(status)) 141 if (ACPI_FAILURE(status))
141 return -EFAULT; 142 return -EFAULT;
142 143
diff --git a/drivers/platform/x86/intel_mid_powerbtn.c b/drivers/platform/x86/intel_mid_powerbtn.c
new file mode 100644
index 000000000000..f1ae5078b7ec
--- /dev/null
+++ b/drivers/platform/x86/intel_mid_powerbtn.c
@@ -0,0 +1,136 @@
1/*
2 * Power button driver for Medfield.
3 *
4 * Copyright (C) 2010 Intel Corp
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; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
18 */
19
20#include <linux/module.h>
21#include <linux/init.h>
22#include <linux/interrupt.h>
23#include <linux/slab.h>
24#include <linux/platform_device.h>
25#include <linux/input.h>
26
27#include <asm/intel_scu_ipc.h>
28
29#define DRIVER_NAME "msic_power_btn"
30
31#define MSIC_PB_STATUS 0x3f
32#define MSIC_PB_LEVEL (1 << 3) /* 1 - release, 0 - press */
33
34static irqreturn_t mfld_pb_isr(int irq, void *dev_id)
35{
36 struct input_dev *input = dev_id;
37 int ret;
38 u8 pbstat;
39
40 ret = intel_scu_ipc_ioread8(MSIC_PB_STATUS, &pbstat);
41 if (ret < 0) {
42 dev_err(input->dev.parent, "Read error %d while reading"
43 " MSIC_PB_STATUS\n", ret);
44 } else {
45 input_event(input, EV_KEY, KEY_POWER,
46 !(pbstat & MSIC_PB_LEVEL));
47 input_sync(input);
48 }
49
50 return IRQ_HANDLED;
51}
52
53static int __devinit mfld_pb_probe(struct platform_device *pdev)
54{
55 struct input_dev *input;
56 int irq = platform_get_irq(pdev, 0);
57 int error;
58
59 if (irq < 0)
60 return -EINVAL;
61
62 input = input_allocate_device();
63 if (!input) {
64 dev_err(&pdev->dev, "Input device allocation error\n");
65 return -ENOMEM;
66 }
67
68 input->name = pdev->name;
69 input->phys = "power-button/input0";
70 input->id.bustype = BUS_HOST;
71 input->dev.parent = &pdev->dev;
72
73 input_set_capability(input, EV_KEY, KEY_POWER);
74
75 error = request_threaded_irq(irq, NULL, mfld_pb_isr, 0,
76 DRIVER_NAME, input);
77 if (error) {
78 dev_err(&pdev->dev, "Unable to request irq %d for mfld power"
79 "button\n", irq);
80 goto err_free_input;
81 }
82
83 error = input_register_device(input);
84 if (error) {
85 dev_err(&pdev->dev, "Unable to register input dev, error "
86 "%d\n", error);
87 goto err_free_irq;
88 }
89
90 platform_set_drvdata(pdev, input);
91 return 0;
92
93err_free_irq:
94 free_irq(irq, input);
95err_free_input:
96 input_free_device(input);
97 return error;
98}
99
100static int __devexit mfld_pb_remove(struct platform_device *pdev)
101{
102 struct input_dev *input = platform_get_drvdata(pdev);
103 int irq = platform_get_irq(pdev, 0);
104
105 free_irq(irq, input);
106 input_unregister_device(input);
107 platform_set_drvdata(pdev, NULL);
108
109 return 0;
110}
111
112static struct platform_driver mfld_pb_driver = {
113 .driver = {
114 .name = DRIVER_NAME,
115 .owner = THIS_MODULE,
116 },
117 .probe = mfld_pb_probe,
118 .remove = __devexit_p(mfld_pb_remove),
119};
120
121static int __init mfld_pb_init(void)
122{
123 return platform_driver_register(&mfld_pb_driver);
124}
125module_init(mfld_pb_init);
126
127static void __exit mfld_pb_exit(void)
128{
129 platform_driver_unregister(&mfld_pb_driver);
130}
131module_exit(mfld_pb_exit);
132
133MODULE_AUTHOR("Hong Liu <hong.liu@intel.com>");
134MODULE_DESCRIPTION("Intel Medfield Power Button Driver");
135MODULE_LICENSE("GPL v2");
136MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/platform/x86/intel_mid_thermal.c b/drivers/platform/x86/intel_mid_thermal.c
new file mode 100644
index 000000000000..3a578323122b
--- /dev/null
+++ b/drivers/platform/x86/intel_mid_thermal.c
@@ -0,0 +1,571 @@
1/*
2 * intel_mid_thermal.c - Intel MID platform thermal driver
3 *
4 * Copyright (C) 2011 Intel Corporation
5 *
6 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
20 *
21 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
22 * Author: Durgadoss R <durgadoss.r@intel.com>
23 */
24
25#define pr_fmt(fmt) "intel_mid_thermal: " fmt
26
27#include <linux/module.h>
28#include <linux/init.h>
29#include <linux/err.h>
30#include <linux/param.h>
31#include <linux/device.h>
32#include <linux/platform_device.h>
33#include <linux/slab.h>
34#include <linux/pm.h>
35#include <linux/thermal.h>
36
37#include <asm/intel_scu_ipc.h>
38
39/* Number of thermal sensors */
40#define MSIC_THERMAL_SENSORS 4
41
42/* ADC1 - thermal registers */
43#define MSIC_THERM_ADC1CNTL1 0x1C0
44#define MSIC_ADC_ENBL 0x10
45#define MSIC_ADC_START 0x08
46
47#define MSIC_THERM_ADC1CNTL3 0x1C2
48#define MSIC_ADCTHERM_ENBL 0x04
49#define MSIC_ADCRRDATA_ENBL 0x05
50#define MSIC_CHANL_MASK_VAL 0x0F
51
52#define MSIC_STOPBIT_MASK 16
53#define MSIC_ADCTHERM_MASK 4
54/* Number of ADC channels */
55#define ADC_CHANLS_MAX 15
56#define ADC_LOOP_MAX (ADC_CHANLS_MAX - MSIC_THERMAL_SENSORS)
57
58/* ADC channel code values */
59#define SKIN_SENSOR0_CODE 0x08
60#define SKIN_SENSOR1_CODE 0x09
61#define SYS_SENSOR_CODE 0x0A
62#define MSIC_DIE_SENSOR_CODE 0x03
63
64#define SKIN_THERM_SENSOR0 0
65#define SKIN_THERM_SENSOR1 1
66#define SYS_THERM_SENSOR2 2
67#define MSIC_DIE_THERM_SENSOR3 3
68
69/* ADC code range */
70#define ADC_MAX 977
71#define ADC_MIN 162
72#define ADC_VAL0C 887
73#define ADC_VAL20C 720
74#define ADC_VAL40C 508
75#define ADC_VAL60C 315
76
77/* ADC base addresses */
78#define ADC_CHNL_START_ADDR 0x1C5 /* increments by 1 */
79#define ADC_DATA_START_ADDR 0x1D4 /* increments by 2 */
80
81/* MSIC die attributes */
82#define MSIC_DIE_ADC_MIN 488
83#define MSIC_DIE_ADC_MAX 1004
84
85/* This holds the address of the first free ADC channel,
86 * among the 15 channels
87 */
88static int channel_index;
89
90struct platform_info {
91 struct platform_device *pdev;
92 struct thermal_zone_device *tzd[MSIC_THERMAL_SENSORS];
93};
94
95struct thermal_device_info {
96 unsigned int chnl_addr;
97 int direct;
98 /* This holds the current temperature in millidegree celsius */
99 long curr_temp;
100};
101
102/**
103 * to_msic_die_temp - converts adc_val to msic_die temperature
104 * @adc_val: ADC value to be converted
105 *
106 * Can sleep
107 */
108static int to_msic_die_temp(uint16_t adc_val)
109{
110 return (368 * (adc_val) / 1000) - 220;
111}
112
113/**
114 * is_valid_adc - checks whether the adc code is within the defined range
115 * @min: minimum value for the sensor
116 * @max: maximum value for the sensor
117 *
118 * Can sleep
119 */
120static int is_valid_adc(uint16_t adc_val, uint16_t min, uint16_t max)
121{
122 return (adc_val >= min) && (adc_val <= max);
123}
124
125/**
126 * adc_to_temp - converts the ADC code to temperature in C
127 * @direct: true if ths channel is direct index
128 * @adc_val: the adc_val that needs to be converted
129 * @tp: temperature return value
130 *
131 * Linear approximation is used to covert the skin adc value into temperature.
132 * This technique is used to avoid very long look-up table to get
133 * the appropriate temp value from ADC value.
134 * The adc code vs sensor temp curve is split into five parts
135 * to achieve very close approximate temp value with less than
136 * 0.5C error
137 */
138static int adc_to_temp(int direct, uint16_t adc_val, unsigned long *tp)
139{
140 int temp;
141
142 /* Direct conversion for die temperature */
143 if (direct) {
144 if (is_valid_adc(adc_val, MSIC_DIE_ADC_MIN, MSIC_DIE_ADC_MAX)) {
145 *tp = to_msic_die_temp(adc_val) * 1000;
146 return 0;
147 }
148 return -ERANGE;
149 }
150
151 if (!is_valid_adc(adc_val, ADC_MIN, ADC_MAX))
152 return -ERANGE;
153
154 /* Linear approximation for skin temperature */
155 if (adc_val > ADC_VAL0C)
156 temp = 177 - (adc_val/5);
157 else if ((adc_val <= ADC_VAL0C) && (adc_val > ADC_VAL20C))
158 temp = 111 - (adc_val/8);
159 else if ((adc_val <= ADC_VAL20C) && (adc_val > ADC_VAL40C))
160 temp = 92 - (adc_val/10);
161 else if ((adc_val <= ADC_VAL40C) && (adc_val > ADC_VAL60C))
162 temp = 91 - (adc_val/10);
163 else
164 temp = 112 - (adc_val/6);
165
166 /* Convert temperature in celsius to milli degree celsius */
167 *tp = temp * 1000;
168 return 0;
169}
170
171/**
172 * mid_read_temp - read sensors for temperature
173 * @temp: holds the current temperature for the sensor after reading
174 *
175 * reads the adc_code from the channel and converts it to real
176 * temperature. The converted value is stored in temp.
177 *
178 * Can sleep
179 */
180static int mid_read_temp(struct thermal_zone_device *tzd, unsigned long *temp)
181{
182 struct thermal_device_info *td_info = tzd->devdata;
183 uint16_t adc_val, addr;
184 uint8_t data = 0;
185 int ret;
186 unsigned long curr_temp;
187
188
189 addr = td_info->chnl_addr;
190
191 /* Enable the msic for conversion before reading */
192 ret = intel_scu_ipc_iowrite8(MSIC_THERM_ADC1CNTL3, MSIC_ADCRRDATA_ENBL);
193 if (ret)
194 return ret;
195
196 /* Re-toggle the RRDATARD bit (temporary workaround) */
197 ret = intel_scu_ipc_iowrite8(MSIC_THERM_ADC1CNTL3, MSIC_ADCTHERM_ENBL);
198 if (ret)
199 return ret;
200
201 /* Read the higher bits of data */
202 ret = intel_scu_ipc_ioread8(addr, &data);
203 if (ret)
204 return ret;
205
206 /* Shift bits to accommodate the lower two data bits */
207 adc_val = (data << 2);
208 addr++;
209
210 ret = intel_scu_ipc_ioread8(addr, &data);/* Read lower bits */
211 if (ret)
212 return ret;
213
214 /* Adding lower two bits to the higher bits */
215 data &= 03;
216 adc_val += data;
217
218 /* Convert ADC value to temperature */
219 ret = adc_to_temp(td_info->direct, adc_val, &curr_temp);
220 if (ret == 0)
221 *temp = td_info->curr_temp = curr_temp;
222 return ret;
223}
224
225/**
226 * configure_adc - enables/disables the ADC for conversion
227 * @val: zero: disables the ADC non-zero:enables the ADC
228 *
229 * Enable/Disable the ADC depending on the argument
230 *
231 * Can sleep
232 */
233static int configure_adc(int val)
234{
235 int ret;
236 uint8_t data;
237
238 ret = intel_scu_ipc_ioread8(MSIC_THERM_ADC1CNTL1, &data);
239 if (ret)
240 return ret;
241
242 if (val) {
243 /* Enable and start the ADC */
244 data |= (MSIC_ADC_ENBL | MSIC_ADC_START);
245 } else {
246 /* Just stop the ADC */
247 data &= (~MSIC_ADC_START);
248 }
249 return intel_scu_ipc_iowrite8(MSIC_THERM_ADC1CNTL1, data);
250}
251
252/**
253 * set_up_therm_channel - enable thermal channel for conversion
254 * @base_addr: index of free msic ADC channel
255 *
256 * Enable all the three channels for conversion
257 *
258 * Can sleep
259 */
260static int set_up_therm_channel(u16 base_addr)
261{
262 int ret;
263
264 /* Enable all the sensor channels */
265 ret = intel_scu_ipc_iowrite8(base_addr, SKIN_SENSOR0_CODE);
266 if (ret)
267 return ret;
268
269 ret = intel_scu_ipc_iowrite8(base_addr + 1, SKIN_SENSOR1_CODE);
270 if (ret)
271 return ret;
272
273 ret = intel_scu_ipc_iowrite8(base_addr + 2, SYS_SENSOR_CODE);
274 if (ret)
275 return ret;
276
277 /* Since this is the last channel, set the stop bit
278 * to 1 by ORing the DIE_SENSOR_CODE with 0x10 */
279 ret = intel_scu_ipc_iowrite8(base_addr + 3,
280 (MSIC_DIE_SENSOR_CODE | 0x10));
281 if (ret)
282 return ret;
283
284 /* Enable ADC and start it */
285 return configure_adc(1);
286}
287
288/**
289 * reset_stopbit - sets the stop bit to 0 on the given channel
290 * @addr: address of the channel
291 *
292 * Can sleep
293 */
294static int reset_stopbit(uint16_t addr)
295{
296 int ret;
297 uint8_t data;
298 ret = intel_scu_ipc_ioread8(addr, &data);
299 if (ret)
300 return ret;
301 /* Set the stop bit to zero */
302 return intel_scu_ipc_iowrite8(addr, (data & 0xEF));
303}
304
305/**
306 * find_free_channel - finds an empty channel for conversion
307 *
308 * If the ADC is not enabled then start using 0th channel
309 * itself. Otherwise find an empty channel by looking for a
310 * channel in which the stopbit is set to 1. returns the index
311 * of the first free channel if succeeds or an error code.
312 *
313 * Context: can sleep
314 *
315 * FIXME: Ultimately the channel allocator will move into the intel_scu_ipc
316 * code.
317 */
318static int find_free_channel(void)
319{
320 int ret;
321 int i;
322 uint8_t data;
323
324 /* check whether ADC is enabled */
325 ret = intel_scu_ipc_ioread8(MSIC_THERM_ADC1CNTL1, &data);
326 if (ret)
327 return ret;
328
329 if ((data & MSIC_ADC_ENBL) == 0)
330 return 0;
331
332 /* ADC is already enabled; Looking for an empty channel */
333 for (i = 0; i < ADC_CHANLS_MAX; i++) {
334 ret = intel_scu_ipc_ioread8(ADC_CHNL_START_ADDR + i, &data);
335 if (ret)
336 return ret;
337
338 if (data & MSIC_STOPBIT_MASK) {
339 ret = i;
340 break;
341 }
342 }
343 return (ret > ADC_LOOP_MAX) ? (-EINVAL) : ret;
344}
345
346/**
347 * mid_initialize_adc - initializing the ADC
348 * @dev: our device structure
349 *
350 * Initialize the ADC for reading thermistor values. Can sleep.
351 */
352static int mid_initialize_adc(struct device *dev)
353{
354 u8 data;
355 u16 base_addr;
356 int ret;
357
358 /*
359 * Ensure that adctherm is disabled before we
360 * initialize the ADC
361 */
362 ret = intel_scu_ipc_ioread8(MSIC_THERM_ADC1CNTL3, &data);
363 if (ret)
364 return ret;
365
366 if (data & MSIC_ADCTHERM_MASK)
367 dev_warn(dev, "ADCTHERM already set");
368
369 /* Index of the first channel in which the stop bit is set */
370 channel_index = find_free_channel();
371 if (channel_index < 0) {
372 dev_err(dev, "No free ADC channels");
373 return channel_index;
374 }
375
376 base_addr = ADC_CHNL_START_ADDR + channel_index;
377
378 if (!(channel_index == 0 || channel_index == ADC_LOOP_MAX)) {
379 /* Reset stop bit for channels other than 0 and 12 */
380 ret = reset_stopbit(base_addr);
381 if (ret)
382 return ret;
383
384 /* Index of the first free channel */
385 base_addr++;
386 channel_index++;
387 }
388
389 ret = set_up_therm_channel(base_addr);
390 if (ret) {
391 dev_err(dev, "unable to enable ADC");
392 return ret;
393 }
394 dev_dbg(dev, "ADC initialization successful");
395 return ret;
396}
397
398/**
399 * initialize_sensor - sets default temp and timer ranges
400 * @index: index of the sensor
401 *
402 * Context: can sleep
403 */
404static struct thermal_device_info *initialize_sensor(int index)
405{
406 struct thermal_device_info *td_info =
407 kzalloc(sizeof(struct thermal_device_info), GFP_KERNEL);
408
409 if (!td_info)
410 return NULL;
411
412 /* Set the base addr of the channel for this sensor */
413 td_info->chnl_addr = ADC_DATA_START_ADDR + 2 * (channel_index + index);
414 /* Sensor 3 is direct conversion */
415 if (index == 3)
416 td_info->direct = 1;
417 return td_info;
418}
419
420/**
421 * mid_thermal_resume - resume routine
422 * @pdev: platform device structure
423 *
424 * mid thermal resume: re-initializes the adc. Can sleep.
425 */
426static int mid_thermal_resume(struct platform_device *pdev)
427{
428 return mid_initialize_adc(&pdev->dev);
429}
430
431/**
432 * mid_thermal_suspend - suspend routine
433 * @pdev: platform device structure
434 *
435 * mid thermal suspend implements the suspend functionality
436 * by stopping the ADC. Can sleep.
437 */
438static int mid_thermal_suspend(struct platform_device *pdev, pm_message_t mesg)
439{
440 /*
441 * This just stops the ADC and does not disable it.
442 * temporary workaround until we have a generic ADC driver.
443 * If 0 is passed, it disables the ADC.
444 */
445 return configure_adc(0);
446}
447
448/**
449 * read_curr_temp - reads the current temperature and stores in temp
450 * @temp: holds the current temperature value after reading
451 *
452 * Can sleep
453 */
454static int read_curr_temp(struct thermal_zone_device *tzd, unsigned long *temp)
455{
456 WARN_ON(tzd == NULL);
457 return mid_read_temp(tzd, temp);
458}
459
460/* Can't be const */
461static struct thermal_zone_device_ops tzd_ops = {
462 .get_temp = read_curr_temp,
463};
464
465/**
466 * mid_thermal_probe - mfld thermal initialize
467 * @pdev: platform device structure
468 *
469 * mid thermal probe initializes the hardware and registers
470 * all the sensors with the generic thermal framework. Can sleep.
471 */
472static int mid_thermal_probe(struct platform_device *pdev)
473{
474 static char *name[MSIC_THERMAL_SENSORS] = {
475 "skin0", "skin1", "sys", "msicdie"
476 };
477
478 int ret;
479 int i;
480 struct platform_info *pinfo;
481
482 pinfo = kzalloc(sizeof(struct platform_info), GFP_KERNEL);
483 if (!pinfo)
484 return -ENOMEM;
485
486 /* Initializing the hardware */
487 ret = mid_initialize_adc(&pdev->dev);
488 if (ret) {
489 dev_err(&pdev->dev, "ADC init failed");
490 kfree(pinfo);
491 return ret;
492 }
493
494 /* Register each sensor with the generic thermal framework*/
495 for (i = 0; i < MSIC_THERMAL_SENSORS; i++) {
496 pinfo->tzd[i] = thermal_zone_device_register(name[i],
497 0, initialize_sensor(i), &tzd_ops, 0, 0, 0, 0);
498 if (IS_ERR(pinfo->tzd[i]))
499 goto reg_fail;
500 }
501
502 pinfo->pdev = pdev;
503 platform_set_drvdata(pdev, pinfo);
504 return 0;
505
506reg_fail:
507 ret = PTR_ERR(pinfo->tzd[i]);
508 while (--i >= 0)
509 thermal_zone_device_unregister(pinfo->tzd[i]);
510 configure_adc(0);
511 kfree(pinfo);
512 return ret;
513}
514
515/**
516 * mid_thermal_remove - mfld thermal finalize
517 * @dev: platform device structure
518 *
519 * MLFD thermal remove unregisters all the sensors from the generic
520 * thermal framework. Can sleep.
521 */
522static int mid_thermal_remove(struct platform_device *pdev)
523{
524 int i;
525 struct platform_info *pinfo = platform_get_drvdata(pdev);
526
527 for (i = 0; i < MSIC_THERMAL_SENSORS; i++)
528 thermal_zone_device_unregister(pinfo->tzd[i]);
529
530 kfree(pinfo);
531 platform_set_drvdata(pdev, NULL);
532
533 /* Stop the ADC */
534 return configure_adc(0);
535}
536
537#define DRIVER_NAME "msic_sensor"
538
539static const struct platform_device_id therm_id_table[] = {
540 { DRIVER_NAME, 1 },
541 { }
542};
543
544static struct platform_driver mid_thermal_driver = {
545 .driver = {
546 .name = DRIVER_NAME,
547 .owner = THIS_MODULE,
548 },
549 .probe = mid_thermal_probe,
550 .suspend = mid_thermal_suspend,
551 .resume = mid_thermal_resume,
552 .remove = __devexit_p(mid_thermal_remove),
553 .id_table = therm_id_table,
554};
555
556static int __init mid_thermal_module_init(void)
557{
558 return platform_driver_register(&mid_thermal_driver);
559}
560
561static void __exit mid_thermal_module_exit(void)
562{
563 platform_driver_unregister(&mid_thermal_driver);
564}
565
566module_init(mid_thermal_module_init);
567module_exit(mid_thermal_module_exit);
568
569MODULE_AUTHOR("Durgadoss R <durgadoss.r@intel.com>");
570MODULE_DESCRIPTION("Intel Medfield Platform Thermal Driver");
571MODULE_LICENSE("GPL");
diff --git a/drivers/platform/x86/intel_oaktrail.c b/drivers/platform/x86/intel_oaktrail.c
new file mode 100644
index 000000000000..7f88c7923fc6
--- /dev/null
+++ b/drivers/platform/x86/intel_oaktrail.c
@@ -0,0 +1,397 @@
1/*
2 * intel_oaktrail.c - Intel OakTrail Platform support.
3 *
4 * Copyright (C) 2010-2011 Intel Corporation
5 * Author: Yin Kangkai (kangkai.yin@intel.com)
6 *
7 * based on Compal driver, Copyright (C) 2008 Cezary Jackiewicz
8 * <cezary.jackiewicz (at) gmail.com>, based on MSI driver
9 * Copyright (C) 2006 Lennart Poettering <mzxreary (at) 0pointer (dot) de>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24 * 02110-1301, USA.
25 *
26 * This driver does below things:
27 * 1. registers itself in the Linux backlight control in
28 * /sys/class/backlight/intel_oaktrail/
29 *
30 * 2. registers in the rfkill subsystem here: /sys/class/rfkill/rfkillX/
31 * for these components: wifi, bluetooth, wwan (3g), gps
32 *
33 * This driver might work on other products based on Oaktrail. If you
34 * want to try it you can pass force=1 as argument to the module which
35 * will force it to load even when the DMI data doesn't identify the
36 * product as compatible.
37 */
38
39#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
40
41#include <linux/module.h>
42#include <linux/kernel.h>
43#include <linux/init.h>
44#include <linux/acpi.h>
45#include <linux/fb.h>
46#include <linux/mutex.h>
47#include <linux/err.h>
48#include <linux/i2c.h>
49#include <linux/backlight.h>
50#include <linux/platform_device.h>
51#include <linux/dmi.h>
52#include <linux/rfkill.h>
53#include <acpi/acpi_bus.h>
54#include <acpi/acpi_drivers.h>
55
56
57#define DRIVER_NAME "intel_oaktrail"
58#define DRIVER_VERSION "0.4ac1"
59
60/*
61 * This is the devices status address in EC space, and the control bits
62 * definition:
63 *
64 * (1 << 0): Camera enable/disable, RW.
65 * (1 << 1): Bluetooth enable/disable, RW.
66 * (1 << 2): GPS enable/disable, RW.
67 * (1 << 3): WiFi enable/disable, RW.
68 * (1 << 4): WWAN (3G) enable/disalbe, RW.
69 * (1 << 5): Touchscreen enable/disable, Read Only.
70 */
71#define OT_EC_DEVICE_STATE_ADDRESS 0xD6
72
73#define OT_EC_CAMERA_MASK (1 << 0)
74#define OT_EC_BT_MASK (1 << 1)
75#define OT_EC_GPS_MASK (1 << 2)
76#define OT_EC_WIFI_MASK (1 << 3)
77#define OT_EC_WWAN_MASK (1 << 4)
78#define OT_EC_TS_MASK (1 << 5)
79
80/*
81 * This is the address in EC space and commands used to control LCD backlight:
82 *
83 * Two steps needed to change the LCD backlight:
84 * 1. write the backlight percentage into OT_EC_BL_BRIGHTNESS_ADDRESS;
85 * 2. write OT_EC_BL_CONTROL_ON_DATA into OT_EC_BL_CONTROL_ADDRESS.
86 *
87 * To read the LCD back light, just read out the value from
88 * OT_EC_BL_BRIGHTNESS_ADDRESS.
89 *
90 * LCD backlight brightness range: 0 - 100 (OT_EC_BL_BRIGHTNESS_MAX)
91 */
92#define OT_EC_BL_BRIGHTNESS_ADDRESS 0x44
93#define OT_EC_BL_BRIGHTNESS_MAX 100
94#define OT_EC_BL_CONTROL_ADDRESS 0x3A
95#define OT_EC_BL_CONTROL_ON_DATA 0x1A
96
97
98static int force;
99module_param(force, bool, 0);
100MODULE_PARM_DESC(force, "Force driver load, ignore DMI data");
101
102static struct platform_device *oaktrail_device;
103static struct backlight_device *oaktrail_bl_device;
104static struct rfkill *bt_rfkill;
105static struct rfkill *gps_rfkill;
106static struct rfkill *wifi_rfkill;
107static struct rfkill *wwan_rfkill;
108
109
110/* rfkill */
111static int oaktrail_rfkill_set(void *data, bool blocked)
112{
113 u8 value;
114 u8 result;
115 unsigned long radio = (unsigned long) data;
116
117 ec_read(OT_EC_DEVICE_STATE_ADDRESS, &result);
118
119 if (!blocked)
120 value = (u8) (result | radio);
121 else
122 value = (u8) (result & ~radio);
123
124 ec_write(OT_EC_DEVICE_STATE_ADDRESS, value);
125
126 return 0;
127}
128
129static const struct rfkill_ops oaktrail_rfkill_ops = {
130 .set_block = oaktrail_rfkill_set,
131};
132
133static struct rfkill *oaktrail_rfkill_new(char *name, enum rfkill_type type,
134 unsigned long mask)
135{
136 struct rfkill *rfkill_dev;
137 u8 value;
138 int err;
139
140 rfkill_dev = rfkill_alloc(name, &oaktrail_device->dev, type,
141 &oaktrail_rfkill_ops, (void *)mask);
142 if (!rfkill_dev)
143 return ERR_PTR(-ENOMEM);
144
145 ec_read(OT_EC_DEVICE_STATE_ADDRESS, &value);
146 rfkill_init_sw_state(rfkill_dev, (value & mask) != 1);
147
148 err = rfkill_register(rfkill_dev);
149 if (err) {
150 rfkill_destroy(rfkill_dev);
151 return ERR_PTR(err);
152 }
153
154 return rfkill_dev;
155}
156
157static inline void __oaktrail_rfkill_cleanup(struct rfkill *rf)
158{
159 if (rf) {
160 rfkill_unregister(rf);
161 rfkill_destroy(rf);
162 }
163}
164
165static void oaktrail_rfkill_cleanup(void)
166{
167 __oaktrail_rfkill_cleanup(wifi_rfkill);
168 __oaktrail_rfkill_cleanup(bt_rfkill);
169 __oaktrail_rfkill_cleanup(gps_rfkill);
170 __oaktrail_rfkill_cleanup(wwan_rfkill);
171}
172
173static int oaktrail_rfkill_init(void)
174{
175 int ret;
176
177 wifi_rfkill = oaktrail_rfkill_new("oaktrail-wifi",
178 RFKILL_TYPE_WLAN,
179 OT_EC_WIFI_MASK);
180 if (IS_ERR(wifi_rfkill)) {
181 ret = PTR_ERR(wifi_rfkill);
182 wifi_rfkill = NULL;
183 goto cleanup;
184 }
185
186 bt_rfkill = oaktrail_rfkill_new("oaktrail-bluetooth",
187 RFKILL_TYPE_BLUETOOTH,
188 OT_EC_BT_MASK);
189 if (IS_ERR(bt_rfkill)) {
190 ret = PTR_ERR(bt_rfkill);
191 bt_rfkill = NULL;
192 goto cleanup;
193 }
194
195 gps_rfkill = oaktrail_rfkill_new("oaktrail-gps",
196 RFKILL_TYPE_GPS,
197 OT_EC_GPS_MASK);
198 if (IS_ERR(gps_rfkill)) {
199 ret = PTR_ERR(gps_rfkill);
200 gps_rfkill = NULL;
201 goto cleanup;
202 }
203
204 wwan_rfkill = oaktrail_rfkill_new("oaktrail-wwan",
205 RFKILL_TYPE_WWAN,
206 OT_EC_WWAN_MASK);
207 if (IS_ERR(wwan_rfkill)) {
208 ret = PTR_ERR(wwan_rfkill);
209 wwan_rfkill = NULL;
210 goto cleanup;
211 }
212
213 return 0;
214
215cleanup:
216 oaktrail_rfkill_cleanup();
217 return ret;
218}
219
220
221/* backlight */
222static int get_backlight_brightness(struct backlight_device *b)
223{
224 u8 value;
225 ec_read(OT_EC_BL_BRIGHTNESS_ADDRESS, &value);
226
227 return value;
228}
229
230static int set_backlight_brightness(struct backlight_device *b)
231{
232 u8 percent = (u8) b->props.brightness;
233 if (percent < 0 || percent > OT_EC_BL_BRIGHTNESS_MAX)
234 return -EINVAL;
235
236 ec_write(OT_EC_BL_BRIGHTNESS_ADDRESS, percent);
237 ec_write(OT_EC_BL_CONTROL_ADDRESS, OT_EC_BL_CONTROL_ON_DATA);
238
239 return 0;
240}
241
242static const struct backlight_ops oaktrail_bl_ops = {
243 .get_brightness = get_backlight_brightness,
244 .update_status = set_backlight_brightness,
245};
246
247static int oaktrail_backlight_init(void)
248{
249 struct backlight_device *bd;
250 struct backlight_properties props;
251
252 memset(&props, 0, sizeof(struct backlight_properties));
253 props.type = BACKLIGHT_PLATFORM;
254 props.max_brightness = OT_EC_BL_BRIGHTNESS_MAX;
255 bd = backlight_device_register(DRIVER_NAME,
256 &oaktrail_device->dev, NULL,
257 &oaktrail_bl_ops,
258 &props);
259
260 if (IS_ERR(bd)) {
261 oaktrail_bl_device = NULL;
262 pr_warning("Unable to register backlight device\n");
263 return PTR_ERR(bd);
264 }
265
266 oaktrail_bl_device = bd;
267
268 bd->props.brightness = get_backlight_brightness(bd);
269 bd->props.power = FB_BLANK_UNBLANK;
270 backlight_update_status(bd);
271
272 return 0;
273}
274
275static void oaktrail_backlight_exit(void)
276{
277 if (oaktrail_bl_device)
278 backlight_device_unregister(oaktrail_bl_device);
279}
280
281static int __devinit oaktrail_probe(struct platform_device *pdev)
282{
283 return 0;
284}
285
286static int __devexit oaktrail_remove(struct platform_device *pdev)
287{
288 return 0;
289}
290
291static struct platform_driver oaktrail_driver = {
292 .driver = {
293 .name = DRIVER_NAME,
294 .owner = THIS_MODULE,
295 },
296 .probe = oaktrail_probe,
297 .remove = __devexit_p(oaktrail_remove)
298};
299
300static int dmi_check_cb(const struct dmi_system_id *id)
301{
302 pr_info("Identified model '%s'\n", id->ident);
303 return 0;
304}
305
306static struct dmi_system_id __initdata oaktrail_dmi_table[] = {
307 {
308 .ident = "OakTrail platform",
309 .matches = {
310 DMI_MATCH(DMI_PRODUCT_NAME, "OakTrail platform"),
311 },
312 .callback = dmi_check_cb
313 },
314 { }
315};
316
317static int __init oaktrail_init(void)
318{
319 int ret;
320
321 if (acpi_disabled) {
322 pr_err("ACPI needs to be enabled for this driver to work!\n");
323 return -ENODEV;
324 }
325
326 if (!force && !dmi_check_system(oaktrail_dmi_table)) {
327 pr_err("Platform not recognized (You could try the module's force-parameter)");
328 return -ENODEV;
329 }
330
331 ret = platform_driver_register(&oaktrail_driver);
332 if (ret) {
333 pr_warning("Unable to register platform driver\n");
334 goto err_driver_reg;
335 }
336
337 oaktrail_device = platform_device_alloc(DRIVER_NAME, -1);
338 if (!oaktrail_device) {
339 pr_warning("Unable to allocate platform device\n");
340 ret = -ENOMEM;
341 goto err_device_alloc;
342 }
343
344 ret = platform_device_add(oaktrail_device);
345 if (ret) {
346 pr_warning("Unable to add platform device\n");
347 goto err_device_add;
348 }
349
350 if (!acpi_video_backlight_support()) {
351 ret = oaktrail_backlight_init();
352 if (ret)
353 goto err_backlight;
354
355 } else
356 pr_info("Backlight controlled by ACPI video driver\n");
357
358 ret = oaktrail_rfkill_init();
359 if (ret) {
360 pr_warning("Setup rfkill failed\n");
361 goto err_rfkill;
362 }
363
364 pr_info("Driver "DRIVER_VERSION" successfully loaded\n");
365 return 0;
366
367err_rfkill:
368 oaktrail_backlight_exit();
369err_backlight:
370 platform_device_del(oaktrail_device);
371err_device_add:
372 platform_device_put(oaktrail_device);
373err_device_alloc:
374 platform_driver_unregister(&oaktrail_driver);
375err_driver_reg:
376
377 return ret;
378}
379
380static void __exit oaktrail_cleanup(void)
381{
382 oaktrail_backlight_exit();
383 oaktrail_rfkill_cleanup();
384 platform_device_unregister(oaktrail_device);
385 platform_driver_unregister(&oaktrail_driver);
386
387 pr_info("Driver unloaded\n");
388}
389
390module_init(oaktrail_init);
391module_exit(oaktrail_cleanup);
392
393MODULE_AUTHOR("Yin Kangkai (kangkai.yin@intel.com)");
394MODULE_DESCRIPTION("Intel Oaktrail Platform ACPI Extras");
395MODULE_VERSION(DRIVER_VERSION);
396MODULE_LICENSE("GPL");
397MODULE_ALIAS("dmi:*:svnIntelCorporation:pnOakTrailplatform:*");
diff --git a/drivers/platform/x86/intel_pmic_gpio.c b/drivers/platform/x86/intel_pmic_gpio.c
index 5cdcff653918..1686c1e07d5d 100644
--- a/drivers/platform/x86/intel_pmic_gpio.c
+++ b/drivers/platform/x86/intel_pmic_gpio.c
@@ -19,6 +19,8 @@
19 * Moorestown platform PMIC chip 19 * Moorestown platform PMIC chip
20 */ 20 */
21 21
22#define pr_fmt(fmt) "%s: " fmt, __func__
23
22#include <linux/module.h> 24#include <linux/module.h>
23#include <linux/kernel.h> 25#include <linux/kernel.h>
24#include <linux/interrupt.h> 26#include <linux/interrupt.h>
@@ -29,7 +31,6 @@
29#include <linux/init.h> 31#include <linux/init.h>
30#include <linux/io.h> 32#include <linux/io.h>
31#include <linux/gpio.h> 33#include <linux/gpio.h>
32#include <linux/interrupt.h>
33#include <asm/intel_scu_ipc.h> 34#include <asm/intel_scu_ipc.h>
34#include <linux/device.h> 35#include <linux/device.h>
35#include <linux/intel_pmic_gpio.h> 36#include <linux/intel_pmic_gpio.h>
@@ -61,23 +62,18 @@ enum pmic_gpio_register {
61#define GPOSW_DOU 0x08 62#define GPOSW_DOU 0x08
62#define GPOSW_RDRV 0x30 63#define GPOSW_RDRV 0x30
63 64
65#define GPIO_UPDATE_TYPE 0x80000000
64 66
65#define NUM_GPIO 24 67#define NUM_GPIO 24
66 68
67struct pmic_gpio_irq {
68 spinlock_t lock;
69 u32 trigger[NUM_GPIO];
70 u32 dirty;
71 struct work_struct work;
72};
73
74
75struct pmic_gpio { 69struct pmic_gpio {
70 struct mutex buslock;
76 struct gpio_chip chip; 71 struct gpio_chip chip;
77 struct pmic_gpio_irq irqtypes;
78 void *gpiointr; 72 void *gpiointr;
79 int irq; 73 int irq;
80 unsigned irq_base; 74 unsigned irq_base;
75 unsigned int update_type;
76 u32 trigger_type;
81}; 77};
82 78
83static void pmic_program_irqtype(int gpio, int type) 79static void pmic_program_irqtype(int gpio, int type)
@@ -93,42 +89,10 @@ static void pmic_program_irqtype(int gpio, int type)
93 intel_scu_ipc_update_register(GPIO0 + gpio, 0x00, 0x10); 89 intel_scu_ipc_update_register(GPIO0 + gpio, 0x00, 0x10);
94}; 90};
95 91
96static void pmic_irqtype_work(struct work_struct *work)
97{
98 struct pmic_gpio_irq *t =
99 container_of(work, struct pmic_gpio_irq, work);
100 unsigned long flags;
101 int i;
102 u16 type;
103
104 spin_lock_irqsave(&t->lock, flags);
105 /* As we drop the lock, we may need multiple scans if we race the
106 pmic_irq_type function */
107 while (t->dirty) {
108 /*
109 * For each pin that has the dirty bit set send an IPC
110 * message to configure the hardware via the PMIC
111 */
112 for (i = 0; i < NUM_GPIO; i++) {
113 if (!(t->dirty & (1 << i)))
114 continue;
115 t->dirty &= ~(1 << i);
116 /* We can't trust the array entry or dirty
117 once the lock is dropped */
118 type = t->trigger[i];
119 spin_unlock_irqrestore(&t->lock, flags);
120 pmic_program_irqtype(i, type);
121 spin_lock_irqsave(&t->lock, flags);
122 }
123 }
124 spin_unlock_irqrestore(&t->lock, flags);
125}
126
127static int pmic_gpio_direction_input(struct gpio_chip *chip, unsigned offset) 92static int pmic_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
128{ 93{
129 if (offset > 8) { 94 if (offset > 8) {
130 printk(KERN_ERR 95 pr_err("only pin 0-7 support input\n");
131 "%s: only pin 0-7 support input\n", __func__);
132 return -1;/* we only have 8 GPIO can use as input */ 96 return -1;/* we only have 8 GPIO can use as input */
133 } 97 }
134 return intel_scu_ipc_update_register(GPIO0 + offset, 98 return intel_scu_ipc_update_register(GPIO0 + offset,
@@ -142,19 +106,18 @@ static int pmic_gpio_direction_output(struct gpio_chip *chip,
142 106
143 if (offset < 8)/* it is GPIO */ 107 if (offset < 8)/* it is GPIO */
144 rc = intel_scu_ipc_update_register(GPIO0 + offset, 108 rc = intel_scu_ipc_update_register(GPIO0 + offset,
145 GPIO_DRV | GPIO_DOU | GPIO_DIR, 109 GPIO_DRV | (value ? GPIO_DOU : 0),
146 GPIO_DRV | (value ? GPIO_DOU : 0)); 110 GPIO_DRV | GPIO_DOU | GPIO_DIR);
147 else if (offset < 16)/* it is GPOSW */ 111 else if (offset < 16)/* it is GPOSW */
148 rc = intel_scu_ipc_update_register(GPOSWCTL0 + offset - 8, 112 rc = intel_scu_ipc_update_register(GPOSWCTL0 + offset - 8,
149 GPOSW_DRV | GPOSW_DOU | GPOSW_RDRV, 113 GPOSW_DRV | (value ? GPOSW_DOU : 0),
150 GPOSW_DRV | (value ? GPOSW_DOU : 0)); 114 GPOSW_DRV | GPOSW_DOU | GPOSW_RDRV);
151 else if (offset > 15 && offset < 24)/* it is GPO */ 115 else if (offset > 15 && offset < 24)/* it is GPO */
152 rc = intel_scu_ipc_update_register(GPO, 116 rc = intel_scu_ipc_update_register(GPO,
153 1 << (offset - 16), 117 value ? 1 << (offset - 16) : 0,
154 value ? 1 << (offset - 16) : 0); 118 1 << (offset - 16));
155 else { 119 else {
156 printk(KERN_ERR 120 pr_err("invalid PMIC GPIO pin %d!\n", offset);
157 "%s: invalid PMIC GPIO pin %d!\n", __func__, offset);
158 WARN_ON(1); 121 WARN_ON(1);
159 } 122 }
160 123
@@ -179,37 +142,36 @@ static void pmic_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
179{ 142{
180 if (offset < 8)/* it is GPIO */ 143 if (offset < 8)/* it is GPIO */
181 intel_scu_ipc_update_register(GPIO0 + offset, 144 intel_scu_ipc_update_register(GPIO0 + offset,
182 GPIO_DRV | GPIO_DOU, 145 GPIO_DRV | (value ? GPIO_DOU : 0),
183 GPIO_DRV | (value ? GPIO_DOU : 0)); 146 GPIO_DRV | GPIO_DOU);
184 else if (offset < 16)/* it is GPOSW */ 147 else if (offset < 16)/* it is GPOSW */
185 intel_scu_ipc_update_register(GPOSWCTL0 + offset - 8, 148 intel_scu_ipc_update_register(GPOSWCTL0 + offset - 8,
186 GPOSW_DRV | GPOSW_DOU | GPOSW_RDRV, 149 GPOSW_DRV | (value ? GPOSW_DOU : 0),
187 GPOSW_DRV | (value ? GPOSW_DOU : 0)); 150 GPOSW_DRV | GPOSW_DOU | GPOSW_RDRV);
188 else if (offset > 15 && offset < 24) /* it is GPO */ 151 else if (offset > 15 && offset < 24) /* it is GPO */
189 intel_scu_ipc_update_register(GPO, 152 intel_scu_ipc_update_register(GPO,
190 1 << (offset - 16), 153 value ? 1 << (offset - 16) : 0,
191 value ? 1 << (offset - 16) : 0); 154 1 << (offset - 16));
192} 155}
193 156
194static int pmic_irq_type(unsigned irq, unsigned type) 157/*
158 * This is called from genirq with pg->buslock locked and
159 * irq_desc->lock held. We can not access the scu bus here, so we
160 * store the change and update in the bus_sync_unlock() function below
161 */
162static int pmic_irq_type(struct irq_data *data, unsigned type)
195{ 163{
196 struct pmic_gpio *pg = get_irq_chip_data(irq); 164 struct pmic_gpio *pg = irq_data_get_irq_chip_data(data);
197 u32 gpio = irq - pg->irq_base; 165 u32 gpio = data->irq - pg->irq_base;
198 unsigned long flags;
199 166
200 if (gpio > pg->chip.ngpio) 167 if (gpio >= pg->chip.ngpio)
201 return -EINVAL; 168 return -EINVAL;
202 169
203 spin_lock_irqsave(&pg->irqtypes.lock, flags); 170 pg->trigger_type = type;
204 pg->irqtypes.trigger[gpio] = type; 171 pg->update_type = gpio | GPIO_UPDATE_TYPE;
205 pg->irqtypes.dirty |= (1 << gpio);
206 spin_unlock_irqrestore(&pg->irqtypes.lock, flags);
207 schedule_work(&pg->irqtypes.work);
208 return 0; 172 return 0;
209} 173}
210 174
211
212
213static int pmic_gpio_to_irq(struct gpio_chip *chip, unsigned offset) 175static int pmic_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
214{ 176{
215 struct pmic_gpio *pg = container_of(chip, struct pmic_gpio, chip); 177 struct pmic_gpio *pg = container_of(chip, struct pmic_gpio, chip);
@@ -217,35 +179,55 @@ static int pmic_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
217 return pg->irq_base + offset; 179 return pg->irq_base + offset;
218} 180}
219 181
220/* the gpiointr register is read-clear, so just do nothing. */ 182static void pmic_bus_lock(struct irq_data *data)
221static void pmic_irq_unmask(unsigned irq)
222{ 183{
223}; 184 struct pmic_gpio *pg = irq_data_get_irq_chip_data(data);
224 185
225static void pmic_irq_mask(unsigned irq) 186 mutex_lock(&pg->buslock);
187}
188
189static void pmic_bus_sync_unlock(struct irq_data *data)
226{ 190{
227}; 191 struct pmic_gpio *pg = irq_data_get_irq_chip_data(data);
192
193 if (pg->update_type) {
194 unsigned int gpio = pg->update_type & ~GPIO_UPDATE_TYPE;
195
196 pmic_program_irqtype(gpio, pg->trigger_type);
197 pg->update_type = 0;
198 }
199 mutex_unlock(&pg->buslock);
200}
201
202/* the gpiointr register is read-clear, so just do nothing. */
203static void pmic_irq_unmask(struct irq_data *data) { }
204
205static void pmic_irq_mask(struct irq_data *data) { }
228 206
229static struct irq_chip pmic_irqchip = { 207static struct irq_chip pmic_irqchip = {
230 .name = "PMIC-GPIO", 208 .name = "PMIC-GPIO",
231 .mask = pmic_irq_mask, 209 .irq_mask = pmic_irq_mask,
232 .unmask = pmic_irq_unmask, 210 .irq_unmask = pmic_irq_unmask,
233 .set_type = pmic_irq_type, 211 .irq_set_type = pmic_irq_type,
212 .irq_bus_lock = pmic_bus_lock,
213 .irq_bus_sync_unlock = pmic_bus_sync_unlock,
234}; 214};
235 215
236static void pmic_irq_handler(unsigned irq, struct irq_desc *desc) 216static irqreturn_t pmic_irq_handler(int irq, void *data)
237{ 217{
238 struct pmic_gpio *pg = (struct pmic_gpio *)get_irq_data(irq); 218 struct pmic_gpio *pg = data;
239 u8 intsts = *((u8 *)pg->gpiointr + 4); 219 u8 intsts = *((u8 *)pg->gpiointr + 4);
240 int gpio; 220 int gpio;
221 irqreturn_t ret = IRQ_NONE;
241 222
242 for (gpio = 0; gpio < 8; gpio++) { 223 for (gpio = 0; gpio < 8; gpio++) {
243 if (intsts & (1 << gpio)) { 224 if (intsts & (1 << gpio)) {
244 pr_debug("pmic pin %d triggered\n", gpio); 225 pr_debug("pmic pin %d triggered\n", gpio);
245 generic_handle_irq(pg->irq_base + gpio); 226 generic_handle_irq(pg->irq_base + gpio);
227 ret = IRQ_HANDLED;
246 } 228 }
247 } 229 }
248 desc->chip->eoi(irq); 230 return ret;
249} 231}
250 232
251static int __devinit platform_pmic_gpio_probe(struct platform_device *pdev) 233static int __devinit platform_pmic_gpio_probe(struct platform_device *pdev)
@@ -278,7 +260,7 @@ static int __devinit platform_pmic_gpio_probe(struct platform_device *pdev)
278 /* setting up SRAM mapping for GPIOINT register */ 260 /* setting up SRAM mapping for GPIOINT register */
279 pg->gpiointr = ioremap_nocache(pdata->gpiointr, 8); 261 pg->gpiointr = ioremap_nocache(pdata->gpiointr, 8);
280 if (!pg->gpiointr) { 262 if (!pg->gpiointr) {
281 printk(KERN_ERR "%s: Can not map GPIOINT.\n", __func__); 263 pr_err("Can not map GPIOINT\n");
282 retval = -EINVAL; 264 retval = -EINVAL;
283 goto err2; 265 goto err2;
284 } 266 }
@@ -294,21 +276,27 @@ static int __devinit platform_pmic_gpio_probe(struct platform_device *pdev)
294 pg->chip.can_sleep = 1; 276 pg->chip.can_sleep = 1;
295 pg->chip.dev = dev; 277 pg->chip.dev = dev;
296 278
297 INIT_WORK(&pg->irqtypes.work, pmic_irqtype_work); 279 mutex_init(&pg->buslock);
298 spin_lock_init(&pg->irqtypes.lock);
299 280
300 pg->chip.dev = dev; 281 pg->chip.dev = dev;
301 retval = gpiochip_add(&pg->chip); 282 retval = gpiochip_add(&pg->chip);
302 if (retval) { 283 if (retval) {
303 printk(KERN_ERR "%s: Can not add pmic gpio chip.\n", __func__); 284 pr_err("Can not add pmic gpio chip\n");
304 goto err; 285 goto err;
305 } 286 }
306 set_irq_data(pg->irq, pg); 287
307 set_irq_chained_handler(pg->irq, pmic_irq_handler); 288 retval = request_irq(pg->irq, pmic_irq_handler, 0, "pmic", pg);
289 if (retval) {
290 pr_warn("Interrupt request failed\n");
291 goto err;
292 }
293
308 for (i = 0; i < 8; i++) { 294 for (i = 0; i < 8; i++) {
309 set_irq_chip_and_handler_name(i + pg->irq_base, &pmic_irqchip, 295 irq_set_chip_and_handler_name(i + pg->irq_base,
310 handle_simple_irq, "demux"); 296 &pmic_irqchip,
311 set_irq_chip_data(i + pg->irq_base, pg); 297 handle_simple_irq,
298 "demux");
299 irq_set_chip_data(i + pg->irq_base, pg);
312 } 300 }
313 return 0; 301 return 0;
314err: 302err:
diff --git a/drivers/platform/x86/intel_rar_register.c b/drivers/platform/x86/intel_rar_register.c
index 2b11a33325e6..bde47e9080cd 100644
--- a/drivers/platform/x86/intel_rar_register.c
+++ b/drivers/platform/x86/intel_rar_register.c
@@ -485,7 +485,7 @@ EXPORT_SYMBOL(rar_lock);
485 * 485 *
486 * The register_rar function is to used by other device drivers 486 * The register_rar function is to used by other device drivers
487 * to ensure that this driver is ready. As we cannot be sure of 487 * to ensure that this driver is ready. As we cannot be sure of
488 * the compile/execute order of drivers in ther kernel, it is 488 * the compile/execute order of drivers in the kernel, it is
489 * best to give this driver a callback function to call when 489 * best to give this driver a callback function to call when
490 * it is ready to give out addresses. The callback function 490 * it is ready to give out addresses. The callback function
491 * would have those steps that continue the initialization of 491 * would have those steps that continue the initialization of
diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c
index 6abe18e638e9..940accbe28d3 100644
--- a/drivers/platform/x86/intel_scu_ipc.c
+++ b/drivers/platform/x86/intel_scu_ipc.c
@@ -9,7 +9,7 @@
9 * as published by the Free Software Foundation; version 2 9 * as published by the Free Software Foundation; version 2
10 * of the License. 10 * of the License.
11 * 11 *
12 * SCU runing in ARC processor communicates with other entity running in IA 12 * SCU running in ARC processor communicates with other entity running in IA
13 * core through IPC mechanism which in turn messaging between IA core ad SCU. 13 * core through IPC mechanism which in turn messaging between IA core ad SCU.
14 * SCU has two IPC mechanism IPC-1 and IPC-2. IPC-1 is used between IA32 and 14 * SCU has two IPC mechanism IPC-1 and IPC-2. IPC-1 is used between IA32 and
15 * SCU where IPC-2 is used between P-Unit and SCU. This driver delas with 15 * SCU where IPC-2 is used between P-Unit and SCU. This driver delas with
@@ -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
@@ -159,7 +160,7 @@ static int pwr_reg_rdwr(u16 *addr, u8 *data, u32 count, u32 op, u32 id)
159{ 160{
160 int i, nc, bytes, d; 161 int i, nc, bytes, d;
161 u32 offset = 0; 162 u32 offset = 0;
162 u32 err = 0; 163 int err;
163 u8 cbuf[IPC_WWBUF_SIZE] = { }; 164 u8 cbuf[IPC_WWBUF_SIZE] = { };
164 u32 *wbuf = (u32 *)&cbuf; 165 u32 *wbuf = (u32 *)&cbuf;
165 166
@@ -402,7 +403,7 @@ EXPORT_SYMBOL(intel_scu_ipc_update_register);
402 */ 403 */
403int intel_scu_ipc_simple_command(int cmd, int sub) 404int intel_scu_ipc_simple_command(int cmd, int sub)
404{ 405{
405 u32 err = 0; 406 int err;
406 407
407 mutex_lock(&ipclock); 408 mutex_lock(&ipclock);
408 if (ipcdev.pdev == NULL) { 409 if (ipcdev.pdev == NULL) {
@@ -432,8 +433,7 @@ EXPORT_SYMBOL(intel_scu_ipc_simple_command);
432int intel_scu_ipc_command(int cmd, int sub, u32 *in, int inlen, 433int intel_scu_ipc_command(int cmd, int sub, u32 *in, int inlen,
433 u32 *out, int outlen) 434 u32 *out, int outlen)
434{ 435{
435 u32 err = 0; 436 int i, err;
436 int i = 0;
437 437
438 mutex_lock(&ipclock); 438 mutex_lock(&ipclock);
439 if (ipcdev.pdev == NULL) { 439 if (ipcdev.pdev == NULL) {
@@ -495,7 +495,7 @@ int intel_scu_ipc_i2c_cntrl(u32 addr, u32 *data)
495 "intel_scu_ipc: I2C INVALID_CMD = 0x%x\n", cmd); 495 "intel_scu_ipc: I2C INVALID_CMD = 0x%x\n", cmd);
496 496
497 mutex_unlock(&ipclock); 497 mutex_unlock(&ipclock);
498 return -1; 498 return -EIO;
499 } 499 }
500 mutex_unlock(&ipclock); 500 mutex_unlock(&ipclock);
501 return 0; 501 return 0;
@@ -640,7 +640,7 @@ update_end:
640 640
641 if (status == IPC_FW_UPDATE_SUCCESS) 641 if (status == IPC_FW_UPDATE_SUCCESS)
642 return 0; 642 return 0;
643 return -1; 643 return -EIO;
644} 644}
645EXPORT_SYMBOL(intel_scu_ipc_fw_update); 645EXPORT_SYMBOL(intel_scu_ipc_fw_update);
646 646
@@ -698,6 +698,9 @@ static int ipc_probe(struct pci_dev *dev, const struct pci_device_id *id)
698 iounmap(ipcdev.ipc_base); 698 iounmap(ipcdev.ipc_base);
699 return -ENOMEM; 699 return -ENOMEM;
700 } 700 }
701
702 intel_scu_devices_create();
703
701 return 0; 704 return 0;
702} 705}
703 706
@@ -719,6 +722,7 @@ static void ipc_remove(struct pci_dev *pdev)
719 iounmap(ipcdev.ipc_base); 722 iounmap(ipcdev.ipc_base);
720 iounmap(ipcdev.i2c_base); 723 iounmap(ipcdev.i2c_base);
721 ipcdev.pdev = NULL; 724 ipcdev.pdev = NULL;
725 intel_scu_devices_destroy();
722} 726}
723 727
724static const struct pci_device_id pci_ids[] = { 728static const struct pci_device_id pci_ids[] = {
diff --git a/drivers/platform/x86/intel_scu_ipcutil.c b/drivers/platform/x86/intel_scu_ipcutil.c
new file mode 100644
index 000000000000..b93a03259c16
--- /dev/null
+++ b/drivers/platform/x86/intel_scu_ipcutil.c
@@ -0,0 +1,133 @@
1/*
2 * intel_scu_ipc.c: Driver for the Intel SCU IPC mechanism
3 *
4 * (C) Copyright 2008-2010 Intel Corporation
5 * Author: Sreedhara DS (sreedhara.ds@intel.com)
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; version 2
10 * of the License.
11 *
12 * This driver provides ioctl interfaces to call intel scu ipc driver api
13 */
14
15#include <linux/module.h>
16#include <linux/kernel.h>
17#include <linux/errno.h>
18#include <linux/types.h>
19#include <linux/fs.h>
20#include <linux/fcntl.h>
21#include <linux/sched.h>
22#include <linux/uaccess.h>
23#include <linux/slab.h>
24#include <linux/init.h>
25#include <asm/intel_scu_ipc.h>
26
27static u32 major;
28
29#define MAX_FW_SIZE 264192
30
31/* ioctl commnds */
32#define INTE_SCU_IPC_REGISTER_READ 0
33#define INTE_SCU_IPC_REGISTER_WRITE 1
34#define INTE_SCU_IPC_REGISTER_UPDATE 2
35#define INTE_SCU_IPC_FW_UPDATE 0xA2
36
37struct scu_ipc_data {
38 u32 count; /* No. of registers */
39 u16 addr[5]; /* Register addresses */
40 u8 data[5]; /* Register data */
41 u8 mask; /* Valid for read-modify-write */
42};
43
44/**
45 * scu_reg_access - implement register access ioctls
46 * @cmd: command we are doing (read/write/update)
47 * @data: kernel copy of ioctl data
48 *
49 * Allow the user to perform register accesses on the SCU via the
50 * kernel interface
51 */
52
53static int scu_reg_access(u32 cmd, struct scu_ipc_data *data)
54{
55 int count = data->count;
56
57 if (count == 0 || count == 3 || count > 4)
58 return -EINVAL;
59
60 switch (cmd) {
61 case INTE_SCU_IPC_REGISTER_READ:
62 return intel_scu_ipc_readv(data->addr, data->data, count);
63 case INTE_SCU_IPC_REGISTER_WRITE:
64 return intel_scu_ipc_writev(data->addr, data->data, count);
65 case INTE_SCU_IPC_REGISTER_UPDATE:
66 return intel_scu_ipc_update_register(data->addr[0],
67 data->data[0], data->mask);
68 default:
69 return -ENOTTY;
70 }
71}
72
73/**
74 * scu_ipc_ioctl - control ioctls for the SCU
75 * @fp: file handle of the SCU device
76 * @cmd: ioctl coce
77 * @arg: pointer to user passed structure
78 *
79 * Support the I/O and firmware flashing interfaces of the SCU
80 */
81static long scu_ipc_ioctl(struct file *fp, unsigned int cmd,
82 unsigned long arg)
83{
84 int ret;
85 struct scu_ipc_data data;
86 void __user *argp = (void __user *)arg;
87
88 if (!capable(CAP_SYS_RAWIO))
89 return -EPERM;
90
91 if (cmd == INTE_SCU_IPC_FW_UPDATE) {
92 u8 *fwbuf = kmalloc(MAX_FW_SIZE, GFP_KERNEL);
93 if (fwbuf == NULL)
94 return -ENOMEM;
95 if (copy_from_user(fwbuf, (u8 *)arg, MAX_FW_SIZE)) {
96 kfree(fwbuf);
97 return -EFAULT;
98 }
99 ret = intel_scu_ipc_fw_update(fwbuf, MAX_FW_SIZE);
100 kfree(fwbuf);
101 return ret;
102 } else {
103 if (copy_from_user(&data, argp, sizeof(struct scu_ipc_data)))
104 return -EFAULT;
105 ret = scu_reg_access(cmd, &data);
106 if (ret < 0)
107 return ret;
108 if (copy_to_user(argp, &data, sizeof(struct scu_ipc_data)))
109 return -EFAULT;
110 return 0;
111 }
112}
113
114static const struct file_operations scu_ipc_fops = {
115 .unlocked_ioctl = scu_ipc_ioctl,
116};
117
118static int __init ipc_module_init(void)
119{
120 return register_chrdev(0, "intel_mid_scu", &scu_ipc_fops);
121}
122
123static void __exit ipc_module_exit(void)
124{
125 unregister_chrdev(major, "intel_mid_scu");
126}
127
128module_init(ipc_module_init);
129module_exit(ipc_module_exit);
130
131MODULE_LICENSE("GPL v2");
132MODULE_DESCRIPTION("Utility driver for intel scu ipc");
133MODULE_AUTHOR("Sreedhara <sreedhara.ds@intel.com>");
diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c
index 7e9bb6df9d39..3ff629df9f01 100644
--- a/drivers/platform/x86/msi-laptop.c
+++ b/drivers/platform/x86/msi-laptop.c
@@ -51,6 +51,8 @@
51 * laptop as MSI S270. YMMV. 51 * laptop as MSI S270. YMMV.
52 */ 52 */
53 53
54#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
55
54#include <linux/module.h> 56#include <linux/module.h>
55#include <linux/kernel.h> 57#include <linux/kernel.h>
56#include <linux/init.h> 58#include <linux/init.h>
@@ -60,6 +62,8 @@
60#include <linux/platform_device.h> 62#include <linux/platform_device.h>
61#include <linux/rfkill.h> 63#include <linux/rfkill.h>
62#include <linux/i8042.h> 64#include <linux/i8042.h>
65#include <linux/input.h>
66#include <linux/input/sparse-keymap.h>
63 67
64#define MSI_DRIVER_VERSION "0.5" 68#define MSI_DRIVER_VERSION "0.5"
65 69
@@ -78,6 +82,9 @@
78#define MSI_STANDARD_EC_SCM_LOAD_ADDRESS 0x2d 82#define MSI_STANDARD_EC_SCM_LOAD_ADDRESS 0x2d
79#define MSI_STANDARD_EC_SCM_LOAD_MASK (1 << 0) 83#define MSI_STANDARD_EC_SCM_LOAD_MASK (1 << 0)
80 84
85#define MSI_STANDARD_EC_TOUCHPAD_ADDRESS 0xe4
86#define MSI_STANDARD_EC_TOUCHPAD_MASK (1 << 4)
87
81static int msi_laptop_resume(struct platform_device *device); 88static int msi_laptop_resume(struct platform_device *device);
82 89
83#define MSI_STANDARD_EC_DEVICES_EXISTS_ADDRESS 0x2f 90#define MSI_STANDARD_EC_DEVICES_EXISTS_ADDRESS 0x2f
@@ -90,6 +97,14 @@ static int auto_brightness;
90module_param(auto_brightness, int, 0); 97module_param(auto_brightness, int, 0);
91MODULE_PARM_DESC(auto_brightness, "Enable automatic brightness control (0: disabled; 1: enabled; 2: don't touch)"); 98MODULE_PARM_DESC(auto_brightness, "Enable automatic brightness control (0: disabled; 1: enabled; 2: don't touch)");
92 99
100static const struct key_entry msi_laptop_keymap[] = {
101 {KE_KEY, KEY_TOUCHPAD_ON, {KEY_TOUCHPAD_ON} }, /* Touch Pad On */
102 {KE_KEY, KEY_TOUCHPAD_OFF, {KEY_TOUCHPAD_OFF} },/* Touch Pad On */
103 {KE_END, 0}
104};
105
106static struct input_dev *msi_laptop_input_dev;
107
93static bool old_ec_model; 108static bool old_ec_model;
94static int wlan_s, bluetooth_s, threeg_s; 109static int wlan_s, bluetooth_s, threeg_s;
95static int threeg_exists; 110static int threeg_exists;
@@ -120,7 +135,7 @@ static int set_lcd_level(int level)
120 buf[1] = (u8) (level*31); 135 buf[1] = (u8) (level*31);
121 136
122 return ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, buf, sizeof(buf), 137 return ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, buf, sizeof(buf),
123 NULL, 0, 1); 138 NULL, 0);
124} 139}
125 140
126static int get_lcd_level(void) 141static int get_lcd_level(void)
@@ -129,7 +144,7 @@ static int get_lcd_level(void)
129 int result; 144 int result;
130 145
131 result = ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, &wdata, 1, 146 result = ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, &wdata, 1,
132 &rdata, 1, 1); 147 &rdata, 1);
133 if (result < 0) 148 if (result < 0)
134 return result; 149 return result;
135 150
@@ -142,7 +157,7 @@ static int get_auto_brightness(void)
142 int result; 157 int result;
143 158
144 result = ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, &wdata, 1, 159 result = ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, &wdata, 1,
145 &rdata, 1, 1); 160 &rdata, 1);
146 if (result < 0) 161 if (result < 0)
147 return result; 162 return result;
148 163
@@ -157,7 +172,7 @@ static int set_auto_brightness(int enable)
157 wdata[0] = 4; 172 wdata[0] = 4;
158 173
159 result = ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, wdata, 1, 174 result = ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, wdata, 1,
160 &rdata, 1, 1); 175 &rdata, 1);
161 if (result < 0) 176 if (result < 0)
162 return result; 177 return result;
163 178
@@ -165,7 +180,7 @@ static int set_auto_brightness(int enable)
165 wdata[1] = (rdata & 0xF7) | (enable ? 8 : 0); 180 wdata[1] = (rdata & 0xF7) | (enable ? 8 : 0);
166 181
167 return ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, wdata, 2, 182 return ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, wdata, 2,
168 NULL, 0, 1); 183 NULL, 0);
169} 184}
170 185
171static ssize_t set_device_state(const char *buf, size_t count, u8 mask) 186static ssize_t set_device_state(const char *buf, size_t count, u8 mask)
@@ -202,7 +217,7 @@ static int get_wireless_state(int *wlan, int *bluetooth)
202 u8 wdata = 0, rdata; 217 u8 wdata = 0, rdata;
203 int result; 218 int result;
204 219
205 result = ec_transaction(MSI_EC_COMMAND_WIRELESS, &wdata, 1, &rdata, 1, 1); 220 result = ec_transaction(MSI_EC_COMMAND_WIRELESS, &wdata, 1, &rdata, 1);
206 if (result < 0) 221 if (result < 0)
207 return -1; 222 return -1;
208 223
@@ -432,8 +447,7 @@ static struct platform_device *msipf_device;
432 447
433static int dmi_check_cb(const struct dmi_system_id *id) 448static int dmi_check_cb(const struct dmi_system_id *id)
434{ 449{
435 printk(KERN_INFO "msi-laptop: Identified laptop model '%s'.\n", 450 pr_info("Identified laptop model '%s'\n", id->ident);
436 id->ident);
437 return 1; 451 return 1;
438} 452}
439 453
@@ -605,6 +619,21 @@ static void msi_update_rfkill(struct work_struct *ignored)
605} 619}
606static DECLARE_DELAYED_WORK(msi_rfkill_work, msi_update_rfkill); 620static DECLARE_DELAYED_WORK(msi_rfkill_work, msi_update_rfkill);
607 621
622static void msi_send_touchpad_key(struct work_struct *ignored)
623{
624 u8 rdata;
625 int result;
626
627 result = ec_read(MSI_STANDARD_EC_TOUCHPAD_ADDRESS, &rdata);
628 if (result < 0)
629 return;
630
631 sparse_keymap_report_event(msi_laptop_input_dev,
632 (rdata & MSI_STANDARD_EC_TOUCHPAD_MASK) ?
633 KEY_TOUCHPAD_ON : KEY_TOUCHPAD_OFF, 1, true);
634}
635static DECLARE_DELAYED_WORK(msi_touchpad_work, msi_send_touchpad_key);
636
608static bool msi_laptop_i8042_filter(unsigned char data, unsigned char str, 637static bool msi_laptop_i8042_filter(unsigned char data, unsigned char str,
609 struct serio *port) 638 struct serio *port)
610{ 639{
@@ -613,12 +642,17 @@ static bool msi_laptop_i8042_filter(unsigned char data, unsigned char str,
613 if (str & 0x20) 642 if (str & 0x20)
614 return false; 643 return false;
615 644
616 /* 0x54 wwan, 0x62 bluetooth, 0x76 wlan*/ 645 /* 0x54 wwan, 0x62 bluetooth, 0x76 wlan, 0xE4 touchpad toggle*/
617 if (unlikely(data == 0xe0)) { 646 if (unlikely(data == 0xe0)) {
618 extended = true; 647 extended = true;
619 return false; 648 return false;
620 } else if (unlikely(extended)) { 649 } else if (unlikely(extended)) {
650 extended = false;
621 switch (data) { 651 switch (data) {
652 case 0xE4:
653 schedule_delayed_work(&msi_touchpad_work,
654 round_jiffies_relative(0.5 * HZ));
655 break;
622 case 0x54: 656 case 0x54:
623 case 0x62: 657 case 0x62:
624 case 0x76: 658 case 0x76:
@@ -626,7 +660,6 @@ static bool msi_laptop_i8042_filter(unsigned char data, unsigned char str,
626 round_jiffies_relative(0.5 * HZ)); 660 round_jiffies_relative(0.5 * HZ));
627 break; 661 break;
628 } 662 }
629 extended = false;
630 } 663 }
631 664
632 return false; 665 return false;
@@ -731,7 +764,43 @@ static int msi_laptop_resume(struct platform_device *device)
731 return 0; 764 return 0;
732} 765}
733 766
734static int load_scm_model_init(struct platform_device *sdev) 767static int __init msi_laptop_input_setup(void)
768{
769 int err;
770
771 msi_laptop_input_dev = input_allocate_device();
772 if (!msi_laptop_input_dev)
773 return -ENOMEM;
774
775 msi_laptop_input_dev->name = "MSI Laptop hotkeys";
776 msi_laptop_input_dev->phys = "msi-laptop/input0";
777 msi_laptop_input_dev->id.bustype = BUS_HOST;
778
779 err = sparse_keymap_setup(msi_laptop_input_dev,
780 msi_laptop_keymap, NULL);
781 if (err)
782 goto err_free_dev;
783
784 err = input_register_device(msi_laptop_input_dev);
785 if (err)
786 goto err_free_keymap;
787
788 return 0;
789
790err_free_keymap:
791 sparse_keymap_free(msi_laptop_input_dev);
792err_free_dev:
793 input_free_device(msi_laptop_input_dev);
794 return err;
795}
796
797static void msi_laptop_input_destroy(void)
798{
799 sparse_keymap_free(msi_laptop_input_dev);
800 input_unregister_device(msi_laptop_input_dev);
801}
802
803static int __init load_scm_model_init(struct platform_device *sdev)
735{ 804{
736 u8 data; 805 u8 data;
737 int result; 806 int result;
@@ -759,16 +828,23 @@ static int load_scm_model_init(struct platform_device *sdev)
759 if (result < 0) 828 if (result < 0)
760 goto fail_rfkill; 829 goto fail_rfkill;
761 830
831 /* setup input device */
832 result = msi_laptop_input_setup();
833 if (result)
834 goto fail_input;
835
762 result = i8042_install_filter(msi_laptop_i8042_filter); 836 result = i8042_install_filter(msi_laptop_i8042_filter);
763 if (result) { 837 if (result) {
764 printk(KERN_ERR 838 pr_err("Unable to install key filter\n");
765 "msi-laptop: Unable to install key filter\n");
766 goto fail_filter; 839 goto fail_filter;
767 } 840 }
768 841
769 return 0; 842 return 0;
770 843
771fail_filter: 844fail_filter:
845 msi_laptop_input_destroy();
846
847fail_input:
772 rfkill_cleanup(); 848 rfkill_cleanup();
773 849
774fail_rfkill: 850fail_rfkill:
@@ -799,11 +875,11 @@ static int __init msi_init(void)
799 /* Register backlight stuff */ 875 /* Register backlight stuff */
800 876
801 if (acpi_video_backlight_support()) { 877 if (acpi_video_backlight_support()) {
802 printk(KERN_INFO "MSI: Brightness ignored, must be controlled " 878 pr_info("Brightness ignored, must be controlled by ACPI video driver\n");
803 "by ACPI video driver\n");
804 } else { 879 } else {
805 struct backlight_properties props; 880 struct backlight_properties props;
806 memset(&props, 0, sizeof(struct backlight_properties)); 881 memset(&props, 0, sizeof(struct backlight_properties));
882 props.type = BACKLIGHT_PLATFORM;
807 props.max_brightness = MSI_LCD_LEVEL_MAX - 1; 883 props.max_brightness = MSI_LCD_LEVEL_MAX - 1;
808 msibl_device = backlight_device_register("msi-laptop-bl", NULL, 884 msibl_device = backlight_device_register("msi-laptop-bl", NULL,
809 NULL, &msibl_ops, 885 NULL, &msibl_ops,
@@ -853,7 +929,7 @@ static int __init msi_init(void)
853 if (auto_brightness != 2) 929 if (auto_brightness != 2)
854 set_auto_brightness(auto_brightness); 930 set_auto_brightness(auto_brightness);
855 931
856 printk(KERN_INFO "msi-laptop: driver "MSI_DRIVER_VERSION" successfully loaded.\n"); 932 pr_info("driver " MSI_DRIVER_VERSION " successfully loaded\n");
857 933
858 return 0; 934 return 0;
859 935
@@ -885,6 +961,7 @@ static void __exit msi_cleanup(void)
885{ 961{
886 if (load_scm_model) { 962 if (load_scm_model) {
887 i8042_remove_filter(msi_laptop_i8042_filter); 963 i8042_remove_filter(msi_laptop_i8042_filter);
964 msi_laptop_input_destroy();
888 cancel_delayed_work_sync(&msi_rfkill_work); 965 cancel_delayed_work_sync(&msi_rfkill_work);
889 rfkill_cleanup(); 966 rfkill_cleanup();
890 } 967 }
@@ -900,7 +977,7 @@ static void __exit msi_cleanup(void)
900 if (auto_brightness != 2) 977 if (auto_brightness != 2)
901 set_auto_brightness(1); 978 set_auto_brightness(1);
902 979
903 printk(KERN_INFO "msi-laptop: driver unloaded.\n"); 980 pr_info("driver unloaded\n");
904} 981}
905 982
906module_init(msi_init); 983module_init(msi_init);
diff --git a/drivers/platform/x86/msi-wmi.c b/drivers/platform/x86/msi-wmi.c
index 42a5469a2459..c832e3356cd6 100644
--- a/drivers/platform/x86/msi-wmi.c
+++ b/drivers/platform/x86/msi-wmi.c
@@ -20,6 +20,7 @@
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */ 21 */
22 22
23#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
23 24
24#include <linux/kernel.h> 25#include <linux/kernel.h>
25#include <linux/input.h> 26#include <linux/input.h>
@@ -36,23 +37,22 @@ MODULE_ALIAS("wmi:551A1F84-FBDD-4125-91DB-3EA8F44F1D45");
36MODULE_ALIAS("wmi:B6F3EEF2-3D2F-49DC-9DE3-85BCE18C62F2"); 37MODULE_ALIAS("wmi:B6F3EEF2-3D2F-49DC-9DE3-85BCE18C62F2");
37 38
38#define DRV_NAME "msi-wmi" 39#define DRV_NAME "msi-wmi"
39#define DRV_PFX DRV_NAME ": "
40 40
41#define MSIWMI_BIOS_GUID "551A1F84-FBDD-4125-91DB-3EA8F44F1D45" 41#define MSIWMI_BIOS_GUID "551A1F84-FBDD-4125-91DB-3EA8F44F1D45"
42#define MSIWMI_EVENT_GUID "B6F3EEF2-3D2F-49DC-9DE3-85BCE18C62F2" 42#define MSIWMI_EVENT_GUID "B6F3EEF2-3D2F-49DC-9DE3-85BCE18C62F2"
43 43
44#define dprintk(msg...) pr_debug(DRV_PFX msg) 44#define SCANCODE_BASE 0xD0
45 45#define MSI_WMI_BRIGHTNESSUP SCANCODE_BASE
46#define KEYCODE_BASE 0xD0 46#define MSI_WMI_BRIGHTNESSDOWN (SCANCODE_BASE + 1)
47#define MSI_WMI_BRIGHTNESSUP KEYCODE_BASE 47#define MSI_WMI_VOLUMEUP (SCANCODE_BASE + 2)
48#define MSI_WMI_BRIGHTNESSDOWN (KEYCODE_BASE + 1) 48#define MSI_WMI_VOLUMEDOWN (SCANCODE_BASE + 3)
49#define MSI_WMI_VOLUMEUP (KEYCODE_BASE + 2) 49#define MSI_WMI_MUTE (SCANCODE_BASE + 4)
50#define MSI_WMI_VOLUMEDOWN (KEYCODE_BASE + 3)
51static struct key_entry msi_wmi_keymap[] = { 50static struct key_entry msi_wmi_keymap[] = {
52 { KE_KEY, MSI_WMI_BRIGHTNESSUP, {KEY_BRIGHTNESSUP} }, 51 { KE_KEY, MSI_WMI_BRIGHTNESSUP, {KEY_BRIGHTNESSUP} },
53 { KE_KEY, MSI_WMI_BRIGHTNESSDOWN, {KEY_BRIGHTNESSDOWN} }, 52 { KE_KEY, MSI_WMI_BRIGHTNESSDOWN, {KEY_BRIGHTNESSDOWN} },
54 { KE_KEY, MSI_WMI_VOLUMEUP, {KEY_VOLUMEUP} }, 53 { KE_KEY, MSI_WMI_VOLUMEUP, {KEY_VOLUMEUP} },
55 { KE_KEY, MSI_WMI_VOLUMEDOWN, {KEY_VOLUMEDOWN} }, 54 { KE_KEY, MSI_WMI_VOLUMEDOWN, {KEY_VOLUMEDOWN} },
55 { KE_KEY, MSI_WMI_MUTE, {KEY_MUTE} },
56 { KE_END, 0} 56 { KE_END, 0}
57}; 57};
58static ktime_t last_pressed[ARRAY_SIZE(msi_wmi_keymap) - 1]; 58static ktime_t last_pressed[ARRAY_SIZE(msi_wmi_keymap) - 1];
@@ -76,7 +76,7 @@ static int msi_wmi_query_block(int instance, int *ret)
76 76
77 if (!obj || obj->type != ACPI_TYPE_INTEGER) { 77 if (!obj || obj->type != ACPI_TYPE_INTEGER) {
78 if (obj) { 78 if (obj) {
79 printk(KERN_ERR DRV_PFX "query block returned object " 79 pr_err("query block returned object "
80 "type: %d - buffer length:%d\n", obj->type, 80 "type: %d - buffer length:%d\n", obj->type,
81 obj->type == ACPI_TYPE_BUFFER ? 81 obj->type == ACPI_TYPE_BUFFER ?
82 obj->buffer.length : 0); 82 obj->buffer.length : 0);
@@ -95,8 +95,8 @@ static int msi_wmi_set_block(int instance, int value)
95 95
96 struct acpi_buffer input = { sizeof(int), &value }; 96 struct acpi_buffer input = { sizeof(int), &value };
97 97
98 dprintk("Going to set block of instance: %d - value: %d\n", 98 pr_debug("Going to set block of instance: %d - value: %d\n",
99 instance, value); 99 instance, value);
100 100
101 status = wmi_set_block(MSIWMI_BIOS_GUID, instance, &input); 101 status = wmi_set_block(MSIWMI_BIOS_GUID, instance, &input);
102 102
@@ -110,20 +110,19 @@ static int bl_get(struct backlight_device *bd)
110 /* Instance 1 is "get backlight", cmp with DSDT */ 110 /* Instance 1 is "get backlight", cmp with DSDT */
111 err = msi_wmi_query_block(1, &ret); 111 err = msi_wmi_query_block(1, &ret);
112 if (err) { 112 if (err) {
113 printk(KERN_ERR DRV_PFX "Could not query backlight: %d\n", err); 113 pr_err("Could not query backlight: %d\n", err);
114 return -EINVAL; 114 return -EINVAL;
115 } 115 }
116 dprintk("Get: Query block returned: %d\n", ret); 116 pr_debug("Get: Query block returned: %d\n", ret);
117 for (level = 0; level < ARRAY_SIZE(backlight_map); level++) { 117 for (level = 0; level < ARRAY_SIZE(backlight_map); level++) {
118 if (backlight_map[level] == ret) { 118 if (backlight_map[level] == ret) {
119 dprintk("Current backlight level: 0x%X - index: %d\n", 119 pr_debug("Current backlight level: 0x%X - index: %d\n",
120 backlight_map[level], level); 120 backlight_map[level], level);
121 break; 121 break;
122 } 122 }
123 } 123 }
124 if (level == ARRAY_SIZE(backlight_map)) { 124 if (level == ARRAY_SIZE(backlight_map)) {
125 printk(KERN_ERR DRV_PFX "get: Invalid brightness value: 0x%X\n", 125 pr_err("get: Invalid brightness value: 0x%X\n", ret);
126 ret);
127 return -EINVAL; 126 return -EINVAL;
128 } 127 }
129 return level; 128 return level;
@@ -154,7 +153,7 @@ static void msi_wmi_notify(u32 value, void *context)
154 153
155 status = wmi_get_event_data(value, &response); 154 status = wmi_get_event_data(value, &response);
156 if (status != AE_OK) { 155 if (status != AE_OK) {
157 printk(KERN_INFO DRV_PFX "bad event status 0x%x\n", status); 156 pr_info("bad event status 0x%x\n", status);
158 return; 157 return;
159 } 158 }
160 159
@@ -162,40 +161,39 @@ static void msi_wmi_notify(u32 value, void *context)
162 161
163 if (obj && obj->type == ACPI_TYPE_INTEGER) { 162 if (obj && obj->type == ACPI_TYPE_INTEGER) {
164 int eventcode = obj->integer.value; 163 int eventcode = obj->integer.value;
165 dprintk("Eventcode: 0x%x\n", eventcode); 164 pr_debug("Eventcode: 0x%x\n", eventcode);
166 key = sparse_keymap_entry_from_scancode(msi_wmi_input_dev, 165 key = sparse_keymap_entry_from_scancode(msi_wmi_input_dev,
167 eventcode); 166 eventcode);
168 if (key) { 167 if (key) {
169 ktime_t diff; 168 ktime_t diff;
170 cur = ktime_get_real(); 169 cur = ktime_get_real();
171 diff = ktime_sub(cur, last_pressed[key->code - 170 diff = ktime_sub(cur, last_pressed[key->code -
172 KEYCODE_BASE]); 171 SCANCODE_BASE]);
173 /* Ignore event if the same event happened in a 50 ms 172 /* Ignore event if the same event happened in a 50 ms
174 timeframe -> Key press may result in 10-20 GPEs */ 173 timeframe -> Key press may result in 10-20 GPEs */
175 if (ktime_to_us(diff) < 1000 * 50) { 174 if (ktime_to_us(diff) < 1000 * 50) {
176 dprintk("Suppressed key event 0x%X - " 175 pr_debug("Suppressed key event 0x%X - "
177 "Last press was %lld us ago\n", 176 "Last press was %lld us ago\n",
178 key->code, ktime_to_us(diff)); 177 key->code, ktime_to_us(diff));
179 return; 178 return;
180 } 179 }
181 last_pressed[key->code - KEYCODE_BASE] = cur; 180 last_pressed[key->code - SCANCODE_BASE] = cur;
182 181
183 if (key->type == KE_KEY && 182 if (key->type == KE_KEY &&
184 /* Brightness is served via acpi video driver */ 183 /* Brightness is served via acpi video driver */
185 (!acpi_video_backlight_support() || 184 (!acpi_video_backlight_support() ||
186 (key->code != MSI_WMI_BRIGHTNESSUP && 185 (key->code != MSI_WMI_BRIGHTNESSUP &&
187 key->code != MSI_WMI_BRIGHTNESSDOWN))) { 186 key->code != MSI_WMI_BRIGHTNESSDOWN))) {
188 dprintk("Send key: 0x%X - " 187 pr_debug("Send key: 0x%X - "
189 "Input layer keycode: %d\n", key->code, 188 "Input layer keycode: %d\n",
190 key->keycode); 189 key->code, key->keycode);
191 sparse_keymap_report_entry(msi_wmi_input_dev, 190 sparse_keymap_report_entry(msi_wmi_input_dev,
192 key, 1, true); 191 key, 1, true);
193 } 192 }
194 } else 193 } else
195 printk(KERN_INFO "Unknown key pressed - %x\n", 194 pr_info("Unknown key pressed - %x\n", eventcode);
196 eventcode);
197 } else 195 } else
198 printk(KERN_INFO DRV_PFX "Unknown event received\n"); 196 pr_info("Unknown event received\n");
199 kfree(response.pointer); 197 kfree(response.pointer);
200} 198}
201 199
@@ -236,8 +234,7 @@ static int __init msi_wmi_init(void)
236 int err; 234 int err;
237 235
238 if (!wmi_has_guid(MSIWMI_EVENT_GUID)) { 236 if (!wmi_has_guid(MSIWMI_EVENT_GUID)) {
239 printk(KERN_ERR 237 pr_err("This machine doesn't have MSI-hotkeys through WMI\n");
240 "This machine doesn't have MSI-hotkeys through WMI\n");
241 return -ENODEV; 238 return -ENODEV;
242 } 239 }
243 err = wmi_install_notify_handler(MSIWMI_EVENT_GUID, 240 err = wmi_install_notify_handler(MSIWMI_EVENT_GUID,
@@ -252,6 +249,7 @@ static int __init msi_wmi_init(void)
252 if (!acpi_video_backlight_support()) { 249 if (!acpi_video_backlight_support()) {
253 struct backlight_properties props; 250 struct backlight_properties props;
254 memset(&props, 0, sizeof(struct backlight_properties)); 251 memset(&props, 0, sizeof(struct backlight_properties));
252 props.type = BACKLIGHT_PLATFORM;
255 props.max_brightness = ARRAY_SIZE(backlight_map) - 1; 253 props.max_brightness = ARRAY_SIZE(backlight_map) - 1;
256 backlight = backlight_device_register(DRV_NAME, NULL, NULL, 254 backlight = backlight_device_register(DRV_NAME, NULL, NULL,
257 &msi_backlight_ops, 255 &msi_backlight_ops,
@@ -267,7 +265,7 @@ static int __init msi_wmi_init(void)
267 265
268 backlight->props.brightness = err; 266 backlight->props.brightness = err;
269 } 267 }
270 dprintk("Event handler installed\n"); 268 pr_debug("Event handler installed\n");
271 269
272 return 0; 270 return 0;
273 271
diff --git a/drivers/platform/x86/mxm-wmi.c b/drivers/platform/x86/mxm-wmi.c
new file mode 100644
index 000000000000..0aea63b3729a
--- /dev/null
+++ b/drivers/platform/x86/mxm-wmi.c
@@ -0,0 +1,111 @@
1/*
2 * MXM WMI driver
3 *
4 * Copyright(C) 2010 Red Hat.
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 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20#include <linux/kernel.h>
21#include <linux/module.h>
22#include <linux/init.h>
23#include <acpi/acpi_bus.h>
24#include <acpi/acpi_drivers.h>
25
26MODULE_AUTHOR("Dave Airlie");
27MODULE_DESCRIPTION("MXM WMI Driver");
28MODULE_LICENSE("GPL");
29
30#define MXM_WMMX_GUID "F6CB5C3C-9CAE-4EBD-B577-931EA32A2CC0"
31
32MODULE_ALIAS("wmi:"MXM_WMMX_GUID);
33
34#define MXM_WMMX_FUNC_MXDS 0x5344584D /* "MXDS" */
35#define MXM_WMMX_FUNC_MXMX 0x53445344 /* "MXMX" */
36
37struct mxds_args {
38 u32 func;
39 u32 args;
40 u32 xarg;
41};
42
43int mxm_wmi_call_mxds(int adapter)
44{
45 struct mxds_args args = {
46 .func = MXM_WMMX_FUNC_MXDS,
47 .args = 0,
48 .xarg = 1,
49 };
50 struct acpi_buffer input = { (acpi_size)sizeof(args), &args };
51 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
52 acpi_status status;
53
54 printk("calling mux switch %d\n", adapter);
55
56 status = wmi_evaluate_method(MXM_WMMX_GUID, 0x1, adapter, &input,
57 &output);
58
59 if (ACPI_FAILURE(status))
60 return status;
61
62 printk("mux switched %d\n", status);
63 return 0;
64
65}
66EXPORT_SYMBOL_GPL(mxm_wmi_call_mxds);
67
68int mxm_wmi_call_mxmx(int adapter)
69{
70 struct mxds_args args = {
71 .func = MXM_WMMX_FUNC_MXMX,
72 .args = 0,
73 .xarg = 1,
74 };
75 struct acpi_buffer input = { (acpi_size)sizeof(args), &args };
76 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
77 acpi_status status;
78
79 printk("calling mux switch %d\n", adapter);
80
81 status = wmi_evaluate_method(MXM_WMMX_GUID, 0x1, adapter, &input,
82 &output);
83
84 if (ACPI_FAILURE(status))
85 return status;
86
87 printk("mux mutex set switched %d\n", status);
88 return 0;
89
90}
91EXPORT_SYMBOL_GPL(mxm_wmi_call_mxmx);
92
93bool mxm_wmi_supported(void)
94{
95 bool guid_valid;
96 guid_valid = wmi_has_guid(MXM_WMMX_GUID);
97 return guid_valid;
98}
99EXPORT_SYMBOL_GPL(mxm_wmi_supported);
100
101static int __init mxm_wmi_init(void)
102{
103 return 0;
104}
105
106static void __exit mxm_wmi_exit(void)
107{
108}
109
110module_init(mxm_wmi_init);
111module_exit(mxm_wmi_exit);
diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c
index ec01c3d8fc5a..05be30ee158b 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,22 +591,24 @@ 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 */
648 memset(&props, 0, sizeof(struct backlight_properties)); 604 memset(&props, 0, sizeof(struct backlight_properties));
605 props.type = BACKLIGHT_PLATFORM;
649 props.max_brightness = pcc->sinf[SINF_AC_MAX_BRIGHT]; 606 props.max_brightness = pcc->sinf[SINF_AC_MAX_BRIGHT];
650 pcc->backlight = backlight_device_register("panasonic", NULL, pcc, 607 pcc->backlight = backlight_device_register("panasonic", NULL, pcc,
651 &pcc_backlight_ops, &props); 608 &pcc_backlight_ops, &props);
652 if (IS_ERR(pcc->backlight)) { 609 if (IS_ERR(pcc->backlight)) {
653 result = PTR_ERR(pcc->backlight); 610 result = PTR_ERR(pcc->backlight);
654 goto out_sinf; 611 goto out_input;
655 } 612 }
656 613
657 /* read the initial brightness setting from the hardware */ 614 /* read the initial brightness setting from the hardware */
@@ -669,12 +626,10 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
669 626
670out_backlight: 627out_backlight:
671 backlight_device_unregister(pcc->backlight); 628 backlight_device_unregister(pcc->backlight);
629out_input:
630 acpi_pcc_destroy_input(pcc);
672out_sinf: 631out_sinf:
673 kfree(pcc->sinf); 632 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: 633out_hotkey:
679 kfree(pcc); 634 kfree(pcc);
680 635
@@ -709,9 +664,7 @@ static int acpi_pcc_hotkey_remove(struct acpi_device *device, int type)
709 664
710 backlight_device_unregister(pcc->backlight); 665 backlight_device_unregister(pcc->backlight);
711 666
712 input_unregister_device(pcc->input_dev); 667 acpi_pcc_destroy_input(pcc);
713 /* no need to input_free_device() since core input API refcount and
714 * free()s the device */
715 668
716 kfree(pcc->sinf); 669 kfree(pcc->sinf);
717 kfree(pcc); 670 kfree(pcc);
diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c
new file mode 100644
index 000000000000..d347116d150e
--- /dev/null
+++ b/drivers/platform/x86/samsung-laptop.c
@@ -0,0 +1,843 @@
1/*
2 * Samsung Laptop driver
3 *
4 * Copyright (C) 2009,2011 Greg Kroah-Hartman (gregkh@suse.de)
5 * Copyright (C) 2009,2011 Novell Inc.
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published by
9 * the Free Software Foundation.
10 *
11 */
12#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13
14#include <linux/kernel.h>
15#include <linux/init.h>
16#include <linux/module.h>
17#include <linux/delay.h>
18#include <linux/pci.h>
19#include <linux/backlight.h>
20#include <linux/fb.h>
21#include <linux/dmi.h>
22#include <linux/platform_device.h>
23#include <linux/rfkill.h>
24
25/*
26 * This driver is needed because a number of Samsung laptops do not hook
27 * their control settings through ACPI. So we have to poke around in the
28 * BIOS to do things like brightness values, and "special" key controls.
29 */
30
31/*
32 * We have 0 - 8 as valid brightness levels. The specs say that level 0 should
33 * be reserved by the BIOS (which really doesn't make much sense), we tell
34 * userspace that the value is 0 - 7 and then just tell the hardware 1 - 8
35 */
36#define MAX_BRIGHT 0x07
37
38
39#define SABI_IFACE_MAIN 0x00
40#define SABI_IFACE_SUB 0x02
41#define SABI_IFACE_COMPLETE 0x04
42#define SABI_IFACE_DATA 0x05
43
44/* Structure to get data back to the calling function */
45struct sabi_retval {
46 u8 retval[20];
47};
48
49struct sabi_header_offsets {
50 u8 port;
51 u8 re_mem;
52 u8 iface_func;
53 u8 en_mem;
54 u8 data_offset;
55 u8 data_segment;
56};
57
58struct sabi_commands {
59 /*
60 * Brightness is 0 - 8, as described above.
61 * Value 0 is for the BIOS to use
62 */
63 u8 get_brightness;
64 u8 set_brightness;
65
66 /*
67 * first byte:
68 * 0x00 - wireless is off
69 * 0x01 - wireless is on
70 * second byte:
71 * 0x02 - 3G is off
72 * 0x03 - 3G is on
73 * TODO, verify 3G is correct, that doesn't seem right...
74 */
75 u8 get_wireless_button;
76 u8 set_wireless_button;
77
78 /* 0 is off, 1 is on */
79 u8 get_backlight;
80 u8 set_backlight;
81
82 /*
83 * 0x80 or 0x00 - no action
84 * 0x81 - recovery key pressed
85 */
86 u8 get_recovery_mode;
87 u8 set_recovery_mode;
88
89 /*
90 * on seclinux: 0 is low, 1 is high,
91 * on swsmi: 0 is normal, 1 is silent, 2 is turbo
92 */
93 u8 get_performance_level;
94 u8 set_performance_level;
95
96 /*
97 * Tell the BIOS that Linux is running on this machine.
98 * 81 is on, 80 is off
99 */
100 u8 set_linux;
101};
102
103struct sabi_performance_level {
104 const char *name;
105 u8 value;
106};
107
108struct sabi_config {
109 const char *test_string;
110 u16 main_function;
111 const struct sabi_header_offsets header_offsets;
112 const struct sabi_commands commands;
113 const struct sabi_performance_level performance_levels[4];
114 u8 min_brightness;
115 u8 max_brightness;
116};
117
118static const struct sabi_config sabi_configs[] = {
119 {
120 .test_string = "SECLINUX",
121
122 .main_function = 0x4c49,
123
124 .header_offsets = {
125 .port = 0x00,
126 .re_mem = 0x02,
127 .iface_func = 0x03,
128 .en_mem = 0x04,
129 .data_offset = 0x05,
130 .data_segment = 0x07,
131 },
132
133 .commands = {
134 .get_brightness = 0x00,
135 .set_brightness = 0x01,
136
137 .get_wireless_button = 0x02,
138 .set_wireless_button = 0x03,
139
140 .get_backlight = 0x04,
141 .set_backlight = 0x05,
142
143 .get_recovery_mode = 0x06,
144 .set_recovery_mode = 0x07,
145
146 .get_performance_level = 0x08,
147 .set_performance_level = 0x09,
148
149 .set_linux = 0x0a,
150 },
151
152 .performance_levels = {
153 {
154 .name = "silent",
155 .value = 0,
156 },
157 {
158 .name = "normal",
159 .value = 1,
160 },
161 { },
162 },
163 .min_brightness = 1,
164 .max_brightness = 8,
165 },
166 {
167 .test_string = "SwSmi@",
168
169 .main_function = 0x5843,
170
171 .header_offsets = {
172 .port = 0x00,
173 .re_mem = 0x04,
174 .iface_func = 0x02,
175 .en_mem = 0x03,
176 .data_offset = 0x05,
177 .data_segment = 0x07,
178 },
179
180 .commands = {
181 .get_brightness = 0x10,
182 .set_brightness = 0x11,
183
184 .get_wireless_button = 0x12,
185 .set_wireless_button = 0x13,
186
187 .get_backlight = 0x2d,
188 .set_backlight = 0x2e,
189
190 .get_recovery_mode = 0xff,
191 .set_recovery_mode = 0xff,
192
193 .get_performance_level = 0x31,
194 .set_performance_level = 0x32,
195
196 .set_linux = 0xff,
197 },
198
199 .performance_levels = {
200 {
201 .name = "normal",
202 .value = 0,
203 },
204 {
205 .name = "silent",
206 .value = 1,
207 },
208 {
209 .name = "overclock",
210 .value = 2,
211 },
212 { },
213 },
214 .min_brightness = 0,
215 .max_brightness = 8,
216 },
217 { },
218};
219
220static const struct sabi_config *sabi_config;
221
222static void __iomem *sabi;
223static void __iomem *sabi_iface;
224static void __iomem *f0000_segment;
225static struct backlight_device *backlight_device;
226static struct mutex sabi_mutex;
227static struct platform_device *sdev;
228static struct rfkill *rfk;
229
230static int force;
231module_param(force, bool, 0);
232MODULE_PARM_DESC(force,
233 "Disable the DMI check and forces the driver to be loaded");
234
235static int debug;
236module_param(debug, bool, S_IRUGO | S_IWUSR);
237MODULE_PARM_DESC(debug, "Debug enabled or not");
238
239static int sabi_get_command(u8 command, struct sabi_retval *sretval)
240{
241 int retval = 0;
242 u16 port = readw(sabi + sabi_config->header_offsets.port);
243 u8 complete, iface_data;
244
245 mutex_lock(&sabi_mutex);
246
247 /* enable memory to be able to write to it */
248 outb(readb(sabi + sabi_config->header_offsets.en_mem), port);
249
250 /* write out the command */
251 writew(sabi_config->main_function, sabi_iface + SABI_IFACE_MAIN);
252 writew(command, sabi_iface + SABI_IFACE_SUB);
253 writeb(0, sabi_iface + SABI_IFACE_COMPLETE);
254 outb(readb(sabi + sabi_config->header_offsets.iface_func), port);
255
256 /* write protect memory to make it safe */
257 outb(readb(sabi + sabi_config->header_offsets.re_mem), port);
258
259 /* see if the command actually succeeded */
260 complete = readb(sabi_iface + SABI_IFACE_COMPLETE);
261 iface_data = readb(sabi_iface + SABI_IFACE_DATA);
262 if (complete != 0xaa || iface_data == 0xff) {
263 pr_warn("SABI get command 0x%02x failed with completion flag 0x%02x and data 0x%02x\n",
264 command, complete, iface_data);
265 retval = -EINVAL;
266 goto exit;
267 }
268 /*
269 * Save off the data into a structure so the caller use it.
270 * Right now we only want the first 4 bytes,
271 * There are commands that need more, but not for the ones we
272 * currently care about.
273 */
274 sretval->retval[0] = readb(sabi_iface + SABI_IFACE_DATA);
275 sretval->retval[1] = readb(sabi_iface + SABI_IFACE_DATA + 1);
276 sretval->retval[2] = readb(sabi_iface + SABI_IFACE_DATA + 2);
277 sretval->retval[3] = readb(sabi_iface + SABI_IFACE_DATA + 3);
278
279exit:
280 mutex_unlock(&sabi_mutex);
281 return retval;
282
283}
284
285static int sabi_set_command(u8 command, u8 data)
286{
287 int retval = 0;
288 u16 port = readw(sabi + sabi_config->header_offsets.port);
289 u8 complete, iface_data;
290
291 mutex_lock(&sabi_mutex);
292
293 /* enable memory to be able to write to it */
294 outb(readb(sabi + sabi_config->header_offsets.en_mem), port);
295
296 /* write out the command */
297 writew(sabi_config->main_function, sabi_iface + SABI_IFACE_MAIN);
298 writew(command, sabi_iface + SABI_IFACE_SUB);
299 writeb(0, sabi_iface + SABI_IFACE_COMPLETE);
300 writeb(data, sabi_iface + SABI_IFACE_DATA);
301 outb(readb(sabi + sabi_config->header_offsets.iface_func), port);
302
303 /* write protect memory to make it safe */
304 outb(readb(sabi + sabi_config->header_offsets.re_mem), port);
305
306 /* see if the command actually succeeded */
307 complete = readb(sabi_iface + SABI_IFACE_COMPLETE);
308 iface_data = readb(sabi_iface + SABI_IFACE_DATA);
309 if (complete != 0xaa || iface_data == 0xff) {
310 pr_warn("SABI set command 0x%02x failed with completion flag 0x%02x and data 0x%02x\n",
311 command, complete, iface_data);
312 retval = -EINVAL;
313 }
314
315 mutex_unlock(&sabi_mutex);
316 return retval;
317}
318
319static void test_backlight(void)
320{
321 struct sabi_retval sretval;
322
323 sabi_get_command(sabi_config->commands.get_backlight, &sretval);
324 printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]);
325
326 sabi_set_command(sabi_config->commands.set_backlight, 0);
327 printk(KERN_DEBUG "backlight should be off\n");
328
329 sabi_get_command(sabi_config->commands.get_backlight, &sretval);
330 printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]);
331
332 msleep(1000);
333
334 sabi_set_command(sabi_config->commands.set_backlight, 1);
335 printk(KERN_DEBUG "backlight should be on\n");
336
337 sabi_get_command(sabi_config->commands.get_backlight, &sretval);
338 printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]);
339}
340
341static void test_wireless(void)
342{
343 struct sabi_retval sretval;
344
345 sabi_get_command(sabi_config->commands.get_wireless_button, &sretval);
346 printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]);
347
348 sabi_set_command(sabi_config->commands.set_wireless_button, 0);
349 printk(KERN_DEBUG "wireless led should be off\n");
350
351 sabi_get_command(sabi_config->commands.get_wireless_button, &sretval);
352 printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]);
353
354 msleep(1000);
355
356 sabi_set_command(sabi_config->commands.set_wireless_button, 1);
357 printk(KERN_DEBUG "wireless led should be on\n");
358
359 sabi_get_command(sabi_config->commands.get_wireless_button, &sretval);
360 printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]);
361}
362
363static u8 read_brightness(void)
364{
365 struct sabi_retval sretval;
366 int user_brightness = 0;
367 int retval;
368
369 retval = sabi_get_command(sabi_config->commands.get_brightness,
370 &sretval);
371 if (!retval) {
372 user_brightness = sretval.retval[0];
373 if (user_brightness != 0)
374 user_brightness -= sabi_config->min_brightness;
375 }
376 return user_brightness;
377}
378
379static void set_brightness(u8 user_brightness)
380{
381 u8 user_level = user_brightness - sabi_config->min_brightness;
382
383 sabi_set_command(sabi_config->commands.set_brightness, user_level);
384}
385
386static int get_brightness(struct backlight_device *bd)
387{
388 return (int)read_brightness();
389}
390
391static int update_status(struct backlight_device *bd)
392{
393 set_brightness(bd->props.brightness);
394
395 if (bd->props.power == FB_BLANK_UNBLANK)
396 sabi_set_command(sabi_config->commands.set_backlight, 1);
397 else
398 sabi_set_command(sabi_config->commands.set_backlight, 0);
399 return 0;
400}
401
402static const struct backlight_ops backlight_ops = {
403 .get_brightness = get_brightness,
404 .update_status = update_status,
405};
406
407static int rfkill_set(void *data, bool blocked)
408{
409 /* Do something with blocked...*/
410 /*
411 * blocked == false is on
412 * blocked == true is off
413 */
414 if (blocked)
415 sabi_set_command(sabi_config->commands.set_wireless_button, 0);
416 else
417 sabi_set_command(sabi_config->commands.set_wireless_button, 1);
418
419 return 0;
420}
421
422static struct rfkill_ops rfkill_ops = {
423 .set_block = rfkill_set,
424};
425
426static int init_wireless(struct platform_device *sdev)
427{
428 int retval;
429
430 rfk = rfkill_alloc("samsung-wifi", &sdev->dev, RFKILL_TYPE_WLAN,
431 &rfkill_ops, NULL);
432 if (!rfk)
433 return -ENOMEM;
434
435 retval = rfkill_register(rfk);
436 if (retval) {
437 rfkill_destroy(rfk);
438 return -ENODEV;
439 }
440
441 return 0;
442}
443
444static void destroy_wireless(void)
445{
446 rfkill_unregister(rfk);
447 rfkill_destroy(rfk);
448}
449
450static ssize_t get_performance_level(struct device *dev,
451 struct device_attribute *attr, char *buf)
452{
453 struct sabi_retval sretval;
454 int retval;
455 int i;
456
457 /* Read the state */
458 retval = sabi_get_command(sabi_config->commands.get_performance_level,
459 &sretval);
460 if (retval)
461 return retval;
462
463 /* The logic is backwards, yeah, lots of fun... */
464 for (i = 0; sabi_config->performance_levels[i].name; ++i) {
465 if (sretval.retval[0] == sabi_config->performance_levels[i].value)
466 return sprintf(buf, "%s\n", sabi_config->performance_levels[i].name);
467 }
468 return sprintf(buf, "%s\n", "unknown");
469}
470
471static ssize_t set_performance_level(struct device *dev,
472 struct device_attribute *attr, const char *buf,
473 size_t count)
474{
475 if (count >= 1) {
476 int i;
477 for (i = 0; sabi_config->performance_levels[i].name; ++i) {
478 const struct sabi_performance_level *level =
479 &sabi_config->performance_levels[i];
480 if (!strncasecmp(level->name, buf, strlen(level->name))) {
481 sabi_set_command(sabi_config->commands.set_performance_level,
482 level->value);
483 break;
484 }
485 }
486 if (!sabi_config->performance_levels[i].name)
487 return -EINVAL;
488 }
489 return count;
490}
491static DEVICE_ATTR(performance_level, S_IWUSR | S_IRUGO,
492 get_performance_level, set_performance_level);
493
494
495static int __init dmi_check_cb(const struct dmi_system_id *id)
496{
497 pr_info("found laptop model '%s'\n",
498 id->ident);
499 return 1;
500}
501
502static struct dmi_system_id __initdata samsung_dmi_table[] = {
503 {
504 .ident = "N128",
505 .matches = {
506 DMI_MATCH(DMI_SYS_VENDOR,
507 "SAMSUNG ELECTRONICS CO., LTD."),
508 DMI_MATCH(DMI_PRODUCT_NAME, "N128"),
509 DMI_MATCH(DMI_BOARD_NAME, "N128"),
510 },
511 .callback = dmi_check_cb,
512 },
513 {
514 .ident = "N130",
515 .matches = {
516 DMI_MATCH(DMI_SYS_VENDOR,
517 "SAMSUNG ELECTRONICS CO., LTD."),
518 DMI_MATCH(DMI_PRODUCT_NAME, "N130"),
519 DMI_MATCH(DMI_BOARD_NAME, "N130"),
520 },
521 .callback = dmi_check_cb,
522 },
523 {
524 .ident = "X125",
525 .matches = {
526 DMI_MATCH(DMI_SYS_VENDOR,
527 "SAMSUNG ELECTRONICS CO., LTD."),
528 DMI_MATCH(DMI_PRODUCT_NAME, "X125"),
529 DMI_MATCH(DMI_BOARD_NAME, "X125"),
530 },
531 .callback = dmi_check_cb,
532 },
533 {
534 .ident = "X120/X170",
535 .matches = {
536 DMI_MATCH(DMI_SYS_VENDOR,
537 "SAMSUNG ELECTRONICS CO., LTD."),
538 DMI_MATCH(DMI_PRODUCT_NAME, "X120/X170"),
539 DMI_MATCH(DMI_BOARD_NAME, "X120/X170"),
540 },
541 .callback = dmi_check_cb,
542 },
543 {
544 .ident = "NC10",
545 .matches = {
546 DMI_MATCH(DMI_SYS_VENDOR,
547 "SAMSUNG ELECTRONICS CO., LTD."),
548 DMI_MATCH(DMI_PRODUCT_NAME, "NC10"),
549 DMI_MATCH(DMI_BOARD_NAME, "NC10"),
550 },
551 .callback = dmi_check_cb,
552 },
553 {
554 .ident = "NP-Q45",
555 .matches = {
556 DMI_MATCH(DMI_SYS_VENDOR,
557 "SAMSUNG ELECTRONICS CO., LTD."),
558 DMI_MATCH(DMI_PRODUCT_NAME, "SQ45S70S"),
559 DMI_MATCH(DMI_BOARD_NAME, "SQ45S70S"),
560 },
561 .callback = dmi_check_cb,
562 },
563 {
564 .ident = "X360",
565 .matches = {
566 DMI_MATCH(DMI_SYS_VENDOR,
567 "SAMSUNG ELECTRONICS CO., LTD."),
568 DMI_MATCH(DMI_PRODUCT_NAME, "X360"),
569 DMI_MATCH(DMI_BOARD_NAME, "X360"),
570 },
571 .callback = dmi_check_cb,
572 },
573 {
574 .ident = "R410 Plus",
575 .matches = {
576 DMI_MATCH(DMI_SYS_VENDOR,
577 "SAMSUNG ELECTRONICS CO., LTD."),
578 DMI_MATCH(DMI_PRODUCT_NAME, "R410P"),
579 DMI_MATCH(DMI_BOARD_NAME, "R460"),
580 },
581 .callback = dmi_check_cb,
582 },
583 {
584 .ident = "R518",
585 .matches = {
586 DMI_MATCH(DMI_SYS_VENDOR,
587 "SAMSUNG ELECTRONICS CO., LTD."),
588 DMI_MATCH(DMI_PRODUCT_NAME, "R518"),
589 DMI_MATCH(DMI_BOARD_NAME, "R518"),
590 },
591 .callback = dmi_check_cb,
592 },
593 {
594 .ident = "R519/R719",
595 .matches = {
596 DMI_MATCH(DMI_SYS_VENDOR,
597 "SAMSUNG ELECTRONICS CO., LTD."),
598 DMI_MATCH(DMI_PRODUCT_NAME, "R519/R719"),
599 DMI_MATCH(DMI_BOARD_NAME, "R519/R719"),
600 },
601 .callback = dmi_check_cb,
602 },
603 {
604 .ident = "N150/N210/N220/N230",
605 .matches = {
606 DMI_MATCH(DMI_SYS_VENDOR,
607 "SAMSUNG ELECTRONICS CO., LTD."),
608 DMI_MATCH(DMI_PRODUCT_NAME, "N150/N210/N220/N230"),
609 DMI_MATCH(DMI_BOARD_NAME, "N150/N210/N220/N230"),
610 },
611 .callback = dmi_check_cb,
612 },
613 {
614 .ident = "N150P/N210P/N220P",
615 .matches = {
616 DMI_MATCH(DMI_SYS_VENDOR,
617 "SAMSUNG ELECTRONICS CO., LTD."),
618 DMI_MATCH(DMI_PRODUCT_NAME, "N150P/N210P/N220P"),
619 DMI_MATCH(DMI_BOARD_NAME, "N150P/N210P/N220P"),
620 },
621 .callback = dmi_check_cb,
622 },
623 {
624 .ident = "R530/R730",
625 .matches = {
626 DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
627 DMI_MATCH(DMI_PRODUCT_NAME, "R530/R730"),
628 DMI_MATCH(DMI_BOARD_NAME, "R530/R730"),
629 },
630 .callback = dmi_check_cb,
631 },
632 {
633 .ident = "NF110/NF210/NF310",
634 .matches = {
635 DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
636 DMI_MATCH(DMI_PRODUCT_NAME, "NF110/NF210/NF310"),
637 DMI_MATCH(DMI_BOARD_NAME, "NF110/NF210/NF310"),
638 },
639 .callback = dmi_check_cb,
640 },
641 {
642 .ident = "N145P/N250P/N260P",
643 .matches = {
644 DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
645 DMI_MATCH(DMI_PRODUCT_NAME, "N145P/N250P/N260P"),
646 DMI_MATCH(DMI_BOARD_NAME, "N145P/N250P/N260P"),
647 },
648 .callback = dmi_check_cb,
649 },
650 {
651 .ident = "R70/R71",
652 .matches = {
653 DMI_MATCH(DMI_SYS_VENDOR,
654 "SAMSUNG ELECTRONICS CO., LTD."),
655 DMI_MATCH(DMI_PRODUCT_NAME, "R70/R71"),
656 DMI_MATCH(DMI_BOARD_NAME, "R70/R71"),
657 },
658 .callback = dmi_check_cb,
659 },
660 {
661 .ident = "P460",
662 .matches = {
663 DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
664 DMI_MATCH(DMI_PRODUCT_NAME, "P460"),
665 DMI_MATCH(DMI_BOARD_NAME, "P460"),
666 },
667 .callback = dmi_check_cb,
668 },
669 { },
670};
671MODULE_DEVICE_TABLE(dmi, samsung_dmi_table);
672
673static int find_signature(void __iomem *memcheck, const char *testStr)
674{
675 int i = 0;
676 int loca;
677
678 for (loca = 0; loca < 0xffff; loca++) {
679 char temp = readb(memcheck + loca);
680
681 if (temp == testStr[i]) {
682 if (i == strlen(testStr)-1)
683 break;
684 ++i;
685 } else {
686 i = 0;
687 }
688 }
689 return loca;
690}
691
692static int __init samsung_init(void)
693{
694 struct backlight_properties props;
695 struct sabi_retval sretval;
696 unsigned int ifaceP;
697 int i;
698 int loca;
699 int retval;
700
701 mutex_init(&sabi_mutex);
702
703 if (!force && !dmi_check_system(samsung_dmi_table))
704 return -ENODEV;
705
706 f0000_segment = ioremap_nocache(0xf0000, 0xffff);
707 if (!f0000_segment) {
708 pr_err("Can't map the segment at 0xf0000\n");
709 return -EINVAL;
710 }
711
712 /* Try to find one of the signatures in memory to find the header */
713 for (i = 0; sabi_configs[i].test_string != 0; ++i) {
714 sabi_config = &sabi_configs[i];
715 loca = find_signature(f0000_segment, sabi_config->test_string);
716 if (loca != 0xffff)
717 break;
718 }
719
720 if (loca == 0xffff) {
721 pr_err("This computer does not support SABI\n");
722 goto error_no_signature;
723 }
724
725 /* point to the SMI port Number */
726 loca += 1;
727 sabi = (f0000_segment + loca);
728
729 if (debug) {
730 printk(KERN_DEBUG "This computer supports SABI==%x\n",
731 loca + 0xf0000 - 6);
732 printk(KERN_DEBUG "SABI header:\n");
733 printk(KERN_DEBUG " SMI Port Number = 0x%04x\n",
734 readw(sabi + sabi_config->header_offsets.port));
735 printk(KERN_DEBUG " SMI Interface Function = 0x%02x\n",
736 readb(sabi + sabi_config->header_offsets.iface_func));
737 printk(KERN_DEBUG " SMI enable memory buffer = 0x%02x\n",
738 readb(sabi + sabi_config->header_offsets.en_mem));
739 printk(KERN_DEBUG " SMI restore memory buffer = 0x%02x\n",
740 readb(sabi + sabi_config->header_offsets.re_mem));
741 printk(KERN_DEBUG " SABI data offset = 0x%04x\n",
742 readw(sabi + sabi_config->header_offsets.data_offset));
743 printk(KERN_DEBUG " SABI data segment = 0x%04x\n",
744 readw(sabi + sabi_config->header_offsets.data_segment));
745 }
746
747 /* Get a pointer to the SABI Interface */
748 ifaceP = (readw(sabi + sabi_config->header_offsets.data_segment) & 0x0ffff) << 4;
749 ifaceP += readw(sabi + sabi_config->header_offsets.data_offset) & 0x0ffff;
750 sabi_iface = ioremap_nocache(ifaceP, 16);
751 if (!sabi_iface) {
752 pr_err("Can't remap %x\n", ifaceP);
753 goto exit;
754 }
755 if (debug) {
756 printk(KERN_DEBUG "ifaceP = 0x%08x\n", ifaceP);
757 printk(KERN_DEBUG "sabi_iface = %p\n", sabi_iface);
758
759 test_backlight();
760 test_wireless();
761
762 retval = sabi_get_command(sabi_config->commands.get_brightness,
763 &sretval);
764 printk(KERN_DEBUG "brightness = 0x%02x\n", sretval.retval[0]);
765 }
766
767 /* Turn on "Linux" mode in the BIOS */
768 if (sabi_config->commands.set_linux != 0xff) {
769 retval = sabi_set_command(sabi_config->commands.set_linux,
770 0x81);
771 if (retval) {
772 pr_warn("Linux mode was not set!\n");
773 goto error_no_platform;
774 }
775 }
776
777 /* knock up a platform device to hang stuff off of */
778 sdev = platform_device_register_simple("samsung", -1, NULL, 0);
779 if (IS_ERR(sdev))
780 goto error_no_platform;
781
782 /* create a backlight device to talk to this one */
783 memset(&props, 0, sizeof(struct backlight_properties));
784 props.type = BACKLIGHT_PLATFORM;
785 props.max_brightness = sabi_config->max_brightness;
786 backlight_device = backlight_device_register("samsung", &sdev->dev,
787 NULL, &backlight_ops,
788 &props);
789 if (IS_ERR(backlight_device))
790 goto error_no_backlight;
791
792 backlight_device->props.brightness = read_brightness();
793 backlight_device->props.power = FB_BLANK_UNBLANK;
794 backlight_update_status(backlight_device);
795
796 retval = init_wireless(sdev);
797 if (retval)
798 goto error_no_rfk;
799
800 retval = device_create_file(&sdev->dev, &dev_attr_performance_level);
801 if (retval)
802 goto error_file_create;
803
804exit:
805 return 0;
806
807error_file_create:
808 destroy_wireless();
809
810error_no_rfk:
811 backlight_device_unregister(backlight_device);
812
813error_no_backlight:
814 platform_device_unregister(sdev);
815
816error_no_platform:
817 iounmap(sabi_iface);
818
819error_no_signature:
820 iounmap(f0000_segment);
821 return -EINVAL;
822}
823
824static void __exit samsung_exit(void)
825{
826 /* Turn off "Linux" mode in the BIOS */
827 if (sabi_config->commands.set_linux != 0xff)
828 sabi_set_command(sabi_config->commands.set_linux, 0x80);
829
830 device_remove_file(&sdev->dev, &dev_attr_performance_level);
831 backlight_device_unregister(backlight_device);
832 destroy_wireless();
833 iounmap(sabi_iface);
834 iounmap(f0000_segment);
835 platform_device_unregister(sdev);
836}
837
838module_init(samsung_init);
839module_exit(samsung_exit);
840
841MODULE_AUTHOR("Greg Kroah-Hartman <gregkh@suse.de>");
842MODULE_DESCRIPTION("Samsung Backlight driver");
843MODULE_LICENSE("GPL");
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index e3154ff7a39f..bbd182e178cb 100644
--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -42,6 +42,8 @@
42 * 42 *
43 */ 43 */
44 44
45#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
46
45#include <linux/kernel.h> 47#include <linux/kernel.h>
46#include <linux/module.h> 48#include <linux/module.h>
47#include <linux/moduleparam.h> 49#include <linux/moduleparam.h>
@@ -70,9 +72,10 @@
70#include <linux/miscdevice.h> 72#include <linux/miscdevice.h>
71#endif 73#endif
72 74
73#define DRV_PFX "sony-laptop: " 75#define dprintk(fmt, ...) \
74#define dprintk(msg...) do { \ 76do { \
75 if (debug) printk(KERN_WARNING DRV_PFX msg); \ 77 if (debug) \
78 pr_warn(fmt, ##__VA_ARGS__); \
76} while (0) 79} while (0)
77 80
78#define SONY_LAPTOP_DRIVER_VERSION "0.6" 81#define SONY_LAPTOP_DRIVER_VERSION "0.6"
@@ -124,6 +127,21 @@ MODULE_PARM_DESC(minor,
124 "default is -1 (automatic)"); 127 "default is -1 (automatic)");
125#endif 128#endif
126 129
130static int kbd_backlight; /* = 1 */
131module_param(kbd_backlight, int, 0444);
132MODULE_PARM_DESC(kbd_backlight,
133 "set this to 0 to disable keyboard backlight, "
134 "1 to enable it (default: 0)");
135
136static int kbd_backlight_timeout; /* = 0 */
137module_param(kbd_backlight_timeout, int, 0444);
138MODULE_PARM_DESC(kbd_backlight_timeout,
139 "set this to 0 to set the default 10 seconds timeout, "
140 "1 for 30 seconds, 2 for 60 seconds and 3 to disable timeout "
141 "(default: 0)");
142
143static void sony_nc_kbd_backlight_resume(void);
144
127enum sony_nc_rfkill { 145enum sony_nc_rfkill {
128 SONY_WIFI, 146 SONY_WIFI,
129 SONY_BLUETOOTH, 147 SONY_BLUETOOTH,
@@ -235,6 +253,7 @@ static int sony_laptop_input_index[] = {
235 57, /* 70 SONYPI_EVENT_VOLUME_DEC_PRESSED */ 253 57, /* 70 SONYPI_EVENT_VOLUME_DEC_PRESSED */
236 -1, /* 71 SONYPI_EVENT_BRIGHTNESS_PRESSED */ 254 -1, /* 71 SONYPI_EVENT_BRIGHTNESS_PRESSED */
237 58, /* 72 SONYPI_EVENT_MEDIA_PRESSED */ 255 58, /* 72 SONYPI_EVENT_MEDIA_PRESSED */
256 59, /* 72 SONYPI_EVENT_VENDOR_PRESSED */
238}; 257};
239 258
240static int sony_laptop_input_keycode_map[] = { 259static int sony_laptop_input_keycode_map[] = {
@@ -297,6 +316,7 @@ static int sony_laptop_input_keycode_map[] = {
297 KEY_VOLUMEUP, /* 56 SONYPI_EVENT_VOLUME_INC_PRESSED */ 316 KEY_VOLUMEUP, /* 56 SONYPI_EVENT_VOLUME_INC_PRESSED */
298 KEY_VOLUMEDOWN, /* 57 SONYPI_EVENT_VOLUME_DEC_PRESSED */ 317 KEY_VOLUMEDOWN, /* 57 SONYPI_EVENT_VOLUME_DEC_PRESSED */
299 KEY_MEDIA, /* 58 SONYPI_EVENT_MEDIA_PRESSED */ 318 KEY_MEDIA, /* 58 SONYPI_EVENT_MEDIA_PRESSED */
319 KEY_VENDOR, /* 59 SONYPI_EVENT_VENDOR_PRESSED */
300}; 320};
301 321
302/* release buttons after a short delay if pressed */ 322/* release buttons after a short delay if pressed */
@@ -400,7 +420,7 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device)
400 error = kfifo_alloc(&sony_laptop_input.fifo, 420 error = kfifo_alloc(&sony_laptop_input.fifo,
401 SONY_LAPTOP_BUF_SIZE, GFP_KERNEL); 421 SONY_LAPTOP_BUF_SIZE, GFP_KERNEL);
402 if (error) { 422 if (error) {
403 printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n"); 423 pr_err("kfifo_alloc failed\n");
404 goto err_dec_users; 424 goto err_dec_users;
405 } 425 }
406 426
@@ -589,7 +609,7 @@ struct sony_nc_value {
589 int value; /* current setting */ 609 int value; /* current setting */
590 int valid; /* Has ever been set */ 610 int valid; /* Has ever been set */
591 int debug; /* active only in debug mode ? */ 611 int debug; /* active only in debug mode ? */
592 struct device_attribute devattr; /* sysfs atribute */ 612 struct device_attribute devattr; /* sysfs attribute */
593}; 613};
594 614
595#define SNC_HANDLE_NAMES(_name, _values...) \ 615#define SNC_HANDLE_NAMES(_name, _values...) \
@@ -684,7 +704,7 @@ static int acpi_callgetfunc(acpi_handle handle, char *name, int *result)
684 return 0; 704 return 0;
685 } 705 }
686 706
687 printk(KERN_WARNING DRV_PFX "acpi_callreadfunc failed\n"); 707 pr_warn("acpi_callreadfunc failed\n");
688 708
689 return -1; 709 return -1;
690} 710}
@@ -710,8 +730,7 @@ static int acpi_callsetfunc(acpi_handle handle, char *name, int value,
710 if (status == AE_OK) { 730 if (status == AE_OK) {
711 if (result != NULL) { 731 if (result != NULL) {
712 if (out_obj.type != ACPI_TYPE_INTEGER) { 732 if (out_obj.type != ACPI_TYPE_INTEGER) {
713 printk(KERN_WARNING DRV_PFX "acpi_evaluate_object bad " 733 pr_warn("acpi_evaluate_object bad return type\n");
714 "return type\n");
715 return -1; 734 return -1;
716 } 735 }
717 *result = out_obj.integer.value; 736 *result = out_obj.integer.value;
@@ -719,34 +738,111 @@ static int acpi_callsetfunc(acpi_handle handle, char *name, int value,
719 return 0; 738 return 0;
720 } 739 }
721 740
722 printk(KERN_WARNING DRV_PFX "acpi_evaluate_object failed\n"); 741 pr_warn("acpi_evaluate_object failed\n");
723 742
724 return -1; 743 return -1;
725} 744}
726 745
727static int sony_find_snc_handle(int handle) 746struct sony_nc_handles {
747 u16 cap[0x10];
748 struct device_attribute devattr;
749};
750
751static struct sony_nc_handles *handles;
752
753static ssize_t sony_nc_handles_show(struct device *dev,
754 struct device_attribute *attr, char *buffer)
755{
756 ssize_t len = 0;
757 int i;
758
759 for (i = 0; i < ARRAY_SIZE(handles->cap); i++) {
760 len += snprintf(buffer + len, PAGE_SIZE - len, "0x%.4x ",
761 handles->cap[i]);
762 }
763 len += snprintf(buffer + len, PAGE_SIZE - len, "\n");
764
765 return len;
766}
767
768static int sony_nc_handles_setup(struct platform_device *pd)
728{ 769{
729 int i; 770 int i;
730 int result; 771 int result;
731 772
732 for (i = 0x20; i < 0x30; i++) { 773 handles = kzalloc(sizeof(*handles), GFP_KERNEL);
733 acpi_callsetfunc(sony_nc_acpi_handle, "SN00", i, &result); 774 if (!handles)
734 if (result == handle) 775 return -ENOMEM;
735 return i-0x20; 776
777 for (i = 0; i < ARRAY_SIZE(handles->cap); i++) {
778 if (!acpi_callsetfunc(sony_nc_acpi_handle,
779 "SN00", i + 0x20, &result)) {
780 dprintk("caching handle 0x%.4x (offset: 0x%.2x)\n",
781 result, i);
782 handles->cap[i] = result;
783 }
784 }
785
786 if (debug) {
787 sysfs_attr_init(&handles->devattr.attr);
788 handles->devattr.attr.name = "handles";
789 handles->devattr.attr.mode = S_IRUGO;
790 handles->devattr.show = sony_nc_handles_show;
791
792 /* allow reading capabilities via sysfs */
793 if (device_create_file(&pd->dev, &handles->devattr)) {
794 kfree(handles);
795 handles = NULL;
796 return -1;
797 }
798 }
799
800 return 0;
801}
802
803static int sony_nc_handles_cleanup(struct platform_device *pd)
804{
805 if (handles) {
806 if (debug)
807 device_remove_file(&pd->dev, &handles->devattr);
808 kfree(handles);
809 handles = NULL;
736 } 810 }
811 return 0;
812}
813
814static int sony_find_snc_handle(int handle)
815{
816 int i;
817
818 /* not initialized yet, return early */
819 if (!handles)
820 return -1;
737 821
822 for (i = 0; i < 0x10; i++) {
823 if (handles->cap[i] == handle) {
824 dprintk("found handle 0x%.4x (offset: 0x%.2x)\n",
825 handle, i);
826 return i;
827 }
828 }
829 dprintk("handle 0x%.4x not found\n", handle);
738 return -1; 830 return -1;
739} 831}
740 832
741static int sony_call_snc_handle(int handle, int argument, int *result) 833static int sony_call_snc_handle(int handle, int argument, int *result)
742{ 834{
835 int ret = 0;
743 int offset = sony_find_snc_handle(handle); 836 int offset = sony_find_snc_handle(handle);
744 837
745 if (offset < 0) 838 if (offset < 0)
746 return -1; 839 return -1;
747 840
748 return acpi_callsetfunc(sony_nc_acpi_handle, "SN07", offset | argument, 841 ret = acpi_callsetfunc(sony_nc_acpi_handle, "SN07", offset | argument,
749 result); 842 result);
843 dprintk("called SN07 with 0x%.4x (result: 0x%.4x)\n", offset | argument,
844 *result);
845 return ret;
750} 846}
751 847
752/* 848/*
@@ -839,6 +935,14 @@ static ssize_t sony_nc_sysfs_store(struct device *dev,
839/* 935/*
840 * Backlight device 936 * Backlight device
841 */ 937 */
938struct sony_backlight_props {
939 struct backlight_device *dev;
940 int handle;
941 u8 offset;
942 u8 maxlvl;
943};
944struct sony_backlight_props sony_bl_props;
945
842static int sony_backlight_update_status(struct backlight_device *bd) 946static int sony_backlight_update_status(struct backlight_device *bd)
843{ 947{
844 return acpi_callsetfunc(sony_nc_acpi_handle, "SBRT", 948 return acpi_callsetfunc(sony_nc_acpi_handle, "SBRT",
@@ -855,11 +959,40 @@ static int sony_backlight_get_brightness(struct backlight_device *bd)
855 return value - 1; 959 return value - 1;
856} 960}
857 961
858static struct backlight_device *sony_backlight_device; 962static int sony_nc_get_brightness_ng(struct backlight_device *bd)
859static struct backlight_ops sony_backlight_ops = { 963{
964 int result;
965 struct sony_backlight_props *sdev =
966 (struct sony_backlight_props *)bl_get_data(bd);
967
968 sony_call_snc_handle(sdev->handle, 0x0200, &result);
969
970 return (result & 0xff) - sdev->offset;
971}
972
973static int sony_nc_update_status_ng(struct backlight_device *bd)
974{
975 int value, result;
976 struct sony_backlight_props *sdev =
977 (struct sony_backlight_props *)bl_get_data(bd);
978
979 value = bd->props.brightness + sdev->offset;
980 if (sony_call_snc_handle(sdev->handle, 0x0100 | (value << 16), &result))
981 return -EIO;
982
983 return value;
984}
985
986static const struct backlight_ops sony_backlight_ops = {
987 .options = BL_CORE_SUSPENDRESUME,
860 .update_status = sony_backlight_update_status, 988 .update_status = sony_backlight_update_status,
861 .get_brightness = sony_backlight_get_brightness, 989 .get_brightness = sony_backlight_get_brightness,
862}; 990};
991static const struct backlight_ops sony_backlight_ng_ops = {
992 .options = BL_CORE_SUSPENDRESUME,
993 .update_status = sony_nc_update_status_ng,
994 .get_brightness = sony_nc_get_brightness_ng,
995};
863 996
864/* 997/*
865 * New SNC-only Vaios event mapping to driver known keys 998 * New SNC-only Vaios event mapping to driver known keys
@@ -894,10 +1027,18 @@ static struct sony_nc_event sony_100_events[] = {
894 { 0x0A, SONYPI_EVENT_FNKEY_RELEASED }, 1027 { 0x0A, SONYPI_EVENT_FNKEY_RELEASED },
895 { 0x8C, SONYPI_EVENT_FNKEY_F12 }, 1028 { 0x8C, SONYPI_EVENT_FNKEY_F12 },
896 { 0x0C, SONYPI_EVENT_FNKEY_RELEASED }, 1029 { 0x0C, SONYPI_EVENT_FNKEY_RELEASED },
1030 { 0x9d, SONYPI_EVENT_ZOOM_PRESSED },
1031 { 0x1d, SONYPI_EVENT_ANYBUTTON_RELEASED },
897 { 0x9f, SONYPI_EVENT_CD_EJECT_PRESSED }, 1032 { 0x9f, SONYPI_EVENT_CD_EJECT_PRESSED },
898 { 0x1f, SONYPI_EVENT_ANYBUTTON_RELEASED }, 1033 { 0x1f, SONYPI_EVENT_ANYBUTTON_RELEASED },
899 { 0xa1, SONYPI_EVENT_MEDIA_PRESSED }, 1034 { 0xa1, SONYPI_EVENT_MEDIA_PRESSED },
900 { 0x21, SONYPI_EVENT_ANYBUTTON_RELEASED }, 1035 { 0x21, SONYPI_EVENT_ANYBUTTON_RELEASED },
1036 { 0xa4, SONYPI_EVENT_CD_EJECT_PRESSED },
1037 { 0x24, SONYPI_EVENT_ANYBUTTON_RELEASED },
1038 { 0xa5, SONYPI_EVENT_VENDOR_PRESSED },
1039 { 0x25, SONYPI_EVENT_ANYBUTTON_RELEASED },
1040 { 0xa6, SONYPI_EVENT_HELP_PRESSED },
1041 { 0x26, SONYPI_EVENT_ANYBUTTON_RELEASED },
901 { 0, 0 }, 1042 { 0, 0 },
902}; 1043};
903 1044
@@ -962,10 +1103,8 @@ static void sony_nc_notify(struct acpi_device *device, u32 event)
962 } 1103 }
963 1104
964 if (!key_event->data) 1105 if (!key_event->data)
965 printk(KERN_INFO DRV_PFX 1106 pr_info("Unknown event: 0x%x 0x%x\n",
966 "Unknown event: 0x%x 0x%x\n", 1107 key_handle, ev);
967 key_handle,
968 ev);
969 else 1108 else
970 sony_laptop_report_input_event(ev); 1109 sony_laptop_report_input_event(ev);
971 } 1110 }
@@ -986,7 +1125,7 @@ static acpi_status sony_walk_callback(acpi_handle handle, u32 level,
986 struct acpi_device_info *info; 1125 struct acpi_device_info *info;
987 1126
988 if (ACPI_SUCCESS(acpi_get_object_info(handle, &info))) { 1127 if (ACPI_SUCCESS(acpi_get_object_info(handle, &info))) {
989 printk(KERN_WARNING DRV_PFX "method: name: %4.4s, args %X\n", 1128 pr_warn("method: name: %4.4s, args %X\n",
990 (char *)&info->name, info->param_count); 1129 (char *)&info->name, info->param_count);
991 1130
992 kfree(info); 1131 kfree(info);
@@ -1027,7 +1166,7 @@ static int sony_nc_resume(struct acpi_device *device)
1027 ret = acpi_callsetfunc(sony_nc_acpi_handle, *item->acpiset, 1166 ret = acpi_callsetfunc(sony_nc_acpi_handle, *item->acpiset,
1028 item->value, NULL); 1167 item->value, NULL);
1029 if (ret < 0) { 1168 if (ret < 0) {
1030 printk("%s: %d\n", __func__, ret); 1169 pr_err("%s: %d\n", __func__, ret);
1031 break; 1170 break;
1032 } 1171 }
1033 } 1172 }
@@ -1044,14 +1183,12 @@ static int sony_nc_resume(struct acpi_device *device)
1044 sony_nc_function_setup(device); 1183 sony_nc_function_setup(device);
1045 } 1184 }
1046 1185
1047 /* set the last requested brightness level */
1048 if (sony_backlight_device &&
1049 sony_backlight_update_status(sony_backlight_device) < 0)
1050 printk(KERN_WARNING DRV_PFX "unable to restore brightness level\n");
1051
1052 /* re-read rfkill state */ 1186 /* re-read rfkill state */
1053 sony_nc_rfkill_update(); 1187 sony_nc_rfkill_update();
1054 1188
1189 /* restore kbd backlight states */
1190 sony_nc_kbd_backlight_resume();
1191
1055 return 0; 1192 return 0;
1056} 1193}
1057 1194
@@ -1131,7 +1268,7 @@ static int sony_nc_setup_rfkill(struct acpi_device *device,
1131 return err; 1268 return err;
1132} 1269}
1133 1270
1134static void sony_nc_rfkill_update() 1271static void sony_nc_rfkill_update(void)
1135{ 1272{
1136 enum sony_nc_rfkill i; 1273 enum sony_nc_rfkill i;
1137 int result; 1274 int result;
@@ -1196,11 +1333,11 @@ static void sony_nc_rfkill_setup(struct acpi_device *device)
1196 1333
1197 device_enum = (union acpi_object *) buffer.pointer; 1334 device_enum = (union acpi_object *) buffer.pointer;
1198 if (!device_enum) { 1335 if (!device_enum) {
1199 pr_err("Invalid SN06 return object\n"); 1336 pr_err("No SN06 return object\n");
1200 goto out_no_enum; 1337 goto out_no_enum;
1201 } 1338 }
1202 if (device_enum->type != ACPI_TYPE_BUFFER) { 1339 if (device_enum->type != ACPI_TYPE_BUFFER) {
1203 pr_err("Invalid SN06 return object type 0x%.2x\n", 1340 pr_err("Invalid SN06 return object 0x%.2x\n",
1204 device_enum->type); 1341 device_enum->type);
1205 goto out_no_enum; 1342 goto out_no_enum;
1206 } 1343 }
@@ -1235,6 +1372,306 @@ out_no_enum:
1235 return; 1372 return;
1236} 1373}
1237 1374
1375/* Keyboard backlight feature */
1376#define KBDBL_HANDLER 0x137
1377#define KBDBL_PRESENT 0xB00
1378#define SET_MODE 0xC00
1379#define SET_STATE 0xD00
1380#define SET_TIMEOUT 0xE00
1381
1382struct kbd_backlight {
1383 int mode;
1384 int timeout;
1385 struct device_attribute mode_attr;
1386 struct device_attribute timeout_attr;
1387};
1388
1389static struct kbd_backlight *kbdbl_handle;
1390
1391static ssize_t __sony_nc_kbd_backlight_mode_set(u8 value)
1392{
1393 int result;
1394
1395 if (value > 1)
1396 return -EINVAL;
1397
1398 if (sony_call_snc_handle(KBDBL_HANDLER,
1399 (value << 0x10) | SET_MODE, &result))
1400 return -EIO;
1401
1402 /* Try to turn the light on/off immediately */
1403 sony_call_snc_handle(KBDBL_HANDLER, (value << 0x10) | SET_STATE,
1404 &result);
1405
1406 kbdbl_handle->mode = value;
1407
1408 return 0;
1409}
1410
1411static ssize_t sony_nc_kbd_backlight_mode_store(struct device *dev,
1412 struct device_attribute *attr,
1413 const char *buffer, size_t count)
1414{
1415 int ret = 0;
1416 unsigned long value;
1417
1418 if (count > 31)
1419 return -EINVAL;
1420
1421 if (strict_strtoul(buffer, 10, &value))
1422 return -EINVAL;
1423
1424 ret = __sony_nc_kbd_backlight_mode_set(value);
1425 if (ret < 0)
1426 return ret;
1427
1428 return count;
1429}
1430
1431static ssize_t sony_nc_kbd_backlight_mode_show(struct device *dev,
1432 struct device_attribute *attr, char *buffer)
1433{
1434 ssize_t count = 0;
1435 count = snprintf(buffer, PAGE_SIZE, "%d\n", kbdbl_handle->mode);
1436 return count;
1437}
1438
1439static int __sony_nc_kbd_backlight_timeout_set(u8 value)
1440{
1441 int result;
1442
1443 if (value > 3)
1444 return -EINVAL;
1445
1446 if (sony_call_snc_handle(KBDBL_HANDLER,
1447 (value << 0x10) | SET_TIMEOUT, &result))
1448 return -EIO;
1449
1450 kbdbl_handle->timeout = value;
1451
1452 return 0;
1453}
1454
1455static ssize_t sony_nc_kbd_backlight_timeout_store(struct device *dev,
1456 struct device_attribute *attr,
1457 const char *buffer, size_t count)
1458{
1459 int ret = 0;
1460 unsigned long value;
1461
1462 if (count > 31)
1463 return -EINVAL;
1464
1465 if (strict_strtoul(buffer, 10, &value))
1466 return -EINVAL;
1467
1468 ret = __sony_nc_kbd_backlight_timeout_set(value);
1469 if (ret < 0)
1470 return ret;
1471
1472 return count;
1473}
1474
1475static ssize_t sony_nc_kbd_backlight_timeout_show(struct device *dev,
1476 struct device_attribute *attr, char *buffer)
1477{
1478 ssize_t count = 0;
1479 count = snprintf(buffer, PAGE_SIZE, "%d\n", kbdbl_handle->timeout);
1480 return count;
1481}
1482
1483static int sony_nc_kbd_backlight_setup(struct platform_device *pd)
1484{
1485 int result;
1486
1487 if (sony_call_snc_handle(KBDBL_HANDLER, KBDBL_PRESENT, &result))
1488 return 0;
1489 if (!(result & 0x02))
1490 return 0;
1491
1492 kbdbl_handle = kzalloc(sizeof(*kbdbl_handle), GFP_KERNEL);
1493 if (!kbdbl_handle)
1494 return -ENOMEM;
1495
1496 sysfs_attr_init(&kbdbl_handle->mode_attr.attr);
1497 kbdbl_handle->mode_attr.attr.name = "kbd_backlight";
1498 kbdbl_handle->mode_attr.attr.mode = S_IRUGO | S_IWUSR;
1499 kbdbl_handle->mode_attr.show = sony_nc_kbd_backlight_mode_show;
1500 kbdbl_handle->mode_attr.store = sony_nc_kbd_backlight_mode_store;
1501
1502 sysfs_attr_init(&kbdbl_handle->timeout_attr.attr);
1503 kbdbl_handle->timeout_attr.attr.name = "kbd_backlight_timeout";
1504 kbdbl_handle->timeout_attr.attr.mode = S_IRUGO | S_IWUSR;
1505 kbdbl_handle->timeout_attr.show = sony_nc_kbd_backlight_timeout_show;
1506 kbdbl_handle->timeout_attr.store = sony_nc_kbd_backlight_timeout_store;
1507
1508 if (device_create_file(&pd->dev, &kbdbl_handle->mode_attr))
1509 goto outkzalloc;
1510
1511 if (device_create_file(&pd->dev, &kbdbl_handle->timeout_attr))
1512 goto outmode;
1513
1514 __sony_nc_kbd_backlight_mode_set(kbd_backlight);
1515 __sony_nc_kbd_backlight_timeout_set(kbd_backlight_timeout);
1516
1517 return 0;
1518
1519outmode:
1520 device_remove_file(&pd->dev, &kbdbl_handle->mode_attr);
1521outkzalloc:
1522 kfree(kbdbl_handle);
1523 kbdbl_handle = NULL;
1524 return -1;
1525}
1526
1527static int sony_nc_kbd_backlight_cleanup(struct platform_device *pd)
1528{
1529 if (kbdbl_handle) {
1530 int result;
1531
1532 device_remove_file(&pd->dev, &kbdbl_handle->mode_attr);
1533 device_remove_file(&pd->dev, &kbdbl_handle->timeout_attr);
1534
1535 /* restore the default hw behaviour */
1536 sony_call_snc_handle(KBDBL_HANDLER, 0x1000 | SET_MODE, &result);
1537 sony_call_snc_handle(KBDBL_HANDLER, SET_TIMEOUT, &result);
1538
1539 kfree(kbdbl_handle);
1540 }
1541 return 0;
1542}
1543
1544static void sony_nc_kbd_backlight_resume(void)
1545{
1546 int ignore = 0;
1547
1548 if (!kbdbl_handle)
1549 return;
1550
1551 if (kbdbl_handle->mode == 0)
1552 sony_call_snc_handle(KBDBL_HANDLER, SET_MODE, &ignore);
1553
1554 if (kbdbl_handle->timeout != 0)
1555 sony_call_snc_handle(KBDBL_HANDLER,
1556 (kbdbl_handle->timeout << 0x10) | SET_TIMEOUT,
1557 &ignore);
1558}
1559
1560static void sony_nc_backlight_ng_read_limits(int handle,
1561 struct sony_backlight_props *props)
1562{
1563 int offset;
1564 acpi_status status;
1565 u8 brlvl, i;
1566 u8 min = 0xff, max = 0x00;
1567 struct acpi_object_list params;
1568 union acpi_object in_obj;
1569 union acpi_object *lvl_enum;
1570 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
1571
1572 props->handle = handle;
1573 props->offset = 0;
1574 props->maxlvl = 0xff;
1575
1576 offset = sony_find_snc_handle(handle);
1577 if (offset < 0)
1578 return;
1579
1580 /* try to read the boundaries from ACPI tables, if we fail the above
1581 * defaults should be reasonable
1582 */
1583 params.count = 1;
1584 params.pointer = &in_obj;
1585 in_obj.type = ACPI_TYPE_INTEGER;
1586 in_obj.integer.value = offset;
1587 status = acpi_evaluate_object(sony_nc_acpi_handle, "SN06", &params,
1588 &buffer);
1589 if (ACPI_FAILURE(status))
1590 return;
1591
1592 lvl_enum = (union acpi_object *) buffer.pointer;
1593 if (!lvl_enum) {
1594 pr_err("No SN06 return object.");
1595 return;
1596 }
1597 if (lvl_enum->type != ACPI_TYPE_BUFFER) {
1598 pr_err("Invalid SN06 return object 0x%.2x\n",
1599 lvl_enum->type);
1600 goto out_invalid;
1601 }
1602
1603 /* the buffer lists brightness levels available, brightness levels are
1604 * from 0 to 8 in the array, other values are used by ALS control.
1605 */
1606 for (i = 0; i < 9 && i < lvl_enum->buffer.length; i++) {
1607
1608 brlvl = *(lvl_enum->buffer.pointer + i);
1609 dprintk("Brightness level: %d\n", brlvl);
1610
1611 if (!brlvl)
1612 break;
1613
1614 if (brlvl > max)
1615 max = brlvl;
1616 if (brlvl < min)
1617 min = brlvl;
1618 }
1619 props->offset = min;
1620 props->maxlvl = max;
1621 dprintk("Brightness levels: min=%d max=%d\n", props->offset,
1622 props->maxlvl);
1623
1624out_invalid:
1625 kfree(buffer.pointer);
1626 return;
1627}
1628
1629static void sony_nc_backlight_setup(void)
1630{
1631 acpi_handle unused;
1632 int max_brightness = 0;
1633 const struct backlight_ops *ops = NULL;
1634 struct backlight_properties props;
1635
1636 if (sony_find_snc_handle(0x12f) != -1) {
1637 ops = &sony_backlight_ng_ops;
1638 sony_nc_backlight_ng_read_limits(0x12f, &sony_bl_props);
1639 max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset;
1640
1641 } else if (sony_find_snc_handle(0x137) != -1) {
1642 ops = &sony_backlight_ng_ops;
1643 sony_nc_backlight_ng_read_limits(0x137, &sony_bl_props);
1644 max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset;
1645
1646 } else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT",
1647 &unused))) {
1648 ops = &sony_backlight_ops;
1649 max_brightness = SONY_MAX_BRIGHTNESS - 1;
1650
1651 } else
1652 return;
1653
1654 memset(&props, 0, sizeof(struct backlight_properties));
1655 props.type = BACKLIGHT_PLATFORM;
1656 props.max_brightness = max_brightness;
1657 sony_bl_props.dev = backlight_device_register("sony", NULL,
1658 &sony_bl_props,
1659 ops, &props);
1660
1661 if (IS_ERR(sony_bl_props.dev)) {
1662 pr_warn("unable to register backlight device\n");
1663 sony_bl_props.dev = NULL;
1664 } else
1665 sony_bl_props.dev->props.brightness =
1666 ops->get_brightness(sony_bl_props.dev);
1667}
1668
1669static void sony_nc_backlight_cleanup(void)
1670{
1671 if (sony_bl_props.dev)
1672 backlight_device_unregister(sony_bl_props.dev);
1673}
1674
1238static int sony_nc_add(struct acpi_device *device) 1675static int sony_nc_add(struct acpi_device *device)
1239{ 1676{
1240 acpi_status status; 1677 acpi_status status;
@@ -1242,8 +1679,7 @@ static int sony_nc_add(struct acpi_device *device)
1242 acpi_handle handle; 1679 acpi_handle handle;
1243 struct sony_nc_value *item; 1680 struct sony_nc_value *item;
1244 1681
1245 printk(KERN_INFO DRV_PFX "%s v%s.\n", 1682 pr_info("%s v%s\n", SONY_NC_DRIVER_NAME, SONY_LAPTOP_DRIVER_VERSION);
1246 SONY_NC_DRIVER_NAME, SONY_LAPTOP_DRIVER_VERSION);
1247 1683
1248 sony_nc_acpi_device = device; 1684 sony_nc_acpi_device = device;
1249 strcpy(acpi_device_class(device), "sony/hotkey"); 1685 strcpy(acpi_device_class(device), "sony/hotkey");
@@ -1259,13 +1695,18 @@ static int sony_nc_add(struct acpi_device *device)
1259 goto outwalk; 1695 goto outwalk;
1260 } 1696 }
1261 1697
1698 result = sony_pf_add();
1699 if (result)
1700 goto outpresent;
1701
1262 if (debug) { 1702 if (debug) {
1263 status = acpi_walk_namespace(ACPI_TYPE_METHOD, sony_nc_acpi_handle, 1703 status = acpi_walk_namespace(ACPI_TYPE_METHOD,
1264 1, sony_walk_callback, NULL, NULL, NULL); 1704 sony_nc_acpi_handle, 1, sony_walk_callback,
1705 NULL, NULL, NULL);
1265 if (ACPI_FAILURE(status)) { 1706 if (ACPI_FAILURE(status)) {
1266 printk(KERN_WARNING DRV_PFX "unable to walk acpi resources\n"); 1707 pr_warn("unable to walk acpi resources\n");
1267 result = -ENODEV; 1708 result = -ENODEV;
1268 goto outwalk; 1709 goto outpresent;
1269 } 1710 }
1270 } 1711 }
1271 1712
@@ -1278,6 +1719,12 @@ static int sony_nc_add(struct acpi_device *device)
1278 if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00", 1719 if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00",
1279 &handle))) { 1720 &handle))) {
1280 dprintk("Doing SNC setup\n"); 1721 dprintk("Doing SNC setup\n");
1722 result = sony_nc_handles_setup(sony_pf_device);
1723 if (result)
1724 goto outpresent;
1725 result = sony_nc_kbd_backlight_setup(sony_pf_device);
1726 if (result)
1727 goto outsnc;
1281 sony_nc_function_setup(device); 1728 sony_nc_function_setup(device);
1282 sony_nc_rfkill_setup(device); 1729 sony_nc_rfkill_setup(device);
1283 } 1730 }
@@ -1285,39 +1732,16 @@ static int sony_nc_add(struct acpi_device *device)
1285 /* setup input devices and helper fifo */ 1732 /* setup input devices and helper fifo */
1286 result = sony_laptop_setup_input(device); 1733 result = sony_laptop_setup_input(device);
1287 if (result) { 1734 if (result) {
1288 printk(KERN_ERR DRV_PFX 1735 pr_err("Unable to create input devices\n");
1289 "Unable to create input devices.\n"); 1736 goto outkbdbacklight;
1290 goto outwalk;
1291 } 1737 }
1292 1738
1293 if (acpi_video_backlight_support()) { 1739 if (acpi_video_backlight_support()) {
1294 printk(KERN_INFO DRV_PFX "brightness ignored, must be " 1740 pr_info("brightness ignored, must be controlled by ACPI video driver\n");
1295 "controlled by ACPI video driver\n"); 1741 } else {
1296 } else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT", 1742 sony_nc_backlight_setup();
1297 &handle))) {
1298 struct backlight_properties props;
1299 memset(&props, 0, sizeof(struct backlight_properties));
1300 props.max_brightness = SONY_MAX_BRIGHTNESS - 1;
1301 sony_backlight_device = backlight_device_register("sony", NULL,
1302 NULL,
1303 &sony_backlight_ops,
1304 &props);
1305
1306 if (IS_ERR(sony_backlight_device)) {
1307 printk(KERN_WARNING DRV_PFX "unable to register backlight device\n");
1308 sony_backlight_device = NULL;
1309 } else {
1310 sony_backlight_device->props.brightness =
1311 sony_backlight_get_brightness
1312 (sony_backlight_device);
1313 }
1314
1315 } 1743 }
1316 1744
1317 result = sony_pf_add();
1318 if (result)
1319 goto outbacklight;
1320
1321 /* create sony_pf sysfs attributes related to the SNC device */ 1745 /* create sony_pf sysfs attributes related to the SNC device */
1322 for (item = sony_nc_values; item->name; ++item) { 1746 for (item = sony_nc_values; item->name; ++item) {
1323 1747
@@ -1363,14 +1787,19 @@ static int sony_nc_add(struct acpi_device *device)
1363 for (item = sony_nc_values; item->name; ++item) { 1787 for (item = sony_nc_values; item->name; ++item) {
1364 device_remove_file(&sony_pf_device->dev, &item->devattr); 1788 device_remove_file(&sony_pf_device->dev, &item->devattr);
1365 } 1789 }
1366 sony_pf_remove(); 1790 sony_nc_backlight_cleanup();
1367
1368 outbacklight:
1369 if (sony_backlight_device)
1370 backlight_device_unregister(sony_backlight_device);
1371 1791
1372 sony_laptop_remove_input(); 1792 sony_laptop_remove_input();
1373 1793
1794 outkbdbacklight:
1795 sony_nc_kbd_backlight_cleanup(sony_pf_device);
1796
1797 outsnc:
1798 sony_nc_handles_cleanup(sony_pf_device);
1799
1800 outpresent:
1801 sony_pf_remove();
1802
1374 outwalk: 1803 outwalk:
1375 sony_nc_rfkill_cleanup(); 1804 sony_nc_rfkill_cleanup();
1376 return result; 1805 return result;
@@ -1380,8 +1809,7 @@ static int sony_nc_remove(struct acpi_device *device, int type)
1380{ 1809{
1381 struct sony_nc_value *item; 1810 struct sony_nc_value *item;
1382 1811
1383 if (sony_backlight_device) 1812 sony_nc_backlight_cleanup();
1384 backlight_device_unregister(sony_backlight_device);
1385 1813
1386 sony_nc_acpi_device = NULL; 1814 sony_nc_acpi_device = NULL;
1387 1815
@@ -1389,6 +1817,8 @@ static int sony_nc_remove(struct acpi_device *device, int type)
1389 device_remove_file(&sony_pf_device->dev, &item->devattr); 1817 device_remove_file(&sony_pf_device->dev, &item->devattr);
1390 } 1818 }
1391 1819
1820 sony_nc_kbd_backlight_cleanup(sony_pf_device);
1821 sony_nc_handles_cleanup(sony_pf_device);
1392 sony_pf_remove(); 1822 sony_pf_remove();
1393 sony_laptop_remove_input(); 1823 sony_laptop_remove_input();
1394 sony_nc_rfkill_cleanup(); 1824 sony_nc_rfkill_cleanup();
@@ -1427,7 +1857,6 @@ static struct acpi_driver sony_nc_driver = {
1427#define SONYPI_DEVICE_TYPE1 0x00000001 1857#define SONYPI_DEVICE_TYPE1 0x00000001
1428#define SONYPI_DEVICE_TYPE2 0x00000002 1858#define SONYPI_DEVICE_TYPE2 0x00000002
1429#define SONYPI_DEVICE_TYPE3 0x00000004 1859#define SONYPI_DEVICE_TYPE3 0x00000004
1430#define SONYPI_DEVICE_TYPE4 0x00000008
1431 1860
1432#define SONYPI_TYPE1_OFFSET 0x04 1861#define SONYPI_TYPE1_OFFSET 0x04
1433#define SONYPI_TYPE2_OFFSET 0x12 1862#define SONYPI_TYPE2_OFFSET 0x12
@@ -1573,8 +2002,8 @@ static struct sonypi_event sonypi_blueev[] = {
1573 2002
1574/* The set of possible wireless events */ 2003/* The set of possible wireless events */
1575static struct sonypi_event sonypi_wlessev[] = { 2004static struct sonypi_event sonypi_wlessev[] = {
1576 { 0x59, SONYPI_EVENT_WIRELESS_ON }, 2005 { 0x59, SONYPI_EVENT_IGNORE },
1577 { 0x5a, SONYPI_EVENT_WIRELESS_OFF }, 2006 { 0x5a, SONYPI_EVENT_IGNORE },
1578 { 0, 0 } 2007 { 0, 0 }
1579}; 2008};
1580 2009
@@ -1831,9 +2260,9 @@ out:
1831 if (pcidev) 2260 if (pcidev)
1832 pci_dev_put(pcidev); 2261 pci_dev_put(pcidev);
1833 2262
1834 printk(KERN_INFO DRV_PFX "detected Type%d model\n", 2263 pr_info("detected Type%d model\n",
1835 dev->model == SONYPI_DEVICE_TYPE1 ? 1 : 2264 dev->model == SONYPI_DEVICE_TYPE1 ? 1 :
1836 dev->model == SONYPI_DEVICE_TYPE2 ? 2 : 3); 2265 dev->model == SONYPI_DEVICE_TYPE2 ? 2 : 3);
1837} 2266}
1838 2267
1839/* camera tests and poweron/poweroff */ 2268/* camera tests and poweron/poweroff */
@@ -1879,7 +2308,7 @@ static int __sony_pic_camera_ready(void)
1879static int __sony_pic_camera_off(void) 2308static int __sony_pic_camera_off(void)
1880{ 2309{
1881 if (!camera) { 2310 if (!camera) {
1882 printk(KERN_WARNING DRV_PFX "camera control not enabled\n"); 2311 pr_warn("camera control not enabled\n");
1883 return -ENODEV; 2312 return -ENODEV;
1884 } 2313 }
1885 2314
@@ -1899,7 +2328,7 @@ static int __sony_pic_camera_on(void)
1899 int i, j, x; 2328 int i, j, x;
1900 2329
1901 if (!camera) { 2330 if (!camera) {
1902 printk(KERN_WARNING DRV_PFX "camera control not enabled\n"); 2331 pr_warn("camera control not enabled\n");
1903 return -ENODEV; 2332 return -ENODEV;
1904 } 2333 }
1905 2334
@@ -1922,7 +2351,7 @@ static int __sony_pic_camera_on(void)
1922 } 2351 }
1923 2352
1924 if (j == 0) { 2353 if (j == 0) {
1925 printk(KERN_WARNING DRV_PFX "failed to power on camera\n"); 2354 pr_warn("failed to power on camera\n");
1926 return -ENODEV; 2355 return -ENODEV;
1927 } 2356 }
1928 2357
@@ -1978,8 +2407,7 @@ int sony_pic_camera_command(int command, u8 value)
1978 ITERATIONS_SHORT); 2407 ITERATIONS_SHORT);
1979 break; 2408 break;
1980 default: 2409 default:
1981 printk(KERN_ERR DRV_PFX "sony_pic_camera_command invalid: %d\n", 2410 pr_err("sony_pic_camera_command invalid: %d\n", command);
1982 command);
1983 break; 2411 break;
1984 } 2412 }
1985 mutex_unlock(&spic_dev.lock); 2413 mutex_unlock(&spic_dev.lock);
@@ -2236,7 +2664,7 @@ static long sonypi_misc_ioctl(struct file *fp, unsigned int cmd,
2236 mutex_lock(&spic_dev.lock); 2664 mutex_lock(&spic_dev.lock);
2237 switch (cmd) { 2665 switch (cmd) {
2238 case SONYPI_IOCGBRT: 2666 case SONYPI_IOCGBRT:
2239 if (sony_backlight_device == NULL) { 2667 if (sony_bl_props.dev == NULL) {
2240 ret = -EIO; 2668 ret = -EIO;
2241 break; 2669 break;
2242 } 2670 }
@@ -2249,7 +2677,7 @@ static long sonypi_misc_ioctl(struct file *fp, unsigned int cmd,
2249 ret = -EFAULT; 2677 ret = -EFAULT;
2250 break; 2678 break;
2251 case SONYPI_IOCSBRT: 2679 case SONYPI_IOCSBRT:
2252 if (sony_backlight_device == NULL) { 2680 if (sony_bl_props.dev == NULL) {
2253 ret = -EIO; 2681 ret = -EIO;
2254 break; 2682 break;
2255 } 2683 }
@@ -2263,8 +2691,8 @@ static long sonypi_misc_ioctl(struct file *fp, unsigned int cmd,
2263 break; 2691 break;
2264 } 2692 }
2265 /* sync the backlight device status */ 2693 /* sync the backlight device status */
2266 sony_backlight_device->props.brightness = 2694 sony_bl_props.dev->props.brightness =
2267 sony_backlight_get_brightness(sony_backlight_device); 2695 sony_backlight_get_brightness(sony_bl_props.dev);
2268 break; 2696 break;
2269 case SONYPI_IOCGBAT1CAP: 2697 case SONYPI_IOCGBAT1CAP:
2270 if (ec_read16(SONYPI_BAT1_FULL, &val16)) { 2698 if (ec_read16(SONYPI_BAT1_FULL, &val16)) {
@@ -2360,6 +2788,7 @@ static const struct file_operations sonypi_misc_fops = {
2360 .release = sonypi_misc_release, 2788 .release = sonypi_misc_release,
2361 .fasync = sonypi_misc_fasync, 2789 .fasync = sonypi_misc_fasync,
2362 .unlocked_ioctl = sonypi_misc_ioctl, 2790 .unlocked_ioctl = sonypi_misc_ioctl,
2791 .llseek = noop_llseek,
2363}; 2792};
2364 2793
2365static struct miscdevice sonypi_misc_device = { 2794static struct miscdevice sonypi_misc_device = {
@@ -2384,7 +2813,7 @@ static int sonypi_compat_init(void)
2384 error = 2813 error =
2385 kfifo_alloc(&sonypi_compat.fifo, SONY_LAPTOP_BUF_SIZE, GFP_KERNEL); 2814 kfifo_alloc(&sonypi_compat.fifo, SONY_LAPTOP_BUF_SIZE, GFP_KERNEL);
2386 if (error) { 2815 if (error) {
2387 printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n"); 2816 pr_err("kfifo_alloc failed\n");
2388 return error; 2817 return error;
2389 } 2818 }
2390 2819
@@ -2394,12 +2823,12 @@ static int sonypi_compat_init(void)
2394 sonypi_misc_device.minor = minor; 2823 sonypi_misc_device.minor = minor;
2395 error = misc_register(&sonypi_misc_device); 2824 error = misc_register(&sonypi_misc_device);
2396 if (error) { 2825 if (error) {
2397 printk(KERN_ERR DRV_PFX "misc_register failed\n"); 2826 pr_err("misc_register failed\n");
2398 goto err_free_kfifo; 2827 goto err_free_kfifo;
2399 } 2828 }
2400 if (minor == -1) 2829 if (minor == -1)
2401 printk(KERN_INFO DRV_PFX "device allocated minor is %d\n", 2830 pr_info("device allocated minor is %d\n",
2402 sonypi_misc_device.minor); 2831 sonypi_misc_device.minor);
2403 2832
2404 return 0; 2833 return 0;
2405 2834
@@ -2458,9 +2887,8 @@ sony_pic_read_possible_resource(struct acpi_resource *resource, void *context)
2458 } 2887 }
2459 for (i = 0; i < p->interrupt_count; i++) { 2888 for (i = 0; i < p->interrupt_count; i++) {
2460 if (!p->interrupts[i]) { 2889 if (!p->interrupts[i]) {
2461 printk(KERN_WARNING DRV_PFX 2890 pr_warn("Invalid IRQ %d\n",
2462 "Invalid IRQ %d\n", 2891 p->interrupts[i]);
2463 p->interrupts[i]);
2464 continue; 2892 continue;
2465 } 2893 }
2466 interrupt = kzalloc(sizeof(*interrupt), 2894 interrupt = kzalloc(sizeof(*interrupt),
@@ -2498,14 +2926,14 @@ sony_pic_read_possible_resource(struct acpi_resource *resource, void *context)
2498 ioport->io2.address_length); 2926 ioport->io2.address_length);
2499 } 2927 }
2500 else { 2928 else {
2501 printk(KERN_ERR DRV_PFX "Unknown SPIC Type, more than 2 IO Ports\n"); 2929 pr_err("Unknown SPIC Type, more than 2 IO Ports\n");
2502 return AE_ERROR; 2930 return AE_ERROR;
2503 } 2931 }
2504 return AE_OK; 2932 return AE_OK;
2505 } 2933 }
2506 default: 2934 default:
2507 dprintk("Resource %d isn't an IRQ nor an IO port\n", 2935 dprintk("Resource %d isn't an IRQ nor an IO port\n",
2508 resource->type); 2936 resource->type);
2509 2937
2510 case ACPI_RESOURCE_TYPE_END_TAG: 2938 case ACPI_RESOURCE_TYPE_END_TAG:
2511 return AE_OK; 2939 return AE_OK;
@@ -2526,7 +2954,7 @@ static int sony_pic_possible_resources(struct acpi_device *device)
2526 dprintk("Evaluating _STA\n"); 2954 dprintk("Evaluating _STA\n");
2527 result = acpi_bus_get_status(device); 2955 result = acpi_bus_get_status(device);
2528 if (result) { 2956 if (result) {
2529 printk(KERN_WARNING DRV_PFX "Unable to read status\n"); 2957 pr_warn("Unable to read status\n");
2530 goto end; 2958 goto end;
2531 } 2959 }
2532 2960
@@ -2542,9 +2970,7 @@ static int sony_pic_possible_resources(struct acpi_device *device)
2542 status = acpi_walk_resources(device->handle, METHOD_NAME__PRS, 2970 status = acpi_walk_resources(device->handle, METHOD_NAME__PRS,
2543 sony_pic_read_possible_resource, &spic_dev); 2971 sony_pic_read_possible_resource, &spic_dev);
2544 if (ACPI_FAILURE(status)) { 2972 if (ACPI_FAILURE(status)) {
2545 printk(KERN_WARNING DRV_PFX 2973 pr_warn("Failure evaluating %s\n", METHOD_NAME__PRS);
2546 "Failure evaluating %s\n",
2547 METHOD_NAME__PRS);
2548 result = -ENODEV; 2974 result = -ENODEV;
2549 } 2975 }
2550end: 2976end:
@@ -2657,7 +3083,7 @@ static int sony_pic_enable(struct acpi_device *device,
2657 3083
2658 /* check for total failure */ 3084 /* check for total failure */
2659 if (ACPI_FAILURE(status)) { 3085 if (ACPI_FAILURE(status)) {
2660 printk(KERN_ERR DRV_PFX "Error evaluating _SRS\n"); 3086 pr_err("Error evaluating _SRS\n");
2661 result = -ENODEV; 3087 result = -ENODEV;
2662 goto end; 3088 goto end;
2663 } 3089 }
@@ -2713,6 +3139,9 @@ static irqreturn_t sony_pic_irq(int irq, void *dev_id)
2713 if (ev == dev->event_types[i].events[j].data) { 3139 if (ev == dev->event_types[i].events[j].data) {
2714 device_event = 3140 device_event =
2715 dev->event_types[i].events[j].event; 3141 dev->event_types[i].events[j].event;
3142 /* some events may require ignoring */
3143 if (!device_event)
3144 return IRQ_HANDLED;
2716 goto found; 3145 goto found;
2717 } 3146 }
2718 } 3147 }
@@ -2732,7 +3161,6 @@ found:
2732 sony_laptop_report_input_event(device_event); 3161 sony_laptop_report_input_event(device_event);
2733 acpi_bus_generate_proc_event(dev->acpi_dev, 1, device_event); 3162 acpi_bus_generate_proc_event(dev->acpi_dev, 1, device_event);
2734 sonypi_compat_report_event(device_event); 3163 sonypi_compat_report_event(device_event);
2735
2736 return IRQ_HANDLED; 3164 return IRQ_HANDLED;
2737} 3165}
2738 3166
@@ -2747,7 +3175,7 @@ static int sony_pic_remove(struct acpi_device *device, int type)
2747 struct sony_pic_irq *irq, *tmp_irq; 3175 struct sony_pic_irq *irq, *tmp_irq;
2748 3176
2749 if (sony_pic_disable(device)) { 3177 if (sony_pic_disable(device)) {
2750 printk(KERN_ERR DRV_PFX "Couldn't disable device.\n"); 3178 pr_err("Couldn't disable device\n");
2751 return -ENXIO; 3179 return -ENXIO;
2752 } 3180 }
2753 3181
@@ -2787,8 +3215,7 @@ static int sony_pic_add(struct acpi_device *device)
2787 struct sony_pic_ioport *io, *tmp_io; 3215 struct sony_pic_ioport *io, *tmp_io;
2788 struct sony_pic_irq *irq, *tmp_irq; 3216 struct sony_pic_irq *irq, *tmp_irq;
2789 3217
2790 printk(KERN_INFO DRV_PFX "%s v%s.\n", 3218 pr_info("%s v%s\n", SONY_PIC_DRIVER_NAME, SONY_LAPTOP_DRIVER_VERSION);
2791 SONY_PIC_DRIVER_NAME, SONY_LAPTOP_DRIVER_VERSION);
2792 3219
2793 spic_dev.acpi_dev = device; 3220 spic_dev.acpi_dev = device;
2794 strcpy(acpi_device_class(device), "sony/hotkey"); 3221 strcpy(acpi_device_class(device), "sony/hotkey");
@@ -2798,16 +3225,14 @@ static int sony_pic_add(struct acpi_device *device)
2798 /* read _PRS resources */ 3225 /* read _PRS resources */
2799 result = sony_pic_possible_resources(device); 3226 result = sony_pic_possible_resources(device);
2800 if (result) { 3227 if (result) {
2801 printk(KERN_ERR DRV_PFX 3228 pr_err("Unable to read possible resources\n");
2802 "Unable to read possible resources.\n");
2803 goto err_free_resources; 3229 goto err_free_resources;
2804 } 3230 }
2805 3231
2806 /* setup input devices and helper fifo */ 3232 /* setup input devices and helper fifo */
2807 result = sony_laptop_setup_input(device); 3233 result = sony_laptop_setup_input(device);
2808 if (result) { 3234 if (result) {
2809 printk(KERN_ERR DRV_PFX 3235 pr_err("Unable to create input devices\n");
2810 "Unable to create input devices.\n");
2811 goto err_free_resources; 3236 goto err_free_resources;
2812 } 3237 }
2813 3238
@@ -2817,7 +3242,7 @@ static int sony_pic_add(struct acpi_device *device)
2817 /* request io port */ 3242 /* request io port */
2818 list_for_each_entry_reverse(io, &spic_dev.ioports, list) { 3243 list_for_each_entry_reverse(io, &spic_dev.ioports, list) {
2819 if (request_region(io->io1.minimum, io->io1.address_length, 3244 if (request_region(io->io1.minimum, io->io1.address_length,
2820 "Sony Programable I/O Device")) { 3245 "Sony Programmable I/O Device")) {
2821 dprintk("I/O port1: 0x%.4x (0x%.4x) + 0x%.2x\n", 3246 dprintk("I/O port1: 0x%.4x (0x%.4x) + 0x%.2x\n",
2822 io->io1.minimum, io->io1.maximum, 3247 io->io1.minimum, io->io1.maximum,
2823 io->io1.address_length); 3248 io->io1.address_length);
@@ -2825,7 +3250,7 @@ static int sony_pic_add(struct acpi_device *device)
2825 if (io->io2.minimum) { 3250 if (io->io2.minimum) {
2826 if (request_region(io->io2.minimum, 3251 if (request_region(io->io2.minimum,
2827 io->io2.address_length, 3252 io->io2.address_length,
2828 "Sony Programable I/O Device")) { 3253 "Sony Programmable I/O Device")) {
2829 dprintk("I/O port2: 0x%.4x (0x%.4x) + 0x%.2x\n", 3254 dprintk("I/O port2: 0x%.4x (0x%.4x) + 0x%.2x\n",
2830 io->io2.minimum, io->io2.maximum, 3255 io->io2.minimum, io->io2.maximum,
2831 io->io2.address_length); 3256 io->io2.address_length);
@@ -2848,7 +3273,7 @@ static int sony_pic_add(struct acpi_device *device)
2848 } 3273 }
2849 } 3274 }
2850 if (!spic_dev.cur_ioport) { 3275 if (!spic_dev.cur_ioport) {
2851 printk(KERN_ERR DRV_PFX "Failed to request_region.\n"); 3276 pr_err("Failed to request_region\n");
2852 result = -ENODEV; 3277 result = -ENODEV;
2853 goto err_remove_compat; 3278 goto err_remove_compat;
2854 } 3279 }
@@ -2868,7 +3293,7 @@ static int sony_pic_add(struct acpi_device *device)
2868 } 3293 }
2869 } 3294 }
2870 if (!spic_dev.cur_irq) { 3295 if (!spic_dev.cur_irq) {
2871 printk(KERN_ERR DRV_PFX "Failed to request_irq.\n"); 3296 pr_err("Failed to request_irq\n");
2872 result = -ENODEV; 3297 result = -ENODEV;
2873 goto err_release_region; 3298 goto err_release_region;
2874 } 3299 }
@@ -2876,7 +3301,7 @@ static int sony_pic_add(struct acpi_device *device)
2876 /* set resource status _SRS */ 3301 /* set resource status _SRS */
2877 result = sony_pic_enable(device, spic_dev.cur_ioport, spic_dev.cur_irq); 3302 result = sony_pic_enable(device, spic_dev.cur_ioport, spic_dev.cur_irq);
2878 if (result) { 3303 if (result) {
2879 printk(KERN_ERR DRV_PFX "Couldn't enable device.\n"); 3304 pr_err("Couldn't enable device\n");
2880 goto err_free_irq; 3305 goto err_free_irq;
2881 } 3306 }
2882 3307
@@ -2985,8 +3410,7 @@ static int __init sony_laptop_init(void)
2985 if (!no_spic && dmi_check_system(sonypi_dmi_table)) { 3410 if (!no_spic && dmi_check_system(sonypi_dmi_table)) {
2986 result = acpi_bus_register_driver(&sony_pic_driver); 3411 result = acpi_bus_register_driver(&sony_pic_driver);
2987 if (result) { 3412 if (result) {
2988 printk(KERN_ERR DRV_PFX 3413 pr_err("Unable to register SPIC driver\n");
2989 "Unable to register SPIC driver.");
2990 goto out; 3414 goto out;
2991 } 3415 }
2992 spic_drv_registered = 1; 3416 spic_drv_registered = 1;
@@ -2994,7 +3418,7 @@ static int __init sony_laptop_init(void)
2994 3418
2995 result = acpi_bus_register_driver(&sony_nc_driver); 3419 result = acpi_bus_register_driver(&sony_nc_driver);
2996 if (result) { 3420 if (result) {
2997 printk(KERN_ERR DRV_PFX "Unable to register SNC driver."); 3421 pr_err("Unable to register SNC driver\n");
2998 goto out_unregister_pic; 3422 goto out_unregister_pic;
2999 } 3423 }
3000 3424
diff --git a/drivers/platform/x86/tc1100-wmi.c b/drivers/platform/x86/tc1100-wmi.c
index 1fe0f1feff71..e24f5ae475af 100644
--- a/drivers/platform/x86/tc1100-wmi.c
+++ b/drivers/platform/x86/tc1100-wmi.c
@@ -25,6 +25,8 @@
25 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 25 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
26 */ 26 */
27 27
28#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
29
28#include <linux/kernel.h> 30#include <linux/kernel.h>
29#include <linux/module.h> 31#include <linux/module.h>
30#include <linux/slab.h> 32#include <linux/slab.h>
@@ -40,9 +42,6 @@
40#define TC1100_INSTANCE_WIRELESS 1 42#define TC1100_INSTANCE_WIRELESS 1
41#define TC1100_INSTANCE_JOGDIAL 2 43#define TC1100_INSTANCE_JOGDIAL 2
42 44
43#define TC1100_LOGPREFIX "tc1100-wmi: "
44#define TC1100_INFO KERN_INFO TC1100_LOGPREFIX
45
46MODULE_AUTHOR("Jamey Hicks, Carlos Corbacho"); 45MODULE_AUTHOR("Jamey Hicks, Carlos Corbacho");
47MODULE_DESCRIPTION("HP Compaq TC1100 Tablet WMI Extras"); 46MODULE_DESCRIPTION("HP Compaq TC1100 Tablet WMI Extras");
48MODULE_LICENSE("GPL"); 47MODULE_LICENSE("GPL");
@@ -162,7 +161,7 @@ set_bool_##value(struct device *dev, struct device_attribute *attr, \
162 return -EINVAL; \ 161 return -EINVAL; \
163 return count; \ 162 return count; \
164} \ 163} \
165static DEVICE_ATTR(value, S_IWUGO | S_IRUGO | S_IWUSR, \ 164static DEVICE_ATTR(value, S_IRUGO | S_IWUSR, \
166 show_bool_##value, set_bool_##value); 165 show_bool_##value, set_bool_##value);
167 166
168show_set_bool(wireless, TC1100_INSTANCE_WIRELESS); 167show_set_bool(wireless, TC1100_INSTANCE_WIRELESS);
@@ -264,7 +263,7 @@ static int __init tc1100_init(void)
264 if (error) 263 if (error)
265 goto err_device_del; 264 goto err_device_del;
266 265
267 printk(TC1100_INFO "HP Compaq TC1100 Tablet WMI Extras loaded\n"); 266 pr_info("HP Compaq TC1100 Tablet WMI Extras loaded\n");
268 return 0; 267 return 0;
269 268
270 err_device_del: 269 err_device_del:
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index 2d61186ad5a2..26c5b117df22 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -21,6 +21,8 @@
21 * 02110-1301, USA. 21 * 02110-1301, USA.
22 */ 22 */
23 23
24#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
25
24#define TPACPI_VERSION "0.24" 26#define TPACPI_VERSION "0.24"
25#define TPACPI_SYSFS_VERSION 0x020700 27#define TPACPI_SYSFS_VERSION 0x020700
26 28
@@ -128,7 +130,8 @@ enum {
128}; 130};
129 131
130/* ACPI HIDs */ 132/* ACPI HIDs */
131#define TPACPI_ACPI_HKEY_HID "IBM0068" 133#define TPACPI_ACPI_IBM_HKEY_HID "IBM0068"
134#define TPACPI_ACPI_LENOVO_HKEY_HID "LEN0068"
132#define TPACPI_ACPI_EC_HID "PNP0C09" 135#define TPACPI_ACPI_EC_HID "PNP0C09"
133 136
134/* Input IDs */ 137/* Input IDs */
@@ -181,6 +184,10 @@ enum tpacpi_hkey_event_t {
181 184
182 /* Misc bay events */ 185 /* Misc bay events */
183 TP_HKEY_EV_OPTDRV_EJ = 0x3006, /* opt. drive tray ejected */ 186 TP_HKEY_EV_OPTDRV_EJ = 0x3006, /* opt. drive tray ejected */
187 TP_HKEY_EV_HOTPLUG_DOCK = 0x4010, /* docked into hotplug dock
188 or port replicator */
189 TP_HKEY_EV_HOTPLUG_UNDOCK = 0x4011, /* undocked from hotplug
190 dock or port replicator */
184 191
185 /* User-interface events */ 192 /* User-interface events */
186 TP_HKEY_EV_LID_CLOSE = 0x5001, /* laptop lid closed */ 193 TP_HKEY_EV_LID_CLOSE = 0x5001, /* laptop lid closed */
@@ -191,6 +198,10 @@ enum tpacpi_hkey_event_t {
191 TP_HKEY_EV_PEN_REMOVED = 0x500c, /* tablet pen removed */ 198 TP_HKEY_EV_PEN_REMOVED = 0x500c, /* tablet pen removed */
192 TP_HKEY_EV_BRGHT_CHANGED = 0x5010, /* backlight control event */ 199 TP_HKEY_EV_BRGHT_CHANGED = 0x5010, /* backlight control event */
193 200
201 /* Key-related user-interface events */
202 TP_HKEY_EV_KEY_NUMLOCK = 0x6000, /* NumLock key pressed */
203 TP_HKEY_EV_KEY_FN = 0x6005, /* Fn key pressed? E420 */
204
194 /* Thermal events */ 205 /* Thermal events */
195 TP_HKEY_EV_ALARM_BAT_HOT = 0x6011, /* battery too hot */ 206 TP_HKEY_EV_ALARM_BAT_HOT = 0x6011, /* battery too hot */
196 TP_HKEY_EV_ALARM_BAT_XHOT = 0x6012, /* battery critically hot */ 207 TP_HKEY_EV_ALARM_BAT_XHOT = 0x6012, /* battery critically hot */
@@ -198,6 +209,10 @@ enum tpacpi_hkey_event_t {
198 TP_HKEY_EV_ALARM_SENSOR_XHOT = 0x6022, /* sensor critically hot */ 209 TP_HKEY_EV_ALARM_SENSOR_XHOT = 0x6022, /* sensor critically hot */
199 TP_HKEY_EV_THM_TABLE_CHANGED = 0x6030, /* thermal table changed */ 210 TP_HKEY_EV_THM_TABLE_CHANGED = 0x6030, /* thermal table changed */
200 211
212 TP_HKEY_EV_UNK_6040 = 0x6040, /* Related to AC change?
213 some sort of APM hint,
214 W520 */
215
201 /* Misc */ 216 /* Misc */
202 TP_HKEY_EV_RFKILL_CHANGED = 0x7000, /* rfkill switch changed */ 217 TP_HKEY_EV_RFKILL_CHANGED = 0x7000, /* rfkill switch changed */
203}; 218};
@@ -223,17 +238,6 @@ enum tpacpi_hkey_event_t {
223 238
224#define TPACPI_MAX_ACPI_ARGS 3 239#define TPACPI_MAX_ACPI_ARGS 3
225 240
226/* printk headers */
227#define TPACPI_LOG TPACPI_FILE ": "
228#define TPACPI_EMERG KERN_EMERG TPACPI_LOG
229#define TPACPI_ALERT KERN_ALERT TPACPI_LOG
230#define TPACPI_CRIT KERN_CRIT TPACPI_LOG
231#define TPACPI_ERR KERN_ERR TPACPI_LOG
232#define TPACPI_WARN KERN_WARNING TPACPI_LOG
233#define TPACPI_NOTICE KERN_NOTICE TPACPI_LOG
234#define TPACPI_INFO KERN_INFO TPACPI_LOG
235#define TPACPI_DEBUG KERN_DEBUG TPACPI_LOG
236
237/* Debugging printk groups */ 241/* Debugging printk groups */
238#define TPACPI_DBG_ALL 0xffff 242#define TPACPI_DBG_ALL 0xffff
239#define TPACPI_DBG_DISCLOSETASK 0x8000 243#define TPACPI_DBG_DISCLOSETASK 0x8000
@@ -388,34 +392,36 @@ static int tpacpi_uwb_emulstate;
388 * Debugging helpers 392 * Debugging helpers
389 */ 393 */
390 394
391#define dbg_printk(a_dbg_level, format, arg...) \ 395#define dbg_printk(a_dbg_level, format, arg...) \
392 do { if (dbg_level & (a_dbg_level)) \ 396do { \
393 printk(TPACPI_DEBUG "%s: " format, __func__ , ## arg); \ 397 if (dbg_level & (a_dbg_level)) \
394 } while (0) 398 printk(KERN_DEBUG pr_fmt("%s: " format), \
399 __func__, ##arg); \
400} while (0)
395 401
396#ifdef CONFIG_THINKPAD_ACPI_DEBUG 402#ifdef CONFIG_THINKPAD_ACPI_DEBUG
397#define vdbg_printk dbg_printk 403#define vdbg_printk dbg_printk
398static const char *str_supported(int is_supported); 404static const char *str_supported(int is_supported);
399#else 405#else
400#define vdbg_printk(a_dbg_level, format, arg...) \ 406static inline const char *str_supported(int is_supported) { return ""; }
401 do { } while (0) 407#define vdbg_printk(a_dbg_level, format, arg...) \
408 no_printk(format, ##arg)
402#endif 409#endif
403 410
404static void tpacpi_log_usertask(const char * const what) 411static void tpacpi_log_usertask(const char * const what)
405{ 412{
406 printk(TPACPI_DEBUG "%s: access by process with PID %d\n", 413 printk(KERN_DEBUG pr_fmt("%s: access by process with PID %d\n"),
407 what, task_tgid_vnr(current)); 414 what, task_tgid_vnr(current));
408} 415}
409 416
410#define tpacpi_disclose_usertask(what, format, arg...) \ 417#define tpacpi_disclose_usertask(what, format, arg...) \
411 do { \ 418do { \
412 if (unlikely( \ 419 if (unlikely((dbg_level & TPACPI_DBG_DISCLOSETASK) && \
413 (dbg_level & TPACPI_DBG_DISCLOSETASK) && \ 420 (tpacpi_lifecycle == TPACPI_LIFE_RUNNING))) { \
414 (tpacpi_lifecycle == TPACPI_LIFE_RUNNING))) { \ 421 printk(KERN_DEBUG pr_fmt("%s: PID %d: " format), \
415 printk(TPACPI_DEBUG "%s: PID %d: " format, \ 422 what, task_tgid_vnr(current), ## arg); \
416 what, task_tgid_vnr(current), ## arg); \ 423 } \
417 } \ 424} while (0)
418 } while (0)
419 425
420/* 426/*
421 * Quirk handling helpers 427 * Quirk handling helpers
@@ -534,15 +540,6 @@ TPACPI_HANDLE(hkey, ec, "\\_SB.HKEY", /* 600e/x, 770e, 770x */
534 "HKEY", /* all others */ 540 "HKEY", /* all others */
535 ); /* 570 */ 541 ); /* 570 */
536 542
537TPACPI_HANDLE(vid, root, "\\_SB.PCI.AGP.VGA", /* 570 */
538 "\\_SB.PCI0.AGP0.VID0", /* 600e/x, 770x */
539 "\\_SB.PCI0.VID0", /* 770e */
540 "\\_SB.PCI0.VID", /* A21e, G4x, R50e, X30, X40 */
541 "\\_SB.PCI0.AGP.VGA", /* X100e and a few others */
542 "\\_SB.PCI0.AGP.VID", /* all others */
543 ); /* R30, R31 */
544
545
546/************************************************************************* 543/*************************************************************************
547 * ACPI helpers 544 * ACPI helpers
548 */ 545 */
@@ -562,7 +559,7 @@ static int acpi_evalf(acpi_handle handle,
562 int quiet; 559 int quiet;
563 560
564 if (!*fmt) { 561 if (!*fmt) {
565 printk(TPACPI_ERR "acpi_evalf() called with empty format\n"); 562 pr_err("acpi_evalf() called with empty format\n");
566 return 0; 563 return 0;
567 } 564 }
568 565
@@ -587,8 +584,9 @@ static int acpi_evalf(acpi_handle handle,
587 break; 584 break;
588 /* add more types as needed */ 585 /* add more types as needed */
589 default: 586 default:
590 printk(TPACPI_ERR "acpi_evalf() called " 587 pr_err("acpi_evalf() called "
591 "with invalid format character '%c'\n", c); 588 "with invalid format character '%c'\n", c);
589 va_end(ap);
592 return 0; 590 return 0;
593 } 591 }
594 } 592 }
@@ -615,13 +613,13 @@ static int acpi_evalf(acpi_handle handle,
615 break; 613 break;
616 /* add more types as needed */ 614 /* add more types as needed */
617 default: 615 default:
618 printk(TPACPI_ERR "acpi_evalf() called " 616 pr_err("acpi_evalf() called "
619 "with invalid format character '%c'\n", res_type); 617 "with invalid format character '%c'\n", res_type);
620 return 0; 618 return 0;
621 } 619 }
622 620
623 if (!success && !quiet) 621 if (!success && !quiet)
624 printk(TPACPI_ERR "acpi_evalf(%s, %s, ...) failed: %s\n", 622 pr_err("acpi_evalf(%s, %s, ...) failed: %s\n",
625 method, fmt0, acpi_format_exception(status)); 623 method, fmt0, acpi_format_exception(status));
626 624
627 return success; 625 return success;
@@ -765,8 +763,7 @@ static int __init setup_acpi_notify(struct ibm_struct *ibm)
765 763
766 rc = acpi_bus_get_device(*ibm->acpi->handle, &ibm->acpi->device); 764 rc = acpi_bus_get_device(*ibm->acpi->handle, &ibm->acpi->device);
767 if (rc < 0) { 765 if (rc < 0) {
768 printk(TPACPI_ERR "acpi_bus_get_device(%s) failed: %d\n", 766 pr_err("acpi_bus_get_device(%s) failed: %d\n", ibm->name, rc);
769 ibm->name, rc);
770 return -ENODEV; 767 return -ENODEV;
771 } 768 }
772 769
@@ -779,12 +776,10 @@ static int __init setup_acpi_notify(struct ibm_struct *ibm)
779 ibm->acpi->type, dispatch_acpi_notify, ibm); 776 ibm->acpi->type, dispatch_acpi_notify, ibm);
780 if (ACPI_FAILURE(status)) { 777 if (ACPI_FAILURE(status)) {
781 if (status == AE_ALREADY_EXISTS) { 778 if (status == AE_ALREADY_EXISTS) {
782 printk(TPACPI_NOTICE 779 pr_notice("another device driver is already "
783 "another device driver is already " 780 "handling %s events\n", ibm->name);
784 "handling %s events\n", ibm->name);
785 } else { 781 } else {
786 printk(TPACPI_ERR 782 pr_err("acpi_install_notify_handler(%s) failed: %s\n",
787 "acpi_install_notify_handler(%s) failed: %s\n",
788 ibm->name, acpi_format_exception(status)); 783 ibm->name, acpi_format_exception(status));
789 } 784 }
790 return -ENODEV; 785 return -ENODEV;
@@ -809,8 +804,7 @@ static int __init register_tpacpi_subdriver(struct ibm_struct *ibm)
809 804
810 ibm->acpi->driver = kzalloc(sizeof(struct acpi_driver), GFP_KERNEL); 805 ibm->acpi->driver = kzalloc(sizeof(struct acpi_driver), GFP_KERNEL);
811 if (!ibm->acpi->driver) { 806 if (!ibm->acpi->driver) {
812 printk(TPACPI_ERR 807 pr_err("failed to allocate memory for ibm->acpi->driver\n");
813 "failed to allocate memory for ibm->acpi->driver\n");
814 return -ENOMEM; 808 return -ENOMEM;
815 } 809 }
816 810
@@ -821,7 +815,7 @@ static int __init register_tpacpi_subdriver(struct ibm_struct *ibm)
821 815
822 rc = acpi_bus_register_driver(ibm->acpi->driver); 816 rc = acpi_bus_register_driver(ibm->acpi->driver);
823 if (rc < 0) { 817 if (rc < 0) {
824 printk(TPACPI_ERR "acpi_bus_register_driver(%s) failed: %d\n", 818 pr_err("acpi_bus_register_driver(%s) failed: %d\n",
825 ibm->name, rc); 819 ibm->name, rc);
826 kfree(ibm->acpi->driver); 820 kfree(ibm->acpi->driver);
827 ibm->acpi->driver = NULL; 821 ibm->acpi->driver = NULL;
@@ -1079,15 +1073,14 @@ static int parse_strtoul(const char *buf,
1079static void tpacpi_disable_brightness_delay(void) 1073static void tpacpi_disable_brightness_delay(void)
1080{ 1074{
1081 if (acpi_evalf(hkey_handle, NULL, "PWMS", "qvd", 0)) 1075 if (acpi_evalf(hkey_handle, NULL, "PWMS", "qvd", 0))
1082 printk(TPACPI_NOTICE 1076 pr_notice("ACPI backlight control delay disabled\n");
1083 "ACPI backlight control delay disabled\n");
1084} 1077}
1085 1078
1086static void printk_deprecated_attribute(const char * const what, 1079static void printk_deprecated_attribute(const char * const what,
1087 const char * const details) 1080 const char * const details)
1088{ 1081{
1089 tpacpi_log_usertask("deprecated sysfs attribute"); 1082 tpacpi_log_usertask("deprecated sysfs attribute");
1090 printk(TPACPI_WARN "WARNING: sysfs attribute %s is deprecated and " 1083 pr_warn("WARNING: sysfs attribute %s is deprecated and "
1091 "will be removed. %s\n", 1084 "will be removed. %s\n",
1092 what, details); 1085 what, details);
1093} 1086}
@@ -1262,8 +1255,7 @@ static int __init tpacpi_new_rfkill(const enum tpacpi_rfk_id id,
1262 &tpacpi_rfk_rfkill_ops, 1255 &tpacpi_rfk_rfkill_ops,
1263 atp_rfk); 1256 atp_rfk);
1264 if (!atp_rfk || !atp_rfk->rfkill) { 1257 if (!atp_rfk || !atp_rfk->rfkill) {
1265 printk(TPACPI_ERR 1258 pr_err("failed to allocate memory for rfkill class\n");
1266 "failed to allocate memory for rfkill class\n");
1267 kfree(atp_rfk); 1259 kfree(atp_rfk);
1268 return -ENOMEM; 1260 return -ENOMEM;
1269 } 1261 }
@@ -1273,9 +1265,8 @@ static int __init tpacpi_new_rfkill(const enum tpacpi_rfk_id id,
1273 1265
1274 sw_status = (tp_rfkops->get_status)(); 1266 sw_status = (tp_rfkops->get_status)();
1275 if (sw_status < 0) { 1267 if (sw_status < 0) {
1276 printk(TPACPI_ERR 1268 pr_err("failed to read initial state for %s, error %d\n",
1277 "failed to read initial state for %s, error %d\n", 1269 name, sw_status);
1278 name, sw_status);
1279 } else { 1270 } else {
1280 sw_state = (sw_status == TPACPI_RFK_RADIO_OFF); 1271 sw_state = (sw_status == TPACPI_RFK_RADIO_OFF);
1281 if (set_default) { 1272 if (set_default) {
@@ -1289,9 +1280,7 @@ static int __init tpacpi_new_rfkill(const enum tpacpi_rfk_id id,
1289 1280
1290 res = rfkill_register(atp_rfk->rfkill); 1281 res = rfkill_register(atp_rfk->rfkill);
1291 if (res < 0) { 1282 if (res < 0) {
1292 printk(TPACPI_ERR 1283 pr_err("failed to register %s rfkill switch: %d\n", name, res);
1293 "failed to register %s rfkill switch: %d\n",
1294 name, res);
1295 rfkill_destroy(atp_rfk->rfkill); 1284 rfkill_destroy(atp_rfk->rfkill);
1296 kfree(atp_rfk); 1285 kfree(atp_rfk);
1297 return res; 1286 return res;
@@ -1299,7 +1288,7 @@ static int __init tpacpi_new_rfkill(const enum tpacpi_rfk_id id,
1299 1288
1300 tpacpi_rfkill_switches[id] = atp_rfk; 1289 tpacpi_rfkill_switches[id] = atp_rfk;
1301 1290
1302 printk(TPACPI_INFO "rfkill switch %s: radio is %sblocked\n", 1291 pr_info("rfkill switch %s: radio is %sblocked\n",
1303 name, (sw_state || hw_state) ? "" : "un"); 1292 name, (sw_state || hw_state) ? "" : "un");
1304 return 0; 1293 return 0;
1305} 1294}
@@ -1823,10 +1812,8 @@ static void __init tpacpi_check_outdated_fw(void)
1823 * broken, or really stable to begin with, so it is 1812 * broken, or really stable to begin with, so it is
1824 * best if the user upgrades the firmware anyway. 1813 * best if the user upgrades the firmware anyway.
1825 */ 1814 */
1826 printk(TPACPI_WARN 1815 pr_warn("WARNING: Outdated ThinkPad BIOS/EC firmware\n");
1827 "WARNING: Outdated ThinkPad BIOS/EC firmware\n"); 1816 pr_warn("WARNING: This firmware may be missing critical bug "
1828 printk(TPACPI_WARN
1829 "WARNING: This firmware may be missing critical bug "
1830 "fixes and/or important features\n"); 1817 "fixes and/or important features\n");
1831 } 1818 }
1832} 1819}
@@ -2115,9 +2102,7 @@ void static hotkey_mask_warn_incomplete_mask(void)
2115 (hotkey_all_mask | TPACPI_HKEY_NVRAM_KNOWN_MASK); 2102 (hotkey_all_mask | TPACPI_HKEY_NVRAM_KNOWN_MASK);
2116 2103
2117 if (wantedmask) 2104 if (wantedmask)
2118 printk(TPACPI_NOTICE 2105 pr_notice("required events 0x%08x not enabled!\n", wantedmask);
2119 "required events 0x%08x not enabled!\n",
2120 wantedmask);
2121} 2106}
2122 2107
2123/* 2108/*
@@ -2155,10 +2140,9 @@ static int hotkey_mask_set(u32 mask)
2155 * a given event. 2140 * a given event.
2156 */ 2141 */
2157 if (!hotkey_mask_get() && !rc && (fwmask & ~hotkey_acpi_mask)) { 2142 if (!hotkey_mask_get() && !rc && (fwmask & ~hotkey_acpi_mask)) {
2158 printk(TPACPI_NOTICE 2143 pr_notice("asked for hotkey mask 0x%08x, but "
2159 "asked for hotkey mask 0x%08x, but " 2144 "firmware forced it to 0x%08x\n",
2160 "firmware forced it to 0x%08x\n", 2145 fwmask, hotkey_acpi_mask);
2161 fwmask, hotkey_acpi_mask);
2162 } 2146 }
2163 2147
2164 if (tpacpi_lifecycle != TPACPI_LIFE_EXITING) 2148 if (tpacpi_lifecycle != TPACPI_LIFE_EXITING)
@@ -2182,13 +2166,11 @@ static int hotkey_user_mask_set(const u32 mask)
2182 (mask == 0xffff || mask == 0xffffff || 2166 (mask == 0xffff || mask == 0xffffff ||
2183 mask == 0xffffffff)) { 2167 mask == 0xffffffff)) {
2184 tp_warned.hotkey_mask_ff = 1; 2168 tp_warned.hotkey_mask_ff = 1;
2185 printk(TPACPI_NOTICE 2169 pr_notice("setting the hotkey mask to 0x%08x is likely "
2186 "setting the hotkey mask to 0x%08x is likely " 2170 "not the best way to go about it\n", mask);
2187 "not the best way to go about it\n", mask); 2171 pr_notice("please consider using the driver defaults, "
2188 printk(TPACPI_NOTICE 2172 "and refer to up-to-date thinkpad-acpi "
2189 "please consider using the driver defaults, " 2173 "documentation\n");
2190 "and refer to up-to-date thinkpad-acpi "
2191 "documentation\n");
2192 } 2174 }
2193 2175
2194 /* Try to enable what the user asked for, plus whatever we need. 2176 /* Try to enable what the user asked for, plus whatever we need.
@@ -2274,16 +2256,12 @@ static void tpacpi_input_send_key(const unsigned int scancode)
2274 if (keycode != KEY_RESERVED) { 2256 if (keycode != KEY_RESERVED) {
2275 mutex_lock(&tpacpi_inputdev_send_mutex); 2257 mutex_lock(&tpacpi_inputdev_send_mutex);
2276 2258
2259 input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN, scancode);
2277 input_report_key(tpacpi_inputdev, keycode, 1); 2260 input_report_key(tpacpi_inputdev, keycode, 1);
2278 if (keycode == KEY_UNKNOWN)
2279 input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN,
2280 scancode);
2281 input_sync(tpacpi_inputdev); 2261 input_sync(tpacpi_inputdev);
2282 2262
2263 input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN, scancode);
2283 input_report_key(tpacpi_inputdev, keycode, 0); 2264 input_report_key(tpacpi_inputdev, keycode, 0);
2284 if (keycode == KEY_UNKNOWN)
2285 input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN,
2286 scancode);
2287 input_sync(tpacpi_inputdev); 2265 input_sync(tpacpi_inputdev);
2288 2266
2289 mutex_unlock(&tpacpi_inputdev_send_mutex); 2267 mutex_unlock(&tpacpi_inputdev_send_mutex);
@@ -2410,7 +2388,7 @@ static void hotkey_compare_and_issue_event(struct tp_nvram_state *oldn,
2410 * This code is supposed to duplicate the IBM firmware behaviour: 2388 * This code is supposed to duplicate the IBM firmware behaviour:
2411 * - Pressing MUTE issues mute hotkey message, even when already mute 2389 * - Pressing MUTE issues mute hotkey message, even when already mute
2412 * - Pressing Volume up/down issues volume up/down hotkey messages, 2390 * - Pressing Volume up/down issues volume up/down hotkey messages,
2413 * even when already at maximum or minumum volume 2391 * even when already at maximum or minimum volume
2414 * - The act of unmuting issues volume up/down notification, 2392 * - The act of unmuting issues volume up/down notification,
2415 * depending which key was used to unmute 2393 * depending which key was used to unmute
2416 * 2394 *
@@ -2576,8 +2554,7 @@ static void hotkey_poll_setup(const bool may_warn)
2576 NULL, TPACPI_NVRAM_KTHREAD_NAME); 2554 NULL, TPACPI_NVRAM_KTHREAD_NAME);
2577 if (IS_ERR(tpacpi_hotkey_task)) { 2555 if (IS_ERR(tpacpi_hotkey_task)) {
2578 tpacpi_hotkey_task = NULL; 2556 tpacpi_hotkey_task = NULL;
2579 printk(TPACPI_ERR 2557 pr_err("could not create kernel thread "
2580 "could not create kernel thread "
2581 "for hotkey polling\n"); 2558 "for hotkey polling\n");
2582 } 2559 }
2583 } 2560 }
@@ -2585,11 +2562,10 @@ static void hotkey_poll_setup(const bool may_warn)
2585 hotkey_poll_stop_sync(); 2562 hotkey_poll_stop_sync();
2586 if (may_warn && (poll_driver_mask || poll_user_mask) && 2563 if (may_warn && (poll_driver_mask || poll_user_mask) &&
2587 hotkey_poll_freq == 0) { 2564 hotkey_poll_freq == 0) {
2588 printk(TPACPI_NOTICE 2565 pr_notice("hot keys 0x%08x and/or events 0x%08x "
2589 "hot keys 0x%08x and/or events 0x%08x " 2566 "require polling, which is currently "
2590 "require polling, which is currently " 2567 "disabled\n",
2591 "disabled\n", 2568 poll_user_mask, poll_driver_mask);
2592 poll_user_mask, poll_driver_mask);
2593 } 2569 }
2594 } 2570 }
2595} 2571}
@@ -2813,13 +2789,13 @@ static ssize_t hotkey_source_mask_store(struct device *dev,
2813 mutex_unlock(&hotkey_mutex); 2789 mutex_unlock(&hotkey_mutex);
2814 2790
2815 if (rc < 0) 2791 if (rc < 0)
2816 printk(TPACPI_ERR "hotkey_source_mask: failed to update the" 2792 pr_err("hotkey_source_mask: "
2817 "firmware event mask!\n"); 2793 "failed to update the firmware event mask!\n");
2818 2794
2819 if (r_ev) 2795 if (r_ev)
2820 printk(TPACPI_NOTICE "hotkey_source_mask: " 2796 pr_notice("hotkey_source_mask: "
2821 "some important events were disabled: " 2797 "some important events were disabled: 0x%04x\n",
2822 "0x%04x\n", r_ev); 2798 r_ev);
2823 2799
2824 tpacpi_disclose_usertask("hotkey_source_mask", "set to 0x%08lx\n", t); 2800 tpacpi_disclose_usertask("hotkey_source_mask", "set to 0x%08lx\n", t);
2825 2801
@@ -2993,7 +2969,7 @@ static void tpacpi_send_radiosw_update(void)
2993 * rfkill input events, or we will race the rfkill core input 2969 * rfkill input events, or we will race the rfkill core input
2994 * handler. 2970 * handler.
2995 * 2971 *
2996 * tpacpi_inputdev_send_mutex works as a syncronization point 2972 * tpacpi_inputdev_send_mutex works as a synchronization point
2997 * for the above. 2973 * for the above.
2998 * 2974 *
2999 * We optimize to avoid numerous calls to hotkey_get_wlsw. 2975 * We optimize to avoid numerous calls to hotkey_get_wlsw.
@@ -3050,8 +3026,7 @@ static void hotkey_exit(void)
3050 if (((tp_features.hotkey_mask && 3026 if (((tp_features.hotkey_mask &&
3051 hotkey_mask_set(hotkey_orig_mask)) | 3027 hotkey_mask_set(hotkey_orig_mask)) |
3052 hotkey_status_set(false)) != 0) 3028 hotkey_status_set(false)) != 0)
3053 printk(TPACPI_ERR 3029 pr_err("failed to restore hot key mask "
3054 "failed to restore hot key mask "
3055 "to BIOS defaults\n"); 3030 "to BIOS defaults\n");
3056} 3031}
3057 3032
@@ -3290,10 +3265,9 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
3290 for HKEY interface version 0x100 */ 3265 for HKEY interface version 0x100 */
3291 if (acpi_evalf(hkey_handle, &hkeyv, "MHKV", "qd")) { 3266 if (acpi_evalf(hkey_handle, &hkeyv, "MHKV", "qd")) {
3292 if ((hkeyv >> 8) != 1) { 3267 if ((hkeyv >> 8) != 1) {
3293 printk(TPACPI_ERR "unknown version of the " 3268 pr_err("unknown version of the HKEY interface: 0x%x\n",
3294 "HKEY interface: 0x%x\n", hkeyv); 3269 hkeyv);
3295 printk(TPACPI_ERR "please report this to %s\n", 3270 pr_err("please report this to %s\n", TPACPI_MAIL);
3296 TPACPI_MAIL);
3297 } else { 3271 } else {
3298 /* 3272 /*
3299 * MHKV 0x100 in A31, R40, R40e, 3273 * MHKV 0x100 in A31, R40, R40e,
@@ -3306,8 +3280,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
3306 /* Paranoia check AND init hotkey_all_mask */ 3280 /* Paranoia check AND init hotkey_all_mask */
3307 if (!acpi_evalf(hkey_handle, &hotkey_all_mask, 3281 if (!acpi_evalf(hkey_handle, &hotkey_all_mask,
3308 "MHKA", "qd")) { 3282 "MHKA", "qd")) {
3309 printk(TPACPI_ERR 3283 pr_err("missing MHKA handler, "
3310 "missing MHKA handler, "
3311 "please report this to %s\n", 3284 "please report this to %s\n",
3312 TPACPI_MAIL); 3285 TPACPI_MAIL);
3313 /* Fallback: pre-init for FN+F3,F4,F12 */ 3286 /* Fallback: pre-init for FN+F3,F4,F12 */
@@ -3345,16 +3318,14 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
3345 if (dbg_wlswemul) { 3318 if (dbg_wlswemul) {
3346 tp_features.hotkey_wlsw = 1; 3319 tp_features.hotkey_wlsw = 1;
3347 radiosw_state = !!tpacpi_wlsw_emulstate; 3320 radiosw_state = !!tpacpi_wlsw_emulstate;
3348 printk(TPACPI_INFO 3321 pr_info("radio switch emulation enabled\n");
3349 "radio switch emulation enabled\n");
3350 } else 3322 } else
3351#endif 3323#endif
3352 /* Not all thinkpads have a hardware radio switch */ 3324 /* Not all thinkpads have a hardware radio switch */
3353 if (acpi_evalf(hkey_handle, &status, "WLSW", "qd")) { 3325 if (acpi_evalf(hkey_handle, &status, "WLSW", "qd")) {
3354 tp_features.hotkey_wlsw = 1; 3326 tp_features.hotkey_wlsw = 1;
3355 radiosw_state = !!status; 3327 radiosw_state = !!status;
3356 printk(TPACPI_INFO 3328 pr_info("radio switch found; radios are %s\n",
3357 "radio switch found; radios are %s\n",
3358 enabled(status, 0)); 3329 enabled(status, 0));
3359 } 3330 }
3360 if (tp_features.hotkey_wlsw) 3331 if (tp_features.hotkey_wlsw)
@@ -3365,8 +3336,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
3365 if (!res && acpi_evalf(hkey_handle, &status, "MHKG", "qd")) { 3336 if (!res && acpi_evalf(hkey_handle, &status, "MHKG", "qd")) {
3366 tp_features.hotkey_tablet = 1; 3337 tp_features.hotkey_tablet = 1;
3367 tabletsw_state = !!(status & TP_HOTKEY_TABLET_MASK); 3338 tabletsw_state = !!(status & TP_HOTKEY_TABLET_MASK);
3368 printk(TPACPI_INFO 3339 pr_info("possible tablet mode switch found; "
3369 "possible tablet mode switch found; "
3370 "ThinkPad in %s mode\n", 3340 "ThinkPad in %s mode\n",
3371 (tabletsw_state) ? "tablet" : "laptop"); 3341 (tabletsw_state) ? "tablet" : "laptop");
3372 res = add_to_attr_set(hotkey_dev_attributes, 3342 res = add_to_attr_set(hotkey_dev_attributes,
@@ -3384,8 +3354,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
3384 hotkey_keycode_map = kmalloc(TPACPI_HOTKEY_MAP_SIZE, 3354 hotkey_keycode_map = kmalloc(TPACPI_HOTKEY_MAP_SIZE,
3385 GFP_KERNEL); 3355 GFP_KERNEL);
3386 if (!hotkey_keycode_map) { 3356 if (!hotkey_keycode_map) {
3387 printk(TPACPI_ERR 3357 pr_err("failed to allocate memory for key map\n");
3388 "failed to allocate memory for key map\n");
3389 res = -ENOMEM; 3358 res = -ENOMEM;
3390 goto err_exit; 3359 goto err_exit;
3391 } 3360 }
@@ -3428,13 +3397,11 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
3428 * userspace. tpacpi_detect_brightness_capabilities() must have 3397 * userspace. tpacpi_detect_brightness_capabilities() must have
3429 * been called before this point */ 3398 * been called before this point */
3430 if (tp_features.bright_acpimode && acpi_video_backlight_support()) { 3399 if (tp_features.bright_acpimode && acpi_video_backlight_support()) {
3431 printk(TPACPI_INFO 3400 pr_info("This ThinkPad has standard ACPI backlight "
3432 "This ThinkPad has standard ACPI backlight " 3401 "brightness control, supported by the ACPI "
3433 "brightness control, supported by the ACPI " 3402 "video driver\n");
3434 "video driver\n"); 3403 pr_notice("Disabling thinkpad-acpi brightness events "
3435 printk(TPACPI_NOTICE 3404 "by default...\n");
3436 "Disabling thinkpad-acpi brightness events "
3437 "by default...\n");
3438 3405
3439 /* Disable brightness up/down on Lenovo thinkpads when 3406 /* Disable brightness up/down on Lenovo thinkpads when
3440 * ACPI is handling them, otherwise it is plain impossible 3407 * ACPI is handling them, otherwise it is plain impossible
@@ -3541,8 +3508,7 @@ static bool hotkey_notify_wakeup(const u32 hkey,
3541 3508
3542 case TP_HKEY_EV_WKUP_S3_BATLOW: /* Battery on critical low level/S3 */ 3509 case TP_HKEY_EV_WKUP_S3_BATLOW: /* Battery on critical low level/S3 */
3543 case TP_HKEY_EV_WKUP_S4_BATLOW: /* Battery on critical low level/S4 */ 3510 case TP_HKEY_EV_WKUP_S4_BATLOW: /* Battery on critical low level/S4 */
3544 printk(TPACPI_ALERT 3511 pr_alert("EMERGENCY WAKEUP: battery almost empty\n");
3545 "EMERGENCY WAKEUP: battery almost empty\n");
3546 /* how to auto-heal: */ 3512 /* how to auto-heal: */
3547 /* 2313: woke up from S3, go to S4/S5 */ 3513 /* 2313: woke up from S3, go to S4/S5 */
3548 /* 2413: woke up from S4, go to S5 */ 3514 /* 2413: woke up from S4, go to S5 */
@@ -3553,14 +3519,40 @@ static bool hotkey_notify_wakeup(const u32 hkey,
3553 } 3519 }
3554 3520
3555 if (hotkey_wakeup_reason != TP_ACPI_WAKEUP_NONE) { 3521 if (hotkey_wakeup_reason != TP_ACPI_WAKEUP_NONE) {
3556 printk(TPACPI_INFO 3522 pr_info("woke up due to a hot-unplug request...\n");
3557 "woke up due to a hot-unplug "
3558 "request...\n");
3559 hotkey_wakeup_reason_notify_change(); 3523 hotkey_wakeup_reason_notify_change();
3560 } 3524 }
3561 return true; 3525 return true;
3562} 3526}
3563 3527
3528static bool hotkey_notify_dockevent(const u32 hkey,
3529 bool *send_acpi_ev,
3530 bool *ignore_acpi_ev)
3531{
3532 /* 0x4000-0x4FFF: dock-related events */
3533 *send_acpi_ev = true;
3534 *ignore_acpi_ev = false;
3535
3536 switch (hkey) {
3537 case TP_HKEY_EV_UNDOCK_ACK:
3538 /* ACPI undock operation completed after wakeup */
3539 hotkey_autosleep_ack = 1;
3540 pr_info("undocked\n");
3541 hotkey_wakeup_hotunplug_complete_notify_change();
3542 return true;
3543
3544 case TP_HKEY_EV_HOTPLUG_DOCK: /* docked to port replicator */
3545 pr_info("docked into hotplug port replicator\n");
3546 return true;
3547 case TP_HKEY_EV_HOTPLUG_UNDOCK: /* undocked from port replicator */
3548 pr_info("undocked from hotplug port replicator\n");
3549 return true;
3550
3551 default:
3552 return false;
3553 }
3554}
3555
3564static bool hotkey_notify_usrevent(const u32 hkey, 3556static bool hotkey_notify_usrevent(const u32 hkey,
3565 bool *send_acpi_ev, 3557 bool *send_acpi_ev,
3566 bool *ignore_acpi_ev) 3558 bool *ignore_acpi_ev)
@@ -3595,49 +3587,52 @@ static bool hotkey_notify_usrevent(const u32 hkey,
3595 3587
3596static void thermal_dump_all_sensors(void); 3588static void thermal_dump_all_sensors(void);
3597 3589
3598static bool hotkey_notify_thermal(const u32 hkey, 3590static bool hotkey_notify_6xxx(const u32 hkey,
3599 bool *send_acpi_ev, 3591 bool *send_acpi_ev,
3600 bool *ignore_acpi_ev) 3592 bool *ignore_acpi_ev)
3601{ 3593{
3602 bool known = true; 3594 bool known = true;
3603 3595
3604 /* 0x6000-0x6FFF: thermal alarms */ 3596 /* 0x6000-0x6FFF: thermal alarms/notices and keyboard events */
3605 *send_acpi_ev = true; 3597 *send_acpi_ev = true;
3606 *ignore_acpi_ev = false; 3598 *ignore_acpi_ev = false;
3607 3599
3608 switch (hkey) { 3600 switch (hkey) {
3609 case TP_HKEY_EV_THM_TABLE_CHANGED: 3601 case TP_HKEY_EV_THM_TABLE_CHANGED:
3610 printk(TPACPI_INFO 3602 pr_info("EC reports that Thermal Table has changed\n");
3611 "EC reports that Thermal Table has changed\n");
3612 /* recommended action: do nothing, we don't have 3603 /* recommended action: do nothing, we don't have
3613 * Lenovo ATM information */ 3604 * Lenovo ATM information */
3614 return true; 3605 return true;
3615 case TP_HKEY_EV_ALARM_BAT_HOT: 3606 case TP_HKEY_EV_ALARM_BAT_HOT:
3616 printk(TPACPI_CRIT 3607 pr_crit("THERMAL ALARM: battery is too hot!\n");
3617 "THERMAL ALARM: battery is too hot!\n");
3618 /* recommended action: warn user through gui */ 3608 /* recommended action: warn user through gui */
3619 break; 3609 break;
3620 case TP_HKEY_EV_ALARM_BAT_XHOT: 3610 case TP_HKEY_EV_ALARM_BAT_XHOT:
3621 printk(TPACPI_ALERT 3611 pr_alert("THERMAL EMERGENCY: battery is extremely hot!\n");
3622 "THERMAL EMERGENCY: battery is extremely hot!\n");
3623 /* recommended action: immediate sleep/hibernate */ 3612 /* recommended action: immediate sleep/hibernate */
3624 break; 3613 break;
3625 case TP_HKEY_EV_ALARM_SENSOR_HOT: 3614 case TP_HKEY_EV_ALARM_SENSOR_HOT:
3626 printk(TPACPI_CRIT 3615 pr_crit("THERMAL ALARM: "
3627 "THERMAL ALARM: "
3628 "a sensor reports something is too hot!\n"); 3616 "a sensor reports something is too hot!\n");
3629 /* recommended action: warn user through gui, that */ 3617 /* recommended action: warn user through gui, that */
3630 /* some internal component is too hot */ 3618 /* some internal component is too hot */
3631 break; 3619 break;
3632 case TP_HKEY_EV_ALARM_SENSOR_XHOT: 3620 case TP_HKEY_EV_ALARM_SENSOR_XHOT:
3633 printk(TPACPI_ALERT 3621 pr_alert("THERMAL EMERGENCY: "
3634 "THERMAL EMERGENCY: " 3622 "a sensor reports something is extremely hot!\n");
3635 "a sensor reports something is extremely hot!\n");
3636 /* recommended action: immediate sleep/hibernate */ 3623 /* recommended action: immediate sleep/hibernate */
3637 break; 3624 break;
3625
3626 case TP_HKEY_EV_KEY_NUMLOCK:
3627 case TP_HKEY_EV_KEY_FN:
3628 /* key press events, we just ignore them as long as the EC
3629 * is still reporting them in the normal keyboard stream */
3630 *send_acpi_ev = false;
3631 *ignore_acpi_ev = true;
3632 return true;
3633
3638 default: 3634 default:
3639 printk(TPACPI_ALERT 3635 pr_warn("unknown possible thermal alarm or keyboard event received\n");
3640 "THERMAL ALERT: unknown thermal alarm received\n");
3641 known = false; 3636 known = false;
3642 } 3637 }
3643 3638
@@ -3654,8 +3649,7 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
3654 bool known_ev; 3649 bool known_ev;
3655 3650
3656 if (event != 0x80) { 3651 if (event != 0x80) {
3657 printk(TPACPI_ERR 3652 pr_err("unknown HKEY notification event %d\n", event);
3658 "unknown HKEY notification event %d\n", event);
3659 /* forward it to userspace, maybe it knows how to handle it */ 3653 /* forward it to userspace, maybe it knows how to handle it */
3660 acpi_bus_generate_netlink_event( 3654 acpi_bus_generate_netlink_event(
3661 ibm->acpi->device->pnp.device_class, 3655 ibm->acpi->device->pnp.device_class,
@@ -3666,7 +3660,7 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
3666 3660
3667 while (1) { 3661 while (1) {
3668 if (!acpi_evalf(hkey_handle, &hkey, "MHKP", "d")) { 3662 if (!acpi_evalf(hkey_handle, &hkey, "MHKP", "d")) {
3669 printk(TPACPI_ERR "failed to retrieve HKEY event\n"); 3663 pr_err("failed to retrieve HKEY event\n");
3670 return; 3664 return;
3671 } 3665 }
3672 3666
@@ -3694,8 +3688,7 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
3694 switch (hkey) { 3688 switch (hkey) {
3695 case TP_HKEY_EV_BAYEJ_ACK: 3689 case TP_HKEY_EV_BAYEJ_ACK:
3696 hotkey_autosleep_ack = 1; 3690 hotkey_autosleep_ack = 1;
3697 printk(TPACPI_INFO 3691 pr_info("bay ejected\n");
3698 "bay ejected\n");
3699 hotkey_wakeup_hotunplug_complete_notify_change(); 3692 hotkey_wakeup_hotunplug_complete_notify_change();
3700 known_ev = true; 3693 known_ev = true;
3701 break; 3694 break;
@@ -3708,16 +3701,9 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
3708 } 3701 }
3709 break; 3702 break;
3710 case 4: 3703 case 4:
3711 /* 0x4000-0x4FFF: dock-related wakeups */ 3704 /* 0x4000-0x4FFF: dock-related events */
3712 if (hkey == TP_HKEY_EV_UNDOCK_ACK) { 3705 known_ev = hotkey_notify_dockevent(hkey, &send_acpi_ev,
3713 hotkey_autosleep_ack = 1; 3706 &ignore_acpi_ev);
3714 printk(TPACPI_INFO
3715 "undocked\n");
3716 hotkey_wakeup_hotunplug_complete_notify_change();
3717 known_ev = true;
3718 } else {
3719 known_ev = false;
3720 }
3721 break; 3707 break;
3722 case 5: 3708 case 5:
3723 /* 0x5000-0x5FFF: human interface helpers */ 3709 /* 0x5000-0x5FFF: human interface helpers */
@@ -3725,8 +3711,9 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
3725 &ignore_acpi_ev); 3711 &ignore_acpi_ev);
3726 break; 3712 break;
3727 case 6: 3713 case 6:
3728 /* 0x6000-0x6FFF: thermal alarms */ 3714 /* 0x6000-0x6FFF: thermal alarms/notices and
3729 known_ev = hotkey_notify_thermal(hkey, &send_acpi_ev, 3715 * keyboard events */
3716 known_ev = hotkey_notify_6xxx(hkey, &send_acpi_ev,
3730 &ignore_acpi_ev); 3717 &ignore_acpi_ev);
3731 break; 3718 break;
3732 case 7: 3719 case 7:
@@ -3743,11 +3730,9 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
3743 known_ev = false; 3730 known_ev = false;
3744 } 3731 }
3745 if (!known_ev) { 3732 if (!known_ev) {
3746 printk(TPACPI_NOTICE 3733 pr_notice("unhandled HKEY event 0x%04x\n", hkey);
3747 "unhandled HKEY event 0x%04x\n", hkey); 3734 pr_notice("please report the conditions when this "
3748 printk(TPACPI_NOTICE 3735 "event happened to %s\n", TPACPI_MAIL);
3749 "please report the conditions when this "
3750 "event happened to %s\n", TPACPI_MAIL);
3751 } 3736 }
3752 3737
3753 /* Legacy events */ 3738 /* Legacy events */
@@ -3780,8 +3765,7 @@ static void hotkey_resume(void)
3780 3765
3781 if (hotkey_status_set(true) < 0 || 3766 if (hotkey_status_set(true) < 0 ||
3782 hotkey_mask_set(hotkey_acpi_mask) < 0) 3767 hotkey_mask_set(hotkey_acpi_mask) < 0)
3783 printk(TPACPI_ERR 3768 pr_err("error while attempting to reset the event "
3784 "error while attempting to reset the event "
3785 "firmware interface\n"); 3769 "firmware interface\n");
3786 3770
3787 tpacpi_send_radiosw_update(); 3771 tpacpi_send_radiosw_update();
@@ -3826,14 +3810,12 @@ static void hotkey_enabledisable_warn(bool enable)
3826{ 3810{
3827 tpacpi_log_usertask("procfs hotkey enable/disable"); 3811 tpacpi_log_usertask("procfs hotkey enable/disable");
3828 if (!WARN((tpacpi_lifecycle == TPACPI_LIFE_RUNNING || !enable), 3812 if (!WARN((tpacpi_lifecycle == TPACPI_LIFE_RUNNING || !enable),
3829 TPACPI_WARN 3813 pr_fmt("hotkey enable/disable functionality has been "
3830 "hotkey enable/disable functionality has been " 3814 "removed from the driver. "
3831 "removed from the driver. Hotkeys are always " 3815 "Hotkeys are always enabled.\n")))
3832 "enabled\n")) 3816 pr_err("Please remove the hotkey=enable module "
3833 printk(TPACPI_ERR 3817 "parameter, it is deprecated. "
3834 "Please remove the hotkey=enable module " 3818 "Hotkeys are always enabled.\n");
3835 "parameter, it is deprecated. Hotkeys are always "
3836 "enabled\n");
3837} 3819}
3838 3820
3839static int hotkey_write(char *buf) 3821static int hotkey_write(char *buf)
@@ -3882,7 +3864,8 @@ errexit:
3882} 3864}
3883 3865
3884static const struct acpi_device_id ibm_htk_device_ids[] = { 3866static const struct acpi_device_id ibm_htk_device_ids[] = {
3885 {TPACPI_ACPI_HKEY_HID, 0}, 3867 {TPACPI_ACPI_IBM_HKEY_HID, 0},
3868 {TPACPI_ACPI_LENOVO_HKEY_HID, 0},
3886 {"", 0}, 3869 {"", 0},
3887}; 3870};
3888 3871
@@ -4012,8 +3995,7 @@ static void bluetooth_shutdown(void)
4012 /* Order firmware to save current state to NVRAM */ 3995 /* Order firmware to save current state to NVRAM */
4013 if (!acpi_evalf(NULL, NULL, "\\BLTH", "vd", 3996 if (!acpi_evalf(NULL, NULL, "\\BLTH", "vd",
4014 TP_ACPI_BLTH_SAVE_STATE)) 3997 TP_ACPI_BLTH_SAVE_STATE))
4015 printk(TPACPI_NOTICE 3998 pr_notice("failed to save bluetooth state to NVRAM\n");
4016 "failed to save bluetooth state to NVRAM\n");
4017 else 3999 else
4018 vdbg_printk(TPACPI_DBG_RFKILL, 4000 vdbg_printk(TPACPI_DBG_RFKILL,
4019 "bluestooth state saved to NVRAM\n"); 4001 "bluestooth state saved to NVRAM\n");
@@ -4052,8 +4034,7 @@ static int __init bluetooth_init(struct ibm_init_struct *iibm)
4052#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES 4034#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
4053 if (dbg_bluetoothemul) { 4035 if (dbg_bluetoothemul) {
4054 tp_features.bluetooth = 1; 4036 tp_features.bluetooth = 1;
4055 printk(TPACPI_INFO 4037 pr_info("bluetooth switch emulation enabled\n");
4056 "bluetooth switch emulation enabled\n");
4057 } else 4038 } else
4058#endif 4039#endif
4059 if (tp_features.bluetooth && 4040 if (tp_features.bluetooth &&
@@ -4204,8 +4185,7 @@ static void wan_shutdown(void)
4204 /* Order firmware to save current state to NVRAM */ 4185 /* Order firmware to save current state to NVRAM */
4205 if (!acpi_evalf(NULL, NULL, "\\WGSV", "vd", 4186 if (!acpi_evalf(NULL, NULL, "\\WGSV", "vd",
4206 TP_ACPI_WGSV_SAVE_STATE)) 4187 TP_ACPI_WGSV_SAVE_STATE))
4207 printk(TPACPI_NOTICE 4188 pr_notice("failed to save WWAN state to NVRAM\n");
4208 "failed to save WWAN state to NVRAM\n");
4209 else 4189 else
4210 vdbg_printk(TPACPI_DBG_RFKILL, 4190 vdbg_printk(TPACPI_DBG_RFKILL,
4211 "WWAN state saved to NVRAM\n"); 4191 "WWAN state saved to NVRAM\n");
@@ -4242,8 +4222,7 @@ static int __init wan_init(struct ibm_init_struct *iibm)
4242#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES 4222#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
4243 if (dbg_wwanemul) { 4223 if (dbg_wwanemul) {
4244 tp_features.wan = 1; 4224 tp_features.wan = 1;
4245 printk(TPACPI_INFO 4225 pr_info("wwan switch emulation enabled\n");
4246 "wwan switch emulation enabled\n");
4247 } else 4226 } else
4248#endif 4227#endif
4249 if (tp_features.wan && 4228 if (tp_features.wan &&
@@ -4383,8 +4362,7 @@ static int __init uwb_init(struct ibm_init_struct *iibm)
4383#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES 4362#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
4384 if (dbg_uwbemul) { 4363 if (dbg_uwbemul) {
4385 tp_features.uwb = 1; 4364 tp_features.uwb = 1;
4386 printk(TPACPI_INFO 4365 pr_info("uwb switch emulation enabled\n");
4387 "uwb switch emulation enabled\n");
4388 } else 4366 } else
4389#endif 4367#endif
4390 if (tp_features.uwb && 4368 if (tp_features.uwb &&
@@ -4445,6 +4423,15 @@ static int video_orig_autosw;
4445static int video_autosw_get(void); 4423static int video_autosw_get(void);
4446static int video_autosw_set(int enable); 4424static int video_autosw_set(int enable);
4447 4425
4426TPACPI_HANDLE(vid, root,
4427 "\\_SB.PCI.AGP.VGA", /* 570 */
4428 "\\_SB.PCI0.AGP0.VID0", /* 600e/x, 770x */
4429 "\\_SB.PCI0.VID0", /* 770e */
4430 "\\_SB.PCI0.VID", /* A21e, G4x, R50e, X30, X40 */
4431 "\\_SB.PCI0.AGP.VGA", /* X100e and a few others */
4432 "\\_SB.PCI0.AGP.VID", /* all others */
4433 ); /* R30, R31 */
4434
4448TPACPI_HANDLE(vid2, root, "\\_SB.PCI0.AGPB.VID"); /* G41 */ 4435TPACPI_HANDLE(vid2, root, "\\_SB.PCI0.AGPB.VID"); /* G41 */
4449 4436
4450static int __init video_init(struct ibm_init_struct *iibm) 4437static int __init video_init(struct ibm_init_struct *iibm)
@@ -4488,7 +4475,7 @@ static void video_exit(void)
4488 dbg_printk(TPACPI_DBG_EXIT, 4475 dbg_printk(TPACPI_DBG_EXIT,
4489 "restoring original video autoswitch mode\n"); 4476 "restoring original video autoswitch mode\n");
4490 if (video_autosw_set(video_orig_autosw)) 4477 if (video_autosw_set(video_orig_autosw))
4491 printk(TPACPI_ERR "error while trying to restore original " 4478 pr_err("error while trying to restore original "
4492 "video autoswitch mode\n"); 4479 "video autoswitch mode\n");
4493} 4480}
4494 4481
@@ -4561,8 +4548,7 @@ static int video_outputsw_set(int status)
4561 res = acpi_evalf(vid_handle, NULL, 4548 res = acpi_evalf(vid_handle, NULL,
4562 "ASWT", "vdd", status * 0x100, 0); 4549 "ASWT", "vdd", status * 0x100, 0);
4563 if (!autosw && video_autosw_set(autosw)) { 4550 if (!autosw && video_autosw_set(autosw)) {
4564 printk(TPACPI_ERR 4551 pr_err("video auto-switch left enabled due to error\n");
4565 "video auto-switch left enabled due to error\n");
4566 return -EIO; 4552 return -EIO;
4567 } 4553 }
4568 break; 4554 break;
@@ -4631,8 +4617,7 @@ static int video_outputsw_cycle(void)
4631 return -ENOSYS; 4617 return -ENOSYS;
4632 } 4618 }
4633 if (!autosw && video_autosw_set(autosw)) { 4619 if (!autosw && video_autosw_set(autosw)) {
4634 printk(TPACPI_ERR 4620 pr_err("video auto-switch left enabled due to error\n");
4635 "video auto-switch left enabled due to error\n");
4636 return -EIO; 4621 return -EIO;
4637 } 4622 }
4638 4623
@@ -5349,7 +5334,7 @@ static int __init led_init(struct ibm_init_struct *iibm)
5349 tpacpi_leds = kzalloc(sizeof(*tpacpi_leds) * TPACPI_LED_NUMLEDS, 5334 tpacpi_leds = kzalloc(sizeof(*tpacpi_leds) * TPACPI_LED_NUMLEDS,
5350 GFP_KERNEL); 5335 GFP_KERNEL);
5351 if (!tpacpi_leds) { 5336 if (!tpacpi_leds) {
5352 printk(TPACPI_ERR "Out of memory for LED data\n"); 5337 pr_err("Out of memory for LED data\n");
5353 return -ENOMEM; 5338 return -ENOMEM;
5354 } 5339 }
5355 5340
@@ -5368,9 +5353,8 @@ static int __init led_init(struct ibm_init_struct *iibm)
5368 } 5353 }
5369 5354
5370#ifdef CONFIG_THINKPAD_ACPI_UNSAFE_LEDS 5355#ifdef CONFIG_THINKPAD_ACPI_UNSAFE_LEDS
5371 printk(TPACPI_NOTICE 5356 pr_notice("warning: userspace override of important "
5372 "warning: userspace override of important " 5357 "firmware LEDs is enabled\n");
5373 "firmware LEDs is enabled\n");
5374#endif 5358#endif
5375 return 0; 5359 return 0;
5376} 5360}
@@ -5640,17 +5624,16 @@ static void thermal_dump_all_sensors(void)
5640 if (n <= 0) 5624 if (n <= 0)
5641 return; 5625 return;
5642 5626
5643 printk(TPACPI_NOTICE 5627 pr_notice("temperatures (Celsius):");
5644 "temperatures (Celsius):");
5645 5628
5646 for (i = 0; i < n; i++) { 5629 for (i = 0; i < n; i++) {
5647 if (t.temp[i] != TPACPI_THERMAL_SENSOR_NA) 5630 if (t.temp[i] != TPACPI_THERMAL_SENSOR_NA)
5648 printk(KERN_CONT " %d", (int)(t.temp[i] / 1000)); 5631 pr_cont(" %d", (int)(t.temp[i] / 1000));
5649 else 5632 else
5650 printk(KERN_CONT " N/A"); 5633 pr_cont(" N/A");
5651 } 5634 }
5652 5635
5653 printk(KERN_CONT "\n"); 5636 pr_cont("\n");
5654} 5637}
5655 5638
5656/* sysfs temp##_input -------------------------------------------------- */ 5639/* sysfs temp##_input -------------------------------------------------- */
@@ -5770,14 +5753,12 @@ static int __init thermal_init(struct ibm_init_struct *iibm)
5770 if (ta1 == 0) { 5753 if (ta1 == 0) {
5771 /* This is sheer paranoia, but we handle it anyway */ 5754 /* This is sheer paranoia, but we handle it anyway */
5772 if (acpi_tmp7) { 5755 if (acpi_tmp7) {
5773 printk(TPACPI_ERR 5756 pr_err("ThinkPad ACPI EC access misbehaving, "
5774 "ThinkPad ACPI EC access misbehaving, "
5775 "falling back to ACPI TMPx access " 5757 "falling back to ACPI TMPx access "
5776 "mode\n"); 5758 "mode\n");
5777 thermal_read_mode = TPACPI_THERMAL_ACPI_TMP07; 5759 thermal_read_mode = TPACPI_THERMAL_ACPI_TMP07;
5778 } else { 5760 } else {
5779 printk(TPACPI_ERR 5761 pr_err("ThinkPad ACPI EC access misbehaving, "
5780 "ThinkPad ACPI EC access misbehaving, "
5781 "disabling thermal sensors access\n"); 5762 "disabling thermal sensors access\n");
5782 thermal_read_mode = TPACPI_THERMAL_NONE; 5763 thermal_read_mode = TPACPI_THERMAL_NONE;
5783 } 5764 }
@@ -6109,7 +6090,7 @@ static void tpacpi_brightness_notify_change(void)
6109 BACKLIGHT_UPDATE_HOTKEY); 6090 BACKLIGHT_UPDATE_HOTKEY);
6110} 6091}
6111 6092
6112static struct backlight_ops ibm_backlight_data = { 6093static const struct backlight_ops ibm_backlight_data = {
6113 .get_brightness = brightness_get, 6094 .get_brightness = brightness_get,
6114 .update_status = brightness_update_status, 6095 .update_status = brightness_update_status,
6115}; 6096};
@@ -6130,8 +6111,8 @@ static int __init tpacpi_query_bcl_levels(acpi_handle handle)
6130 if (ACPI_SUCCESS(acpi_evaluate_object(handle, "_BCL", NULL, &buffer))) { 6111 if (ACPI_SUCCESS(acpi_evaluate_object(handle, "_BCL", NULL, &buffer))) {
6131 obj = (union acpi_object *)buffer.pointer; 6112 obj = (union acpi_object *)buffer.pointer;
6132 if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) { 6113 if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) {
6133 printk(TPACPI_ERR "Unknown _BCL data, " 6114 pr_err("Unknown _BCL data, please report this to %s\n",
6134 "please report this to %s\n", TPACPI_MAIL); 6115 TPACPI_MAIL);
6135 rc = 0; 6116 rc = 0;
6136 } else { 6117 } else {
6137 rc = obj->package.count; 6118 rc = obj->package.count;
@@ -6215,18 +6196,15 @@ static void __init tpacpi_detect_brightness_capabilities(void)
6215 switch (b) { 6196 switch (b) {
6216 case 16: 6197 case 16:
6217 bright_maxlvl = 15; 6198 bright_maxlvl = 15;
6218 printk(TPACPI_INFO 6199 pr_info("detected a 16-level brightness capable ThinkPad\n");
6219 "detected a 16-level brightness capable ThinkPad\n");
6220 break; 6200 break;
6221 case 8: 6201 case 8:
6222 case 0: 6202 case 0:
6223 bright_maxlvl = 7; 6203 bright_maxlvl = 7;
6224 printk(TPACPI_INFO 6204 pr_info("detected a 8-level brightness capable ThinkPad\n");
6225 "detected a 8-level brightness capable ThinkPad\n");
6226 break; 6205 break;
6227 default: 6206 default:
6228 printk(TPACPI_ERR 6207 pr_err("Unsupported brightness interface, "
6229 "Unsupported brightness interface, "
6230 "please contact %s\n", TPACPI_MAIL); 6208 "please contact %s\n", TPACPI_MAIL);
6231 tp_features.bright_unkfw = 1; 6209 tp_features.bright_unkfw = 1;
6232 bright_maxlvl = b - 1; 6210 bright_maxlvl = b - 1;
@@ -6261,22 +6239,19 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
6261 6239
6262 if (acpi_video_backlight_support()) { 6240 if (acpi_video_backlight_support()) {
6263 if (brightness_enable > 1) { 6241 if (brightness_enable > 1) {
6264 printk(TPACPI_INFO 6242 pr_info("Standard ACPI backlight interface "
6265 "Standard ACPI backlight interface " 6243 "available, not loading native one\n");
6266 "available, not loading native one.\n");
6267 return 1; 6244 return 1;
6268 } else if (brightness_enable == 1) { 6245 } else if (brightness_enable == 1) {
6269 printk(TPACPI_WARN 6246 pr_warn("Cannot enable backlight brightness support, "
6270 "Cannot enable backlight brightness support, "
6271 "ACPI is already handling it. Refer to the " 6247 "ACPI is already handling it. Refer to the "
6272 "acpi_backlight kernel parameter\n"); 6248 "acpi_backlight kernel parameter.\n");
6273 return 1; 6249 return 1;
6274 } 6250 }
6275 } else if (tp_features.bright_acpimode && brightness_enable > 1) { 6251 } else if (tp_features.bright_acpimode && brightness_enable > 1) {
6276 printk(TPACPI_NOTICE 6252 pr_notice("Standard ACPI backlight interface not "
6277 "Standard ACPI backlight interface not " 6253 "available, thinkpad_acpi native "
6278 "available, thinkpad_acpi native " 6254 "brightness control enabled\n");
6279 "brightness control enabled\n");
6280 } 6255 }
6281 6256
6282 /* 6257 /*
@@ -6310,6 +6285,7 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
6310 return 1; 6285 return 1;
6311 6286
6312 memset(&props, 0, sizeof(struct backlight_properties)); 6287 memset(&props, 0, sizeof(struct backlight_properties));
6288 props.type = BACKLIGHT_PLATFORM;
6313 props.max_brightness = bright_maxlvl; 6289 props.max_brightness = bright_maxlvl;
6314 props.brightness = b & TP_EC_BACKLIGHT_LVLMSK; 6290 props.brightness = b & TP_EC_BACKLIGHT_LVLMSK;
6315 ibm_backlight_device = backlight_device_register(TPACPI_BACKLIGHT_DEV_NAME, 6291 ibm_backlight_device = backlight_device_register(TPACPI_BACKLIGHT_DEV_NAME,
@@ -6319,19 +6295,17 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
6319 if (IS_ERR(ibm_backlight_device)) { 6295 if (IS_ERR(ibm_backlight_device)) {
6320 int rc = PTR_ERR(ibm_backlight_device); 6296 int rc = PTR_ERR(ibm_backlight_device);
6321 ibm_backlight_device = NULL; 6297 ibm_backlight_device = NULL;
6322 printk(TPACPI_ERR "Could not register backlight device\n"); 6298 pr_err("Could not register backlight device\n");
6323 return rc; 6299 return rc;
6324 } 6300 }
6325 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_BRGHT, 6301 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_BRGHT,
6326 "brightness is supported\n"); 6302 "brightness is supported\n");
6327 6303
6328 if (quirks & TPACPI_BRGHT_Q_ASK) { 6304 if (quirks & TPACPI_BRGHT_Q_ASK) {
6329 printk(TPACPI_NOTICE 6305 pr_notice("brightness: will use unverified default: "
6330 "brightness: will use unverified default: " 6306 "brightness_mode=%d\n", brightness_mode);
6331 "brightness_mode=%d\n", brightness_mode); 6307 pr_notice("brightness: please report to %s whether it works well "
6332 printk(TPACPI_NOTICE 6308 "or not on your ThinkPad\n", TPACPI_MAIL);
6333 "brightness: please report to %s whether it works well "
6334 "or not on your ThinkPad\n", TPACPI_MAIL);
6335 } 6309 }
6336 6310
6337 /* Added by mistake in early 2007. Probably useless, but it could 6311 /* Added by mistake in early 2007. Probably useless, but it could
@@ -6345,7 +6319,7 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
6345 "as change notification\n"); 6319 "as change notification\n");
6346 tpacpi_hotkey_driver_mask_set(hotkey_driver_mask 6320 tpacpi_hotkey_driver_mask_set(hotkey_driver_mask
6347 | TP_ACPI_HKEY_BRGHTUP_MASK 6321 | TP_ACPI_HKEY_BRGHTUP_MASK
6348 | TP_ACPI_HKEY_BRGHTDWN_MASK);; 6322 | TP_ACPI_HKEY_BRGHTDWN_MASK);
6349 return 0; 6323 return 0;
6350} 6324}
6351 6325
@@ -6804,8 +6778,7 @@ static int __init volume_create_alsa_mixer(void)
6804 rc = snd_card_create(alsa_index, alsa_id, THIS_MODULE, 6778 rc = snd_card_create(alsa_index, alsa_id, THIS_MODULE,
6805 sizeof(struct tpacpi_alsa_data), &card); 6779 sizeof(struct tpacpi_alsa_data), &card);
6806 if (rc < 0 || !card) { 6780 if (rc < 0 || !card) {
6807 printk(TPACPI_ERR 6781 pr_err("Failed to create ALSA card structures: %d\n", rc);
6808 "Failed to create ALSA card structures: %d\n", rc);
6809 return 1; 6782 return 1;
6810 } 6783 }
6811 6784
@@ -6839,9 +6812,8 @@ static int __init volume_create_alsa_mixer(void)
6839 ctl_vol = snd_ctl_new1(&volume_alsa_control_vol, NULL); 6812 ctl_vol = snd_ctl_new1(&volume_alsa_control_vol, NULL);
6840 rc = snd_ctl_add(card, ctl_vol); 6813 rc = snd_ctl_add(card, ctl_vol);
6841 if (rc < 0) { 6814 if (rc < 0) {
6842 printk(TPACPI_ERR 6815 pr_err("Failed to create ALSA volume control: %d\n",
6843 "Failed to create ALSA volume control: %d\n", 6816 rc);
6844 rc);
6845 goto err_exit; 6817 goto err_exit;
6846 } 6818 }
6847 data->ctl_vol_id = &ctl_vol->id; 6819 data->ctl_vol_id = &ctl_vol->id;
@@ -6850,8 +6822,7 @@ static int __init volume_create_alsa_mixer(void)
6850 ctl_mute = snd_ctl_new1(&volume_alsa_control_mute, NULL); 6822 ctl_mute = snd_ctl_new1(&volume_alsa_control_mute, NULL);
6851 rc = snd_ctl_add(card, ctl_mute); 6823 rc = snd_ctl_add(card, ctl_mute);
6852 if (rc < 0) { 6824 if (rc < 0) {
6853 printk(TPACPI_ERR "Failed to create ALSA mute control: %d\n", 6825 pr_err("Failed to create ALSA mute control: %d\n", rc);
6854 rc);
6855 goto err_exit; 6826 goto err_exit;
6856 } 6827 }
6857 data->ctl_mute_id = &ctl_mute->id; 6828 data->ctl_mute_id = &ctl_mute->id;
@@ -6859,7 +6830,7 @@ static int __init volume_create_alsa_mixer(void)
6859 snd_card_set_dev(card, &tpacpi_pdev->dev); 6830 snd_card_set_dev(card, &tpacpi_pdev->dev);
6860 rc = snd_card_register(card); 6831 rc = snd_card_register(card);
6861 if (rc < 0) { 6832 if (rc < 0) {
6862 printk(TPACPI_ERR "Failed to register ALSA card: %d\n", rc); 6833 pr_err("Failed to register ALSA card: %d\n", rc);
6863 goto err_exit; 6834 goto err_exit;
6864 } 6835 }
6865 6836
@@ -6915,9 +6886,8 @@ static int __init volume_init(struct ibm_init_struct *iibm)
6915 return -EINVAL; 6886 return -EINVAL;
6916 6887
6917 if (volume_mode == TPACPI_VOL_MODE_UCMS_STEP) { 6888 if (volume_mode == TPACPI_VOL_MODE_UCMS_STEP) {
6918 printk(TPACPI_ERR 6889 pr_err("UCMS step volume mode not implemented, "
6919 "UCMS step volume mode not implemented, " 6890 "please contact %s\n", TPACPI_MAIL);
6920 "please contact %s\n", TPACPI_MAIL);
6921 return 1; 6891 return 1;
6922 } 6892 }
6923 6893
@@ -6981,13 +6951,11 @@ static int __init volume_init(struct ibm_init_struct *iibm)
6981 6951
6982 rc = volume_create_alsa_mixer(); 6952 rc = volume_create_alsa_mixer();
6983 if (rc) { 6953 if (rc) {
6984 printk(TPACPI_ERR 6954 pr_err("Could not create the ALSA mixer interface\n");
6985 "Could not create the ALSA mixer interface\n");
6986 return rc; 6955 return rc;
6987 } 6956 }
6988 6957
6989 printk(TPACPI_INFO 6958 pr_info("Console audio control enabled, mode: %s\n",
6990 "Console audio control enabled, mode: %s\n",
6991 (volume_control_allowed) ? 6959 (volume_control_allowed) ?
6992 "override (read/write)" : 6960 "override (read/write)" :
6993 "monitor (read only)"); 6961 "monitor (read only)");
@@ -7049,12 +7017,10 @@ static int volume_write(char *buf)
7049 if (!volume_control_allowed && tpacpi_lifecycle != TPACPI_LIFE_INIT) { 7017 if (!volume_control_allowed && tpacpi_lifecycle != TPACPI_LIFE_INIT) {
7050 if (unlikely(!tp_warned.volume_ctrl_forbidden)) { 7018 if (unlikely(!tp_warned.volume_ctrl_forbidden)) {
7051 tp_warned.volume_ctrl_forbidden = 1; 7019 tp_warned.volume_ctrl_forbidden = 1;
7052 printk(TPACPI_NOTICE 7020 pr_notice("Console audio control in monitor mode, "
7053 "Console audio control in monitor mode, " 7021 "changes are not allowed\n");
7054 "changes are not allowed.\n"); 7022 pr_notice("Use the volume_control=1 module parameter "
7055 printk(TPACPI_NOTICE 7023 "to enable volume control\n");
7056 "Use the volume_control=1 module parameter "
7057 "to enable volume control\n");
7058 } 7024 }
7059 return -EPERM; 7025 return -EPERM;
7060 } 7026 }
@@ -7129,8 +7095,7 @@ static void inline volume_alsa_notify_change(void)
7129 7095
7130static int __init volume_init(struct ibm_init_struct *iibm) 7096static int __init volume_init(struct ibm_init_struct *iibm)
7131{ 7097{
7132 printk(TPACPI_INFO 7098 pr_info("volume: disabled as there is no ALSA support in this kernel\n");
7133 "volume: disabled as there is no ALSA support in this kernel\n");
7134 7099
7135 return 1; 7100 return 1;
7136} 7101}
@@ -7193,7 +7158,7 @@ static struct ibm_struct volume_driver_data = {
7193 * TPACPI_FAN_WR_ACPI_FANS (X31/X40/X41) 7158 * TPACPI_FAN_WR_ACPI_FANS (X31/X40/X41)
7194 * 7159 *
7195 * FIRMWARE BUG: on some models, EC 0x2f might not be initialized at 7160 * FIRMWARE BUG: on some models, EC 0x2f might not be initialized at
7196 * boot. Apparently the EC does not intialize it, so unless ACPI DSDT 7161 * boot. Apparently the EC does not initialize it, so unless ACPI DSDT
7197 * does so, its initial value is meaningless (0x07). 7162 * does so, its initial value is meaningless (0x07).
7198 * 7163 *
7199 * For firmware bugs, refer to: 7164 * For firmware bugs, refer to:
@@ -7337,9 +7302,8 @@ TPACPI_HANDLE(sfan, ec, "SFAN", /* 570 */
7337static void fan_quirk1_setup(void) 7302static void fan_quirk1_setup(void)
7338{ 7303{
7339 if (fan_control_initial_status == 0x07) { 7304 if (fan_control_initial_status == 0x07) {
7340 printk(TPACPI_NOTICE 7305 pr_notice("fan_init: initial fan status is unknown, "
7341 "fan_init: initial fan status is unknown, " 7306 "assuming it is in auto mode\n");
7342 "assuming it is in auto mode\n");
7343 tp_features.fan_ctrl_status_undef = 1; 7307 tp_features.fan_ctrl_status_undef = 1;
7344 } 7308 }
7345} 7309}
@@ -7726,8 +7690,7 @@ static void fan_watchdog_reset(void)
7726 if (!queue_delayed_work(tpacpi_wq, &fan_watchdog_task, 7690 if (!queue_delayed_work(tpacpi_wq, &fan_watchdog_task,
7727 msecs_to_jiffies(fan_watchdog_maxinterval 7691 msecs_to_jiffies(fan_watchdog_maxinterval
7728 * 1000))) { 7692 * 1000))) {
7729 printk(TPACPI_ERR 7693 pr_err("failed to queue the fan watchdog, "
7730 "failed to queue the fan watchdog, "
7731 "watchdog will not trigger\n"); 7694 "watchdog will not trigger\n");
7732 } 7695 }
7733 } else 7696 } else
@@ -7741,11 +7704,11 @@ static void fan_watchdog_fire(struct work_struct *ignored)
7741 if (tpacpi_lifecycle != TPACPI_LIFE_RUNNING) 7704 if (tpacpi_lifecycle != TPACPI_LIFE_RUNNING)
7742 return; 7705 return;
7743 7706
7744 printk(TPACPI_NOTICE "fan watchdog: enabling fan\n"); 7707 pr_notice("fan watchdog: enabling fan\n");
7745 rc = fan_set_enable(); 7708 rc = fan_set_enable();
7746 if (rc < 0) { 7709 if (rc < 0) {
7747 printk(TPACPI_ERR "fan watchdog: error %d while enabling fan, " 7710 pr_err("fan watchdog: error %d while enabling fan, "
7748 "will try again later...\n", -rc); 7711 "will try again later...\n", -rc);
7749 /* reschedule for later */ 7712 /* reschedule for later */
7750 fan_watchdog_reset(); 7713 fan_watchdog_reset();
7751 } 7714 }
@@ -8049,8 +8012,7 @@ static int __init fan_init(struct ibm_init_struct *iibm)
8049 "secondary fan support enabled\n"); 8012 "secondary fan support enabled\n");
8050 } 8013 }
8051 } else { 8014 } else {
8052 printk(TPACPI_ERR 8015 pr_err("ThinkPad ACPI EC access misbehaving, "
8053 "ThinkPad ACPI EC access misbehaving, "
8054 "fan status and control unavailable\n"); 8016 "fan status and control unavailable\n");
8055 return 1; 8017 return 1;
8056 } 8018 }
@@ -8150,9 +8112,8 @@ static void fan_suspend(pm_message_t state)
8150 fan_control_resume_level = 0; 8112 fan_control_resume_level = 0;
8151 rc = fan_get_status_safe(&fan_control_resume_level); 8113 rc = fan_get_status_safe(&fan_control_resume_level);
8152 if (rc < 0) 8114 if (rc < 0)
8153 printk(TPACPI_NOTICE 8115 pr_notice("failed to read fan level for later "
8154 "failed to read fan level for later " 8116 "restore during resume: %d\n", rc);
8155 "restore during resume: %d\n", rc);
8156 8117
8157 /* if it is undefined, don't attempt to restore it. 8118 /* if it is undefined, don't attempt to restore it.
8158 * KEEP THIS LAST */ 8119 * KEEP THIS LAST */
@@ -8207,13 +8168,11 @@ static void fan_resume(void)
8207 return; 8168 return;
8208 } 8169 }
8209 if (do_set) { 8170 if (do_set) {
8210 printk(TPACPI_NOTICE 8171 pr_notice("restoring fan level to 0x%02x\n",
8211 "restoring fan level to 0x%02x\n", 8172 fan_control_resume_level);
8212 fan_control_resume_level);
8213 rc = fan_set_level_safe(fan_control_resume_level); 8173 rc = fan_set_level_safe(fan_control_resume_level);
8214 if (rc < 0) 8174 if (rc < 0)
8215 printk(TPACPI_NOTICE 8175 pr_notice("failed to restore fan level: %d\n", rc);
8216 "failed to restore fan level: %d\n", rc);
8217 } 8176 }
8218} 8177}
8219 8178
@@ -8305,8 +8264,8 @@ static int fan_write_cmd_level(const char *cmd, int *rc)
8305 8264
8306 *rc = fan_set_level_safe(level); 8265 *rc = fan_set_level_safe(level);
8307 if (*rc == -ENXIO) 8266 if (*rc == -ENXIO)
8308 printk(TPACPI_ERR "level command accepted for unsupported " 8267 pr_err("level command accepted for unsupported access mode %d\n",
8309 "access mode %d", fan_control_access_mode); 8268 fan_control_access_mode);
8310 else if (!*rc) 8269 else if (!*rc)
8311 tpacpi_disclose_usertask("procfs fan", 8270 tpacpi_disclose_usertask("procfs fan",
8312 "set level to %d\n", level); 8271 "set level to %d\n", level);
@@ -8321,8 +8280,8 @@ static int fan_write_cmd_enable(const char *cmd, int *rc)
8321 8280
8322 *rc = fan_set_enable(); 8281 *rc = fan_set_enable();
8323 if (*rc == -ENXIO) 8282 if (*rc == -ENXIO)
8324 printk(TPACPI_ERR "enable command accepted for unsupported " 8283 pr_err("enable command accepted for unsupported access mode %d\n",
8325 "access mode %d", fan_control_access_mode); 8284 fan_control_access_mode);
8326 else if (!*rc) 8285 else if (!*rc)
8327 tpacpi_disclose_usertask("procfs fan", "enable\n"); 8286 tpacpi_disclose_usertask("procfs fan", "enable\n");
8328 8287
@@ -8336,8 +8295,8 @@ static int fan_write_cmd_disable(const char *cmd, int *rc)
8336 8295
8337 *rc = fan_set_disable(); 8296 *rc = fan_set_disable();
8338 if (*rc == -ENXIO) 8297 if (*rc == -ENXIO)
8339 printk(TPACPI_ERR "disable command accepted for unsupported " 8298 pr_err("disable command accepted for unsupported access mode %d\n",
8340 "access mode %d", fan_control_access_mode); 8299 fan_control_access_mode);
8341 else if (!*rc) 8300 else if (!*rc)
8342 tpacpi_disclose_usertask("procfs fan", "disable\n"); 8301 tpacpi_disclose_usertask("procfs fan", "disable\n");
8343 8302
@@ -8356,8 +8315,8 @@ static int fan_write_cmd_speed(const char *cmd, int *rc)
8356 8315
8357 *rc = fan_set_speed(speed); 8316 *rc = fan_set_speed(speed);
8358 if (*rc == -ENXIO) 8317 if (*rc == -ENXIO)
8359 printk(TPACPI_ERR "speed command accepted for unsupported " 8318 pr_err("speed command accepted for unsupported access mode %d\n",
8360 "access mode %d", fan_control_access_mode); 8319 fan_control_access_mode);
8361 else if (!*rc) 8320 else if (!*rc)
8362 tpacpi_disclose_usertask("procfs fan", 8321 tpacpi_disclose_usertask("procfs fan",
8363 "set speed to %d\n", speed); 8322 "set speed to %d\n", speed);
@@ -8497,7 +8456,6 @@ static void ibm_exit(struct ibm_struct *ibm)
8497 ibm->acpi->type, 8456 ibm->acpi->type,
8498 dispatch_acpi_notify); 8457 dispatch_acpi_notify);
8499 ibm->flags.acpi_notify_installed = 0; 8458 ibm->flags.acpi_notify_installed = 0;
8500 ibm->flags.acpi_notify_installed = 0;
8501 } 8459 }
8502 8460
8503 if (ibm->flags.proc_created) { 8461 if (ibm->flags.proc_created) {
@@ -8561,8 +8519,8 @@ static int __init ibm_init(struct ibm_init_struct *iibm)
8561 if (ibm->acpi->notify) { 8519 if (ibm->acpi->notify) {
8562 ret = setup_acpi_notify(ibm); 8520 ret = setup_acpi_notify(ibm);
8563 if (ret == -ENODEV) { 8521 if (ret == -ENODEV) {
8564 printk(TPACPI_NOTICE "disabling subdriver %s\n", 8522 pr_notice("disabling subdriver %s\n",
8565 ibm->name); 8523 ibm->name);
8566 ret = 0; 8524 ret = 0;
8567 goto err_out; 8525 goto err_out;
8568 } 8526 }
@@ -8584,8 +8542,7 @@ static int __init ibm_init(struct ibm_init_struct *iibm)
8584 entry = proc_create_data(ibm->name, mode, proc_dir, 8542 entry = proc_create_data(ibm->name, mode, proc_dir,
8585 &dispatch_proc_fops, ibm); 8543 &dispatch_proc_fops, ibm);
8586 if (!entry) { 8544 if (!entry) {
8587 printk(TPACPI_ERR "unable to create proc entry %s\n", 8545 pr_err("unable to create proc entry %s\n", ibm->name);
8588 ibm->name);
8589 ret = -ENODEV; 8546 ret = -ENODEV;
8590 goto err_out; 8547 goto err_out;
8591 } 8548 }
@@ -8621,8 +8578,7 @@ static bool __pure __init tpacpi_is_valid_fw_id(const char* const s,
8621 tpacpi_is_fw_digit(s[1]) && 8578 tpacpi_is_fw_digit(s[1]) &&
8622 s[2] == t && s[3] == 'T' && 8579 s[2] == t && s[3] == 'T' &&
8623 tpacpi_is_fw_digit(s[4]) && 8580 tpacpi_is_fw_digit(s[4]) &&
8624 tpacpi_is_fw_digit(s[5]) && 8581 tpacpi_is_fw_digit(s[5]);
8625 s[6] == 'W' && s[7] == 'W';
8626} 8582}
8627 8583
8628/* returns 0 - probe ok, or < 0 - probe error. 8584/* returns 0 - probe ok, or < 0 - probe error.
@@ -8685,13 +8641,11 @@ static int __must_check __init get_thinkpad_model_data(
8685 tp->ec_release = (ec_fw_string[4] << 8) 8641 tp->ec_release = (ec_fw_string[4] << 8)
8686 | ec_fw_string[5]; 8642 | ec_fw_string[5];
8687 } else { 8643 } else {
8688 printk(TPACPI_NOTICE 8644 pr_notice("ThinkPad firmware release %s "
8689 "ThinkPad firmware release %s " 8645 "doesn't match the known patterns\n",
8690 "doesn't match the known patterns\n", 8646 ec_fw_string);
8691 ec_fw_string); 8647 pr_notice("please report this to %s\n",
8692 printk(TPACPI_NOTICE 8648 TPACPI_MAIL);
8693 "please report this to %s\n",
8694 TPACPI_MAIL);
8695 } 8649 }
8696 break; 8650 break;
8697 } 8651 }
@@ -8735,8 +8689,7 @@ static int __init probe_for_thinkpad(void)
8735 tpacpi_acpi_handle_locate("ec", TPACPI_ACPI_EC_HID, &ec_handle); 8689 tpacpi_acpi_handle_locate("ec", TPACPI_ACPI_EC_HID, &ec_handle);
8736 if (!ec_handle) { 8690 if (!ec_handle) {
8737 if (is_thinkpad) 8691 if (is_thinkpad)
8738 printk(TPACPI_ERR 8692 pr_err("Not yet supported ThinkPad detected!\n");
8739 "Not yet supported ThinkPad detected!\n");
8740 return -ENODEV; 8693 return -ENODEV;
8741 } 8694 }
8742 8695
@@ -8748,10 +8701,10 @@ static int __init probe_for_thinkpad(void)
8748 8701
8749static void __init thinkpad_acpi_init_banner(void) 8702static void __init thinkpad_acpi_init_banner(void)
8750{ 8703{
8751 printk(TPACPI_INFO "%s v%s\n", TPACPI_DESC, TPACPI_VERSION); 8704 pr_info("%s v%s\n", TPACPI_DESC, TPACPI_VERSION);
8752 printk(TPACPI_INFO "%s\n", TPACPI_URL); 8705 pr_info("%s\n", TPACPI_URL);
8753 8706
8754 printk(TPACPI_INFO "ThinkPad BIOS %s, EC %s\n", 8707 pr_info("ThinkPad BIOS %s, EC %s\n",
8755 (thinkpad_id.bios_version_str) ? 8708 (thinkpad_id.bios_version_str) ?
8756 thinkpad_id.bios_version_str : "unknown", 8709 thinkpad_id.bios_version_str : "unknown",
8757 (thinkpad_id.ec_version_str) ? 8710 (thinkpad_id.ec_version_str) ?
@@ -8760,7 +8713,7 @@ static void __init thinkpad_acpi_init_banner(void)
8760 BUG_ON(!thinkpad_id.vendor); 8713 BUG_ON(!thinkpad_id.vendor);
8761 8714
8762 if (thinkpad_id.model_str) 8715 if (thinkpad_id.model_str)
8763 printk(TPACPI_INFO "%s %s, model %s\n", 8716 pr_info("%s %s, model %s\n",
8764 (thinkpad_id.vendor == PCI_VENDOR_ID_IBM) ? 8717 (thinkpad_id.vendor == PCI_VENDOR_ID_IBM) ?
8765 "IBM" : ((thinkpad_id.vendor == 8718 "IBM" : ((thinkpad_id.vendor ==
8766 PCI_VENDOR_ID_LENOVO) ? 8719 PCI_VENDOR_ID_LENOVO) ?
@@ -9026,8 +8979,7 @@ static int __init thinkpad_acpi_module_init(void)
9026 8979
9027 ret = get_thinkpad_model_data(&thinkpad_id); 8980 ret = get_thinkpad_model_data(&thinkpad_id);
9028 if (ret) { 8981 if (ret) {
9029 printk(TPACPI_ERR 8982 pr_err("unable to get DMI data: %d\n", ret);
9030 "unable to get DMI data: %d\n", ret);
9031 thinkpad_acpi_module_exit(); 8983 thinkpad_acpi_module_exit();
9032 return ret; 8984 return ret;
9033 } 8985 }
@@ -9053,16 +9005,14 @@ static int __init thinkpad_acpi_module_init(void)
9053 9005
9054 proc_dir = proc_mkdir(TPACPI_PROC_DIR, acpi_root_dir); 9006 proc_dir = proc_mkdir(TPACPI_PROC_DIR, acpi_root_dir);
9055 if (!proc_dir) { 9007 if (!proc_dir) {
9056 printk(TPACPI_ERR 9008 pr_err("unable to create proc dir " TPACPI_PROC_DIR "\n");
9057 "unable to create proc dir " TPACPI_PROC_DIR);
9058 thinkpad_acpi_module_exit(); 9009 thinkpad_acpi_module_exit();
9059 return -ENODEV; 9010 return -ENODEV;
9060 } 9011 }
9061 9012
9062 ret = platform_driver_register(&tpacpi_pdriver); 9013 ret = platform_driver_register(&tpacpi_pdriver);
9063 if (ret) { 9014 if (ret) {
9064 printk(TPACPI_ERR 9015 pr_err("unable to register main platform driver\n");
9065 "unable to register main platform driver\n");
9066 thinkpad_acpi_module_exit(); 9016 thinkpad_acpi_module_exit();
9067 return ret; 9017 return ret;
9068 } 9018 }
@@ -9070,8 +9020,7 @@ static int __init thinkpad_acpi_module_init(void)
9070 9020
9071 ret = platform_driver_register(&tpacpi_hwmon_pdriver); 9021 ret = platform_driver_register(&tpacpi_hwmon_pdriver);
9072 if (ret) { 9022 if (ret) {
9073 printk(TPACPI_ERR 9023 pr_err("unable to register hwmon platform driver\n");
9074 "unable to register hwmon platform driver\n");
9075 thinkpad_acpi_module_exit(); 9024 thinkpad_acpi_module_exit();
9076 return ret; 9025 return ret;
9077 } 9026 }
@@ -9084,8 +9033,7 @@ static int __init thinkpad_acpi_module_init(void)
9084 &tpacpi_hwmon_pdriver.driver); 9033 &tpacpi_hwmon_pdriver.driver);
9085 } 9034 }
9086 if (ret) { 9035 if (ret) {
9087 printk(TPACPI_ERR 9036 pr_err("unable to create sysfs driver attributes\n");
9088 "unable to create sysfs driver attributes\n");
9089 thinkpad_acpi_module_exit(); 9037 thinkpad_acpi_module_exit();
9090 return ret; 9038 return ret;
9091 } 9039 }
@@ -9098,7 +9046,7 @@ static int __init thinkpad_acpi_module_init(void)
9098 if (IS_ERR(tpacpi_pdev)) { 9046 if (IS_ERR(tpacpi_pdev)) {
9099 ret = PTR_ERR(tpacpi_pdev); 9047 ret = PTR_ERR(tpacpi_pdev);
9100 tpacpi_pdev = NULL; 9048 tpacpi_pdev = NULL;
9101 printk(TPACPI_ERR "unable to register platform device\n"); 9049 pr_err("unable to register platform device\n");
9102 thinkpad_acpi_module_exit(); 9050 thinkpad_acpi_module_exit();
9103 return ret; 9051 return ret;
9104 } 9052 }
@@ -9108,16 +9056,14 @@ static int __init thinkpad_acpi_module_init(void)
9108 if (IS_ERR(tpacpi_sensors_pdev)) { 9056 if (IS_ERR(tpacpi_sensors_pdev)) {
9109 ret = PTR_ERR(tpacpi_sensors_pdev); 9057 ret = PTR_ERR(tpacpi_sensors_pdev);
9110 tpacpi_sensors_pdev = NULL; 9058 tpacpi_sensors_pdev = NULL;
9111 printk(TPACPI_ERR 9059 pr_err("unable to register hwmon platform device\n");
9112 "unable to register hwmon platform device\n");
9113 thinkpad_acpi_module_exit(); 9060 thinkpad_acpi_module_exit();
9114 return ret; 9061 return ret;
9115 } 9062 }
9116 ret = device_create_file(&tpacpi_sensors_pdev->dev, 9063 ret = device_create_file(&tpacpi_sensors_pdev->dev,
9117 &dev_attr_thinkpad_acpi_pdev_name); 9064 &dev_attr_thinkpad_acpi_pdev_name);
9118 if (ret) { 9065 if (ret) {
9119 printk(TPACPI_ERR 9066 pr_err("unable to create sysfs hwmon device attributes\n");
9120 "unable to create sysfs hwmon device attributes\n");
9121 thinkpad_acpi_module_exit(); 9067 thinkpad_acpi_module_exit();
9122 return ret; 9068 return ret;
9123 } 9069 }
@@ -9126,14 +9072,14 @@ static int __init thinkpad_acpi_module_init(void)
9126 if (IS_ERR(tpacpi_hwmon)) { 9072 if (IS_ERR(tpacpi_hwmon)) {
9127 ret = PTR_ERR(tpacpi_hwmon); 9073 ret = PTR_ERR(tpacpi_hwmon);
9128 tpacpi_hwmon = NULL; 9074 tpacpi_hwmon = NULL;
9129 printk(TPACPI_ERR "unable to register hwmon device\n"); 9075 pr_err("unable to register hwmon device\n");
9130 thinkpad_acpi_module_exit(); 9076 thinkpad_acpi_module_exit();
9131 return ret; 9077 return ret;
9132 } 9078 }
9133 mutex_init(&tpacpi_inputdev_send_mutex); 9079 mutex_init(&tpacpi_inputdev_send_mutex);
9134 tpacpi_inputdev = input_allocate_device(); 9080 tpacpi_inputdev = input_allocate_device();
9135 if (!tpacpi_inputdev) { 9081 if (!tpacpi_inputdev) {
9136 printk(TPACPI_ERR "unable to allocate input device\n"); 9082 pr_err("unable to allocate input device\n");
9137 thinkpad_acpi_module_exit(); 9083 thinkpad_acpi_module_exit();
9138 return -ENOMEM; 9084 return -ENOMEM;
9139 } else { 9085 } else {
@@ -9165,7 +9111,7 @@ static int __init thinkpad_acpi_module_init(void)
9165 9111
9166 ret = input_register_device(tpacpi_inputdev); 9112 ret = input_register_device(tpacpi_inputdev);
9167 if (ret < 0) { 9113 if (ret < 0) {
9168 printk(TPACPI_ERR "unable to register input device\n"); 9114 pr_err("unable to register input device\n");
9169 thinkpad_acpi_module_exit(); 9115 thinkpad_acpi_module_exit();
9170 return ret; 9116 return ret;
9171 } else { 9117 } else {
diff --git a/drivers/platform/x86/topstar-laptop.c b/drivers/platform/x86/topstar-laptop.c
index ff4b476f1950..4c20447ddbb7 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
@@ -247,7 +194,7 @@ static int __init topstar_laptop_init(void)
247 if (ret < 0) 194 if (ret < 0)
248 return ret; 195 return ret;
249 196
250 printk(KERN_INFO "Topstar Laptop ACPI extras driver loaded\n"); 197 pr_info("ACPI extras driver loaded\n");
251 198
252 return 0; 199 return 0;
253} 200}
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index 7d67a45bb2b0..cb009b2629ee 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -35,6 +35,8 @@
35 * 35 *
36 */ 36 */
37 37
38#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
39
38#define TOSHIBA_ACPI_VERSION "0.19" 40#define TOSHIBA_ACPI_VERSION "0.19"
39#define PROC_INTERFACE_VERSION 1 41#define PROC_INTERFACE_VERSION 1
40 42
@@ -48,6 +50,7 @@
48#include <linux/platform_device.h> 50#include <linux/platform_device.h>
49#include <linux/rfkill.h> 51#include <linux/rfkill.h>
50#include <linux/input.h> 52#include <linux/input.h>
53#include <linux/input/sparse-keymap.h>
51#include <linux/leds.h> 54#include <linux/leds.h>
52#include <linux/slab.h> 55#include <linux/slab.h>
53 56
@@ -59,11 +62,6 @@ MODULE_AUTHOR("John Belmonte");
59MODULE_DESCRIPTION("Toshiba Laptop ACPI Extras Driver"); 62MODULE_DESCRIPTION("Toshiba Laptop ACPI Extras Driver");
60MODULE_LICENSE("GPL"); 63MODULE_LICENSE("GPL");
61 64
62#define MY_LOGPREFIX "toshiba_acpi: "
63#define MY_ERR KERN_ERR MY_LOGPREFIX
64#define MY_NOTICE KERN_NOTICE MY_LOGPREFIX
65#define MY_INFO KERN_INFO MY_LOGPREFIX
66
67/* Toshiba ACPI method paths */ 65/* Toshiba ACPI method paths */
68#define METHOD_LCD_BRIGHTNESS "\\_SB_.PCI0.VGA_.LCD_._BCM" 66#define METHOD_LCD_BRIGHTNESS "\\_SB_.PCI0.VGA_.LCD_._BCM"
69#define TOSH_INTERFACE_1 "\\_SB_.VALD" 67#define TOSH_INTERFACE_1 "\\_SB_.VALD"
@@ -121,36 +119,29 @@ static const struct acpi_device_id toshiba_device_ids[] = {
121}; 119};
122MODULE_DEVICE_TABLE(acpi, toshiba_device_ids); 120MODULE_DEVICE_TABLE(acpi, toshiba_device_ids);
123 121
124struct key_entry { 122static const struct key_entry toshiba_acpi_keymap[] __initconst = {
125 char type; 123 { KE_KEY, 0x101, { KEY_MUTE } },
126 u16 code; 124 { KE_KEY, 0x102, { KEY_ZOOMOUT } },
127 u16 keycode; 125 { KE_KEY, 0x103, { KEY_ZOOMIN } },
128}; 126 { KE_KEY, 0x13b, { KEY_COFFEE } },
129 127 { KE_KEY, 0x13c, { KEY_BATTERY } },
130enum {KE_KEY, KE_END}; 128 { KE_KEY, 0x13d, { KEY_SLEEP } },
131 129 { KE_KEY, 0x13e, { KEY_SUSPEND } },
132static struct key_entry toshiba_acpi_keymap[] = { 130 { KE_KEY, 0x13f, { KEY_SWITCHVIDEOMODE } },
133 {KE_KEY, 0x101, KEY_MUTE}, 131 { KE_KEY, 0x140, { KEY_BRIGHTNESSDOWN } },
134 {KE_KEY, 0x102, KEY_ZOOMOUT}, 132 { KE_KEY, 0x141, { KEY_BRIGHTNESSUP } },
135 {KE_KEY, 0x103, KEY_ZOOMIN}, 133 { KE_KEY, 0x142, { KEY_WLAN } },
136 {KE_KEY, 0x13b, KEY_COFFEE}, 134 { KE_KEY, 0x143, { KEY_PROG1 } },
137 {KE_KEY, 0x13c, KEY_BATTERY}, 135 { KE_KEY, 0x17f, { KEY_FN } },
138 {KE_KEY, 0x13d, KEY_SLEEP}, 136 { KE_KEY, 0xb05, { KEY_PROG2 } },
139 {KE_KEY, 0x13e, KEY_SUSPEND}, 137 { KE_KEY, 0xb06, { KEY_WWW } },
140 {KE_KEY, 0x13f, KEY_SWITCHVIDEOMODE}, 138 { KE_KEY, 0xb07, { KEY_MAIL } },
141 {KE_KEY, 0x140, KEY_BRIGHTNESSDOWN}, 139 { KE_KEY, 0xb30, { KEY_STOP } },
142 {KE_KEY, 0x141, KEY_BRIGHTNESSUP}, 140 { KE_KEY, 0xb31, { KEY_PREVIOUSSONG } },
143 {KE_KEY, 0x142, KEY_WLAN}, 141 { KE_KEY, 0xb32, { KEY_NEXTSONG } },
144 {KE_KEY, 0x143, KEY_PROG1}, 142 { KE_KEY, 0xb33, { KEY_PLAYPAUSE } },
145 {KE_KEY, 0xb05, KEY_PROG2}, 143 { KE_KEY, 0xb5a, { KEY_MEDIA } },
146 {KE_KEY, 0xb06, KEY_WWW}, 144 { KE_END, 0 },
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}; 145};
155 146
156/* utility 147/* utility
@@ -307,7 +298,7 @@ static int toshiba_illumination_available(void)
307 in[0] = 0xf100; 298 in[0] = 0xf100;
308 status = hci_raw(in, out); 299 status = hci_raw(in, out);
309 if (ACPI_FAILURE(status)) { 300 if (ACPI_FAILURE(status)) {
310 printk(MY_INFO "Illumination device not available\n"); 301 pr_info("Illumination device not available\n");
311 return 0; 302 return 0;
312 } 303 }
313 in[0] = 0xf400; 304 in[0] = 0xf400;
@@ -326,7 +317,7 @@ static void toshiba_illumination_set(struct led_classdev *cdev,
326 in[0] = 0xf100; 317 in[0] = 0xf100;
327 status = hci_raw(in, out); 318 status = hci_raw(in, out);
328 if (ACPI_FAILURE(status)) { 319 if (ACPI_FAILURE(status)) {
329 printk(MY_INFO "Illumination device not available\n"); 320 pr_info("Illumination device not available\n");
330 return; 321 return;
331 } 322 }
332 323
@@ -337,7 +328,7 @@ static void toshiba_illumination_set(struct led_classdev *cdev,
337 in[2] = 1; 328 in[2] = 1;
338 status = hci_raw(in, out); 329 status = hci_raw(in, out);
339 if (ACPI_FAILURE(status)) { 330 if (ACPI_FAILURE(status)) {
340 printk(MY_INFO "ACPI call for illumination failed.\n"); 331 pr_info("ACPI call for illumination failed\n");
341 return; 332 return;
342 } 333 }
343 } else { 334 } else {
@@ -347,7 +338,7 @@ static void toshiba_illumination_set(struct led_classdev *cdev,
347 in[2] = 0; 338 in[2] = 0;
348 status = hci_raw(in, out); 339 status = hci_raw(in, out);
349 if (ACPI_FAILURE(status)) { 340 if (ACPI_FAILURE(status)) {
350 printk(MY_INFO "ACPI call for illumination failed.\n"); 341 pr_info("ACPI call for illumination failed.\n");
351 return; 342 return;
352 } 343 }
353 } 344 }
@@ -370,7 +361,7 @@ static enum led_brightness toshiba_illumination_get(struct led_classdev *cdev)
370 in[0] = 0xf100; 361 in[0] = 0xf100;
371 status = hci_raw(in, out); 362 status = hci_raw(in, out);
372 if (ACPI_FAILURE(status)) { 363 if (ACPI_FAILURE(status)) {
373 printk(MY_INFO "Illumination device not available\n"); 364 pr_info("Illumination device not available\n");
374 return LED_OFF; 365 return LED_OFF;
375 } 366 }
376 367
@@ -379,7 +370,7 @@ static enum led_brightness toshiba_illumination_get(struct led_classdev *cdev)
379 in[1] = 0x14e; 370 in[1] = 0x14e;
380 status = hci_raw(in, out); 371 status = hci_raw(in, out);
381 if (ACPI_FAILURE(status)) { 372 if (ACPI_FAILURE(status)) {
382 printk(MY_INFO "ACPI call for illumination failed.\n"); 373 pr_info("ACPI call for illumination failed.\n");
383 return LED_OFF; 374 return LED_OFF;
384 } 375 }
385 376
@@ -523,7 +514,7 @@ static int lcd_proc_show(struct seq_file *m, void *v)
523 seq_printf(m, "brightness_levels: %d\n", 514 seq_printf(m, "brightness_levels: %d\n",
524 HCI_LCD_BRIGHTNESS_LEVELS); 515 HCI_LCD_BRIGHTNESS_LEVELS);
525 } else { 516 } else {
526 printk(MY_ERR "Error reading LCD brightness\n"); 517 pr_err("Error reading LCD brightness\n");
527 } 518 }
528 519
529 return 0; 520 return 0;
@@ -598,7 +589,7 @@ static int video_proc_show(struct seq_file *m, void *v)
598 seq_printf(m, "crt_out: %d\n", is_crt); 589 seq_printf(m, "crt_out: %d\n", is_crt);
599 seq_printf(m, "tv_out: %d\n", is_tv); 590 seq_printf(m, "tv_out: %d\n", is_tv);
600 } else { 591 } else {
601 printk(MY_ERR "Error reading video out status\n"); 592 pr_err("Error reading video out status\n");
602 } 593 }
603 594
604 return 0; 595 return 0;
@@ -692,7 +683,7 @@ static int fan_proc_show(struct seq_file *m, void *v)
692 seq_printf(m, "running: %d\n", (value > 0)); 683 seq_printf(m, "running: %d\n", (value > 0));
693 seq_printf(m, "force_on: %d\n", force_fan); 684 seq_printf(m, "force_on: %d\n", force_fan);
694 } else { 685 } else {
695 printk(MY_ERR "Error reading fan status\n"); 686 pr_err("Error reading fan status\n");
696 } 687 }
697 688
698 return 0; 689 return 0;
@@ -756,9 +747,9 @@ static int keys_proc_show(struct seq_file *m, void *v)
756 * some machines where system events sporadically 747 * some machines where system events sporadically
757 * become disabled. */ 748 * become disabled. */
758 hci_write1(HCI_SYSTEM_EVENT, 1, &hci_result); 749 hci_write1(HCI_SYSTEM_EVENT, 1, &hci_result);
759 printk(MY_NOTICE "Re-enabled hotkeys\n"); 750 pr_notice("Re-enabled hotkeys\n");
760 } else { 751 } else {
761 printk(MY_ERR "Error reading hotkey status\n"); 752 pr_err("Error reading hotkey status\n");
762 goto end; 753 goto end;
763 } 754 }
764 } 755 }
@@ -847,69 +838,14 @@ static void remove_toshiba_proc_entries(void)
847 remove_proc_entry("version", toshiba_proc_dir); 838 remove_proc_entry("version", toshiba_proc_dir);
848} 839}
849 840
850static struct backlight_ops toshiba_backlight_data = { 841static const struct backlight_ops toshiba_backlight_data = {
851 .get_brightness = get_lcd, 842 .get_brightness = get_lcd,
852 .update_status = set_lcd_status, 843 .update_status = set_lcd_status,
853}; 844};
854 845
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) 846static void toshiba_acpi_notify(acpi_handle handle, u32 event, void *context)
910{ 847{
911 u32 hci_result, value; 848 u32 hci_result, value;
912 struct key_entry *key;
913 849
914 if (event != 0x80) 850 if (event != 0x80)
915 return; 851 return;
@@ -922,87 +858,89 @@ static void toshiba_acpi_notify(acpi_handle handle, u32 event, void *context)
922 if (value & 0x80) 858 if (value & 0x80)
923 continue; 859 continue;
924 860
925 key = toshiba_acpi_get_entry_by_scancode 861 if (!sparse_keymap_report_event(toshiba_acpi.hotkey_dev,
926 (value); 862 value, 1, true)) {
927 if (!key) { 863 pr_info("Unknown key %x\n",
928 printk(MY_INFO "Unknown key %x\n",
929 value); 864 value);
930 continue;
931 } 865 }
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) { 866 } else if (hci_result == HCI_NOT_SUPPORTED) {
939 /* This is a workaround for an unresolved issue on 867 /* This is a workaround for an unresolved issue on
940 * some machines where system events sporadically 868 * some machines where system events sporadically
941 * become disabled. */ 869 * become disabled. */
942 hci_write1(HCI_SYSTEM_EVENT, 1, &hci_result); 870 hci_write1(HCI_SYSTEM_EVENT, 1, &hci_result);
943 printk(MY_NOTICE "Re-enabled hotkeys\n"); 871 pr_notice("Re-enabled hotkeys\n");
944 } 872 }
945 } while (hci_result != HCI_EMPTY); 873 } while (hci_result != HCI_EMPTY);
946} 874}
947 875
948static int toshiba_acpi_setup_keyboard(char *device) 876static int __init toshiba_acpi_setup_keyboard(char *device)
949{ 877{
950 acpi_status status; 878 acpi_status status;
951 acpi_handle handle; 879 int error;
952 int result;
953 const struct key_entry *key;
954 880
955 status = acpi_get_handle(NULL, device, &handle); 881 status = acpi_get_handle(NULL, device, &toshiba_acpi.handle);
956 if (ACPI_FAILURE(status)) { 882 if (ACPI_FAILURE(status)) {
957 printk(MY_INFO "Unable to get notification device\n"); 883 pr_info("Unable to get notification device\n");
958 return -ENODEV;
959 }
960
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; 884 return -ENODEV;
974 } 885 }
975 886
976 toshiba_acpi.hotkey_dev = input_allocate_device(); 887 toshiba_acpi.hotkey_dev = input_allocate_device();
977 if (!toshiba_acpi.hotkey_dev) { 888 if (!toshiba_acpi.hotkey_dev) {
978 printk(MY_INFO "Unable to register input device\n"); 889 pr_info("Unable to register input device\n");
979 return -ENOMEM; 890 return -ENOMEM;
980 } 891 }
981 892
982 toshiba_acpi.hotkey_dev->name = "Toshiba input device"; 893 toshiba_acpi.hotkey_dev->name = "Toshiba input device";
983 toshiba_acpi.hotkey_dev->phys = device; 894 toshiba_acpi.hotkey_dev->phys = device;
984 toshiba_acpi.hotkey_dev->id.bustype = BUS_HOST; 895 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 896
988 for (key = toshiba_acpi_keymap; key->type != KE_END; key++) { 897 error = sparse_keymap_setup(toshiba_acpi.hotkey_dev,
989 set_bit(EV_KEY, toshiba_acpi.hotkey_dev->evbit); 898 toshiba_acpi_keymap, NULL);
990 set_bit(key->keycode, toshiba_acpi.hotkey_dev->keybit); 899 if (error)
900 goto err_free_dev;
901
902 status = acpi_install_notify_handler(toshiba_acpi.handle,
903 ACPI_DEVICE_NOTIFY, toshiba_acpi_notify, NULL);
904 if (ACPI_FAILURE(status)) {
905 pr_info("Unable to install hotkey notification\n");
906 error = -ENODEV;
907 goto err_free_keymap;
991 } 908 }
992 909
993 result = input_register_device(toshiba_acpi.hotkey_dev); 910 status = acpi_evaluate_object(toshiba_acpi.handle, "ENAB", NULL, NULL);
994 if (result) { 911 if (ACPI_FAILURE(status)) {
995 printk(MY_INFO "Unable to register input device\n"); 912 pr_info("Unable to enable hotkeys\n");
996 return result; 913 error = -ENODEV;
914 goto err_remove_notify;
915 }
916
917 error = input_register_device(toshiba_acpi.hotkey_dev);
918 if (error) {
919 pr_info("Unable to register input device\n");
920 goto err_remove_notify;
997 } 921 }
998 922
999 return 0; 923 return 0;
924
925 err_remove_notify:
926 acpi_remove_notify_handler(toshiba_acpi.handle,
927 ACPI_DEVICE_NOTIFY, toshiba_acpi_notify);
928 err_free_keymap:
929 sparse_keymap_free(toshiba_acpi.hotkey_dev);
930 err_free_dev:
931 input_free_device(toshiba_acpi.hotkey_dev);
932 toshiba_acpi.hotkey_dev = NULL;
933 return error;
1000} 934}
1001 935
1002static void toshiba_acpi_exit(void) 936static void toshiba_acpi_exit(void)
1003{ 937{
1004 if (toshiba_acpi.hotkey_dev) 938 if (toshiba_acpi.hotkey_dev) {
939 acpi_remove_notify_handler(toshiba_acpi.handle,
940 ACPI_DEVICE_NOTIFY, toshiba_acpi_notify);
941 sparse_keymap_free(toshiba_acpi.hotkey_dev);
1005 input_unregister_device(toshiba_acpi.hotkey_dev); 942 input_unregister_device(toshiba_acpi.hotkey_dev);
943 }
1006 944
1007 if (toshiba_acpi.bt_rfk) { 945 if (toshiba_acpi.bt_rfk) {
1008 rfkill_unregister(toshiba_acpi.bt_rfk); 946 rfkill_unregister(toshiba_acpi.bt_rfk);
@@ -1017,9 +955,6 @@ static void toshiba_acpi_exit(void)
1017 if (toshiba_proc_dir) 955 if (toshiba_proc_dir)
1018 remove_proc_entry(PROC_TOSHIBA, acpi_root_dir); 956 remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
1019 957
1020 acpi_remove_notify_handler(toshiba_acpi.handle, ACPI_DEVICE_NOTIFY,
1021 toshiba_acpi_notify);
1022
1023 if (toshiba_acpi.illumination_installed) 958 if (toshiba_acpi.illumination_installed)
1024 led_classdev_unregister(&toshiba_led); 959 led_classdev_unregister(&toshiba_led);
1025 960
@@ -1042,17 +977,17 @@ static int __init toshiba_acpi_init(void)
1042 if (is_valid_acpi_path(TOSH_INTERFACE_1 GHCI_METHOD)) { 977 if (is_valid_acpi_path(TOSH_INTERFACE_1 GHCI_METHOD)) {
1043 method_hci = TOSH_INTERFACE_1 GHCI_METHOD; 978 method_hci = TOSH_INTERFACE_1 GHCI_METHOD;
1044 if (toshiba_acpi_setup_keyboard(TOSH_INTERFACE_1)) 979 if (toshiba_acpi_setup_keyboard(TOSH_INTERFACE_1))
1045 printk(MY_INFO "Unable to activate hotkeys\n"); 980 pr_info("Unable to activate hotkeys\n");
1046 } else if (is_valid_acpi_path(TOSH_INTERFACE_2 GHCI_METHOD)) { 981 } else if (is_valid_acpi_path(TOSH_INTERFACE_2 GHCI_METHOD)) {
1047 method_hci = TOSH_INTERFACE_2 GHCI_METHOD; 982 method_hci = TOSH_INTERFACE_2 GHCI_METHOD;
1048 if (toshiba_acpi_setup_keyboard(TOSH_INTERFACE_2)) 983 if (toshiba_acpi_setup_keyboard(TOSH_INTERFACE_2))
1049 printk(MY_INFO "Unable to activate hotkeys\n"); 984 pr_info("Unable to activate hotkeys\n");
1050 } else 985 } else
1051 return -ENODEV; 986 return -ENODEV;
1052 987
1053 printk(MY_INFO "Toshiba Laptop ACPI Extras version %s\n", 988 pr_info("Toshiba Laptop ACPI Extras version %s\n",
1054 TOSHIBA_ACPI_VERSION); 989 TOSHIBA_ACPI_VERSION);
1055 printk(MY_INFO " HCI method: %s\n", method_hci); 990 pr_info(" HCI method: %s\n", method_hci);
1056 991
1057 mutex_init(&toshiba_acpi.mutex); 992 mutex_init(&toshiba_acpi.mutex);
1058 993
@@ -1060,7 +995,7 @@ static int __init toshiba_acpi_init(void)
1060 -1, NULL, 0); 995 -1, NULL, 0);
1061 if (IS_ERR(toshiba_acpi.p_dev)) { 996 if (IS_ERR(toshiba_acpi.p_dev)) {
1062 ret = PTR_ERR(toshiba_acpi.p_dev); 997 ret = PTR_ERR(toshiba_acpi.p_dev);
1063 printk(MY_ERR "unable to register platform device\n"); 998 pr_err("unable to register platform device\n");
1064 toshiba_acpi.p_dev = NULL; 999 toshiba_acpi.p_dev = NULL;
1065 toshiba_acpi_exit(); 1000 toshiba_acpi_exit();
1066 return ret; 1001 return ret;
@@ -1080,6 +1015,7 @@ static int __init toshiba_acpi_init(void)
1080 create_toshiba_proc_entries(); 1015 create_toshiba_proc_entries();
1081 } 1016 }
1082 1017
1018 props.type = BACKLIGHT_PLATFORM;
1083 props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1; 1019 props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1;
1084 toshiba_backlight_device = backlight_device_register("toshiba", 1020 toshiba_backlight_device = backlight_device_register("toshiba",
1085 &toshiba_acpi.p_dev->dev, 1021 &toshiba_acpi.p_dev->dev,
@@ -1089,7 +1025,7 @@ static int __init toshiba_acpi_init(void)
1089 if (IS_ERR(toshiba_backlight_device)) { 1025 if (IS_ERR(toshiba_backlight_device)) {
1090 ret = PTR_ERR(toshiba_backlight_device); 1026 ret = PTR_ERR(toshiba_backlight_device);
1091 1027
1092 printk(KERN_ERR "Could not register toshiba backlight device\n"); 1028 pr_err("Could not register toshiba backlight device\n");
1093 toshiba_backlight_device = NULL; 1029 toshiba_backlight_device = NULL;
1094 toshiba_acpi_exit(); 1030 toshiba_acpi_exit();
1095 return ret; 1031 return ret;
@@ -1103,14 +1039,14 @@ static int __init toshiba_acpi_init(void)
1103 &toshiba_rfk_ops, 1039 &toshiba_rfk_ops,
1104 &toshiba_acpi); 1040 &toshiba_acpi);
1105 if (!toshiba_acpi.bt_rfk) { 1041 if (!toshiba_acpi.bt_rfk) {
1106 printk(MY_ERR "unable to allocate rfkill device\n"); 1042 pr_err("unable to allocate rfkill device\n");
1107 toshiba_acpi_exit(); 1043 toshiba_acpi_exit();
1108 return -ENOMEM; 1044 return -ENOMEM;
1109 } 1045 }
1110 1046
1111 ret = rfkill_register(toshiba_acpi.bt_rfk); 1047 ret = rfkill_register(toshiba_acpi.bt_rfk);
1112 if (ret) { 1048 if (ret) {
1113 printk(MY_ERR "unable to register rfkill device\n"); 1049 pr_err("unable to register rfkill device\n");
1114 rfkill_destroy(toshiba_acpi.bt_rfk); 1050 rfkill_destroy(toshiba_acpi.bt_rfk);
1115 toshiba_acpi_exit(); 1051 toshiba_acpi_exit();
1116 return ret; 1052 return ret;
diff --git a/drivers/platform/x86/toshiba_bluetooth.c b/drivers/platform/x86/toshiba_bluetooth.c
index 944068611919..5fb7186694df 100644
--- a/drivers/platform/x86/toshiba_bluetooth.c
+++ b/drivers/platform/x86/toshiba_bluetooth.c
@@ -17,6 +17,8 @@
17 * delivered. 17 * delivered.
18 */ 18 */
19 19
20#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
21
20#include <linux/kernel.h> 22#include <linux/kernel.h>
21#include <linux/module.h> 23#include <linux/module.h>
22#include <linux/init.h> 24#include <linux/init.h>
@@ -70,14 +72,13 @@ static int toshiba_bluetooth_enable(acpi_handle handle)
70 if (!(result & 0x01)) 72 if (!(result & 0x01))
71 return 0; 73 return 0;
72 74
73 printk(KERN_INFO "toshiba_bluetooth: Re-enabling Toshiba Bluetooth\n"); 75 pr_info("Re-enabling Toshiba Bluetooth\n");
74 res1 = acpi_evaluate_object(handle, "AUSB", NULL, NULL); 76 res1 = acpi_evaluate_object(handle, "AUSB", NULL, NULL);
75 res2 = acpi_evaluate_object(handle, "BTPO", NULL, NULL); 77 res2 = acpi_evaluate_object(handle, "BTPO", NULL, NULL);
76 if (!ACPI_FAILURE(res1) || !ACPI_FAILURE(res2)) 78 if (!ACPI_FAILURE(res1) || !ACPI_FAILURE(res2))
77 return 0; 79 return 0;
78 80
79 printk(KERN_WARNING "toshiba_bluetooth: Failed to re-enable " 81 pr_warn("Failed to re-enable Toshiba Bluetooth\n");
80 "Toshiba Bluetooth\n");
81 82
82 return -ENODEV; 83 return -ENODEV;
83} 84}
@@ -107,8 +108,8 @@ static int toshiba_bt_rfkill_add(struct acpi_device *device)
107 &bt_present); 108 &bt_present);
108 109
109 if (!ACPI_FAILURE(status) && bt_present) { 110 if (!ACPI_FAILURE(status) && bt_present) {
110 printk(KERN_INFO "Detected Toshiba ACPI Bluetooth device - " 111 pr_info("Detected Toshiba ACPI Bluetooth device - "
111 "installing RFKill handler\n"); 112 "installing RFKill handler\n");
112 result = toshiba_bluetooth_enable(device->handle); 113 result = toshiba_bluetooth_enable(device->handle);
113 } 114 }
114 115
diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c
index b2978a04317f..f23d5a84e7b1 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}
@@ -562,21 +549,34 @@ acpi_status wmi_install_notify_handler(const char *guid,
562wmi_notify_handler handler, void *data) 549wmi_notify_handler handler, void *data)
563{ 550{
564 struct wmi_block *block; 551 struct wmi_block *block;
565 acpi_status status; 552 acpi_status status = AE_NOT_EXIST;
553 char tmp[16], guid_input[16];
554 struct list_head *p;
566 555
567 if (!guid || !handler) 556 if (!guid || !handler)
568 return AE_BAD_PARAMETER; 557 return AE_BAD_PARAMETER;
569 558
570 if (!find_guid(guid, &block)) 559 wmi_parse_guid(guid, tmp);
571 return AE_NOT_EXIST; 560 wmi_swap_bytes(tmp, guid_input);
572 561
573 if (block->handler && block->handler != wmi_notify_debug) 562 list_for_each(p, &wmi_block_list) {
574 return AE_ALREADY_ACQUIRED; 563 acpi_status wmi_status;
564 block = list_entry(p, struct wmi_block, list);
575 565
576 block->handler = handler; 566 if (memcmp(block->gblock.guid, guid_input, 16) == 0) {
577 block->handler_data = data; 567 if (block->handler &&
568 block->handler != wmi_notify_debug)
569 return AE_ALREADY_ACQUIRED;
578 570
579 status = wmi_method_enable(block, 1); 571 block->handler = handler;
572 block->handler_data = data;
573
574 wmi_status = wmi_method_enable(block, 1);
575 if ((wmi_status != AE_OK) ||
576 ((wmi_status == AE_OK) && (status == AE_NOT_EXIST)))
577 status = wmi_status;
578 }
579 }
580 580
581 return status; 581 return status;
582} 582}
@@ -590,24 +590,40 @@ EXPORT_SYMBOL_GPL(wmi_install_notify_handler);
590acpi_status wmi_remove_notify_handler(const char *guid) 590acpi_status wmi_remove_notify_handler(const char *guid)
591{ 591{
592 struct wmi_block *block; 592 struct wmi_block *block;
593 acpi_status status = AE_OK; 593 acpi_status status = AE_NOT_EXIST;
594 char tmp[16], guid_input[16];
595 struct list_head *p;
594 596
595 if (!guid) 597 if (!guid)
596 return AE_BAD_PARAMETER; 598 return AE_BAD_PARAMETER;
597 599
598 if (!find_guid(guid, &block)) 600 wmi_parse_guid(guid, tmp);
599 return AE_NOT_EXIST; 601 wmi_swap_bytes(tmp, guid_input);
600 602
601 if (!block->handler || block->handler == wmi_notify_debug) 603 list_for_each(p, &wmi_block_list) {
602 return AE_NULL_ENTRY; 604 acpi_status wmi_status;
605 block = list_entry(p, struct wmi_block, list);
603 606
604 if (debug_event) { 607 if (memcmp(block->gblock.guid, guid_input, 16) == 0) {
605 block->handler = wmi_notify_debug; 608 if (!block->handler ||
606 } else { 609 block->handler == wmi_notify_debug)
607 status = wmi_method_enable(block, 0); 610 return AE_NULL_ENTRY;
608 block->handler = NULL; 611
609 block->handler_data = NULL; 612 if (debug_event) {
613 block->handler = wmi_notify_debug;
614 status = AE_OK;
615 } else {
616 wmi_status = wmi_method_enable(block, 0);
617 block->handler = NULL;
618 block->handler_data = NULL;
619 if ((wmi_status != AE_OK) ||
620 ((wmi_status == AE_OK) &&
621 (status == AE_NOT_EXIST)))
622 status = wmi_status;
623 }
624 }
610 } 625 }
626
611 return status; 627 return status;
612} 628}
613EXPORT_SYMBOL_GPL(wmi_remove_notify_handler); 629EXPORT_SYMBOL_GPL(wmi_remove_notify_handler);
@@ -633,7 +649,7 @@ acpi_status wmi_get_event_data(u32 event, struct acpi_buffer *out)
633 params[0].type = ACPI_TYPE_INTEGER; 649 params[0].type = ACPI_TYPE_INTEGER;
634 params[0].integer.value = event; 650 params[0].integer.value = event;
635 651
636 list_for_each(p, &wmi_blocks.list) { 652 list_for_each(p, &wmi_block_list) {
637 wblock = list_entry(p, struct wmi_block, list); 653 wblock = list_entry(p, struct wmi_block, list);
638 gblock = &wblock->gblock; 654 gblock = &wblock->gblock;
639 655
@@ -662,7 +678,7 @@ EXPORT_SYMBOL_GPL(wmi_has_guid);
662/* 678/*
663 * sysfs interface 679 * sysfs interface
664 */ 680 */
665static ssize_t show_modalias(struct device *dev, struct device_attribute *attr, 681static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
666 char *buf) 682 char *buf)
667{ 683{
668 char guid_string[37]; 684 char guid_string[37];
@@ -676,7 +692,11 @@ static ssize_t show_modalias(struct device *dev, struct device_attribute *attr,
676 692
677 return sprintf(buf, "wmi:%s\n", guid_string); 693 return sprintf(buf, "wmi:%s\n", guid_string);
678} 694}
679static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL); 695
696static struct device_attribute wmi_dev_attrs[] = {
697 __ATTR_RO(modalias),
698 __ATTR_NULL
699};
680 700
681static int wmi_dev_uevent(struct device *dev, struct kobj_uevent_env *env) 701static int wmi_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
682{ 702{
@@ -702,108 +722,51 @@ static int wmi_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
702 722
703static void wmi_dev_free(struct device *dev) 723static void wmi_dev_free(struct device *dev)
704{ 724{
705 kfree(dev); 725 struct wmi_block *wmi_block = container_of(dev, struct wmi_block, dev);
726
727 kfree(wmi_block);
706} 728}
707 729
708static struct class wmi_class = { 730static struct class wmi_class = {
709 .name = "wmi", 731 .name = "wmi",
710 .dev_release = wmi_dev_free, 732 .dev_release = wmi_dev_free,
711 .dev_uevent = wmi_dev_uevent, 733 .dev_uevent = wmi_dev_uevent,
734 .dev_attrs = wmi_dev_attrs,
712}; 735};
713 736
714static int wmi_create_devs(void) 737static int wmi_create_device(const struct guid_block *gblock,
738 struct wmi_block *wblock, acpi_handle handle)
715{ 739{
716 int result;
717 char guid_string[37]; 740 char guid_string[37];
718 struct guid_block *gblock;
719 struct wmi_block *wblock;
720 struct list_head *p;
721 struct device *guid_dev;
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 741
738 wmi_gtoa(gblock->guid, guid_string); 742 wblock->dev.class = &wmi_class;
739 dev_set_name(guid_dev, guid_string);
740 743
741 result = device_register(guid_dev); 744 wmi_gtoa(gblock->guid, guid_string);
742 if (result) 745 dev_set_name(&wblock->dev, guid_string);
743 return result;
744 746
745 result = device_create_file(guid_dev, &dev_attr_modalias); 747 dev_set_drvdata(&wblock->dev, wblock);
746 if (result)
747 return result;
748 }
749 748
750 return 0; 749 return device_register(&wblock->dev);
751} 750}
752 751
753static void wmi_remove_devs(void) 752static void wmi_free_devices(void)
754{ 753{
755 struct guid_block *gblock; 754 struct wmi_block *wblock, *next;
756 struct wmi_block *wblock;
757 struct list_head *p;
758 struct device *guid_dev;
759 755
760 /* Delete devices for all the GUIDs */ 756 /* Delete devices for all the GUIDs */
761 list_for_each(p, &wmi_blocks.list) { 757 list_for_each_entry_safe(wblock, next, &wmi_block_list, list)
762 wblock = list_entry(p, struct wmi_block, list); 758 if (wblock->dev.class)
763 759 device_unregister(&wblock->dev);
764 guid_dev = wblock->dev;
765 gblock = &wblock->gblock;
766
767 device_remove_file(guid_dev, &dev_attr_modalias);
768
769 device_unregister(guid_dev);
770 }
771}
772
773static void wmi_class_exit(void)
774{
775 wmi_remove_devs();
776 class_unregister(&wmi_class);
777}
778
779static int wmi_class_init(void)
780{
781 int ret;
782
783 ret = class_register(&wmi_class);
784 if (ret)
785 return ret;
786
787 ret = wmi_create_devs();
788 if (ret)
789 wmi_class_exit();
790
791 return ret;
792} 760}
793 761
794static bool guid_already_parsed(const char *guid_string) 762static bool guid_already_parsed(const char *guid_string)
795{ 763{
796 struct guid_block *gblock;
797 struct wmi_block *wblock; 764 struct wmi_block *wblock;
798 struct list_head *p;
799 765
800 list_for_each(p, &wmi_blocks.list) { 766 list_for_each_entry(wblock, &wmi_block_list, list)
801 wblock = list_entry(p, struct wmi_block, list); 767 if (memcmp(wblock->gblock.guid, guid_string, 16) == 0)
802 gblock = &wblock->gblock;
803
804 if (strncmp(gblock->guid, guid_string, 16) == 0)
805 return true; 768 return true;
806 } 769
807 return false; 770 return false;
808} 771}
809 772
@@ -814,68 +777,67 @@ static acpi_status parse_wdg(acpi_handle handle)
814{ 777{
815 struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL}; 778 struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL};
816 union acpi_object *obj; 779 union acpi_object *obj;
817 struct guid_block *gblock; 780 const struct guid_block *gblock;
818 struct wmi_block *wblock; 781 struct wmi_block *wblock;
819 char guid_string[37];
820 acpi_status status; 782 acpi_status status;
783 int retval;
821 u32 i, total; 784 u32 i, total;
822 785
823 status = acpi_evaluate_object(handle, "_WDG", NULL, &out); 786 status = acpi_evaluate_object(handle, "_WDG", NULL, &out);
824
825 if (ACPI_FAILURE(status)) 787 if (ACPI_FAILURE(status))
826 return status; 788 return -ENXIO;
827 789
828 obj = (union acpi_object *) out.pointer; 790 obj = (union acpi_object *) out.pointer;
791 if (!obj)
792 return -ENXIO;
829 793
830 if (obj->type != ACPI_TYPE_BUFFER) 794 if (obj->type != ACPI_TYPE_BUFFER) {
831 return AE_ERROR; 795 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; 796 goto out_free_pointer;
839 } 797 }
840 798
799 gblock = (const struct guid_block *)obj->buffer.pointer;
800 total = obj->buffer.length / sizeof(struct guid_block);
801
841 for (i = 0; i < total; i++) { 802 for (i = 0; i < total; i++) {
803 if (debug_dump_wdg)
804 wmi_dump_wdg(&gblock[i]);
805
806 wblock = kzalloc(sizeof(struct wmi_block), GFP_KERNEL);
807 if (!wblock)
808 return AE_NO_MEMORY;
809
810 wblock->handle = handle;
811 wblock->gblock = gblock[i];
812
842 /* 813 /*
843 Some WMI devices, like those for nVidia hooks, have a 814 Some WMI devices, like those for nVidia hooks, have a
844 duplicate GUID. It's not clear what we should do in this 815 duplicate GUID. It's not clear what we should do in this
845 case yet, so for now, we'll just ignore the duplicate. 816 case yet, so for now, we'll just ignore the duplicate
846 Anyone who wants to add support for that device can come 817 for device creation.
847 up with a better workaround for the mess then.
848 */ 818 */
849 if (guid_already_parsed(gblock[i].guid) == true) { 819 if (!guid_already_parsed(gblock[i].guid)) {
850 wmi_gtoa(gblock[i].guid, guid_string); 820 retval = wmi_create_device(&gblock[i], wblock, handle);
851 printk(KERN_INFO PREFIX "Skipping duplicate GUID %s\n", 821 if (retval) {
852 guid_string); 822 wmi_free_devices();
853 continue; 823 goto out_free_pointer;
824 }
854 } 825 }
855 if (debug_dump_wdg)
856 wmi_dump_wdg(&gblock[i]);
857 826
858 wblock = kzalloc(sizeof(struct wmi_block), GFP_KERNEL); 827 list_add_tail(&wblock->list, &wmi_block_list);
859 if (!wblock) {
860 status = AE_NO_MEMORY;
861 goto out_free_gblock;
862 }
863 828
864 wblock->gblock = gblock[i];
865 wblock->handle = handle;
866 if (debug_event) { 829 if (debug_event) {
867 wblock->handler = wmi_notify_debug; 830 wblock->handler = wmi_notify_debug;
868 status = wmi_method_enable(wblock, 1); 831 wmi_method_enable(wblock, 1);
869 } 832 }
870 list_add_tail(&wblock->list, &wmi_blocks.list);
871 } 833 }
872 834
873out_free_gblock: 835 retval = 0;
874 kfree(gblock); 836
875out_free_pointer: 837out_free_pointer:
876 kfree(out.pointer); 838 kfree(out.pointer);
877 839
878 return status; 840 return retval;
879} 841}
880 842
881/* 843/*
@@ -929,7 +891,7 @@ static void acpi_wmi_notify(struct acpi_device *device, u32 event)
929 struct list_head *p; 891 struct list_head *p;
930 char guid_string[37]; 892 char guid_string[37];
931 893
932 list_for_each(p, &wmi_blocks.list) { 894 list_for_each(p, &wmi_block_list) {
933 wblock = list_entry(p, struct wmi_block, list); 895 wblock = list_entry(p, struct wmi_block, list);
934 block = &wblock->gblock; 896 block = &wblock->gblock;
935 897
@@ -939,8 +901,7 @@ static void acpi_wmi_notify(struct acpi_device *device, u32 event)
939 wblock->handler(event, wblock->handler_data); 901 wblock->handler(event, wblock->handler_data);
940 if (debug_event) { 902 if (debug_event) {
941 wmi_gtoa(wblock->gblock.guid, guid_string); 903 wmi_gtoa(wblock->gblock.guid, guid_string);
942 printk(KERN_INFO PREFIX "DEBUG Event GUID:" 904 pr_info("DEBUG Event GUID: %s\n", guid_string);
943 " %s\n", guid_string);
944 } 905 }
945 906
946 acpi_bus_generate_netlink_event( 907 acpi_bus_generate_netlink_event(
@@ -955,6 +916,7 @@ static int acpi_wmi_remove(struct acpi_device *device, int type)
955{ 916{
956 acpi_remove_address_space_handler(device->handle, 917 acpi_remove_address_space_handler(device->handle,
957 ACPI_ADR_SPACE_EC, &acpi_wmi_ec_space_handler); 918 ACPI_ADR_SPACE_EC, &acpi_wmi_ec_space_handler);
919 wmi_free_devices();
958 920
959 return 0; 921 return 0;
960} 922}
@@ -962,68 +924,57 @@ static int acpi_wmi_remove(struct acpi_device *device, int type)
962static int acpi_wmi_add(struct acpi_device *device) 924static int acpi_wmi_add(struct acpi_device *device)
963{ 925{
964 acpi_status status; 926 acpi_status status;
965 int result = 0; 927 int error;
966 928
967 status = acpi_install_address_space_handler(device->handle, 929 status = acpi_install_address_space_handler(device->handle,
968 ACPI_ADR_SPACE_EC, 930 ACPI_ADR_SPACE_EC,
969 &acpi_wmi_ec_space_handler, 931 &acpi_wmi_ec_space_handler,
970 NULL, NULL); 932 NULL, NULL);
971 if (ACPI_FAILURE(status))
972 return -ENODEV;
973
974 status = parse_wdg(device->handle);
975 if (ACPI_FAILURE(status)) { 933 if (ACPI_FAILURE(status)) {
976 printk(KERN_ERR PREFIX "Error installing EC region handler\n"); 934 pr_err("Error installing EC region handler\n");
977 return -ENODEV; 935 return -ENODEV;
978 } 936 }
979 937
980 return result; 938 error = parse_wdg(device->handle);
939 if (error) {
940 acpi_remove_address_space_handler(device->handle,
941 ACPI_ADR_SPACE_EC,
942 &acpi_wmi_ec_space_handler);
943 pr_err("Failed to parse WDG method\n");
944 return error;
945 }
946
947 return 0;
981} 948}
982 949
983static int __init acpi_wmi_init(void) 950static int __init acpi_wmi_init(void)
984{ 951{
985 int result; 952 int error;
986
987 INIT_LIST_HEAD(&wmi_blocks.list);
988 953
989 if (acpi_disabled) 954 if (acpi_disabled)
990 return -ENODEV; 955 return -ENODEV;
991 956
992 result = acpi_bus_register_driver(&acpi_wmi_driver); 957 error = class_register(&wmi_class);
993 958 if (error)
994 if (result < 0) { 959 return error;
995 printk(KERN_INFO PREFIX "Error loading mapper\n");
996 return -ENODEV;
997 }
998 960
999 result = wmi_class_init(); 961 error = acpi_bus_register_driver(&acpi_wmi_driver);
1000 if (result) { 962 if (error) {
1001 acpi_bus_unregister_driver(&acpi_wmi_driver); 963 pr_err("Error loading mapper\n");
1002 return result; 964 class_unregister(&wmi_class);
965 return error;
1003 } 966 }
1004 967
1005 printk(KERN_INFO PREFIX "Mapper loaded\n"); 968 pr_info("Mapper loaded\n");
1006 969 return 0;
1007 return result;
1008} 970}
1009 971
1010static void __exit acpi_wmi_exit(void) 972static void __exit acpi_wmi_exit(void)
1011{ 973{
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); 974 acpi_bus_unregister_driver(&acpi_wmi_driver);
975 class_unregister(&wmi_class);
1018 976
1019 list_for_each_safe(p, tmp, &wmi_blocks.list) { 977 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} 978}
1028 979
1029subsys_initcall(acpi_wmi_init); 980subsys_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);
diff --git a/drivers/platform/x86/xo15-ebook.c b/drivers/platform/x86/xo15-ebook.c
new file mode 100644
index 000000000000..fad153dc0355
--- /dev/null
+++ b/drivers/platform/x86/xo15-ebook.c
@@ -0,0 +1,181 @@
1/*
2 * OLPC XO-1.5 ebook switch driver
3 * (based on generic ACPI button driver)
4 *
5 * Copyright (C) 2009 Paul Fox <pgf@laptop.org>
6 * Copyright (C) 2010 One Laptop per Child
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or (at
11 * your option) any later version.
12 */
13
14#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
15
16#include <linux/kernel.h>
17#include <linux/module.h>
18#include <linux/init.h>
19#include <linux/types.h>
20#include <linux/input.h>
21#include <acpi/acpi_bus.h>
22#include <acpi/acpi_drivers.h>
23
24#define MODULE_NAME "xo15-ebook"
25
26#define XO15_EBOOK_CLASS MODULE_NAME
27#define XO15_EBOOK_TYPE_UNKNOWN 0x00
28#define XO15_EBOOK_NOTIFY_STATUS 0x80
29
30#define XO15_EBOOK_SUBCLASS "ebook"
31#define XO15_EBOOK_HID "XO15EBK"
32#define XO15_EBOOK_DEVICE_NAME "EBook Switch"
33
34ACPI_MODULE_NAME(MODULE_NAME);
35
36MODULE_DESCRIPTION("OLPC XO-1.5 ebook switch driver");
37MODULE_LICENSE("GPL");
38
39static const struct acpi_device_id ebook_device_ids[] = {
40 { XO15_EBOOK_HID, 0 },
41 { "", 0 },
42};
43MODULE_DEVICE_TABLE(acpi, ebook_device_ids);
44
45struct ebook_switch {
46 struct input_dev *input;
47 char phys[32]; /* for input device */
48};
49
50static int ebook_send_state(struct acpi_device *device)
51{
52 struct ebook_switch *button = acpi_driver_data(device);
53 unsigned long long state;
54 acpi_status status;
55
56 status = acpi_evaluate_integer(device->handle, "EBK", NULL, &state);
57 if (ACPI_FAILURE(status))
58 return -EIO;
59
60 /* input layer checks if event is redundant */
61 input_report_switch(button->input, SW_TABLET_MODE, !state);
62 input_sync(button->input);
63 return 0;
64}
65
66static void ebook_switch_notify(struct acpi_device *device, u32 event)
67{
68 switch (event) {
69 case ACPI_FIXED_HARDWARE_EVENT:
70 case XO15_EBOOK_NOTIFY_STATUS:
71 ebook_send_state(device);
72 break;
73 default:
74 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
75 "Unsupported event [0x%x]\n", event));
76 break;
77 }
78}
79
80static int ebook_switch_resume(struct acpi_device *device)
81{
82 return ebook_send_state(device);
83}
84
85static int ebook_switch_add(struct acpi_device *device)
86{
87 struct ebook_switch *button;
88 struct input_dev *input;
89 const char *hid = acpi_device_hid(device);
90 char *name, *class;
91 int error;
92
93 button = kzalloc(sizeof(struct ebook_switch), GFP_KERNEL);
94 if (!button)
95 return -ENOMEM;
96
97 device->driver_data = button;
98
99 button->input = input = input_allocate_device();
100 if (!input) {
101 error = -ENOMEM;
102 goto err_free_button;
103 }
104
105 name = acpi_device_name(device);
106 class = acpi_device_class(device);
107
108 if (strcmp(hid, XO15_EBOOK_HID)) {
109 pr_err("Unsupported hid [%s]\n", hid);
110 error = -ENODEV;
111 goto err_free_input;
112 }
113
114 strcpy(name, XO15_EBOOK_DEVICE_NAME);
115 sprintf(class, "%s/%s", XO15_EBOOK_CLASS, XO15_EBOOK_SUBCLASS);
116
117 snprintf(button->phys, sizeof(button->phys), "%s/button/input0", hid);
118
119 input->name = name;
120 input->phys = button->phys;
121 input->id.bustype = BUS_HOST;
122 input->dev.parent = &device->dev;
123
124 input->evbit[0] = BIT_MASK(EV_SW);
125 set_bit(SW_TABLET_MODE, input->swbit);
126
127 error = input_register_device(input);
128 if (error)
129 goto err_free_input;
130
131 ebook_send_state(device);
132
133 if (device->wakeup.flags.valid) {
134 /* Button's GPE is run-wake GPE */
135 acpi_enable_gpe(device->wakeup.gpe_device,
136 device->wakeup.gpe_number);
137 device_set_wakeup_enable(&device->dev, true);
138 }
139
140 return 0;
141
142 err_free_input:
143 input_free_device(input);
144 err_free_button:
145 kfree(button);
146 return error;
147}
148
149static int ebook_switch_remove(struct acpi_device *device, int type)
150{
151 struct ebook_switch *button = acpi_driver_data(device);
152
153 input_unregister_device(button->input);
154 kfree(button);
155 return 0;
156}
157
158static struct acpi_driver xo15_ebook_driver = {
159 .name = MODULE_NAME,
160 .class = XO15_EBOOK_CLASS,
161 .ids = ebook_device_ids,
162 .ops = {
163 .add = ebook_switch_add,
164 .resume = ebook_switch_resume,
165 .remove = ebook_switch_remove,
166 .notify = ebook_switch_notify,
167 },
168};
169
170static int __init xo15_ebook_init(void)
171{
172 return acpi_bus_register_driver(&xo15_ebook_driver);
173}
174
175static void __exit xo15_ebook_exit(void)
176{
177 acpi_bus_unregister_driver(&xo15_ebook_driver);
178}
179
180module_init(xo15_ebook_init);
181module_exit(xo15_ebook_exit);