aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2009-12-15 22:34:48 -0500
committerLen Brown <len.brown@intel.com>2009-12-15 22:34:48 -0500
commit9a3bff236b51583eaac7c2f0bd1db0dcf7b36a5c (patch)
tree0b4ad1c00078b335e49b5fcb460d02797c19a1ff
parent173cc11a6e10c38ff7d4949b48e8d2eb0aee3e05 (diff)
parentd951d4cc84e8b5ddb8e0ab81cf6a72cc73fdd668 (diff)
Merge branch 'asus' into release
Conflicts: Documentation/feature-removal-schedule.txt drivers/platform/x86/eeepc-laptop.c Signed-off-by: Len Brown <len.brown@intel.com>
-rw-r--r--Documentation/feature-removal-schedule.txt19
-rw-r--r--drivers/platform/x86/Kconfig2
-rw-r--r--drivers/platform/x86/asus-laptop.c25
-rw-r--r--drivers/platform/x86/asus_acpi.c19
-rw-r--r--drivers/platform/x86/eeepc-laptop.c1415
5 files changed, 825 insertions, 655 deletions
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 21ab9357326d..870d190fe617 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -474,3 +474,22 @@ Why: Obsoleted by the adt7475 driver.
474Who: Jean Delvare <khali@linux-fr.org> 474Who: Jean Delvare <khali@linux-fr.org>
475 475
476--------------------------- 476---------------------------
477What: Support for lcd_switch and display_get in asus-laptop driver
478When: March 2010
479Why: These two features use non-standard interfaces. There are the
480 only features that really need multiple path to guess what's
481 the right method name on a specific laptop.
482
483 Removing them will allow to remove a lot of code an significantly
484 clean the drivers.
485
486 This will affect the backlight code which won't be able to know
487 if the backlight is on or off. The platform display file will also be
488 write only (like the one in eeepc-laptop).
489
490 This should'nt affect a lot of user because they usually know
491 when their display is on or off.
492
493Who: Corentin Chary <corentin.chary@gmail.com>
494
495----------------------------
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 55ca39dea42e..e5e43121995d 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -334,6 +334,8 @@ config EEEPC_LAPTOP
334 depends on HOTPLUG_PCI 334 depends on HOTPLUG_PCI
335 select BACKLIGHT_CLASS_DEVICE 335 select BACKLIGHT_CLASS_DEVICE
336 select HWMON 336 select HWMON
337 select LEDS_CLASS
338 select NEW_LEDS
337 ---help--- 339 ---help---
338 This driver supports the Fn-Fx keys on Eee PC laptops. 340 This driver supports the Fn-Fx keys on Eee PC laptops.
339 341
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index b39d2bb3e75b..61a1c7503658 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -221,6 +221,7 @@ static struct asus_hotk *hotk;
221 */ 221 */
222static const struct acpi_device_id asus_device_ids[] = { 222static const struct acpi_device_id asus_device_ids[] = {
223 {"ATK0100", 0}, 223 {"ATK0100", 0},
224 {"ATK0101", 0},
224 {"", 0}, 225 {"", 0},
225}; 226};
226MODULE_DEVICE_TABLE(acpi, asus_device_ids); 227MODULE_DEVICE_TABLE(acpi, asus_device_ids);
@@ -232,6 +233,7 @@ static void asus_hotk_notify(struct acpi_device *device, u32 event);
232static struct acpi_driver asus_hotk_driver = { 233static struct acpi_driver asus_hotk_driver = {
233 .name = ASUS_HOTK_NAME, 234 .name = ASUS_HOTK_NAME,
234 .class = ASUS_HOTK_CLASS, 235 .class = ASUS_HOTK_CLASS,
236 .owner = THIS_MODULE,
235 .ids = asus_device_ids, 237 .ids = asus_device_ids,
236 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS, 238 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
237 .ops = { 239 .ops = {
@@ -293,6 +295,11 @@ struct key_entry {
293enum { KE_KEY, KE_END }; 295enum { KE_KEY, KE_END };
294 296
295static struct key_entry asus_keymap[] = { 297static struct key_entry asus_keymap[] = {
298 {KE_KEY, 0x02, KEY_SCREENLOCK},
299 {KE_KEY, 0x05, KEY_WLAN},
300 {KE_KEY, 0x08, KEY_F13},
301 {KE_KEY, 0x17, KEY_ZOOM},
302 {KE_KEY, 0x1f, KEY_BATTERY},
296 {KE_KEY, 0x30, KEY_VOLUMEUP}, 303 {KE_KEY, 0x30, KEY_VOLUMEUP},
297 {KE_KEY, 0x31, KEY_VOLUMEDOWN}, 304 {KE_KEY, 0x31, KEY_VOLUMEDOWN},
298 {KE_KEY, 0x32, KEY_MUTE}, 305 {KE_KEY, 0x32, KEY_MUTE},
@@ -312,8 +319,11 @@ static struct key_entry asus_keymap[] = {
312 {KE_KEY, 0x5F, KEY_WLAN}, 319 {KE_KEY, 0x5F, KEY_WLAN},
313 {KE_KEY, 0x60, KEY_SWITCHVIDEOMODE}, 320 {KE_KEY, 0x60, KEY_SWITCHVIDEOMODE},
314 {KE_KEY, 0x61, KEY_SWITCHVIDEOMODE}, 321 {KE_KEY, 0x61, KEY_SWITCHVIDEOMODE},
315 {KE_KEY, 0x6B, BTN_TOUCH}, /* Lock Mouse */ 322 {KE_KEY, 0x62, KEY_SWITCHVIDEOMODE},
323 {KE_KEY, 0x63, KEY_SWITCHVIDEOMODE},
324 {KE_KEY, 0x6B, KEY_F13}, /* Lock Touchpad */
316 {KE_KEY, 0x82, KEY_CAMERA}, 325 {KE_KEY, 0x82, KEY_CAMERA},
326 {KE_KEY, 0x88, KEY_WLAN },
317 {KE_KEY, 0x8A, KEY_PROG1}, 327 {KE_KEY, 0x8A, KEY_PROG1},
318 {KE_KEY, 0x95, KEY_MEDIA}, 328 {KE_KEY, 0x95, KEY_MEDIA},
319 {KE_KEY, 0x99, KEY_PHONE}, 329 {KE_KEY, 0x99, KEY_PHONE},
@@ -1240,9 +1250,6 @@ static int asus_hotk_add(struct acpi_device *device)
1240{ 1250{
1241 int result; 1251 int result;
1242 1252
1243 if (!device)
1244 return -EINVAL;
1245
1246 pr_notice("Asus Laptop Support version %s\n", 1253 pr_notice("Asus Laptop Support version %s\n",
1247 ASUS_LAPTOP_VERSION); 1254 ASUS_LAPTOP_VERSION);
1248 1255
@@ -1283,8 +1290,8 @@ static int asus_hotk_add(struct acpi_device *device)
1283 hotk->ledd_status = 0xFFF; 1290 hotk->ledd_status = 0xFFF;
1284 1291
1285 /* Set initial values of light sensor and level */ 1292 /* Set initial values of light sensor and level */
1286 hotk->light_switch = 1; /* Default to light sensor disabled */ 1293 hotk->light_switch = 0; /* Default to light sensor disabled */
1287 hotk->light_level = 0; /* level 5 for sensor sensitivity */ 1294 hotk->light_level = 5; /* level 5 for sensor sensitivity */
1288 1295
1289 if (ls_switch_handle) 1296 if (ls_switch_handle)
1290 set_light_sens_switch(hotk->light_switch); 1297 set_light_sens_switch(hotk->light_switch);
@@ -1306,9 +1313,6 @@ end:
1306 1313
1307static int asus_hotk_remove(struct acpi_device *device, int type) 1314static int asus_hotk_remove(struct acpi_device *device, int type)
1308{ 1315{
1309 if (!device || !acpi_driver_data(device))
1310 return -EINVAL;
1311
1312 kfree(hotk->name); 1316 kfree(hotk->name);
1313 kfree(hotk); 1317 kfree(hotk);
1314 1318
@@ -1444,9 +1448,6 @@ static int __init asus_laptop_init(void)
1444{ 1448{
1445 int result; 1449 int result;
1446 1450
1447 if (acpi_disabled)
1448 return -ENODEV;
1449
1450 result = acpi_bus_register_driver(&asus_hotk_driver); 1451 result = acpi_bus_register_driver(&asus_hotk_driver);
1451 if (result < 0) 1452 if (result < 0)
1452 return result; 1453 return result;
diff --git a/drivers/platform/x86/asus_acpi.c b/drivers/platform/x86/asus_acpi.c
index ddf5240ade8c..0c9c53111a22 100644
--- a/drivers/platform/x86/asus_acpi.c
+++ b/drivers/platform/x86/asus_acpi.c
@@ -466,6 +466,7 @@ MODULE_DEVICE_TABLE(acpi, asus_device_ids);
466static struct acpi_driver asus_hotk_driver = { 466static struct acpi_driver asus_hotk_driver = {
467 .name = "asus_acpi", 467 .name = "asus_acpi",
468 .class = ACPI_HOTK_CLASS, 468 .class = ACPI_HOTK_CLASS,
469 .owner = THIS_MODULE,
469 .ids = asus_device_ids, 470 .ids = asus_device_ids,
470 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS, 471 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
471 .ops = { 472 .ops = {
@@ -1334,9 +1335,6 @@ static int asus_hotk_add(struct acpi_device *device)
1334 acpi_status status = AE_OK; 1335 acpi_status status = AE_OK;
1335 int result; 1336 int result;
1336 1337
1337 if (!device)
1338 return -EINVAL;
1339
1340 printk(KERN_NOTICE "Asus Laptop ACPI Extras version %s\n", 1338 printk(KERN_NOTICE "Asus Laptop ACPI Extras version %s\n",
1341 ASUS_ACPI_VERSION); 1339 ASUS_ACPI_VERSION);
1342 1340
@@ -1392,9 +1390,6 @@ end:
1392 1390
1393static int asus_hotk_remove(struct acpi_device *device, int type) 1391static int asus_hotk_remove(struct acpi_device *device, int type)
1394{ 1392{
1395 if (!device || !acpi_driver_data(device))
1396 return -EINVAL;
1397
1398 asus_hotk_remove_fs(device); 1393 asus_hotk_remove_fs(device);
1399 1394
1400 kfree(hotk); 1395 kfree(hotk);
@@ -1422,21 +1417,17 @@ static int __init asus_acpi_init(void)
1422{ 1417{
1423 int result; 1418 int result;
1424 1419
1425 if (acpi_disabled) 1420 result = acpi_bus_register_driver(&asus_hotk_driver);
1426 return -ENODEV; 1421 if (result < 0)
1422 return result;
1427 1423
1428 asus_proc_dir = proc_mkdir(PROC_ASUS, acpi_root_dir); 1424 asus_proc_dir = proc_mkdir(PROC_ASUS, acpi_root_dir);
1429 if (!asus_proc_dir) { 1425 if (!asus_proc_dir) {
1430 printk(KERN_ERR "Asus ACPI: Unable to create /proc entry\n"); 1426 printk(KERN_ERR "Asus ACPI: Unable to create /proc entry\n");
1427 acpi_bus_unregister_driver(&asus_hotk_driver);
1431 return -ENODEV; 1428 return -ENODEV;
1432 } 1429 }
1433 1430
1434 result = acpi_bus_register_driver(&asus_hotk_driver);
1435 if (result < 0) {
1436 remove_proc_entry(PROC_ASUS, acpi_root_dir);
1437 return result;
1438 }
1439
1440 /* 1431 /*
1441 * This is a bit of a kludge. We only want this module loaded 1432 * This is a bit of a kludge. We only want this module loaded
1442 * for ASUS systems, but there's currently no way to probe the 1433 * for ASUS systems, but there's currently no way to probe the
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c
index e647a856b9bf..5838c69b2fb3 100644
--- a/drivers/platform/x86/eeepc-laptop.c
+++ b/drivers/platform/x86/eeepc-laptop.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * eepc-laptop.c - Asus Eee PC extras 2 * eeepc-laptop.c - Asus Eee PC extras
3 * 3 *
4 * Based on asus_acpi.c as patched for the Eee PC by Asus: 4 * Based on asus_acpi.c as patched for the Eee PC by Asus:
5 * ftp://ftp.asus.com/pub/ASUS/EeePC/701/ASUS_ACPI_071126.rar 5 * ftp://ftp.asus.com/pub/ASUS/EeePC/701/ASUS_ACPI_071126.rar
@@ -34,20 +34,23 @@
34#include <linux/rfkill.h> 34#include <linux/rfkill.h>
35#include <linux/pci.h> 35#include <linux/pci.h>
36#include <linux/pci_hotplug.h> 36#include <linux/pci_hotplug.h>
37#include <linux/leds.h>
37 38
38#define EEEPC_LAPTOP_VERSION "0.1" 39#define EEEPC_LAPTOP_VERSION "0.1"
40#define EEEPC_LAPTOP_NAME "Eee PC Hotkey Driver"
41#define EEEPC_LAPTOP_FILE "eeepc"
39 42
40#define EEEPC_HOTK_NAME "Eee PC Hotkey Driver" 43#define EEEPC_ACPI_CLASS "hotkey"
41#define EEEPC_HOTK_FILE "eeepc" 44#define EEEPC_ACPI_DEVICE_NAME "Hotkey"
42#define EEEPC_HOTK_CLASS "hotkey" 45#define EEEPC_ACPI_HID "ASUS010"
43#define EEEPC_HOTK_DEVICE_NAME "Hotkey"
44#define EEEPC_HOTK_HID "ASUS010"
45 46
47MODULE_AUTHOR("Corentin Chary, Eric Cooper");
48MODULE_DESCRIPTION(EEEPC_LAPTOP_NAME);
49MODULE_LICENSE("GPL");
46 50
47/* 51/*
48 * Definitions for Asus EeePC 52 * Definitions for Asus EeePC
49 */ 53 */
50#define NOTIFY_WLAN_ON 0x10
51#define NOTIFY_BRN_MIN 0x20 54#define NOTIFY_BRN_MIN 0x20
52#define NOTIFY_BRN_MAX 0x2f 55#define NOTIFY_BRN_MAX 0x2f
53 56
@@ -117,58 +120,6 @@ static const char *cm_setv[] = {
117 NULL, NULL, "PBPS", "TPDS" 120 NULL, NULL, "PBPS", "TPDS"
118}; 121};
119 122
120#define EEEPC_EC "\\_SB.PCI0.SBRG.EC0."
121
122#define EEEPC_EC_FAN_PWM EEEPC_EC "SC02" /* Fan PWM duty cycle (%) */
123#define EEEPC_EC_SC02 0x63
124#define EEEPC_EC_FAN_HRPM EEEPC_EC "SC05" /* High byte, fan speed (RPM) */
125#define EEEPC_EC_FAN_LRPM EEEPC_EC "SC06" /* Low byte, fan speed (RPM) */
126#define EEEPC_EC_FAN_CTRL EEEPC_EC "SFB3" /* Byte containing SF25 */
127#define EEEPC_EC_SFB3 0xD3
128
129/*
130 * This is the main structure, we can use it to store useful information
131 * about the hotk device
132 */
133struct eeepc_hotk {
134 struct acpi_device *device; /* the device we are in */
135 acpi_handle handle; /* the handle of the hotk device */
136 u32 cm_supported; /* the control methods supported
137 by this BIOS */
138 uint init_flag; /* Init flags */
139 u16 event_count[128]; /* count for each event */
140 struct input_dev *inputdev;
141 u16 *keycode_map;
142 struct rfkill *wlan_rfkill;
143 struct rfkill *bluetooth_rfkill;
144 struct rfkill *wwan3g_rfkill;
145 struct rfkill *wimax_rfkill;
146 struct hotplug_slot *hotplug_slot;
147 struct mutex hotplug_lock;
148};
149
150/* The actual device the driver binds to */
151static struct eeepc_hotk *ehotk;
152
153/* Platform device/driver */
154static int eeepc_hotk_thaw(struct device *device);
155static int eeepc_hotk_restore(struct device *device);
156
157static const struct dev_pm_ops eeepc_pm_ops = {
158 .thaw = eeepc_hotk_thaw,
159 .restore = eeepc_hotk_restore,
160};
161
162static struct platform_driver platform_driver = {
163 .driver = {
164 .name = EEEPC_HOTK_FILE,
165 .owner = THIS_MODULE,
166 .pm = &eeepc_pm_ops,
167 }
168};
169
170static struct platform_device *platform_device;
171
172struct key_entry { 123struct key_entry {
173 char type; 124 char type;
174 u8 code; 125 u8 code;
@@ -177,7 +128,7 @@ struct key_entry {
177 128
178enum { KE_KEY, KE_END }; 129enum { KE_KEY, KE_END };
179 130
180static struct key_entry eeepc_keymap[] = { 131static const struct key_entry eeepc_keymap[] = {
181 /* Sleep already handled via generic ACPI code */ 132 /* Sleep already handled via generic ACPI code */
182 {KE_KEY, 0x10, KEY_WLAN }, 133 {KE_KEY, 0x10, KEY_WLAN },
183 {KE_KEY, 0x11, KEY_WLAN }, 134 {KE_KEY, 0x11, KEY_WLAN },
@@ -185,77 +136,56 @@ static struct key_entry eeepc_keymap[] = {
185 {KE_KEY, 0x13, KEY_MUTE }, 136 {KE_KEY, 0x13, KEY_MUTE },
186 {KE_KEY, 0x14, KEY_VOLUMEDOWN }, 137 {KE_KEY, 0x14, KEY_VOLUMEDOWN },
187 {KE_KEY, 0x15, KEY_VOLUMEUP }, 138 {KE_KEY, 0x15, KEY_VOLUMEUP },
139 {KE_KEY, 0x16, KEY_DISPLAY_OFF },
188 {KE_KEY, 0x1a, KEY_COFFEE }, 140 {KE_KEY, 0x1a, KEY_COFFEE },
189 {KE_KEY, 0x1b, KEY_ZOOM }, 141 {KE_KEY, 0x1b, KEY_ZOOM },
190 {KE_KEY, 0x1c, KEY_PROG2 }, 142 {KE_KEY, 0x1c, KEY_PROG2 },
191 {KE_KEY, 0x1d, KEY_PROG3 }, 143 {KE_KEY, 0x1d, KEY_PROG3 },
192 {KE_KEY, NOTIFY_BRN_MIN, KEY_BRIGHTNESSDOWN }, 144 {KE_KEY, NOTIFY_BRN_MIN, KEY_BRIGHTNESSDOWN },
193 {KE_KEY, NOTIFY_BRN_MIN + 2, KEY_BRIGHTNESSUP }, 145 {KE_KEY, NOTIFY_BRN_MAX, KEY_BRIGHTNESSUP },
194 {KE_KEY, 0x30, KEY_SWITCHVIDEOMODE }, 146 {KE_KEY, 0x30, KEY_SWITCHVIDEOMODE },
195 {KE_KEY, 0x31, KEY_SWITCHVIDEOMODE }, 147 {KE_KEY, 0x31, KEY_SWITCHVIDEOMODE },
196 {KE_KEY, 0x32, KEY_SWITCHVIDEOMODE }, 148 {KE_KEY, 0x32, KEY_SWITCHVIDEOMODE },
149 {KE_KEY, 0x37, KEY_F13 }, /* Disable Touchpad */
150 {KE_KEY, 0x38, KEY_F14 },
197 {KE_END, 0}, 151 {KE_END, 0},
198}; 152};
199 153
154
200/* 155/*
201 * The hotkey driver declaration 156 * This is the main structure, we can use it to store useful information
202 */ 157 */
203static int eeepc_hotk_add(struct acpi_device *device); 158struct eeepc_laptop {
204static int eeepc_hotk_remove(struct acpi_device *device, int type); 159 acpi_handle handle; /* the handle of the acpi device */
205static void eeepc_hotk_notify(struct acpi_device *device, u32 event); 160 u32 cm_supported; /* the control methods supported
206 161 by this BIOS */
207static const struct acpi_device_id eeepc_device_ids[] = { 162 u16 event_count[128]; /* count for each event */
208 {EEEPC_HOTK_HID, 0},
209 {"", 0},
210};
211MODULE_DEVICE_TABLE(acpi, eeepc_device_ids);
212
213static struct acpi_driver eeepc_hotk_driver = {
214 .name = EEEPC_HOTK_NAME,
215 .class = EEEPC_HOTK_CLASS,
216 .ids = eeepc_device_ids,
217 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
218 .ops = {
219 .add = eeepc_hotk_add,
220 .remove = eeepc_hotk_remove,
221 .notify = eeepc_hotk_notify,
222 },
223};
224 163
225/* PCI hotplug ops */ 164 struct platform_device *platform_device;
226static int eeepc_get_adapter_status(struct hotplug_slot *slot, u8 *value); 165 struct device *hwmon_device;
166 struct backlight_device *backlight_device;
227 167
228static struct hotplug_slot_ops eeepc_hotplug_slot_ops = { 168 struct input_dev *inputdev;
229 .owner = THIS_MODULE, 169 struct key_entry *keymap;
230 .get_adapter_status = eeepc_get_adapter_status,
231 .get_power_status = eeepc_get_adapter_status,
232};
233 170
234/* The backlight device /sys/class/backlight */ 171 struct rfkill *wlan_rfkill;
235static struct backlight_device *eeepc_backlight_device; 172 struct rfkill *bluetooth_rfkill;
173 struct rfkill *wwan3g_rfkill;
174 struct rfkill *wimax_rfkill;
236 175
237/* The hwmon device */ 176 struct hotplug_slot *hotplug_slot;
238static struct device *eeepc_hwmon_device; 177 struct mutex hotplug_lock;
239 178
240/* 179 struct led_classdev tpd_led;
241 * The backlight class declaration 180 int tpd_led_wk;
242 */ 181 struct workqueue_struct *led_workqueue;
243static int read_brightness(struct backlight_device *bd); 182 struct work_struct tpd_led_work;
244static int update_bl_status(struct backlight_device *bd);
245static struct backlight_ops eeepcbl_ops = {
246 .get_brightness = read_brightness,
247 .update_status = update_bl_status,
248}; 183};
249 184
250MODULE_AUTHOR("Corentin Chary, Eric Cooper");
251MODULE_DESCRIPTION(EEEPC_HOTK_NAME);
252MODULE_LICENSE("GPL");
253
254/* 185/*
255 * ACPI Helpers 186 * ACPI Helpers
256 */ 187 */
257static int write_acpi_int(acpi_handle handle, const char *method, int val, 188static int write_acpi_int(acpi_handle handle, const char *method, int val)
258 struct acpi_buffer *output)
259{ 189{
260 struct acpi_object_list params; 190 struct acpi_object_list params;
261 union acpi_object in_obj; 191 union acpi_object in_obj;
@@ -266,7 +196,7 @@ static int write_acpi_int(acpi_handle handle, const char *method, int val,
266 in_obj.type = ACPI_TYPE_INTEGER; 196 in_obj.type = ACPI_TYPE_INTEGER;
267 in_obj.integer.value = val; 197 in_obj.integer.value = val;
268 198
269 status = acpi_evaluate_object(handle, (char *)method, &params, output); 199 status = acpi_evaluate_object(handle, (char *)method, &params, NULL);
270 return (status == AE_OK ? 0 : -1); 200 return (status == AE_OK ? 0 : -1);
271} 201}
272 202
@@ -285,81 +215,56 @@ static int read_acpi_int(acpi_handle handle, const char *method, int *val)
285 } 215 }
286} 216}
287 217
288static int set_acpi(int cm, int value) 218static int set_acpi(struct eeepc_laptop *eeepc, int cm, int value)
289{ 219{
290 if (ehotk->cm_supported & (0x1 << cm)) { 220 const char *method = cm_setv[cm];
291 const char *method = cm_setv[cm];
292 if (method == NULL)
293 return -ENODEV;
294 if (write_acpi_int(ehotk->handle, method, value, NULL))
295 pr_warning("Error writing %s\n", method);
296 }
297 return 0;
298}
299 221
300static int get_acpi(int cm) 222 if (method == NULL)
301{ 223 return -ENODEV;
302 int value = -ENODEV; 224 if ((eeepc->cm_supported & (0x1 << cm)) == 0)
303 if ((ehotk->cm_supported & (0x1 << cm))) { 225 return -ENODEV;
304 const char *method = cm_getv[cm];
305 if (method == NULL)
306 return -ENODEV;
307 if (read_acpi_int(ehotk->handle, method, &value))
308 pr_warning("Error reading %s\n", method);
309 }
310 return value;
311}
312
313/*
314 * Backlight
315 */
316static int read_brightness(struct backlight_device *bd)
317{
318 return get_acpi(CM_ASL_PANELBRIGHT);
319}
320 226
321static int set_brightness(struct backlight_device *bd, int value) 227 if (write_acpi_int(eeepc->handle, method, value))
322{ 228 pr_warning("Error writing %s\n", method);
323 value = max(0, min(15, value)); 229 return 0;
324 return set_acpi(CM_ASL_PANELBRIGHT, value);
325} 230}
326 231
327static int update_bl_status(struct backlight_device *bd) 232static int get_acpi(struct eeepc_laptop *eeepc, int cm)
328{ 233{
329 return set_brightness(bd, bd->props.brightness); 234 const char *method = cm_getv[cm];
330} 235 int value;
331 236
332/* 237 if (method == NULL)
333 * Rfkill helpers 238 return -ENODEV;
334 */ 239 if ((eeepc->cm_supported & (0x1 << cm)) == 0)
240 return -ENODEV;
335 241
336static bool eeepc_wlan_rfkill_blocked(void) 242 if (read_acpi_int(eeepc->handle, method, &value))
337{ 243 pr_warning("Error reading %s\n", method);
338 if (get_acpi(CM_ASL_WLAN) == 1) 244 return value;
339 return false;
340 return true;
341} 245}
342 246
343static int eeepc_rfkill_set(void *data, bool blocked) 247static int acpi_setter_handle(struct eeepc_laptop *eeepc, int cm,
248 acpi_handle *handle)
344{ 249{
345 unsigned long asl = (unsigned long)data; 250 const char *method = cm_setv[cm];
346 return set_acpi(asl, !blocked); 251 acpi_status status;
347}
348 252
349static const struct rfkill_ops eeepc_rfkill_ops = { 253 if (method == NULL)
350 .set_block = eeepc_rfkill_set, 254 return -ENODEV;
351}; 255 if ((eeepc->cm_supported & (0x1 << cm)) == 0)
256 return -ENODEV;
352 257
353static void __devinit eeepc_enable_camera(void) 258 status = acpi_get_handle(eeepc->handle, (char *)method,
354{ 259 handle);
355 /* 260 if (status != AE_OK) {
356 * If the following call to set_acpi() fails, it's because there's no 261 pr_warning("Error finding %s\n", method);
357 * camera so we can ignore the error. 262 return -ENODEV;
358 */ 263 }
359 if (get_acpi(CM_ASL_CAMERA) == 0) 264 return 0;
360 set_acpi(CM_ASL_CAMERA, 1);
361} 265}
362 266
267
363/* 268/*
364 * Sys helpers 269 * Sys helpers
365 */ 270 */
@@ -372,60 +277,63 @@ static int parse_arg(const char *buf, unsigned long count, int *val)
372 return count; 277 return count;
373} 278}
374 279
375static ssize_t store_sys_acpi(int cm, const char *buf, size_t count) 280static ssize_t store_sys_acpi(struct device *dev, int cm,
281 const char *buf, size_t count)
376{ 282{
283 struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
377 int rv, value; 284 int rv, value;
378 285
379 rv = parse_arg(buf, count, &value); 286 rv = parse_arg(buf, count, &value);
380 if (rv > 0) 287 if (rv > 0)
381 value = set_acpi(cm, value); 288 value = set_acpi(eeepc, cm, value);
382 if (value < 0) 289 if (value < 0)
383 return value; 290 return -EIO;
384 return rv; 291 return rv;
385} 292}
386 293
387static ssize_t show_sys_acpi(int cm, char *buf) 294static ssize_t show_sys_acpi(struct device *dev, int cm, char *buf)
388{ 295{
389 int value = get_acpi(cm); 296 struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
297 int value = get_acpi(eeepc, cm);
390 298
391 if (value < 0) 299 if (value < 0)
392 return value; 300 return -EIO;
393 return sprintf(buf, "%d\n", value); 301 return sprintf(buf, "%d\n", value);
394} 302}
395 303
396#define EEEPC_CREATE_DEVICE_ATTR(_name, _cm) \ 304#define EEEPC_CREATE_DEVICE_ATTR(_name, _mode, _cm) \
397 static ssize_t show_##_name(struct device *dev, \ 305 static ssize_t show_##_name(struct device *dev, \
398 struct device_attribute *attr, \ 306 struct device_attribute *attr, \
399 char *buf) \ 307 char *buf) \
400 { \ 308 { \
401 return show_sys_acpi(_cm, buf); \ 309 return show_sys_acpi(dev, _cm, buf); \
402 } \ 310 } \
403 static ssize_t store_##_name(struct device *dev, \ 311 static ssize_t store_##_name(struct device *dev, \
404 struct device_attribute *attr, \ 312 struct device_attribute *attr, \
405 const char *buf, size_t count) \ 313 const char *buf, size_t count) \
406 { \ 314 { \
407 return store_sys_acpi(_cm, buf, count); \ 315 return store_sys_acpi(dev, _cm, buf, count); \
408 } \ 316 } \
409 static struct device_attribute dev_attr_##_name = { \ 317 static struct device_attribute dev_attr_##_name = { \
410 .attr = { \ 318 .attr = { \
411 .name = __stringify(_name), \ 319 .name = __stringify(_name), \
412 .mode = 0644 }, \ 320 .mode = _mode }, \
413 .show = show_##_name, \ 321 .show = show_##_name, \
414 .store = store_##_name, \ 322 .store = store_##_name, \
415 } 323 }
416 324
417EEEPC_CREATE_DEVICE_ATTR(camera, CM_ASL_CAMERA); 325EEEPC_CREATE_DEVICE_ATTR(camera, 0644, CM_ASL_CAMERA);
418EEEPC_CREATE_DEVICE_ATTR(cardr, CM_ASL_CARDREADER); 326EEEPC_CREATE_DEVICE_ATTR(cardr, 0644, CM_ASL_CARDREADER);
419EEEPC_CREATE_DEVICE_ATTR(disp, CM_ASL_DISPLAYSWITCH); 327EEEPC_CREATE_DEVICE_ATTR(disp, 0200, CM_ASL_DISPLAYSWITCH);
420 328
421struct eeepc_cpufv { 329struct eeepc_cpufv {
422 int num; 330 int num;
423 int cur; 331 int cur;
424}; 332};
425 333
426static int get_cpufv(struct eeepc_cpufv *c) 334static int get_cpufv(struct eeepc_laptop *eeepc, struct eeepc_cpufv *c)
427{ 335{
428 c->cur = get_acpi(CM_ASL_CPUFV); 336 c->cur = get_acpi(eeepc, CM_ASL_CPUFV);
429 c->num = (c->cur >> 8) & 0xff; 337 c->num = (c->cur >> 8) & 0xff;
430 c->cur &= 0xff; 338 c->cur &= 0xff;
431 if (c->cur < 0 || c->num <= 0 || c->num > 12) 339 if (c->cur < 0 || c->num <= 0 || c->num > 12)
@@ -437,11 +345,12 @@ static ssize_t show_available_cpufv(struct device *dev,
437 struct device_attribute *attr, 345 struct device_attribute *attr,
438 char *buf) 346 char *buf)
439{ 347{
348 struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
440 struct eeepc_cpufv c; 349 struct eeepc_cpufv c;
441 int i; 350 int i;
442 ssize_t len = 0; 351 ssize_t len = 0;
443 352
444 if (get_cpufv(&c)) 353 if (get_cpufv(eeepc, &c))
445 return -ENODEV; 354 return -ENODEV;
446 for (i = 0; i < c.num; i++) 355 for (i = 0; i < c.num; i++)
447 len += sprintf(buf + len, "%d ", i); 356 len += sprintf(buf + len, "%d ", i);
@@ -453,9 +362,10 @@ static ssize_t show_cpufv(struct device *dev,
453 struct device_attribute *attr, 362 struct device_attribute *attr,
454 char *buf) 363 char *buf)
455{ 364{
365 struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
456 struct eeepc_cpufv c; 366 struct eeepc_cpufv c;
457 367
458 if (get_cpufv(&c)) 368 if (get_cpufv(eeepc, &c))
459 return -ENODEV; 369 return -ENODEV;
460 return sprintf(buf, "%#x\n", (c.num << 8) | c.cur); 370 return sprintf(buf, "%#x\n", (c.num << 8) | c.cur);
461} 371}
@@ -464,17 +374,18 @@ static ssize_t store_cpufv(struct device *dev,
464 struct device_attribute *attr, 374 struct device_attribute *attr,
465 const char *buf, size_t count) 375 const char *buf, size_t count)
466{ 376{
377 struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
467 struct eeepc_cpufv c; 378 struct eeepc_cpufv c;
468 int rv, value; 379 int rv, value;
469 380
470 if (get_cpufv(&c)) 381 if (get_cpufv(eeepc, &c))
471 return -ENODEV; 382 return -ENODEV;
472 rv = parse_arg(buf, count, &value); 383 rv = parse_arg(buf, count, &value);
473 if (rv < 0) 384 if (rv < 0)
474 return rv; 385 return rv;
475 if (!rv || value < 0 || value >= c.num) 386 if (!rv || value < 0 || value >= c.num)
476 return -EINVAL; 387 return -EINVAL;
477 set_acpi(CM_ASL_CPUFV, value); 388 set_acpi(eeepc, CM_ASL_CPUFV, value);
478 return rv; 389 return rv;
479} 390}
480 391
@@ -506,156 +417,125 @@ static struct attribute_group platform_attribute_group = {
506 .attrs = platform_attributes 417 .attrs = platform_attributes
507}; 418};
508 419
509/* 420static int eeepc_platform_init(struct eeepc_laptop *eeepc)
510 * Hotkey functions
511 */
512static struct key_entry *eepc_get_entry_by_scancode(int code)
513{ 421{
514 struct key_entry *key; 422 int result;
515
516 for (key = eeepc_keymap; key->type != KE_END; key++)
517 if (code == key->code)
518 return key;
519 423
520 return NULL; 424 eeepc->platform_device = platform_device_alloc(EEEPC_LAPTOP_FILE, -1);
521} 425 if (!eeepc->platform_device)
426 return -ENOMEM;
427 platform_set_drvdata(eeepc->platform_device, eeepc);
522 428
523static struct key_entry *eepc_get_entry_by_keycode(int code) 429 result = platform_device_add(eeepc->platform_device);
524{ 430 if (result)
525 struct key_entry *key; 431 goto fail_platform_device;
526 432
527 for (key = eeepc_keymap; key->type != KE_END; key++) 433 result = sysfs_create_group(&eeepc->platform_device->dev.kobj,
528 if (code == key->keycode && key->type == KE_KEY) 434 &platform_attribute_group);
529 return key; 435 if (result)
436 goto fail_sysfs;
437 return 0;
530 438
531 return NULL; 439fail_sysfs:
440 platform_device_del(eeepc->platform_device);
441fail_platform_device:
442 platform_device_put(eeepc->platform_device);
443 return result;
532} 444}
533 445
534static int eeepc_getkeycode(struct input_dev *dev, int scancode, int *keycode) 446static void eeepc_platform_exit(struct eeepc_laptop *eeepc)
535{ 447{
536 struct key_entry *key = eepc_get_entry_by_scancode(scancode); 448 sysfs_remove_group(&eeepc->platform_device->dev.kobj,
449 &platform_attribute_group);
450 platform_device_unregister(eeepc->platform_device);
451}
537 452
538 if (key && key->type == KE_KEY) { 453/*
539 *keycode = key->keycode; 454 * LEDs
540 return 0; 455 */
541 } 456/*
457 * These functions actually update the LED's, and are called from a
458 * workqueue. By doing this as separate work rather than when the LED
459 * subsystem asks, we avoid messing with the Asus ACPI stuff during a
460 * potentially bad time, such as a timer interrupt.
461 */
462static void tpd_led_update(struct work_struct *work)
463 {
464 struct eeepc_laptop *eeepc;
542 465
543 return -EINVAL; 466 eeepc = container_of(work, struct eeepc_laptop, tpd_led_work);
467
468 set_acpi(eeepc, CM_ASL_TPD, eeepc->tpd_led_wk);
544} 469}
545 470
546static int eeepc_setkeycode(struct input_dev *dev, int scancode, int keycode) 471static void tpd_led_set(struct led_classdev *led_cdev,
472 enum led_brightness value)
547{ 473{
548 struct key_entry *key; 474 struct eeepc_laptop *eeepc;
549 int old_keycode;
550 475
551 if (keycode < 0 || keycode > KEY_MAX) 476 eeepc = container_of(led_cdev, struct eeepc_laptop, tpd_led);
552 return -EINVAL;
553 477
554 key = eepc_get_entry_by_scancode(scancode); 478 eeepc->tpd_led_wk = (value > 0) ? 1 : 0;
555 if (key && key->type == KE_KEY) { 479 queue_work(eeepc->led_workqueue, &eeepc->tpd_led_work);
556 old_keycode = key->keycode;
557 key->keycode = keycode;
558 set_bit(keycode, dev->keybit);
559 if (!eepc_get_entry_by_keycode(old_keycode))
560 clear_bit(old_keycode, dev->keybit);
561 return 0;
562 }
563
564 return -EINVAL;
565} 480}
566 481
567static void cmsg_quirk(int cm, const char *name) 482static int eeepc_led_init(struct eeepc_laptop *eeepc)
568{ 483{
569 int dummy; 484 int rv;
570 485
571 /* Some BIOSes do not report cm although it is avaliable. 486 if (get_acpi(eeepc, CM_ASL_TPD) == -ENODEV)
572 Check if cm_getv[cm] works and, if yes, assume cm should be set. */ 487 return 0;
573 if (!(ehotk->cm_supported & (1 << cm))
574 && !read_acpi_int(ehotk->handle, cm_getv[cm], &dummy)) {
575 pr_info("%s (%x) not reported by BIOS,"
576 " enabling anyway\n", name, 1 << cm);
577 ehotk->cm_supported |= 1 << cm;
578 }
579}
580 488
581static void cmsg_quirks(void) 489 eeepc->led_workqueue = create_singlethread_workqueue("led_workqueue");
582{ 490 if (!eeepc->led_workqueue)
583 cmsg_quirk(CM_ASL_LID, "LID"); 491 return -ENOMEM;
584 cmsg_quirk(CM_ASL_TYPE, "TYPE"); 492 INIT_WORK(&eeepc->tpd_led_work, tpd_led_update);
585 cmsg_quirk(CM_ASL_PANELPOWER, "PANELPOWER");
586 cmsg_quirk(CM_ASL_TPD, "TPD");
587}
588 493
589static int eeepc_hotk_check(void) 494 eeepc->tpd_led.name = "eeepc::touchpad";
590{ 495 eeepc->tpd_led.brightness_set = tpd_led_set;
591 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 496 eeepc->tpd_led.max_brightness = 1;
592 int result;
593 497
594 result = acpi_bus_get_status(ehotk->device); 498 rv = led_classdev_register(&eeepc->platform_device->dev,
595 if (result) 499 &eeepc->tpd_led);
596 return result; 500 if (rv) {
597 if (ehotk->device->status.present) { 501 destroy_workqueue(eeepc->led_workqueue);
598 if (write_acpi_int(ehotk->handle, "INIT", ehotk->init_flag, 502 return rv;
599 &buffer)) {
600 pr_err("Hotkey initialization failed\n");
601 return -ENODEV;
602 } else {
603 pr_notice("Hotkey init flags 0x%x\n", ehotk->init_flag);
604 }
605 /* get control methods supported */
606 if (read_acpi_int(ehotk->handle, "CMSG"
607 , &ehotk->cm_supported)) {
608 pr_err("Get control methods supported failed\n");
609 return -ENODEV;
610 } else {
611 cmsg_quirks();
612 pr_info("Get control methods supported: 0x%x\n",
613 ehotk->cm_supported);
614 }
615 } else {
616 pr_err("Hotkey device not present, aborting\n");
617 return -EINVAL;
618 } 503 }
504
619 return 0; 505 return 0;
620} 506}
621 507
622static int notify_brn(void) 508static void eeepc_led_exit(struct eeepc_laptop *eeepc)
623{ 509{
624 /* returns the *previous* brightness, or -1 */ 510 if (eeepc->tpd_led.dev)
625 struct backlight_device *bd = eeepc_backlight_device; 511 led_classdev_unregister(&eeepc->tpd_led);
626 if (bd) { 512 if (eeepc->led_workqueue)
627 int old = bd->props.brightness; 513 destroy_workqueue(eeepc->led_workqueue);
628 backlight_force_update(bd, BACKLIGHT_UPDATE_HOTKEY);
629 return old;
630 }
631 return -1;
632} 514}
633 515
634static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot,
635 u8 *value)
636{
637 int val = get_acpi(CM_ASL_WLAN);
638 516
639 if (val == 1 || val == 0) 517/*
640 *value = val; 518 * PCI hotplug (for wlan rfkill)
641 else 519 */
642 return -EINVAL; 520static bool eeepc_wlan_rfkill_blocked(struct eeepc_laptop *eeepc)
643 521{
644 return 0; 522 if (get_acpi(eeepc, CM_ASL_WLAN) == 1)
523 return false;
524 return true;
645} 525}
646 526
647static void eeepc_rfkill_hotplug(void) 527static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc)
648{ 528{
649 struct pci_dev *dev; 529 struct pci_dev *dev;
650 struct pci_bus *bus; 530 struct pci_bus *bus;
651 bool blocked = eeepc_wlan_rfkill_blocked(); 531 bool blocked = eeepc_wlan_rfkill_blocked(eeepc);
652 532
653 if (ehotk->wlan_rfkill) 533 if (eeepc->wlan_rfkill)
654 rfkill_set_sw_state(ehotk->wlan_rfkill, blocked); 534 rfkill_set_sw_state(eeepc->wlan_rfkill, blocked);
655 535
656 mutex_lock(&ehotk->hotplug_lock); 536 mutex_lock(&eeepc->hotplug_lock);
657 537
658 if (ehotk->hotplug_slot) { 538 if (eeepc->hotplug_slot) {
659 bus = pci_find_bus(0, 1); 539 bus = pci_find_bus(0, 1);
660 if (!bus) { 540 if (!bus) {
661 pr_warning("Unable to find PCI bus 1?\n"); 541 pr_warning("Unable to find PCI bus 1?\n");
@@ -685,69 +565,23 @@ static void eeepc_rfkill_hotplug(void)
685 } 565 }
686 566
687out_unlock: 567out_unlock:
688 mutex_unlock(&ehotk->hotplug_lock); 568 mutex_unlock(&eeepc->hotplug_lock);
689} 569}
690 570
691static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) 571static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
692{ 572{
573 struct eeepc_laptop *eeepc = data;
574
693 if (event != ACPI_NOTIFY_BUS_CHECK) 575 if (event != ACPI_NOTIFY_BUS_CHECK)
694 return; 576 return;
695 577
696 eeepc_rfkill_hotplug(); 578 eeepc_rfkill_hotplug(eeepc);
697} 579}
698 580
699static void eeepc_hotk_notify(struct acpi_device *device, u32 event) 581static int eeepc_register_rfkill_notifier(struct eeepc_laptop *eeepc,
582 char *node)
700{ 583{
701 static struct key_entry *key; 584 acpi_status status;
702 u16 count;
703 int brn = -ENODEV;
704
705 if (!ehotk)
706 return;
707 if (event > ACPI_MAX_SYS_NOTIFY)
708 return;
709 if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX)
710 brn = notify_brn();
711 count = ehotk->event_count[event % 128]++;
712 acpi_bus_generate_proc_event(ehotk->device, event, count);
713 acpi_bus_generate_netlink_event(ehotk->device->pnp.device_class,
714 dev_name(&ehotk->device->dev), event,
715 count);
716 if (ehotk->inputdev) {
717 if (brn != -ENODEV) {
718 /* brightness-change events need special
719 * handling for conversion to key events
720 */
721 if (brn < 0)
722 brn = event;
723 else
724 brn += NOTIFY_BRN_MIN;
725 if (event < brn)
726 event = NOTIFY_BRN_MIN; /* brightness down */
727 else if (event > brn)
728 event = NOTIFY_BRN_MIN + 2; /* ... up */
729 else
730 event = NOTIFY_BRN_MIN + 1; /* ... unchanged */
731 }
732 key = eepc_get_entry_by_scancode(event);
733 if (key) {
734 switch (key->type) {
735 case KE_KEY:
736 input_report_key(ehotk->inputdev, key->keycode,
737 1);
738 input_sync(ehotk->inputdev);
739 input_report_key(ehotk->inputdev, key->keycode,
740 0);
741 input_sync(ehotk->inputdev);
742 break;
743 }
744 }
745 }
746}
747
748static int eeepc_register_rfkill_notifier(char *node)
749{
750 acpi_status status = AE_OK;
751 acpi_handle handle; 585 acpi_handle handle;
752 586
753 status = acpi_get_handle(NULL, node, &handle); 587 status = acpi_get_handle(NULL, node, &handle);
@@ -756,7 +590,7 @@ static int eeepc_register_rfkill_notifier(char *node)
756 status = acpi_install_notify_handler(handle, 590 status = acpi_install_notify_handler(handle,
757 ACPI_SYSTEM_NOTIFY, 591 ACPI_SYSTEM_NOTIFY,
758 eeepc_rfkill_notify, 592 eeepc_rfkill_notify,
759 NULL); 593 eeepc);
760 if (ACPI_FAILURE(status)) 594 if (ACPI_FAILURE(status))
761 pr_warning("Failed to register notify on %s\n", node); 595 pr_warning("Failed to register notify on %s\n", node);
762 } else 596 } else
@@ -765,7 +599,8 @@ static int eeepc_register_rfkill_notifier(char *node)
765 return 0; 599 return 0;
766} 600}
767 601
768static void eeepc_unregister_rfkill_notifier(char *node) 602static void eeepc_unregister_rfkill_notifier(struct eeepc_laptop *eeepc,
603 char *node)
769{ 604{
770 acpi_status status = AE_OK; 605 acpi_status status = AE_OK;
771 acpi_handle handle; 606 acpi_handle handle;
@@ -782,13 +617,33 @@ static void eeepc_unregister_rfkill_notifier(char *node)
782 } 617 }
783} 618}
784 619
620static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot,
621 u8 *value)
622{
623 struct eeepc_laptop *eeepc = hotplug_slot->private;
624 int val = get_acpi(eeepc, CM_ASL_WLAN);
625
626 if (val == 1 || val == 0)
627 *value = val;
628 else
629 return -EINVAL;
630
631 return 0;
632}
633
785static void eeepc_cleanup_pci_hotplug(struct hotplug_slot *hotplug_slot) 634static void eeepc_cleanup_pci_hotplug(struct hotplug_slot *hotplug_slot)
786{ 635{
787 kfree(hotplug_slot->info); 636 kfree(hotplug_slot->info);
788 kfree(hotplug_slot); 637 kfree(hotplug_slot);
789} 638}
790 639
791static int eeepc_setup_pci_hotplug(void) 640static struct hotplug_slot_ops eeepc_hotplug_slot_ops = {
641 .owner = THIS_MODULE,
642 .get_adapter_status = eeepc_get_adapter_status,
643 .get_power_status = eeepc_get_adapter_status,
644};
645
646static int eeepc_setup_pci_hotplug(struct eeepc_laptop *eeepc)
792{ 647{
793 int ret = -ENOMEM; 648 int ret = -ENOMEM;
794 struct pci_bus *bus = pci_find_bus(0, 1); 649 struct pci_bus *bus = pci_find_bus(0, 1);
@@ -798,22 +653,22 @@ static int eeepc_setup_pci_hotplug(void)
798 return -ENODEV; 653 return -ENODEV;
799 } 654 }
800 655
801 ehotk->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL); 656 eeepc->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
802 if (!ehotk->hotplug_slot) 657 if (!eeepc->hotplug_slot)
803 goto error_slot; 658 goto error_slot;
804 659
805 ehotk->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info), 660 eeepc->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info),
806 GFP_KERNEL); 661 GFP_KERNEL);
807 if (!ehotk->hotplug_slot->info) 662 if (!eeepc->hotplug_slot->info)
808 goto error_info; 663 goto error_info;
809 664
810 ehotk->hotplug_slot->private = ehotk; 665 eeepc->hotplug_slot->private = eeepc;
811 ehotk->hotplug_slot->release = &eeepc_cleanup_pci_hotplug; 666 eeepc->hotplug_slot->release = &eeepc_cleanup_pci_hotplug;
812 ehotk->hotplug_slot->ops = &eeepc_hotplug_slot_ops; 667 eeepc->hotplug_slot->ops = &eeepc_hotplug_slot_ops;
813 eeepc_get_adapter_status(ehotk->hotplug_slot, 668 eeepc_get_adapter_status(eeepc->hotplug_slot,
814 &ehotk->hotplug_slot->info->adapter_status); 669 &eeepc->hotplug_slot->info->adapter_status);
815 670
816 ret = pci_hp_register(ehotk->hotplug_slot, bus, 0, "eeepc-wifi"); 671 ret = pci_hp_register(eeepc->hotplug_slot, bus, 0, "eeepc-wifi");
817 if (ret) { 672 if (ret) {
818 pr_err("Unable to register hotplug slot - %d\n", ret); 673 pr_err("Unable to register hotplug slot - %d\n", ret);
819 goto error_register; 674 goto error_register;
@@ -822,17 +677,156 @@ static int eeepc_setup_pci_hotplug(void)
822 return 0; 677 return 0;
823 678
824error_register: 679error_register:
825 kfree(ehotk->hotplug_slot->info); 680 kfree(eeepc->hotplug_slot->info);
826error_info: 681error_info:
827 kfree(ehotk->hotplug_slot); 682 kfree(eeepc->hotplug_slot);
828 ehotk->hotplug_slot = NULL; 683 eeepc->hotplug_slot = NULL;
829error_slot: 684error_slot:
830 return ret; 685 return ret;
831} 686}
832 687
688/*
689 * Rfkill devices
690 */
691static int eeepc_rfkill_set(void *data, bool blocked)
692{
693 acpi_handle handle = data;
694
695 return write_acpi_int(handle, NULL, !blocked);
696}
697
698static const struct rfkill_ops eeepc_rfkill_ops = {
699 .set_block = eeepc_rfkill_set,
700};
701
702static int eeepc_new_rfkill(struct eeepc_laptop *eeepc,
703 struct rfkill **rfkill,
704 const char *name,
705 enum rfkill_type type, int cm)
706{
707 acpi_handle handle;
708 int result;
709
710 result = acpi_setter_handle(eeepc, cm, &handle);
711 if (result < 0)
712 return result;
713
714 *rfkill = rfkill_alloc(name, &eeepc->platform_device->dev, type,
715 &eeepc_rfkill_ops, handle);
716
717 if (!*rfkill)
718 return -EINVAL;
719
720 rfkill_init_sw_state(*rfkill, get_acpi(eeepc, cm) != 1);
721 result = rfkill_register(*rfkill);
722 if (result) {
723 rfkill_destroy(*rfkill);
724 *rfkill = NULL;
725 return result;
726 }
727 return 0;
728}
729
730static void eeepc_rfkill_exit(struct eeepc_laptop *eeepc)
731{
732 eeepc_unregister_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P5");
733 eeepc_unregister_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P6");
734 eeepc_unregister_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P7");
735 if (eeepc->wlan_rfkill) {
736 rfkill_unregister(eeepc->wlan_rfkill);
737 rfkill_destroy(eeepc->wlan_rfkill);
738 eeepc->wlan_rfkill = NULL;
739 }
740 /*
741 * Refresh pci hotplug in case the rfkill state was changed after
742 * eeepc_unregister_rfkill_notifier()
743 */
744 eeepc_rfkill_hotplug(eeepc);
745 if (eeepc->hotplug_slot)
746 pci_hp_deregister(eeepc->hotplug_slot);
747
748 if (eeepc->bluetooth_rfkill) {
749 rfkill_unregister(eeepc->bluetooth_rfkill);
750 rfkill_destroy(eeepc->bluetooth_rfkill);
751 eeepc->bluetooth_rfkill = NULL;
752 }
753 if (eeepc->wwan3g_rfkill) {
754 rfkill_unregister(eeepc->wwan3g_rfkill);
755 rfkill_destroy(eeepc->wwan3g_rfkill);
756 eeepc->wwan3g_rfkill = NULL;
757 }
758 if (eeepc->wimax_rfkill) {
759 rfkill_unregister(eeepc->wimax_rfkill);
760 rfkill_destroy(eeepc->wimax_rfkill);
761 eeepc->wimax_rfkill = NULL;
762 }
763}
764
765static int eeepc_rfkill_init(struct eeepc_laptop *eeepc)
766{
767 int result = 0;
768
769 mutex_init(&eeepc->hotplug_lock);
770
771 result = eeepc_new_rfkill(eeepc, &eeepc->wlan_rfkill,
772 "eeepc-wlan", RFKILL_TYPE_WLAN,
773 CM_ASL_WLAN);
774
775 if (result && result != -ENODEV)
776 goto exit;
777
778 result = eeepc_new_rfkill(eeepc, &eeepc->bluetooth_rfkill,
779 "eeepc-bluetooth", RFKILL_TYPE_BLUETOOTH,
780 CM_ASL_BLUETOOTH);
781
782 if (result && result != -ENODEV)
783 goto exit;
784
785 result = eeepc_new_rfkill(eeepc, &eeepc->wwan3g_rfkill,
786 "eeepc-wwan3g", RFKILL_TYPE_WWAN,
787 CM_ASL_3G);
788
789 if (result && result != -ENODEV)
790 goto exit;
791
792 result = eeepc_new_rfkill(eeepc, &eeepc->wimax_rfkill,
793 "eeepc-wimax", RFKILL_TYPE_WIMAX,
794 CM_ASL_WIMAX);
795
796 if (result && result != -ENODEV)
797 goto exit;
798
799 result = eeepc_setup_pci_hotplug(eeepc);
800 /*
801 * If we get -EBUSY then something else is handling the PCI hotplug -
802 * don't fail in this case
803 */
804 if (result == -EBUSY)
805 result = 0;
806
807 eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P5");
808 eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P6");
809 eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P7");
810 /*
811 * Refresh pci hotplug in case the rfkill state was changed during
812 * setup.
813 */
814 eeepc_rfkill_hotplug(eeepc);
815
816exit:
817 if (result && result != -ENODEV)
818 eeepc_rfkill_exit(eeepc);
819 return result;
820}
821
822/*
823 * Platform driver - hibernate/resume callbacks
824 */
833static int eeepc_hotk_thaw(struct device *device) 825static int eeepc_hotk_thaw(struct device *device)
834{ 826{
835 if (ehotk->wlan_rfkill) { 827 struct eeepc_laptop *eeepc = dev_get_drvdata(device);
828
829 if (eeepc->wlan_rfkill) {
836 bool wlan; 830 bool wlan;
837 831
838 /* 832 /*
@@ -840,8 +834,8 @@ static int eeepc_hotk_thaw(struct device *device)
840 * during suspend. Normally it restores it on resume, but 834 * during suspend. Normally it restores it on resume, but
841 * we should kick it ourselves in case hibernation is aborted. 835 * we should kick it ourselves in case hibernation is aborted.
842 */ 836 */
843 wlan = get_acpi(CM_ASL_WLAN); 837 wlan = get_acpi(eeepc, CM_ASL_WLAN);
844 set_acpi(CM_ASL_WLAN, wlan); 838 set_acpi(eeepc, CM_ASL_WLAN, wlan);
845 } 839 }
846 840
847 return 0; 841 return 0;
@@ -849,70 +843,96 @@ static int eeepc_hotk_thaw(struct device *device)
849 843
850static int eeepc_hotk_restore(struct device *device) 844static int eeepc_hotk_restore(struct device *device)
851{ 845{
846 struct eeepc_laptop *eeepc = dev_get_drvdata(device);
847
852 /* Refresh both wlan rfkill state and pci hotplug */ 848 /* Refresh both wlan rfkill state and pci hotplug */
853 if (ehotk->wlan_rfkill) 849 if (eeepc->wlan_rfkill)
854 eeepc_rfkill_hotplug(); 850 eeepc_rfkill_hotplug(eeepc);
855 851
856 if (ehotk->bluetooth_rfkill) 852 if (eeepc->bluetooth_rfkill)
857 rfkill_set_sw_state(ehotk->bluetooth_rfkill, 853 rfkill_set_sw_state(eeepc->bluetooth_rfkill,
858 get_acpi(CM_ASL_BLUETOOTH) != 1); 854 get_acpi(eeepc, CM_ASL_BLUETOOTH) != 1);
859 if (ehotk->wwan3g_rfkill) 855 if (eeepc->wwan3g_rfkill)
860 rfkill_set_sw_state(ehotk->wwan3g_rfkill, 856 rfkill_set_sw_state(eeepc->wwan3g_rfkill,
861 get_acpi(CM_ASL_3G) != 1); 857 get_acpi(eeepc, CM_ASL_3G) != 1);
862 if (ehotk->wimax_rfkill) 858 if (eeepc->wimax_rfkill)
863 rfkill_set_sw_state(ehotk->wimax_rfkill, 859 rfkill_set_sw_state(eeepc->wimax_rfkill,
864 get_acpi(CM_ASL_WIMAX) != 1); 860 get_acpi(eeepc, CM_ASL_WIMAX) != 1);
865 861
866 return 0; 862 return 0;
867} 863}
868 864
865static const struct dev_pm_ops eeepc_pm_ops = {
866 .thaw = eeepc_hotk_thaw,
867 .restore = eeepc_hotk_restore,
868};
869
870static struct platform_driver platform_driver = {
871 .driver = {
872 .name = EEEPC_LAPTOP_FILE,
873 .owner = THIS_MODULE,
874 .pm = &eeepc_pm_ops,
875 }
876};
877
869/* 878/*
870 * Hwmon 879 * Hwmon device
871 */ 880 */
881
882#define EEEPC_EC_SC00 0x61
883#define EEEPC_EC_FAN_PWM (EEEPC_EC_SC00 + 2) /* Fan PWM duty cycle (%) */
884#define EEEPC_EC_FAN_HRPM (EEEPC_EC_SC00 + 5) /* High byte, fan speed (RPM) */
885#define EEEPC_EC_FAN_LRPM (EEEPC_EC_SC00 + 6) /* Low byte, fan speed (RPM) */
886
887#define EEEPC_EC_SFB0 0xD0
888#define EEEPC_EC_FAN_CTRL (EEEPC_EC_SFB0 + 3) /* Byte containing SF25 */
889
872static int eeepc_get_fan_pwm(void) 890static int eeepc_get_fan_pwm(void)
873{ 891{
874 int value = 0; 892 u8 value = 0;
875 893
876 read_acpi_int(NULL, EEEPC_EC_FAN_PWM, &value); 894 ec_read(EEEPC_EC_FAN_PWM, &value);
877 value = value * 255 / 100; 895 return value * 255 / 100;
878 return (value);
879} 896}
880 897
881static void eeepc_set_fan_pwm(int value) 898static void eeepc_set_fan_pwm(int value)
882{ 899{
883 value = SENSORS_LIMIT(value, 0, 255); 900 value = SENSORS_LIMIT(value, 0, 255);
884 value = value * 100 / 255; 901 value = value * 100 / 255;
885 ec_write(EEEPC_EC_SC02, value); 902 ec_write(EEEPC_EC_FAN_PWM, value);
886} 903}
887 904
888static int eeepc_get_fan_rpm(void) 905static int eeepc_get_fan_rpm(void)
889{ 906{
890 int high = 0; 907 u8 high = 0;
891 int low = 0; 908 u8 low = 0;
892 909
893 read_acpi_int(NULL, EEEPC_EC_FAN_HRPM, &high); 910 ec_read(EEEPC_EC_FAN_HRPM, &high);
894 read_acpi_int(NULL, EEEPC_EC_FAN_LRPM, &low); 911 ec_read(EEEPC_EC_FAN_LRPM, &low);
895 return (high << 8 | low); 912 return high << 8 | low;
896} 913}
897 914
898static int eeepc_get_fan_ctrl(void) 915static int eeepc_get_fan_ctrl(void)
899{ 916{
900 int value = 0; 917 u8 value = 0;
901 918
902 read_acpi_int(NULL, EEEPC_EC_FAN_CTRL, &value); 919 ec_read(EEEPC_EC_FAN_CTRL, &value);
903 return ((value & 0x02 ? 1 : 0)); 920 if (value & 0x02)
921 return 1; /* manual */
922 else
923 return 2; /* automatic */
904} 924}
905 925
906static void eeepc_set_fan_ctrl(int manual) 926static void eeepc_set_fan_ctrl(int manual)
907{ 927{
908 int value = 0; 928 u8 value = 0;
909 929
910 read_acpi_int(NULL, EEEPC_EC_FAN_CTRL, &value); 930 ec_read(EEEPC_EC_FAN_CTRL, &value);
911 if (manual) 931 if (manual == 1)
912 value |= 0x02; 932 value |= 0x02;
913 else 933 else
914 value &= ~0x02; 934 value &= ~0x02;
915 ec_write(EEEPC_EC_SFB3, value); 935 ec_write(EEEPC_EC_FAN_CTRL, value);
916} 936}
917 937
918static ssize_t store_sys_hwmon(void (*set)(int), const char *buf, size_t count) 938static ssize_t store_sys_hwmon(void (*set)(int), const char *buf, size_t count)
@@ -970,348 +990,485 @@ static struct attribute_group hwmon_attribute_group = {
970 .attrs = hwmon_attributes 990 .attrs = hwmon_attributes
971}; 991};
972 992
973/* 993static void eeepc_hwmon_exit(struct eeepc_laptop *eeepc)
974 * exit/init
975 */
976static void eeepc_backlight_exit(void)
977{ 994{
978 if (eeepc_backlight_device) 995 struct device *hwmon;
979 backlight_device_unregister(eeepc_backlight_device); 996
980 eeepc_backlight_device = NULL; 997 hwmon = eeepc->hwmon_device;
998 if (!hwmon)
999 return;
1000 sysfs_remove_group(&hwmon->kobj,
1001 &hwmon_attribute_group);
1002 hwmon_device_unregister(hwmon);
1003 eeepc->hwmon_device = NULL;
981} 1004}
982 1005
983static void eeepc_rfkill_exit(void) 1006static int eeepc_hwmon_init(struct eeepc_laptop *eeepc)
984{ 1007{
985 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P5"); 1008 struct device *hwmon;
986 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6"); 1009 int result;
987 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7"); 1010
988 if (ehotk->wlan_rfkill) { 1011 hwmon = hwmon_device_register(&eeepc->platform_device->dev);
989 rfkill_unregister(ehotk->wlan_rfkill); 1012 if (IS_ERR(hwmon)) {
990 rfkill_destroy(ehotk->wlan_rfkill); 1013 pr_err("Could not register eeepc hwmon device\n");
991 ehotk->wlan_rfkill = NULL; 1014 eeepc->hwmon_device = NULL;
992 } 1015 return PTR_ERR(hwmon);
993 /*
994 * Refresh pci hotplug in case the rfkill state was changed after
995 * eeepc_unregister_rfkill_notifier()
996 */
997 eeepc_rfkill_hotplug();
998 if (ehotk->hotplug_slot)
999 pci_hp_deregister(ehotk->hotplug_slot);
1000
1001 if (ehotk->bluetooth_rfkill) {
1002 rfkill_unregister(ehotk->bluetooth_rfkill);
1003 rfkill_destroy(ehotk->bluetooth_rfkill);
1004 ehotk->bluetooth_rfkill = NULL;
1005 }
1006 if (ehotk->wwan3g_rfkill) {
1007 rfkill_unregister(ehotk->wwan3g_rfkill);
1008 rfkill_destroy(ehotk->wwan3g_rfkill);
1009 ehotk->wwan3g_rfkill = NULL;
1010 }
1011 if (ehotk->wimax_rfkill) {
1012 rfkill_unregister(ehotk->wimax_rfkill);
1013 rfkill_destroy(ehotk->wimax_rfkill);
1014 ehotk->wimax_rfkill = NULL;
1015 } 1016 }
1017 eeepc->hwmon_device = hwmon;
1018 result = sysfs_create_group(&hwmon->kobj,
1019 &hwmon_attribute_group);
1020 if (result)
1021 eeepc_hwmon_exit(eeepc);
1022 return result;
1016} 1023}
1017 1024
1018static void eeepc_input_exit(void) 1025/*
1026 * Backlight device
1027 */
1028static int read_brightness(struct backlight_device *bd)
1019{ 1029{
1020 if (ehotk->inputdev) 1030 struct eeepc_laptop *eeepc = bl_get_data(bd);
1021 input_unregister_device(ehotk->inputdev); 1031
1032 return get_acpi(eeepc, CM_ASL_PANELBRIGHT);
1022} 1033}
1023 1034
1024static void eeepc_hwmon_exit(void) 1035static int set_brightness(struct backlight_device *bd, int value)
1025{ 1036{
1026 struct device *hwmon; 1037 struct eeepc_laptop *eeepc = bl_get_data(bd);
1027 1038
1028 hwmon = eeepc_hwmon_device; 1039 return set_acpi(eeepc, CM_ASL_PANELBRIGHT, value);
1029 if (!hwmon)
1030 return ;
1031 sysfs_remove_group(&hwmon->kobj,
1032 &hwmon_attribute_group);
1033 hwmon_device_unregister(hwmon);
1034 eeepc_hwmon_device = NULL;
1035} 1040}
1036 1041
1037static int eeepc_new_rfkill(struct rfkill **rfkill, 1042static int update_bl_status(struct backlight_device *bd)
1038 const char *name, struct device *dev,
1039 enum rfkill_type type, int cm)
1040{ 1043{
1041 int result; 1044 return set_brightness(bd, bd->props.brightness);
1045}
1042 1046
1043 result = get_acpi(cm); 1047static struct backlight_ops eeepcbl_ops = {
1044 if (result < 0) 1048 .get_brightness = read_brightness,
1045 return result; 1049 .update_status = update_bl_status,
1050};
1046 1051
1047 *rfkill = rfkill_alloc(name, dev, type, 1052static int eeepc_backlight_notify(struct eeepc_laptop *eeepc)
1048 &eeepc_rfkill_ops, (void *)(unsigned long)cm); 1053{
1054 struct backlight_device *bd = eeepc->backlight_device;
1055 int old = bd->props.brightness;
1049 1056
1050 if (!*rfkill) 1057 backlight_force_update(bd, BACKLIGHT_UPDATE_HOTKEY);
1051 return -EINVAL;
1052 1058
1053 rfkill_init_sw_state(*rfkill, get_acpi(cm) != 1); 1059 return old;
1054 result = rfkill_register(*rfkill);
1055 if (result) {
1056 rfkill_destroy(*rfkill);
1057 *rfkill = NULL;
1058 return result;
1059 }
1060 return 0;
1061} 1060}
1062 1061
1063 1062static int eeepc_backlight_init(struct eeepc_laptop *eeepc)
1064static int eeepc_rfkill_init(struct device *dev)
1065{ 1063{
1066 int result = 0; 1064 struct backlight_device *bd;
1067
1068 mutex_init(&ehotk->hotplug_lock);
1069 1065
1070 result = eeepc_new_rfkill(&ehotk->wlan_rfkill, 1066 bd = backlight_device_register(EEEPC_LAPTOP_FILE,
1071 "eeepc-wlan", dev, 1067 &eeepc->platform_device->dev,
1072 RFKILL_TYPE_WLAN, CM_ASL_WLAN); 1068 eeepc, &eeepcbl_ops);
1069 if (IS_ERR(bd)) {
1070 pr_err("Could not register eeepc backlight device\n");
1071 eeepc->backlight_device = NULL;
1072 return PTR_ERR(bd);
1073 }
1074 eeepc->backlight_device = bd;
1075 bd->props.max_brightness = 15;
1076 bd->props.brightness = read_brightness(bd);
1077 bd->props.power = FB_BLANK_UNBLANK;
1078 backlight_update_status(bd);
1079 return 0;
1080}
1073 1081
1074 if (result && result != -ENODEV) 1082static void eeepc_backlight_exit(struct eeepc_laptop *eeepc)
1075 goto exit; 1083{
1084 if (eeepc->backlight_device)
1085 backlight_device_unregister(eeepc->backlight_device);
1086 eeepc->backlight_device = NULL;
1087}
1076 1088
1077 result = eeepc_new_rfkill(&ehotk->bluetooth_rfkill,
1078 "eeepc-bluetooth", dev,
1079 RFKILL_TYPE_BLUETOOTH, CM_ASL_BLUETOOTH);
1080 1089
1081 if (result && result != -ENODEV) 1090/*
1082 goto exit; 1091 * Input device (i.e. hotkeys)
1092 */
1093static struct key_entry *eeepc_get_entry_by_scancode(
1094 struct eeepc_laptop *eeepc,
1095 int code)
1096{
1097 struct key_entry *key;
1083 1098
1084 result = eeepc_new_rfkill(&ehotk->wwan3g_rfkill, 1099 for (key = eeepc->keymap; key->type != KE_END; key++)
1085 "eeepc-wwan3g", dev, 1100 if (code == key->code)
1086 RFKILL_TYPE_WWAN, CM_ASL_3G); 1101 return key;
1087 1102
1088 if (result && result != -ENODEV) 1103 return NULL;
1089 goto exit; 1104}
1090 1105
1091 result = eeepc_new_rfkill(&ehotk->wimax_rfkill, 1106static void eeepc_input_notify(struct eeepc_laptop *eeepc, int event)
1092 "eeepc-wimax", dev, 1107{
1093 RFKILL_TYPE_WIMAX, CM_ASL_WIMAX); 1108 static struct key_entry *key;
1094 1109
1095 if (result && result != -ENODEV) 1110 key = eeepc_get_entry_by_scancode(eeepc, event);
1096 goto exit; 1111 if (key) {
1112 switch (key->type) {
1113 case KE_KEY:
1114 input_report_key(eeepc->inputdev, key->keycode,
1115 1);
1116 input_sync(eeepc->inputdev);
1117 input_report_key(eeepc->inputdev, key->keycode,
1118 0);
1119 input_sync(eeepc->inputdev);
1120 break;
1121 }
1122 }
1123}
1097 1124
1098 result = eeepc_setup_pci_hotplug(); 1125static struct key_entry *eeepc_get_entry_by_keycode(
1099 /* 1126 struct eeepc_laptop *eeepc, int code)
1100 * If we get -EBUSY then something else is handling the PCI hotplug - 1127{
1101 * don't fail in this case 1128 struct key_entry *key;
1102 */
1103 if (result == -EBUSY)
1104 result = 0;
1105 1129
1106 eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P5"); 1130 for (key = eeepc->keymap; key->type != KE_END; key++)
1107 eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6"); 1131 if (code == key->keycode && key->type == KE_KEY)
1108 eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7"); 1132 return key;
1109 /*
1110 * Refresh pci hotplug in case the rfkill state was changed during
1111 * setup.
1112 */
1113 eeepc_rfkill_hotplug();
1114 1133
1115exit: 1134 return NULL;
1116 if (result && result != -ENODEV)
1117 eeepc_rfkill_exit();
1118 return result;
1119} 1135}
1120 1136
1121static int eeepc_backlight_init(struct device *dev) 1137static int eeepc_getkeycode(struct input_dev *dev, int scancode, int *keycode)
1122{ 1138{
1123 struct backlight_device *bd; 1139 struct eeepc_laptop *eeepc = input_get_drvdata(dev);
1140 struct key_entry *key = eeepc_get_entry_by_scancode(eeepc, scancode);
1124 1141
1125 bd = backlight_device_register(EEEPC_HOTK_FILE, dev, 1142 if (key && key->type == KE_KEY) {
1126 NULL, &eeepcbl_ops); 1143 *keycode = key->keycode;
1127 if (IS_ERR(bd)) { 1144 return 0;
1128 pr_err("Could not register eeepc backlight device\n");
1129 eeepc_backlight_device = NULL;
1130 return PTR_ERR(bd);
1131 } 1145 }
1132 eeepc_backlight_device = bd; 1146
1133 bd->props.max_brightness = 15; 1147 return -EINVAL;
1134 bd->props.brightness = read_brightness(NULL);
1135 bd->props.power = FB_BLANK_UNBLANK;
1136 backlight_update_status(bd);
1137 return 0;
1138} 1148}
1139 1149
1140static int eeepc_hwmon_init(struct device *dev) 1150static int eeepc_setkeycode(struct input_dev *dev, int scancode, int keycode)
1141{ 1151{
1142 struct device *hwmon; 1152 struct eeepc_laptop *eeepc = input_get_drvdata(dev);
1143 int result; 1153 struct key_entry *key;
1154 int old_keycode;
1144 1155
1145 hwmon = hwmon_device_register(dev); 1156 if (keycode < 0 || keycode > KEY_MAX)
1146 if (IS_ERR(hwmon)) { 1157 return -EINVAL;
1147 pr_err("Could not register eeepc hwmon device\n"); 1158
1148 eeepc_hwmon_device = NULL; 1159 key = eeepc_get_entry_by_scancode(eeepc, scancode);
1149 return PTR_ERR(hwmon); 1160 if (key && key->type == KE_KEY) {
1161 old_keycode = key->keycode;
1162 key->keycode = keycode;
1163 set_bit(keycode, dev->keybit);
1164 if (!eeepc_get_entry_by_keycode(eeepc, old_keycode))
1165 clear_bit(old_keycode, dev->keybit);
1166 return 0;
1150 } 1167 }
1151 eeepc_hwmon_device = hwmon; 1168
1152 result = sysfs_create_group(&hwmon->kobj, 1169 return -EINVAL;
1153 &hwmon_attribute_group);
1154 if (result)
1155 eeepc_hwmon_exit();
1156 return result;
1157} 1170}
1158 1171
1159static int eeepc_input_init(struct device *dev) 1172static int eeepc_input_init(struct eeepc_laptop *eeepc)
1160{ 1173{
1161 const struct key_entry *key; 1174 const struct key_entry *key;
1162 int result; 1175 int result;
1163 1176
1164 ehotk->inputdev = input_allocate_device(); 1177 eeepc->inputdev = input_allocate_device();
1165 if (!ehotk->inputdev) { 1178 if (!eeepc->inputdev) {
1166 pr_info("Unable to allocate input device\n"); 1179 pr_info("Unable to allocate input device\n");
1167 return -ENOMEM; 1180 return -ENOMEM;
1168 } 1181 }
1169 ehotk->inputdev->name = "Asus EeePC extra buttons"; 1182 eeepc->inputdev->name = "Asus EeePC extra buttons";
1170 ehotk->inputdev->dev.parent = dev; 1183 eeepc->inputdev->dev.parent = &eeepc->platform_device->dev;
1171 ehotk->inputdev->phys = EEEPC_HOTK_FILE "/input0"; 1184 eeepc->inputdev->phys = EEEPC_LAPTOP_FILE "/input0";
1172 ehotk->inputdev->id.bustype = BUS_HOST; 1185 eeepc->inputdev->id.bustype = BUS_HOST;
1173 ehotk->inputdev->getkeycode = eeepc_getkeycode; 1186 eeepc->inputdev->getkeycode = eeepc_getkeycode;
1174 ehotk->inputdev->setkeycode = eeepc_setkeycode; 1187 eeepc->inputdev->setkeycode = eeepc_setkeycode;
1175 1188 input_set_drvdata(eeepc->inputdev, eeepc);
1189
1190 eeepc->keymap = kmemdup(eeepc_keymap, sizeof(eeepc_keymap),
1191 GFP_KERNEL);
1176 for (key = eeepc_keymap; key->type != KE_END; key++) { 1192 for (key = eeepc_keymap; key->type != KE_END; key++) {
1177 switch (key->type) { 1193 switch (key->type) {
1178 case KE_KEY: 1194 case KE_KEY:
1179 set_bit(EV_KEY, ehotk->inputdev->evbit); 1195 set_bit(EV_KEY, eeepc->inputdev->evbit);
1180 set_bit(key->keycode, ehotk->inputdev->keybit); 1196 set_bit(key->keycode, eeepc->inputdev->keybit);
1181 break; 1197 break;
1182 } 1198 }
1183 } 1199 }
1184 result = input_register_device(ehotk->inputdev); 1200 result = input_register_device(eeepc->inputdev);
1185 if (result) { 1201 if (result) {
1186 pr_info("Unable to register input device\n"); 1202 pr_info("Unable to register input device\n");
1187 input_free_device(ehotk->inputdev); 1203 input_free_device(eeepc->inputdev);
1188 return result; 1204 return result;
1189 } 1205 }
1190 return 0; 1206 return 0;
1191} 1207}
1192 1208
1193static int __devinit eeepc_hotk_add(struct acpi_device *device) 1209static void eeepc_input_exit(struct eeepc_laptop *eeepc)
1194{ 1210{
1195 struct device *dev; 1211 if (eeepc->inputdev) {
1212 input_unregister_device(eeepc->inputdev);
1213 kfree(eeepc->keymap);
1214 }
1215}
1216
1217/*
1218 * ACPI driver
1219 */
1220static void eeepc_acpi_notify(struct acpi_device *device, u32 event)
1221{
1222 struct eeepc_laptop *eeepc = acpi_driver_data(device);
1223 u16 count;
1224
1225 if (event > ACPI_MAX_SYS_NOTIFY)
1226 return;
1227 count = eeepc->event_count[event % 128]++;
1228 acpi_bus_generate_proc_event(device, event, count);
1229 acpi_bus_generate_netlink_event(device->pnp.device_class,
1230 dev_name(&device->dev), event,
1231 count);
1232
1233 /* Brightness events are special */
1234 if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX) {
1235
1236 /* Ignore them completely if the acpi video driver is used */
1237 if (eeepc->backlight_device != NULL) {
1238 int old_brightness, new_brightness;
1239
1240 /* Update the backlight device. */
1241 old_brightness = eeepc_backlight_notify(eeepc);
1242
1243 /* Convert event to keypress (obsolescent hack) */
1244 new_brightness = event - NOTIFY_BRN_MIN;
1245
1246 if (new_brightness < old_brightness) {
1247 event = NOTIFY_BRN_MIN; /* brightness down */
1248 } else if (new_brightness > old_brightness) {
1249 event = NOTIFY_BRN_MAX; /* brightness up */
1250 } else {
1251 /*
1252 * no change in brightness - already at min/max,
1253 * event will be desired value (or else ignored)
1254 */
1255 }
1256 eeepc_input_notify(eeepc, event);
1257 }
1258 } else {
1259 /* Everything else is a bona-fide keypress event */
1260 eeepc_input_notify(eeepc, event);
1261 }
1262}
1263
1264static void cmsg_quirk(struct eeepc_laptop *eeepc, int cm, const char *name)
1265{
1266 int dummy;
1267
1268 /* Some BIOSes do not report cm although it is avaliable.
1269 Check if cm_getv[cm] works and, if yes, assume cm should be set. */
1270 if (!(eeepc->cm_supported & (1 << cm))
1271 && !read_acpi_int(eeepc->handle, cm_getv[cm], &dummy)) {
1272 pr_info("%s (%x) not reported by BIOS,"
1273 " enabling anyway\n", name, 1 << cm);
1274 eeepc->cm_supported |= 1 << cm;
1275 }
1276}
1277
1278static void cmsg_quirks(struct eeepc_laptop *eeepc)
1279{
1280 cmsg_quirk(eeepc, CM_ASL_LID, "LID");
1281 cmsg_quirk(eeepc, CM_ASL_TYPE, "TYPE");
1282 cmsg_quirk(eeepc, CM_ASL_PANELPOWER, "PANELPOWER");
1283 cmsg_quirk(eeepc, CM_ASL_TPD, "TPD");
1284}
1285
1286static int eeepc_acpi_init(struct eeepc_laptop *eeepc,
1287 struct acpi_device *device)
1288{
1289 unsigned int init_flags;
1196 int result; 1290 int result;
1197 1291
1198 if (!device) 1292 result = acpi_bus_get_status(device);
1199 return -EINVAL;
1200 pr_notice(EEEPC_HOTK_NAME "\n");
1201 ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL);
1202 if (!ehotk)
1203 return -ENOMEM;
1204 ehotk->init_flag = DISABLE_ASL_WLAN | DISABLE_ASL_DISPLAYSWITCH;
1205 ehotk->handle = device->handle;
1206 strcpy(acpi_device_name(device), EEEPC_HOTK_DEVICE_NAME);
1207 strcpy(acpi_device_class(device), EEEPC_HOTK_CLASS);
1208 device->driver_data = ehotk;
1209 ehotk->device = device;
1210
1211 result = eeepc_hotk_check();
1212 if (result) 1293 if (result)
1213 goto fail_platform_driver; 1294 return result;
1214 eeepc_enable_camera(); 1295 if (!device->status.present) {
1296 pr_err("Hotkey device not present, aborting\n");
1297 return -ENODEV;
1298 }
1215 1299
1216 /* Register platform stuff */ 1300 init_flags = DISABLE_ASL_WLAN | DISABLE_ASL_DISPLAYSWITCH;
1217 result = platform_driver_register(&platform_driver); 1301 pr_notice("Hotkey init flags 0x%x\n", init_flags);
1218 if (result) 1302
1219 goto fail_platform_driver; 1303 if (write_acpi_int(eeepc->handle, "INIT", init_flags)) {
1220 platform_device = platform_device_alloc(EEEPC_HOTK_FILE, -1); 1304 pr_err("Hotkey initialization failed\n");
1221 if (!platform_device) { 1305 return -ENODEV;
1222 result = -ENOMEM;
1223 goto fail_platform_device1;
1224 } 1306 }
1225 result = platform_device_add(platform_device); 1307
1226 if (result) 1308 /* get control methods supported */
1227 goto fail_platform_device2; 1309 if (read_acpi_int(eeepc->handle, "CMSG", &eeepc->cm_supported)) {
1228 result = sysfs_create_group(&platform_device->dev.kobj, 1310 pr_err("Get control methods supported failed\n");
1229 &platform_attribute_group); 1311 return -ENODEV;
1312 }
1313 cmsg_quirks(eeepc);
1314 pr_info("Get control methods supported: 0x%x\n", eeepc->cm_supported);
1315
1316 return 0;
1317}
1318
1319static void __devinit eeepc_enable_camera(struct eeepc_laptop *eeepc)
1320{
1321 /*
1322 * If the following call to set_acpi() fails, it's because there's no
1323 * camera so we can ignore the error.
1324 */
1325 if (get_acpi(eeepc, CM_ASL_CAMERA) == 0)
1326 set_acpi(eeepc, CM_ASL_CAMERA, 1);
1327}
1328
1329static bool eeepc_device_present;
1330
1331static int __devinit eeepc_acpi_add(struct acpi_device *device)
1332{
1333 struct eeepc_laptop *eeepc;
1334 int result;
1335
1336 pr_notice(EEEPC_LAPTOP_NAME "\n");
1337 eeepc = kzalloc(sizeof(struct eeepc_laptop), GFP_KERNEL);
1338 if (!eeepc)
1339 return -ENOMEM;
1340 eeepc->handle = device->handle;
1341 strcpy(acpi_device_name(device), EEEPC_ACPI_DEVICE_NAME);
1342 strcpy(acpi_device_class(device), EEEPC_ACPI_CLASS);
1343 device->driver_data = eeepc;
1344
1345 result = eeepc_acpi_init(eeepc, device);
1230 if (result) 1346 if (result)
1231 goto fail_sysfs; 1347 goto fail_platform;
1348 eeepc_enable_camera(eeepc);
1232 1349
1233 dev = &platform_device->dev; 1350 /*
1351 * Register the platform device first. It is used as a parent for the
1352 * sub-devices below.
1353 *
1354 * Note that if there are multiple instances of this ACPI device it
1355 * will bail out, because the platform device is registered with a
1356 * fixed name. Of course it doesn't make sense to have more than one,
1357 * and machine-specific scripts find the fixed name convenient. But
1358 * It's also good for us to exclude multiple instances because both
1359 * our hwmon and our wlan rfkill subdevice use global ACPI objects
1360 * (the EC and the wlan PCI slot respectively).
1361 */
1362 result = eeepc_platform_init(eeepc);
1363 if (result)
1364 goto fail_platform;
1234 1365
1235 if (!acpi_video_backlight_support()) { 1366 if (!acpi_video_backlight_support()) {
1236 result = eeepc_backlight_init(dev); 1367 result = eeepc_backlight_init(eeepc);
1237 if (result) 1368 if (result)
1238 goto fail_backlight; 1369 goto fail_backlight;
1239 } else 1370 } else
1240 pr_info("Backlight controlled by ACPI video " 1371 pr_info("Backlight controlled by ACPI video driver\n");
1241 "driver\n");
1242 1372
1243 result = eeepc_input_init(dev); 1373 result = eeepc_input_init(eeepc);
1244 if (result) 1374 if (result)
1245 goto fail_input; 1375 goto fail_input;
1246 1376
1247 result = eeepc_hwmon_init(dev); 1377 result = eeepc_hwmon_init(eeepc);
1248 if (result) 1378 if (result)
1249 goto fail_hwmon; 1379 goto fail_hwmon;
1250 1380
1251 result = eeepc_rfkill_init(dev); 1381 result = eeepc_led_init(eeepc);
1382 if (result)
1383 goto fail_led;
1384
1385 result = eeepc_rfkill_init(eeepc);
1252 if (result) 1386 if (result)
1253 goto fail_rfkill; 1387 goto fail_rfkill;
1254 1388
1389 eeepc_device_present = true;
1255 return 0; 1390 return 0;
1256 1391
1257fail_rfkill: 1392fail_rfkill:
1258 eeepc_hwmon_exit(); 1393 eeepc_led_exit(eeepc);
1394fail_led:
1395 eeepc_hwmon_exit(eeepc);
1259fail_hwmon: 1396fail_hwmon:
1260 eeepc_input_exit(); 1397 eeepc_input_exit(eeepc);
1261fail_input: 1398fail_input:
1262 eeepc_backlight_exit(); 1399 eeepc_backlight_exit(eeepc);
1263fail_backlight: 1400fail_backlight:
1264 sysfs_remove_group(&platform_device->dev.kobj, 1401 eeepc_platform_exit(eeepc);
1265 &platform_attribute_group); 1402fail_platform:
1266fail_sysfs: 1403 kfree(eeepc);
1267 platform_device_del(platform_device);
1268fail_platform_device2:
1269 platform_device_put(platform_device);
1270fail_platform_device1:
1271 platform_driver_unregister(&platform_driver);
1272fail_platform_driver:
1273 kfree(ehotk);
1274 1404
1275 return result; 1405 return result;
1276} 1406}
1277 1407
1278static int eeepc_hotk_remove(struct acpi_device *device, int type) 1408static int eeepc_acpi_remove(struct acpi_device *device, int type)
1279{ 1409{
1280 if (!device || !acpi_driver_data(device)) 1410 struct eeepc_laptop *eeepc = acpi_driver_data(device);
1281 return -EINVAL;
1282 1411
1283 eeepc_backlight_exit(); 1412 eeepc_backlight_exit(eeepc);
1284 eeepc_rfkill_exit(); 1413 eeepc_rfkill_exit(eeepc);
1285 eeepc_input_exit(); 1414 eeepc_input_exit(eeepc);
1286 eeepc_hwmon_exit(); 1415 eeepc_hwmon_exit(eeepc);
1287 sysfs_remove_group(&platform_device->dev.kobj, 1416 eeepc_led_exit(eeepc);
1288 &platform_attribute_group); 1417 eeepc_platform_exit(eeepc);
1289 platform_device_unregister(platform_device);
1290 platform_driver_unregister(&platform_driver);
1291 1418
1292 kfree(ehotk); 1419 kfree(eeepc);
1293 return 0; 1420 return 0;
1294} 1421}
1295 1422
1423
1424static const struct acpi_device_id eeepc_device_ids[] = {
1425 {EEEPC_ACPI_HID, 0},
1426 {"", 0},
1427};
1428MODULE_DEVICE_TABLE(acpi, eeepc_device_ids);
1429
1430static struct acpi_driver eeepc_acpi_driver = {
1431 .name = EEEPC_LAPTOP_NAME,
1432 .class = EEEPC_ACPI_CLASS,
1433 .owner = THIS_MODULE,
1434 .ids = eeepc_device_ids,
1435 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
1436 .ops = {
1437 .add = eeepc_acpi_add,
1438 .remove = eeepc_acpi_remove,
1439 .notify = eeepc_acpi_notify,
1440 },
1441};
1442
1443
1296static int __init eeepc_laptop_init(void) 1444static int __init eeepc_laptop_init(void)
1297{ 1445{
1298 int result; 1446 int result;
1299 1447
1300 if (acpi_disabled) 1448 result = platform_driver_register(&platform_driver);
1301 return -ENODEV;
1302 result = acpi_bus_register_driver(&eeepc_hotk_driver);
1303 if (result < 0) 1449 if (result < 0)
1304 return result; 1450 return result;
1305 if (!ehotk) { 1451
1306 acpi_bus_unregister_driver(&eeepc_hotk_driver); 1452 result = acpi_bus_register_driver(&eeepc_acpi_driver);
1307 return -ENODEV; 1453 if (result < 0)
1454 goto fail_acpi_driver;
1455 if (!eeepc_device_present) {
1456 result = -ENODEV;
1457 goto fail_no_device;
1308 } 1458 }
1309 return 0; 1459 return 0;
1460
1461fail_no_device:
1462 acpi_bus_unregister_driver(&eeepc_acpi_driver);
1463fail_acpi_driver:
1464 platform_driver_unregister(&platform_driver);
1465 return result;
1310} 1466}
1311 1467
1312static void __exit eeepc_laptop_exit(void) 1468static void __exit eeepc_laptop_exit(void)
1313{ 1469{
1314 acpi_bus_unregister_driver(&eeepc_hotk_driver); 1470 acpi_bus_unregister_driver(&eeepc_acpi_driver);
1471 platform_driver_unregister(&platform_driver);
1315} 1472}
1316 1473
1317module_init(eeepc_laptop_init); 1474module_init(eeepc_laptop_init);