aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/platform')
-rw-r--r--drivers/platform/x86/Kconfig24
-rw-r--r--drivers/platform/x86/Makefile1
-rw-r--r--drivers/platform/x86/acer-wmi.c8
-rw-r--r--drivers/platform/x86/asus-laptop.c1745
-rw-r--r--drivers/platform/x86/asus_acpi.c11
-rw-r--r--drivers/platform/x86/classmate-laptop.c17
-rw-r--r--drivers/platform/x86/compal-laptop.c11
-rw-r--r--drivers/platform/x86/dell-laptop.c23
-rw-r--r--drivers/platform/x86/dell-wmi.c17
-rw-r--r--drivers/platform/x86/eeepc-laptop.c30
-rw-r--r--drivers/platform/x86/eeepc-wmi.c158
-rw-r--r--drivers/platform/x86/fujitsu-laptop.c15
-rw-r--r--drivers/platform/x86/hp-wmi.c20
-rw-r--r--drivers/platform/x86/intel_menlow.c2
-rw-r--r--drivers/platform/x86/msi-laptop.c367
-rw-r--r--drivers/platform/x86/msi-wmi.c16
-rw-r--r--drivers/platform/x86/panasonic-laptop.c44
-rw-r--r--drivers/platform/x86/sony-laptop.c100
-rw-r--r--drivers/platform/x86/tc1100-wmi.c1
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c133
-rw-r--r--drivers/platform/x86/topstar-laptop.c14
-rw-r--r--drivers/platform/x86/toshiba_acpi.c58
-rw-r--r--drivers/platform/x86/wmi.c1
23 files changed, 1769 insertions, 1047 deletions
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 6848f213eb5..7bec4588c26 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -59,6 +59,8 @@ config ASUS_LAPTOP
59 select NEW_LEDS 59 select NEW_LEDS
60 select BACKLIGHT_CLASS_DEVICE 60 select BACKLIGHT_CLASS_DEVICE
61 depends on INPUT 61 depends on INPUT
62 depends on RFKILL || RFKILL = n
63 select INPUT_SPARSEKMAP
62 ---help--- 64 ---help---
63 This is the new Linux driver for Asus laptops. It may also support some 65 This is the new Linux driver for Asus laptops. It may also support some
64 MEDION, JVC or VICTOR laptops. It makes all the extra buttons generate 66 MEDION, JVC or VICTOR laptops. It makes all the extra buttons generate
@@ -148,6 +150,7 @@ config MSI_LAPTOP
148 tristate "MSI Laptop Extras" 150 tristate "MSI Laptop Extras"
149 depends on ACPI 151 depends on ACPI
150 depends on BACKLIGHT_CLASS_DEVICE 152 depends on BACKLIGHT_CLASS_DEVICE
153 depends on RFKILL
151 ---help--- 154 ---help---
152 This is a driver for laptops built by MSI (MICRO-STAR 155 This is a driver for laptops built by MSI (MICRO-STAR
153 INTERNATIONAL): 156 INTERNATIONAL):
@@ -177,6 +180,7 @@ config COMPAL_LAPTOP
177 tristate "Compal Laptop Extras" 180 tristate "Compal Laptop Extras"
178 depends on ACPI 181 depends on ACPI
179 depends on BACKLIGHT_CLASS_DEVICE 182 depends on BACKLIGHT_CLASS_DEVICE
183 depends on RFKILL
180 ---help--- 184 ---help---
181 This is a driver for laptops built by Compal: 185 This is a driver for laptops built by Compal:
182 186
@@ -320,9 +324,15 @@ config THINKPAD_ACPI_VIDEO
320 server running, phase of the moon, and the current mood of 324 server running, phase of the moon, and the current mood of
321 Schroedinger's cat. If you can use X.org's RandR to control 325 Schroedinger's cat. If you can use X.org's RandR to control
322 your ThinkPad's video output ports instead of this feature, 326 your ThinkPad's video output ports instead of this feature,
323 don't think twice: do it and say N here to save some memory. 327 don't think twice: do it and say N here to save memory and avoid
328 bad interactions with X.org.
329
330 NOTE: access to this feature is limited to processes with the
331 CAP_SYS_ADMIN capability, to avoid local DoS issues in platforms
332 where it interacts badly with X.org.
324 333
325 If you are not sure, say Y here. 334 If you are not sure, say Y here but do try to check if you could
335 be using X.org RandR instead.
326 336
327config THINKPAD_ACPI_HOTKEY_POLL 337config THINKPAD_ACPI_HOTKEY_POLL
328 bool "Support NVRAM polling for hot keys" 338 bool "Support NVRAM polling for hot keys"
@@ -375,6 +385,16 @@ config EEEPC_LAPTOP
375 385
376 If you have an Eee PC laptop, say Y or M here. 386 If you have an Eee PC laptop, say Y or M here.
377 387
388config EEEPC_WMI
389 tristate "Eee PC WMI Hotkey Driver (EXPERIMENTAL)"
390 depends on ACPI_WMI
391 depends on INPUT
392 depends on EXPERIMENTAL
393 ---help---
394 Say Y here if you want to support WMI-based hotkeys on Eee PC laptops.
395
396 To compile this driver as a module, choose M here: the module will
397 be called eeepc-wmi.
378 398
379config ACPI_WMI 399config ACPI_WMI
380 tristate "WMI" 400 tristate "WMI"
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index 9cd9fa0a27e..a906490e353 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -4,6 +4,7 @@
4# 4#
5obj-$(CONFIG_ASUS_LAPTOP) += asus-laptop.o 5obj-$(CONFIG_ASUS_LAPTOP) += asus-laptop.o
6obj-$(CONFIG_EEEPC_LAPTOP) += eeepc-laptop.o 6obj-$(CONFIG_EEEPC_LAPTOP) += eeepc-laptop.o
7obj-$(CONFIG_EEEPC_WMI) += eeepc-wmi.o
7obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o 8obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o
8obj-$(CONFIG_ACPI_CMPC) += classmate-laptop.o 9obj-$(CONFIG_ACPI_CMPC) += classmate-laptop.o
9obj-$(CONFIG_COMPAL_LAPTOP) += compal-laptop.o 10obj-$(CONFIG_COMPAL_LAPTOP) += compal-laptop.o
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index 226b3e93498..1ea6c434d33 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -36,6 +36,7 @@
36#include <linux/rfkill.h> 36#include <linux/rfkill.h>
37#include <linux/workqueue.h> 37#include <linux/workqueue.h>
38#include <linux/debugfs.h> 38#include <linux/debugfs.h>
39#include <linux/slab.h>
39 40
40#include <acpi/acpi_drivers.h> 41#include <acpi/acpi_drivers.h>
41 42
@@ -922,9 +923,13 @@ static struct backlight_ops acer_bl_ops = {
922 923
923static int __devinit acer_backlight_init(struct device *dev) 924static int __devinit acer_backlight_init(struct device *dev)
924{ 925{
926 struct backlight_properties props;
925 struct backlight_device *bd; 927 struct backlight_device *bd;
926 928
927 bd = backlight_device_register("acer-wmi", dev, NULL, &acer_bl_ops); 929 memset(&props, 0, sizeof(struct backlight_properties));
930 props.max_brightness = max_brightness;
931 bd = backlight_device_register("acer-wmi", dev, NULL, &acer_bl_ops,
932 &props);
928 if (IS_ERR(bd)) { 933 if (IS_ERR(bd)) {
929 printk(ACER_ERR "Could not register Acer backlight device\n"); 934 printk(ACER_ERR "Could not register Acer backlight device\n");
930 acer_backlight_device = NULL; 935 acer_backlight_device = NULL;
@@ -935,7 +940,6 @@ static int __devinit acer_backlight_init(struct device *dev)
935 940
936 bd->props.power = FB_BLANK_UNBLANK; 941 bd->props.power = FB_BLANK_UNBLANK;
937 bd->props.brightness = read_brightness(bd); 942 bd->props.brightness = read_brightness(bd);
938 bd->props.max_brightness = max_brightness;
939 backlight_update_status(bd); 943 backlight_update_status(bd);
940 return 0; 944 return 0;
941} 945}
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index 61a1c750365..52262b012ab 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -45,58 +45,24 @@
45#include <linux/fb.h> 45#include <linux/fb.h>
46#include <linux/leds.h> 46#include <linux/leds.h>
47#include <linux/platform_device.h> 47#include <linux/platform_device.h>
48#include <linux/uaccess.h>
49#include <linux/input.h>
50#include <linux/input/sparse-keymap.h>
51#include <linux/rfkill.h>
52#include <linux/slab.h>
48#include <acpi/acpi_drivers.h> 53#include <acpi/acpi_drivers.h>
49#include <acpi/acpi_bus.h> 54#include <acpi/acpi_bus.h>
50#include <asm/uaccess.h>
51#include <linux/input.h>
52
53#define ASUS_LAPTOP_VERSION "0.42"
54
55#define ASUS_HOTK_NAME "Asus Laptop Support"
56#define ASUS_HOTK_CLASS "hotkey"
57#define ASUS_HOTK_DEVICE_NAME "Hotkey"
58#define ASUS_HOTK_FILE KBUILD_MODNAME
59#define ASUS_HOTK_PREFIX "\\_SB.ATKD."
60 55
56#define ASUS_LAPTOP_VERSION "0.42"
61 57
62/* 58#define ASUS_LAPTOP_NAME "Asus Laptop Support"
63 * Some events we use, same for all Asus 59#define ASUS_LAPTOP_CLASS "hotkey"
64 */ 60#define ASUS_LAPTOP_DEVICE_NAME "Hotkey"
65#define ATKD_BR_UP 0x10 61#define ASUS_LAPTOP_FILE KBUILD_MODNAME
66#define ATKD_BR_DOWN 0x20 62#define ASUS_LAPTOP_PREFIX "\\_SB.ATKD."
67#define ATKD_LCD_ON 0x33
68#define ATKD_LCD_OFF 0x34
69
70/*
71 * Known bits returned by \_SB.ATKD.HWRS
72 */
73#define WL_HWRS 0x80
74#define BT_HWRS 0x100
75
76/*
77 * Flags for hotk status
78 * WL_ON and BT_ON are also used for wireless_status()
79 */
80#define WL_ON 0x01 /* internal Wifi */
81#define BT_ON 0x02 /* internal Bluetooth */
82#define MLED_ON 0x04 /* mail LED */
83#define TLED_ON 0x08 /* touchpad LED */
84#define RLED_ON 0x10 /* Record LED */
85#define PLED_ON 0x20 /* Phone LED */
86#define GLED_ON 0x40 /* Gaming LED */
87#define LCD_ON 0x80 /* LCD backlight */
88#define GPS_ON 0x100 /* GPS */
89#define KEY_ON 0x200 /* Keyboard backlight */
90
91#define ASUS_LOG ASUS_HOTK_FILE ": "
92#define ASUS_ERR KERN_ERR ASUS_LOG
93#define ASUS_WARNING KERN_WARNING ASUS_LOG
94#define ASUS_NOTICE KERN_NOTICE ASUS_LOG
95#define ASUS_INFO KERN_INFO ASUS_LOG
96#define ASUS_DEBUG KERN_DEBUG ASUS_LOG
97 63
98MODULE_AUTHOR("Julien Lerouge, Karol Kozimor, Corentin Chary"); 64MODULE_AUTHOR("Julien Lerouge, Karol Kozimor, Corentin Chary");
99MODULE_DESCRIPTION(ASUS_HOTK_NAME); 65MODULE_DESCRIPTION(ASUS_LAPTOP_NAME);
100MODULE_LICENSE("GPL"); 66MODULE_LICENSE("GPL");
101 67
102/* 68/*
@@ -113,225 +79,209 @@ static uint wapf = 1;
113module_param(wapf, uint, 0644); 79module_param(wapf, uint, 0644);
114MODULE_PARM_DESC(wapf, "WAPF value"); 80MODULE_PARM_DESC(wapf, "WAPF value");
115 81
116#define ASUS_HANDLE(object, paths...) \ 82static uint wlan_status = 1;
117 static acpi_handle object##_handle = NULL; \ 83static uint bluetooth_status = 1;
118 static char *object##_paths[] = { paths } 84
85module_param(wlan_status, uint, 0644);
86MODULE_PARM_DESC(wlan_status, "Set the wireless status on boot "
87 "(0 = disabled, 1 = enabled, -1 = don't do anything). "
88 "default is 1");
89
90module_param(bluetooth_status, uint, 0644);
91MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot "
92 "(0 = disabled, 1 = enabled, -1 = don't do anything). "
93 "default is 1");
94
95/*
96 * Some events we use, same for all Asus
97 */
98#define ATKD_BR_UP 0x10 /* (event & ~ATKD_BR_UP) = brightness level */
99#define ATKD_BR_DOWN 0x20 /* (event & ~ATKD_BR_DOWN) = britghness level */
100#define ATKD_BR_MIN ATKD_BR_UP
101#define ATKD_BR_MAX (ATKD_BR_DOWN | 0xF) /* 0x2f */
102#define ATKD_LCD_ON 0x33
103#define ATKD_LCD_OFF 0x34
104
105/*
106 * Known bits returned by \_SB.ATKD.HWRS
107 */
108#define WL_HWRS 0x80
109#define BT_HWRS 0x100
110
111/*
112 * Flags for hotk status
113 * WL_ON and BT_ON are also used for wireless_status()
114 */
115#define WL_RSTS 0x01 /* internal Wifi */
116#define BT_RSTS 0x02 /* internal Bluetooth */
119 117
120/* LED */ 118/* LED */
121ASUS_HANDLE(mled_set, ASUS_HOTK_PREFIX "MLED"); 119#define METHOD_MLED "MLED"
122ASUS_HANDLE(tled_set, ASUS_HOTK_PREFIX "TLED"); 120#define METHOD_TLED "TLED"
123ASUS_HANDLE(rled_set, ASUS_HOTK_PREFIX "RLED"); /* W1JC */ 121#define METHOD_RLED "RLED" /* W1JC */
124ASUS_HANDLE(pled_set, ASUS_HOTK_PREFIX "PLED"); /* A7J */ 122#define METHOD_PLED "PLED" /* A7J */
125ASUS_HANDLE(gled_set, ASUS_HOTK_PREFIX "GLED"); /* G1, G2 (probably) */ 123#define METHOD_GLED "GLED" /* G1, G2 (probably) */
126 124
127/* LEDD */ 125/* LEDD */
128ASUS_HANDLE(ledd_set, ASUS_HOTK_PREFIX "SLCM"); 126#define METHOD_LEDD "SLCM"
129 127
130/* 128/*
131 * Bluetooth and WLAN 129 * Bluetooth and WLAN
132 * WLED and BLED are not handled like other XLED, because in some dsdt 130 * WLED and BLED are not handled like other XLED, because in some dsdt
133 * they also control the WLAN/Bluetooth device. 131 * they also control the WLAN/Bluetooth device.
134 */ 132 */
135ASUS_HANDLE(wl_switch, ASUS_HOTK_PREFIX "WLED"); 133#define METHOD_WLAN "WLED"
136ASUS_HANDLE(bt_switch, ASUS_HOTK_PREFIX "BLED"); 134#define METHOD_BLUETOOTH "BLED"
137ASUS_HANDLE(wireless_status, ASUS_HOTK_PREFIX "RSTS"); /* All new models */ 135#define METHOD_WL_STATUS "RSTS"
138 136
139/* Brightness */ 137/* Brightness */
140ASUS_HANDLE(brightness_set, ASUS_HOTK_PREFIX "SPLV"); 138#define METHOD_BRIGHTNESS_SET "SPLV"
141ASUS_HANDLE(brightness_get, ASUS_HOTK_PREFIX "GPLV"); 139#define METHOD_BRIGHTNESS_GET "GPLV"
142 140
143/* Backlight */ 141/* Backlight */
144ASUS_HANDLE(lcd_switch, "\\_SB.PCI0.SBRG.EC0._Q10", /* All new models */ 142static acpi_handle lcd_switch_handle;
145 "\\_SB.PCI0.ISA.EC0._Q10", /* A1x */ 143static char *lcd_switch_paths[] = {
146 "\\_SB.PCI0.PX40.ECD0._Q10", /* L3C */ 144 "\\_SB.PCI0.SBRG.EC0._Q10", /* All new models */
147 "\\_SB.PCI0.PX40.EC0.Q10", /* M1A */ 145 "\\_SB.PCI0.ISA.EC0._Q10", /* A1x */
148 "\\_SB.PCI0.LPCB.EC0._Q10", /* P30 */ 146 "\\_SB.PCI0.PX40.ECD0._Q10", /* L3C */
149 "\\_SB.PCI0.LPCB.EC0._Q0E", /* P30/P35 */ 147 "\\_SB.PCI0.PX40.EC0.Q10", /* M1A */
150 "\\_SB.PCI0.PX40.Q10", /* S1x */ 148 "\\_SB.PCI0.LPCB.EC0._Q10", /* P30 */
151 "\\Q10"); /* A2x, L2D, L3D, M2E */ 149 "\\_SB.PCI0.LPCB.EC0._Q0E", /* P30/P35 */
150 "\\_SB.PCI0.PX40.Q10", /* S1x */
151 "\\Q10"}; /* A2x, L2D, L3D, M2E */
152 152
153/* Display */ 153/* Display */
154ASUS_HANDLE(display_set, ASUS_HOTK_PREFIX "SDSP"); 154#define METHOD_SWITCH_DISPLAY "SDSP"
155ASUS_HANDLE(display_get, 155
156 /* A6B, A6K A6R A7D F3JM L4R M6R A3G M6A M6V VX-1 V6J V6V W3Z */ 156static acpi_handle display_get_handle;
157 "\\_SB.PCI0.P0P1.VGA.GETD", 157static char *display_get_paths[] = {
158 /* A3E A4K, A4D A4L A6J A7J A8J Z71V M9V S5A M5A z33A W1Jc W2V G1 */ 158 /* A6B, A6K A6R A7D F3JM L4R M6R A3G M6A M6V VX-1 V6J V6V W3Z */
159 "\\_SB.PCI0.P0P2.VGA.GETD", 159 "\\_SB.PCI0.P0P1.VGA.GETD",
160 /* A6V A6Q */ 160 /* A3E A4K, A4D A4L A6J A7J A8J Z71V M9V S5A M5A z33A W1Jc W2V G1 */
161 "\\_SB.PCI0.P0P3.VGA.GETD", 161 "\\_SB.PCI0.P0P2.VGA.GETD",
162 /* A6T, A6M */ 162 /* A6V A6Q */
163 "\\_SB.PCI0.P0PA.VGA.GETD", 163 "\\_SB.PCI0.P0P3.VGA.GETD",
164 /* L3C */ 164 /* A6T, A6M */
165 "\\_SB.PCI0.PCI1.VGAC.NMAP", 165 "\\_SB.PCI0.P0PA.VGA.GETD",
166 /* Z96F */ 166 /* L3C */
167 "\\_SB.PCI0.VGA.GETD", 167 "\\_SB.PCI0.PCI1.VGAC.NMAP",
168 /* A2D */ 168 /* Z96F */
169 "\\ACTD", 169 "\\_SB.PCI0.VGA.GETD",
170 /* A4G Z71A W1N W5A W5F M2N M3N M5N M6N S1N S5N */ 170 /* A2D */
171 "\\ADVG", 171 "\\ACTD",
172 /* P30 */ 172 /* A4G Z71A W1N W5A W5F M2N M3N M5N M6N S1N S5N */
173 "\\DNXT", 173 "\\ADVG",
174 /* A2H D1 L2D L3D L3H L2E L5D L5C M1A M2E L4L W3V */ 174 /* P30 */
175 "\\INFB", 175 "\\DNXT",
176 /* A3F A6F A3N A3L M6N W3N W6A */ 176 /* A2H D1 L2D L3D L3H L2E L5D L5C M1A M2E L4L W3V */
177 "\\SSTE"); 177 "\\INFB",
178 178 /* A3F A6F A3N A3L M6N W3N W6A */
179ASUS_HANDLE(ls_switch, ASUS_HOTK_PREFIX "ALSC"); /* Z71A Z71V */ 179 "\\SSTE"};
180ASUS_HANDLE(ls_level, ASUS_HOTK_PREFIX "ALSL"); /* Z71A Z71V */ 180
181#define METHOD_ALS_CONTROL "ALSC" /* Z71A Z71V */
182#define METHOD_ALS_LEVEL "ALSL" /* Z71A Z71V */
181 183
182/* GPS */ 184/* GPS */
183/* R2H use different handle for GPS on/off */ 185/* R2H use different handle for GPS on/off */
184ASUS_HANDLE(gps_on, ASUS_HOTK_PREFIX "SDON"); /* R2H */ 186#define METHOD_GPS_ON "SDON"
185ASUS_HANDLE(gps_off, ASUS_HOTK_PREFIX "SDOF"); /* R2H */ 187#define METHOD_GPS_OFF "SDOF"
186ASUS_HANDLE(gps_status, ASUS_HOTK_PREFIX "GPST"); 188#define METHOD_GPS_STATUS "GPST"
187 189
188/* Keyboard light */ 190/* Keyboard light */
189ASUS_HANDLE(kled_set, ASUS_HOTK_PREFIX "SLKB"); 191#define METHOD_KBD_LIGHT_SET "SLKB"
190ASUS_HANDLE(kled_get, ASUS_HOTK_PREFIX "GLKB"); 192#define METHOD_KBD_LIGHT_GET "GLKB"
191 193
192/* 194/*
193 * This is the main structure, we can use it to store anything interesting 195 * Define a specific led structure to keep the main structure clean
194 * about the hotk device
195 */ 196 */
196struct asus_hotk { 197struct asus_led {
197 char *name; /* laptop name */ 198 int wk;
198 struct acpi_device *device; /* the device we are in */ 199 struct work_struct work;
199 acpi_handle handle; /* the handle of the hotk device */ 200 struct led_classdev led;
200 char status; /* status of the hotk, for LEDs, ... */ 201 struct asus_laptop *asus;
201 u32 ledd_status; /* status of the LED display */ 202 const char *method;
202 u8 light_level; /* light sensor level */
203 u8 light_switch; /* light sensor switch value */
204 u16 event_count[128]; /* count for each event TODO make this better */
205 struct input_dev *inputdev;
206 u16 *keycode_map;
207}; 203};
208 204
209/* 205/*
210 * This header is made available to allow proper configuration given model, 206 * This is the main structure, we can use it to store anything interesting
211 * revision number , ... this info cannot go in struct asus_hotk because it is 207 * about the hotk device
212 * available before the hotk
213 */
214static struct acpi_table_header *asus_info;
215
216/* The actual device the driver binds to */
217static struct asus_hotk *hotk;
218
219/*
220 * The hotkey driver declaration
221 */ 208 */
222static const struct acpi_device_id asus_device_ids[] = { 209struct asus_laptop {
223 {"ATK0100", 0}, 210 char *name; /* laptop name */
224 {"ATK0101", 0},
225 {"", 0},
226};
227MODULE_DEVICE_TABLE(acpi, asus_device_ids);
228 211
229static int asus_hotk_add(struct acpi_device *device); 212 struct acpi_table_header *dsdt_info;
230static int asus_hotk_remove(struct acpi_device *device, int type); 213 struct platform_device *platform_device;
231static void asus_hotk_notify(struct acpi_device *device, u32 event); 214 struct acpi_device *device; /* the device we are in */
215 struct backlight_device *backlight_device;
232 216
233static struct acpi_driver asus_hotk_driver = { 217 struct input_dev *inputdev;
234 .name = ASUS_HOTK_NAME, 218 struct key_entry *keymap;
235 .class = ASUS_HOTK_CLASS,
236 .owner = THIS_MODULE,
237 .ids = asus_device_ids,
238 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
239 .ops = {
240 .add = asus_hotk_add,
241 .remove = asus_hotk_remove,
242 .notify = asus_hotk_notify,
243 },
244};
245 219
246/* The backlight device /sys/class/backlight */ 220 struct asus_led mled;
247static struct backlight_device *asus_backlight_device; 221 struct asus_led tled;
222 struct asus_led rled;
223 struct asus_led pled;
224 struct asus_led gled;
225 struct asus_led kled;
226 struct workqueue_struct *led_workqueue;
248 227
249/* 228 int wireless_status;
250 * The backlight class declaration 229 bool have_rsts;
251 */ 230 int lcd_state;
252static int read_brightness(struct backlight_device *bd);
253static int update_bl_status(struct backlight_device *bd);
254static struct backlight_ops asusbl_ops = {
255 .get_brightness = read_brightness,
256 .update_status = update_bl_status,
257};
258 231
259/* 232 struct rfkill *gps_rfkill;
260 * These functions actually update the LED's, and are called from a
261 * workqueue. By doing this as separate work rather than when the LED
262 * subsystem asks, we avoid messing with the Asus ACPI stuff during a
263 * potentially bad time, such as a timer interrupt.
264 */
265static struct workqueue_struct *led_workqueue;
266
267#define ASUS_LED(object, ledname, max) \
268 static void object##_led_set(struct led_classdev *led_cdev, \
269 enum led_brightness value); \
270 static enum led_brightness object##_led_get( \
271 struct led_classdev *led_cdev); \
272 static void object##_led_update(struct work_struct *ignored); \
273 static int object##_led_wk; \
274 static DECLARE_WORK(object##_led_work, object##_led_update); \
275 static struct led_classdev object##_led = { \
276 .name = "asus::" ledname, \
277 .brightness_set = object##_led_set, \
278 .brightness_get = object##_led_get, \
279 .max_brightness = max \
280 }
281 233
282ASUS_LED(mled, "mail", 1); 234 acpi_handle handle; /* the handle of the hotk device */
283ASUS_LED(tled, "touchpad", 1); 235 u32 ledd_status; /* status of the LED display */
284ASUS_LED(rled, "record", 1); 236 u8 light_level; /* light sensor level */
285ASUS_LED(pled, "phone", 1); 237 u8 light_switch; /* light sensor switch value */
286ASUS_LED(gled, "gaming", 1); 238 u16 event_count[128]; /* count for each event TODO make this better */
287ASUS_LED(kled, "kbd_backlight", 3); 239 u16 *keycode_map;
288
289struct key_entry {
290 char type;
291 u8 code;
292 u16 keycode;
293}; 240};
294 241
295enum { KE_KEY, KE_END }; 242static const struct key_entry asus_keymap[] = {
296 243 /* Lenovo SL Specific keycodes */
297static struct key_entry asus_keymap[] = { 244 {KE_KEY, 0x02, { KEY_SCREENLOCK } },
298 {KE_KEY, 0x02, KEY_SCREENLOCK}, 245 {KE_KEY, 0x05, { KEY_WLAN } },
299 {KE_KEY, 0x05, KEY_WLAN}, 246 {KE_KEY, 0x08, { KEY_F13 } },
300 {KE_KEY, 0x08, KEY_F13}, 247 {KE_KEY, 0x17, { KEY_ZOOM } },
301 {KE_KEY, 0x17, KEY_ZOOM}, 248 {KE_KEY, 0x1f, { KEY_BATTERY } },
302 {KE_KEY, 0x1f, KEY_BATTERY}, 249 /* End of Lenovo SL Specific keycodes */
303 {KE_KEY, 0x30, KEY_VOLUMEUP}, 250 {KE_KEY, 0x30, { KEY_VOLUMEUP } },
304 {KE_KEY, 0x31, KEY_VOLUMEDOWN}, 251 {KE_KEY, 0x31, { KEY_VOLUMEDOWN } },
305 {KE_KEY, 0x32, KEY_MUTE}, 252 {KE_KEY, 0x32, { KEY_MUTE } },
306 {KE_KEY, 0x33, KEY_SWITCHVIDEOMODE}, 253 {KE_KEY, 0x33, { KEY_SWITCHVIDEOMODE } },
307 {KE_KEY, 0x34, KEY_SWITCHVIDEOMODE}, 254 {KE_KEY, 0x34, { KEY_SWITCHVIDEOMODE } },
308 {KE_KEY, 0x40, KEY_PREVIOUSSONG}, 255 {KE_KEY, 0x40, { KEY_PREVIOUSSONG } },
309 {KE_KEY, 0x41, KEY_NEXTSONG}, 256 {KE_KEY, 0x41, { KEY_NEXTSONG } },
310 {KE_KEY, 0x43, KEY_STOPCD}, 257 {KE_KEY, 0x43, { KEY_STOPCD } },
311 {KE_KEY, 0x45, KEY_PLAYPAUSE}, 258 {KE_KEY, 0x45, { KEY_PLAYPAUSE } },
312 {KE_KEY, 0x4c, KEY_MEDIA}, 259 {KE_KEY, 0x4c, { KEY_MEDIA } },
313 {KE_KEY, 0x50, KEY_EMAIL}, 260 {KE_KEY, 0x50, { KEY_EMAIL } },
314 {KE_KEY, 0x51, KEY_WWW}, 261 {KE_KEY, 0x51, { KEY_WWW } },
315 {KE_KEY, 0x55, KEY_CALC}, 262 {KE_KEY, 0x55, { KEY_CALC } },
316 {KE_KEY, 0x5C, KEY_SCREENLOCK}, /* Screenlock */ 263 {KE_KEY, 0x5C, { KEY_SCREENLOCK } }, /* Screenlock */
317 {KE_KEY, 0x5D, KEY_WLAN}, 264 {KE_KEY, 0x5D, { KEY_WLAN } },
318 {KE_KEY, 0x5E, KEY_WLAN}, 265 {KE_KEY, 0x5E, { KEY_WLAN } },
319 {KE_KEY, 0x5F, KEY_WLAN}, 266 {KE_KEY, 0x5F, { KEY_WLAN } },
320 {KE_KEY, 0x60, KEY_SWITCHVIDEOMODE}, 267 {KE_KEY, 0x60, { KEY_SWITCHVIDEOMODE } },
321 {KE_KEY, 0x61, KEY_SWITCHVIDEOMODE}, 268 {KE_KEY, 0x61, { KEY_SWITCHVIDEOMODE } },
322 {KE_KEY, 0x62, KEY_SWITCHVIDEOMODE}, 269 {KE_KEY, 0x62, { KEY_SWITCHVIDEOMODE } },
323 {KE_KEY, 0x63, KEY_SWITCHVIDEOMODE}, 270 {KE_KEY, 0x63, { KEY_SWITCHVIDEOMODE } },
324 {KE_KEY, 0x6B, KEY_F13}, /* Lock Touchpad */ 271 {KE_KEY, 0x6B, { KEY_F13 } }, /* Lock Touchpad */
325 {KE_KEY, 0x82, KEY_CAMERA}, 272 {KE_KEY, 0x7E, { KEY_BLUETOOTH } },
326 {KE_KEY, 0x88, KEY_WLAN }, 273 {KE_KEY, 0x7D, { KEY_BLUETOOTH } },
327 {KE_KEY, 0x8A, KEY_PROG1}, 274 {KE_KEY, 0x82, { KEY_CAMERA } },
328 {KE_KEY, 0x95, KEY_MEDIA}, 275 {KE_KEY, 0x88, { KEY_WLAN } },
329 {KE_KEY, 0x99, KEY_PHONE}, 276 {KE_KEY, 0x8A, { KEY_PROG1 } },
330 {KE_KEY, 0xc4, KEY_KBDILLUMUP}, 277 {KE_KEY, 0x95, { KEY_MEDIA } },
331 {KE_KEY, 0xc5, KEY_KBDILLUMDOWN}, 278 {KE_KEY, 0x99, { KEY_PHONE } },
279 {KE_KEY, 0xc4, { KEY_KBDILLUMUP } },
280 {KE_KEY, 0xc5, { KEY_KBDILLUMDOWN } },
332 {KE_END, 0}, 281 {KE_END, 0},
333}; 282};
334 283
284
335/* 285/*
336 * This function evaluates an ACPI method, given an int as parameter, the 286 * This function evaluates an ACPI method, given an int as parameter, the
337 * method is searched within the scope of the handle, can be NULL. The output 287 * method is searched within the scope of the handle, can be NULL. The output
@@ -339,8 +289,8 @@ static struct key_entry asus_keymap[] = {
339 * 289 *
340 * returns 0 if write is successful, -1 else. 290 * returns 0 if write is successful, -1 else.
341 */ 291 */
342static int write_acpi_int(acpi_handle handle, const char *method, int val, 292static int write_acpi_int_ret(acpi_handle handle, const char *method, int val,
343 struct acpi_buffer *output) 293 struct acpi_buffer *output)
344{ 294{
345 struct acpi_object_list params; /* list of input parameters (an int) */ 295 struct acpi_object_list params; /* list of input parameters (an int) */
346 union acpi_object in_obj; /* the only param we use */ 296 union acpi_object in_obj; /* the only param we use */
@@ -361,102 +311,82 @@ static int write_acpi_int(acpi_handle handle, const char *method, int val,
361 return -1; 311 return -1;
362} 312}
363 313
364static int read_wireless_status(int mask) 314static int write_acpi_int(acpi_handle handle, const char *method, int val)
365{ 315{
366 unsigned long long status; 316 return write_acpi_int_ret(handle, method, val, NULL);
367 acpi_status rv = AE_OK; 317}
368 318
369 if (!wireless_status_handle) 319static int acpi_check_handle(acpi_handle handle, const char *method,
370 return (hotk->status & mask) ? 1 : 0; 320 acpi_handle *ret)
321{
322 acpi_status status;
371 323
372 rv = acpi_evaluate_integer(wireless_status_handle, NULL, NULL, &status); 324 if (method == NULL)
373 if (ACPI_FAILURE(rv)) 325 return -ENODEV;
374 pr_warning("Error reading Wireless status\n"); 326
375 else 327 if (ret)
376 return (status & mask) ? 1 : 0; 328 status = acpi_get_handle(handle, (char *)method,
329 ret);
330 else {
331 acpi_handle dummy;
377 332
378 return (hotk->status & mask) ? 1 : 0; 333 status = acpi_get_handle(handle, (char *)method,
334 &dummy);
335 }
336
337 if (status != AE_OK) {
338 if (ret)
339 pr_warning("Error finding %s\n", method);
340 return -ENODEV;
341 }
342 return 0;
379} 343}
380 344
381static int read_gps_status(void) 345/* Generic LED function */
346static int asus_led_set(struct asus_laptop *asus, const char *method,
347 int value)
382{ 348{
383 unsigned long long status; 349 if (!strcmp(method, METHOD_MLED))
384 acpi_status rv = AE_OK; 350 value = !value;
385 351 else if (!strcmp(method, METHOD_GLED))
386 rv = acpi_evaluate_integer(gps_status_handle, NULL, NULL, &status); 352 value = !value + 1;
387 if (ACPI_FAILURE(rv))
388 pr_warning("Error reading GPS status\n");
389 else 353 else
390 return status ? 1 : 0; 354 value = !!value;
391 355
392 return (hotk->status & GPS_ON) ? 1 : 0; 356 return write_acpi_int(asus->handle, method, value);
393} 357}
394 358
395/* Generic LED functions */ 359/*
396static int read_status(int mask) 360 * LEDs
361 */
362/* /sys/class/led handlers */
363static void asus_led_cdev_set(struct led_classdev *led_cdev,
364 enum led_brightness value)
397{ 365{
398 /* There is a special method for both wireless devices */ 366 struct asus_led *led = container_of(led_cdev, struct asus_led, led);
399 if (mask == BT_ON || mask == WL_ON) 367 struct asus_laptop *asus = led->asus;
400 return read_wireless_status(mask);
401 else if (mask == GPS_ON)
402 return read_gps_status();
403 368
404 return (hotk->status & mask) ? 1 : 0; 369 led->wk = !!value;
370 queue_work(asus->led_workqueue, &led->work);
405} 371}
406 372
407static void write_status(acpi_handle handle, int out, int mask) 373static void asus_led_cdev_update(struct work_struct *work)
408{ 374{
409 hotk->status = (out) ? (hotk->status | mask) : (hotk->status & ~mask); 375 struct asus_led *led = container_of(work, struct asus_led, work);
376 struct asus_laptop *asus = led->asus;
410 377
411 switch (mask) { 378 asus_led_set(asus, led->method, led->wk);
412 case MLED_ON:
413 out = !(out & 0x1);
414 break;
415 case GLED_ON:
416 out = (out & 0x1) + 1;
417 break;
418 case GPS_ON:
419 handle = (out) ? gps_on_handle : gps_off_handle;
420 out = 0x02;
421 break;
422 default:
423 out &= 0x1;
424 break;
425 }
426
427 if (write_acpi_int(handle, NULL, out, NULL))
428 pr_warning(" write failed %x\n", mask);
429} 379}
430 380
431/* /sys/class/led handlers */ 381static enum led_brightness asus_led_cdev_get(struct led_classdev *led_cdev)
432#define ASUS_LED_HANDLER(object, mask) \ 382{
433 static void object##_led_set(struct led_classdev *led_cdev, \ 383 return led_cdev->brightness;
434 enum led_brightness value) \ 384}
435 { \
436 object##_led_wk = (value > 0) ? 1 : 0; \
437 queue_work(led_workqueue, &object##_led_work); \
438 } \
439 static void object##_led_update(struct work_struct *ignored) \
440 { \
441 int value = object##_led_wk; \
442 write_status(object##_set_handle, value, (mask)); \
443 } \
444 static enum led_brightness object##_led_get( \
445 struct led_classdev *led_cdev) \
446 { \
447 return led_cdev->brightness; \
448 }
449
450ASUS_LED_HANDLER(mled, MLED_ON);
451ASUS_LED_HANDLER(pled, PLED_ON);
452ASUS_LED_HANDLER(rled, RLED_ON);
453ASUS_LED_HANDLER(tled, TLED_ON);
454ASUS_LED_HANDLER(gled, GLED_ON);
455 385
456/* 386/*
457 * Keyboard backlight 387 * Keyboard backlight (also a LED)
458 */ 388 */
459static int get_kled_lvl(void) 389static int asus_kled_lvl(struct asus_laptop *asus)
460{ 390{
461 unsigned long long kblv; 391 unsigned long long kblv;
462 struct acpi_object_list params; 392 struct acpi_object_list params;
@@ -468,75 +398,183 @@ static int get_kled_lvl(void)
468 in_obj.type = ACPI_TYPE_INTEGER; 398 in_obj.type = ACPI_TYPE_INTEGER;
469 in_obj.integer.value = 2; 399 in_obj.integer.value = 2;
470 400
471 rv = acpi_evaluate_integer(kled_get_handle, NULL, &params, &kblv); 401 rv = acpi_evaluate_integer(asus->handle, METHOD_KBD_LIGHT_GET,
402 &params, &kblv);
472 if (ACPI_FAILURE(rv)) { 403 if (ACPI_FAILURE(rv)) {
473 pr_warning("Error reading kled level\n"); 404 pr_warning("Error reading kled level\n");
474 return 0; 405 return -ENODEV;
475 } 406 }
476 return kblv; 407 return kblv;
477} 408}
478 409
479static int set_kled_lvl(int kblv) 410static int asus_kled_set(struct asus_laptop *asus, int kblv)
480{ 411{
481 if (kblv > 0) 412 if (kblv > 0)
482 kblv = (1 << 7) | (kblv & 0x7F); 413 kblv = (1 << 7) | (kblv & 0x7F);
483 else 414 else
484 kblv = 0; 415 kblv = 0;
485 416
486 if (write_acpi_int(kled_set_handle, NULL, kblv, NULL)) { 417 if (write_acpi_int(asus->handle, METHOD_KBD_LIGHT_SET, kblv)) {
487 pr_warning("Keyboard LED display write failed\n"); 418 pr_warning("Keyboard LED display write failed\n");
488 return -EINVAL; 419 return -EINVAL;
489 } 420 }
490 return 0; 421 return 0;
491} 422}
492 423
493static void kled_led_set(struct led_classdev *led_cdev, 424static void asus_kled_cdev_set(struct led_classdev *led_cdev,
494 enum led_brightness value) 425 enum led_brightness value)
426{
427 struct asus_led *led = container_of(led_cdev, struct asus_led, led);
428 struct asus_laptop *asus = led->asus;
429
430 led->wk = value;
431 queue_work(asus->led_workqueue, &led->work);
432}
433
434static void asus_kled_cdev_update(struct work_struct *work)
495{ 435{
496 kled_led_wk = value; 436 struct asus_led *led = container_of(work, struct asus_led, work);
497 queue_work(led_workqueue, &kled_led_work); 437 struct asus_laptop *asus = led->asus;
438
439 asus_kled_set(asus, led->wk);
498} 440}
499 441
500static void kled_led_update(struct work_struct *ignored) 442static enum led_brightness asus_kled_cdev_get(struct led_classdev *led_cdev)
501{ 443{
502 set_kled_lvl(kled_led_wk); 444 struct asus_led *led = container_of(led_cdev, struct asus_led, led);
445 struct asus_laptop *asus = led->asus;
446
447 return asus_kled_lvl(asus);
503} 448}
504 449
505static enum led_brightness kled_led_get(struct led_classdev *led_cdev) 450static void asus_led_exit(struct asus_laptop *asus)
506{ 451{
507 return get_kled_lvl(); 452 if (asus->mled.led.dev)
453 led_classdev_unregister(&asus->mled.led);
454 if (asus->tled.led.dev)
455 led_classdev_unregister(&asus->tled.led);
456 if (asus->pled.led.dev)
457 led_classdev_unregister(&asus->pled.led);
458 if (asus->rled.led.dev)
459 led_classdev_unregister(&asus->rled.led);
460 if (asus->gled.led.dev)
461 led_classdev_unregister(&asus->gled.led);
462 if (asus->kled.led.dev)
463 led_classdev_unregister(&asus->kled.led);
464 if (asus->led_workqueue) {
465 destroy_workqueue(asus->led_workqueue);
466 asus->led_workqueue = NULL;
467 }
508} 468}
509 469
510static int get_lcd_state(void) 470/* Ugly macro, need to fix that later */
471static int asus_led_register(struct asus_laptop *asus,
472 struct asus_led *led,
473 const char *name, const char *method)
511{ 474{
512 return read_status(LCD_ON); 475 struct led_classdev *led_cdev = &led->led;
476
477 if (!method || acpi_check_handle(asus->handle, method, NULL))
478 return 0; /* Led not present */
479
480 led->asus = asus;
481 led->method = method;
482
483 INIT_WORK(&led->work, asus_led_cdev_update);
484 led_cdev->name = name;
485 led_cdev->brightness_set = asus_led_cdev_set;
486 led_cdev->brightness_get = asus_led_cdev_get;
487 led_cdev->max_brightness = 1;
488 return led_classdev_register(&asus->platform_device->dev, led_cdev);
513} 489}
514 490
515static int set_lcd_state(int value) 491static int asus_led_init(struct asus_laptop *asus)
492{
493 int r;
494
495 /*
496 * Functions that actually update the LED's are called from a
497 * workqueue. By doing this as separate work rather than when the LED
498 * subsystem asks, we avoid messing with the Asus ACPI stuff during a
499 * potentially bad time, such as a timer interrupt.
500 */
501 asus->led_workqueue = create_singlethread_workqueue("led_workqueue");
502 if (!asus->led_workqueue)
503 return -ENOMEM;
504
505 r = asus_led_register(asus, &asus->mled, "asus::mail", METHOD_MLED);
506 if (r)
507 goto error;
508 r = asus_led_register(asus, &asus->tled, "asus::touchpad", METHOD_TLED);
509 if (r)
510 goto error;
511 r = asus_led_register(asus, &asus->rled, "asus::record", METHOD_RLED);
512 if (r)
513 goto error;
514 r = asus_led_register(asus, &asus->pled, "asus::phone", METHOD_PLED);
515 if (r)
516 goto error;
517 r = asus_led_register(asus, &asus->gled, "asus::gaming", METHOD_GLED);
518 if (r)
519 goto error;
520 if (!acpi_check_handle(asus->handle, METHOD_KBD_LIGHT_SET, NULL) &&
521 !acpi_check_handle(asus->handle, METHOD_KBD_LIGHT_GET, NULL)) {
522 struct asus_led *led = &asus->kled;
523 struct led_classdev *cdev = &led->led;
524
525 led->asus = asus;
526
527 INIT_WORK(&led->work, asus_kled_cdev_update);
528 cdev->name = "asus::kbd_backlight";
529 cdev->brightness_set = asus_kled_cdev_set;
530 cdev->brightness_get = asus_kled_cdev_get;
531 cdev->max_brightness = 3;
532 r = led_classdev_register(&asus->platform_device->dev, cdev);
533 }
534error:
535 if (r)
536 asus_led_exit(asus);
537 return r;
538}
539
540/*
541 * Backlight device
542 */
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)
516{ 549{
517 int lcd = 0; 550 int lcd = 0;
518 acpi_status status = 0; 551 acpi_status status = 0;
519 552
520 lcd = value ? 1 : 0; 553 lcd = !!value;
521 554
522 if (lcd == get_lcd_state()) 555 if (lcd == asus_lcd_status(asus))
523 return 0; 556 return 0;
524 557
525 if (lcd_switch_handle) { 558 if (!lcd_switch_handle)
526 status = acpi_evaluate_object(lcd_switch_handle, 559 return -ENODEV;
527 NULL, NULL, NULL); 560
561 status = acpi_evaluate_object(lcd_switch_handle,
562 NULL, NULL, NULL);
528 563
529 if (ACPI_FAILURE(status)) 564 if (ACPI_FAILURE(status)) {
530 pr_warning("Error switching LCD\n"); 565 pr_warning("Error switching LCD\n");
566 return -ENODEV;
531 } 567 }
532 568
533 write_status(NULL, lcd, LCD_ON); 569 asus->lcd_state = lcd;
534 return 0; 570 return 0;
535} 571}
536 572
537static void lcd_blank(int blank) 573static void lcd_blank(struct asus_laptop *asus, int blank)
538{ 574{
539 struct backlight_device *bd = asus_backlight_device; 575 struct backlight_device *bd = asus->backlight_device;
576
577 asus->lcd_state = (blank == FB_BLANK_UNBLANK);
540 578
541 if (bd) { 579 if (bd) {
542 bd->props.power = blank; 580 bd->props.power = blank;
@@ -544,44 +582,94 @@ static void lcd_blank(int blank)
544 } 582 }
545} 583}
546 584
547static int read_brightness(struct backlight_device *bd) 585static int asus_read_brightness(struct backlight_device *bd)
548{ 586{
587 struct asus_laptop *asus = bl_get_data(bd);
549 unsigned long long value; 588 unsigned long long value;
550 acpi_status rv = AE_OK; 589 acpi_status rv = AE_OK;
551 590
552 rv = acpi_evaluate_integer(brightness_get_handle, NULL, NULL, &value); 591 rv = acpi_evaluate_integer(asus->handle, METHOD_BRIGHTNESS_GET,
592 NULL, &value);
553 if (ACPI_FAILURE(rv)) 593 if (ACPI_FAILURE(rv))
554 pr_warning("Error reading brightness\n"); 594 pr_warning("Error reading brightness\n");
555 595
556 return value; 596 return value;
557} 597}
558 598
559static int set_brightness(struct backlight_device *bd, int value) 599static int asus_set_brightness(struct backlight_device *bd, int value)
560{ 600{
561 int ret = 0; 601 struct asus_laptop *asus = bl_get_data(bd);
562 602
563 value = (0 < value) ? ((15 < value) ? 15 : value) : 0; 603 if (write_acpi_int(asus->handle, METHOD_BRIGHTNESS_SET, value)) {
564 /* 0 <= value <= 15 */
565
566 if (write_acpi_int(brightness_set_handle, NULL, value, NULL)) {
567 pr_warning("Error changing brightness\n"); 604 pr_warning("Error changing brightness\n");
568 ret = -EIO; 605 return -EIO;
569 } 606 }
570 607 return 0;
571 return ret;
572} 608}
573 609
574static int update_bl_status(struct backlight_device *bd) 610static int update_bl_status(struct backlight_device *bd)
575{ 611{
612 struct asus_laptop *asus = bl_get_data(bd);
576 int rv; 613 int rv;
577 int value = bd->props.brightness; 614 int value = bd->props.brightness;
578 615
579 rv = set_brightness(bd, value); 616 rv = asus_set_brightness(bd, value);
580 if (rv) 617 if (rv)
581 return rv; 618 return rv;
582 619
583 value = (bd->props.power == FB_BLANK_UNBLANK) ? 1 : 0; 620 value = (bd->props.power == FB_BLANK_UNBLANK) ? 1 : 0;
584 return set_lcd_state(value); 621 return asus_lcd_set(asus, value);
622}
623
624static struct backlight_ops asusbl_ops = {
625 .get_brightness = asus_read_brightness,
626 .update_status = update_bl_status,
627};
628
629static int asus_backlight_notify(struct asus_laptop *asus)
630{
631 struct backlight_device *bd = asus->backlight_device;
632 int old = bd->props.brightness;
633
634 backlight_force_update(bd, BACKLIGHT_UPDATE_HOTKEY);
635
636 return old;
637}
638
639static int asus_backlight_init(struct asus_laptop *asus)
640{
641 struct backlight_device *bd;
642 struct device *dev = &asus->platform_device->dev;
643 struct backlight_properties props;
644
645 if (!acpi_check_handle(asus->handle, METHOD_BRIGHTNESS_GET, NULL) &&
646 !acpi_check_handle(asus->handle, METHOD_BRIGHTNESS_SET, NULL) &&
647 lcd_switch_handle) {
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
661 bd->props.power = FB_BLANK_UNBLANK;
662 bd->props.brightness = asus_read_brightness(bd);
663 backlight_update_status(bd);
664 }
665 return 0;
666}
667
668static void asus_backlight_exit(struct asus_laptop *asus)
669{
670 if (asus->backlight_device)
671 backlight_device_unregister(asus->backlight_device);
672 asus->backlight_device = NULL;
585} 673}
586 674
587/* 675/*
@@ -596,25 +684,26 @@ static int update_bl_status(struct backlight_device *bd)
596static ssize_t show_infos(struct device *dev, 684static ssize_t show_infos(struct device *dev,
597 struct device_attribute *attr, char *page) 685 struct device_attribute *attr, char *page)
598{ 686{
687 struct asus_laptop *asus = dev_get_drvdata(dev);
599 int len = 0; 688 int len = 0;
600 unsigned long long temp; 689 unsigned long long temp;
601 char buf[16]; /* enough for all info */ 690 char buf[16]; /* enough for all info */
602 acpi_status rv = AE_OK; 691 acpi_status rv = AE_OK;
603 692
604 /* 693 /*
605 * We use the easy way, we don't care of off and count, so we don't set eof 694 * We use the easy way, we don't care of off and count,
606 * to 1 695 * so we don't set eof to 1
607 */ 696 */
608 697
609 len += sprintf(page, ASUS_HOTK_NAME " " ASUS_LAPTOP_VERSION "\n"); 698 len += sprintf(page, ASUS_LAPTOP_NAME " " ASUS_LAPTOP_VERSION "\n");
610 len += sprintf(page + len, "Model reference : %s\n", hotk->name); 699 len += sprintf(page + len, "Model reference : %s\n", asus->name);
611 /* 700 /*
612 * The SFUN method probably allows the original driver to get the list 701 * The SFUN method probably allows the original driver to get the list
613 * of features supported by a given model. For now, 0x0100 or 0x0800 702 * of features supported by a given model. For now, 0x0100 or 0x0800
614 * bit signifies that the laptop is equipped with a Wi-Fi MiniPCI card. 703 * bit signifies that the laptop is equipped with a Wi-Fi MiniPCI card.
615 * The significance of others is yet to be found. 704 * The significance of others is yet to be found.
616 */ 705 */
617 rv = acpi_evaluate_integer(hotk->handle, "SFUN", NULL, &temp); 706 rv = acpi_evaluate_integer(asus->handle, "SFUN", NULL, &temp);
618 if (!ACPI_FAILURE(rv)) 707 if (!ACPI_FAILURE(rv))
619 len += sprintf(page + len, "SFUN value : %#x\n", 708 len += sprintf(page + len, "SFUN value : %#x\n",
620 (uint) temp); 709 (uint) temp);
@@ -624,7 +713,7 @@ static ssize_t show_infos(struct device *dev,
624 * The significance of others is yet to be found. 713 * The significance of others is yet to be found.
625 * If we don't find the method, we assume the device are present. 714 * If we don't find the method, we assume the device are present.
626 */ 715 */
627 rv = acpi_evaluate_integer(hotk->handle, "HRWS", NULL, &temp); 716 rv = acpi_evaluate_integer(asus->handle, "HRWS", NULL, &temp);
628 if (!ACPI_FAILURE(rv)) 717 if (!ACPI_FAILURE(rv))
629 len += sprintf(page + len, "HRWS value : %#x\n", 718 len += sprintf(page + len, "HRWS value : %#x\n",
630 (uint) temp); 719 (uint) temp);
@@ -635,26 +724,26 @@ static ssize_t show_infos(struct device *dev,
635 * Note: since not all the laptops provide this method, errors are 724 * Note: since not all the laptops provide this method, errors are
636 * silently ignored. 725 * silently ignored.
637 */ 726 */
638 rv = acpi_evaluate_integer(hotk->handle, "ASYM", NULL, &temp); 727 rv = acpi_evaluate_integer(asus->handle, "ASYM", NULL, &temp);
639 if (!ACPI_FAILURE(rv)) 728 if (!ACPI_FAILURE(rv))
640 len += sprintf(page + len, "ASYM value : %#x\n", 729 len += sprintf(page + len, "ASYM value : %#x\n",
641 (uint) temp); 730 (uint) temp);
642 if (asus_info) { 731 if (asus->dsdt_info) {
643 snprintf(buf, 16, "%d", asus_info->length); 732 snprintf(buf, 16, "%d", asus->dsdt_info->length);
644 len += sprintf(page + len, "DSDT length : %s\n", buf); 733 len += sprintf(page + len, "DSDT length : %s\n", buf);
645 snprintf(buf, 16, "%d", asus_info->checksum); 734 snprintf(buf, 16, "%d", asus->dsdt_info->checksum);
646 len += sprintf(page + len, "DSDT checksum : %s\n", buf); 735 len += sprintf(page + len, "DSDT checksum : %s\n", buf);
647 snprintf(buf, 16, "%d", asus_info->revision); 736 snprintf(buf, 16, "%d", asus->dsdt_info->revision);
648 len += sprintf(page + len, "DSDT revision : %s\n", buf); 737 len += sprintf(page + len, "DSDT revision : %s\n", buf);
649 snprintf(buf, 7, "%s", asus_info->oem_id); 738 snprintf(buf, 7, "%s", asus->dsdt_info->oem_id);
650 len += sprintf(page + len, "OEM id : %s\n", buf); 739 len += sprintf(page + len, "OEM id : %s\n", buf);
651 snprintf(buf, 9, "%s", asus_info->oem_table_id); 740 snprintf(buf, 9, "%s", asus->dsdt_info->oem_table_id);
652 len += sprintf(page + len, "OEM table id : %s\n", buf); 741 len += sprintf(page + len, "OEM table id : %s\n", buf);
653 snprintf(buf, 16, "%x", asus_info->oem_revision); 742 snprintf(buf, 16, "%x", asus->dsdt_info->oem_revision);
654 len += sprintf(page + len, "OEM revision : 0x%s\n", buf); 743 len += sprintf(page + len, "OEM revision : 0x%s\n", buf);
655 snprintf(buf, 5, "%s", asus_info->asl_compiler_id); 744 snprintf(buf, 5, "%s", asus->dsdt_info->asl_compiler_id);
656 len += sprintf(page + len, "ASL comp vendor id : %s\n", buf); 745 len += sprintf(page + len, "ASL comp vendor id : %s\n", buf);
657 snprintf(buf, 16, "%x", asus_info->asl_compiler_revision); 746 snprintf(buf, 16, "%x", asus->dsdt_info->asl_compiler_revision);
658 len += sprintf(page + len, "ASL comp revision : 0x%s\n", buf); 747 len += sprintf(page + len, "ASL comp revision : 0x%s\n", buf);
659 } 748 }
660 749
@@ -672,8 +761,9 @@ static int parse_arg(const char *buf, unsigned long count, int *val)
672 return count; 761 return count;
673} 762}
674 763
675static ssize_t store_status(const char *buf, size_t count, 764static ssize_t sysfs_acpi_set(struct asus_laptop *asus,
676 acpi_handle handle, int mask) 765 const char *buf, size_t count,
766 const char *method)
677{ 767{
678 int rv, value; 768 int rv, value;
679 int out = 0; 769 int out = 0;
@@ -682,8 +772,8 @@ static ssize_t store_status(const char *buf, size_t count,
682 if (rv > 0) 772 if (rv > 0)
683 out = value ? 1 : 0; 773 out = value ? 1 : 0;
684 774
685 write_status(handle, out, mask); 775 if (write_acpi_int(asus->handle, method, value))
686 776 return -ENODEV;
687 return rv; 777 return rv;
688} 778}
689 779
@@ -693,67 +783,116 @@ static ssize_t store_status(const char *buf, size_t count,
693static ssize_t show_ledd(struct device *dev, 783static ssize_t show_ledd(struct device *dev,
694 struct device_attribute *attr, char *buf) 784 struct device_attribute *attr, char *buf)
695{ 785{
696 return sprintf(buf, "0x%08x\n", hotk->ledd_status); 786 struct asus_laptop *asus = dev_get_drvdata(dev);
787
788 return sprintf(buf, "0x%08x\n", asus->ledd_status);
697} 789}
698 790
699static ssize_t store_ledd(struct device *dev, struct device_attribute *attr, 791static ssize_t store_ledd(struct device *dev, struct device_attribute *attr,
700 const char *buf, size_t count) 792 const char *buf, size_t count)
701{ 793{
794 struct asus_laptop *asus = dev_get_drvdata(dev);
702 int rv, value; 795 int rv, value;
703 796
704 rv = parse_arg(buf, count, &value); 797 rv = parse_arg(buf, count, &value);
705 if (rv > 0) { 798 if (rv > 0) {
706 if (write_acpi_int(ledd_set_handle, NULL, value, NULL)) 799 if (write_acpi_int(asus->handle, METHOD_LEDD, value))
707 pr_warning("LED display write failed\n"); 800 pr_warning("LED display write failed\n");
708 else 801 else
709 hotk->ledd_status = (u32) value; 802 asus->ledd_status = (u32) value;
710 } 803 }
711 return rv; 804 return rv;
712} 805}
713 806
714/* 807/*
808 * Wireless
809 */
810static int asus_wireless_status(struct asus_laptop *asus, int mask)
811{
812 unsigned long long status;
813 acpi_status rv = AE_OK;
814
815 if (!asus->have_rsts)
816 return (asus->wireless_status & mask) ? 1 : 0;
817
818 rv = acpi_evaluate_integer(asus->handle, METHOD_WL_STATUS,
819 NULL, &status);
820 if (ACPI_FAILURE(rv)) {
821 pr_warning("Error reading Wireless status\n");
822 return -EINVAL;
823 }
824 return !!(status & mask);
825}
826
827/*
715 * WLAN 828 * WLAN
716 */ 829 */
830static int asus_wlan_set(struct asus_laptop *asus, int status)
831{
832 if (write_acpi_int(asus->handle, METHOD_WLAN, !!status)) {
833 pr_warning("Error setting wlan status to %d", status);
834 return -EIO;
835 }
836 return 0;
837}
838
717static ssize_t show_wlan(struct device *dev, 839static ssize_t show_wlan(struct device *dev,
718 struct device_attribute *attr, char *buf) 840 struct device_attribute *attr, char *buf)
719{ 841{
720 return sprintf(buf, "%d\n", read_status(WL_ON)); 842 struct asus_laptop *asus = dev_get_drvdata(dev);
843
844 return sprintf(buf, "%d\n", asus_wireless_status(asus, WL_RSTS));
721} 845}
722 846
723static ssize_t store_wlan(struct device *dev, struct device_attribute *attr, 847static ssize_t store_wlan(struct device *dev, struct device_attribute *attr,
724 const char *buf, size_t count) 848 const char *buf, size_t count)
725{ 849{
726 return store_status(buf, count, wl_switch_handle, WL_ON); 850 struct asus_laptop *asus = dev_get_drvdata(dev);
851
852 return sysfs_acpi_set(asus, buf, count, METHOD_WLAN);
727} 853}
728 854
729/* 855/*
730 * Bluetooth 856 * Bluetooth
731 */ 857 */
858static int asus_bluetooth_set(struct asus_laptop *asus, int status)
859{
860 if (write_acpi_int(asus->handle, METHOD_BLUETOOTH, !!status)) {
861 pr_warning("Error setting bluetooth status to %d", status);
862 return -EIO;
863 }
864 return 0;
865}
866
732static ssize_t show_bluetooth(struct device *dev, 867static ssize_t show_bluetooth(struct device *dev,
733 struct device_attribute *attr, char *buf) 868 struct device_attribute *attr, char *buf)
734{ 869{
735 return sprintf(buf, "%d\n", read_status(BT_ON)); 870 struct asus_laptop *asus = dev_get_drvdata(dev);
871
872 return sprintf(buf, "%d\n", asus_wireless_status(asus, BT_RSTS));
736} 873}
737 874
738static ssize_t store_bluetooth(struct device *dev, 875static ssize_t store_bluetooth(struct device *dev,
739 struct device_attribute *attr, const char *buf, 876 struct device_attribute *attr, const char *buf,
740 size_t count) 877 size_t count)
741{ 878{
742 return store_status(buf, count, bt_switch_handle, BT_ON); 879 struct asus_laptop *asus = dev_get_drvdata(dev);
880
881 return sysfs_acpi_set(asus, buf, count, METHOD_BLUETOOTH);
743} 882}
744 883
745/* 884/*
746 * Display 885 * Display
747 */ 886 */
748static void set_display(int value) 887static void asus_set_display(struct asus_laptop *asus, int value)
749{ 888{
750 /* no sanity check needed for now */ 889 /* no sanity check needed for now */
751 if (write_acpi_int(display_set_handle, NULL, value, NULL)) 890 if (write_acpi_int(asus->handle, METHOD_SWITCH_DISPLAY, value))
752 pr_warning("Error setting display\n"); 891 pr_warning("Error setting display\n");
753 return; 892 return;
754} 893}
755 894
756static int read_display(void) 895static int read_display(struct asus_laptop *asus)
757{ 896{
758 unsigned long long value = 0; 897 unsigned long long value = 0;
759 acpi_status rv = AE_OK; 898 acpi_status rv = AE_OK;
@@ -769,7 +908,7 @@ static int read_display(void)
769 pr_warning("Error reading display status\n"); 908 pr_warning("Error reading display status\n");
770 } 909 }
771 910
772 value &= 0x0F; /* needed for some models, shouldn't hurt others */ 911 value &= 0x0F; /* needed for some models, shouldn't hurt others */
773 912
774 return value; 913 return value;
775} 914}
@@ -781,7 +920,11 @@ static int read_display(void)
781static ssize_t show_disp(struct device *dev, 920static ssize_t show_disp(struct device *dev,
782 struct device_attribute *attr, char *buf) 921 struct device_attribute *attr, char *buf)
783{ 922{
784 return sprintf(buf, "%d\n", read_display()); 923 struct asus_laptop *asus = dev_get_drvdata(dev);
924
925 if (!display_get_handle)
926 return -ENODEV;
927 return sprintf(buf, "%d\n", read_display(asus));
785} 928}
786 929
787/* 930/*
@@ -794,65 +937,72 @@ static ssize_t show_disp(struct device *dev,
794static ssize_t store_disp(struct device *dev, struct device_attribute *attr, 937static ssize_t store_disp(struct device *dev, struct device_attribute *attr,
795 const char *buf, size_t count) 938 const char *buf, size_t count)
796{ 939{
940 struct asus_laptop *asus = dev_get_drvdata(dev);
797 int rv, value; 941 int rv, value;
798 942
799 rv = parse_arg(buf, count, &value); 943 rv = parse_arg(buf, count, &value);
800 if (rv > 0) 944 if (rv > 0)
801 set_display(value); 945 asus_set_display(asus, value);
802 return rv; 946 return rv;
803} 947}
804 948
805/* 949/*
806 * Light Sens 950 * Light Sens
807 */ 951 */
808static void set_light_sens_switch(int value) 952static void asus_als_switch(struct asus_laptop *asus, int value)
809{ 953{
810 if (write_acpi_int(ls_switch_handle, NULL, value, NULL)) 954 if (write_acpi_int(asus->handle, METHOD_ALS_CONTROL, value))
811 pr_warning("Error setting light sensor switch\n"); 955 pr_warning("Error setting light sensor switch\n");
812 hotk->light_switch = value; 956 asus->light_switch = value;
813} 957}
814 958
815static ssize_t show_lssw(struct device *dev, 959static ssize_t show_lssw(struct device *dev,
816 struct device_attribute *attr, char *buf) 960 struct device_attribute *attr, char *buf)
817{ 961{
818 return sprintf(buf, "%d\n", hotk->light_switch); 962 struct asus_laptop *asus = dev_get_drvdata(dev);
963
964 return sprintf(buf, "%d\n", asus->light_switch);
819} 965}
820 966
821static ssize_t store_lssw(struct device *dev, struct device_attribute *attr, 967static ssize_t store_lssw(struct device *dev, struct device_attribute *attr,
822 const char *buf, size_t count) 968 const char *buf, size_t count)
823{ 969{
970 struct asus_laptop *asus = dev_get_drvdata(dev);
824 int rv, value; 971 int rv, value;
825 972
826 rv = parse_arg(buf, count, &value); 973 rv = parse_arg(buf, count, &value);
827 if (rv > 0) 974 if (rv > 0)
828 set_light_sens_switch(value ? 1 : 0); 975 asus_als_switch(asus, value ? 1 : 0);
829 976
830 return rv; 977 return rv;
831} 978}
832 979
833static void set_light_sens_level(int value) 980static void asus_als_level(struct asus_laptop *asus, int value)
834{ 981{
835 if (write_acpi_int(ls_level_handle, NULL, value, NULL)) 982 if (write_acpi_int(asus->handle, METHOD_ALS_LEVEL, value))
836 pr_warning("Error setting light sensor level\n"); 983 pr_warning("Error setting light sensor level\n");
837 hotk->light_level = value; 984 asus->light_level = value;
838} 985}
839 986
840static ssize_t show_lslvl(struct device *dev, 987static ssize_t show_lslvl(struct device *dev,
841 struct device_attribute *attr, char *buf) 988 struct device_attribute *attr, char *buf)
842{ 989{
843 return sprintf(buf, "%d\n", hotk->light_level); 990 struct asus_laptop *asus = dev_get_drvdata(dev);
991
992 return sprintf(buf, "%d\n", asus->light_level);
844} 993}
845 994
846static ssize_t store_lslvl(struct device *dev, struct device_attribute *attr, 995static ssize_t store_lslvl(struct device *dev, struct device_attribute *attr,
847 const char *buf, size_t count) 996 const char *buf, size_t count)
848{ 997{
998 struct asus_laptop *asus = dev_get_drvdata(dev);
849 int rv, value; 999 int rv, value;
850 1000
851 rv = parse_arg(buf, count, &value); 1001 rv = parse_arg(buf, count, &value);
852 if (rv > 0) { 1002 if (rv > 0) {
853 value = (0 < value) ? ((15 < value) ? 15 : value) : 0; 1003 value = (0 < value) ? ((15 < value) ? 15 : value) : 0;
854 /* 0 <= value <= 15 */ 1004 /* 0 <= value <= 15 */
855 set_light_sens_level(value); 1005 asus_als_level(asus, value);
856 } 1006 }
857 1007
858 return rv; 1008 return rv;
@@ -861,197 +1011,309 @@ static ssize_t store_lslvl(struct device *dev, struct device_attribute *attr,
861/* 1011/*
862 * GPS 1012 * GPS
863 */ 1013 */
1014static int asus_gps_status(struct asus_laptop *asus)
1015{
1016 unsigned long long status;
1017 acpi_status rv = AE_OK;
1018
1019 rv = acpi_evaluate_integer(asus->handle, METHOD_GPS_STATUS,
1020 NULL, &status);
1021 if (ACPI_FAILURE(rv)) {
1022 pr_warning("Error reading GPS status\n");
1023 return -ENODEV;
1024 }
1025 return !!status;
1026}
1027
1028static int asus_gps_switch(struct asus_laptop *asus, int status)
1029{
1030 const char *meth = status ? METHOD_GPS_ON : METHOD_GPS_OFF;
1031
1032 if (write_acpi_int(asus->handle, meth, 0x02))
1033 return -ENODEV;
1034 return 0;
1035}
1036
864static ssize_t show_gps(struct device *dev, 1037static ssize_t show_gps(struct device *dev,
865 struct device_attribute *attr, char *buf) 1038 struct device_attribute *attr, char *buf)
866{ 1039{
867 return sprintf(buf, "%d\n", read_status(GPS_ON)); 1040 struct asus_laptop *asus = dev_get_drvdata(dev);
1041
1042 return sprintf(buf, "%d\n", asus_gps_status(asus));
868} 1043}
869 1044
870static ssize_t store_gps(struct device *dev, struct device_attribute *attr, 1045static ssize_t store_gps(struct device *dev, struct device_attribute *attr,
871 const char *buf, size_t count) 1046 const char *buf, size_t count)
872{ 1047{
873 return store_status(buf, count, NULL, GPS_ON); 1048 struct asus_laptop *asus = dev_get_drvdata(dev);
1049 int rv, value;
1050 int ret;
1051
1052 rv = parse_arg(buf, count, &value);
1053 if (rv <= 0)
1054 return -EINVAL;
1055 ret = asus_gps_switch(asus, !!value);
1056 if (ret)
1057 return ret;
1058 rfkill_set_sw_state(asus->gps_rfkill, !value);
1059 return rv;
874} 1060}
875 1061
876/* 1062/*
877 * Hotkey functions 1063 * rfkill
878 */ 1064 */
879static struct key_entry *asus_get_entry_by_scancode(int code) 1065static int asus_gps_rfkill_set(void *data, bool blocked)
880{ 1066{
881 struct key_entry *key; 1067 acpi_handle handle = data;
882 1068
883 for (key = asus_keymap; key->type != KE_END; key++) 1069 return asus_gps_switch(handle, !blocked);
884 if (code == key->code)
885 return key;
886
887 return NULL;
888} 1070}
889 1071
890static struct key_entry *asus_get_entry_by_keycode(int code) 1072static const struct rfkill_ops asus_gps_rfkill_ops = {
891{ 1073 .set_block = asus_gps_rfkill_set,
892 struct key_entry *key; 1074};
893
894 for (key = asus_keymap; key->type != KE_END; key++)
895 if (code == key->keycode && key->type == KE_KEY)
896 return key;
897 1075
898 return NULL; 1076static void asus_rfkill_exit(struct asus_laptop *asus)
1077{
1078 if (asus->gps_rfkill) {
1079 rfkill_unregister(asus->gps_rfkill);
1080 rfkill_destroy(asus->gps_rfkill);
1081 asus->gps_rfkill = NULL;
1082 }
899} 1083}
900 1084
901static int asus_getkeycode(struct input_dev *dev, int scancode, int *keycode) 1085static int asus_rfkill_init(struct asus_laptop *asus)
902{ 1086{
903 struct key_entry *key = asus_get_entry_by_scancode(scancode); 1087 int result;
904 1088
905 if (key && key->type == KE_KEY) { 1089 if (acpi_check_handle(asus->handle, METHOD_GPS_ON, NULL) ||
906 *keycode = key->keycode; 1090 acpi_check_handle(asus->handle, METHOD_GPS_OFF, NULL) ||
1091 acpi_check_handle(asus->handle, METHOD_GPS_STATUS, NULL))
907 return 0; 1092 return 0;
1093
1094 asus->gps_rfkill = rfkill_alloc("asus-gps", &asus->platform_device->dev,
1095 RFKILL_TYPE_GPS,
1096 &asus_gps_rfkill_ops, NULL);
1097 if (!asus->gps_rfkill)
1098 return -EINVAL;
1099
1100 result = rfkill_register(asus->gps_rfkill);
1101 if (result) {
1102 rfkill_destroy(asus->gps_rfkill);
1103 asus->gps_rfkill = NULL;
908 } 1104 }
909 1105
910 return -EINVAL; 1106 return result;
911} 1107}
912 1108
913static int asus_setkeycode(struct input_dev *dev, int scancode, int keycode) 1109/*
1110 * Input device (i.e. hotkeys)
1111 */
1112static void asus_input_notify(struct asus_laptop *asus, int event)
914{ 1113{
915 struct key_entry *key; 1114 if (asus->inputdev)
916 int old_keycode; 1115 sparse_keymap_report_event(asus->inputdev, event, 1, true);
1116}
917 1117
918 if (keycode < 0 || keycode > KEY_MAX) 1118static int asus_input_init(struct asus_laptop *asus)
919 return -EINVAL; 1119{
1120 struct input_dev *input;
1121 int error;
920 1122
921 key = asus_get_entry_by_scancode(scancode); 1123 input = input_allocate_device();
922 if (key && key->type == KE_KEY) { 1124 if (!input) {
923 old_keycode = key->keycode; 1125 pr_info("Unable to allocate input device\n");
924 key->keycode = keycode;
925 set_bit(keycode, dev->keybit);
926 if (!asus_get_entry_by_keycode(old_keycode))
927 clear_bit(old_keycode, dev->keybit);
928 return 0; 1126 return 0;
929 } 1127 }
1128 input->name = "Asus Laptop extra buttons";
1129 input->phys = ASUS_LAPTOP_FILE "/input0";
1130 input->id.bustype = BUS_HOST;
1131 input->dev.parent = &asus->platform_device->dev;
1132 input_set_drvdata(input, asus);
1133
1134 error = sparse_keymap_setup(input, asus_keymap, NULL);
1135 if (error) {
1136 pr_err("Unable to setup input device keymap\n");
1137 goto err_keymap;
1138 }
1139 error = input_register_device(input);
1140 if (error) {
1141 pr_info("Unable to register input device\n");
1142 goto err_device;
1143 }
930 1144
931 return -EINVAL; 1145 asus->inputdev = input;
1146 return 0;
1147
1148err_keymap:
1149 sparse_keymap_free(input);
1150err_device:
1151 input_free_device(input);
1152 return error;
932} 1153}
933 1154
934static void asus_hotk_notify(struct acpi_device *device, u32 event) 1155static void asus_input_exit(struct asus_laptop *asus)
935{ 1156{
936 static struct key_entry *key; 1157 if (asus->inputdev) {
937 u16 count; 1158 sparse_keymap_free(asus->inputdev);
1159 input_unregister_device(asus->inputdev);
1160 }
1161}
938 1162
939 /* TODO Find a better way to handle events count. */ 1163/*
940 if (!hotk) 1164 * ACPI driver
941 return; 1165 */
1166static void asus_acpi_notify(struct acpi_device *device, u32 event)
1167{
1168 struct asus_laptop *asus = acpi_driver_data(device);
1169 u16 count;
942 1170
943 /* 1171 /*
944 * We need to tell the backlight device when the backlight power is 1172 * We need to tell the backlight device when the backlight power is
945 * switched 1173 * switched
946 */ 1174 */
947 if (event == ATKD_LCD_ON) { 1175 if (event == ATKD_LCD_ON)
948 write_status(NULL, 1, LCD_ON); 1176 lcd_blank(asus, FB_BLANK_UNBLANK);
949 lcd_blank(FB_BLANK_UNBLANK); 1177 else if (event == ATKD_LCD_OFF)
950 } else if (event == ATKD_LCD_OFF) { 1178 lcd_blank(asus, FB_BLANK_POWERDOWN);
951 write_status(NULL, 0, LCD_ON);
952 lcd_blank(FB_BLANK_POWERDOWN);
953 }
954 1179
955 count = hotk->event_count[event % 128]++; 1180 /* TODO Find a better way to handle events count. */
956 acpi_bus_generate_proc_event(hotk->device, event, count); 1181 count = asus->event_count[event % 128]++;
957 acpi_bus_generate_netlink_event(hotk->device->pnp.device_class, 1182 acpi_bus_generate_proc_event(asus->device, event, count);
958 dev_name(&hotk->device->dev), event, 1183 acpi_bus_generate_netlink_event(asus->device->pnp.device_class,
1184 dev_name(&asus->device->dev), event,
959 count); 1185 count);
960 1186
961 if (hotk->inputdev) { 1187 /* Brightness events are special */
962 key = asus_get_entry_by_scancode(event); 1188 if (event >= ATKD_BR_MIN && event <= ATKD_BR_MAX) {
963 if (!key) 1189
964 return ; 1190 /* Ignore them completely if the acpi video driver is used */
965 1191 if (asus->backlight_device != NULL) {
966 switch (key->type) { 1192 /* Update the backlight device. */
967 case KE_KEY: 1193 asus_backlight_notify(asus);
968 input_report_key(hotk->inputdev, key->keycode, 1);
969 input_sync(hotk->inputdev);
970 input_report_key(hotk->inputdev, key->keycode, 0);
971 input_sync(hotk->inputdev);
972 break;
973 } 1194 }
1195 return ;
974 } 1196 }
1197 asus_input_notify(asus, event);
975} 1198}
976 1199
977#define ASUS_CREATE_DEVICE_ATTR(_name) \ 1200static DEVICE_ATTR(infos, S_IRUGO, show_infos, NULL);
978 struct device_attribute dev_attr_##_name = { \ 1201static DEVICE_ATTR(wlan, S_IRUGO | S_IWUSR, show_wlan, store_wlan);
979 .attr = { \ 1202static DEVICE_ATTR(bluetooth, S_IRUGO | S_IWUSR, show_bluetooth,
980 .name = __stringify(_name), \ 1203 store_bluetooth);
981 .mode = 0 }, \ 1204static DEVICE_ATTR(display, S_IRUGO | S_IWUSR, show_disp, store_disp);
982 .show = NULL, \ 1205static DEVICE_ATTR(ledd, S_IRUGO | S_IWUSR, show_ledd, store_ledd);
983 .store = NULL, \ 1206static DEVICE_ATTR(ls_level, S_IRUGO | S_IWUSR, show_lslvl, store_lslvl);
1207static DEVICE_ATTR(ls_switch, S_IRUGO | S_IWUSR, show_lssw, store_lssw);
1208static DEVICE_ATTR(gps, S_IRUGO | S_IWUSR, show_gps, store_gps);
1209
1210static void asus_sysfs_exit(struct asus_laptop *asus)
1211{
1212 struct platform_device *device = asus->platform_device;
1213
1214 device_remove_file(&device->dev, &dev_attr_infos);
1215 device_remove_file(&device->dev, &dev_attr_wlan);
1216 device_remove_file(&device->dev, &dev_attr_bluetooth);
1217 device_remove_file(&device->dev, &dev_attr_display);
1218 device_remove_file(&device->dev, &dev_attr_ledd);
1219 device_remove_file(&device->dev, &dev_attr_ls_switch);
1220 device_remove_file(&device->dev, &dev_attr_ls_level);
1221 device_remove_file(&device->dev, &dev_attr_gps);
1222}
1223
1224static int asus_sysfs_init(struct asus_laptop *asus)
1225{
1226 struct platform_device *device = asus->platform_device;
1227 int err;
1228
1229 err = device_create_file(&device->dev, &dev_attr_infos);
1230 if (err)
1231 return err;
1232
1233 if (!acpi_check_handle(asus->handle, METHOD_WLAN, NULL)) {
1234 err = device_create_file(&device->dev, &dev_attr_wlan);
1235 if (err)
1236 return err;
984 } 1237 }
985 1238
986#define ASUS_SET_DEVICE_ATTR(_name, _mode, _show, _store) \ 1239 if (!acpi_check_handle(asus->handle, METHOD_BLUETOOTH, NULL)) {
987 do { \ 1240 err = device_create_file(&device->dev, &dev_attr_bluetooth);
988 dev_attr_##_name.attr.mode = _mode; \ 1241 if (err)
989 dev_attr_##_name.show = _show; \ 1242 return err;
990 dev_attr_##_name.store = _store; \ 1243 }
991 } while(0)
992
993static ASUS_CREATE_DEVICE_ATTR(infos);
994static ASUS_CREATE_DEVICE_ATTR(wlan);
995static ASUS_CREATE_DEVICE_ATTR(bluetooth);
996static ASUS_CREATE_DEVICE_ATTR(display);
997static ASUS_CREATE_DEVICE_ATTR(ledd);
998static ASUS_CREATE_DEVICE_ATTR(ls_switch);
999static ASUS_CREATE_DEVICE_ATTR(ls_level);
1000static ASUS_CREATE_DEVICE_ATTR(gps);
1001
1002static struct attribute *asuspf_attributes[] = {
1003 &dev_attr_infos.attr,
1004 &dev_attr_wlan.attr,
1005 &dev_attr_bluetooth.attr,
1006 &dev_attr_display.attr,
1007 &dev_attr_ledd.attr,
1008 &dev_attr_ls_switch.attr,
1009 &dev_attr_ls_level.attr,
1010 &dev_attr_gps.attr,
1011 NULL
1012};
1013 1244
1014static struct attribute_group asuspf_attribute_group = { 1245 if (!acpi_check_handle(asus->handle, METHOD_SWITCH_DISPLAY, NULL)) {
1015 .attrs = asuspf_attributes 1246 err = device_create_file(&device->dev, &dev_attr_display);
1016}; 1247 if (err)
1248 return err;
1249 }
1017 1250
1018static struct platform_driver asuspf_driver = { 1251 if (!acpi_check_handle(asus->handle, METHOD_LEDD, NULL)) {
1019 .driver = { 1252 err = device_create_file(&device->dev, &dev_attr_ledd);
1020 .name = ASUS_HOTK_FILE, 1253 if (err)
1021 .owner = THIS_MODULE, 1254 return err;
1022 } 1255 }
1023};
1024 1256
1025static struct platform_device *asuspf_device; 1257 if (!acpi_check_handle(asus->handle, METHOD_ALS_CONTROL, NULL) &&
1258 !acpi_check_handle(asus->handle, METHOD_ALS_LEVEL, NULL)) {
1259 err = device_create_file(&device->dev, &dev_attr_ls_switch);
1260 if (err)
1261 return err;
1262 err = device_create_file(&device->dev, &dev_attr_ls_level);
1263 if (err)
1264 return err;
1265 }
1026 1266
1027static void asus_hotk_add_fs(void) 1267 if (!acpi_check_handle(asus->handle, METHOD_GPS_ON, NULL) &&
1028{ 1268 !acpi_check_handle(asus->handle, METHOD_GPS_OFF, NULL) &&
1029 ASUS_SET_DEVICE_ATTR(infos, 0444, show_infos, NULL); 1269 !acpi_check_handle(asus->handle, METHOD_GPS_STATUS, NULL)) {
1270 err = device_create_file(&device->dev, &dev_attr_gps);
1271 if (err)
1272 return err;
1273 }
1274
1275 return err;
1276}
1030 1277
1031 if (wl_switch_handle) 1278static int asus_platform_init(struct asus_laptop *asus)
1032 ASUS_SET_DEVICE_ATTR(wlan, 0644, show_wlan, store_wlan); 1279{
1280 int err;
1033 1281
1034 if (bt_switch_handle) 1282 asus->platform_device = platform_device_alloc(ASUS_LAPTOP_FILE, -1);
1035 ASUS_SET_DEVICE_ATTR(bluetooth, 0644, 1283 if (!asus->platform_device)
1036 show_bluetooth, store_bluetooth); 1284 return -ENOMEM;
1285 platform_set_drvdata(asus->platform_device, asus);
1037 1286
1038 if (display_set_handle && display_get_handle) 1287 err = platform_device_add(asus->platform_device);
1039 ASUS_SET_DEVICE_ATTR(display, 0644, show_disp, store_disp); 1288 if (err)
1040 else if (display_set_handle) 1289 goto fail_platform_device;
1041 ASUS_SET_DEVICE_ATTR(display, 0200, NULL, store_disp);
1042 1290
1043 if (ledd_set_handle) 1291 err = asus_sysfs_init(asus);
1044 ASUS_SET_DEVICE_ATTR(ledd, 0644, show_ledd, store_ledd); 1292 if (err)
1293 goto fail_sysfs;
1294 return 0;
1045 1295
1046 if (ls_switch_handle && ls_level_handle) { 1296fail_sysfs:
1047 ASUS_SET_DEVICE_ATTR(ls_level, 0644, show_lslvl, store_lslvl); 1297 asus_sysfs_exit(asus);
1048 ASUS_SET_DEVICE_ATTR(ls_switch, 0644, show_lssw, store_lssw); 1298 platform_device_del(asus->platform_device);
1049 } 1299fail_platform_device:
1300 platform_device_put(asus->platform_device);
1301 return err;
1302}
1050 1303
1051 if (gps_status_handle && gps_on_handle && gps_off_handle) 1304static void asus_platform_exit(struct asus_laptop *asus)
1052 ASUS_SET_DEVICE_ATTR(gps, 0644, show_gps, store_gps); 1305{
1306 asus_sysfs_exit(asus);
1307 platform_device_unregister(asus->platform_device);
1053} 1308}
1054 1309
1310static struct platform_driver platform_driver = {
1311 .driver = {
1312 .name = ASUS_LAPTOP_FILE,
1313 .owner = THIS_MODULE,
1314 }
1315};
1316
1055static int asus_handle_init(char *name, acpi_handle * handle, 1317static int asus_handle_init(char *name, acpi_handle * handle,
1056 char **paths, int num_paths) 1318 char **paths, int num_paths)
1057{ 1319{
@@ -1073,10 +1335,11 @@ static int asus_handle_init(char *name, acpi_handle * handle,
1073 ARRAY_SIZE(object##_paths)) 1335 ARRAY_SIZE(object##_paths))
1074 1336
1075/* 1337/*
1076 * This function is used to initialize the hotk with right values. In this 1338 * This function is used to initialize the context with right values. In this
1077 * method, we can make all the detection we want, and modify the hotk struct 1339 * method, we can make all the detection we want, and modify the asus_laptop
1340 * struct
1078 */ 1341 */
1079static int asus_hotk_get_info(void) 1342static int asus_laptop_get_info(struct asus_laptop *asus)
1080{ 1343{
1081 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 1344 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
1082 union acpi_object *model = NULL; 1345 union acpi_object *model = NULL;
@@ -1089,22 +1352,21 @@ static int asus_hotk_get_info(void)
1089 * models, but late enough to allow acpi_bus_register_driver() to fail 1352 * models, but late enough to allow acpi_bus_register_driver() to fail
1090 * before doing anything ACPI-specific. Should we encounter a machine, 1353 * before doing anything ACPI-specific. Should we encounter a machine,
1091 * which needs special handling (i.e. its hotkey device has a different 1354 * which needs special handling (i.e. its hotkey device has a different
1092 * HID), this bit will be moved. A global variable asus_info contains 1355 * HID), this bit will be moved.
1093 * the DSDT header.
1094 */ 1356 */
1095 status = acpi_get_table(ACPI_SIG_DSDT, 1, &asus_info); 1357 status = acpi_get_table(ACPI_SIG_DSDT, 1, &asus->dsdt_info);
1096 if (ACPI_FAILURE(status)) 1358 if (ACPI_FAILURE(status))
1097 pr_warning("Couldn't get the DSDT table header\n"); 1359 pr_warning("Couldn't get the DSDT table header\n");
1098 1360
1099 /* We have to write 0 on init this far for all ASUS models */ 1361 /* We have to write 0 on init this far for all ASUS models */
1100 if (write_acpi_int(hotk->handle, "INIT", 0, &buffer)) { 1362 if (write_acpi_int_ret(asus->handle, "INIT", 0, &buffer)) {
1101 pr_err("Hotkey initialization failed\n"); 1363 pr_err("Hotkey initialization failed\n");
1102 return -ENODEV; 1364 return -ENODEV;
1103 } 1365 }
1104 1366
1105 /* This needs to be called for some laptops to init properly */ 1367 /* This needs to be called for some laptops to init properly */
1106 status = 1368 status =
1107 acpi_evaluate_integer(hotk->handle, "BSTS", NULL, &bsts_result); 1369 acpi_evaluate_integer(asus->handle, "BSTS", NULL, &bsts_result);
1108 if (ACPI_FAILURE(status)) 1370 if (ACPI_FAILURE(status))
1109 pr_warning("Error calling BSTS\n"); 1371 pr_warning("Error calling BSTS\n");
1110 else if (bsts_result) 1372 else if (bsts_result)
@@ -1112,8 +1374,8 @@ static int asus_hotk_get_info(void)
1112 (uint) bsts_result); 1374 (uint) bsts_result);
1113 1375
1114 /* This too ... */ 1376 /* This too ... */
1115 write_acpi_int(hotk->handle, "CWAP", wapf, NULL); 1377 if (write_acpi_int(asus->handle, "CWAP", wapf))
1116 1378 pr_err("Error calling CWAP(%d)\n", wapf);
1117 /* 1379 /*
1118 * Try to match the object returned by INIT to the specific model. 1380 * Try to match the object returned by INIT to the specific model.
1119 * Handle every possible object (or the lack of thereof) the DSDT 1381 * Handle every possible object (or the lack of thereof) the DSDT
@@ -1134,397 +1396,210 @@ static int asus_hotk_get_info(void)
1134 break; 1396 break;
1135 } 1397 }
1136 } 1398 }
1137 hotk->name = kstrdup(string, GFP_KERNEL); 1399 asus->name = kstrdup(string, GFP_KERNEL);
1138 if (!hotk->name) 1400 if (!asus->name)
1139 return -ENOMEM; 1401 return -ENOMEM;
1140 1402
1141 if (*string) 1403 if (*string)
1142 pr_notice(" %s model detected\n", string); 1404 pr_notice(" %s model detected\n", string);
1143 1405
1144 ASUS_HANDLE_INIT(mled_set);
1145 ASUS_HANDLE_INIT(tled_set);
1146 ASUS_HANDLE_INIT(rled_set);
1147 ASUS_HANDLE_INIT(pled_set);
1148 ASUS_HANDLE_INIT(gled_set);
1149
1150 ASUS_HANDLE_INIT(ledd_set);
1151
1152 ASUS_HANDLE_INIT(kled_set);
1153 ASUS_HANDLE_INIT(kled_get);
1154
1155 /* 1406 /*
1156 * The HWRS method return informations about the hardware. 1407 * The HWRS method return informations about the hardware.
1157 * 0x80 bit is for WLAN, 0x100 for Bluetooth. 1408 * 0x80 bit is for WLAN, 0x100 for Bluetooth.
1158 * The significance of others is yet to be found. 1409 * The significance of others is yet to be found.
1159 * If we don't find the method, we assume the device are present.
1160 */ 1410 */
1161 status = 1411 status =
1162 acpi_evaluate_integer(hotk->handle, "HRWS", NULL, &hwrs_result); 1412 acpi_evaluate_integer(asus->handle, "HRWS", NULL, &hwrs_result);
1163 if (ACPI_FAILURE(status)) 1413 if (!ACPI_FAILURE(status))
1164 hwrs_result = WL_HWRS | BT_HWRS; 1414 pr_notice(" HRWS returned %x", (int)hwrs_result);
1165
1166 if (hwrs_result & WL_HWRS)
1167 ASUS_HANDLE_INIT(wl_switch);
1168 if (hwrs_result & BT_HWRS)
1169 ASUS_HANDLE_INIT(bt_switch);
1170 1415
1171 ASUS_HANDLE_INIT(wireless_status); 1416 if (!acpi_check_handle(asus->handle, METHOD_WL_STATUS, NULL))
1172 1417 asus->have_rsts = true;
1173 ASUS_HANDLE_INIT(brightness_set);
1174 ASUS_HANDLE_INIT(brightness_get);
1175 1418
1419 /* Scheduled for removal */
1176 ASUS_HANDLE_INIT(lcd_switch); 1420 ASUS_HANDLE_INIT(lcd_switch);
1177
1178 ASUS_HANDLE_INIT(display_set);
1179 ASUS_HANDLE_INIT(display_get); 1421 ASUS_HANDLE_INIT(display_get);
1180 1422
1181 /*
1182 * There is a lot of models with "ALSL", but a few get
1183 * a real light sens, so we need to check it.
1184 */
1185 if (!ASUS_HANDLE_INIT(ls_switch))
1186 ASUS_HANDLE_INIT(ls_level);
1187
1188 ASUS_HANDLE_INIT(gps_on);
1189 ASUS_HANDLE_INIT(gps_off);
1190 ASUS_HANDLE_INIT(gps_status);
1191
1192 kfree(model); 1423 kfree(model);
1193 1424
1194 return AE_OK; 1425 return AE_OK;
1195} 1426}
1196 1427
1197static int asus_input_init(void) 1428static bool asus_device_present;
1198{
1199 const struct key_entry *key;
1200 int result;
1201 1429
1202 hotk->inputdev = input_allocate_device(); 1430static int __devinit asus_acpi_init(struct asus_laptop *asus)
1203 if (!hotk->inputdev) {
1204 pr_info("Unable to allocate input device\n");
1205 return 0;
1206 }
1207 hotk->inputdev->name = "Asus Laptop extra buttons";
1208 hotk->inputdev->phys = ASUS_HOTK_FILE "/input0";
1209 hotk->inputdev->id.bustype = BUS_HOST;
1210 hotk->inputdev->getkeycode = asus_getkeycode;
1211 hotk->inputdev->setkeycode = asus_setkeycode;
1212
1213 for (key = asus_keymap; key->type != KE_END; key++) {
1214 switch (key->type) {
1215 case KE_KEY:
1216 set_bit(EV_KEY, hotk->inputdev->evbit);
1217 set_bit(key->keycode, hotk->inputdev->keybit);
1218 break;
1219 }
1220 }
1221 result = input_register_device(hotk->inputdev);
1222 if (result) {
1223 pr_info("Unable to register input device\n");
1224 input_free_device(hotk->inputdev);
1225 }
1226 return result;
1227}
1228
1229static int asus_hotk_check(void)
1230{ 1431{
1231 int result = 0; 1432 int result = 0;
1232 1433
1233 result = acpi_bus_get_status(hotk->device); 1434 result = acpi_bus_get_status(asus->device);
1234 if (result) 1435 if (result)
1235 return result; 1436 return result;
1236 1437 if (!asus->device->status.present) {
1237 if (hotk->device->status.present) {
1238 result = asus_hotk_get_info();
1239 } else {
1240 pr_err("Hotkey device not present, aborting\n"); 1438 pr_err("Hotkey device not present, aborting\n");
1241 return -EINVAL; 1439 return -ENODEV;
1242 } 1440 }
1243 1441
1244 return result; 1442 result = asus_laptop_get_info(asus);
1245}
1246
1247static int asus_hotk_found;
1248
1249static int asus_hotk_add(struct acpi_device *device)
1250{
1251 int result;
1252
1253 pr_notice("Asus Laptop Support version %s\n",
1254 ASUS_LAPTOP_VERSION);
1255
1256 hotk = kzalloc(sizeof(struct asus_hotk), GFP_KERNEL);
1257 if (!hotk)
1258 return -ENOMEM;
1259
1260 hotk->handle = device->handle;
1261 strcpy(acpi_device_name(device), ASUS_HOTK_DEVICE_NAME);
1262 strcpy(acpi_device_class(device), ASUS_HOTK_CLASS);
1263 device->driver_data = hotk;
1264 hotk->device = device;
1265
1266 result = asus_hotk_check();
1267 if (result) 1443 if (result)
1268 goto end; 1444 return result;
1269
1270 asus_hotk_add_fs();
1271
1272 asus_hotk_found = 1;
1273 1445
1274 /* WLED and BLED are on by default */ 1446 /* WLED and BLED are on by default */
1275 write_status(bt_switch_handle, 1, BT_ON); 1447 if (bluetooth_status >= 0)
1276 write_status(wl_switch_handle, 1, WL_ON); 1448 asus_bluetooth_set(asus, !!bluetooth_status);
1277 1449
1278 /* If the h/w switch is off, we need to check the real status */ 1450 if (wlan_status >= 0)
1279 write_status(NULL, read_status(BT_ON), BT_ON); 1451 asus_wlan_set(asus, !!wlan_status);
1280 write_status(NULL, read_status(WL_ON), WL_ON);
1281
1282 /* LCD Backlight is on by default */
1283 write_status(NULL, 1, LCD_ON);
1284 1452
1285 /* Keyboard Backlight is on by default */ 1453 /* Keyboard Backlight is on by default */
1286 if (kled_set_handle) 1454 if (!acpi_check_handle(asus->handle, METHOD_KBD_LIGHT_SET, NULL))
1287 set_kled_lvl(1); 1455 asus_kled_set(asus, 1);
1288 1456
1289 /* LED display is off by default */ 1457 /* LED display is off by default */
1290 hotk->ledd_status = 0xFFF; 1458 asus->ledd_status = 0xFFF;
1291 1459
1292 /* Set initial values of light sensor and level */ 1460 /* Set initial values of light sensor and level */
1293 hotk->light_switch = 0; /* Default to light sensor disabled */ 1461 asus->light_switch = 0; /* Default to light sensor disabled */
1294 hotk->light_level = 5; /* level 5 for sensor sensitivity */ 1462 asus->light_level = 5; /* level 5 for sensor sensitivity */
1295
1296 if (ls_switch_handle)
1297 set_light_sens_switch(hotk->light_switch);
1298
1299 if (ls_level_handle)
1300 set_light_sens_level(hotk->light_level);
1301
1302 /* GPS is on by default */
1303 write_status(NULL, 1, GPS_ON);
1304 1463
1305end: 1464 if (!acpi_check_handle(asus->handle, METHOD_ALS_CONTROL, NULL) &&
1306 if (result) { 1465 !acpi_check_handle(asus->handle, METHOD_ALS_LEVEL, NULL)) {
1307 kfree(hotk->name); 1466 asus_als_switch(asus, asus->light_switch);
1308 kfree(hotk); 1467 asus_als_level(asus, asus->light_level);
1309 } 1468 }
1310 1469
1470 asus->lcd_state = 1; /* LCD should be on when the module load */
1311 return result; 1471 return result;
1312} 1472}
1313 1473
1314static int asus_hotk_remove(struct acpi_device *device, int type) 1474static int __devinit asus_acpi_add(struct acpi_device *device)
1315{
1316 kfree(hotk->name);
1317 kfree(hotk);
1318
1319 return 0;
1320}
1321
1322static void asus_backlight_exit(void)
1323{ 1475{
1324 if (asus_backlight_device) 1476 struct asus_laptop *asus;
1325 backlight_device_unregister(asus_backlight_device); 1477 int result;
1326}
1327
1328#define ASUS_LED_UNREGISTER(object) \
1329 if (object##_led.dev) \
1330 led_classdev_unregister(&object##_led)
1331 1478
1332static void asus_led_exit(void) 1479 pr_notice("Asus Laptop Support version %s\n",
1333{ 1480 ASUS_LAPTOP_VERSION);
1334 destroy_workqueue(led_workqueue); 1481 asus = kzalloc(sizeof(struct asus_laptop), GFP_KERNEL);
1335 ASUS_LED_UNREGISTER(mled); 1482 if (!asus)
1336 ASUS_LED_UNREGISTER(tled); 1483 return -ENOMEM;
1337 ASUS_LED_UNREGISTER(pled); 1484 asus->handle = device->handle;
1338 ASUS_LED_UNREGISTER(rled); 1485 strcpy(acpi_device_name(device), ASUS_LAPTOP_DEVICE_NAME);
1339 ASUS_LED_UNREGISTER(gled); 1486 strcpy(acpi_device_class(device), ASUS_LAPTOP_CLASS);
1340 ASUS_LED_UNREGISTER(kled); 1487 device->driver_data = asus;
1341} 1488 asus->device = device;
1342 1489
1343static void asus_input_exit(void) 1490 result = asus_acpi_init(asus);
1344{ 1491 if (result)
1345 if (hotk->inputdev) 1492 goto fail_platform;
1346 input_unregister_device(hotk->inputdev);
1347}
1348 1493
1349static void __exit asus_laptop_exit(void) 1494 /*
1350{ 1495 * Register the platform device first. It is used as a parent for the
1351 asus_backlight_exit(); 1496 * sub-devices below.
1352 asus_led_exit(); 1497 */
1353 asus_input_exit(); 1498 result = asus_platform_init(asus);
1499 if (result)
1500 goto fail_platform;
1354 1501
1355 acpi_bus_unregister_driver(&asus_hotk_driver); 1502 if (!acpi_video_backlight_support()) {
1356 sysfs_remove_group(&asuspf_device->dev.kobj, &asuspf_attribute_group); 1503 result = asus_backlight_init(asus);
1357 platform_device_unregister(asuspf_device); 1504 if (result)
1358 platform_driver_unregister(&asuspf_driver); 1505 goto fail_backlight;
1359} 1506 } else
1507 pr_info("Backlight controlled by ACPI video driver\n");
1360 1508
1361static int asus_backlight_init(struct device *dev) 1509 result = asus_input_init(asus);
1362{ 1510 if (result)
1363 struct backlight_device *bd; 1511 goto fail_input;
1364 1512
1365 if (brightness_set_handle && lcd_switch_handle) { 1513 result = asus_led_init(asus);
1366 bd = backlight_device_register(ASUS_HOTK_FILE, dev, 1514 if (result)
1367 NULL, &asusbl_ops); 1515 goto fail_led;
1368 if (IS_ERR(bd)) {
1369 pr_err("Could not register asus backlight device\n");
1370 asus_backlight_device = NULL;
1371 return PTR_ERR(bd);
1372 }
1373 1516
1374 asus_backlight_device = bd; 1517 result = asus_rfkill_init(asus);
1518 if (result)
1519 goto fail_rfkill;
1375 1520
1376 bd->props.max_brightness = 15; 1521 asus_device_present = true;
1377 bd->props.brightness = read_brightness(NULL);
1378 bd->props.power = FB_BLANK_UNBLANK;
1379 backlight_update_status(bd);
1380 }
1381 return 0; 1522 return 0;
1382}
1383 1523
1384static int asus_led_register(acpi_handle handle, 1524fail_rfkill:
1385 struct led_classdev *ldev, struct device *dev) 1525 asus_led_exit(asus);
1386{ 1526fail_led:
1387 if (!handle) 1527 asus_input_exit(asus);
1388 return 0; 1528fail_input:
1529 asus_backlight_exit(asus);
1530fail_backlight:
1531 asus_platform_exit(asus);
1532fail_platform:
1533 kfree(asus->name);
1534 kfree(asus);
1389 1535
1390 return led_classdev_register(dev, ldev); 1536 return result;
1391} 1537}
1392 1538
1393#define ASUS_LED_REGISTER(object, device) \ 1539static int asus_acpi_remove(struct acpi_device *device, int type)
1394 asus_led_register(object##_set_handle, &object##_led, device)
1395
1396static int asus_led_init(struct device *dev)
1397{ 1540{
1398 int rv; 1541 struct asus_laptop *asus = acpi_driver_data(device);
1399
1400 rv = ASUS_LED_REGISTER(mled, dev);
1401 if (rv)
1402 goto out;
1403
1404 rv = ASUS_LED_REGISTER(tled, dev);
1405 if (rv)
1406 goto out1;
1407
1408 rv = ASUS_LED_REGISTER(rled, dev);
1409 if (rv)
1410 goto out2;
1411
1412 rv = ASUS_LED_REGISTER(pled, dev);
1413 if (rv)
1414 goto out3;
1415
1416 rv = ASUS_LED_REGISTER(gled, dev);
1417 if (rv)
1418 goto out4;
1419 1542
1420 if (kled_set_handle && kled_get_handle) 1543 asus_backlight_exit(asus);
1421 rv = ASUS_LED_REGISTER(kled, dev); 1544 asus_rfkill_exit(asus);
1422 if (rv) 1545 asus_led_exit(asus);
1423 goto out5; 1546 asus_input_exit(asus);
1424 1547 asus_platform_exit(asus);
1425 led_workqueue = create_singlethread_workqueue("led_workqueue");
1426 if (!led_workqueue)
1427 goto out6;
1428 1548
1549 kfree(asus->name);
1550 kfree(asus);
1429 return 0; 1551 return 0;
1430out6:
1431 rv = -ENOMEM;
1432 ASUS_LED_UNREGISTER(kled);
1433out5:
1434 ASUS_LED_UNREGISTER(gled);
1435out4:
1436 ASUS_LED_UNREGISTER(pled);
1437out3:
1438 ASUS_LED_UNREGISTER(rled);
1439out2:
1440 ASUS_LED_UNREGISTER(tled);
1441out1:
1442 ASUS_LED_UNREGISTER(mled);
1443out:
1444 return rv;
1445} 1552}
1446 1553
1554static const struct acpi_device_id asus_device_ids[] = {
1555 {"ATK0100", 0},
1556 {"ATK0101", 0},
1557 {"", 0},
1558};
1559MODULE_DEVICE_TABLE(acpi, asus_device_ids);
1560
1561static struct acpi_driver asus_acpi_driver = {
1562 .name = ASUS_LAPTOP_NAME,
1563 .class = ASUS_LAPTOP_CLASS,
1564 .owner = THIS_MODULE,
1565 .ids = asus_device_ids,
1566 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
1567 .ops = {
1568 .add = asus_acpi_add,
1569 .remove = asus_acpi_remove,
1570 .notify = asus_acpi_notify,
1571 },
1572};
1573
1447static int __init asus_laptop_init(void) 1574static int __init asus_laptop_init(void)
1448{ 1575{
1449 int result; 1576 int result;
1450 1577
1451 result = acpi_bus_register_driver(&asus_hotk_driver); 1578 result = platform_driver_register(&platform_driver);
1452 if (result < 0) 1579 if (result < 0)
1453 return result; 1580 return result;
1454 1581
1455 /* 1582 result = acpi_bus_register_driver(&asus_acpi_driver);
1456 * This is a bit of a kludge. We only want this module loaded 1583 if (result < 0)
1457 * for ASUS systems, but there's currently no way to probe the 1584 goto fail_acpi_driver;
1458 * ACPI namespace for ASUS HIDs. So we just return failure if 1585 if (!asus_device_present) {
1459 * we didn't find one, which will cause the module to be 1586 result = -ENODEV;
1460 * unloaded. 1587 goto fail_no_device;
1461 */
1462 if (!asus_hotk_found) {
1463 acpi_bus_unregister_driver(&asus_hotk_driver);
1464 return -ENODEV;
1465 }
1466
1467 result = asus_input_init();
1468 if (result)
1469 goto fail_input;
1470
1471 /* Register platform stuff */
1472 result = platform_driver_register(&asuspf_driver);
1473 if (result)
1474 goto fail_platform_driver;
1475
1476 asuspf_device = platform_device_alloc(ASUS_HOTK_FILE, -1);
1477 if (!asuspf_device) {
1478 result = -ENOMEM;
1479 goto fail_platform_device1;
1480 } 1588 }
1481
1482 result = platform_device_add(asuspf_device);
1483 if (result)
1484 goto fail_platform_device2;
1485
1486 result = sysfs_create_group(&asuspf_device->dev.kobj,
1487 &asuspf_attribute_group);
1488 if (result)
1489 goto fail_sysfs;
1490
1491 result = asus_led_init(&asuspf_device->dev);
1492 if (result)
1493 goto fail_led;
1494
1495 if (!acpi_video_backlight_support()) {
1496 result = asus_backlight_init(&asuspf_device->dev);
1497 if (result)
1498 goto fail_backlight;
1499 } else
1500 pr_info("Brightness ignored, must be controlled by "
1501 "ACPI video driver\n");
1502
1503 return 0; 1589 return 0;
1504 1590
1505fail_backlight: 1591fail_no_device:
1506 asus_led_exit(); 1592 acpi_bus_unregister_driver(&asus_acpi_driver);
1507 1593fail_acpi_driver:
1508fail_led: 1594 platform_driver_unregister(&platform_driver);
1509 sysfs_remove_group(&asuspf_device->dev.kobj,
1510 &asuspf_attribute_group);
1511
1512fail_sysfs:
1513 platform_device_del(asuspf_device);
1514
1515fail_platform_device2:
1516 platform_device_put(asuspf_device);
1517
1518fail_platform_device1:
1519 platform_driver_unregister(&asuspf_driver);
1520
1521fail_platform_driver:
1522 asus_input_exit();
1523
1524fail_input:
1525
1526 return result; 1595 return result;
1527} 1596}
1528 1597
1598static void __exit asus_laptop_exit(void)
1599{
1600 acpi_bus_unregister_driver(&asus_acpi_driver);
1601 platform_driver_unregister(&platform_driver);
1602}
1603
1529module_init(asus_laptop_init); 1604module_init(asus_laptop_init);
1530module_exit(asus_laptop_exit); 1605module_exit(asus_laptop_exit);
diff --git a/drivers/platform/x86/asus_acpi.c b/drivers/platform/x86/asus_acpi.c
index c1d2aeeea94..92fd30c9379 100644
--- a/drivers/platform/x86/asus_acpi.c
+++ b/drivers/platform/x86/asus_acpi.c
@@ -32,6 +32,7 @@
32 32
33#include <linux/kernel.h> 33#include <linux/kernel.h>
34#include <linux/module.h> 34#include <linux/module.h>
35#include <linux/slab.h>
35#include <linux/init.h> 36#include <linux/init.h>
36#include <linux/types.h> 37#include <linux/types.h>
37#include <linux/proc_fs.h> 38#include <linux/proc_fs.h>
@@ -1225,9 +1226,8 @@ static int asus_model_match(char *model)
1225 else if (strncmp(model, "M2N", 3) == 0 || 1226 else if (strncmp(model, "M2N", 3) == 0 ||
1226 strncmp(model, "M3N", 3) == 0 || 1227 strncmp(model, "M3N", 3) == 0 ||
1227 strncmp(model, "M5N", 3) == 0 || 1228 strncmp(model, "M5N", 3) == 0 ||
1228 strncmp(model, "M6N", 3) == 0 ||
1229 strncmp(model, "S1N", 3) == 0 || 1229 strncmp(model, "S1N", 3) == 0 ||
1230 strncmp(model, "S5N", 3) == 0 || strncmp(model, "W1N", 3) == 0) 1230 strncmp(model, "S5N", 3) == 0)
1231 return xxN; 1231 return xxN;
1232 else if (strncmp(model, "M1", 2) == 0) 1232 else if (strncmp(model, "M1", 2) == 0)
1233 return M1A; 1233 return M1A;
@@ -1482,6 +1482,7 @@ static void asus_acpi_exit(void)
1482 1482
1483static int __init asus_acpi_init(void) 1483static int __init asus_acpi_init(void)
1484{ 1484{
1485 struct backlight_properties props;
1485 int result; 1486 int result;
1486 1487
1487 result = acpi_bus_register_driver(&asus_hotk_driver); 1488 result = acpi_bus_register_driver(&asus_hotk_driver);
@@ -1508,15 +1509,17 @@ static int __init asus_acpi_init(void)
1508 return -ENODEV; 1509 return -ENODEV;
1509 } 1510 }
1510 1511
1512 memset(&props, 0, sizeof(struct backlight_properties));
1513 props.max_brightness = 15;
1511 asus_backlight_device = backlight_device_register("asus", NULL, NULL, 1514 asus_backlight_device = backlight_device_register("asus", NULL, NULL,
1512 &asus_backlight_data); 1515 &asus_backlight_data,
1516 &props);
1513 if (IS_ERR(asus_backlight_device)) { 1517 if (IS_ERR(asus_backlight_device)) {
1514 printk(KERN_ERR "Could not register asus backlight device\n"); 1518 printk(KERN_ERR "Could not register asus backlight device\n");
1515 asus_backlight_device = NULL; 1519 asus_backlight_device = NULL;
1516 asus_acpi_exit(); 1520 asus_acpi_exit();
1517 return -ENODEV; 1521 return -ENODEV;
1518 } 1522 }
1519 asus_backlight_device->props.max_brightness = 15;
1520 1523
1521 return 0; 1524 return 0;
1522} 1525}
diff --git a/drivers/platform/x86/classmate-laptop.c b/drivers/platform/x86/classmate-laptop.c
index 8cb20e45bad..7f9e5ddc949 100644
--- a/drivers/platform/x86/classmate-laptop.c
+++ b/drivers/platform/x86/classmate-laptop.c
@@ -19,6 +19,7 @@
19 19
20#include <linux/init.h> 20#include <linux/init.h>
21#include <linux/module.h> 21#include <linux/module.h>
22#include <linux/slab.h>
22#include <linux/workqueue.h> 23#include <linux/workqueue.h>
23#include <acpi/acpi_drivers.h> 24#include <acpi/acpi_drivers.h>
24#include <linux/backlight.h> 25#include <linux/backlight.h>
@@ -455,18 +456,22 @@ static int cmpc_bl_update_status(struct backlight_device *bd)
455 return -1; 456 return -1;
456} 457}
457 458
458static struct backlight_ops cmpc_bl_ops = { 459static const struct backlight_ops cmpc_bl_ops = {
459 .get_brightness = cmpc_bl_get_brightness, 460 .get_brightness = cmpc_bl_get_brightness,
460 .update_status = cmpc_bl_update_status 461 .update_status = cmpc_bl_update_status
461}; 462};
462 463
463static int cmpc_bl_add(struct acpi_device *acpi) 464static int cmpc_bl_add(struct acpi_device *acpi)
464{ 465{
466 struct backlight_properties props;
465 struct backlight_device *bd; 467 struct backlight_device *bd;
466 468
467 bd = backlight_device_register("cmpc_bl", &acpi->dev, 469 memset(&props, 0, sizeof(struct backlight_properties));
468 acpi->handle, &cmpc_bl_ops); 470 props.max_brightness = 7;
469 bd->props.max_brightness = 7; 471 bd = backlight_device_register("cmpc_bl", &acpi->dev, acpi->handle,
472 &cmpc_bl_ops, &props);
473 if (IS_ERR(bd))
474 return PTR_ERR(bd);
470 dev_set_drvdata(&acpi->dev, bd); 475 dev_set_drvdata(&acpi->dev, bd);
471 return 0; 476 return 0;
472} 477}
@@ -507,6 +512,10 @@ static int cmpc_keys_codes[] = {
507 KEY_BRIGHTNESSDOWN, 512 KEY_BRIGHTNESSDOWN,
508 KEY_BRIGHTNESSUP, 513 KEY_BRIGHTNESSUP,
509 KEY_VENDOR, 514 KEY_VENDOR,
515 KEY_UNKNOWN,
516 KEY_CAMERA,
517 KEY_BACK,
518 KEY_FORWARD,
510 KEY_MAX 519 KEY_MAX
511}; 520};
512 521
diff --git a/drivers/platform/x86/compal-laptop.c b/drivers/platform/x86/compal-laptop.c
index 2740b40aad9..71ff1545a93 100644
--- a/drivers/platform/x86/compal-laptop.c
+++ b/drivers/platform/x86/compal-laptop.c
@@ -291,12 +291,15 @@ static int __init compal_init(void)
291 /* Register backlight stuff */ 291 /* Register backlight stuff */
292 292
293 if (!acpi_video_backlight_support()) { 293 if (!acpi_video_backlight_support()) {
294 compalbl_device = backlight_device_register("compal-laptop", NULL, NULL, 294 struct backlight_properties props;
295 &compalbl_ops); 295 memset(&props, 0, sizeof(struct backlight_properties));
296 props.max_brightness = COMPAL_LCD_LEVEL_MAX - 1;
297 compalbl_device = backlight_device_register("compal-laptop",
298 NULL, NULL,
299 &compalbl_ops,
300 &props);
296 if (IS_ERR(compalbl_device)) 301 if (IS_ERR(compalbl_device))
297 return PTR_ERR(compalbl_device); 302 return PTR_ERR(compalbl_device);
298
299 compalbl_device->props.max_brightness = COMPAL_LCD_LEVEL_MAX-1;
300 } 303 }
301 304
302 ret = platform_driver_register(&compal_driver); 305 ret = platform_driver_register(&compal_driver);
diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
index b7f4d270591..661e3ac4d5b 100644
--- a/drivers/platform/x86/dell-laptop.c
+++ b/drivers/platform/x86/dell-laptop.c
@@ -24,6 +24,7 @@
24#include <linux/acpi.h> 24#include <linux/acpi.h>
25#include <linux/mm.h> 25#include <linux/mm.h>
26#include <linux/i8042.h> 26#include <linux/i8042.h>
27#include <linux/slab.h>
27#include "../../firmware/dcdbas.h" 28#include "../../firmware/dcdbas.h"
28 29
29#define BRIGHTNESS_TOKEN 0x7d 30#define BRIGHTNESS_TOKEN 0x7d
@@ -132,8 +133,8 @@ static struct dmi_system_id __devinitdata dell_blacklist[] = {
132}; 133};
133 134
134static struct calling_interface_buffer *buffer; 135static struct calling_interface_buffer *buffer;
135struct page *bufferpage; 136static struct page *bufferpage;
136DEFINE_MUTEX(buffer_mutex); 137static DEFINE_MUTEX(buffer_mutex);
137 138
138static int hwswitch_state; 139static int hwswitch_state;
139 140
@@ -559,10 +560,14 @@ static int __init dell_init(void)
559 release_buffer(); 560 release_buffer();
560 561
561 if (max_intensity) { 562 if (max_intensity) {
562 dell_backlight_device = backlight_device_register( 563 struct backlight_properties props;
563 "dell_backlight", 564 memset(&props, 0, sizeof(struct backlight_properties));
564 &platform_device->dev, NULL, 565 props.max_brightness = max_intensity;
565 &dell_ops); 566 dell_backlight_device = backlight_device_register("dell_backlight",
567 &platform_device->dev,
568 NULL,
569 &dell_ops,
570 &props);
566 571
567 if (IS_ERR(dell_backlight_device)) { 572 if (IS_ERR(dell_backlight_device)) {
568 ret = PTR_ERR(dell_backlight_device); 573 ret = PTR_ERR(dell_backlight_device);
@@ -570,7 +575,6 @@ static int __init dell_init(void)
570 goto fail_backlight; 575 goto fail_backlight;
571 } 576 }
572 577
573 dell_backlight_device->props.max_brightness = max_intensity;
574 dell_backlight_device->props.brightness = 578 dell_backlight_device->props.brightness =
575 dell_get_intensity(dell_backlight_device); 579 dell_get_intensity(dell_backlight_device);
576 backlight_update_status(dell_backlight_device); 580 backlight_update_status(dell_backlight_device);
@@ -580,6 +584,7 @@ static int __init dell_init(void)
580 584
581fail_backlight: 585fail_backlight:
582 i8042_remove_filter(dell_laptop_i8042_filter); 586 i8042_remove_filter(dell_laptop_i8042_filter);
587 cancel_delayed_work_sync(&dell_rfkill_work);
583fail_filter: 588fail_filter:
584 dell_cleanup_rfkill(); 589 dell_cleanup_rfkill();
585fail_rfkill: 590fail_rfkill:
@@ -597,12 +602,12 @@ fail_platform_driver:
597 602
598static void __exit dell_exit(void) 603static void __exit dell_exit(void)
599{ 604{
600 cancel_delayed_work_sync(&dell_rfkill_work);
601 i8042_remove_filter(dell_laptop_i8042_filter); 605 i8042_remove_filter(dell_laptop_i8042_filter);
606 cancel_delayed_work_sync(&dell_rfkill_work);
602 backlight_device_unregister(dell_backlight_device); 607 backlight_device_unregister(dell_backlight_device);
603 dell_cleanup_rfkill(); 608 dell_cleanup_rfkill();
604 if (platform_device) { 609 if (platform_device) {
605 platform_device_del(platform_device); 610 platform_device_unregister(platform_device);
606 platform_driver_unregister(&platform_driver); 611 platform_driver_unregister(&platform_driver);
607 } 612 }
608 kfree(da_tokens); 613 kfree(da_tokens);
diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c
index 1b1dddbd574..6ba6c30e5bb 100644
--- a/drivers/platform/x86/dell-wmi.c
+++ b/drivers/platform/x86/dell-wmi.c
@@ -26,6 +26,7 @@
26#include <linux/kernel.h> 26#include <linux/kernel.h>
27#include <linux/module.h> 27#include <linux/module.h>
28#include <linux/init.h> 28#include <linux/init.h>
29#include <linux/slab.h>
29#include <linux/types.h> 30#include <linux/types.h>
30#include <linux/input.h> 31#include <linux/input.h>
31#include <acpi/acpi_drivers.h> 32#include <acpi/acpi_drivers.h>
@@ -142,7 +143,7 @@ static struct key_entry *dell_wmi_keymap = dell_legacy_wmi_keymap;
142 143
143static struct input_dev *dell_wmi_input_dev; 144static struct input_dev *dell_wmi_input_dev;
144 145
145static struct key_entry *dell_wmi_get_entry_by_scancode(int code) 146static struct key_entry *dell_wmi_get_entry_by_scancode(unsigned int code)
146{ 147{
147 struct key_entry *key; 148 struct key_entry *key;
148 149
@@ -153,7 +154,7 @@ static struct key_entry *dell_wmi_get_entry_by_scancode(int code)
153 return NULL; 154 return NULL;
154} 155}
155 156
156static struct key_entry *dell_wmi_get_entry_by_keycode(int keycode) 157static struct key_entry *dell_wmi_get_entry_by_keycode(unsigned int keycode)
157{ 158{
158 struct key_entry *key; 159 struct key_entry *key;
159 160
@@ -164,8 +165,8 @@ static struct key_entry *dell_wmi_get_entry_by_keycode(int keycode)
164 return NULL; 165 return NULL;
165} 166}
166 167
167static int dell_wmi_getkeycode(struct input_dev *dev, int scancode, 168static int dell_wmi_getkeycode(struct input_dev *dev,
168 int *keycode) 169 unsigned int scancode, unsigned int *keycode)
169{ 170{
170 struct key_entry *key = dell_wmi_get_entry_by_scancode(scancode); 171 struct key_entry *key = dell_wmi_get_entry_by_scancode(scancode);
171 172
@@ -177,13 +178,11 @@ static int dell_wmi_getkeycode(struct input_dev *dev, int scancode,
177 return -EINVAL; 178 return -EINVAL;
178} 179}
179 180
180static int dell_wmi_setkeycode(struct input_dev *dev, int scancode, int keycode) 181static int dell_wmi_setkeycode(struct input_dev *dev,
182 unsigned int scancode, unsigned int keycode)
181{ 183{
182 struct key_entry *key; 184 struct key_entry *key;
183 int old_keycode; 185 unsigned int old_keycode;
184
185 if (keycode < 0 || keycode > KEY_MAX)
186 return -EINVAL;
187 186
188 key = dell_wmi_get_entry_by_scancode(scancode); 187 key = dell_wmi_get_entry_by_scancode(scancode);
189 if (key && key->type == KE_KEY) { 188 if (key && key->type == KE_KEY) {
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c
index e2be6bb33d9..54a015785ca 100644
--- a/drivers/platform/x86/eeepc-laptop.c
+++ b/drivers/platform/x86/eeepc-laptop.c
@@ -27,6 +27,7 @@
27#include <linux/fb.h> 27#include <linux/fb.h>
28#include <linux/hwmon.h> 28#include <linux/hwmon.h>
29#include <linux/hwmon-sysfs.h> 29#include <linux/hwmon-sysfs.h>
30#include <linux/slab.h>
30#include <acpi/acpi_drivers.h> 31#include <acpi/acpi_drivers.h>
31#include <acpi/acpi_bus.h> 32#include <acpi/acpi_bus.h>
32#include <linux/uaccess.h> 33#include <linux/uaccess.h>
@@ -578,6 +579,8 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc)
578 struct pci_dev *dev; 579 struct pci_dev *dev;
579 struct pci_bus *bus; 580 struct pci_bus *bus;
580 bool blocked = eeepc_wlan_rfkill_blocked(eeepc); 581 bool blocked = eeepc_wlan_rfkill_blocked(eeepc);
582 bool absent;
583 u32 l;
581 584
582 if (eeepc->wlan_rfkill) 585 if (eeepc->wlan_rfkill)
583 rfkill_set_sw_state(eeepc->wlan_rfkill, blocked); 586 rfkill_set_sw_state(eeepc->wlan_rfkill, blocked);
@@ -591,6 +594,22 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc)
591 goto out_unlock; 594 goto out_unlock;
592 } 595 }
593 596
597 if (pci_bus_read_config_dword(bus, 0, PCI_VENDOR_ID, &l)) {
598 pr_err("Unable to read PCI config space?\n");
599 goto out_unlock;
600 }
601 absent = (l == 0xffffffff);
602
603 if (blocked != absent) {
604 pr_warning("BIOS says wireless lan is %s, "
605 "but the pci device is %s\n",
606 blocked ? "blocked" : "unblocked",
607 absent ? "absent" : "present");
608 pr_warning("skipped wireless hotplug as probably "
609 "inappropriate for this model\n");
610 goto out_unlock;
611 }
612
594 if (!blocked) { 613 if (!blocked) {
595 dev = pci_get_slot(bus, 0); 614 dev = pci_get_slot(bus, 0);
596 if (dev) { 615 if (dev) {
@@ -1113,18 +1132,20 @@ static int eeepc_backlight_notify(struct eeepc_laptop *eeepc)
1113 1132
1114static int eeepc_backlight_init(struct eeepc_laptop *eeepc) 1133static int eeepc_backlight_init(struct eeepc_laptop *eeepc)
1115{ 1134{
1135 struct backlight_properties props;
1116 struct backlight_device *bd; 1136 struct backlight_device *bd;
1117 1137
1138 memset(&props, 0, sizeof(struct backlight_properties));
1139 props.max_brightness = 15;
1118 bd = backlight_device_register(EEEPC_LAPTOP_FILE, 1140 bd = backlight_device_register(EEEPC_LAPTOP_FILE,
1119 &eeepc->platform_device->dev, 1141 &eeepc->platform_device->dev, eeepc,
1120 eeepc, &eeepcbl_ops); 1142 &eeepcbl_ops, &props);
1121 if (IS_ERR(bd)) { 1143 if (IS_ERR(bd)) {
1122 pr_err("Could not register eeepc backlight device\n"); 1144 pr_err("Could not register eeepc backlight device\n");
1123 eeepc->backlight_device = NULL; 1145 eeepc->backlight_device = NULL;
1124 return PTR_ERR(bd); 1146 return PTR_ERR(bd);
1125 } 1147 }
1126 eeepc->backlight_device = bd; 1148 eeepc->backlight_device = bd;
1127 bd->props.max_brightness = 15;
1128 bd->props.brightness = read_brightness(bd); 1149 bd->props.brightness = read_brightness(bd);
1129 bd->props.power = FB_BLANK_UNBLANK; 1150 bd->props.power = FB_BLANK_UNBLANK;
1130 backlight_update_status(bd); 1151 backlight_update_status(bd);
@@ -1277,7 +1298,8 @@ static void eeepc_dmi_check(struct eeepc_laptop *eeepc)
1277 * hotplug code. In fact, current hotplug code seems to unplug another 1298 * hotplug code. In fact, current hotplug code seems to unplug another
1278 * device... 1299 * device...
1279 */ 1300 */
1280 if (strcmp(model, "1005HA") == 0 || strcmp(model, "1201N") == 0) { 1301 if (strcmp(model, "1005HA") == 0 || strcmp(model, "1201N") == 0 ||
1302 strcmp(model, "1005PE") == 0) {
1281 eeepc->hotplug_disabled = true; 1303 eeepc->hotplug_disabled = true;
1282 pr_info("wlan hotplug disabled\n"); 1304 pr_info("wlan hotplug disabled\n");
1283 } 1305 }
diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c
new file mode 100644
index 00000000000..9f8822658fd
--- /dev/null
+++ b/drivers/platform/x86/eeepc-wmi.c
@@ -0,0 +1,158 @@
1/*
2 * Eee PC WMI hotkey driver
3 *
4 * Copyright(C) 2010 Intel Corporation.
5 *
6 * Portions based on wistron_btns.c:
7 * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz>
8 * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org>
9 * Copyright (C) 2005 Dmitry Torokhov <dtor@mail.ru>
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,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */
25
26#include <linux/kernel.h>
27#include <linux/module.h>
28#include <linux/init.h>
29#include <linux/types.h>
30#include <linux/slab.h>
31#include <linux/input.h>
32#include <linux/input/sparse-keymap.h>
33#include <acpi/acpi_bus.h>
34#include <acpi/acpi_drivers.h>
35
36MODULE_AUTHOR("Yong Wang <yong.y.wang@intel.com>");
37MODULE_DESCRIPTION("Eee PC WMI Hotkey Driver");
38MODULE_LICENSE("GPL");
39
40#define EEEPC_WMI_EVENT_GUID "ABBC0F72-8EA1-11D1-00A0-C90629100000"
41
42MODULE_ALIAS("wmi:"EEEPC_WMI_EVENT_GUID);
43
44#define NOTIFY_BRNUP_MIN 0x11
45#define NOTIFY_BRNUP_MAX 0x1f
46#define NOTIFY_BRNDOWN_MIN 0x20
47#define NOTIFY_BRNDOWN_MAX 0x2e
48
49static const struct key_entry eeepc_wmi_keymap[] = {
50 /* Sleep already handled via generic ACPI code */
51 { KE_KEY, 0x5d, { KEY_WLAN } },
52 { KE_KEY, 0x32, { KEY_MUTE } },
53 { KE_KEY, 0x31, { KEY_VOLUMEDOWN } },
54 { KE_KEY, 0x30, { KEY_VOLUMEUP } },
55 { KE_IGNORE, NOTIFY_BRNDOWN_MIN, { KEY_BRIGHTNESSDOWN } },
56 { KE_IGNORE, NOTIFY_BRNUP_MIN, { KEY_BRIGHTNESSUP } },
57 { KE_KEY, 0xcc, { KEY_SWITCHVIDEOMODE } },
58 { KE_END, 0},
59};
60
61static struct input_dev *eeepc_wmi_input_dev;
62
63static void eeepc_wmi_notify(u32 value, void *context)
64{
65 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
66 union acpi_object *obj;
67 acpi_status status;
68 int code;
69
70 status = wmi_get_event_data(value, &response);
71 if (status != AE_OK) {
72 pr_err("EEEPC WMI: bad event status 0x%x\n", status);
73 return;
74 }
75
76 obj = (union acpi_object *)response.pointer;
77
78 if (obj && obj->type == ACPI_TYPE_INTEGER) {
79 code = obj->integer.value;
80
81 if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX)
82 code = NOTIFY_BRNUP_MIN;
83 else if (code >= NOTIFY_BRNDOWN_MIN && code <= NOTIFY_BRNDOWN_MAX)
84 code = NOTIFY_BRNDOWN_MIN;
85
86 if (!sparse_keymap_report_event(eeepc_wmi_input_dev,
87 code, 1, true))
88 pr_info("EEEPC WMI: Unknown key %x pressed\n", code);
89 }
90
91 kfree(obj);
92}
93
94static int eeepc_wmi_input_setup(void)
95{
96 int err;
97
98 eeepc_wmi_input_dev = input_allocate_device();
99 if (!eeepc_wmi_input_dev)
100 return -ENOMEM;
101
102 eeepc_wmi_input_dev->name = "Eee PC WMI hotkeys";
103 eeepc_wmi_input_dev->phys = "wmi/input0";
104 eeepc_wmi_input_dev->id.bustype = BUS_HOST;
105
106 err = sparse_keymap_setup(eeepc_wmi_input_dev, eeepc_wmi_keymap, NULL);
107 if (err)
108 goto err_free_dev;
109
110 err = input_register_device(eeepc_wmi_input_dev);
111 if (err)
112 goto err_free_keymap;
113
114 return 0;
115
116err_free_keymap:
117 sparse_keymap_free(eeepc_wmi_input_dev);
118err_free_dev:
119 input_free_device(eeepc_wmi_input_dev);
120 return err;
121}
122
123static int __init eeepc_wmi_init(void)
124{
125 int err;
126 acpi_status status;
127
128 if (!wmi_has_guid(EEEPC_WMI_EVENT_GUID)) {
129 pr_warning("EEEPC WMI: No known WMI GUID found\n");
130 return -ENODEV;
131 }
132
133 err = eeepc_wmi_input_setup();
134 if (err)
135 return err;
136
137 status = wmi_install_notify_handler(EEEPC_WMI_EVENT_GUID,
138 eeepc_wmi_notify, NULL);
139 if (ACPI_FAILURE(status)) {
140 sparse_keymap_free(eeepc_wmi_input_dev);
141 input_unregister_device(eeepc_wmi_input_dev);
142 pr_err("EEEPC WMI: Unable to register notify handler - %d\n",
143 status);
144 return -ENODEV;
145 }
146
147 return 0;
148}
149
150static void __exit eeepc_wmi_exit(void)
151{
152 wmi_remove_notify_handler(EEEPC_WMI_EVENT_GUID);
153 sparse_keymap_free(eeepc_wmi_input_dev);
154 input_unregister_device(eeepc_wmi_input_dev);
155}
156
157module_init(eeepc_wmi_init);
158module_exit(eeepc_wmi_exit);
diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c
index 5f3320d468f..47b4fd75aa3 100644
--- a/drivers/platform/x86/fujitsu-laptop.c
+++ b/drivers/platform/x86/fujitsu-laptop.c
@@ -66,6 +66,7 @@
66#include <linux/kfifo.h> 66#include <linux/kfifo.h>
67#include <linux/video_output.h> 67#include <linux/video_output.h>
68#include <linux/platform_device.h> 68#include <linux/platform_device.h>
69#include <linux/slab.h>
69#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE) 70#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE)
70#include <linux/leds.h> 71#include <linux/leds.h>
71#endif 72#endif
@@ -1126,16 +1127,20 @@ static int __init fujitsu_init(void)
1126 /* Register backlight stuff */ 1127 /* Register backlight stuff */
1127 1128
1128 if (!acpi_video_backlight_support()) { 1129 if (!acpi_video_backlight_support()) {
1129 fujitsu->bl_device = 1130 struct backlight_properties props;
1130 backlight_device_register("fujitsu-laptop", NULL, NULL, 1131
1131 &fujitsubl_ops); 1132 memset(&props, 0, sizeof(struct backlight_properties));
1133 max_brightness = fujitsu->max_brightness;
1134 props.max_brightness = max_brightness - 1;
1135 fujitsu->bl_device = backlight_device_register("fujitsu-laptop",
1136 NULL, NULL,
1137 &fujitsubl_ops,
1138 &props);
1132 if (IS_ERR(fujitsu->bl_device)) { 1139 if (IS_ERR(fujitsu->bl_device)) {
1133 ret = PTR_ERR(fujitsu->bl_device); 1140 ret = PTR_ERR(fujitsu->bl_device);
1134 fujitsu->bl_device = NULL; 1141 fujitsu->bl_device = NULL;
1135 goto fail_sysfs_group; 1142 goto fail_sysfs_group;
1136 } 1143 }
1137 max_brightness = fujitsu->max_brightness;
1138 fujitsu->bl_device->props.max_brightness = max_brightness - 1;
1139 fujitsu->bl_device->props.brightness = fujitsu->brightness_level; 1144 fujitsu->bl_device->props.brightness = fujitsu->brightness_level;
1140 } 1145 }
1141 1146
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c
index 3aa57da8b43..51c07a05a7b 100644
--- a/drivers/platform/x86/hp-wmi.c
+++ b/drivers/platform/x86/hp-wmi.c
@@ -26,6 +26,7 @@
26#include <linux/kernel.h> 26#include <linux/kernel.h>
27#include <linux/module.h> 27#include <linux/module.h>
28#include <linux/init.h> 28#include <linux/init.h>
29#include <linux/slab.h>
29#include <linux/types.h> 30#include <linux/types.h>
30#include <linux/input.h> 31#include <linux/input.h>
31#include <acpi/acpi_drivers.h> 32#include <acpi/acpi_drivers.h>
@@ -57,7 +58,7 @@ enum hp_wmi_radio {
57 HPWMI_WWAN = 2, 58 HPWMI_WWAN = 2,
58}; 59};
59 60
60static int __init hp_wmi_bios_setup(struct platform_device *device); 61static int __devinit hp_wmi_bios_setup(struct platform_device *device);
61static int __exit hp_wmi_bios_remove(struct platform_device *device); 62static int __exit hp_wmi_bios_remove(struct platform_device *device);
62static int hp_wmi_resume_handler(struct device *device); 63static int hp_wmi_resume_handler(struct device *device);
63 64
@@ -278,7 +279,7 @@ static DEVICE_ATTR(als, S_IRUGO | S_IWUSR, show_als, set_als);
278static DEVICE_ATTR(dock, S_IRUGO, show_dock, NULL); 279static DEVICE_ATTR(dock, S_IRUGO, show_dock, NULL);
279static DEVICE_ATTR(tablet, S_IRUGO, show_tablet, NULL); 280static DEVICE_ATTR(tablet, S_IRUGO, show_tablet, NULL);
280 281
281static struct key_entry *hp_wmi_get_entry_by_scancode(int code) 282static struct key_entry *hp_wmi_get_entry_by_scancode(unsigned int code)
282{ 283{
283 struct key_entry *key; 284 struct key_entry *key;
284 285
@@ -289,7 +290,7 @@ static struct key_entry *hp_wmi_get_entry_by_scancode(int code)
289 return NULL; 290 return NULL;
290} 291}
291 292
292static struct key_entry *hp_wmi_get_entry_by_keycode(int keycode) 293static struct key_entry *hp_wmi_get_entry_by_keycode(unsigned int keycode)
293{ 294{
294 struct key_entry *key; 295 struct key_entry *key;
295 296
@@ -300,7 +301,8 @@ static struct key_entry *hp_wmi_get_entry_by_keycode(int keycode)
300 return NULL; 301 return NULL;
301} 302}
302 303
303static int hp_wmi_getkeycode(struct input_dev *dev, int scancode, int *keycode) 304static int hp_wmi_getkeycode(struct input_dev *dev,
305 unsigned int scancode, unsigned int *keycode)
304{ 306{
305 struct key_entry *key = hp_wmi_get_entry_by_scancode(scancode); 307 struct key_entry *key = hp_wmi_get_entry_by_scancode(scancode);
306 308
@@ -312,13 +314,11 @@ static int hp_wmi_getkeycode(struct input_dev *dev, int scancode, int *keycode)
312 return -EINVAL; 314 return -EINVAL;
313} 315}
314 316
315static int hp_wmi_setkeycode(struct input_dev *dev, int scancode, int keycode) 317static int hp_wmi_setkeycode(struct input_dev *dev,
318 unsigned int scancode, unsigned int keycode)
316{ 319{
317 struct key_entry *key; 320 struct key_entry *key;
318 int old_keycode; 321 unsigned int old_keycode;
319
320 if (keycode < 0 || keycode > KEY_MAX)
321 return -EINVAL;
322 322
323 key = hp_wmi_get_entry_by_scancode(scancode); 323 key = hp_wmi_get_entry_by_scancode(scancode);
324 if (key && key->type == KE_KEY) { 324 if (key && key->type == KE_KEY) {
@@ -447,7 +447,7 @@ static void cleanup_sysfs(struct platform_device *device)
447 device_remove_file(&device->dev, &dev_attr_tablet); 447 device_remove_file(&device->dev, &dev_attr_tablet);
448} 448}
449 449
450static int __init hp_wmi_bios_setup(struct platform_device *device) 450static int __devinit hp_wmi_bios_setup(struct platform_device *device)
451{ 451{
452 int err; 452 int err;
453 int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0); 453 int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0);
diff --git a/drivers/platform/x86/intel_menlow.c b/drivers/platform/x86/intel_menlow.c
index f0a90a6bf39..2f795ce2b93 100644
--- a/drivers/platform/x86/intel_menlow.c
+++ b/drivers/platform/x86/intel_menlow.c
@@ -30,6 +30,7 @@
30#include <linux/kernel.h> 30#include <linux/kernel.h>
31#include <linux/module.h> 31#include <linux/module.h>
32#include <linux/init.h> 32#include <linux/init.h>
33#include <linux/slab.h>
33#include <linux/types.h> 34#include <linux/types.h>
34#include <linux/pci.h> 35#include <linux/pci.h>
35#include <linux/pm.h> 36#include <linux/pm.h>
@@ -396,6 +397,7 @@ static int intel_menlow_add_one_attribute(char *name, int mode, void *show,
396 if (!attr) 397 if (!attr)
397 return -ENOMEM; 398 return -ENOMEM;
398 399
400 sysfs_attr_init(&attr->attr.attr); /* That is consistent naming :D */
399 attr->attr.attr.name = name; 401 attr->attr.attr.name = name;
400 attr->attr.attr.mode = mode; 402 attr->attr.attr.mode = mode;
401 attr->attr.show = show; 403 attr->attr.show = show;
diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c
index 759763d18e4..996223a7c00 100644
--- a/drivers/platform/x86/msi-laptop.c
+++ b/drivers/platform/x86/msi-laptop.c
@@ -58,6 +58,7 @@
58#include <linux/dmi.h> 58#include <linux/dmi.h>
59#include <linux/backlight.h> 59#include <linux/backlight.h>
60#include <linux/platform_device.h> 60#include <linux/platform_device.h>
61#include <linux/rfkill.h>
61 62
62#define MSI_DRIVER_VERSION "0.5" 63#define MSI_DRIVER_VERSION "0.5"
63 64
@@ -66,6 +67,20 @@
66#define MSI_EC_COMMAND_WIRELESS 0x10 67#define MSI_EC_COMMAND_WIRELESS 0x10
67#define MSI_EC_COMMAND_LCD_LEVEL 0x11 68#define MSI_EC_COMMAND_LCD_LEVEL 0x11
68 69
70#define MSI_STANDARD_EC_COMMAND_ADDRESS 0x2e
71#define MSI_STANDARD_EC_BLUETOOTH_MASK (1 << 0)
72#define MSI_STANDARD_EC_WEBCAM_MASK (1 << 1)
73#define MSI_STANDARD_EC_WLAN_MASK (1 << 3)
74#define MSI_STANDARD_EC_3G_MASK (1 << 4)
75
76/* For set SCM load flag to disable BIOS fn key */
77#define MSI_STANDARD_EC_SCM_LOAD_ADDRESS 0x2d
78#define MSI_STANDARD_EC_SCM_LOAD_MASK (1 << 0)
79
80static int msi_laptop_resume(struct platform_device *device);
81
82#define MSI_STANDARD_EC_DEVICES_EXISTS_ADDRESS 0x2f
83
69static int force; 84static int force;
70module_param(force, bool, 0); 85module_param(force, bool, 0);
71MODULE_PARM_DESC(force, "Force driver load, ignore DMI data"); 86MODULE_PARM_DESC(force, "Force driver load, ignore DMI data");
@@ -74,6 +89,23 @@ static int auto_brightness;
74module_param(auto_brightness, int, 0); 89module_param(auto_brightness, int, 0);
75MODULE_PARM_DESC(auto_brightness, "Enable automatic brightness control (0: disabled; 1: enabled; 2: don't touch)"); 90MODULE_PARM_DESC(auto_brightness, "Enable automatic brightness control (0: disabled; 1: enabled; 2: don't touch)");
76 91
92static bool old_ec_model;
93static int wlan_s, bluetooth_s, threeg_s;
94static int threeg_exists;
95
96/* Some MSI 3G netbook only have one fn key to control Wlan/Bluetooth/3G,
97 * those netbook will load the SCM (windows app) to disable the original
98 * Wlan/Bluetooth control by BIOS when user press fn key, then control
99 * Wlan/Bluetooth/3G by SCM (software control by OS). Without SCM, user
100 * cann't on/off 3G module on those 3G netbook.
101 * On Linux, msi-laptop driver will do the same thing to disable the
102 * original BIOS control, then might need use HAL or other userland
103 * application to do the software control that simulate with SCM.
104 * e.g. MSI N034 netbook
105 */
106static bool load_scm_model;
107static struct rfkill *rfk_wlan, *rfk_bluetooth, *rfk_threeg;
108
77/* Hardware access */ 109/* Hardware access */
78 110
79static int set_lcd_level(int level) 111static int set_lcd_level(int level)
@@ -130,6 +162,35 @@ static int set_auto_brightness(int enable)
130 return ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, wdata, 2, NULL, 0, 1); 162 return ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, wdata, 2, NULL, 0, 1);
131} 163}
132 164
165static ssize_t set_device_state(const char *buf, size_t count, u8 mask)
166{
167 int status;
168 u8 wdata = 0, rdata;
169 int result;
170
171 if (sscanf(buf, "%i", &status) != 1 || (status < 0 || status > 1))
172 return -EINVAL;
173
174 /* read current device state */
175 result = ec_read(MSI_STANDARD_EC_COMMAND_ADDRESS, &rdata);
176 if (result < 0)
177 return -EINVAL;
178
179 if (!!(rdata & mask) != status) {
180 /* reverse device bit */
181 if (rdata & mask)
182 wdata = rdata & ~mask;
183 else
184 wdata = rdata | mask;
185
186 result = ec_write(MSI_STANDARD_EC_COMMAND_ADDRESS, wdata);
187 if (result < 0)
188 return -EINVAL;
189 }
190
191 return count;
192}
193
133static int get_wireless_state(int *wlan, int *bluetooth) 194static int get_wireless_state(int *wlan, int *bluetooth)
134{ 195{
135 u8 wdata = 0, rdata; 196 u8 wdata = 0, rdata;
@@ -148,6 +209,38 @@ static int get_wireless_state(int *wlan, int *bluetooth)
148 return 0; 209 return 0;
149} 210}
150 211
212static int get_wireless_state_ec_standard(void)
213{
214 u8 rdata;
215 int result;
216
217 result = ec_read(MSI_STANDARD_EC_COMMAND_ADDRESS, &rdata);
218 if (result < 0)
219 return -1;
220
221 wlan_s = !!(rdata & MSI_STANDARD_EC_WLAN_MASK);
222
223 bluetooth_s = !!(rdata & MSI_STANDARD_EC_BLUETOOTH_MASK);
224
225 threeg_s = !!(rdata & MSI_STANDARD_EC_3G_MASK);
226
227 return 0;
228}
229
230static int get_threeg_exists(void)
231{
232 u8 rdata;
233 int result;
234
235 result = ec_read(MSI_STANDARD_EC_DEVICES_EXISTS_ADDRESS, &rdata);
236 if (result < 0)
237 return -1;
238
239 threeg_exists = !!(rdata & MSI_STANDARD_EC_3G_MASK);
240
241 return 0;
242}
243
151/* Backlight device stuff */ 244/* Backlight device stuff */
152 245
153static int bl_get_brightness(struct backlight_device *b) 246static int bl_get_brightness(struct backlight_device *b)
@@ -176,26 +269,71 @@ static ssize_t show_wlan(struct device *dev,
176 269
177 int ret, enabled; 270 int ret, enabled;
178 271
179 ret = get_wireless_state(&enabled, NULL); 272 if (old_ec_model) {
273 ret = get_wireless_state(&enabled, NULL);
274 } else {
275 ret = get_wireless_state_ec_standard();
276 enabled = wlan_s;
277 }
180 if (ret < 0) 278 if (ret < 0)
181 return ret; 279 return ret;
182 280
183 return sprintf(buf, "%i\n", enabled); 281 return sprintf(buf, "%i\n", enabled);
184} 282}
185 283
284static ssize_t store_wlan(struct device *dev,
285 struct device_attribute *attr, const char *buf, size_t count)
286{
287 return set_device_state(buf, count, MSI_STANDARD_EC_WLAN_MASK);
288}
289
186static ssize_t show_bluetooth(struct device *dev, 290static ssize_t show_bluetooth(struct device *dev,
187 struct device_attribute *attr, char *buf) 291 struct device_attribute *attr, char *buf)
188{ 292{
189 293
190 int ret, enabled; 294 int ret, enabled;
191 295
192 ret = get_wireless_state(NULL, &enabled); 296 if (old_ec_model) {
297 ret = get_wireless_state(NULL, &enabled);
298 } else {
299 ret = get_wireless_state_ec_standard();
300 enabled = bluetooth_s;
301 }
193 if (ret < 0) 302 if (ret < 0)
194 return ret; 303 return ret;
195 304
196 return sprintf(buf, "%i\n", enabled); 305 return sprintf(buf, "%i\n", enabled);
197} 306}
198 307
308static ssize_t store_bluetooth(struct device *dev,
309 struct device_attribute *attr, const char *buf, size_t count)
310{
311 return set_device_state(buf, count, MSI_STANDARD_EC_BLUETOOTH_MASK);
312}
313
314static ssize_t show_threeg(struct device *dev,
315 struct device_attribute *attr, char *buf)
316{
317
318 int ret;
319
320 /* old msi ec not support 3G */
321 if (old_ec_model)
322 return -1;
323
324 ret = get_wireless_state_ec_standard();
325 if (ret < 0)
326 return ret;
327
328 return sprintf(buf, "%i\n", threeg_s);
329}
330
331static ssize_t store_threeg(struct device *dev,
332 struct device_attribute *attr, const char *buf, size_t count)
333{
334 return set_device_state(buf, count, MSI_STANDARD_EC_3G_MASK);
335}
336
199static ssize_t show_lcd_level(struct device *dev, 337static ssize_t show_lcd_level(struct device *dev,
200 struct device_attribute *attr, char *buf) 338 struct device_attribute *attr, char *buf)
201{ 339{
@@ -258,6 +396,7 @@ static DEVICE_ATTR(lcd_level, 0644, show_lcd_level, store_lcd_level);
258static DEVICE_ATTR(auto_brightness, 0644, show_auto_brightness, store_auto_brightness); 396static DEVICE_ATTR(auto_brightness, 0644, show_auto_brightness, store_auto_brightness);
259static DEVICE_ATTR(bluetooth, 0444, show_bluetooth, NULL); 397static DEVICE_ATTR(bluetooth, 0444, show_bluetooth, NULL);
260static DEVICE_ATTR(wlan, 0444, show_wlan, NULL); 398static DEVICE_ATTR(wlan, 0444, show_wlan, NULL);
399static DEVICE_ATTR(threeg, 0444, show_threeg, NULL);
261 400
262static struct attribute *msipf_attributes[] = { 401static struct attribute *msipf_attributes[] = {
263 &dev_attr_lcd_level.attr, 402 &dev_attr_lcd_level.attr,
@@ -275,7 +414,8 @@ static struct platform_driver msipf_driver = {
275 .driver = { 414 .driver = {
276 .name = "msi-laptop-pf", 415 .name = "msi-laptop-pf",
277 .owner = THIS_MODULE, 416 .owner = THIS_MODULE,
278 } 417 },
418 .resume = msi_laptop_resume,
279}; 419};
280 420
281static struct platform_device *msipf_device; 421static struct platform_device *msipf_device;
@@ -332,6 +472,192 @@ static struct dmi_system_id __initdata msi_dmi_table[] = {
332 { } 472 { }
333}; 473};
334 474
475static struct dmi_system_id __initdata msi_load_scm_models_dmi_table[] = {
476 {
477 .ident = "MSI N034",
478 .matches = {
479 DMI_MATCH(DMI_SYS_VENDOR,
480 "MICRO-STAR INTERNATIONAL CO., LTD"),
481 DMI_MATCH(DMI_PRODUCT_NAME, "MS-N034"),
482 DMI_MATCH(DMI_CHASSIS_VENDOR,
483 "MICRO-STAR INTERNATIONAL CO., LTD")
484 },
485 .callback = dmi_check_cb
486 },
487 { }
488};
489
490static int rfkill_bluetooth_set(void *data, bool blocked)
491{
492 /* Do something with blocked...*/
493 /*
494 * blocked == false is on
495 * blocked == true is off
496 */
497 if (blocked)
498 set_device_state("0", 0, MSI_STANDARD_EC_BLUETOOTH_MASK);
499 else
500 set_device_state("1", 0, MSI_STANDARD_EC_BLUETOOTH_MASK);
501
502 return 0;
503}
504
505static int rfkill_wlan_set(void *data, bool blocked)
506{
507 if (blocked)
508 set_device_state("0", 0, MSI_STANDARD_EC_WLAN_MASK);
509 else
510 set_device_state("1", 0, MSI_STANDARD_EC_WLAN_MASK);
511
512 return 0;
513}
514
515static int rfkill_threeg_set(void *data, bool blocked)
516{
517 if (blocked)
518 set_device_state("0", 0, MSI_STANDARD_EC_3G_MASK);
519 else
520 set_device_state("1", 0, MSI_STANDARD_EC_3G_MASK);
521
522 return 0;
523}
524
525static struct rfkill_ops rfkill_bluetooth_ops = {
526 .set_block = rfkill_bluetooth_set
527};
528
529static struct rfkill_ops rfkill_wlan_ops = {
530 .set_block = rfkill_wlan_set
531};
532
533static struct rfkill_ops rfkill_threeg_ops = {
534 .set_block = rfkill_threeg_set
535};
536
537static void rfkill_cleanup(void)
538{
539 if (rfk_bluetooth) {
540 rfkill_unregister(rfk_bluetooth);
541 rfkill_destroy(rfk_bluetooth);
542 }
543
544 if (rfk_threeg) {
545 rfkill_unregister(rfk_threeg);
546 rfkill_destroy(rfk_threeg);
547 }
548
549 if (rfk_wlan) {
550 rfkill_unregister(rfk_wlan);
551 rfkill_destroy(rfk_wlan);
552 }
553}
554
555static int rfkill_init(struct platform_device *sdev)
556{
557 /* add rfkill */
558 int retval;
559
560 rfk_bluetooth = rfkill_alloc("msi-bluetooth", &sdev->dev,
561 RFKILL_TYPE_BLUETOOTH,
562 &rfkill_bluetooth_ops, NULL);
563 if (!rfk_bluetooth) {
564 retval = -ENOMEM;
565 goto err_bluetooth;
566 }
567 retval = rfkill_register(rfk_bluetooth);
568 if (retval)
569 goto err_bluetooth;
570
571 rfk_wlan = rfkill_alloc("msi-wlan", &sdev->dev, RFKILL_TYPE_WLAN,
572 &rfkill_wlan_ops, NULL);
573 if (!rfk_wlan) {
574 retval = -ENOMEM;
575 goto err_wlan;
576 }
577 retval = rfkill_register(rfk_wlan);
578 if (retval)
579 goto err_wlan;
580
581 if (threeg_exists) {
582 rfk_threeg = rfkill_alloc("msi-threeg", &sdev->dev,
583 RFKILL_TYPE_WWAN, &rfkill_threeg_ops, NULL);
584 if (!rfk_threeg) {
585 retval = -ENOMEM;
586 goto err_threeg;
587 }
588 retval = rfkill_register(rfk_threeg);
589 if (retval)
590 goto err_threeg;
591 }
592
593 return 0;
594
595err_threeg:
596 rfkill_destroy(rfk_threeg);
597 if (rfk_wlan)
598 rfkill_unregister(rfk_wlan);
599err_wlan:
600 rfkill_destroy(rfk_wlan);
601 if (rfk_bluetooth)
602 rfkill_unregister(rfk_bluetooth);
603err_bluetooth:
604 rfkill_destroy(rfk_bluetooth);
605
606 return retval;
607}
608
609static int msi_laptop_resume(struct platform_device *device)
610{
611 u8 data;
612 int result;
613
614 if (!load_scm_model)
615 return 0;
616
617 /* set load SCM to disable hardware control by fn key */
618 result = ec_read(MSI_STANDARD_EC_SCM_LOAD_ADDRESS, &data);
619 if (result < 0)
620 return result;
621
622 result = ec_write(MSI_STANDARD_EC_SCM_LOAD_ADDRESS,
623 data | MSI_STANDARD_EC_SCM_LOAD_MASK);
624 if (result < 0)
625 return result;
626
627 return 0;
628}
629
630static int load_scm_model_init(struct platform_device *sdev)
631{
632 u8 data;
633 int result;
634
635 /* allow userland write sysfs file */
636 dev_attr_bluetooth.store = store_bluetooth;
637 dev_attr_wlan.store = store_wlan;
638 dev_attr_threeg.store = store_threeg;
639 dev_attr_bluetooth.attr.mode |= S_IWUSR;
640 dev_attr_wlan.attr.mode |= S_IWUSR;
641 dev_attr_threeg.attr.mode |= S_IWUSR;
642
643 /* disable hardware control by fn key */
644 result = ec_read(MSI_STANDARD_EC_SCM_LOAD_ADDRESS, &data);
645 if (result < 0)
646 return result;
647
648 result = ec_write(MSI_STANDARD_EC_SCM_LOAD_ADDRESS,
649 data | MSI_STANDARD_EC_SCM_LOAD_MASK);
650 if (result < 0)
651 return result;
652
653 /* initial rfkill */
654 result = rfkill_init(sdev);
655 if (result < 0)
656 return result;
657
658 return 0;
659}
660
335static int __init msi_init(void) 661static int __init msi_init(void)
336{ 662{
337 int ret; 663 int ret;
@@ -339,8 +665,14 @@ static int __init msi_init(void)
339 if (acpi_disabled) 665 if (acpi_disabled)
340 return -ENODEV; 666 return -ENODEV;
341 667
342 if (!force && !dmi_check_system(msi_dmi_table)) 668 if (force || dmi_check_system(msi_dmi_table))
343 return -ENODEV; 669 old_ec_model = 1;
670
671 if (!old_ec_model)
672 get_threeg_exists();
673
674 if (!old_ec_model && dmi_check_system(msi_load_scm_models_dmi_table))
675 load_scm_model = 1;
344 676
345 if (auto_brightness < 0 || auto_brightness > 2) 677 if (auto_brightness < 0 || auto_brightness > 2)
346 return -EINVAL; 678 return -EINVAL;
@@ -351,11 +683,14 @@ static int __init msi_init(void)
351 printk(KERN_INFO "MSI: Brightness ignored, must be controlled " 683 printk(KERN_INFO "MSI: Brightness ignored, must be controlled "
352 "by ACPI video driver\n"); 684 "by ACPI video driver\n");
353 } else { 685 } else {
686 struct backlight_properties props;
687 memset(&props, 0, sizeof(struct backlight_properties));
688 props.max_brightness = MSI_LCD_LEVEL_MAX - 1;
354 msibl_device = backlight_device_register("msi-laptop-bl", NULL, 689 msibl_device = backlight_device_register("msi-laptop-bl", NULL,
355 NULL, &msibl_ops); 690 NULL, &msibl_ops,
691 &props);
356 if (IS_ERR(msibl_device)) 692 if (IS_ERR(msibl_device))
357 return PTR_ERR(msibl_device); 693 return PTR_ERR(msibl_device);
358 msibl_device->props.max_brightness = MSI_LCD_LEVEL_MAX-1;
359 } 694 }
360 695
361 ret = platform_driver_register(&msipf_driver); 696 ret = platform_driver_register(&msipf_driver);
@@ -374,10 +709,23 @@ static int __init msi_init(void)
374 if (ret) 709 if (ret)
375 goto fail_platform_device1; 710 goto fail_platform_device1;
376 711
712 if (load_scm_model && (load_scm_model_init(msipf_device) < 0)) {
713 ret = -EINVAL;
714 goto fail_platform_device1;
715 }
716
377 ret = sysfs_create_group(&msipf_device->dev.kobj, &msipf_attribute_group); 717 ret = sysfs_create_group(&msipf_device->dev.kobj, &msipf_attribute_group);
378 if (ret) 718 if (ret)
379 goto fail_platform_device2; 719 goto fail_platform_device2;
380 720
721 if (!old_ec_model) {
722 if (threeg_exists)
723 ret = device_create_file(&msipf_device->dev,
724 &dev_attr_threeg);
725 if (ret)
726 goto fail_platform_device2;
727 }
728
381 /* Disable automatic brightness control by default because 729 /* Disable automatic brightness control by default because
382 * this module was probably loaded to do brightness control in 730 * this module was probably loaded to do brightness control in
383 * software. */ 731 * software. */
@@ -412,10 +760,14 @@ static void __exit msi_cleanup(void)
412{ 760{
413 761
414 sysfs_remove_group(&msipf_device->dev.kobj, &msipf_attribute_group); 762 sysfs_remove_group(&msipf_device->dev.kobj, &msipf_attribute_group);
763 if (!old_ec_model && threeg_exists)
764 device_remove_file(&msipf_device->dev, &dev_attr_threeg);
415 platform_device_unregister(msipf_device); 765 platform_device_unregister(msipf_device);
416 platform_driver_unregister(&msipf_driver); 766 platform_driver_unregister(&msipf_driver);
417 backlight_device_unregister(msibl_device); 767 backlight_device_unregister(msibl_device);
418 768
769 rfkill_cleanup();
770
419 /* Enable automatic brightness control again */ 771 /* Enable automatic brightness control again */
420 if (auto_brightness != 2) 772 if (auto_brightness != 2)
421 set_auto_brightness(1); 773 set_auto_brightness(1);
@@ -435,3 +787,4 @@ MODULE_ALIAS("dmi:*:svnMICRO-STARINT'LCO.,LTD:pnMS-1013:pvr0131*:cvnMICRO-STARIN
435MODULE_ALIAS("dmi:*:svnMicro-StarInternational:pnMS-1058:pvr0581:rvnMSI:rnMS-1058:*:ct10:*"); 787MODULE_ALIAS("dmi:*:svnMicro-StarInternational:pnMS-1058:pvr0581:rvnMSI:rnMS-1058:*:ct10:*");
436MODULE_ALIAS("dmi:*:svnMicro-StarInternational:pnMS-1412:*:rvnMSI:rnMS-1412:*:cvnMICRO-STARINT'LCO.,LTD:ct10:*"); 788MODULE_ALIAS("dmi:*:svnMicro-StarInternational:pnMS-1412:*:rvnMSI:rnMS-1412:*:cvnMICRO-STARINT'LCO.,LTD:ct10:*");
437MODULE_ALIAS("dmi:*:svnNOTEBOOK:pnSAM2000:pvr0131*:cvnMICRO-STARINT'LCO.,LTD:ct10:*"); 789MODULE_ALIAS("dmi:*:svnNOTEBOOK:pnSAM2000:pvr0131*:cvnMICRO-STARINT'LCO.,LTD:ct10:*");
790MODULE_ALIAS("dmi:*:svnMICRO-STARINTERNATIONAL*:pnMS-N034:*");
diff --git a/drivers/platform/x86/msi-wmi.c b/drivers/platform/x86/msi-wmi.c
index f5f70d4c691..d1736009636 100644
--- a/drivers/platform/x86/msi-wmi.c
+++ b/drivers/platform/x86/msi-wmi.c
@@ -26,6 +26,7 @@
26#include <linux/input/sparse-keymap.h> 26#include <linux/input/sparse-keymap.h>
27#include <linux/acpi.h> 27#include <linux/acpi.h>
28#include <linux/backlight.h> 28#include <linux/backlight.h>
29#include <linux/slab.h>
29 30
30MODULE_AUTHOR("Thomas Renninger <trenn@suse.de>"); 31MODULE_AUTHOR("Thomas Renninger <trenn@suse.de>");
31MODULE_DESCRIPTION("MSI laptop WMI hotkeys driver"); 32MODULE_DESCRIPTION("MSI laptop WMI hotkeys driver");
@@ -138,7 +139,7 @@ static int bl_set_status(struct backlight_device *bd)
138 return msi_wmi_set_block(0, backlight_map[bright]); 139 return msi_wmi_set_block(0, backlight_map[bright]);
139} 140}
140 141
141static struct backlight_ops msi_backlight_ops = { 142static const struct backlight_ops msi_backlight_ops = {
142 .get_brightness = bl_get, 143 .get_brightness = bl_get,
143 .update_status = bl_set_status, 144 .update_status = bl_set_status,
144}; 145};
@@ -249,12 +250,17 @@ static int __init msi_wmi_init(void)
249 goto err_uninstall_notifier; 250 goto err_uninstall_notifier;
250 251
251 if (!acpi_video_backlight_support()) { 252 if (!acpi_video_backlight_support()) {
252 backlight = backlight_device_register(DRV_NAME, 253 struct backlight_properties props;
253 NULL, NULL, &msi_backlight_ops); 254 memset(&props, 0, sizeof(struct backlight_properties));
254 if (IS_ERR(backlight)) 255 props.max_brightness = ARRAY_SIZE(backlight_map) - 1;
256 backlight = backlight_device_register(DRV_NAME, NULL, NULL,
257 &msi_backlight_ops,
258 &props);
259 if (IS_ERR(backlight)) {
260 err = PTR_ERR(backlight);
255 goto err_free_input; 261 goto err_free_input;
262 }
256 263
257 backlight->props.max_brightness = ARRAY_SIZE(backlight_map) - 1;
258 err = bl_get(NULL); 264 err = bl_get(NULL);
259 if (err < 0) 265 if (err < 0)
260 goto err_free_backlight; 266 goto err_free_backlight;
diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c
index fe7cf0188ac..2fb9a32926f 100644
--- a/drivers/platform/x86/panasonic-laptop.c
+++ b/drivers/platform/x86/panasonic-laptop.c
@@ -124,6 +124,7 @@
124#include <linux/ctype.h> 124#include <linux/ctype.h>
125#include <linux/seq_file.h> 125#include <linux/seq_file.h>
126#include <linux/uaccess.h> 126#include <linux/uaccess.h>
127#include <linux/slab.h>
127#include <acpi/acpi_bus.h> 128#include <acpi/acpi_bus.h>
128#include <acpi/acpi_drivers.h> 129#include <acpi/acpi_drivers.h>
129#include <linux/input.h> 130#include <linux/input.h>
@@ -200,7 +201,7 @@ static struct acpi_driver acpi_pcc_driver = {
200}; 201};
201 202
202#define KEYMAP_SIZE 11 203#define KEYMAP_SIZE 11
203static const int initial_keymap[KEYMAP_SIZE] = { 204static const unsigned int initial_keymap[KEYMAP_SIZE] = {
204 /* 0 */ KEY_RESERVED, 205 /* 0 */ KEY_RESERVED,
205 /* 1 */ KEY_BRIGHTNESSDOWN, 206 /* 1 */ KEY_BRIGHTNESSDOWN,
206 /* 2 */ KEY_BRIGHTNESSUP, 207 /* 2 */ KEY_BRIGHTNESSUP,
@@ -222,7 +223,7 @@ struct pcc_acpi {
222 struct acpi_device *device; 223 struct acpi_device *device;
223 struct input_dev *input_dev; 224 struct input_dev *input_dev;
224 struct backlight_device *backlight; 225 struct backlight_device *backlight;
225 int keymap[KEYMAP_SIZE]; 226 unsigned int keymap[KEYMAP_SIZE];
226}; 227};
227 228
228struct pcc_keyinput { 229struct pcc_keyinput {
@@ -352,7 +353,7 @@ static int bl_set_status(struct backlight_device *bd)
352 return acpi_pcc_write_sset(pcc, SINF_DC_CUR_BRIGHT, bright); 353 return acpi_pcc_write_sset(pcc, SINF_DC_CUR_BRIGHT, bright);
353} 354}
354 355
355static struct backlight_ops pcc_backlight_ops = { 356static const struct backlight_ops pcc_backlight_ops = {
356 .get_brightness = bl_get, 357 .get_brightness = bl_get,
357 .update_status = bl_set_status, 358 .update_status = bl_set_status,
358}; 359};
@@ -445,7 +446,8 @@ static struct attribute_group pcc_attr_group = {
445 446
446/* hotkey input device driver */ 447/* hotkey input device driver */
447 448
448static int pcc_getkeycode(struct input_dev *dev, int scancode, int *keycode) 449static int pcc_getkeycode(struct input_dev *dev,
450 unsigned int scancode, unsigned int *keycode)
449{ 451{
450 struct pcc_acpi *pcc = input_get_drvdata(dev); 452 struct pcc_acpi *pcc = input_get_drvdata(dev);
451 453
@@ -457,7 +459,7 @@ static int pcc_getkeycode(struct input_dev *dev, int scancode, int *keycode)
457 return 0; 459 return 0;
458} 460}
459 461
460static int keymap_get_by_keycode(struct pcc_acpi *pcc, int keycode) 462static int keymap_get_by_keycode(struct pcc_acpi *pcc, unsigned int keycode)
461{ 463{
462 int i; 464 int i;
463 465
@@ -469,7 +471,8 @@ static int keymap_get_by_keycode(struct pcc_acpi *pcc, int keycode)
469 return 0; 471 return 0;
470} 472}
471 473
472static int pcc_setkeycode(struct input_dev *dev, int scancode, int keycode) 474static int pcc_setkeycode(struct input_dev *dev,
475 unsigned int scancode, unsigned int keycode)
473{ 476{
474 struct pcc_acpi *pcc = input_get_drvdata(dev); 477 struct pcc_acpi *pcc = input_get_drvdata(dev);
475 int oldkeycode; 478 int oldkeycode;
@@ -477,9 +480,6 @@ static int pcc_setkeycode(struct input_dev *dev, int scancode, int keycode)
477 if (scancode >= ARRAY_SIZE(pcc->keymap)) 480 if (scancode >= ARRAY_SIZE(pcc->keymap))
478 return -EINVAL; 481 return -EINVAL;
479 482
480 if (keycode < 0 || keycode > KEY_MAX)
481 return -EINVAL;
482
483 oldkeycode = pcc->keymap[scancode]; 483 oldkeycode = pcc->keymap[scancode];
484 pcc->keymap[scancode] = keycode; 484 pcc->keymap[scancode] = keycode;
485 485
@@ -601,6 +601,7 @@ static int acpi_pcc_hotkey_resume(struct acpi_device *device)
601 601
602static int acpi_pcc_hotkey_add(struct acpi_device *device) 602static int acpi_pcc_hotkey_add(struct acpi_device *device)
603{ 603{
604 struct backlight_properties props;
604 struct pcc_acpi *pcc; 605 struct pcc_acpi *pcc;
605 int num_sifr, result; 606 int num_sifr, result;
606 607
@@ -638,24 +639,25 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
638 if (result) { 639 if (result) {
639 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 640 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
640 "Error installing keyinput handler\n")); 641 "Error installing keyinput handler\n"));
641 goto out_sinf; 642 goto out_hotkey;
642 } 643 }
643 644
644 /* initialize backlight */
645 pcc->backlight = backlight_device_register("panasonic", NULL, pcc,
646 &pcc_backlight_ops);
647 if (IS_ERR(pcc->backlight))
648 goto out_input;
649
650 if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) { 645 if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) {
651 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 646 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
652 "Couldn't retrieve BIOS data\n")); 647 "Couldn't retrieve BIOS data\n"));
653 goto out_backlight; 648 goto out_input;
649 }
650 /* initialize backlight */
651 memset(&props, 0, sizeof(struct backlight_properties));
652 props.max_brightness = pcc->sinf[SINF_AC_MAX_BRIGHT];
653 pcc->backlight = backlight_device_register("panasonic", NULL, pcc,
654 &pcc_backlight_ops, &props);
655 if (IS_ERR(pcc->backlight)) {
656 result = PTR_ERR(pcc->backlight);
657 goto out_sinf;
654 } 658 }
655 659
656 /* read the initial brightness setting from the hardware */ 660 /* read the initial brightness setting from the hardware */
657 pcc->backlight->props.max_brightness =
658 pcc->sinf[SINF_AC_MAX_BRIGHT];
659 pcc->backlight->props.brightness = pcc->sinf[SINF_AC_CUR_BRIGHT]; 661 pcc->backlight->props.brightness = pcc->sinf[SINF_AC_CUR_BRIGHT];
660 662
661 /* read the initial sticky key mode from the hardware */ 663 /* read the initial sticky key mode from the hardware */
@@ -670,12 +672,12 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
670 672
671out_backlight: 673out_backlight:
672 backlight_device_unregister(pcc->backlight); 674 backlight_device_unregister(pcc->backlight);
675out_sinf:
676 kfree(pcc->sinf);
673out_input: 677out_input:
674 input_unregister_device(pcc->input_dev); 678 input_unregister_device(pcc->input_dev);
675 /* no need to input_free_device() since core input API refcount and 679 /* no need to input_free_device() since core input API refcount and
676 * free()s the device */ 680 * free()s the device */
677out_sinf:
678 kfree(pcc->sinf);
679out_hotkey: 681out_hotkey:
680 kfree(pcc); 682 kfree(pcc);
681 683
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index 3f71a605a49..1387c5f9c24 100644
--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -58,6 +58,7 @@
58#include <linux/kfifo.h> 58#include <linux/kfifo.h>
59#include <linux/workqueue.h> 59#include <linux/workqueue.h>
60#include <linux/acpi.h> 60#include <linux/acpi.h>
61#include <linux/slab.h>
61#include <acpi/acpi_drivers.h> 62#include <acpi/acpi_drivers.h>
62#include <acpi/acpi_bus.h> 63#include <acpi/acpi_bus.h>
63#include <asm/uaccess.h> 64#include <asm/uaccess.h>
@@ -145,7 +146,7 @@ struct sony_laptop_input_s {
145 struct input_dev *key_dev; 146 struct input_dev *key_dev;
146 struct kfifo fifo; 147 struct kfifo fifo;
147 spinlock_t fifo_lock; 148 spinlock_t fifo_lock;
148 struct workqueue_struct *wq; 149 struct timer_list release_key_timer;
149}; 150};
150 151
151static struct sony_laptop_input_s sony_laptop_input = { 152static struct sony_laptop_input_s sony_laptop_input = {
@@ -299,20 +300,26 @@ static int sony_laptop_input_keycode_map[] = {
299}; 300};
300 301
301/* release buttons after a short delay if pressed */ 302/* release buttons after a short delay if pressed */
302static void do_sony_laptop_release_key(struct work_struct *work) 303static void do_sony_laptop_release_key(unsigned long unused)
303{ 304{
304 struct sony_laptop_keypress kp; 305 struct sony_laptop_keypress kp;
306 unsigned long flags;
307
308 spin_lock_irqsave(&sony_laptop_input.fifo_lock, flags);
305 309
306 while (kfifo_out_locked(&sony_laptop_input.fifo, (unsigned char *)&kp, 310 if (kfifo_out(&sony_laptop_input.fifo,
307 sizeof(kp), &sony_laptop_input.fifo_lock) 311 (unsigned char *)&kp, sizeof(kp)) == sizeof(kp)) {
308 == sizeof(kp)) {
309 msleep(10);
310 input_report_key(kp.dev, kp.key, 0); 312 input_report_key(kp.dev, kp.key, 0);
311 input_sync(kp.dev); 313 input_sync(kp.dev);
312 } 314 }
315
316 /* If there is something in the fifo schedule next release. */
317 if (kfifo_len(&sony_laptop_input.fifo) != 0)
318 mod_timer(&sony_laptop_input.release_key_timer,
319 jiffies + msecs_to_jiffies(10));
320
321 spin_unlock_irqrestore(&sony_laptop_input.fifo_lock, flags);
313} 322}
314static DECLARE_WORK(sony_laptop_release_key_work,
315 do_sony_laptop_release_key);
316 323
317/* forward event to the input subsystem */ 324/* forward event to the input subsystem */
318static void sony_laptop_report_input_event(u8 event) 325static void sony_laptop_report_input_event(u8 event)
@@ -366,13 +373,13 @@ static void sony_laptop_report_input_event(u8 event)
366 /* we emit the scancode so we can always remap the key */ 373 /* we emit the scancode so we can always remap the key */
367 input_event(kp.dev, EV_MSC, MSC_SCAN, event); 374 input_event(kp.dev, EV_MSC, MSC_SCAN, event);
368 input_sync(kp.dev); 375 input_sync(kp.dev);
369 kfifo_in_locked(&sony_laptop_input.fifo,
370 (unsigned char *)&kp, sizeof(kp),
371 &sony_laptop_input.fifo_lock);
372 376
373 if (!work_pending(&sony_laptop_release_key_work)) 377 /* schedule key release */
374 queue_work(sony_laptop_input.wq, 378 kfifo_in_locked(&sony_laptop_input.fifo,
375 &sony_laptop_release_key_work); 379 (unsigned char *)&kp, sizeof(kp),
380 &sony_laptop_input.fifo_lock);
381 mod_timer(&sony_laptop_input.release_key_timer,
382 jiffies + msecs_to_jiffies(10));
376 } else 383 } else
377 dprintk("unknown input event %.2x\n", event); 384 dprintk("unknown input event %.2x\n", event);
378} 385}
@@ -390,27 +397,21 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device)
390 397
391 /* kfifo */ 398 /* kfifo */
392 spin_lock_init(&sony_laptop_input.fifo_lock); 399 spin_lock_init(&sony_laptop_input.fifo_lock);
393 error = 400 error = kfifo_alloc(&sony_laptop_input.fifo,
394 kfifo_alloc(&sony_laptop_input.fifo, SONY_LAPTOP_BUF_SIZE, GFP_KERNEL); 401 SONY_LAPTOP_BUF_SIZE, GFP_KERNEL);
395 if (error) { 402 if (error) {
396 printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n"); 403 printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n");
397 goto err_dec_users; 404 goto err_dec_users;
398 } 405 }
399 406
400 /* init workqueue */ 407 setup_timer(&sony_laptop_input.release_key_timer,
401 sony_laptop_input.wq = create_singlethread_workqueue("sony-laptop"); 408 do_sony_laptop_release_key, 0);
402 if (!sony_laptop_input.wq) {
403 printk(KERN_ERR DRV_PFX
404 "Unable to create workqueue.\n");
405 error = -ENXIO;
406 goto err_free_kfifo;
407 }
408 409
409 /* input keys */ 410 /* input keys */
410 key_dev = input_allocate_device(); 411 key_dev = input_allocate_device();
411 if (!key_dev) { 412 if (!key_dev) {
412 error = -ENOMEM; 413 error = -ENOMEM;
413 goto err_destroy_wq; 414 goto err_free_kfifo;
414 } 415 }
415 416
416 key_dev->name = "Sony Vaio Keys"; 417 key_dev->name = "Sony Vaio Keys";
@@ -419,18 +420,15 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device)
419 key_dev->dev.parent = &acpi_device->dev; 420 key_dev->dev.parent = &acpi_device->dev;
420 421
421 /* Initialize the Input Drivers: special keys */ 422 /* Initialize the Input Drivers: special keys */
422 set_bit(EV_KEY, key_dev->evbit); 423 input_set_capability(key_dev, EV_MSC, MSC_SCAN);
423 set_bit(EV_MSC, key_dev->evbit); 424
424 set_bit(MSC_SCAN, key_dev->mscbit); 425 __set_bit(EV_KEY, key_dev->evbit);
425 key_dev->keycodesize = sizeof(sony_laptop_input_keycode_map[0]); 426 key_dev->keycodesize = sizeof(sony_laptop_input_keycode_map[0]);
426 key_dev->keycodemax = ARRAY_SIZE(sony_laptop_input_keycode_map); 427 key_dev->keycodemax = ARRAY_SIZE(sony_laptop_input_keycode_map);
427 key_dev->keycode = &sony_laptop_input_keycode_map; 428 key_dev->keycode = &sony_laptop_input_keycode_map;
428 for (i = 0; i < ARRAY_SIZE(sony_laptop_input_keycode_map); i++) { 429 for (i = 0; i < ARRAY_SIZE(sony_laptop_input_keycode_map); i++)
429 if (sony_laptop_input_keycode_map[i] != KEY_RESERVED) { 430 __set_bit(sony_laptop_input_keycode_map[i], key_dev->keybit);
430 set_bit(sony_laptop_input_keycode_map[i], 431 __clear_bit(KEY_RESERVED, key_dev->keybit);
431 key_dev->keybit);
432 }
433 }
434 432
435 error = input_register_device(key_dev); 433 error = input_register_device(key_dev);
436 if (error) 434 if (error)
@@ -450,9 +448,8 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device)
450 jog_dev->id.vendor = PCI_VENDOR_ID_SONY; 448 jog_dev->id.vendor = PCI_VENDOR_ID_SONY;
451 key_dev->dev.parent = &acpi_device->dev; 449 key_dev->dev.parent = &acpi_device->dev;
452 450
453 jog_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); 451 input_set_capability(jog_dev, EV_KEY, BTN_MIDDLE);
454 jog_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_MIDDLE); 452 input_set_capability(jog_dev, EV_REL, REL_WHEEL);
455 jog_dev->relbit[0] = BIT_MASK(REL_WHEEL);
456 453
457 error = input_register_device(jog_dev); 454 error = input_register_device(jog_dev);
458 if (error) 455 if (error)
@@ -473,9 +470,6 @@ err_unregister_keydev:
473err_free_keydev: 470err_free_keydev:
474 input_free_device(key_dev); 471 input_free_device(key_dev);
475 472
476err_destroy_wq:
477 destroy_workqueue(sony_laptop_input.wq);
478
479err_free_kfifo: 473err_free_kfifo:
480 kfifo_free(&sony_laptop_input.fifo); 474 kfifo_free(&sony_laptop_input.fifo);
481 475
@@ -486,12 +480,23 @@ err_dec_users:
486 480
487static void sony_laptop_remove_input(void) 481static void sony_laptop_remove_input(void)
488{ 482{
489 /* cleanup only after the last user has gone */ 483 struct sony_laptop_keypress kp = { NULL };
484
485 /* Cleanup only after the last user has gone */
490 if (!atomic_dec_and_test(&sony_laptop_input.users)) 486 if (!atomic_dec_and_test(&sony_laptop_input.users))
491 return; 487 return;
492 488
493 /* flush workqueue first */ 489 del_timer_sync(&sony_laptop_input.release_key_timer);
494 flush_workqueue(sony_laptop_input.wq); 490
491 /*
492 * Generate key-up events for remaining keys. Note that we don't
493 * need locking since nobody is adding new events to the kfifo.
494 */
495 while (kfifo_out(&sony_laptop_input.fifo,
496 (unsigned char *)&kp, sizeof(kp)) == sizeof(kp)) {
497 input_report_key(kp.dev, kp.key, 0);
498 input_sync(kp.dev);
499 }
495 500
496 /* destroy input devs */ 501 /* destroy input devs */
497 input_unregister_device(sony_laptop_input.key_dev); 502 input_unregister_device(sony_laptop_input.key_dev);
@@ -502,7 +507,6 @@ static void sony_laptop_remove_input(void)
502 sony_laptop_input.jog_dev = NULL; 507 sony_laptop_input.jog_dev = NULL;
503 } 508 }
504 509
505 destroy_workqueue(sony_laptop_input.wq);
506 kfifo_free(&sony_laptop_input.fifo); 510 kfifo_free(&sony_laptop_input.fifo);
507} 511}
508 512
@@ -1288,9 +1292,13 @@ static int sony_nc_add(struct acpi_device *device)
1288 "controlled by ACPI video driver\n"); 1292 "controlled by ACPI video driver\n");
1289 } else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT", 1293 } else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT",
1290 &handle))) { 1294 &handle))) {
1295 struct backlight_properties props;
1296 memset(&props, 0, sizeof(struct backlight_properties));
1297 props.max_brightness = SONY_MAX_BRIGHTNESS - 1;
1291 sony_backlight_device = backlight_device_register("sony", NULL, 1298 sony_backlight_device = backlight_device_register("sony", NULL,
1292 NULL, 1299 NULL,
1293 &sony_backlight_ops); 1300 &sony_backlight_ops,
1301 &props);
1294 1302
1295 if (IS_ERR(sony_backlight_device)) { 1303 if (IS_ERR(sony_backlight_device)) {
1296 printk(KERN_WARNING DRV_PFX "unable to register backlight device\n"); 1304 printk(KERN_WARNING DRV_PFX "unable to register backlight device\n");
@@ -1299,8 +1307,6 @@ static int sony_nc_add(struct acpi_device *device)
1299 sony_backlight_device->props.brightness = 1307 sony_backlight_device->props.brightness =
1300 sony_backlight_get_brightness 1308 sony_backlight_get_brightness
1301 (sony_backlight_device); 1309 (sony_backlight_device);
1302 sony_backlight_device->props.max_brightness =
1303 SONY_MAX_BRIGHTNESS - 1;
1304 } 1310 }
1305 1311
1306 } 1312 }
diff --git a/drivers/platform/x86/tc1100-wmi.c b/drivers/platform/x86/tc1100-wmi.c
index dd33b51c348..1fe0f1feff7 100644
--- a/drivers/platform/x86/tc1100-wmi.c
+++ b/drivers/platform/x86/tc1100-wmi.c
@@ -27,6 +27,7 @@
27 27
28#include <linux/kernel.h> 28#include <linux/kernel.h>
29#include <linux/module.h> 29#include <linux/module.h>
30#include <linux/slab.h>
30#include <linux/init.h> 31#include <linux/init.h>
31#include <linux/types.h> 32#include <linux/types.h>
32#include <acpi/acpi.h> 33#include <acpi/acpi.h>
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index eb603f1d55c..63290b33c87 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -58,6 +58,7 @@
58#include <linux/kthread.h> 58#include <linux/kthread.h>
59#include <linux/freezer.h> 59#include <linux/freezer.h>
60#include <linux/delay.h> 60#include <linux/delay.h>
61#include <linux/slab.h>
61 62
62#include <linux/nvram.h> 63#include <linux/nvram.h>
63#include <linux/proc_fs.h> 64#include <linux/proc_fs.h>
@@ -286,6 +287,7 @@ struct ibm_init_struct {
286 char param[32]; 287 char param[32];
287 288
288 int (*init) (struct ibm_init_struct *); 289 int (*init) (struct ibm_init_struct *);
290 mode_t base_procfs_mode;
289 struct ibm_struct *data; 291 struct ibm_struct *data;
290}; 292};
291 293
@@ -1667,7 +1669,7 @@ static void tpacpi_remove_driver_attributes(struct device_driver *drv)
1667 * Table of recommended minimum BIOS versions 1669 * Table of recommended minimum BIOS versions
1668 * 1670 *
1669 * Reasons for listing: 1671 * Reasons for listing:
1670 * 1. Stable BIOS, listed because the unknown ammount of 1672 * 1. Stable BIOS, listed because the unknown amount of
1671 * bugs and bad ACPI behaviour on older versions 1673 * bugs and bad ACPI behaviour on older versions
1672 * 1674 *
1673 * 2. BIOS or EC fw with known bugs that trigger on Linux 1675 * 2. BIOS or EC fw with known bugs that trigger on Linux
@@ -2082,6 +2084,7 @@ static struct attribute_set *hotkey_dev_attributes;
2082 2084
2083static void tpacpi_driver_event(const unsigned int hkey_event); 2085static void tpacpi_driver_event(const unsigned int hkey_event);
2084static void hotkey_driver_event(const unsigned int scancode); 2086static void hotkey_driver_event(const unsigned int scancode);
2087static void hotkey_poll_setup(const bool may_warn);
2085 2088
2086/* HKEY.MHKG() return bits */ 2089/* HKEY.MHKG() return bits */
2087#define TP_HOTKEY_TABLET_MASK (1 << 3) 2090#define TP_HOTKEY_TABLET_MASK (1 << 3)
@@ -2264,6 +2267,8 @@ static int tpacpi_hotkey_driver_mask_set(const u32 mask)
2264 2267
2265 rc = hotkey_mask_set((hotkey_acpi_mask | hotkey_driver_mask) & 2268 rc = hotkey_mask_set((hotkey_acpi_mask | hotkey_driver_mask) &
2266 ~hotkey_source_mask); 2269 ~hotkey_source_mask);
2270 hotkey_poll_setup(true);
2271
2267 mutex_unlock(&hotkey_mutex); 2272 mutex_unlock(&hotkey_mutex);
2268 2273
2269 return rc; 2274 return rc;
@@ -2548,7 +2553,7 @@ static void hotkey_poll_stop_sync(void)
2548} 2553}
2549 2554
2550/* call with hotkey_mutex held */ 2555/* call with hotkey_mutex held */
2551static void hotkey_poll_setup(bool may_warn) 2556static void hotkey_poll_setup(const bool may_warn)
2552{ 2557{
2553 const u32 poll_driver_mask = hotkey_driver_mask & hotkey_source_mask; 2558 const u32 poll_driver_mask = hotkey_driver_mask & hotkey_source_mask;
2554 const u32 poll_user_mask = hotkey_user_mask & hotkey_source_mask; 2559 const u32 poll_user_mask = hotkey_user_mask & hotkey_source_mask;
@@ -2579,7 +2584,7 @@ static void hotkey_poll_setup(bool may_warn)
2579 } 2584 }
2580} 2585}
2581 2586
2582static void hotkey_poll_setup_safe(bool may_warn) 2587static void hotkey_poll_setup_safe(const bool may_warn)
2583{ 2588{
2584 mutex_lock(&hotkey_mutex); 2589 mutex_lock(&hotkey_mutex);
2585 hotkey_poll_setup(may_warn); 2590 hotkey_poll_setup(may_warn);
@@ -2597,7 +2602,11 @@ static void hotkey_poll_set_freq(unsigned int freq)
2597 2602
2598#else /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */ 2603#else /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */
2599 2604
2600static void hotkey_poll_setup_safe(bool __unused) 2605static void hotkey_poll_setup(const bool __unused)
2606{
2607}
2608
2609static void hotkey_poll_setup_safe(const bool __unused)
2601{ 2610{
2602} 2611}
2603 2612
@@ -2607,16 +2616,11 @@ static int hotkey_inputdev_open(struct input_dev *dev)
2607{ 2616{
2608 switch (tpacpi_lifecycle) { 2617 switch (tpacpi_lifecycle) {
2609 case TPACPI_LIFE_INIT: 2618 case TPACPI_LIFE_INIT:
2610 /*
2611 * hotkey_init will call hotkey_poll_setup_safe
2612 * at the appropriate moment
2613 */
2614 return 0;
2615 case TPACPI_LIFE_EXITING:
2616 return -EBUSY;
2617 case TPACPI_LIFE_RUNNING: 2619 case TPACPI_LIFE_RUNNING:
2618 hotkey_poll_setup_safe(false); 2620 hotkey_poll_setup_safe(false);
2619 return 0; 2621 return 0;
2622 case TPACPI_LIFE_EXITING:
2623 return -EBUSY;
2620 } 2624 }
2621 2625
2622 /* Should only happen if tpacpi_lifecycle is corrupt */ 2626 /* Should only happen if tpacpi_lifecycle is corrupt */
@@ -2627,7 +2631,7 @@ static int hotkey_inputdev_open(struct input_dev *dev)
2627static void hotkey_inputdev_close(struct input_dev *dev) 2631static void hotkey_inputdev_close(struct input_dev *dev)
2628{ 2632{
2629 /* disable hotkey polling when possible */ 2633 /* disable hotkey polling when possible */
2630 if (tpacpi_lifecycle == TPACPI_LIFE_RUNNING && 2634 if (tpacpi_lifecycle != TPACPI_LIFE_EXITING &&
2631 !(hotkey_source_mask & hotkey_driver_mask)) 2635 !(hotkey_source_mask & hotkey_driver_mask))
2632 hotkey_poll_setup_safe(false); 2636 hotkey_poll_setup_safe(false);
2633} 2637}
@@ -3655,13 +3659,19 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
3655 break; 3659 break;
3656 case 3: 3660 case 3:
3657 /* 0x3000-0x3FFF: bay-related wakeups */ 3661 /* 0x3000-0x3FFF: bay-related wakeups */
3658 if (hkey == TP_HKEY_EV_BAYEJ_ACK) { 3662 switch (hkey) {
3663 case TP_HKEY_EV_BAYEJ_ACK:
3659 hotkey_autosleep_ack = 1; 3664 hotkey_autosleep_ack = 1;
3660 printk(TPACPI_INFO 3665 printk(TPACPI_INFO
3661 "bay ejected\n"); 3666 "bay ejected\n");
3662 hotkey_wakeup_hotunplug_complete_notify_change(); 3667 hotkey_wakeup_hotunplug_complete_notify_change();
3663 known_ev = true; 3668 known_ev = true;
3664 } else { 3669 break;
3670 case TP_HKEY_EV_OPTDRV_EJ:
3671 /* FIXME: kick libata if SATA link offline */
3672 known_ev = true;
3673 break;
3674 default:
3665 known_ev = false; 3675 known_ev = false;
3666 } 3676 }
3667 break; 3677 break;
@@ -3870,7 +3880,7 @@ enum {
3870 TP_ACPI_BLUETOOTH_HWPRESENT = 0x01, /* Bluetooth hw available */ 3880 TP_ACPI_BLUETOOTH_HWPRESENT = 0x01, /* Bluetooth hw available */
3871 TP_ACPI_BLUETOOTH_RADIOSSW = 0x02, /* Bluetooth radio enabled */ 3881 TP_ACPI_BLUETOOTH_RADIOSSW = 0x02, /* Bluetooth radio enabled */
3872 TP_ACPI_BLUETOOTH_RESUMECTRL = 0x04, /* Bluetooth state at resume: 3882 TP_ACPI_BLUETOOTH_RESUMECTRL = 0x04, /* Bluetooth state at resume:
3873 off / last state */ 3883 0 = disable, 1 = enable */
3874}; 3884};
3875 3885
3876enum { 3886enum {
@@ -3916,10 +3926,11 @@ static int bluetooth_set_status(enum tpacpi_rfkill_state state)
3916 } 3926 }
3917#endif 3927#endif
3918 3928
3919 /* We make sure to keep TP_ACPI_BLUETOOTH_RESUMECTRL off */
3920 status = TP_ACPI_BLUETOOTH_RESUMECTRL;
3921 if (state == TPACPI_RFK_RADIO_ON) 3929 if (state == TPACPI_RFK_RADIO_ON)
3922 status |= TP_ACPI_BLUETOOTH_RADIOSSW; 3930 status = TP_ACPI_BLUETOOTH_RADIOSSW
3931 | TP_ACPI_BLUETOOTH_RESUMECTRL;
3932 else
3933 status = 0;
3923 3934
3924 if (!acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status)) 3935 if (!acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status))
3925 return -EIO; 3936 return -EIO;
@@ -4070,7 +4081,7 @@ enum {
4070 TP_ACPI_WANCARD_HWPRESENT = 0x01, /* Wan hw available */ 4081 TP_ACPI_WANCARD_HWPRESENT = 0x01, /* Wan hw available */
4071 TP_ACPI_WANCARD_RADIOSSW = 0x02, /* Wan radio enabled */ 4082 TP_ACPI_WANCARD_RADIOSSW = 0x02, /* Wan radio enabled */
4072 TP_ACPI_WANCARD_RESUMECTRL = 0x04, /* Wan state at resume: 4083 TP_ACPI_WANCARD_RESUMECTRL = 0x04, /* Wan state at resume:
4073 off / last state */ 4084 0 = disable, 1 = enable */
4074}; 4085};
4075 4086
4076#define TPACPI_RFK_WWAN_SW_NAME "tpacpi_wwan_sw" 4087#define TPACPI_RFK_WWAN_SW_NAME "tpacpi_wwan_sw"
@@ -4107,10 +4118,11 @@ static int wan_set_status(enum tpacpi_rfkill_state state)
4107 } 4118 }
4108#endif 4119#endif
4109 4120
4110 /* We make sure to set TP_ACPI_WANCARD_RESUMECTRL */
4111 status = TP_ACPI_WANCARD_RESUMECTRL;
4112 if (state == TPACPI_RFK_RADIO_ON) 4121 if (state == TPACPI_RFK_RADIO_ON)
4113 status |= TP_ACPI_WANCARD_RADIOSSW; 4122 status = TP_ACPI_WANCARD_RADIOSSW
4123 | TP_ACPI_WANCARD_RESUMECTRL;
4124 else
4125 status = 0;
4114 4126
4115 if (!acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status)) 4127 if (!acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status))
4116 return -EIO; 4128 return -EIO;
@@ -4619,6 +4631,10 @@ static int video_read(struct seq_file *m)
4619 return 0; 4631 return 0;
4620 } 4632 }
4621 4633
4634 /* Even reads can crash X.org, so... */
4635 if (!capable(CAP_SYS_ADMIN))
4636 return -EPERM;
4637
4622 status = video_outputsw_get(); 4638 status = video_outputsw_get();
4623 if (status < 0) 4639 if (status < 0)
4624 return status; 4640 return status;
@@ -4652,6 +4668,10 @@ static int video_write(char *buf)
4652 if (video_supported == TPACPI_VIDEO_NONE) 4668 if (video_supported == TPACPI_VIDEO_NONE)
4653 return -ENODEV; 4669 return -ENODEV;
4654 4670
4671 /* Even reads can crash X.org, let alone writes... */
4672 if (!capable(CAP_SYS_ADMIN))
4673 return -EPERM;
4674
4655 enable = 0; 4675 enable = 0;
4656 disable = 0; 4676 disable = 0;
4657 4677
@@ -6133,13 +6153,13 @@ static const struct tpacpi_quirk brightness_quirk_table[] __initconst = {
6133 TPACPI_Q_IBM('1', 'Y', TPACPI_BRGHT_Q_EC), /* T43/p ATI */ 6153 TPACPI_Q_IBM('1', 'Y', TPACPI_BRGHT_Q_EC), /* T43/p ATI */
6134 6154
6135 /* Models with ATI GPUs that can use ECNVRAM */ 6155 /* Models with ATI GPUs that can use ECNVRAM */
6136 TPACPI_Q_IBM('1', 'R', TPACPI_BRGHT_Q_EC), 6156 TPACPI_Q_IBM('1', 'R', TPACPI_BRGHT_Q_EC), /* R50,51 T40-42 */
6137 TPACPI_Q_IBM('1', 'Q', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), 6157 TPACPI_Q_IBM('1', 'Q', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
6138 TPACPI_Q_IBM('7', '6', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), 6158 TPACPI_Q_IBM('7', '6', TPACPI_BRGHT_Q_EC), /* R52 */
6139 TPACPI_Q_IBM('7', '8', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), 6159 TPACPI_Q_IBM('7', '8', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
6140 6160
6141 /* Models with Intel Extreme Graphics 2 */ 6161 /* Models with Intel Extreme Graphics 2 */
6142 TPACPI_Q_IBM('1', 'U', TPACPI_BRGHT_Q_NOEC), 6162 TPACPI_Q_IBM('1', 'U', TPACPI_BRGHT_Q_NOEC), /* X40 */
6143 TPACPI_Q_IBM('1', 'V', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), 6163 TPACPI_Q_IBM('1', 'V', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
6144 TPACPI_Q_IBM('1', 'W', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), 6164 TPACPI_Q_IBM('1', 'W', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
6145 6165
@@ -6151,6 +6171,7 @@ static const struct tpacpi_quirk brightness_quirk_table[] __initconst = {
6151 6171
6152static int __init brightness_init(struct ibm_init_struct *iibm) 6172static int __init brightness_init(struct ibm_init_struct *iibm)
6153{ 6173{
6174 struct backlight_properties props;
6154 int b; 6175 int b;
6155 unsigned long quirks; 6176 unsigned long quirks;
6156 6177
@@ -6240,9 +6261,12 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
6240 printk(TPACPI_INFO 6261 printk(TPACPI_INFO
6241 "detected a 16-level brightness capable ThinkPad\n"); 6262 "detected a 16-level brightness capable ThinkPad\n");
6242 6263
6243 ibm_backlight_device = backlight_device_register( 6264 memset(&props, 0, sizeof(struct backlight_properties));
6244 TPACPI_BACKLIGHT_DEV_NAME, NULL, NULL, 6265 props.max_brightness = (tp_features.bright_16levels) ? 15 : 7;
6245 &ibm_backlight_data); 6266 ibm_backlight_device = backlight_device_register(TPACPI_BACKLIGHT_DEV_NAME,
6267 NULL, NULL,
6268 &ibm_backlight_data,
6269 &props);
6246 if (IS_ERR(ibm_backlight_device)) { 6270 if (IS_ERR(ibm_backlight_device)) {
6247 int rc = PTR_ERR(ibm_backlight_device); 6271 int rc = PTR_ERR(ibm_backlight_device);
6248 ibm_backlight_device = NULL; 6272 ibm_backlight_device = NULL;
@@ -6261,8 +6285,6 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
6261 "or not on your ThinkPad\n", TPACPI_MAIL); 6285 "or not on your ThinkPad\n", TPACPI_MAIL);
6262 } 6286 }
6263 6287
6264 ibm_backlight_device->props.max_brightness =
6265 (tp_features.bright_16levels)? 15 : 7;
6266 ibm_backlight_device->props.brightness = b & TP_EC_BACKLIGHT_LVLMSK; 6288 ibm_backlight_device->props.brightness = b & TP_EC_BACKLIGHT_LVLMSK;
6267 backlight_update_status(ibm_backlight_device); 6289 backlight_update_status(ibm_backlight_device);
6268 6290
@@ -6522,7 +6544,8 @@ static int volume_set_status(const u8 status)
6522 return volume_set_status_ec(status); 6544 return volume_set_status_ec(status);
6523} 6545}
6524 6546
6525static int volume_set_mute_ec(const bool mute) 6547/* returns < 0 on error, 0 on no change, 1 on change */
6548static int __volume_set_mute_ec(const bool mute)
6526{ 6549{
6527 int rc; 6550 int rc;
6528 u8 s, n; 6551 u8 s, n;
@@ -6537,22 +6560,37 @@ static int volume_set_mute_ec(const bool mute)
6537 n = (mute) ? s | TP_EC_AUDIO_MUTESW_MSK : 6560 n = (mute) ? s | TP_EC_AUDIO_MUTESW_MSK :
6538 s & ~TP_EC_AUDIO_MUTESW_MSK; 6561 s & ~TP_EC_AUDIO_MUTESW_MSK;
6539 6562
6540 if (n != s) 6563 if (n != s) {
6541 rc = volume_set_status_ec(n); 6564 rc = volume_set_status_ec(n);
6565 if (!rc)
6566 rc = 1;
6567 }
6542 6568
6543unlock: 6569unlock:
6544 mutex_unlock(&volume_mutex); 6570 mutex_unlock(&volume_mutex);
6545 return rc; 6571 return rc;
6546} 6572}
6547 6573
6574static int volume_alsa_set_mute(const bool mute)
6575{
6576 dbg_printk(TPACPI_DBG_MIXER, "ALSA: trying to %smute\n",
6577 (mute) ? "" : "un");
6578 return __volume_set_mute_ec(mute);
6579}
6580
6548static int volume_set_mute(const bool mute) 6581static int volume_set_mute(const bool mute)
6549{ 6582{
6583 int rc;
6584
6550 dbg_printk(TPACPI_DBG_MIXER, "trying to %smute\n", 6585 dbg_printk(TPACPI_DBG_MIXER, "trying to %smute\n",
6551 (mute) ? "" : "un"); 6586 (mute) ? "" : "un");
6552 return volume_set_mute_ec(mute); 6587
6588 rc = __volume_set_mute_ec(mute);
6589 return (rc < 0) ? rc : 0;
6553} 6590}
6554 6591
6555static int volume_set_volume_ec(const u8 vol) 6592/* returns < 0 on error, 0 on no change, 1 on change */
6593static int __volume_set_volume_ec(const u8 vol)
6556{ 6594{
6557 int rc; 6595 int rc;
6558 u8 s, n; 6596 u8 s, n;
@@ -6569,19 +6607,22 @@ static int volume_set_volume_ec(const u8 vol)
6569 6607
6570 n = (s & ~TP_EC_AUDIO_LVL_MSK) | vol; 6608 n = (s & ~TP_EC_AUDIO_LVL_MSK) | vol;
6571 6609
6572 if (n != s) 6610 if (n != s) {
6573 rc = volume_set_status_ec(n); 6611 rc = volume_set_status_ec(n);
6612 if (!rc)
6613 rc = 1;
6614 }
6574 6615
6575unlock: 6616unlock:
6576 mutex_unlock(&volume_mutex); 6617 mutex_unlock(&volume_mutex);
6577 return rc; 6618 return rc;
6578} 6619}
6579 6620
6580static int volume_set_volume(const u8 vol) 6621static int volume_alsa_set_volume(const u8 vol)
6581{ 6622{
6582 dbg_printk(TPACPI_DBG_MIXER, 6623 dbg_printk(TPACPI_DBG_MIXER,
6583 "trying to set volume level to %hu\n", vol); 6624 "ALSA: trying to set volume level to %hu\n", vol);
6584 return volume_set_volume_ec(vol); 6625 return __volume_set_volume_ec(vol);
6585} 6626}
6586 6627
6587static void volume_alsa_notify_change(void) 6628static void volume_alsa_notify_change(void)
@@ -6628,7 +6669,7 @@ static int volume_alsa_vol_get(struct snd_kcontrol *kcontrol,
6628static int volume_alsa_vol_put(struct snd_kcontrol *kcontrol, 6669static int volume_alsa_vol_put(struct snd_kcontrol *kcontrol,
6629 struct snd_ctl_elem_value *ucontrol) 6670 struct snd_ctl_elem_value *ucontrol)
6630{ 6671{
6631 return volume_set_volume(ucontrol->value.integer.value[0]); 6672 return volume_alsa_set_volume(ucontrol->value.integer.value[0]);
6632} 6673}
6633 6674
6634#define volume_alsa_mute_info snd_ctl_boolean_mono_info 6675#define volume_alsa_mute_info snd_ctl_boolean_mono_info
@@ -6651,7 +6692,7 @@ static int volume_alsa_mute_get(struct snd_kcontrol *kcontrol,
6651static int volume_alsa_mute_put(struct snd_kcontrol *kcontrol, 6692static int volume_alsa_mute_put(struct snd_kcontrol *kcontrol,
6652 struct snd_ctl_elem_value *ucontrol) 6693 struct snd_ctl_elem_value *ucontrol)
6653{ 6694{
6654 return volume_set_mute(!ucontrol->value.integer.value[0]); 6695 return volume_alsa_set_mute(!ucontrol->value.integer.value[0]);
6655} 6696}
6656 6697
6657static struct snd_kcontrol_new volume_alsa_control_vol __devinitdata = { 6698static struct snd_kcontrol_new volume_alsa_control_vol __devinitdata = {
@@ -7070,7 +7111,7 @@ static struct ibm_struct volume_driver_data = {
7070 * 7111 *
7071 * Fan speed changes of any sort (including those caused by the 7112 * Fan speed changes of any sort (including those caused by the
7072 * disengaged mode) are usually done slowly by the firmware as the 7113 * disengaged mode) are usually done slowly by the firmware as the
7073 * maximum ammount of fan duty cycle change per second seems to be 7114 * maximum amount of fan duty cycle change per second seems to be
7074 * limited. 7115 * limited.
7075 * 7116 *
7076 * Reading is not available if GFAN exists. 7117 * Reading is not available if GFAN exists.
@@ -8477,9 +8518,10 @@ static int __init ibm_init(struct ibm_init_struct *iibm)
8477 "%s installed\n", ibm->name); 8518 "%s installed\n", ibm->name);
8478 8519
8479 if (ibm->read) { 8520 if (ibm->read) {
8480 mode_t mode; 8521 mode_t mode = iibm->base_procfs_mode;
8481 8522
8482 mode = S_IRUGO; 8523 if (!mode)
8524 mode = S_IRUGO;
8483 if (ibm->write) 8525 if (ibm->write)
8484 mode |= S_IWUSR; 8526 mode |= S_IWUSR;
8485 entry = proc_create_data(ibm->name, mode, proc_dir, 8527 entry = proc_create_data(ibm->name, mode, proc_dir,
@@ -8670,6 +8712,7 @@ static struct ibm_init_struct ibms_init[] __initdata = {
8670#ifdef CONFIG_THINKPAD_ACPI_VIDEO 8712#ifdef CONFIG_THINKPAD_ACPI_VIDEO
8671 { 8713 {
8672 .init = video_init, 8714 .init = video_init,
8715 .base_procfs_mode = S_IRUSR,
8673 .data = &video_driver_data, 8716 .data = &video_driver_data,
8674 }, 8717 },
8675#endif 8718#endif
@@ -9032,6 +9075,9 @@ static int __init thinkpad_acpi_module_init(void)
9032 return ret; 9075 return ret;
9033 } 9076 }
9034 } 9077 }
9078
9079 tpacpi_lifecycle = TPACPI_LIFE_RUNNING;
9080
9035 ret = input_register_device(tpacpi_inputdev); 9081 ret = input_register_device(tpacpi_inputdev);
9036 if (ret < 0) { 9082 if (ret < 0) {
9037 printk(TPACPI_ERR "unable to register input device\n"); 9083 printk(TPACPI_ERR "unable to register input device\n");
@@ -9041,7 +9087,6 @@ static int __init thinkpad_acpi_module_init(void)
9041 tp_features.input_device_registered = 1; 9087 tp_features.input_device_registered = 1;
9042 } 9088 }
9043 9089
9044 tpacpi_lifecycle = TPACPI_LIFE_RUNNING;
9045 return 0; 9090 return 0;
9046} 9091}
9047 9092
diff --git a/drivers/platform/x86/topstar-laptop.c b/drivers/platform/x86/topstar-laptop.c
index 02f3d4e9e66..ff4b476f195 100644
--- a/drivers/platform/x86/topstar-laptop.c
+++ b/drivers/platform/x86/topstar-laptop.c
@@ -16,6 +16,7 @@
16#include <linux/kernel.h> 16#include <linux/kernel.h>
17#include <linux/module.h> 17#include <linux/module.h>
18#include <linux/init.h> 18#include <linux/init.h>
19#include <linux/slab.h>
19#include <linux/acpi.h> 20#include <linux/acpi.h>
20#include <linux/input.h> 21#include <linux/input.h>
21 22
@@ -46,7 +47,7 @@ static struct tps_key_entry topstar_keymap[] = {
46 { } 47 { }
47}; 48};
48 49
49static struct tps_key_entry *tps_get_key_by_scancode(int code) 50static struct tps_key_entry *tps_get_key_by_scancode(unsigned int code)
50{ 51{
51 struct tps_key_entry *key; 52 struct tps_key_entry *key;
52 53
@@ -57,7 +58,7 @@ static struct tps_key_entry *tps_get_key_by_scancode(int code)
57 return NULL; 58 return NULL;
58} 59}
59 60
60static struct tps_key_entry *tps_get_key_by_keycode(int code) 61static struct tps_key_entry *tps_get_key_by_keycode(unsigned int code)
61{ 62{
62 struct tps_key_entry *key; 63 struct tps_key_entry *key;
63 64
@@ -126,7 +127,8 @@ static int acpi_topstar_fncx_switch(struct acpi_device *device, bool state)
126 return 0; 127 return 0;
127} 128}
128 129
129static int topstar_getkeycode(struct input_dev *dev, int scancode, int *keycode) 130static int topstar_getkeycode(struct input_dev *dev,
131 unsigned int scancode, unsigned int *keycode)
130{ 132{
131 struct tps_key_entry *key = tps_get_key_by_scancode(scancode); 133 struct tps_key_entry *key = tps_get_key_by_scancode(scancode);
132 134
@@ -137,14 +139,12 @@ static int topstar_getkeycode(struct input_dev *dev, int scancode, int *keycode)
137 return 0; 139 return 0;
138} 140}
139 141
140static int topstar_setkeycode(struct input_dev *dev, int scancode, int keycode) 142static int topstar_setkeycode(struct input_dev *dev,
143 unsigned int scancode, unsigned int keycode)
141{ 144{
142 struct tps_key_entry *key; 145 struct tps_key_entry *key;
143 int old_keycode; 146 int old_keycode;
144 147
145 if (keycode < 0 || keycode > KEY_MAX)
146 return -EINVAL;
147
148 key = tps_get_key_by_scancode(scancode); 148 key = tps_get_key_by_scancode(scancode);
149 149
150 if (!key) 150 if (!key)
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index 26c211724ac..37aa1479855 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -47,6 +47,7 @@
47#include <linux/platform_device.h> 47#include <linux/platform_device.h>
48#include <linux/rfkill.h> 48#include <linux/rfkill.h>
49#include <linux/input.h> 49#include <linux/input.h>
50#include <linux/slab.h>
50 51
51#include <asm/uaccess.h> 52#include <asm/uaccess.h>
52 53
@@ -745,7 +746,7 @@ static struct backlight_ops toshiba_backlight_data = {
745 .update_status = set_lcd_status, 746 .update_status = set_lcd_status,
746}; 747};
747 748
748static struct key_entry *toshiba_acpi_get_entry_by_scancode(int code) 749static struct key_entry *toshiba_acpi_get_entry_by_scancode(unsigned int code)
749{ 750{
750 struct key_entry *key; 751 struct key_entry *key;
751 752
@@ -756,7 +757,7 @@ static struct key_entry *toshiba_acpi_get_entry_by_scancode(int code)
756 return NULL; 757 return NULL;
757} 758}
758 759
759static struct key_entry *toshiba_acpi_get_entry_by_keycode(int code) 760static struct key_entry *toshiba_acpi_get_entry_by_keycode(unsigned int code)
760{ 761{
761 struct key_entry *key; 762 struct key_entry *key;
762 763
@@ -767,8 +768,8 @@ static struct key_entry *toshiba_acpi_get_entry_by_keycode(int code)
767 return NULL; 768 return NULL;
768} 769}
769 770
770static int toshiba_acpi_getkeycode(struct input_dev *dev, int scancode, 771static int toshiba_acpi_getkeycode(struct input_dev *dev,
771 int *keycode) 772 unsigned int scancode, unsigned int *keycode)
772{ 773{
773 struct key_entry *key = toshiba_acpi_get_entry_by_scancode(scancode); 774 struct key_entry *key = toshiba_acpi_get_entry_by_scancode(scancode);
774 775
@@ -780,14 +781,11 @@ static int toshiba_acpi_getkeycode(struct input_dev *dev, int scancode,
780 return -EINVAL; 781 return -EINVAL;
781} 782}
782 783
783static int toshiba_acpi_setkeycode(struct input_dev *dev, int scancode, 784static int toshiba_acpi_setkeycode(struct input_dev *dev,
784 int keycode) 785 unsigned int scancode, unsigned int keycode)
785{ 786{
786 struct key_entry *key; 787 struct key_entry *key;
787 int old_keycode; 788 unsigned int old_keycode;
788
789 if (keycode < 0 || keycode > KEY_MAX)
790 return -EINVAL;
791 789
792 key = toshiba_acpi_get_entry_by_scancode(scancode); 790 key = toshiba_acpi_get_entry_by_scancode(scancode);
793 if (key && key->type == KE_KEY) { 791 if (key && key->type == KE_KEY) {
@@ -814,21 +812,23 @@ static void toshiba_acpi_notify(acpi_handle handle, u32 event, void *context)
814 if (hci_result == HCI_SUCCESS) { 812 if (hci_result == HCI_SUCCESS) {
815 if (value == 0x100) 813 if (value == 0x100)
816 continue; 814 continue;
817 else if (value & 0x80) { 815 /* act on key press; ignore key release */
818 key = toshiba_acpi_get_entry_by_scancode 816 if (value & 0x80)
819 (value & ~0x80); 817 continue;
820 if (!key) { 818
821 printk(MY_INFO "Unknown key %x\n", 819 key = toshiba_acpi_get_entry_by_scancode
822 value & ~0x80); 820 (value);
823 continue; 821 if (!key) {
824 } 822 printk(MY_INFO "Unknown key %x\n",
825 input_report_key(toshiba_acpi.hotkey_dev, 823 value);
826 key->keycode, 1); 824 continue;
827 input_sync(toshiba_acpi.hotkey_dev);
828 input_report_key(toshiba_acpi.hotkey_dev,
829 key->keycode, 0);
830 input_sync(toshiba_acpi.hotkey_dev);
831 } 825 }
826 input_report_key(toshiba_acpi.hotkey_dev,
827 key->keycode, 1);
828 input_sync(toshiba_acpi.hotkey_dev);
829 input_report_key(toshiba_acpi.hotkey_dev,
830 key->keycode, 0);
831 input_sync(toshiba_acpi.hotkey_dev);
832 } else if (hci_result == HCI_NOT_SUPPORTED) { 832 } else if (hci_result == HCI_NOT_SUPPORTED) {
833 /* This is a workaround for an unresolved issue on 833 /* This is a workaround for an unresolved issue on
834 * some machines where system events sporadically 834 * some machines where system events sporadically
@@ -925,6 +925,7 @@ static int __init toshiba_acpi_init(void)
925 u32 hci_result; 925 u32 hci_result;
926 bool bt_present; 926 bool bt_present;
927 int ret = 0; 927 int ret = 0;
928 struct backlight_properties props;
928 929
929 if (acpi_disabled) 930 if (acpi_disabled)
930 return -ENODEV; 931 return -ENODEV;
@@ -975,10 +976,12 @@ static int __init toshiba_acpi_init(void)
975 } 976 }
976 } 977 }
977 978
979 props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1;
978 toshiba_backlight_device = backlight_device_register("toshiba", 980 toshiba_backlight_device = backlight_device_register("toshiba",
979 &toshiba_acpi.p_dev->dev, 981 &toshiba_acpi.p_dev->dev,
980 NULL, 982 NULL,
981 &toshiba_backlight_data); 983 &toshiba_backlight_data,
984 &props);
982 if (IS_ERR(toshiba_backlight_device)) { 985 if (IS_ERR(toshiba_backlight_device)) {
983 ret = PTR_ERR(toshiba_backlight_device); 986 ret = PTR_ERR(toshiba_backlight_device);
984 987
@@ -987,7 +990,6 @@ static int __init toshiba_acpi_init(void)
987 toshiba_acpi_exit(); 990 toshiba_acpi_exit();
988 return ret; 991 return ret;
989 } 992 }
990 toshiba_backlight_device->props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1;
991 993
992 /* Register rfkill switch for Bluetooth */ 994 /* Register rfkill switch for Bluetooth */
993 if (hci_get_bt_present(&bt_present) == HCI_SUCCESS && bt_present) { 995 if (hci_get_bt_present(&bt_present) == HCI_SUCCESS && bt_present) {
diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c
index 09e9918c69c..39ec5b6c2e3 100644
--- a/drivers/platform/x86/wmi.c
+++ b/drivers/platform/x86/wmi.c
@@ -33,6 +33,7 @@
33#include <linux/device.h> 33#include <linux/device.h>
34#include <linux/list.h> 34#include <linux/list.h>
35#include <linux/acpi.h> 35#include <linux/acpi.h>
36#include <linux/slab.h>
36#include <acpi/acpi_bus.h> 37#include <acpi/acpi_bus.h>
37#include <acpi/acpi_drivers.h> 38#include <acpi/acpi_drivers.h>
38 39