rcv reorder queue bugfix
[cor_2_6_31.git] / drivers / platform / x86 / eeepc-laptop.c
blobec560f16d7204a20c42b874d7e54902aaf2762cd
1 /*
2 * eepc-laptop.c - Asus Eee PC extras
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
6 * Based on eee.c from eeepc-linux
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
19 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
21 #include <linux/kernel.h>
22 #include <linux/module.h>
23 #include <linux/init.h>
24 #include <linux/types.h>
25 #include <linux/platform_device.h>
26 #include <linux/backlight.h>
27 #include <linux/fb.h>
28 #include <linux/hwmon.h>
29 #include <linux/hwmon-sysfs.h>
30 #include <acpi/acpi_drivers.h>
31 #include <acpi/acpi_bus.h>
32 #include <linux/uaccess.h>
33 #include <linux/input.h>
34 #include <linux/rfkill.h>
35 #include <linux/pci.h>
36 #include <linux/pci_hotplug.h>
38 #define EEEPC_LAPTOP_VERSION "0.1"
40 #define EEEPC_HOTK_NAME "Eee PC Hotkey Driver"
41 #define EEEPC_HOTK_FILE "eeepc"
42 #define EEEPC_HOTK_CLASS "hotkey"
43 #define EEEPC_HOTK_DEVICE_NAME "Hotkey"
44 #define EEEPC_HOTK_HID "ASUS010"
48 * Definitions for Asus EeePC
50 #define NOTIFY_WLAN_ON 0x10
51 #define NOTIFY_BRN_MIN 0x20
52 #define NOTIFY_BRN_MAX 0x2f
54 enum {
55 DISABLE_ASL_WLAN = 0x0001,
56 DISABLE_ASL_BLUETOOTH = 0x0002,
57 DISABLE_ASL_IRDA = 0x0004,
58 DISABLE_ASL_CAMERA = 0x0008,
59 DISABLE_ASL_TV = 0x0010,
60 DISABLE_ASL_GPS = 0x0020,
61 DISABLE_ASL_DISPLAYSWITCH = 0x0040,
62 DISABLE_ASL_MODEM = 0x0080,
63 DISABLE_ASL_CARDREADER = 0x0100,
64 DISABLE_ASL_3G = 0x0200,
65 DISABLE_ASL_WIMAX = 0x0400,
66 DISABLE_ASL_HWCF = 0x0800
69 enum {
70 CM_ASL_WLAN = 0,
71 CM_ASL_BLUETOOTH,
72 CM_ASL_IRDA,
73 CM_ASL_1394,
74 CM_ASL_CAMERA,
75 CM_ASL_TV,
76 CM_ASL_GPS,
77 CM_ASL_DVDROM,
78 CM_ASL_DISPLAYSWITCH,
79 CM_ASL_PANELBRIGHT,
80 CM_ASL_BIOSFLASH,
81 CM_ASL_ACPIFLASH,
82 CM_ASL_CPUFV,
83 CM_ASL_CPUTEMPERATURE,
84 CM_ASL_FANCPU,
85 CM_ASL_FANCHASSIS,
86 CM_ASL_USBPORT1,
87 CM_ASL_USBPORT2,
88 CM_ASL_USBPORT3,
89 CM_ASL_MODEM,
90 CM_ASL_CARDREADER,
91 CM_ASL_3G,
92 CM_ASL_WIMAX,
93 CM_ASL_HWCF,
94 CM_ASL_LID,
95 CM_ASL_TYPE,
96 CM_ASL_PANELPOWER, /*P901*/
97 CM_ASL_TPD
100 static const char *cm_getv[] = {
101 "WLDG", "BTHG", NULL, NULL,
102 "CAMG", NULL, NULL, NULL,
103 NULL, "PBLG", NULL, NULL,
104 "CFVG", NULL, NULL, NULL,
105 "USBG", NULL, NULL, "MODG",
106 "CRDG", "M3GG", "WIMG", "HWCF",
107 "LIDG", "TYPE", "PBPG", "TPDG"
110 static const char *cm_setv[] = {
111 "WLDS", "BTHS", NULL, NULL,
112 "CAMS", NULL, NULL, NULL,
113 "SDSP", "PBLS", "HDPS", NULL,
114 "CFVS", NULL, NULL, NULL,
115 "USBG", NULL, NULL, "MODS",
116 "CRDS", "M3GS", "WIMS", NULL,
117 NULL, NULL, "PBPS", "TPDS"
120 #define EEEPC_EC "\\_SB.PCI0.SBRG.EC0."
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
130 * This is the main structure, we can use it to store useful information
131 * about the hotk device
133 struct 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 hotplug_slot *hotplug_slot;
148 /* The actual device the driver binds to */
149 static struct eeepc_hotk *ehotk;
151 /* Platform device/driver */
152 static struct platform_driver platform_driver = {
153 .driver = {
154 .name = EEEPC_HOTK_FILE,
155 .owner = THIS_MODULE,
159 static struct platform_device *platform_device;
161 struct key_entry {
162 char type;
163 u8 code;
164 u16 keycode;
167 enum { KE_KEY, KE_END };
169 static struct key_entry eeepc_keymap[] = {
170 /* Sleep already handled via generic ACPI code */
171 {KE_KEY, 0x10, KEY_WLAN },
172 {KE_KEY, 0x11, KEY_WLAN },
173 {KE_KEY, 0x12, KEY_PROG1 },
174 {KE_KEY, 0x13, KEY_MUTE },
175 {KE_KEY, 0x14, KEY_VOLUMEDOWN },
176 {KE_KEY, 0x15, KEY_VOLUMEUP },
177 {KE_KEY, 0x1a, KEY_COFFEE },
178 {KE_KEY, 0x1b, KEY_ZOOM },
179 {KE_KEY, 0x1c, KEY_PROG2 },
180 {KE_KEY, 0x1d, KEY_PROG3 },
181 {KE_KEY, NOTIFY_BRN_MIN, KEY_BRIGHTNESSDOWN },
182 {KE_KEY, NOTIFY_BRN_MIN + 2, KEY_BRIGHTNESSUP },
183 {KE_KEY, 0x30, KEY_SWITCHVIDEOMODE },
184 {KE_KEY, 0x31, KEY_SWITCHVIDEOMODE },
185 {KE_KEY, 0x32, KEY_SWITCHVIDEOMODE },
186 {KE_END, 0},
190 * The hotkey driver declaration
192 static int eeepc_hotk_add(struct acpi_device *device);
193 static int eeepc_hotk_remove(struct acpi_device *device, int type);
194 static int eeepc_hotk_resume(struct acpi_device *device);
195 static void eeepc_hotk_notify(struct acpi_device *device, u32 event);
197 static const struct acpi_device_id eeepc_device_ids[] = {
198 {EEEPC_HOTK_HID, 0},
199 {"", 0},
201 MODULE_DEVICE_TABLE(acpi, eeepc_device_ids);
203 static struct acpi_driver eeepc_hotk_driver = {
204 .name = EEEPC_HOTK_NAME,
205 .class = EEEPC_HOTK_CLASS,
206 .ids = eeepc_device_ids,
207 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
208 .ops = {
209 .add = eeepc_hotk_add,
210 .remove = eeepc_hotk_remove,
211 .resume = eeepc_hotk_resume,
212 .notify = eeepc_hotk_notify,
216 /* PCI hotplug ops */
217 static int eeepc_get_adapter_status(struct hotplug_slot *slot, u8 *value);
219 static struct hotplug_slot_ops eeepc_hotplug_slot_ops = {
220 .owner = THIS_MODULE,
221 .get_adapter_status = eeepc_get_adapter_status,
222 .get_power_status = eeepc_get_adapter_status,
225 /* The backlight device /sys/class/backlight */
226 static struct backlight_device *eeepc_backlight_device;
228 /* The hwmon device */
229 static struct device *eeepc_hwmon_device;
232 * The backlight class declaration
234 static int read_brightness(struct backlight_device *bd);
235 static int update_bl_status(struct backlight_device *bd);
236 static struct backlight_ops eeepcbl_ops = {
237 .get_brightness = read_brightness,
238 .update_status = update_bl_status,
241 MODULE_AUTHOR("Corentin Chary, Eric Cooper");
242 MODULE_DESCRIPTION(EEEPC_HOTK_NAME);
243 MODULE_LICENSE("GPL");
246 * ACPI Helpers
248 static int write_acpi_int(acpi_handle handle, const char *method, int val,
249 struct acpi_buffer *output)
251 struct acpi_object_list params;
252 union acpi_object in_obj;
253 acpi_status status;
255 params.count = 1;
256 params.pointer = &in_obj;
257 in_obj.type = ACPI_TYPE_INTEGER;
258 in_obj.integer.value = val;
260 status = acpi_evaluate_object(handle, (char *)method, &params, output);
261 return (status == AE_OK ? 0 : -1);
264 static int read_acpi_int(acpi_handle handle, const char *method, int *val)
266 acpi_status status;
267 unsigned long long result;
269 status = acpi_evaluate_integer(handle, (char *)method, NULL, &result);
270 if (ACPI_FAILURE(status)) {
271 *val = -1;
272 return -1;
273 } else {
274 *val = result;
275 return 0;
279 static int set_acpi(int cm, int value)
281 if (ehotk->cm_supported & (0x1 << cm)) {
282 const char *method = cm_setv[cm];
283 if (method == NULL)
284 return -ENODEV;
285 if (write_acpi_int(ehotk->handle, method, value, NULL))
286 pr_warning("Error writing %s\n", method);
288 return 0;
291 static int get_acpi(int cm)
293 int value = -ENODEV;
294 if ((ehotk->cm_supported & (0x1 << cm))) {
295 const char *method = cm_getv[cm];
296 if (method == NULL)
297 return -ENODEV;
298 if (read_acpi_int(ehotk->handle, method, &value))
299 pr_warning("Error reading %s\n", method);
301 return value;
305 * Backlight
307 static int read_brightness(struct backlight_device *bd)
309 return get_acpi(CM_ASL_PANELBRIGHT);
312 static int set_brightness(struct backlight_device *bd, int value)
314 value = max(0, min(15, value));
315 return set_acpi(CM_ASL_PANELBRIGHT, value);
318 static int update_bl_status(struct backlight_device *bd)
320 return set_brightness(bd, bd->props.brightness);
324 * Rfkill helpers
327 static bool eeepc_wlan_rfkill_blocked(void)
329 if (get_acpi(CM_ASL_WLAN) == 1)
330 return false;
331 return true;
334 static int eeepc_rfkill_set(void *data, bool blocked)
336 unsigned long asl = (unsigned long)data;
337 return set_acpi(asl, !blocked);
340 static const struct rfkill_ops eeepc_rfkill_ops = {
341 .set_block = eeepc_rfkill_set,
344 static void __init eeepc_enable_camera(void)
347 * If the following call to set_acpi() fails, it's because there's no
348 * camera so we can ignore the error.
350 set_acpi(CM_ASL_CAMERA, 1);
354 * Sys helpers
356 static int parse_arg(const char *buf, unsigned long count, int *val)
358 if (!count)
359 return 0;
360 if (sscanf(buf, "%i", val) != 1)
361 return -EINVAL;
362 return count;
365 static ssize_t store_sys_acpi(int cm, const char *buf, size_t count)
367 int rv, value;
369 rv = parse_arg(buf, count, &value);
370 if (rv > 0)
371 value = set_acpi(cm, value);
372 if (value < 0)
373 return value;
374 return rv;
377 static ssize_t show_sys_acpi(int cm, char *buf)
379 int value = get_acpi(cm);
381 if (value < 0)
382 return value;
383 return sprintf(buf, "%d\n", value);
386 #define EEEPC_CREATE_DEVICE_ATTR(_name, _cm) \
387 static ssize_t show_##_name(struct device *dev, \
388 struct device_attribute *attr, \
389 char *buf) \
391 return show_sys_acpi(_cm, buf); \
393 static ssize_t store_##_name(struct device *dev, \
394 struct device_attribute *attr, \
395 const char *buf, size_t count) \
397 return store_sys_acpi(_cm, buf, count); \
399 static struct device_attribute dev_attr_##_name = { \
400 .attr = { \
401 .name = __stringify(_name), \
402 .mode = 0644 }, \
403 .show = show_##_name, \
404 .store = store_##_name, \
407 EEEPC_CREATE_DEVICE_ATTR(camera, CM_ASL_CAMERA);
408 EEEPC_CREATE_DEVICE_ATTR(cardr, CM_ASL_CARDREADER);
409 EEEPC_CREATE_DEVICE_ATTR(disp, CM_ASL_DISPLAYSWITCH);
411 struct eeepc_cpufv {
412 int num;
413 int cur;
416 static int get_cpufv(struct eeepc_cpufv *c)
418 c->cur = get_acpi(CM_ASL_CPUFV);
419 c->num = (c->cur >> 8) & 0xff;
420 c->cur &= 0xff;
421 if (c->cur < 0 || c->num <= 0 || c->num > 12)
422 return -ENODEV;
423 return 0;
426 static ssize_t show_available_cpufv(struct device *dev,
427 struct device_attribute *attr,
428 char *buf)
430 struct eeepc_cpufv c;
431 int i;
432 ssize_t len = 0;
434 if (get_cpufv(&c))
435 return -ENODEV;
436 for (i = 0; i < c.num; i++)
437 len += sprintf(buf + len, "%d ", i);
438 len += sprintf(buf + len, "\n");
439 return len;
442 static ssize_t show_cpufv(struct device *dev,
443 struct device_attribute *attr,
444 char *buf)
446 struct eeepc_cpufv c;
448 if (get_cpufv(&c))
449 return -ENODEV;
450 return sprintf(buf, "%#x\n", (c.num << 8) | c.cur);
453 static ssize_t store_cpufv(struct device *dev,
454 struct device_attribute *attr,
455 const char *buf, size_t count)
457 struct eeepc_cpufv c;
458 int rv, value;
460 if (get_cpufv(&c))
461 return -ENODEV;
462 rv = parse_arg(buf, count, &value);
463 if (rv < 0)
464 return rv;
465 if (!rv || value < 0 || value >= c.num)
466 return -EINVAL;
467 set_acpi(CM_ASL_CPUFV, value);
468 return rv;
471 static struct device_attribute dev_attr_cpufv = {
472 .attr = {
473 .name = "cpufv",
474 .mode = 0644 },
475 .show = show_cpufv,
476 .store = store_cpufv
479 static struct device_attribute dev_attr_available_cpufv = {
480 .attr = {
481 .name = "available_cpufv",
482 .mode = 0444 },
483 .show = show_available_cpufv
486 static struct attribute *platform_attributes[] = {
487 &dev_attr_camera.attr,
488 &dev_attr_cardr.attr,
489 &dev_attr_disp.attr,
490 &dev_attr_cpufv.attr,
491 &dev_attr_available_cpufv.attr,
492 NULL
495 static struct attribute_group platform_attribute_group = {
496 .attrs = platform_attributes
500 * Hotkey functions
502 static struct key_entry *eepc_get_entry_by_scancode(int code)
504 struct key_entry *key;
506 for (key = eeepc_keymap; key->type != KE_END; key++)
507 if (code == key->code)
508 return key;
510 return NULL;
513 static struct key_entry *eepc_get_entry_by_keycode(int code)
515 struct key_entry *key;
517 for (key = eeepc_keymap; key->type != KE_END; key++)
518 if (code == key->keycode && key->type == KE_KEY)
519 return key;
521 return NULL;
524 static int eeepc_getkeycode(struct input_dev *dev, int scancode, int *keycode)
526 struct key_entry *key = eepc_get_entry_by_scancode(scancode);
528 if (key && key->type == KE_KEY) {
529 *keycode = key->keycode;
530 return 0;
533 return -EINVAL;
536 static int eeepc_setkeycode(struct input_dev *dev, int scancode, int keycode)
538 struct key_entry *key;
539 int old_keycode;
541 if (keycode < 0 || keycode > KEY_MAX)
542 return -EINVAL;
544 key = eepc_get_entry_by_scancode(scancode);
545 if (key && key->type == KE_KEY) {
546 old_keycode = key->keycode;
547 key->keycode = keycode;
548 set_bit(keycode, dev->keybit);
549 if (!eepc_get_entry_by_keycode(old_keycode))
550 clear_bit(old_keycode, dev->keybit);
551 return 0;
554 return -EINVAL;
557 static void cmsg_quirk(int cm, const char *name)
559 int dummy;
561 /* Some BIOSes do not report cm although it is avaliable.
562 Check if cm_getv[cm] works and, if yes, assume cm should be set. */
563 if (!(ehotk->cm_supported & (1 << cm))
564 && !read_acpi_int(ehotk->handle, cm_getv[cm], &dummy)) {
565 pr_info("%s (%x) not reported by BIOS,"
566 " enabling anyway\n", name, 1 << cm);
567 ehotk->cm_supported |= 1 << cm;
571 static void cmsg_quirks(void)
573 cmsg_quirk(CM_ASL_LID, "LID");
574 cmsg_quirk(CM_ASL_TYPE, "TYPE");
575 cmsg_quirk(CM_ASL_PANELPOWER, "PANELPOWER");
576 cmsg_quirk(CM_ASL_TPD, "TPD");
579 static int eeepc_hotk_check(void)
581 const struct key_entry *key;
582 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
583 int result;
585 result = acpi_bus_get_status(ehotk->device);
586 if (result)
587 return result;
588 if (ehotk->device->status.present) {
589 if (write_acpi_int(ehotk->handle, "INIT", ehotk->init_flag,
590 &buffer)) {
591 pr_err("Hotkey initialization failed\n");
592 return -ENODEV;
593 } else {
594 pr_notice("Hotkey init flags 0x%x\n", ehotk->init_flag);
596 /* get control methods supported */
597 if (read_acpi_int(ehotk->handle, "CMSG"
598 , &ehotk->cm_supported)) {
599 pr_err("Get control methods supported failed\n");
600 return -ENODEV;
601 } else {
602 cmsg_quirks();
603 pr_info("Get control methods supported: 0x%x\n",
604 ehotk->cm_supported);
606 ehotk->inputdev = input_allocate_device();
607 if (!ehotk->inputdev) {
608 pr_info("Unable to allocate input device\n");
609 return 0;
611 ehotk->inputdev->name = "Asus EeePC extra buttons";
612 ehotk->inputdev->phys = EEEPC_HOTK_FILE "/input0";
613 ehotk->inputdev->id.bustype = BUS_HOST;
614 ehotk->inputdev->getkeycode = eeepc_getkeycode;
615 ehotk->inputdev->setkeycode = eeepc_setkeycode;
617 for (key = eeepc_keymap; key->type != KE_END; key++) {
618 switch (key->type) {
619 case KE_KEY:
620 set_bit(EV_KEY, ehotk->inputdev->evbit);
621 set_bit(key->keycode, ehotk->inputdev->keybit);
622 break;
625 result = input_register_device(ehotk->inputdev);
626 if (result) {
627 pr_info("Unable to register input device\n");
628 input_free_device(ehotk->inputdev);
629 return 0;
631 } else {
632 pr_err("Hotkey device not present, aborting\n");
633 return -EINVAL;
635 return 0;
638 static int notify_brn(void)
640 /* returns the *previous* brightness, or -1 */
641 struct backlight_device *bd = eeepc_backlight_device;
642 if (bd) {
643 int old = bd->props.brightness;
644 bd->props.brightness = read_brightness(bd);
645 return old;
647 return -1;
650 static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot,
651 u8 *value)
653 int val = get_acpi(CM_ASL_WLAN);
655 if (val == 1 || val == 0)
656 *value = val;
657 else
658 return -EINVAL;
660 return 0;
663 static void eeepc_rfkill_hotplug(void)
665 struct pci_dev *dev;
666 struct pci_bus *bus = pci_find_bus(0, 1);
667 bool blocked;
669 if (!bus) {
670 pr_warning("Unable to find PCI bus 1?\n");
671 return;
674 blocked = eeepc_wlan_rfkill_blocked();
675 if (!blocked) {
676 dev = pci_get_slot(bus, 0);
677 if (dev) {
678 /* Device already present */
679 pci_dev_put(dev);
680 return;
682 dev = pci_scan_single_device(bus, 0);
683 if (dev) {
684 pci_bus_assign_resources(bus);
685 if (pci_bus_add_device(dev))
686 pr_err("Unable to hotplug wifi\n");
688 } else {
689 dev = pci_get_slot(bus, 0);
690 if (dev) {
691 pci_remove_bus_device(dev);
692 pci_dev_put(dev);
696 rfkill_set_sw_state(ehotk->wlan_rfkill, blocked);
699 static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
701 if (event != ACPI_NOTIFY_BUS_CHECK)
702 return;
704 eeepc_rfkill_hotplug();
707 static void eeepc_hotk_notify(struct acpi_device *device, u32 event)
709 static struct key_entry *key;
710 u16 count;
711 int brn = -ENODEV;
713 if (!ehotk)
714 return;
715 if (event > ACPI_MAX_SYS_NOTIFY)
716 return;
717 if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX)
718 brn = notify_brn();
719 count = ehotk->event_count[event % 128]++;
720 acpi_bus_generate_proc_event(ehotk->device, event, count);
721 acpi_bus_generate_netlink_event(ehotk->device->pnp.device_class,
722 dev_name(&ehotk->device->dev), event,
723 count);
724 if (ehotk->inputdev) {
725 if (brn != -ENODEV) {
726 /* brightness-change events need special
727 * handling for conversion to key events
729 if (brn < 0)
730 brn = event;
731 else
732 brn += NOTIFY_BRN_MIN;
733 if (event < brn)
734 event = NOTIFY_BRN_MIN; /* brightness down */
735 else if (event > brn)
736 event = NOTIFY_BRN_MIN + 2; /* ... up */
737 else
738 event = NOTIFY_BRN_MIN + 1; /* ... unchanged */
740 key = eepc_get_entry_by_scancode(event);
741 if (key) {
742 switch (key->type) {
743 case KE_KEY:
744 input_report_key(ehotk->inputdev, key->keycode,
746 input_sync(ehotk->inputdev);
747 input_report_key(ehotk->inputdev, key->keycode,
749 input_sync(ehotk->inputdev);
750 break;
756 static int eeepc_register_rfkill_notifier(char *node)
758 acpi_status status = AE_OK;
759 acpi_handle handle;
761 status = acpi_get_handle(NULL, node, &handle);
763 if (ACPI_SUCCESS(status)) {
764 status = acpi_install_notify_handler(handle,
765 ACPI_SYSTEM_NOTIFY,
766 eeepc_rfkill_notify,
767 NULL);
768 if (ACPI_FAILURE(status))
769 pr_warning("Failed to register notify on %s\n", node);
770 } else
771 return -ENODEV;
773 return 0;
776 static void eeepc_unregister_rfkill_notifier(char *node)
778 acpi_status status = AE_OK;
779 acpi_handle handle;
781 status = acpi_get_handle(NULL, node, &handle);
783 if (ACPI_SUCCESS(status)) {
784 status = acpi_remove_notify_handler(handle,
785 ACPI_SYSTEM_NOTIFY,
786 eeepc_rfkill_notify);
787 if (ACPI_FAILURE(status))
788 pr_err("Error removing rfkill notify handler %s\n",
789 node);
793 static void eeepc_cleanup_pci_hotplug(struct hotplug_slot *hotplug_slot)
795 kfree(hotplug_slot->info);
796 kfree(hotplug_slot);
799 static int eeepc_setup_pci_hotplug(void)
801 int ret = -ENOMEM;
802 struct pci_bus *bus = pci_find_bus(0, 1);
804 if (!bus) {
805 pr_err("Unable to find wifi PCI bus\n");
806 return -ENODEV;
809 ehotk->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
810 if (!ehotk->hotplug_slot)
811 goto error_slot;
813 ehotk->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info),
814 GFP_KERNEL);
815 if (!ehotk->hotplug_slot->info)
816 goto error_info;
818 ehotk->hotplug_slot->private = ehotk;
819 ehotk->hotplug_slot->release = &eeepc_cleanup_pci_hotplug;
820 ehotk->hotplug_slot->ops = &eeepc_hotplug_slot_ops;
821 eeepc_get_adapter_status(ehotk->hotplug_slot,
822 &ehotk->hotplug_slot->info->adapter_status);
824 ret = pci_hp_register(ehotk->hotplug_slot, bus, 0, "eeepc-wifi");
825 if (ret) {
826 pr_err("Unable to register hotplug slot - %d\n", ret);
827 goto error_register;
830 return 0;
832 error_register:
833 kfree(ehotk->hotplug_slot->info);
834 error_info:
835 kfree(ehotk->hotplug_slot);
836 ehotk->hotplug_slot = NULL;
837 error_slot:
838 return ret;
841 static int eeepc_hotk_add(struct acpi_device *device)
843 int result;
845 if (!device)
846 return -EINVAL;
847 pr_notice(EEEPC_HOTK_NAME "\n");
848 ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL);
849 if (!ehotk)
850 return -ENOMEM;
851 ehotk->init_flag = DISABLE_ASL_WLAN | DISABLE_ASL_DISPLAYSWITCH;
852 ehotk->handle = device->handle;
853 strcpy(acpi_device_name(device), EEEPC_HOTK_DEVICE_NAME);
854 strcpy(acpi_device_class(device), EEEPC_HOTK_CLASS);
855 device->driver_data = ehotk;
856 ehotk->device = device;
857 result = eeepc_hotk_check();
858 if (result)
859 goto ehotk_fail;
861 return 0;
863 ehotk_fail:
864 kfree(ehotk);
865 ehotk = NULL;
867 return result;
870 static int eeepc_hotk_remove(struct acpi_device *device, int type)
872 if (!device || !acpi_driver_data(device))
873 return -EINVAL;
875 kfree(ehotk);
876 return 0;
879 static int eeepc_hotk_resume(struct acpi_device *device)
881 if (ehotk->wlan_rfkill) {
882 bool wlan;
884 /* Workaround - it seems that _PTS disables the wireless
885 without notification or changing the value read by WLAN.
886 Normally this is fine because the correct value is restored
887 from the non-volatile storage on resume, but we need to do
888 it ourself if case suspend is aborted, or we lose wireless.
890 wlan = get_acpi(CM_ASL_WLAN);
891 set_acpi(CM_ASL_WLAN, wlan);
893 rfkill_set_sw_state(ehotk->wlan_rfkill, wlan != 1);
895 eeepc_rfkill_hotplug();
898 if (ehotk->bluetooth_rfkill)
899 rfkill_set_sw_state(ehotk->bluetooth_rfkill,
900 get_acpi(CM_ASL_BLUETOOTH) != 1);
902 return 0;
906 * Hwmon
908 static int eeepc_get_fan_pwm(void)
910 int value = 0;
912 read_acpi_int(NULL, EEEPC_EC_FAN_PWM, &value);
913 value = value * 255 / 100;
914 return (value);
917 static void eeepc_set_fan_pwm(int value)
919 value = SENSORS_LIMIT(value, 0, 255);
920 value = value * 100 / 255;
921 ec_write(EEEPC_EC_SC02, value);
924 static int eeepc_get_fan_rpm(void)
926 int high = 0;
927 int low = 0;
929 read_acpi_int(NULL, EEEPC_EC_FAN_HRPM, &high);
930 read_acpi_int(NULL, EEEPC_EC_FAN_LRPM, &low);
931 return (high << 8 | low);
934 static int eeepc_get_fan_ctrl(void)
936 int value = 0;
938 read_acpi_int(NULL, EEEPC_EC_FAN_CTRL, &value);
939 return ((value & 0x02 ? 1 : 0));
942 static void eeepc_set_fan_ctrl(int manual)
944 int value = 0;
946 read_acpi_int(NULL, EEEPC_EC_FAN_CTRL, &value);
947 if (manual)
948 value |= 0x02;
949 else
950 value &= ~0x02;
951 ec_write(EEEPC_EC_SFB3, value);
954 static ssize_t store_sys_hwmon(void (*set)(int), const char *buf, size_t count)
956 int rv, value;
958 rv = parse_arg(buf, count, &value);
959 if (rv > 0)
960 set(value);
961 return rv;
964 static ssize_t show_sys_hwmon(int (*get)(void), char *buf)
966 return sprintf(buf, "%d\n", get());
969 #define EEEPC_CREATE_SENSOR_ATTR(_name, _mode, _set, _get) \
970 static ssize_t show_##_name(struct device *dev, \
971 struct device_attribute *attr, \
972 char *buf) \
974 return show_sys_hwmon(_set, buf); \
976 static ssize_t store_##_name(struct device *dev, \
977 struct device_attribute *attr, \
978 const char *buf, size_t count) \
980 return store_sys_hwmon(_get, buf, count); \
982 static SENSOR_DEVICE_ATTR(_name, _mode, show_##_name, store_##_name, 0);
984 EEEPC_CREATE_SENSOR_ATTR(fan1_input, S_IRUGO, eeepc_get_fan_rpm, NULL);
985 EEEPC_CREATE_SENSOR_ATTR(pwm1, S_IRUGO | S_IWUSR,
986 eeepc_get_fan_pwm, eeepc_set_fan_pwm);
987 EEEPC_CREATE_SENSOR_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
988 eeepc_get_fan_ctrl, eeepc_set_fan_ctrl);
990 static ssize_t
991 show_name(struct device *dev, struct device_attribute *attr, char *buf)
993 return sprintf(buf, "eeepc\n");
995 static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0);
997 static struct attribute *hwmon_attributes[] = {
998 &sensor_dev_attr_pwm1.dev_attr.attr,
999 &sensor_dev_attr_fan1_input.dev_attr.attr,
1000 &sensor_dev_attr_pwm1_enable.dev_attr.attr,
1001 &sensor_dev_attr_name.dev_attr.attr,
1002 NULL
1005 static struct attribute_group hwmon_attribute_group = {
1006 .attrs = hwmon_attributes
1010 * exit/init
1012 static void eeepc_backlight_exit(void)
1014 if (eeepc_backlight_device)
1015 backlight_device_unregister(eeepc_backlight_device);
1016 eeepc_backlight_device = NULL;
1019 static void eeepc_rfkill_exit(void)
1021 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6");
1022 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7");
1023 if (ehotk->wlan_rfkill)
1024 rfkill_unregister(ehotk->wlan_rfkill);
1025 if (ehotk->bluetooth_rfkill)
1026 rfkill_unregister(ehotk->bluetooth_rfkill);
1027 if (ehotk->wwan3g_rfkill)
1028 rfkill_unregister(ehotk->wwan3g_rfkill);
1029 if (ehotk->hotplug_slot)
1030 pci_hp_deregister(ehotk->hotplug_slot);
1033 static void eeepc_input_exit(void)
1035 if (ehotk->inputdev)
1036 input_unregister_device(ehotk->inputdev);
1039 static void eeepc_hwmon_exit(void)
1041 struct device *hwmon;
1043 hwmon = eeepc_hwmon_device;
1044 if (!hwmon)
1045 return ;
1046 sysfs_remove_group(&hwmon->kobj,
1047 &hwmon_attribute_group);
1048 hwmon_device_unregister(hwmon);
1049 eeepc_hwmon_device = NULL;
1052 static void __exit eeepc_laptop_exit(void)
1054 eeepc_backlight_exit();
1055 eeepc_rfkill_exit();
1056 eeepc_input_exit();
1057 eeepc_hwmon_exit();
1058 acpi_bus_unregister_driver(&eeepc_hotk_driver);
1059 sysfs_remove_group(&platform_device->dev.kobj,
1060 &platform_attribute_group);
1061 platform_device_unregister(platform_device);
1062 platform_driver_unregister(&platform_driver);
1065 static int eeepc_new_rfkill(struct rfkill **rfkill,
1066 const char *name, struct device *dev,
1067 enum rfkill_type type, int cm)
1069 int result;
1071 result = get_acpi(cm);
1072 if (result < 0)
1073 return result;
1075 *rfkill = rfkill_alloc(name, dev, type,
1076 &eeepc_rfkill_ops, (void *)(unsigned long)cm);
1078 if (!*rfkill)
1079 return -EINVAL;
1081 rfkill_init_sw_state(*rfkill, get_acpi(cm) != 1);
1082 result = rfkill_register(*rfkill);
1083 if (result) {
1084 rfkill_destroy(*rfkill);
1085 *rfkill = NULL;
1086 return result;
1088 return 0;
1092 static int eeepc_rfkill_init(struct device *dev)
1094 int result = 0;
1096 eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6");
1097 eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7");
1099 result = eeepc_new_rfkill(&ehotk->wlan_rfkill,
1100 "eeepc-wlan", dev,
1101 RFKILL_TYPE_WLAN, CM_ASL_WLAN);
1103 if (result && result != -ENODEV)
1104 goto exit;
1106 result = eeepc_new_rfkill(&ehotk->bluetooth_rfkill,
1107 "eeepc-bluetooth", dev,
1108 RFKILL_TYPE_BLUETOOTH, CM_ASL_BLUETOOTH);
1110 if (result && result != -ENODEV)
1111 goto exit;
1113 result = eeepc_new_rfkill(&ehotk->wwan3g_rfkill,
1114 "eeepc-wwan3g", dev,
1115 RFKILL_TYPE_WWAN, CM_ASL_3G);
1117 if (result && result != -ENODEV)
1118 goto exit;
1120 result = eeepc_setup_pci_hotplug();
1122 * If we get -EBUSY then something else is handling the PCI hotplug -
1123 * don't fail in this case
1125 if (result == -EBUSY)
1126 result = 0;
1128 exit:
1129 if (result && result != -ENODEV)
1130 eeepc_rfkill_exit();
1131 return result;
1134 static int eeepc_backlight_init(struct device *dev)
1136 struct backlight_device *bd;
1138 bd = backlight_device_register(EEEPC_HOTK_FILE, dev,
1139 NULL, &eeepcbl_ops);
1140 if (IS_ERR(bd)) {
1141 pr_err("Could not register eeepc backlight device\n");
1142 eeepc_backlight_device = NULL;
1143 return PTR_ERR(bd);
1145 eeepc_backlight_device = bd;
1146 bd->props.max_brightness = 15;
1147 bd->props.brightness = read_brightness(NULL);
1148 bd->props.power = FB_BLANK_UNBLANK;
1149 backlight_update_status(bd);
1150 return 0;
1153 static int eeepc_hwmon_init(struct device *dev)
1155 struct device *hwmon;
1156 int result;
1158 hwmon = hwmon_device_register(dev);
1159 if (IS_ERR(hwmon)) {
1160 pr_err("Could not register eeepc hwmon device\n");
1161 eeepc_hwmon_device = NULL;
1162 return PTR_ERR(hwmon);
1164 eeepc_hwmon_device = hwmon;
1165 result = sysfs_create_group(&hwmon->kobj,
1166 &hwmon_attribute_group);
1167 if (result)
1168 eeepc_hwmon_exit();
1169 return result;
1172 static int __init eeepc_laptop_init(void)
1174 struct device *dev;
1175 int result;
1177 if (acpi_disabled)
1178 return -ENODEV;
1179 result = acpi_bus_register_driver(&eeepc_hotk_driver);
1180 if (result < 0)
1181 return result;
1182 if (!ehotk) {
1183 acpi_bus_unregister_driver(&eeepc_hotk_driver);
1184 return -ENODEV;
1187 eeepc_enable_camera();
1189 /* Register platform stuff */
1190 result = platform_driver_register(&platform_driver);
1191 if (result)
1192 goto fail_platform_driver;
1193 platform_device = platform_device_alloc(EEEPC_HOTK_FILE, -1);
1194 if (!platform_device) {
1195 result = -ENOMEM;
1196 goto fail_platform_device1;
1198 result = platform_device_add(platform_device);
1199 if (result)
1200 goto fail_platform_device2;
1201 result = sysfs_create_group(&platform_device->dev.kobj,
1202 &platform_attribute_group);
1203 if (result)
1204 goto fail_sysfs;
1206 dev = &platform_device->dev;
1208 if (!acpi_video_backlight_support()) {
1209 result = eeepc_backlight_init(dev);
1210 if (result)
1211 goto fail_backlight;
1212 } else
1213 pr_info("Backlight controlled by ACPI video "
1214 "driver\n");
1216 result = eeepc_hwmon_init(dev);
1217 if (result)
1218 goto fail_hwmon;
1220 result = eeepc_rfkill_init(dev);
1221 if (result)
1222 goto fail_rfkill;
1224 return 0;
1225 fail_rfkill:
1226 eeepc_hwmon_exit();
1227 fail_hwmon:
1228 eeepc_backlight_exit();
1229 fail_backlight:
1230 sysfs_remove_group(&platform_device->dev.kobj,
1231 &platform_attribute_group);
1232 fail_sysfs:
1233 platform_device_del(platform_device);
1234 fail_platform_device2:
1235 platform_device_put(platform_device);
1236 fail_platform_device1:
1237 platform_driver_unregister(&platform_driver);
1238 fail_platform_driver:
1239 eeepc_input_exit();
1240 return result;
1243 module_init(eeepc_laptop_init);
1244 module_exit(eeepc_laptop_exit);