eeepc-laptop: cpufv updates
[linux-2.6/mini2440.git] / drivers / platform / x86 / eeepc-laptop.c
blob4207b26ff990634d3a75d35394f20b4c80afba21
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);
396 struct eeepc_cpufv {
397 int num;
398 int cur;
401 static int get_cpufv(struct eeepc_cpufv *c)
403 c->cur = get_acpi(CM_ASL_CPUFV);
404 c->num = (c->cur >> 8) & 0xff;
405 c->cur &= 0xff;
406 if (c->cur < 0 || c->num <= 0 || c->num > 12)
407 return -ENODEV;
408 return 0;
411 static ssize_t show_available_cpufv(struct device *dev,
412 struct device_attribute *attr,
413 char *buf)
415 struct eeepc_cpufv c;
416 int i;
417 ssize_t len = 0;
419 if (get_cpufv(&c))
420 return -ENODEV;
421 for (i = 0; i < c.num; i++)
422 len += sprintf(buf + len, "%d ", i);
423 len += sprintf(buf + len, "\n");
424 return len;
427 static ssize_t show_cpufv(struct device *dev,
428 struct device_attribute *attr,
429 char *buf)
431 struct eeepc_cpufv c;
433 if (get_cpufv(&c))
434 return -ENODEV;
435 return sprintf(buf, "%#x\n", (c.num << 8) | c.cur);
438 static ssize_t store_cpufv(struct device *dev,
439 struct device_attribute *attr,
440 const char *buf, size_t count)
442 struct eeepc_cpufv c;
443 int rv, value;
445 if (get_cpufv(&c))
446 return -ENODEV;
447 rv = parse_arg(buf, count, &value);
448 if (rv < 0)
449 return rv;
450 if (!rv || value < 0 || value >= c.num)
451 return -EINVAL;
452 set_acpi(CM_ASL_CPUFV, value);
453 return rv;
456 static struct device_attribute dev_attr_cpufv = {
457 .attr = {
458 .name = "cpufv",
459 .mode = 0644 },
460 .show = show_cpufv,
461 .store = store_cpufv
464 static struct device_attribute dev_attr_available_cpufv = {
465 .attr = {
466 .name = "available_cpufv",
467 .mode = 0444 },
468 .show = show_available_cpufv
471 static struct attribute *platform_attributes[] = {
472 &dev_attr_camera.attr,
473 &dev_attr_cardr.attr,
474 &dev_attr_disp.attr,
475 &dev_attr_cpufv.attr,
476 &dev_attr_available_cpufv.attr,
477 NULL
480 static struct attribute_group platform_attribute_group = {
481 .attrs = platform_attributes
485 * Hotkey functions
487 static struct key_entry *eepc_get_entry_by_scancode(int code)
489 struct key_entry *key;
491 for (key = eeepc_keymap; key->type != KE_END; key++)
492 if (code == key->code)
493 return key;
495 return NULL;
498 static struct key_entry *eepc_get_entry_by_keycode(int code)
500 struct key_entry *key;
502 for (key = eeepc_keymap; key->type != KE_END; key++)
503 if (code == key->keycode && key->type == KE_KEY)
504 return key;
506 return NULL;
509 static int eeepc_getkeycode(struct input_dev *dev, int scancode, int *keycode)
511 struct key_entry *key = eepc_get_entry_by_scancode(scancode);
513 if (key && key->type == KE_KEY) {
514 *keycode = key->keycode;
515 return 0;
518 return -EINVAL;
521 static int eeepc_setkeycode(struct input_dev *dev, int scancode, int keycode)
523 struct key_entry *key;
524 int old_keycode;
526 if (keycode < 0 || keycode > KEY_MAX)
527 return -EINVAL;
529 key = eepc_get_entry_by_scancode(scancode);
530 if (key && key->type == KE_KEY) {
531 old_keycode = key->keycode;
532 key->keycode = keycode;
533 set_bit(keycode, dev->keybit);
534 if (!eepc_get_entry_by_keycode(old_keycode))
535 clear_bit(old_keycode, dev->keybit);
536 return 0;
539 return -EINVAL;
542 static int eeepc_hotk_check(void)
544 const struct key_entry *key;
545 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
546 int result;
548 result = acpi_bus_get_status(ehotk->device);
549 if (result)
550 return result;
551 if (ehotk->device->status.present) {
552 if (write_acpi_int(ehotk->handle, "INIT", ehotk->init_flag,
553 &buffer)) {
554 printk(EEEPC_ERR "Hotkey initialization failed\n");
555 return -ENODEV;
556 } else {
557 printk(EEEPC_NOTICE "Hotkey init flags 0x%x\n",
558 ehotk->init_flag);
560 /* get control methods supported */
561 if (read_acpi_int(ehotk->handle, "CMSG"
562 , &ehotk->cm_supported)) {
563 printk(EEEPC_ERR
564 "Get control methods supported failed\n");
565 return -ENODEV;
566 } else {
567 printk(EEEPC_INFO
568 "Get control methods supported: 0x%x\n",
569 ehotk->cm_supported);
571 ehotk->inputdev = input_allocate_device();
572 if (!ehotk->inputdev) {
573 printk(EEEPC_INFO "Unable to allocate input device\n");
574 return 0;
576 ehotk->inputdev->name = "Asus EeePC extra buttons";
577 ehotk->inputdev->phys = EEEPC_HOTK_FILE "/input0";
578 ehotk->inputdev->id.bustype = BUS_HOST;
579 ehotk->inputdev->getkeycode = eeepc_getkeycode;
580 ehotk->inputdev->setkeycode = eeepc_setkeycode;
582 for (key = eeepc_keymap; key->type != KE_END; key++) {
583 switch (key->type) {
584 case KE_KEY:
585 set_bit(EV_KEY, ehotk->inputdev->evbit);
586 set_bit(key->keycode, ehotk->inputdev->keybit);
587 break;
590 result = input_register_device(ehotk->inputdev);
591 if (result) {
592 printk(EEEPC_INFO "Unable to register input device\n");
593 input_free_device(ehotk->inputdev);
594 return 0;
596 } else {
597 printk(EEEPC_ERR "Hotkey device not present, aborting\n");
598 return -EINVAL;
600 return 0;
603 static int notify_brn(void)
605 /* returns the *previous* brightness, or -1 */
606 struct backlight_device *bd = eeepc_backlight_device;
607 if (bd) {
608 int old = bd->props.brightness;
609 bd->props.brightness = read_brightness(bd);
610 return old;
612 return -1;
615 static void eeepc_rfkill_hotplug(void)
617 struct pci_dev *dev;
618 struct pci_bus *bus = pci_find_bus(0, 1);
619 bool blocked;
621 if (!bus) {
622 printk(EEEPC_WARNING "Unable to find PCI bus 1?\n");
623 return;
626 blocked = eeepc_wlan_rfkill_blocked();
627 if (!blocked) {
628 dev = pci_get_slot(bus, 0);
629 if (dev) {
630 /* Device already present */
631 pci_dev_put(dev);
632 return;
634 dev = pci_scan_single_device(bus, 0);
635 if (dev) {
636 pci_bus_assign_resources(bus);
637 if (pci_bus_add_device(dev))
638 printk(EEEPC_ERR "Unable to hotplug wifi\n");
640 } else {
641 dev = pci_get_slot(bus, 0);
642 if (dev) {
643 pci_remove_bus_device(dev);
644 pci_dev_put(dev);
648 rfkill_set_sw_state(ehotk->eeepc_wlan_rfkill, blocked);
651 static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
653 if (event != ACPI_NOTIFY_BUS_CHECK)
654 return;
656 eeepc_rfkill_hotplug();
659 static void eeepc_hotk_notify(struct acpi_device *device, u32 event)
661 static struct key_entry *key;
662 u16 count;
663 int brn = -ENODEV;
665 if (!ehotk)
666 return;
667 if (event > ACPI_MAX_SYS_NOTIFY)
668 return;
669 if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX)
670 brn = notify_brn();
671 count = ehotk->event_count[event % 128]++;
672 acpi_bus_generate_proc_event(ehotk->device, event, count);
673 acpi_bus_generate_netlink_event(ehotk->device->pnp.device_class,
674 dev_name(&ehotk->device->dev), event,
675 count);
676 if (ehotk->inputdev) {
677 if (brn != -ENODEV) {
678 /* brightness-change events need special
679 * handling for conversion to key events
681 if (brn < 0)
682 brn = event;
683 else
684 brn += NOTIFY_BRN_MIN;
685 if (event < brn)
686 event = NOTIFY_BRN_MIN; /* brightness down */
687 else if (event > brn)
688 event = NOTIFY_BRN_MIN + 2; /* ... up */
689 else
690 event = NOTIFY_BRN_MIN + 1; /* ... unchanged */
692 key = eepc_get_entry_by_scancode(event);
693 if (key) {
694 switch (key->type) {
695 case KE_KEY:
696 input_report_key(ehotk->inputdev, key->keycode,
698 input_sync(ehotk->inputdev);
699 input_report_key(ehotk->inputdev, key->keycode,
701 input_sync(ehotk->inputdev);
702 break;
708 static int eeepc_register_rfkill_notifier(char *node)
710 acpi_status status = AE_OK;
711 acpi_handle handle;
713 status = acpi_get_handle(NULL, node, &handle);
715 if (ACPI_SUCCESS(status)) {
716 status = acpi_install_notify_handler(handle,
717 ACPI_SYSTEM_NOTIFY,
718 eeepc_rfkill_notify,
719 NULL);
720 if (ACPI_FAILURE(status))
721 printk(EEEPC_WARNING
722 "Failed to register notify on %s\n", node);
723 } else
724 return -ENODEV;
726 return 0;
729 static void eeepc_unregister_rfkill_notifier(char *node)
731 acpi_status status = AE_OK;
732 acpi_handle handle;
734 status = acpi_get_handle(NULL, node, &handle);
736 if (ACPI_SUCCESS(status)) {
737 status = acpi_remove_notify_handler(handle,
738 ACPI_SYSTEM_NOTIFY,
739 eeepc_rfkill_notify);
740 if (ACPI_FAILURE(status))
741 printk(EEEPC_ERR
742 "Error removing rfkill notify handler %s\n",
743 node);
747 static int eeepc_hotk_add(struct acpi_device *device)
749 int result;
751 if (!device)
752 return -EINVAL;
753 printk(EEEPC_NOTICE EEEPC_HOTK_NAME "\n");
754 ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL);
755 if (!ehotk)
756 return -ENOMEM;
757 ehotk->init_flag = DISABLE_ASL_WLAN | DISABLE_ASL_DISPLAYSWITCH;
758 ehotk->handle = device->handle;
759 strcpy(acpi_device_name(device), EEEPC_HOTK_DEVICE_NAME);
760 strcpy(acpi_device_class(device), EEEPC_HOTK_CLASS);
761 device->driver_data = ehotk;
762 ehotk->device = device;
763 result = eeepc_hotk_check();
764 if (result)
765 goto ehotk_fail;
767 eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6");
768 eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7");
770 if (get_acpi(CM_ASL_WLAN) != -1) {
771 ehotk->eeepc_wlan_rfkill = rfkill_alloc("eeepc-wlan",
772 &device->dev,
773 RFKILL_TYPE_WLAN,
774 &eeepc_rfkill_ops,
775 (void *)CM_ASL_WLAN);
777 if (!ehotk->eeepc_wlan_rfkill)
778 goto wlan_fail;
780 rfkill_init_sw_state(ehotk->eeepc_wlan_rfkill,
781 get_acpi(CM_ASL_WLAN) != 1);
782 result = rfkill_register(ehotk->eeepc_wlan_rfkill);
783 if (result)
784 goto wlan_fail;
787 if (get_acpi(CM_ASL_BLUETOOTH) != -1) {
788 ehotk->eeepc_bluetooth_rfkill =
789 rfkill_alloc("eeepc-bluetooth",
790 &device->dev,
791 RFKILL_TYPE_BLUETOOTH,
792 &eeepc_rfkill_ops,
793 (void *)CM_ASL_BLUETOOTH);
795 if (!ehotk->eeepc_bluetooth_rfkill)
796 goto bluetooth_fail;
798 rfkill_init_sw_state(ehotk->eeepc_bluetooth_rfkill,
799 get_acpi(CM_ASL_BLUETOOTH) != 1);
800 result = rfkill_register(ehotk->eeepc_bluetooth_rfkill);
801 if (result)
802 goto bluetooth_fail;
805 return 0;
807 bluetooth_fail:
808 rfkill_destroy(ehotk->eeepc_bluetooth_rfkill);
809 rfkill_unregister(ehotk->eeepc_wlan_rfkill);
810 wlan_fail:
811 rfkill_destroy(ehotk->eeepc_wlan_rfkill);
812 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6");
813 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7");
814 ehotk_fail:
815 kfree(ehotk);
816 ehotk = NULL;
818 return result;
821 static int eeepc_hotk_remove(struct acpi_device *device, int type)
823 if (!device || !acpi_driver_data(device))
824 return -EINVAL;
826 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6");
827 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7");
829 kfree(ehotk);
830 return 0;
833 static int eeepc_hotk_resume(struct acpi_device *device)
835 if (ehotk->eeepc_wlan_rfkill) {
836 bool wlan;
838 /* Workaround - it seems that _PTS disables the wireless
839 without notification or changing the value read by WLAN.
840 Normally this is fine because the correct value is restored
841 from the non-volatile storage on resume, but we need to do
842 it ourself if case suspend is aborted, or we lose wireless.
844 wlan = get_acpi(CM_ASL_WLAN);
845 set_acpi(CM_ASL_WLAN, wlan);
847 rfkill_set_sw_state(ehotk->eeepc_wlan_rfkill,
848 wlan != 1);
850 eeepc_rfkill_hotplug();
853 if (ehotk->eeepc_bluetooth_rfkill)
854 rfkill_set_sw_state(ehotk->eeepc_bluetooth_rfkill,
855 get_acpi(CM_ASL_BLUETOOTH) != 1);
857 return 0;
861 * Hwmon
863 static int eeepc_get_fan_pwm(void)
865 int value = 0;
867 read_acpi_int(NULL, EEEPC_EC_FAN_PWM, &value);
868 value = value * 255 / 100;
869 return (value);
872 static void eeepc_set_fan_pwm(int value)
874 value = SENSORS_LIMIT(value, 0, 255);
875 value = value * 100 / 255;
876 ec_write(EEEPC_EC_SC02, value);
879 static int eeepc_get_fan_rpm(void)
881 int high = 0;
882 int low = 0;
884 read_acpi_int(NULL, EEEPC_EC_FAN_HRPM, &high);
885 read_acpi_int(NULL, EEEPC_EC_FAN_LRPM, &low);
886 return (high << 8 | low);
889 static int eeepc_get_fan_ctrl(void)
891 int value = 0;
893 read_acpi_int(NULL, EEEPC_EC_FAN_CTRL, &value);
894 return ((value & 0x02 ? 1 : 0));
897 static void eeepc_set_fan_ctrl(int manual)
899 int value = 0;
901 read_acpi_int(NULL, EEEPC_EC_FAN_CTRL, &value);
902 if (manual)
903 value |= 0x02;
904 else
905 value &= ~0x02;
906 ec_write(EEEPC_EC_SFB3, value);
909 static ssize_t store_sys_hwmon(void (*set)(int), const char *buf, size_t count)
911 int rv, value;
913 rv = parse_arg(buf, count, &value);
914 if (rv > 0)
915 set(value);
916 return rv;
919 static ssize_t show_sys_hwmon(int (*get)(void), char *buf)
921 return sprintf(buf, "%d\n", get());
924 #define EEEPC_CREATE_SENSOR_ATTR(_name, _mode, _set, _get) \
925 static ssize_t show_##_name(struct device *dev, \
926 struct device_attribute *attr, \
927 char *buf) \
929 return show_sys_hwmon(_set, buf); \
931 static ssize_t store_##_name(struct device *dev, \
932 struct device_attribute *attr, \
933 const char *buf, size_t count) \
935 return store_sys_hwmon(_get, buf, count); \
937 static SENSOR_DEVICE_ATTR(_name, _mode, show_##_name, store_##_name, 0);
939 EEEPC_CREATE_SENSOR_ATTR(fan1_input, S_IRUGO, eeepc_get_fan_rpm, NULL);
940 EEEPC_CREATE_SENSOR_ATTR(pwm1, S_IRUGO | S_IWUSR,
941 eeepc_get_fan_pwm, eeepc_set_fan_pwm);
942 EEEPC_CREATE_SENSOR_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
943 eeepc_get_fan_ctrl, eeepc_set_fan_ctrl);
945 static ssize_t
946 show_name(struct device *dev, struct device_attribute *attr, char *buf)
948 return sprintf(buf, "eeepc\n");
950 static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0);
952 static struct attribute *hwmon_attributes[] = {
953 &sensor_dev_attr_pwm1.dev_attr.attr,
954 &sensor_dev_attr_fan1_input.dev_attr.attr,
955 &sensor_dev_attr_pwm1_enable.dev_attr.attr,
956 &sensor_dev_attr_name.dev_attr.attr,
957 NULL
960 static struct attribute_group hwmon_attribute_group = {
961 .attrs = hwmon_attributes
965 * exit/init
967 static void eeepc_backlight_exit(void)
969 if (eeepc_backlight_device)
970 backlight_device_unregister(eeepc_backlight_device);
971 eeepc_backlight_device = NULL;
974 static void eeepc_rfkill_exit(void)
976 if (ehotk->eeepc_wlan_rfkill)
977 rfkill_unregister(ehotk->eeepc_wlan_rfkill);
978 if (ehotk->eeepc_bluetooth_rfkill)
979 rfkill_unregister(ehotk->eeepc_bluetooth_rfkill);
982 static void eeepc_input_exit(void)
984 if (ehotk->inputdev)
985 input_unregister_device(ehotk->inputdev);
988 static void eeepc_hwmon_exit(void)
990 struct device *hwmon;
992 hwmon = eeepc_hwmon_device;
993 if (!hwmon)
994 return ;
995 sysfs_remove_group(&hwmon->kobj,
996 &hwmon_attribute_group);
997 hwmon_device_unregister(hwmon);
998 eeepc_hwmon_device = NULL;
1001 static void __exit eeepc_laptop_exit(void)
1003 eeepc_backlight_exit();
1004 eeepc_rfkill_exit();
1005 eeepc_input_exit();
1006 eeepc_hwmon_exit();
1007 acpi_bus_unregister_driver(&eeepc_hotk_driver);
1008 sysfs_remove_group(&platform_device->dev.kobj,
1009 &platform_attribute_group);
1010 platform_device_unregister(platform_device);
1011 platform_driver_unregister(&platform_driver);
1014 static int eeepc_backlight_init(struct device *dev)
1016 struct backlight_device *bd;
1018 bd = backlight_device_register(EEEPC_HOTK_FILE, dev,
1019 NULL, &eeepcbl_ops);
1020 if (IS_ERR(bd)) {
1021 printk(EEEPC_ERR
1022 "Could not register eeepc backlight device\n");
1023 eeepc_backlight_device = NULL;
1024 return PTR_ERR(bd);
1026 eeepc_backlight_device = bd;
1027 bd->props.max_brightness = 15;
1028 bd->props.brightness = read_brightness(NULL);
1029 bd->props.power = FB_BLANK_UNBLANK;
1030 backlight_update_status(bd);
1031 return 0;
1034 static int eeepc_hwmon_init(struct device *dev)
1036 struct device *hwmon;
1037 int result;
1039 hwmon = hwmon_device_register(dev);
1040 if (IS_ERR(hwmon)) {
1041 printk(EEEPC_ERR
1042 "Could not register eeepc hwmon device\n");
1043 eeepc_hwmon_device = NULL;
1044 return PTR_ERR(hwmon);
1046 eeepc_hwmon_device = hwmon;
1047 result = sysfs_create_group(&hwmon->kobj,
1048 &hwmon_attribute_group);
1049 if (result)
1050 eeepc_hwmon_exit();
1051 return result;
1054 static int __init eeepc_laptop_init(void)
1056 struct device *dev;
1057 int result;
1059 if (acpi_disabled)
1060 return -ENODEV;
1061 result = acpi_bus_register_driver(&eeepc_hotk_driver);
1062 if (result < 0)
1063 return result;
1064 if (!ehotk) {
1065 acpi_bus_unregister_driver(&eeepc_hotk_driver);
1066 return -ENODEV;
1068 dev = acpi_get_physical_device(ehotk->device->handle);
1070 if (!acpi_video_backlight_support()) {
1071 result = eeepc_backlight_init(dev);
1072 if (result)
1073 goto fail_backlight;
1074 } else
1075 printk(EEEPC_INFO "Backlight controlled by ACPI video "
1076 "driver\n");
1078 result = eeepc_hwmon_init(dev);
1079 if (result)
1080 goto fail_hwmon;
1082 eeepc_enable_camera();
1084 /* Register platform stuff */
1085 result = platform_driver_register(&platform_driver);
1086 if (result)
1087 goto fail_platform_driver;
1088 platform_device = platform_device_alloc(EEEPC_HOTK_FILE, -1);
1089 if (!platform_device) {
1090 result = -ENOMEM;
1091 goto fail_platform_device1;
1093 result = platform_device_add(platform_device);
1094 if (result)
1095 goto fail_platform_device2;
1096 result = sysfs_create_group(&platform_device->dev.kobj,
1097 &platform_attribute_group);
1098 if (result)
1099 goto fail_sysfs;
1100 return 0;
1101 fail_sysfs:
1102 platform_device_del(platform_device);
1103 fail_platform_device2:
1104 platform_device_put(platform_device);
1105 fail_platform_device1:
1106 platform_driver_unregister(&platform_driver);
1107 fail_platform_driver:
1108 eeepc_hwmon_exit();
1109 fail_hwmon:
1110 eeepc_backlight_exit();
1111 fail_backlight:
1112 eeepc_input_exit();
1113 eeepc_rfkill_exit();
1114 return result;
1117 module_init(eeepc_laptop_init);
1118 module_exit(eeepc_laptop_exit);