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