eeepc-laptop: sync eeepc-laptop with asus_acpi
[linux-2.6/mini2440.git] / drivers / platform / x86 / eeepc-laptop.c
blob73f3cb0fd76ca5ceafff129b296fd3c7847591c7
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>
35 #define EEEPC_LAPTOP_VERSION "0.1"
37 #define EEEPC_HOTK_NAME "Eee PC Hotkey Driver"
38 #define EEEPC_HOTK_FILE "eeepc"
39 #define EEEPC_HOTK_CLASS "hotkey"
40 #define EEEPC_HOTK_DEVICE_NAME "Hotkey"
41 #define EEEPC_HOTK_HID "ASUS010"
43 #define EEEPC_LOG EEEPC_HOTK_FILE ": "
44 #define EEEPC_ERR KERN_ERR EEEPC_LOG
45 #define EEEPC_WARNING KERN_WARNING EEEPC_LOG
46 #define EEEPC_NOTICE KERN_NOTICE EEEPC_LOG
47 #define EEEPC_INFO KERN_INFO EEEPC_LOG
50 * Definitions for Asus EeePC
52 #define NOTIFY_WLAN_ON 0x10
53 #define NOTIFY_BRN_MIN 0x20
54 #define NOTIFY_BRN_MAX 0x2f
56 enum {
57 DISABLE_ASL_WLAN = 0x0001,
58 DISABLE_ASL_BLUETOOTH = 0x0002,
59 DISABLE_ASL_IRDA = 0x0004,
60 DISABLE_ASL_CAMERA = 0x0008,
61 DISABLE_ASL_TV = 0x0010,
62 DISABLE_ASL_GPS = 0x0020,
63 DISABLE_ASL_DISPLAYSWITCH = 0x0040,
64 DISABLE_ASL_MODEM = 0x0080,
65 DISABLE_ASL_CARDREADER = 0x0100,
66 DISABLE_ASL_3G = 0x0200,
67 DISABLE_ASL_WIMAX = 0x0400,
68 DISABLE_ASL_HWCF = 0x0800
71 enum {
72 CM_ASL_WLAN = 0,
73 CM_ASL_BLUETOOTH,
74 CM_ASL_IRDA,
75 CM_ASL_1394,
76 CM_ASL_CAMERA,
77 CM_ASL_TV,
78 CM_ASL_GPS,
79 CM_ASL_DVDROM,
80 CM_ASL_DISPLAYSWITCH,
81 CM_ASL_PANELBRIGHT,
82 CM_ASL_BIOSFLASH,
83 CM_ASL_ACPIFLASH,
84 CM_ASL_CPUFV,
85 CM_ASL_CPUTEMPERATURE,
86 CM_ASL_FANCPU,
87 CM_ASL_FANCHASSIS,
88 CM_ASL_USBPORT1,
89 CM_ASL_USBPORT2,
90 CM_ASL_USBPORT3,
91 CM_ASL_MODEM,
92 CM_ASL_CARDREADER,
93 CM_ASL_3G,
94 CM_ASL_WIMAX,
95 CM_ASL_HWCF,
96 CM_ASL_LID,
97 CM_ASL_TYPE,
98 CM_ASL_PANELPOWER, /*P901*/
99 CM_ASL_TPD
102 static const char *cm_getv[] = {
103 "WLDG", "BTHG", NULL, NULL,
104 "CAMG", NULL, NULL, NULL,
105 NULL, "PBLG", NULL, NULL,
106 "CFVG", NULL, NULL, NULL,
107 "USBG", NULL, NULL, "MODG",
108 "CRDG", "M3GG", "WIMG", "HWCF",
109 "LIDG", "TYPE", "PBPG", "TPDG"
112 static const char *cm_setv[] = {
113 "WLDS", "BTHS", NULL, NULL,
114 "CAMS", NULL, NULL, NULL,
115 "SDSP", "PBLS", "HDPS", NULL,
116 "CFVS", NULL, NULL, NULL,
117 "USBG", NULL, NULL, "MODS",
118 "CRDS", "M3GS", "WIMS", NULL,
119 NULL, NULL, "PBPS", "TPDS"
122 #define EEEPC_EC "\\_SB.PCI0.SBRG.EC0."
124 #define EEEPC_EC_FAN_PWM EEEPC_EC "SC02" /* Fan PWM duty cycle (%) */
125 #define EEEPC_EC_SC02 0x63
126 #define EEEPC_EC_FAN_HRPM EEEPC_EC "SC05" /* High byte, fan speed (RPM) */
127 #define EEEPC_EC_FAN_LRPM EEEPC_EC "SC06" /* Low byte, fan speed (RPM) */
128 #define EEEPC_EC_FAN_CTRL EEEPC_EC "SFB3" /* Byte containing SF25 */
129 #define EEEPC_EC_SFB3 0xD3
132 * This is the main structure, we can use it to store useful information
133 * about the hotk device
135 struct eeepc_hotk {
136 struct acpi_device *device; /* the device we are in */
137 acpi_handle handle; /* the handle of the hotk device */
138 u32 cm_supported; /* the control methods supported
139 by this BIOS */
140 uint init_flag; /* Init flags */
141 u16 event_count[128]; /* count for each event */
142 struct input_dev *inputdev;
143 u16 *keycode_map;
144 struct rfkill *eeepc_wlan_rfkill;
145 struct rfkill *eeepc_bluetooth_rfkill;
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 /* The backlight device /sys/class/backlight */
217 static struct backlight_device *eeepc_backlight_device;
219 /* The hwmon device */
220 static struct device *eeepc_hwmon_device;
223 * The backlight class declaration
225 static int read_brightness(struct backlight_device *bd);
226 static int update_bl_status(struct backlight_device *bd);
227 static struct backlight_ops eeepcbl_ops = {
228 .get_brightness = read_brightness,
229 .update_status = update_bl_status,
232 MODULE_AUTHOR("Corentin Chary, Eric Cooper");
233 MODULE_DESCRIPTION(EEEPC_HOTK_NAME);
234 MODULE_LICENSE("GPL");
237 * ACPI Helpers
239 static int write_acpi_int(acpi_handle handle, const char *method, int val,
240 struct acpi_buffer *output)
242 struct acpi_object_list params;
243 union acpi_object in_obj;
244 acpi_status status;
246 params.count = 1;
247 params.pointer = &in_obj;
248 in_obj.type = ACPI_TYPE_INTEGER;
249 in_obj.integer.value = val;
251 status = acpi_evaluate_object(handle, (char *)method, &params, output);
252 return (status == AE_OK ? 0 : -1);
255 static int read_acpi_int(acpi_handle handle, const char *method, int *val)
257 acpi_status status;
258 unsigned long long result;
260 status = acpi_evaluate_integer(handle, (char *)method, NULL, &result);
261 if (ACPI_FAILURE(status)) {
262 *val = -1;
263 return -1;
264 } else {
265 *val = result;
266 return 0;
270 static int set_acpi(int cm, int value)
272 if (ehotk->cm_supported & (0x1 << cm)) {
273 const char *method = cm_setv[cm];
274 if (method == NULL)
275 return -ENODEV;
276 if (write_acpi_int(ehotk->handle, method, value, NULL))
277 printk(EEEPC_WARNING "Error writing %s\n", method);
279 return 0;
282 static int get_acpi(int cm)
284 int value = -1;
285 if ((ehotk->cm_supported & (0x1 << cm))) {
286 const char *method = cm_getv[cm];
287 if (method == NULL)
288 return -ENODEV;
289 if (read_acpi_int(ehotk->handle, method, &value))
290 printk(EEEPC_WARNING "Error reading %s\n", method);
292 return value;
296 * Backlight
298 static int read_brightness(struct backlight_device *bd)
300 return get_acpi(CM_ASL_PANELBRIGHT);
303 static int set_brightness(struct backlight_device *bd, int value)
305 value = max(0, min(15, value));
306 return set_acpi(CM_ASL_PANELBRIGHT, value);
309 static int update_bl_status(struct backlight_device *bd)
311 return set_brightness(bd, bd->props.brightness);
315 * Rfkill helpers
318 static bool eeepc_wlan_rfkill_blocked(void)
320 if (get_acpi(CM_ASL_WLAN) == 1)
321 return false;
322 return true;
325 static int eeepc_rfkill_set(void *data, bool blocked)
327 unsigned long asl = (unsigned long)data;
328 return set_acpi(asl, !blocked);
331 static const struct rfkill_ops eeepc_rfkill_ops = {
332 .set_block = eeepc_rfkill_set,
335 static void __init eeepc_enable_camera(void)
338 * If the following call to set_acpi() fails, it's because there's no
339 * camera so we can ignore the error.
341 set_acpi(CM_ASL_CAMERA, 1);
345 * Sys helpers
347 static int parse_arg(const char *buf, unsigned long count, int *val)
349 if (!count)
350 return 0;
351 if (sscanf(buf, "%i", val) != 1)
352 return -EINVAL;
353 return count;
356 static ssize_t store_sys_acpi(int cm, const char *buf, size_t count)
358 int rv, value;
360 rv = parse_arg(buf, count, &value);
361 if (rv > 0)
362 set_acpi(cm, value);
363 return rv;
366 static ssize_t show_sys_acpi(int cm, char *buf)
368 return sprintf(buf, "%d\n", get_acpi(cm));
371 #define EEEPC_CREATE_DEVICE_ATTR(_name, _cm) \
372 static ssize_t show_##_name(struct device *dev, \
373 struct device_attribute *attr, \
374 char *buf) \
376 return show_sys_acpi(_cm, buf); \
378 static ssize_t store_##_name(struct device *dev, \
379 struct device_attribute *attr, \
380 const char *buf, size_t count) \
382 return store_sys_acpi(_cm, buf, count); \
384 static struct device_attribute dev_attr_##_name = { \
385 .attr = { \
386 .name = __stringify(_name), \
387 .mode = 0644 }, \
388 .show = show_##_name, \
389 .store = store_##_name, \
392 EEEPC_CREATE_DEVICE_ATTR(camera, CM_ASL_CAMERA);
393 EEEPC_CREATE_DEVICE_ATTR(cardr, CM_ASL_CARDREADER);
394 EEEPC_CREATE_DEVICE_ATTR(disp, CM_ASL_DISPLAYSWITCH);
395 EEEPC_CREATE_DEVICE_ATTR(cpufv, CM_ASL_CPUFV);
397 static struct attribute *platform_attributes[] = {
398 &dev_attr_camera.attr,
399 &dev_attr_cardr.attr,
400 &dev_attr_disp.attr,
401 &dev_attr_cpufv.attr,
402 NULL
405 static struct attribute_group platform_attribute_group = {
406 .attrs = platform_attributes
410 * Hotkey functions
412 static struct key_entry *eepc_get_entry_by_scancode(int code)
414 struct key_entry *key;
416 for (key = eeepc_keymap; key->type != KE_END; key++)
417 if (code == key->code)
418 return key;
420 return NULL;
423 static struct key_entry *eepc_get_entry_by_keycode(int code)
425 struct key_entry *key;
427 for (key = eeepc_keymap; key->type != KE_END; key++)
428 if (code == key->keycode && key->type == KE_KEY)
429 return key;
431 return NULL;
434 static int eeepc_getkeycode(struct input_dev *dev, int scancode, int *keycode)
436 struct key_entry *key = eepc_get_entry_by_scancode(scancode);
438 if (key && key->type == KE_KEY) {
439 *keycode = key->keycode;
440 return 0;
443 return -EINVAL;
446 static int eeepc_setkeycode(struct input_dev *dev, int scancode, int keycode)
448 struct key_entry *key;
449 int old_keycode;
451 if (keycode < 0 || keycode > KEY_MAX)
452 return -EINVAL;
454 key = eepc_get_entry_by_scancode(scancode);
455 if (key && key->type == KE_KEY) {
456 old_keycode = key->keycode;
457 key->keycode = keycode;
458 set_bit(keycode, dev->keybit);
459 if (!eepc_get_entry_by_keycode(old_keycode))
460 clear_bit(old_keycode, dev->keybit);
461 return 0;
464 return -EINVAL;
467 static int eeepc_hotk_check(void)
469 const struct key_entry *key;
470 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
471 int result;
473 result = acpi_bus_get_status(ehotk->device);
474 if (result)
475 return result;
476 if (ehotk->device->status.present) {
477 if (write_acpi_int(ehotk->handle, "INIT", ehotk->init_flag,
478 &buffer)) {
479 printk(EEEPC_ERR "Hotkey initialization failed\n");
480 return -ENODEV;
481 } else {
482 printk(EEEPC_NOTICE "Hotkey init flags 0x%x\n",
483 ehotk->init_flag);
485 /* get control methods supported */
486 if (read_acpi_int(ehotk->handle, "CMSG"
487 , &ehotk->cm_supported)) {
488 printk(EEEPC_ERR
489 "Get control methods supported failed\n");
490 return -ENODEV;
491 } else {
492 printk(EEEPC_INFO
493 "Get control methods supported: 0x%x\n",
494 ehotk->cm_supported);
496 ehotk->inputdev = input_allocate_device();
497 if (!ehotk->inputdev) {
498 printk(EEEPC_INFO "Unable to allocate input device\n");
499 return 0;
501 ehotk->inputdev->name = "Asus EeePC extra buttons";
502 ehotk->inputdev->phys = EEEPC_HOTK_FILE "/input0";
503 ehotk->inputdev->id.bustype = BUS_HOST;
504 ehotk->inputdev->getkeycode = eeepc_getkeycode;
505 ehotk->inputdev->setkeycode = eeepc_setkeycode;
507 for (key = eeepc_keymap; key->type != KE_END; key++) {
508 switch (key->type) {
509 case KE_KEY:
510 set_bit(EV_KEY, ehotk->inputdev->evbit);
511 set_bit(key->keycode, ehotk->inputdev->keybit);
512 break;
515 result = input_register_device(ehotk->inputdev);
516 if (result) {
517 printk(EEEPC_INFO "Unable to register input device\n");
518 input_free_device(ehotk->inputdev);
519 return 0;
521 } else {
522 printk(EEEPC_ERR "Hotkey device not present, aborting\n");
523 return -EINVAL;
525 return 0;
528 static int notify_brn(void)
530 /* returns the *previous* brightness, or -1 */
531 struct backlight_device *bd = eeepc_backlight_device;
532 if (bd) {
533 int old = bd->props.brightness;
534 bd->props.brightness = read_brightness(bd);
535 return old;
537 return -1;
540 static void eeepc_rfkill_hotplug(void)
542 struct pci_dev *dev;
543 struct pci_bus *bus = pci_find_bus(0, 1);
544 bool blocked;
546 if (!bus) {
547 printk(EEEPC_WARNING "Unable to find PCI bus 1?\n");
548 return;
551 blocked = eeepc_wlan_rfkill_blocked();
552 if (!blocked) {
553 dev = pci_get_slot(bus, 0);
554 if (dev) {
555 /* Device already present */
556 pci_dev_put(dev);
557 return;
559 dev = pci_scan_single_device(bus, 0);
560 if (dev) {
561 pci_bus_assign_resources(bus);
562 if (pci_bus_add_device(dev))
563 printk(EEEPC_ERR "Unable to hotplug wifi\n");
565 } else {
566 dev = pci_get_slot(bus, 0);
567 if (dev) {
568 pci_remove_bus_device(dev);
569 pci_dev_put(dev);
573 rfkill_set_sw_state(ehotk->eeepc_wlan_rfkill, blocked);
576 static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
578 if (event != ACPI_NOTIFY_BUS_CHECK)
579 return;
581 eeepc_rfkill_hotplug();
584 static void eeepc_hotk_notify(struct acpi_device *device, u32 event)
586 static struct key_entry *key;
587 u16 count;
588 int brn = -ENODEV;
590 if (!ehotk)
591 return;
592 if (event > ACPI_MAX_SYS_NOTIFY)
593 return;
594 if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX)
595 brn = notify_brn();
596 count = ehotk->event_count[event % 128]++;
597 acpi_bus_generate_proc_event(ehotk->device, event, count);
598 acpi_bus_generate_netlink_event(ehotk->device->pnp.device_class,
599 dev_name(&ehotk->device->dev), event,
600 count);
601 if (ehotk->inputdev) {
602 if (brn != -ENODEV) {
603 /* brightness-change events need special
604 * handling for conversion to key events
606 if (brn < 0)
607 brn = event;
608 else
609 brn += NOTIFY_BRN_MIN;
610 if (event < brn)
611 event = NOTIFY_BRN_MIN; /* brightness down */
612 else if (event > brn)
613 event = NOTIFY_BRN_MIN + 2; /* ... up */
614 else
615 event = NOTIFY_BRN_MIN + 1; /* ... unchanged */
617 key = eepc_get_entry_by_scancode(event);
618 if (key) {
619 switch (key->type) {
620 case KE_KEY:
621 input_report_key(ehotk->inputdev, key->keycode,
623 input_sync(ehotk->inputdev);
624 input_report_key(ehotk->inputdev, key->keycode,
626 input_sync(ehotk->inputdev);
627 break;
633 static int eeepc_register_rfkill_notifier(char *node)
635 acpi_status status = AE_OK;
636 acpi_handle handle;
638 status = acpi_get_handle(NULL, node, &handle);
640 if (ACPI_SUCCESS(status)) {
641 status = acpi_install_notify_handler(handle,
642 ACPI_SYSTEM_NOTIFY,
643 eeepc_rfkill_notify,
644 NULL);
645 if (ACPI_FAILURE(status))
646 printk(EEEPC_WARNING
647 "Failed to register notify on %s\n", node);
648 } else
649 return -ENODEV;
651 return 0;
654 static void eeepc_unregister_rfkill_notifier(char *node)
656 acpi_status status = AE_OK;
657 acpi_handle handle;
659 status = acpi_get_handle(NULL, node, &handle);
661 if (ACPI_SUCCESS(status)) {
662 status = acpi_remove_notify_handler(handle,
663 ACPI_SYSTEM_NOTIFY,
664 eeepc_rfkill_notify);
665 if (ACPI_FAILURE(status))
666 printk(EEEPC_ERR
667 "Error removing rfkill notify handler %s\n",
668 node);
672 static int eeepc_hotk_add(struct acpi_device *device)
674 int result;
676 if (!device)
677 return -EINVAL;
678 printk(EEEPC_NOTICE EEEPC_HOTK_NAME "\n");
679 ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL);
680 if (!ehotk)
681 return -ENOMEM;
682 ehotk->init_flag = DISABLE_ASL_WLAN | DISABLE_ASL_DISPLAYSWITCH;
683 ehotk->handle = device->handle;
684 strcpy(acpi_device_name(device), EEEPC_HOTK_DEVICE_NAME);
685 strcpy(acpi_device_class(device), EEEPC_HOTK_CLASS);
686 device->driver_data = ehotk;
687 ehotk->device = device;
688 result = eeepc_hotk_check();
689 if (result)
690 goto ehotk_fail;
692 eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6");
693 eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7");
695 if (get_acpi(CM_ASL_WLAN) != -1) {
696 ehotk->eeepc_wlan_rfkill = rfkill_alloc("eeepc-wlan",
697 &device->dev,
698 RFKILL_TYPE_WLAN,
699 &eeepc_rfkill_ops,
700 (void *)CM_ASL_WLAN);
702 if (!ehotk->eeepc_wlan_rfkill)
703 goto wlan_fail;
705 rfkill_init_sw_state(ehotk->eeepc_wlan_rfkill,
706 get_acpi(CM_ASL_WLAN) != 1);
707 result = rfkill_register(ehotk->eeepc_wlan_rfkill);
708 if (result)
709 goto wlan_fail;
712 if (get_acpi(CM_ASL_BLUETOOTH) != -1) {
713 ehotk->eeepc_bluetooth_rfkill =
714 rfkill_alloc("eeepc-bluetooth",
715 &device->dev,
716 RFKILL_TYPE_BLUETOOTH,
717 &eeepc_rfkill_ops,
718 (void *)CM_ASL_BLUETOOTH);
720 if (!ehotk->eeepc_bluetooth_rfkill)
721 goto bluetooth_fail;
723 rfkill_init_sw_state(ehotk->eeepc_bluetooth_rfkill,
724 get_acpi(CM_ASL_BLUETOOTH) != 1);
725 result = rfkill_register(ehotk->eeepc_bluetooth_rfkill);
726 if (result)
727 goto bluetooth_fail;
730 return 0;
732 bluetooth_fail:
733 rfkill_destroy(ehotk->eeepc_bluetooth_rfkill);
734 rfkill_unregister(ehotk->eeepc_wlan_rfkill);
735 wlan_fail:
736 rfkill_destroy(ehotk->eeepc_wlan_rfkill);
737 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6");
738 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7");
739 ehotk_fail:
740 kfree(ehotk);
741 ehotk = NULL;
743 return result;
746 static int eeepc_hotk_remove(struct acpi_device *device, int type)
748 if (!device || !acpi_driver_data(device))
749 return -EINVAL;
751 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6");
752 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7");
754 kfree(ehotk);
755 return 0;
758 static int eeepc_hotk_resume(struct acpi_device *device)
760 if (ehotk->eeepc_wlan_rfkill) {
761 bool wlan;
763 /* Workaround - it seems that _PTS disables the wireless
764 without notification or changing the value read by WLAN.
765 Normally this is fine because the correct value is restored
766 from the non-volatile storage on resume, but we need to do
767 it ourself if case suspend is aborted, or we lose wireless.
769 wlan = get_acpi(CM_ASL_WLAN);
770 set_acpi(CM_ASL_WLAN, wlan);
772 rfkill_set_sw_state(ehotk->eeepc_wlan_rfkill,
773 wlan != 1);
775 eeepc_rfkill_hotplug();
778 if (ehotk->eeepc_bluetooth_rfkill)
779 rfkill_set_sw_state(ehotk->eeepc_bluetooth_rfkill,
780 get_acpi(CM_ASL_BLUETOOTH) != 1);
782 return 0;
786 * Hwmon
788 static int eeepc_get_fan_pwm(void)
790 int value = 0;
792 read_acpi_int(NULL, EEEPC_EC_FAN_PWM, &value);
793 value = value * 255 / 100;
794 return (value);
797 static void eeepc_set_fan_pwm(int value)
799 value = SENSORS_LIMIT(value, 0, 255);
800 value = value * 100 / 255;
801 ec_write(EEEPC_EC_SC02, value);
804 static int eeepc_get_fan_rpm(void)
806 int high = 0;
807 int low = 0;
809 read_acpi_int(NULL, EEEPC_EC_FAN_HRPM, &high);
810 read_acpi_int(NULL, EEEPC_EC_FAN_LRPM, &low);
811 return (high << 8 | low);
814 static int eeepc_get_fan_ctrl(void)
816 int value = 0;
818 read_acpi_int(NULL, EEEPC_EC_FAN_CTRL, &value);
819 return ((value & 0x02 ? 1 : 0));
822 static void eeepc_set_fan_ctrl(int manual)
824 int value = 0;
826 read_acpi_int(NULL, EEEPC_EC_FAN_CTRL, &value);
827 if (manual)
828 value |= 0x02;
829 else
830 value &= ~0x02;
831 ec_write(EEEPC_EC_SFB3, value);
834 static ssize_t store_sys_hwmon(void (*set)(int), const char *buf, size_t count)
836 int rv, value;
838 rv = parse_arg(buf, count, &value);
839 if (rv > 0)
840 set(value);
841 return rv;
844 static ssize_t show_sys_hwmon(int (*get)(void), char *buf)
846 return sprintf(buf, "%d\n", get());
849 #define EEEPC_CREATE_SENSOR_ATTR(_name, _mode, _set, _get) \
850 static ssize_t show_##_name(struct device *dev, \
851 struct device_attribute *attr, \
852 char *buf) \
854 return show_sys_hwmon(_set, buf); \
856 static ssize_t store_##_name(struct device *dev, \
857 struct device_attribute *attr, \
858 const char *buf, size_t count) \
860 return store_sys_hwmon(_get, buf, count); \
862 static SENSOR_DEVICE_ATTR(_name, _mode, show_##_name, store_##_name, 0);
864 EEEPC_CREATE_SENSOR_ATTR(fan1_input, S_IRUGO, eeepc_get_fan_rpm, NULL);
865 EEEPC_CREATE_SENSOR_ATTR(pwm1, S_IRUGO | S_IWUSR,
866 eeepc_get_fan_pwm, eeepc_set_fan_pwm);
867 EEEPC_CREATE_SENSOR_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
868 eeepc_get_fan_ctrl, eeepc_set_fan_ctrl);
870 static ssize_t
871 show_name(struct device *dev, struct device_attribute *attr, char *buf)
873 return sprintf(buf, "eeepc\n");
875 static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0);
877 static struct attribute *hwmon_attributes[] = {
878 &sensor_dev_attr_pwm1.dev_attr.attr,
879 &sensor_dev_attr_fan1_input.dev_attr.attr,
880 &sensor_dev_attr_pwm1_enable.dev_attr.attr,
881 &sensor_dev_attr_name.dev_attr.attr,
882 NULL
885 static struct attribute_group hwmon_attribute_group = {
886 .attrs = hwmon_attributes
890 * exit/init
892 static void eeepc_backlight_exit(void)
894 if (eeepc_backlight_device)
895 backlight_device_unregister(eeepc_backlight_device);
896 eeepc_backlight_device = NULL;
899 static void eeepc_rfkill_exit(void)
901 if (ehotk->eeepc_wlan_rfkill)
902 rfkill_unregister(ehotk->eeepc_wlan_rfkill);
903 if (ehotk->eeepc_bluetooth_rfkill)
904 rfkill_unregister(ehotk->eeepc_bluetooth_rfkill);
907 static void eeepc_input_exit(void)
909 if (ehotk->inputdev)
910 input_unregister_device(ehotk->inputdev);
913 static void eeepc_hwmon_exit(void)
915 struct device *hwmon;
917 hwmon = eeepc_hwmon_device;
918 if (!hwmon)
919 return ;
920 sysfs_remove_group(&hwmon->kobj,
921 &hwmon_attribute_group);
922 hwmon_device_unregister(hwmon);
923 eeepc_hwmon_device = NULL;
926 static void __exit eeepc_laptop_exit(void)
928 eeepc_backlight_exit();
929 eeepc_rfkill_exit();
930 eeepc_input_exit();
931 eeepc_hwmon_exit();
932 acpi_bus_unregister_driver(&eeepc_hotk_driver);
933 sysfs_remove_group(&platform_device->dev.kobj,
934 &platform_attribute_group);
935 platform_device_unregister(platform_device);
936 platform_driver_unregister(&platform_driver);
939 static int eeepc_backlight_init(struct device *dev)
941 struct backlight_device *bd;
943 bd = backlight_device_register(EEEPC_HOTK_FILE, dev,
944 NULL, &eeepcbl_ops);
945 if (IS_ERR(bd)) {
946 printk(EEEPC_ERR
947 "Could not register eeepc backlight device\n");
948 eeepc_backlight_device = NULL;
949 return PTR_ERR(bd);
951 eeepc_backlight_device = bd;
952 bd->props.max_brightness = 15;
953 bd->props.brightness = read_brightness(NULL);
954 bd->props.power = FB_BLANK_UNBLANK;
955 backlight_update_status(bd);
956 return 0;
959 static int eeepc_hwmon_init(struct device *dev)
961 struct device *hwmon;
962 int result;
964 hwmon = hwmon_device_register(dev);
965 if (IS_ERR(hwmon)) {
966 printk(EEEPC_ERR
967 "Could not register eeepc hwmon device\n");
968 eeepc_hwmon_device = NULL;
969 return PTR_ERR(hwmon);
971 eeepc_hwmon_device = hwmon;
972 result = sysfs_create_group(&hwmon->kobj,
973 &hwmon_attribute_group);
974 if (result)
975 eeepc_hwmon_exit();
976 return result;
979 static int __init eeepc_laptop_init(void)
981 struct device *dev;
982 int result;
984 if (acpi_disabled)
985 return -ENODEV;
986 result = acpi_bus_register_driver(&eeepc_hotk_driver);
987 if (result < 0)
988 return result;
989 if (!ehotk) {
990 acpi_bus_unregister_driver(&eeepc_hotk_driver);
991 return -ENODEV;
993 dev = acpi_get_physical_device(ehotk->device->handle);
995 if (!acpi_video_backlight_support()) {
996 result = eeepc_backlight_init(dev);
997 if (result)
998 goto fail_backlight;
999 } else
1000 printk(EEEPC_INFO "Backlight controlled by ACPI video "
1001 "driver\n");
1003 result = eeepc_hwmon_init(dev);
1004 if (result)
1005 goto fail_hwmon;
1007 eeepc_enable_camera();
1009 /* Register platform stuff */
1010 result = platform_driver_register(&platform_driver);
1011 if (result)
1012 goto fail_platform_driver;
1013 platform_device = platform_device_alloc(EEEPC_HOTK_FILE, -1);
1014 if (!platform_device) {
1015 result = -ENOMEM;
1016 goto fail_platform_device1;
1018 result = platform_device_add(platform_device);
1019 if (result)
1020 goto fail_platform_device2;
1021 result = sysfs_create_group(&platform_device->dev.kobj,
1022 &platform_attribute_group);
1023 if (result)
1024 goto fail_sysfs;
1025 return 0;
1026 fail_sysfs:
1027 platform_device_del(platform_device);
1028 fail_platform_device2:
1029 platform_device_put(platform_device);
1030 fail_platform_device1:
1031 platform_driver_unregister(&platform_driver);
1032 fail_platform_driver:
1033 eeepc_hwmon_exit();
1034 fail_hwmon:
1035 eeepc_backlight_exit();
1036 fail_backlight:
1037 eeepc_input_exit();
1038 eeepc_rfkill_exit();
1039 return result;
1042 module_init(eeepc_laptop_init);
1043 module_exit(eeepc_laptop_exit);