eeepc-laptop: Register as a pci-hotplug device
[linux-2.6/linux-acpi-2.6.git] / drivers / platform / x86 / eeepc-laptop.c
blobc0b203ca29fbb2e51d4dab014d4d0237d0cb322e
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 #include <linux/kernel.h>
20 #include <linux/module.h>
21 #include <linux/init.h>
22 #include <linux/types.h>
23 #include <linux/platform_device.h>
24 #include <linux/backlight.h>
25 #include <linux/fb.h>
26 #include <linux/hwmon.h>
27 #include <linux/hwmon-sysfs.h>
28 #include <acpi/acpi_drivers.h>
29 #include <acpi/acpi_bus.h>
30 #include <linux/uaccess.h>
31 #include <linux/input.h>
32 #include <linux/rfkill.h>
33 #include <linux/pci.h>
34 #include <linux/pci_hotplug.h>
36 #define EEEPC_LAPTOP_VERSION "0.1"
38 #define EEEPC_HOTK_NAME "Eee PC Hotkey Driver"
39 #define EEEPC_HOTK_FILE "eeepc"
40 #define EEEPC_HOTK_CLASS "hotkey"
41 #define EEEPC_HOTK_DEVICE_NAME "Hotkey"
42 #define EEEPC_HOTK_HID "ASUS010"
44 #define EEEPC_LOG EEEPC_HOTK_FILE ": "
45 #define EEEPC_ERR KERN_ERR EEEPC_LOG
46 #define EEEPC_WARNING KERN_WARNING EEEPC_LOG
47 #define EEEPC_NOTICE KERN_NOTICE EEEPC_LOG
48 #define EEEPC_INFO KERN_INFO EEEPC_LOG
51 * Definitions for Asus EeePC
53 #define NOTIFY_WLAN_ON 0x10
54 #define NOTIFY_BRN_MIN 0x20
55 #define NOTIFY_BRN_MAX 0x2f
57 enum {
58 DISABLE_ASL_WLAN = 0x0001,
59 DISABLE_ASL_BLUETOOTH = 0x0002,
60 DISABLE_ASL_IRDA = 0x0004,
61 DISABLE_ASL_CAMERA = 0x0008,
62 DISABLE_ASL_TV = 0x0010,
63 DISABLE_ASL_GPS = 0x0020,
64 DISABLE_ASL_DISPLAYSWITCH = 0x0040,
65 DISABLE_ASL_MODEM = 0x0080,
66 DISABLE_ASL_CARDREADER = 0x0100,
67 DISABLE_ASL_3G = 0x0200,
68 DISABLE_ASL_WIMAX = 0x0400,
69 DISABLE_ASL_HWCF = 0x0800
72 enum {
73 CM_ASL_WLAN = 0,
74 CM_ASL_BLUETOOTH,
75 CM_ASL_IRDA,
76 CM_ASL_1394,
77 CM_ASL_CAMERA,
78 CM_ASL_TV,
79 CM_ASL_GPS,
80 CM_ASL_DVDROM,
81 CM_ASL_DISPLAYSWITCH,
82 CM_ASL_PANELBRIGHT,
83 CM_ASL_BIOSFLASH,
84 CM_ASL_ACPIFLASH,
85 CM_ASL_CPUFV,
86 CM_ASL_CPUTEMPERATURE,
87 CM_ASL_FANCPU,
88 CM_ASL_FANCHASSIS,
89 CM_ASL_USBPORT1,
90 CM_ASL_USBPORT2,
91 CM_ASL_USBPORT3,
92 CM_ASL_MODEM,
93 CM_ASL_CARDREADER,
94 CM_ASL_3G,
95 CM_ASL_WIMAX,
96 CM_ASL_HWCF,
97 CM_ASL_LID,
98 CM_ASL_TYPE,
99 CM_ASL_PANELPOWER, /*P901*/
100 CM_ASL_TPD
103 static const char *cm_getv[] = {
104 "WLDG", "BTHG", NULL, NULL,
105 "CAMG", NULL, NULL, NULL,
106 NULL, "PBLG", NULL, NULL,
107 "CFVG", NULL, NULL, NULL,
108 "USBG", NULL, NULL, "MODG",
109 "CRDG", "M3GG", "WIMG", "HWCF",
110 "LIDG", "TYPE", "PBPG", "TPDG"
113 static const char *cm_setv[] = {
114 "WLDS", "BTHS", NULL, NULL,
115 "CAMS", NULL, NULL, NULL,
116 "SDSP", "PBLS", "HDPS", NULL,
117 "CFVS", NULL, NULL, NULL,
118 "USBG", NULL, NULL, "MODS",
119 "CRDS", "M3GS", "WIMS", NULL,
120 NULL, NULL, "PBPS", "TPDS"
123 #define EEEPC_EC "\\_SB.PCI0.SBRG.EC0."
125 #define EEEPC_EC_FAN_PWM EEEPC_EC "SC02" /* Fan PWM duty cycle (%) */
126 #define EEEPC_EC_SC02 0x63
127 #define EEEPC_EC_FAN_HRPM EEEPC_EC "SC05" /* High byte, fan speed (RPM) */
128 #define EEEPC_EC_FAN_LRPM EEEPC_EC "SC06" /* Low byte, fan speed (RPM) */
129 #define EEEPC_EC_FAN_CTRL EEEPC_EC "SFB3" /* Byte containing SF25 */
130 #define EEEPC_EC_SFB3 0xD3
133 * This is the main structure, we can use it to store useful information
134 * about the hotk device
136 struct eeepc_hotk {
137 struct acpi_device *device; /* the device we are in */
138 acpi_handle handle; /* the handle of the hotk device */
139 u32 cm_supported; /* the control methods supported
140 by this BIOS */
141 uint init_flag; /* Init flags */
142 u16 event_count[128]; /* count for each event */
143 struct input_dev *inputdev;
144 u16 *keycode_map;
145 struct rfkill *eeepc_wlan_rfkill;
146 struct rfkill *eeepc_bluetooth_rfkill;
147 struct hotplug_slot *hotplug_slot;
150 /* The actual device the driver binds to */
151 static struct eeepc_hotk *ehotk;
153 /* Platform device/driver */
154 static struct platform_driver platform_driver = {
155 .driver = {
156 .name = EEEPC_HOTK_FILE,
157 .owner = THIS_MODULE,
161 static struct platform_device *platform_device;
163 struct key_entry {
164 char type;
165 u8 code;
166 u16 keycode;
169 enum { KE_KEY, KE_END };
171 static struct key_entry eeepc_keymap[] = {
172 /* Sleep already handled via generic ACPI code */
173 {KE_KEY, 0x10, KEY_WLAN },
174 {KE_KEY, 0x11, KEY_WLAN },
175 {KE_KEY, 0x12, KEY_PROG1 },
176 {KE_KEY, 0x13, KEY_MUTE },
177 {KE_KEY, 0x14, KEY_VOLUMEDOWN },
178 {KE_KEY, 0x15, KEY_VOLUMEUP },
179 {KE_KEY, 0x1a, KEY_COFFEE },
180 {KE_KEY, 0x1b, KEY_ZOOM },
181 {KE_KEY, 0x1c, KEY_PROG2 },
182 {KE_KEY, 0x1d, KEY_PROG3 },
183 {KE_KEY, NOTIFY_BRN_MIN, KEY_BRIGHTNESSDOWN },
184 {KE_KEY, NOTIFY_BRN_MIN + 2, KEY_BRIGHTNESSUP },
185 {KE_KEY, 0x30, KEY_SWITCHVIDEOMODE },
186 {KE_KEY, 0x31, KEY_SWITCHVIDEOMODE },
187 {KE_KEY, 0x32, KEY_SWITCHVIDEOMODE },
188 {KE_END, 0},
192 * The hotkey driver declaration
194 static int eeepc_hotk_add(struct acpi_device *device);
195 static int eeepc_hotk_remove(struct acpi_device *device, int type);
196 static int eeepc_hotk_resume(struct acpi_device *device);
197 static void eeepc_hotk_notify(struct acpi_device *device, u32 event);
199 static const struct acpi_device_id eeepc_device_ids[] = {
200 {EEEPC_HOTK_HID, 0},
201 {"", 0},
203 MODULE_DEVICE_TABLE(acpi, eeepc_device_ids);
205 static struct acpi_driver eeepc_hotk_driver = {
206 .name = EEEPC_HOTK_NAME,
207 .class = EEEPC_HOTK_CLASS,
208 .ids = eeepc_device_ids,
209 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
210 .ops = {
211 .add = eeepc_hotk_add,
212 .remove = eeepc_hotk_remove,
213 .resume = eeepc_hotk_resume,
214 .notify = eeepc_hotk_notify,
218 /* PCI hotplug ops */
219 static int eeepc_get_adapter_status(struct hotplug_slot *slot, u8 *value);
221 static struct hotplug_slot_ops eeepc_hotplug_slot_ops = {
222 .owner = THIS_MODULE,
223 .get_adapter_status = eeepc_get_adapter_status,
224 .get_power_status = eeepc_get_adapter_status,
227 /* The backlight device /sys/class/backlight */
228 static struct backlight_device *eeepc_backlight_device;
230 /* The hwmon device */
231 static struct device *eeepc_hwmon_device;
234 * The backlight class declaration
236 static int read_brightness(struct backlight_device *bd);
237 static int update_bl_status(struct backlight_device *bd);
238 static struct backlight_ops eeepcbl_ops = {
239 .get_brightness = read_brightness,
240 .update_status = update_bl_status,
243 MODULE_AUTHOR("Corentin Chary, Eric Cooper");
244 MODULE_DESCRIPTION(EEEPC_HOTK_NAME);
245 MODULE_LICENSE("GPL");
248 * ACPI Helpers
250 static int write_acpi_int(acpi_handle handle, const char *method, int val,
251 struct acpi_buffer *output)
253 struct acpi_object_list params;
254 union acpi_object in_obj;
255 acpi_status status;
257 params.count = 1;
258 params.pointer = &in_obj;
259 in_obj.type = ACPI_TYPE_INTEGER;
260 in_obj.integer.value = val;
262 status = acpi_evaluate_object(handle, (char *)method, &params, output);
263 return (status == AE_OK ? 0 : -1);
266 static int read_acpi_int(acpi_handle handle, const char *method, int *val)
268 acpi_status status;
269 unsigned long long result;
271 status = acpi_evaluate_integer(handle, (char *)method, NULL, &result);
272 if (ACPI_FAILURE(status)) {
273 *val = -1;
274 return -1;
275 } else {
276 *val = result;
277 return 0;
281 static int set_acpi(int cm, int value)
283 if (ehotk->cm_supported & (0x1 << cm)) {
284 const char *method = cm_setv[cm];
285 if (method == NULL)
286 return -ENODEV;
287 if (write_acpi_int(ehotk->handle, method, value, NULL))
288 printk(EEEPC_WARNING "Error writing %s\n", method);
290 return 0;
293 static int get_acpi(int cm)
295 int value = -1;
296 if ((ehotk->cm_supported & (0x1 << cm))) {
297 const char *method = cm_getv[cm];
298 if (method == NULL)
299 return -ENODEV;
300 if (read_acpi_int(ehotk->handle, method, &value))
301 printk(EEEPC_WARNING "Error reading %s\n", method);
303 return value;
307 * Backlight
309 static int read_brightness(struct backlight_device *bd)
311 return get_acpi(CM_ASL_PANELBRIGHT);
314 static int set_brightness(struct backlight_device *bd, int value)
316 value = max(0, min(15, value));
317 return set_acpi(CM_ASL_PANELBRIGHT, value);
320 static int update_bl_status(struct backlight_device *bd)
322 return set_brightness(bd, bd->props.brightness);
326 * Rfkill helpers
329 static bool eeepc_wlan_rfkill_blocked(void)
331 if (get_acpi(CM_ASL_WLAN) == 1)
332 return false;
333 return true;
336 static int eeepc_rfkill_set(void *data, bool blocked)
338 unsigned long asl = (unsigned long)data;
339 return set_acpi(asl, !blocked);
342 static const struct rfkill_ops eeepc_rfkill_ops = {
343 .set_block = eeepc_rfkill_set,
346 static void __init eeepc_enable_camera(void)
349 * If the following call to set_acpi() fails, it's because there's no
350 * camera so we can ignore the error.
352 set_acpi(CM_ASL_CAMERA, 1);
356 * Sys helpers
358 static int parse_arg(const char *buf, unsigned long count, int *val)
360 if (!count)
361 return 0;
362 if (sscanf(buf, "%i", val) != 1)
363 return -EINVAL;
364 return count;
367 static ssize_t store_sys_acpi(int cm, const char *buf, size_t count)
369 int rv, value;
371 rv = parse_arg(buf, count, &value);
372 if (rv > 0)
373 set_acpi(cm, value);
374 return rv;
377 static ssize_t show_sys_acpi(int cm, char *buf)
379 return sprintf(buf, "%d\n", get_acpi(cm));
382 #define EEEPC_CREATE_DEVICE_ATTR(_name, _cm) \
383 static ssize_t show_##_name(struct device *dev, \
384 struct device_attribute *attr, \
385 char *buf) \
387 return show_sys_acpi(_cm, buf); \
389 static ssize_t store_##_name(struct device *dev, \
390 struct device_attribute *attr, \
391 const char *buf, size_t count) \
393 return store_sys_acpi(_cm, buf, count); \
395 static struct device_attribute dev_attr_##_name = { \
396 .attr = { \
397 .name = __stringify(_name), \
398 .mode = 0644 }, \
399 .show = show_##_name, \
400 .store = store_##_name, \
403 EEEPC_CREATE_DEVICE_ATTR(camera, CM_ASL_CAMERA);
404 EEEPC_CREATE_DEVICE_ATTR(cardr, CM_ASL_CARDREADER);
405 EEEPC_CREATE_DEVICE_ATTR(disp, CM_ASL_DISPLAYSWITCH);
407 struct eeepc_cpufv {
408 int num;
409 int cur;
412 static int get_cpufv(struct eeepc_cpufv *c)
414 c->cur = get_acpi(CM_ASL_CPUFV);
415 c->num = (c->cur >> 8) & 0xff;
416 c->cur &= 0xff;
417 if (c->cur < 0 || c->num <= 0 || c->num > 12)
418 return -ENODEV;
419 return 0;
422 static ssize_t show_available_cpufv(struct device *dev,
423 struct device_attribute *attr,
424 char *buf)
426 struct eeepc_cpufv c;
427 int i;
428 ssize_t len = 0;
430 if (get_cpufv(&c))
431 return -ENODEV;
432 for (i = 0; i < c.num; i++)
433 len += sprintf(buf + len, "%d ", i);
434 len += sprintf(buf + len, "\n");
435 return len;
438 static ssize_t show_cpufv(struct device *dev,
439 struct device_attribute *attr,
440 char *buf)
442 struct eeepc_cpufv c;
444 if (get_cpufv(&c))
445 return -ENODEV;
446 return sprintf(buf, "%#x\n", (c.num << 8) | c.cur);
449 static ssize_t store_cpufv(struct device *dev,
450 struct device_attribute *attr,
451 const char *buf, size_t count)
453 struct eeepc_cpufv c;
454 int rv, value;
456 if (get_cpufv(&c))
457 return -ENODEV;
458 rv = parse_arg(buf, count, &value);
459 if (rv < 0)
460 return rv;
461 if (!rv || value < 0 || value >= c.num)
462 return -EINVAL;
463 set_acpi(CM_ASL_CPUFV, value);
464 return rv;
467 static struct device_attribute dev_attr_cpufv = {
468 .attr = {
469 .name = "cpufv",
470 .mode = 0644 },
471 .show = show_cpufv,
472 .store = store_cpufv
475 static struct device_attribute dev_attr_available_cpufv = {
476 .attr = {
477 .name = "available_cpufv",
478 .mode = 0444 },
479 .show = show_available_cpufv
482 static struct attribute *platform_attributes[] = {
483 &dev_attr_camera.attr,
484 &dev_attr_cardr.attr,
485 &dev_attr_disp.attr,
486 &dev_attr_cpufv.attr,
487 &dev_attr_available_cpufv.attr,
488 NULL
491 static struct attribute_group platform_attribute_group = {
492 .attrs = platform_attributes
496 * Hotkey functions
498 static struct key_entry *eepc_get_entry_by_scancode(int code)
500 struct key_entry *key;
502 for (key = eeepc_keymap; key->type != KE_END; key++)
503 if (code == key->code)
504 return key;
506 return NULL;
509 static struct key_entry *eepc_get_entry_by_keycode(int code)
511 struct key_entry *key;
513 for (key = eeepc_keymap; key->type != KE_END; key++)
514 if (code == key->keycode && key->type == KE_KEY)
515 return key;
517 return NULL;
520 static int eeepc_getkeycode(struct input_dev *dev, int scancode, int *keycode)
522 struct key_entry *key = eepc_get_entry_by_scancode(scancode);
524 if (key && key->type == KE_KEY) {
525 *keycode = key->keycode;
526 return 0;
529 return -EINVAL;
532 static int eeepc_setkeycode(struct input_dev *dev, int scancode, int keycode)
534 struct key_entry *key;
535 int old_keycode;
537 if (keycode < 0 || keycode > KEY_MAX)
538 return -EINVAL;
540 key = eepc_get_entry_by_scancode(scancode);
541 if (key && key->type == KE_KEY) {
542 old_keycode = key->keycode;
543 key->keycode = keycode;
544 set_bit(keycode, dev->keybit);
545 if (!eepc_get_entry_by_keycode(old_keycode))
546 clear_bit(old_keycode, dev->keybit);
547 return 0;
550 return -EINVAL;
553 static int eeepc_hotk_check(void)
555 const struct key_entry *key;
556 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
557 int result;
559 result = acpi_bus_get_status(ehotk->device);
560 if (result)
561 return result;
562 if (ehotk->device->status.present) {
563 if (write_acpi_int(ehotk->handle, "INIT", ehotk->init_flag,
564 &buffer)) {
565 printk(EEEPC_ERR "Hotkey initialization failed\n");
566 return -ENODEV;
567 } else {
568 printk(EEEPC_NOTICE "Hotkey init flags 0x%x\n",
569 ehotk->init_flag);
571 /* get control methods supported */
572 if (read_acpi_int(ehotk->handle, "CMSG"
573 , &ehotk->cm_supported)) {
574 printk(EEEPC_ERR
575 "Get control methods supported failed\n");
576 return -ENODEV;
577 } else {
578 printk(EEEPC_INFO
579 "Get control methods supported: 0x%x\n",
580 ehotk->cm_supported);
582 ehotk->inputdev = input_allocate_device();
583 if (!ehotk->inputdev) {
584 printk(EEEPC_INFO "Unable to allocate input device\n");
585 return 0;
587 ehotk->inputdev->name = "Asus EeePC extra buttons";
588 ehotk->inputdev->phys = EEEPC_HOTK_FILE "/input0";
589 ehotk->inputdev->id.bustype = BUS_HOST;
590 ehotk->inputdev->getkeycode = eeepc_getkeycode;
591 ehotk->inputdev->setkeycode = eeepc_setkeycode;
593 for (key = eeepc_keymap; key->type != KE_END; key++) {
594 switch (key->type) {
595 case KE_KEY:
596 set_bit(EV_KEY, ehotk->inputdev->evbit);
597 set_bit(key->keycode, ehotk->inputdev->keybit);
598 break;
601 result = input_register_device(ehotk->inputdev);
602 if (result) {
603 printk(EEEPC_INFO "Unable to register input device\n");
604 input_free_device(ehotk->inputdev);
605 return 0;
607 } else {
608 printk(EEEPC_ERR "Hotkey device not present, aborting\n");
609 return -EINVAL;
611 return 0;
614 static int notify_brn(void)
616 /* returns the *previous* brightness, or -1 */
617 struct backlight_device *bd = eeepc_backlight_device;
618 if (bd) {
619 int old = bd->props.brightness;
620 bd->props.brightness = read_brightness(bd);
621 return old;
623 return -1;
626 static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot,
627 u8 *value)
629 int val = get_acpi(CM_ASL_WLAN);
631 if (val == 1 || val == 0)
632 *value = val;
633 else
634 return -EINVAL;
636 return 0;
639 static void eeepc_rfkill_hotplug(void)
641 struct pci_dev *dev;
642 struct pci_bus *bus = pci_find_bus(0, 1);
643 bool blocked;
645 if (!bus) {
646 printk(EEEPC_WARNING "Unable to find PCI bus 1?\n");
647 return;
650 blocked = eeepc_wlan_rfkill_blocked();
651 if (!blocked) {
652 dev = pci_get_slot(bus, 0);
653 if (dev) {
654 /* Device already present */
655 pci_dev_put(dev);
656 return;
658 dev = pci_scan_single_device(bus, 0);
659 if (dev) {
660 pci_bus_assign_resources(bus);
661 if (pci_bus_add_device(dev))
662 printk(EEEPC_ERR "Unable to hotplug wifi\n");
664 } else {
665 dev = pci_get_slot(bus, 0);
666 if (dev) {
667 pci_remove_bus_device(dev);
668 pci_dev_put(dev);
672 rfkill_set_sw_state(ehotk->eeepc_wlan_rfkill, blocked);
675 static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
677 if (event != ACPI_NOTIFY_BUS_CHECK)
678 return;
680 eeepc_rfkill_hotplug();
683 static void eeepc_hotk_notify(struct acpi_device *device, u32 event)
685 static struct key_entry *key;
686 u16 count;
687 int brn = -ENODEV;
689 if (!ehotk)
690 return;
691 if (event > ACPI_MAX_SYS_NOTIFY)
692 return;
693 if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX)
694 brn = notify_brn();
695 count = ehotk->event_count[event % 128]++;
696 acpi_bus_generate_proc_event(ehotk->device, event, count);
697 acpi_bus_generate_netlink_event(ehotk->device->pnp.device_class,
698 dev_name(&ehotk->device->dev), event,
699 count);
700 if (ehotk->inputdev) {
701 if (brn != -ENODEV) {
702 /* brightness-change events need special
703 * handling for conversion to key events
705 if (brn < 0)
706 brn = event;
707 else
708 brn += NOTIFY_BRN_MIN;
709 if (event < brn)
710 event = NOTIFY_BRN_MIN; /* brightness down */
711 else if (event > brn)
712 event = NOTIFY_BRN_MIN + 2; /* ... up */
713 else
714 event = NOTIFY_BRN_MIN + 1; /* ... unchanged */
716 key = eepc_get_entry_by_scancode(event);
717 if (key) {
718 switch (key->type) {
719 case KE_KEY:
720 input_report_key(ehotk->inputdev, key->keycode,
722 input_sync(ehotk->inputdev);
723 input_report_key(ehotk->inputdev, key->keycode,
725 input_sync(ehotk->inputdev);
726 break;
732 static int eeepc_register_rfkill_notifier(char *node)
734 acpi_status status = AE_OK;
735 acpi_handle handle;
737 status = acpi_get_handle(NULL, node, &handle);
739 if (ACPI_SUCCESS(status)) {
740 status = acpi_install_notify_handler(handle,
741 ACPI_SYSTEM_NOTIFY,
742 eeepc_rfkill_notify,
743 NULL);
744 if (ACPI_FAILURE(status))
745 printk(EEEPC_WARNING
746 "Failed to register notify on %s\n", node);
747 } else
748 return -ENODEV;
750 return 0;
753 static void eeepc_unregister_rfkill_notifier(char *node)
755 acpi_status status = AE_OK;
756 acpi_handle handle;
758 status = acpi_get_handle(NULL, node, &handle);
760 if (ACPI_SUCCESS(status)) {
761 status = acpi_remove_notify_handler(handle,
762 ACPI_SYSTEM_NOTIFY,
763 eeepc_rfkill_notify);
764 if (ACPI_FAILURE(status))
765 printk(EEEPC_ERR
766 "Error removing rfkill notify handler %s\n",
767 node);
771 static void eeepc_cleanup_pci_hotplug(struct hotplug_slot *hotplug_slot)
773 kfree(hotplug_slot->info);
774 kfree(hotplug_slot);
777 static int eeepc_setup_pci_hotplug(void)
779 int ret = -ENOMEM;
780 struct pci_bus *bus = pci_find_bus(0, 1);
782 if (!bus) {
783 printk(EEEPC_ERR "Unable to find wifi PCI bus\n");
784 return -ENODEV;
787 ehotk->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
788 if (!ehotk->hotplug_slot)
789 goto error_slot;
791 ehotk->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info),
792 GFP_KERNEL);
793 if (!ehotk->hotplug_slot->info)
794 goto error_info;
796 ehotk->hotplug_slot->private = ehotk;
797 ehotk->hotplug_slot->release = &eeepc_cleanup_pci_hotplug;
798 ehotk->hotplug_slot->ops = &eeepc_hotplug_slot_ops;
799 eeepc_get_adapter_status(ehotk->hotplug_slot,
800 &ehotk->hotplug_slot->info->adapter_status);
802 ret = pci_hp_register(ehotk->hotplug_slot, bus, 0, "eeepc-wifi");
803 if (ret) {
804 printk(EEEPC_ERR "Unable to register hotplug slot - %d\n", ret);
805 goto error_register;
808 return 0;
810 error_register:
811 kfree(ehotk->hotplug_slot->info);
812 error_info:
813 kfree(ehotk->hotplug_slot);
814 ehotk->hotplug_slot = NULL;
815 error_slot:
816 return ret;
819 static int eeepc_hotk_add(struct acpi_device *device)
821 int result;
823 if (!device)
824 return -EINVAL;
825 printk(EEEPC_NOTICE EEEPC_HOTK_NAME "\n");
826 ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL);
827 if (!ehotk)
828 return -ENOMEM;
829 ehotk->init_flag = DISABLE_ASL_WLAN | DISABLE_ASL_DISPLAYSWITCH;
830 ehotk->handle = device->handle;
831 strcpy(acpi_device_name(device), EEEPC_HOTK_DEVICE_NAME);
832 strcpy(acpi_device_class(device), EEEPC_HOTK_CLASS);
833 device->driver_data = ehotk;
834 ehotk->device = device;
835 result = eeepc_hotk_check();
836 if (result)
837 goto ehotk_fail;
839 eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6");
840 eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7");
842 if (get_acpi(CM_ASL_WLAN) != -1) {
843 ehotk->eeepc_wlan_rfkill = rfkill_alloc("eeepc-wlan",
844 &device->dev,
845 RFKILL_TYPE_WLAN,
846 &eeepc_rfkill_ops,
847 (void *)CM_ASL_WLAN);
849 if (!ehotk->eeepc_wlan_rfkill)
850 goto wlan_fail;
852 rfkill_init_sw_state(ehotk->eeepc_wlan_rfkill,
853 get_acpi(CM_ASL_WLAN) != 1);
854 result = rfkill_register(ehotk->eeepc_wlan_rfkill);
855 if (result)
856 goto wlan_fail;
859 if (get_acpi(CM_ASL_BLUETOOTH) != -1) {
860 ehotk->eeepc_bluetooth_rfkill =
861 rfkill_alloc("eeepc-bluetooth",
862 &device->dev,
863 RFKILL_TYPE_BLUETOOTH,
864 &eeepc_rfkill_ops,
865 (void *)CM_ASL_BLUETOOTH);
867 if (!ehotk->eeepc_bluetooth_rfkill)
868 goto bluetooth_fail;
870 rfkill_init_sw_state(ehotk->eeepc_bluetooth_rfkill,
871 get_acpi(CM_ASL_BLUETOOTH) != 1);
872 result = rfkill_register(ehotk->eeepc_bluetooth_rfkill);
873 if (result)
874 goto bluetooth_fail;
877 result = eeepc_setup_pci_hotplug();
879 * If we get -EBUSY then something else is handling the PCI hotplug -
880 * don't fail in this case
882 if (result == -EBUSY)
883 return 0;
884 else if (result)
885 goto pci_fail;
887 return 0;
889 pci_fail:
890 if (ehotk->eeepc_bluetooth_rfkill)
891 rfkill_unregister(ehotk->eeepc_bluetooth_rfkill);
892 bluetooth_fail:
893 rfkill_destroy(ehotk->eeepc_bluetooth_rfkill);
894 rfkill_unregister(ehotk->eeepc_wlan_rfkill);
895 wlan_fail:
896 rfkill_destroy(ehotk->eeepc_wlan_rfkill);
897 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6");
898 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7");
899 ehotk_fail:
900 kfree(ehotk);
901 ehotk = NULL;
903 return result;
906 static int eeepc_hotk_remove(struct acpi_device *device, int type)
908 if (!device || !acpi_driver_data(device))
909 return -EINVAL;
911 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6");
912 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7");
913 if (ehotk->hotplug_slot)
914 pci_hp_deregister(ehotk->hotplug_slot);
916 kfree(ehotk);
917 return 0;
920 static int eeepc_hotk_resume(struct acpi_device *device)
922 if (ehotk->eeepc_wlan_rfkill) {
923 bool wlan;
925 /* Workaround - it seems that _PTS disables the wireless
926 without notification or changing the value read by WLAN.
927 Normally this is fine because the correct value is restored
928 from the non-volatile storage on resume, but we need to do
929 it ourself if case suspend is aborted, or we lose wireless.
931 wlan = get_acpi(CM_ASL_WLAN);
932 set_acpi(CM_ASL_WLAN, wlan);
934 rfkill_set_sw_state(ehotk->eeepc_wlan_rfkill,
935 wlan != 1);
937 eeepc_rfkill_hotplug();
940 if (ehotk->eeepc_bluetooth_rfkill)
941 rfkill_set_sw_state(ehotk->eeepc_bluetooth_rfkill,
942 get_acpi(CM_ASL_BLUETOOTH) != 1);
944 return 0;
948 * Hwmon
950 static int eeepc_get_fan_pwm(void)
952 int value = 0;
954 read_acpi_int(NULL, EEEPC_EC_FAN_PWM, &value);
955 value = value * 255 / 100;
956 return (value);
959 static void eeepc_set_fan_pwm(int value)
961 value = SENSORS_LIMIT(value, 0, 255);
962 value = value * 100 / 255;
963 ec_write(EEEPC_EC_SC02, value);
966 static int eeepc_get_fan_rpm(void)
968 int high = 0;
969 int low = 0;
971 read_acpi_int(NULL, EEEPC_EC_FAN_HRPM, &high);
972 read_acpi_int(NULL, EEEPC_EC_FAN_LRPM, &low);
973 return (high << 8 | low);
976 static int eeepc_get_fan_ctrl(void)
978 int value = 0;
980 read_acpi_int(NULL, EEEPC_EC_FAN_CTRL, &value);
981 return ((value & 0x02 ? 1 : 0));
984 static void eeepc_set_fan_ctrl(int manual)
986 int value = 0;
988 read_acpi_int(NULL, EEEPC_EC_FAN_CTRL, &value);
989 if (manual)
990 value |= 0x02;
991 else
992 value &= ~0x02;
993 ec_write(EEEPC_EC_SFB3, value);
996 static ssize_t store_sys_hwmon(void (*set)(int), const char *buf, size_t count)
998 int rv, value;
1000 rv = parse_arg(buf, count, &value);
1001 if (rv > 0)
1002 set(value);
1003 return rv;
1006 static ssize_t show_sys_hwmon(int (*get)(void), char *buf)
1008 return sprintf(buf, "%d\n", get());
1011 #define EEEPC_CREATE_SENSOR_ATTR(_name, _mode, _set, _get) \
1012 static ssize_t show_##_name(struct device *dev, \
1013 struct device_attribute *attr, \
1014 char *buf) \
1016 return show_sys_hwmon(_set, buf); \
1018 static ssize_t store_##_name(struct device *dev, \
1019 struct device_attribute *attr, \
1020 const char *buf, size_t count) \
1022 return store_sys_hwmon(_get, buf, count); \
1024 static SENSOR_DEVICE_ATTR(_name, _mode, show_##_name, store_##_name, 0);
1026 EEEPC_CREATE_SENSOR_ATTR(fan1_input, S_IRUGO, eeepc_get_fan_rpm, NULL);
1027 EEEPC_CREATE_SENSOR_ATTR(pwm1, S_IRUGO | S_IWUSR,
1028 eeepc_get_fan_pwm, eeepc_set_fan_pwm);
1029 EEEPC_CREATE_SENSOR_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
1030 eeepc_get_fan_ctrl, eeepc_set_fan_ctrl);
1032 static ssize_t
1033 show_name(struct device *dev, struct device_attribute *attr, char *buf)
1035 return sprintf(buf, "eeepc\n");
1037 static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0);
1039 static struct attribute *hwmon_attributes[] = {
1040 &sensor_dev_attr_pwm1.dev_attr.attr,
1041 &sensor_dev_attr_fan1_input.dev_attr.attr,
1042 &sensor_dev_attr_pwm1_enable.dev_attr.attr,
1043 &sensor_dev_attr_name.dev_attr.attr,
1044 NULL
1047 static struct attribute_group hwmon_attribute_group = {
1048 .attrs = hwmon_attributes
1052 * exit/init
1054 static void eeepc_backlight_exit(void)
1056 if (eeepc_backlight_device)
1057 backlight_device_unregister(eeepc_backlight_device);
1058 eeepc_backlight_device = NULL;
1061 static void eeepc_rfkill_exit(void)
1063 if (ehotk->eeepc_wlan_rfkill)
1064 rfkill_unregister(ehotk->eeepc_wlan_rfkill);
1065 if (ehotk->eeepc_bluetooth_rfkill)
1066 rfkill_unregister(ehotk->eeepc_bluetooth_rfkill);
1069 static void eeepc_input_exit(void)
1071 if (ehotk->inputdev)
1072 input_unregister_device(ehotk->inputdev);
1075 static void eeepc_hwmon_exit(void)
1077 struct device *hwmon;
1079 hwmon = eeepc_hwmon_device;
1080 if (!hwmon)
1081 return ;
1082 sysfs_remove_group(&hwmon->kobj,
1083 &hwmon_attribute_group);
1084 hwmon_device_unregister(hwmon);
1085 eeepc_hwmon_device = NULL;
1088 static void __exit eeepc_laptop_exit(void)
1090 eeepc_backlight_exit();
1091 eeepc_rfkill_exit();
1092 eeepc_input_exit();
1093 eeepc_hwmon_exit();
1094 acpi_bus_unregister_driver(&eeepc_hotk_driver);
1095 sysfs_remove_group(&platform_device->dev.kobj,
1096 &platform_attribute_group);
1097 platform_device_unregister(platform_device);
1098 platform_driver_unregister(&platform_driver);
1101 static int eeepc_backlight_init(struct device *dev)
1103 struct backlight_device *bd;
1105 bd = backlight_device_register(EEEPC_HOTK_FILE, dev,
1106 NULL, &eeepcbl_ops);
1107 if (IS_ERR(bd)) {
1108 printk(EEEPC_ERR
1109 "Could not register eeepc backlight device\n");
1110 eeepc_backlight_device = NULL;
1111 return PTR_ERR(bd);
1113 eeepc_backlight_device = bd;
1114 bd->props.max_brightness = 15;
1115 bd->props.brightness = read_brightness(NULL);
1116 bd->props.power = FB_BLANK_UNBLANK;
1117 backlight_update_status(bd);
1118 return 0;
1121 static int eeepc_hwmon_init(struct device *dev)
1123 struct device *hwmon;
1124 int result;
1126 hwmon = hwmon_device_register(dev);
1127 if (IS_ERR(hwmon)) {
1128 printk(EEEPC_ERR
1129 "Could not register eeepc hwmon device\n");
1130 eeepc_hwmon_device = NULL;
1131 return PTR_ERR(hwmon);
1133 eeepc_hwmon_device = hwmon;
1134 result = sysfs_create_group(&hwmon->kobj,
1135 &hwmon_attribute_group);
1136 if (result)
1137 eeepc_hwmon_exit();
1138 return result;
1141 static int __init eeepc_laptop_init(void)
1143 struct device *dev;
1144 int result;
1146 if (acpi_disabled)
1147 return -ENODEV;
1148 result = acpi_bus_register_driver(&eeepc_hotk_driver);
1149 if (result < 0)
1150 return result;
1151 if (!ehotk) {
1152 acpi_bus_unregister_driver(&eeepc_hotk_driver);
1153 return -ENODEV;
1155 dev = acpi_get_physical_device(ehotk->device->handle);
1157 if (!acpi_video_backlight_support()) {
1158 result = eeepc_backlight_init(dev);
1159 if (result)
1160 goto fail_backlight;
1161 } else
1162 printk(EEEPC_INFO "Backlight controlled by ACPI video "
1163 "driver\n");
1165 result = eeepc_hwmon_init(dev);
1166 if (result)
1167 goto fail_hwmon;
1169 eeepc_enable_camera();
1171 /* Register platform stuff */
1172 result = platform_driver_register(&platform_driver);
1173 if (result)
1174 goto fail_platform_driver;
1175 platform_device = platform_device_alloc(EEEPC_HOTK_FILE, -1);
1176 if (!platform_device) {
1177 result = -ENOMEM;
1178 goto fail_platform_device1;
1180 result = platform_device_add(platform_device);
1181 if (result)
1182 goto fail_platform_device2;
1183 result = sysfs_create_group(&platform_device->dev.kobj,
1184 &platform_attribute_group);
1185 if (result)
1186 goto fail_sysfs;
1187 return 0;
1188 fail_sysfs:
1189 platform_device_del(platform_device);
1190 fail_platform_device2:
1191 platform_device_put(platform_device);
1192 fail_platform_device1:
1193 platform_driver_unregister(&platform_driver);
1194 fail_platform_driver:
1195 eeepc_hwmon_exit();
1196 fail_hwmon:
1197 eeepc_backlight_exit();
1198 fail_backlight:
1199 eeepc_input_exit();
1200 eeepc_rfkill_exit();
1201 return result;
1204 module_init(eeepc_laptop_init);
1205 module_exit(eeepc_laptop_exit);