eeepc-laptop: makes get_acpi() returns -ENODEV
[linux-2.6/linux-acpi-2.6.git] / drivers / platform / x86 / eeepc-laptop.c
blob19cc9ae7db5a7077f0b46b26c1c7439e055b2a4a
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 hotplug_slot *hotplug_slot;
147 /* The actual device the driver binds to */
148 static struct eeepc_hotk *ehotk;
150 /* Platform device/driver */
151 static struct platform_driver platform_driver = {
152 .driver = {
153 .name = EEEPC_HOTK_FILE,
154 .owner = THIS_MODULE,
158 static struct platform_device *platform_device;
160 struct key_entry {
161 char type;
162 u8 code;
163 u16 keycode;
166 enum { KE_KEY, KE_END };
168 static struct key_entry eeepc_keymap[] = {
169 /* Sleep already handled via generic ACPI code */
170 {KE_KEY, 0x10, KEY_WLAN },
171 {KE_KEY, 0x11, KEY_WLAN },
172 {KE_KEY, 0x12, KEY_PROG1 },
173 {KE_KEY, 0x13, KEY_MUTE },
174 {KE_KEY, 0x14, KEY_VOLUMEDOWN },
175 {KE_KEY, 0x15, KEY_VOLUMEUP },
176 {KE_KEY, 0x1a, KEY_COFFEE },
177 {KE_KEY, 0x1b, KEY_ZOOM },
178 {KE_KEY, 0x1c, KEY_PROG2 },
179 {KE_KEY, 0x1d, KEY_PROG3 },
180 {KE_KEY, NOTIFY_BRN_MIN, KEY_BRIGHTNESSDOWN },
181 {KE_KEY, NOTIFY_BRN_MIN + 2, KEY_BRIGHTNESSUP },
182 {KE_KEY, 0x30, KEY_SWITCHVIDEOMODE },
183 {KE_KEY, 0x31, KEY_SWITCHVIDEOMODE },
184 {KE_KEY, 0x32, KEY_SWITCHVIDEOMODE },
185 {KE_END, 0},
189 * The hotkey driver declaration
191 static int eeepc_hotk_add(struct acpi_device *device);
192 static int eeepc_hotk_remove(struct acpi_device *device, int type);
193 static int eeepc_hotk_resume(struct acpi_device *device);
194 static void eeepc_hotk_notify(struct acpi_device *device, u32 event);
196 static const struct acpi_device_id eeepc_device_ids[] = {
197 {EEEPC_HOTK_HID, 0},
198 {"", 0},
200 MODULE_DEVICE_TABLE(acpi, eeepc_device_ids);
202 static struct acpi_driver eeepc_hotk_driver = {
203 .name = EEEPC_HOTK_NAME,
204 .class = EEEPC_HOTK_CLASS,
205 .ids = eeepc_device_ids,
206 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
207 .ops = {
208 .add = eeepc_hotk_add,
209 .remove = eeepc_hotk_remove,
210 .resume = eeepc_hotk_resume,
211 .notify = eeepc_hotk_notify,
215 /* PCI hotplug ops */
216 static int eeepc_get_adapter_status(struct hotplug_slot *slot, u8 *value);
218 static struct hotplug_slot_ops eeepc_hotplug_slot_ops = {
219 .owner = THIS_MODULE,
220 .get_adapter_status = eeepc_get_adapter_status,
221 .get_power_status = eeepc_get_adapter_status,
224 /* The backlight device /sys/class/backlight */
225 static struct backlight_device *eeepc_backlight_device;
227 /* The hwmon device */
228 static struct device *eeepc_hwmon_device;
231 * The backlight class declaration
233 static int read_brightness(struct backlight_device *bd);
234 static int update_bl_status(struct backlight_device *bd);
235 static struct backlight_ops eeepcbl_ops = {
236 .get_brightness = read_brightness,
237 .update_status = update_bl_status,
240 MODULE_AUTHOR("Corentin Chary, Eric Cooper");
241 MODULE_DESCRIPTION(EEEPC_HOTK_NAME);
242 MODULE_LICENSE("GPL");
245 * ACPI Helpers
247 static int write_acpi_int(acpi_handle handle, const char *method, int val,
248 struct acpi_buffer *output)
250 struct acpi_object_list params;
251 union acpi_object in_obj;
252 acpi_status status;
254 params.count = 1;
255 params.pointer = &in_obj;
256 in_obj.type = ACPI_TYPE_INTEGER;
257 in_obj.integer.value = val;
259 status = acpi_evaluate_object(handle, (char *)method, &params, output);
260 return (status == AE_OK ? 0 : -1);
263 static int read_acpi_int(acpi_handle handle, const char *method, int *val)
265 acpi_status status;
266 unsigned long long result;
268 status = acpi_evaluate_integer(handle, (char *)method, NULL, &result);
269 if (ACPI_FAILURE(status)) {
270 *val = -1;
271 return -1;
272 } else {
273 *val = result;
274 return 0;
278 static int set_acpi(int cm, int value)
280 if (ehotk->cm_supported & (0x1 << cm)) {
281 const char *method = cm_setv[cm];
282 if (method == NULL)
283 return -ENODEV;
284 if (write_acpi_int(ehotk->handle, method, value, NULL))
285 pr_warning("Error writing %s\n", method);
287 return 0;
290 static int get_acpi(int cm)
292 int value = -ENODEV;
293 if ((ehotk->cm_supported & (0x1 << cm))) {
294 const char *method = cm_getv[cm];
295 if (method == NULL)
296 return -ENODEV;
297 if (read_acpi_int(ehotk->handle, method, &value))
298 pr_warning("Error reading %s\n", method);
300 return value;
304 * Backlight
306 static int read_brightness(struct backlight_device *bd)
308 return get_acpi(CM_ASL_PANELBRIGHT);
311 static int set_brightness(struct backlight_device *bd, int value)
313 value = max(0, min(15, value));
314 return set_acpi(CM_ASL_PANELBRIGHT, value);
317 static int update_bl_status(struct backlight_device *bd)
319 return set_brightness(bd, bd->props.brightness);
323 * Rfkill helpers
326 static bool eeepc_wlan_rfkill_blocked(void)
328 if (get_acpi(CM_ASL_WLAN) == 1)
329 return false;
330 return true;
333 static int eeepc_rfkill_set(void *data, bool blocked)
335 unsigned long asl = (unsigned long)data;
336 return set_acpi(asl, !blocked);
339 static const struct rfkill_ops eeepc_rfkill_ops = {
340 .set_block = eeepc_rfkill_set,
343 static void __init eeepc_enable_camera(void)
346 * If the following call to set_acpi() fails, it's because there's no
347 * camera so we can ignore the error.
349 set_acpi(CM_ASL_CAMERA, 1);
353 * Sys helpers
355 static int parse_arg(const char *buf, unsigned long count, int *val)
357 if (!count)
358 return 0;
359 if (sscanf(buf, "%i", val) != 1)
360 return -EINVAL;
361 return count;
364 static ssize_t store_sys_acpi(int cm, const char *buf, size_t count)
366 int rv, value;
368 rv = parse_arg(buf, count, &value);
369 if (rv > 0)
370 value = set_acpi(cm, value);
371 if (value < 0)
372 return value;
373 return rv;
376 static ssize_t show_sys_acpi(int cm, char *buf)
378 int value = get_acpi(cm);
380 if (value < 0)
381 return value;
382 return sprintf(buf, "%d\n", value);
385 #define EEEPC_CREATE_DEVICE_ATTR(_name, _cm) \
386 static ssize_t show_##_name(struct device *dev, \
387 struct device_attribute *attr, \
388 char *buf) \
390 return show_sys_acpi(_cm, buf); \
392 static ssize_t store_##_name(struct device *dev, \
393 struct device_attribute *attr, \
394 const char *buf, size_t count) \
396 return store_sys_acpi(_cm, buf, count); \
398 static struct device_attribute dev_attr_##_name = { \
399 .attr = { \
400 .name = __stringify(_name), \
401 .mode = 0644 }, \
402 .show = show_##_name, \
403 .store = store_##_name, \
406 EEEPC_CREATE_DEVICE_ATTR(camera, CM_ASL_CAMERA);
407 EEEPC_CREATE_DEVICE_ATTR(cardr, CM_ASL_CARDREADER);
408 EEEPC_CREATE_DEVICE_ATTR(disp, CM_ASL_DISPLAYSWITCH);
410 struct eeepc_cpufv {
411 int num;
412 int cur;
415 static int get_cpufv(struct eeepc_cpufv *c)
417 c->cur = get_acpi(CM_ASL_CPUFV);
418 c->num = (c->cur >> 8) & 0xff;
419 c->cur &= 0xff;
420 if (c->cur < 0 || c->num <= 0 || c->num > 12)
421 return -ENODEV;
422 return 0;
425 static ssize_t show_available_cpufv(struct device *dev,
426 struct device_attribute *attr,
427 char *buf)
429 struct eeepc_cpufv c;
430 int i;
431 ssize_t len = 0;
433 if (get_cpufv(&c))
434 return -ENODEV;
435 for (i = 0; i < c.num; i++)
436 len += sprintf(buf + len, "%d ", i);
437 len += sprintf(buf + len, "\n");
438 return len;
441 static ssize_t show_cpufv(struct device *dev,
442 struct device_attribute *attr,
443 char *buf)
445 struct eeepc_cpufv c;
447 if (get_cpufv(&c))
448 return -ENODEV;
449 return sprintf(buf, "%#x\n", (c.num << 8) | c.cur);
452 static ssize_t store_cpufv(struct device *dev,
453 struct device_attribute *attr,
454 const char *buf, size_t count)
456 struct eeepc_cpufv c;
457 int rv, value;
459 if (get_cpufv(&c))
460 return -ENODEV;
461 rv = parse_arg(buf, count, &value);
462 if (rv < 0)
463 return rv;
464 if (!rv || value < 0 || value >= c.num)
465 return -EINVAL;
466 set_acpi(CM_ASL_CPUFV, value);
467 return rv;
470 static struct device_attribute dev_attr_cpufv = {
471 .attr = {
472 .name = "cpufv",
473 .mode = 0644 },
474 .show = show_cpufv,
475 .store = store_cpufv
478 static struct device_attribute dev_attr_available_cpufv = {
479 .attr = {
480 .name = "available_cpufv",
481 .mode = 0444 },
482 .show = show_available_cpufv
485 static struct attribute *platform_attributes[] = {
486 &dev_attr_camera.attr,
487 &dev_attr_cardr.attr,
488 &dev_attr_disp.attr,
489 &dev_attr_cpufv.attr,
490 &dev_attr_available_cpufv.attr,
491 NULL
494 static struct attribute_group platform_attribute_group = {
495 .attrs = platform_attributes
499 * Hotkey functions
501 static struct key_entry *eepc_get_entry_by_scancode(int code)
503 struct key_entry *key;
505 for (key = eeepc_keymap; key->type != KE_END; key++)
506 if (code == key->code)
507 return key;
509 return NULL;
512 static struct key_entry *eepc_get_entry_by_keycode(int code)
514 struct key_entry *key;
516 for (key = eeepc_keymap; key->type != KE_END; key++)
517 if (code == key->keycode && key->type == KE_KEY)
518 return key;
520 return NULL;
523 static int eeepc_getkeycode(struct input_dev *dev, int scancode, int *keycode)
525 struct key_entry *key = eepc_get_entry_by_scancode(scancode);
527 if (key && key->type == KE_KEY) {
528 *keycode = key->keycode;
529 return 0;
532 return -EINVAL;
535 static int eeepc_setkeycode(struct input_dev *dev, int scancode, int keycode)
537 struct key_entry *key;
538 int old_keycode;
540 if (keycode < 0 || keycode > KEY_MAX)
541 return -EINVAL;
543 key = eepc_get_entry_by_scancode(scancode);
544 if (key && key->type == KE_KEY) {
545 old_keycode = key->keycode;
546 key->keycode = keycode;
547 set_bit(keycode, dev->keybit);
548 if (!eepc_get_entry_by_keycode(old_keycode))
549 clear_bit(old_keycode, dev->keybit);
550 return 0;
553 return -EINVAL;
556 static int eeepc_hotk_check(void)
558 const struct key_entry *key;
559 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
560 int result;
562 result = acpi_bus_get_status(ehotk->device);
563 if (result)
564 return result;
565 if (ehotk->device->status.present) {
566 if (write_acpi_int(ehotk->handle, "INIT", ehotk->init_flag,
567 &buffer)) {
568 pr_err("Hotkey initialization failed\n");
569 return -ENODEV;
570 } else {
571 pr_notice("Hotkey init flags 0x%x\n", ehotk->init_flag);
573 /* get control methods supported */
574 if (read_acpi_int(ehotk->handle, "CMSG"
575 , &ehotk->cm_supported)) {
576 pr_err("Get control methods supported failed\n");
577 return -ENODEV;
578 } else {
579 pr_info("Get control methods supported: 0x%x\n",
580 ehotk->cm_supported);
582 ehotk->inputdev = input_allocate_device();
583 if (!ehotk->inputdev) {
584 pr_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 pr_info("Unable to register input device\n");
604 input_free_device(ehotk->inputdev);
605 return 0;
607 } else {
608 pr_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 pr_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 pr_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->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 pr_warning("Failed to register notify on %s\n", node);
746 } else
747 return -ENODEV;
749 return 0;
752 static void eeepc_unregister_rfkill_notifier(char *node)
754 acpi_status status = AE_OK;
755 acpi_handle handle;
757 status = acpi_get_handle(NULL, node, &handle);
759 if (ACPI_SUCCESS(status)) {
760 status = acpi_remove_notify_handler(handle,
761 ACPI_SYSTEM_NOTIFY,
762 eeepc_rfkill_notify);
763 if (ACPI_FAILURE(status))
764 pr_err("Error removing rfkill notify handler %s\n",
765 node);
769 static void eeepc_cleanup_pci_hotplug(struct hotplug_slot *hotplug_slot)
771 kfree(hotplug_slot->info);
772 kfree(hotplug_slot);
775 static int eeepc_setup_pci_hotplug(void)
777 int ret = -ENOMEM;
778 struct pci_bus *bus = pci_find_bus(0, 1);
780 if (!bus) {
781 pr_err("Unable to find wifi PCI bus\n");
782 return -ENODEV;
785 ehotk->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
786 if (!ehotk->hotplug_slot)
787 goto error_slot;
789 ehotk->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info),
790 GFP_KERNEL);
791 if (!ehotk->hotplug_slot->info)
792 goto error_info;
794 ehotk->hotplug_slot->private = ehotk;
795 ehotk->hotplug_slot->release = &eeepc_cleanup_pci_hotplug;
796 ehotk->hotplug_slot->ops = &eeepc_hotplug_slot_ops;
797 eeepc_get_adapter_status(ehotk->hotplug_slot,
798 &ehotk->hotplug_slot->info->adapter_status);
800 ret = pci_hp_register(ehotk->hotplug_slot, bus, 0, "eeepc-wifi");
801 if (ret) {
802 pr_err("Unable to register hotplug slot - %d\n", ret);
803 goto error_register;
806 return 0;
808 error_register:
809 kfree(ehotk->hotplug_slot->info);
810 error_info:
811 kfree(ehotk->hotplug_slot);
812 ehotk->hotplug_slot = NULL;
813 error_slot:
814 return ret;
817 static int eeepc_hotk_add(struct acpi_device *device)
819 int result;
821 if (!device)
822 return -EINVAL;
823 pr_notice(EEEPC_HOTK_NAME "\n");
824 ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL);
825 if (!ehotk)
826 return -ENOMEM;
827 ehotk->init_flag = DISABLE_ASL_WLAN | DISABLE_ASL_DISPLAYSWITCH;
828 ehotk->handle = device->handle;
829 strcpy(acpi_device_name(device), EEEPC_HOTK_DEVICE_NAME);
830 strcpy(acpi_device_class(device), EEEPC_HOTK_CLASS);
831 device->driver_data = ehotk;
832 ehotk->device = device;
833 result = eeepc_hotk_check();
834 if (result)
835 goto ehotk_fail;
837 return 0;
839 ehotk_fail:
840 kfree(ehotk);
841 ehotk = NULL;
843 return result;
846 static int eeepc_hotk_remove(struct acpi_device *device, int type)
848 if (!device || !acpi_driver_data(device))
849 return -EINVAL;
851 kfree(ehotk);
852 return 0;
855 static int eeepc_hotk_resume(struct acpi_device *device)
857 if (ehotk->wlan_rfkill) {
858 bool wlan;
860 /* Workaround - it seems that _PTS disables the wireless
861 without notification or changing the value read by WLAN.
862 Normally this is fine because the correct value is restored
863 from the non-volatile storage on resume, but we need to do
864 it ourself if case suspend is aborted, or we lose wireless.
866 wlan = get_acpi(CM_ASL_WLAN);
867 set_acpi(CM_ASL_WLAN, wlan);
869 rfkill_set_sw_state(ehotk->wlan_rfkill, wlan != 1);
871 eeepc_rfkill_hotplug();
874 if (ehotk->bluetooth_rfkill)
875 rfkill_set_sw_state(ehotk->bluetooth_rfkill,
876 get_acpi(CM_ASL_BLUETOOTH) != 1);
878 return 0;
882 * Hwmon
884 static int eeepc_get_fan_pwm(void)
886 int value = 0;
888 read_acpi_int(NULL, EEEPC_EC_FAN_PWM, &value);
889 value = value * 255 / 100;
890 return (value);
893 static void eeepc_set_fan_pwm(int value)
895 value = SENSORS_LIMIT(value, 0, 255);
896 value = value * 100 / 255;
897 ec_write(EEEPC_EC_SC02, value);
900 static int eeepc_get_fan_rpm(void)
902 int high = 0;
903 int low = 0;
905 read_acpi_int(NULL, EEEPC_EC_FAN_HRPM, &high);
906 read_acpi_int(NULL, EEEPC_EC_FAN_LRPM, &low);
907 return (high << 8 | low);
910 static int eeepc_get_fan_ctrl(void)
912 int value = 0;
914 read_acpi_int(NULL, EEEPC_EC_FAN_CTRL, &value);
915 return ((value & 0x02 ? 1 : 0));
918 static void eeepc_set_fan_ctrl(int manual)
920 int value = 0;
922 read_acpi_int(NULL, EEEPC_EC_FAN_CTRL, &value);
923 if (manual)
924 value |= 0x02;
925 else
926 value &= ~0x02;
927 ec_write(EEEPC_EC_SFB3, value);
930 static ssize_t store_sys_hwmon(void (*set)(int), const char *buf, size_t count)
932 int rv, value;
934 rv = parse_arg(buf, count, &value);
935 if (rv > 0)
936 set(value);
937 return rv;
940 static ssize_t show_sys_hwmon(int (*get)(void), char *buf)
942 return sprintf(buf, "%d\n", get());
945 #define EEEPC_CREATE_SENSOR_ATTR(_name, _mode, _set, _get) \
946 static ssize_t show_##_name(struct device *dev, \
947 struct device_attribute *attr, \
948 char *buf) \
950 return show_sys_hwmon(_set, buf); \
952 static ssize_t store_##_name(struct device *dev, \
953 struct device_attribute *attr, \
954 const char *buf, size_t count) \
956 return store_sys_hwmon(_get, buf, count); \
958 static SENSOR_DEVICE_ATTR(_name, _mode, show_##_name, store_##_name, 0);
960 EEEPC_CREATE_SENSOR_ATTR(fan1_input, S_IRUGO, eeepc_get_fan_rpm, NULL);
961 EEEPC_CREATE_SENSOR_ATTR(pwm1, S_IRUGO | S_IWUSR,
962 eeepc_get_fan_pwm, eeepc_set_fan_pwm);
963 EEEPC_CREATE_SENSOR_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
964 eeepc_get_fan_ctrl, eeepc_set_fan_ctrl);
966 static ssize_t
967 show_name(struct device *dev, struct device_attribute *attr, char *buf)
969 return sprintf(buf, "eeepc\n");
971 static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0);
973 static struct attribute *hwmon_attributes[] = {
974 &sensor_dev_attr_pwm1.dev_attr.attr,
975 &sensor_dev_attr_fan1_input.dev_attr.attr,
976 &sensor_dev_attr_pwm1_enable.dev_attr.attr,
977 &sensor_dev_attr_name.dev_attr.attr,
978 NULL
981 static struct attribute_group hwmon_attribute_group = {
982 .attrs = hwmon_attributes
986 * exit/init
988 static void eeepc_backlight_exit(void)
990 if (eeepc_backlight_device)
991 backlight_device_unregister(eeepc_backlight_device);
992 eeepc_backlight_device = NULL;
995 static void eeepc_rfkill_exit(void)
997 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6");
998 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7");
999 if (ehotk->wlan_rfkill)
1000 rfkill_unregister(ehotk->wlan_rfkill);
1001 if (ehotk->bluetooth_rfkill)
1002 rfkill_unregister(ehotk->bluetooth_rfkill);
1003 if (ehotk->hotplug_slot)
1004 pci_hp_deregister(ehotk->hotplug_slot);
1007 static void eeepc_input_exit(void)
1009 if (ehotk->inputdev)
1010 input_unregister_device(ehotk->inputdev);
1013 static void eeepc_hwmon_exit(void)
1015 struct device *hwmon;
1017 hwmon = eeepc_hwmon_device;
1018 if (!hwmon)
1019 return ;
1020 sysfs_remove_group(&hwmon->kobj,
1021 &hwmon_attribute_group);
1022 hwmon_device_unregister(hwmon);
1023 eeepc_hwmon_device = NULL;
1026 static void __exit eeepc_laptop_exit(void)
1028 eeepc_backlight_exit();
1029 eeepc_rfkill_exit();
1030 eeepc_input_exit();
1031 eeepc_hwmon_exit();
1032 acpi_bus_unregister_driver(&eeepc_hotk_driver);
1033 sysfs_remove_group(&platform_device->dev.kobj,
1034 &platform_attribute_group);
1035 platform_device_unregister(platform_device);
1036 platform_driver_unregister(&platform_driver);
1039 static int eeepc_new_rfkill(struct rfkill **rfkill,
1040 const char *name, struct device *dev,
1041 enum rfkill_type type, int cm)
1043 int result;
1045 result = get_acpi(cm);
1046 if (result < 0)
1047 return result;
1049 *rfkill = rfkill_alloc(name, dev, type,
1050 &eeepc_rfkill_ops, (void *)(unsigned long)cm);
1052 if (!*rfkill)
1053 return -EINVAL;
1055 rfkill_init_sw_state(*rfkill, get_acpi(cm) != 1);
1056 result = rfkill_register(*rfkill);
1057 if (result) {
1058 rfkill_destroy(*rfkill);
1059 *rfkill = NULL;
1060 return result;
1062 return 0;
1066 static int eeepc_rfkill_init(struct device *dev)
1068 int result = 0;
1070 eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6");
1071 eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7");
1073 result = eeepc_new_rfkill(&ehotk->wlan_rfkill,
1074 "eeepc-wlan", dev,
1075 RFKILL_TYPE_WLAN, CM_ASL_WLAN);
1077 if (result && result != -ENODEV)
1078 goto exit;
1080 result = eeepc_new_rfkill(&ehotk->bluetooth_rfkill,
1081 "eeepc-bluetooth", dev,
1082 RFKILL_TYPE_BLUETOOTH, CM_ASL_BLUETOOTH);
1084 if (result && result != -ENODEV)
1085 goto exit;
1087 result = eeepc_setup_pci_hotplug();
1089 * If we get -EBUSY then something else is handling the PCI hotplug -
1090 * don't fail in this case
1092 if (result == -EBUSY)
1093 result = 0;
1095 exit:
1096 if (result && result != -ENODEV)
1097 eeepc_rfkill_exit();
1098 return result;
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 pr_err("Could not register eeepc backlight device\n");
1109 eeepc_backlight_device = NULL;
1110 return PTR_ERR(bd);
1112 eeepc_backlight_device = bd;
1113 bd->props.max_brightness = 15;
1114 bd->props.brightness = read_brightness(NULL);
1115 bd->props.power = FB_BLANK_UNBLANK;
1116 backlight_update_status(bd);
1117 return 0;
1120 static int eeepc_hwmon_init(struct device *dev)
1122 struct device *hwmon;
1123 int result;
1125 hwmon = hwmon_device_register(dev);
1126 if (IS_ERR(hwmon)) {
1127 pr_err("Could not register eeepc hwmon device\n");
1128 eeepc_hwmon_device = NULL;
1129 return PTR_ERR(hwmon);
1131 eeepc_hwmon_device = hwmon;
1132 result = sysfs_create_group(&hwmon->kobj,
1133 &hwmon_attribute_group);
1134 if (result)
1135 eeepc_hwmon_exit();
1136 return result;
1139 static int __init eeepc_laptop_init(void)
1141 struct device *dev;
1142 int result;
1144 if (acpi_disabled)
1145 return -ENODEV;
1146 result = acpi_bus_register_driver(&eeepc_hotk_driver);
1147 if (result < 0)
1148 return result;
1149 if (!ehotk) {
1150 acpi_bus_unregister_driver(&eeepc_hotk_driver);
1151 return -ENODEV;
1154 eeepc_enable_camera();
1156 /* Register platform stuff */
1157 result = platform_driver_register(&platform_driver);
1158 if (result)
1159 goto fail_platform_driver;
1160 platform_device = platform_device_alloc(EEEPC_HOTK_FILE, -1);
1161 if (!platform_device) {
1162 result = -ENOMEM;
1163 goto fail_platform_device1;
1165 result = platform_device_add(platform_device);
1166 if (result)
1167 goto fail_platform_device2;
1168 result = sysfs_create_group(&platform_device->dev.kobj,
1169 &platform_attribute_group);
1170 if (result)
1171 goto fail_sysfs;
1173 dev = &platform_device->dev;
1175 if (!acpi_video_backlight_support()) {
1176 result = eeepc_backlight_init(dev);
1177 if (result)
1178 goto fail_backlight;
1179 } else
1180 pr_info("Backlight controlled by ACPI video "
1181 "driver\n");
1183 result = eeepc_hwmon_init(dev);
1184 if (result)
1185 goto fail_hwmon;
1187 result = eeepc_rfkill_init(dev);
1188 if (result)
1189 goto fail_rfkill;
1191 return 0;
1192 fail_rfkill:
1193 eeepc_hwmon_exit();
1194 fail_hwmon:
1195 eeepc_backlight_exit();
1196 fail_backlight:
1197 sysfs_remove_group(&platform_device->dev.kobj,
1198 &platform_attribute_group);
1199 fail_sysfs:
1200 platform_device_del(platform_device);
1201 fail_platform_device2:
1202 platform_device_put(platform_device);
1203 fail_platform_device1:
1204 platform_driver_unregister(&platform_driver);
1205 fail_platform_driver:
1206 eeepc_input_exit();
1207 return result;
1210 module_init(eeepc_laptop_init);
1211 module_exit(eeepc_laptop_exit);