eeepc-laptop: report brightness control events via the input layer
[linux-2.6] / drivers / platform / x86 / eeepc-laptop.c
1 /*
2  *  eepc-laptop.c - Asus Eee PC extras
3  *
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
7  *
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.
12  *
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.
17  */
18
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
35 #define EEEPC_LAPTOP_VERSION    "0.1"
36
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"
42
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
48
49 /*
50  * Definitions for Asus EeePC
51  */
52 #define NOTIFY_WLAN_ON  0x10
53 #define NOTIFY_BRN_MIN  0x20
54 #define NOTIFY_BRN_MAX  0x2f
55
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 };
67
68 enum {
69         CM_ASL_WLAN = 0,
70         CM_ASL_BLUETOOTH,
71         CM_ASL_IRDA,
72         CM_ASL_1394,
73         CM_ASL_CAMERA,
74         CM_ASL_TV,
75         CM_ASL_GPS,
76         CM_ASL_DVDROM,
77         CM_ASL_DISPLAYSWITCH,
78         CM_ASL_PANELBRIGHT,
79         CM_ASL_BIOSFLASH,
80         CM_ASL_ACPIFLASH,
81         CM_ASL_CPUFV,
82         CM_ASL_CPUTEMPERATURE,
83         CM_ASL_FANCPU,
84         CM_ASL_FANCHASSIS,
85         CM_ASL_USBPORT1,
86         CM_ASL_USBPORT2,
87         CM_ASL_USBPORT3,
88         CM_ASL_MODEM,
89         CM_ASL_CARDREADER,
90         CM_ASL_LID
91 };
92
93 static const char *cm_getv[] = {
94         "WLDG", "BTHG", NULL, NULL,
95         "CAMG", NULL, NULL, NULL,
96         NULL, "PBLG", NULL, NULL,
97         "CFVG", NULL, NULL, NULL,
98         "USBG", NULL, NULL, "MODG",
99         "CRDG", "LIDG"
100 };
101
102 static const char *cm_setv[] = {
103         "WLDS", "BTHS", NULL, NULL,
104         "CAMS", NULL, NULL, NULL,
105         "SDSP", "PBLS", "HDPS", NULL,
106         "CFVS", NULL, NULL, NULL,
107         "USBG", NULL, NULL, "MODS",
108         "CRDS", NULL
109 };
110
111 #define EEEPC_EC        "\\_SB.PCI0.SBRG.EC0."
112
113 #define EEEPC_EC_FAN_PWM        EEEPC_EC "SC02" /* Fan PWM duty cycle (%) */
114 #define EEEPC_EC_SC02           0x63
115 #define EEEPC_EC_FAN_HRPM       EEEPC_EC "SC05" /* High byte, fan speed (RPM) */
116 #define EEEPC_EC_FAN_LRPM       EEEPC_EC "SC06" /* Low byte, fan speed (RPM) */
117 #define EEEPC_EC_FAN_CTRL       EEEPC_EC "SFB3" /* Byte containing SF25  */
118 #define EEEPC_EC_SFB3           0xD3
119
120 /*
121  * This is the main structure, we can use it to store useful information
122  * about the hotk device
123  */
124 struct eeepc_hotk {
125         struct acpi_device *device;     /* the device we are in */
126         acpi_handle handle;             /* the handle of the hotk device */
127         u32 cm_supported;               /* the control methods supported
128                                            by this BIOS */
129         uint init_flag;                 /* Init flags */
130         u16 event_count[128];           /* count for each event */
131         struct input_dev *inputdev;
132         u16 *keycode_map;
133         struct rfkill *eeepc_wlan_rfkill;
134         struct rfkill *eeepc_bluetooth_rfkill;
135 };
136
137 /* The actual device the driver binds to */
138 static struct eeepc_hotk *ehotk;
139
140 /* Platform device/driver */
141 static struct platform_driver platform_driver = {
142         .driver = {
143                 .name = EEEPC_HOTK_FILE,
144                 .owner = THIS_MODULE,
145         }
146 };
147
148 static struct platform_device *platform_device;
149
150 struct key_entry {
151         char type;
152         u8 code;
153         u16 keycode;
154 };
155
156 enum { KE_KEY, KE_END };
157
158 static struct key_entry eeepc_keymap[] = {
159         /* Sleep already handled via generic ACPI code */
160         {KE_KEY, 0x10, KEY_WLAN },
161         {KE_KEY, 0x12, KEY_PROG1 },
162         {KE_KEY, 0x13, KEY_MUTE },
163         {KE_KEY, 0x14, KEY_VOLUMEDOWN },
164         {KE_KEY, 0x15, KEY_VOLUMEUP },
165         {KE_KEY, 0x1a, KEY_COFFEE },
166         {KE_KEY, 0x1b, KEY_ZOOM },
167         {KE_KEY, 0x1c, KEY_PROG2 },
168         {KE_KEY, 0x1d, KEY_PROG3 },
169         {KE_KEY, NOTIFY_BRN_MIN,     KEY_BRIGHTNESSDOWN },
170         {KE_KEY, NOTIFY_BRN_MIN + 2, KEY_BRIGHTNESSUP },
171         {KE_KEY, 0x30, KEY_SWITCHVIDEOMODE },
172         {KE_KEY, 0x31, KEY_SWITCHVIDEOMODE },
173         {KE_KEY, 0x32, KEY_SWITCHVIDEOMODE },
174         {KE_END, 0},
175 };
176
177 /*
178  * The hotkey driver declaration
179  */
180 static int eeepc_hotk_add(struct acpi_device *device);
181 static int eeepc_hotk_remove(struct acpi_device *device, int type);
182
183 static const struct acpi_device_id eeepc_device_ids[] = {
184         {EEEPC_HOTK_HID, 0},
185         {"", 0},
186 };
187 MODULE_DEVICE_TABLE(acpi, eeepc_device_ids);
188
189 static struct acpi_driver eeepc_hotk_driver = {
190         .name = EEEPC_HOTK_NAME,
191         .class = EEEPC_HOTK_CLASS,
192         .ids = eeepc_device_ids,
193         .ops = {
194                 .add = eeepc_hotk_add,
195                 .remove = eeepc_hotk_remove,
196         },
197 };
198
199 /* The backlight device /sys/class/backlight */
200 static struct backlight_device *eeepc_backlight_device;
201
202 /* The hwmon device */
203 static struct device *eeepc_hwmon_device;
204
205 /*
206  * The backlight class declaration
207  */
208 static int read_brightness(struct backlight_device *bd);
209 static int update_bl_status(struct backlight_device *bd);
210 static struct backlight_ops eeepcbl_ops = {
211         .get_brightness = read_brightness,
212         .update_status = update_bl_status,
213 };
214
215 MODULE_AUTHOR("Corentin Chary, Eric Cooper");
216 MODULE_DESCRIPTION(EEEPC_HOTK_NAME);
217 MODULE_LICENSE("GPL");
218
219 /*
220  * ACPI Helpers
221  */
222 static int write_acpi_int(acpi_handle handle, const char *method, int val,
223                           struct acpi_buffer *output)
224 {
225         struct acpi_object_list params;
226         union acpi_object in_obj;
227         acpi_status status;
228
229         params.count = 1;
230         params.pointer = &in_obj;
231         in_obj.type = ACPI_TYPE_INTEGER;
232         in_obj.integer.value = val;
233
234         status = acpi_evaluate_object(handle, (char *)method, &params, output);
235         return (status == AE_OK ? 0 : -1);
236 }
237
238 static int read_acpi_int(acpi_handle handle, const char *method, int *val)
239 {
240         acpi_status status;
241         unsigned long long result;
242
243         status = acpi_evaluate_integer(handle, (char *)method, NULL, &result);
244         if (ACPI_FAILURE(status)) {
245                 *val = -1;
246                 return -1;
247         } else {
248                 *val = result;
249                 return 0;
250         }
251 }
252
253 static int set_acpi(int cm, int value)
254 {
255         if (ehotk->cm_supported & (0x1 << cm)) {
256                 const char *method = cm_setv[cm];
257                 if (method == NULL)
258                         return -ENODEV;
259                 if (write_acpi_int(ehotk->handle, method, value, NULL))
260                         printk(EEEPC_WARNING "Error writing %s\n", method);
261         }
262         return 0;
263 }
264
265 static int get_acpi(int cm)
266 {
267         int value = -1;
268         if ((ehotk->cm_supported & (0x1 << cm))) {
269                 const char *method = cm_getv[cm];
270                 if (method == NULL)
271                         return -ENODEV;
272                 if (read_acpi_int(ehotk->handle, method, &value))
273                         printk(EEEPC_WARNING "Error reading %s\n", method);
274         }
275         return value;
276 }
277
278 /*
279  * Backlight
280  */
281 static int read_brightness(struct backlight_device *bd)
282 {
283         return get_acpi(CM_ASL_PANELBRIGHT);
284 }
285
286 static int set_brightness(struct backlight_device *bd, int value)
287 {
288         value = max(0, min(15, value));
289         return set_acpi(CM_ASL_PANELBRIGHT, value);
290 }
291
292 static int update_bl_status(struct backlight_device *bd)
293 {
294         return set_brightness(bd, bd->props.brightness);
295 }
296
297 /*
298  * Rfkill helpers
299  */
300
301 static int eeepc_wlan_rfkill_set(void *data, enum rfkill_state state)
302 {
303         if (state == RFKILL_STATE_SOFT_BLOCKED)
304                 return set_acpi(CM_ASL_WLAN, 0);
305         else
306                 return set_acpi(CM_ASL_WLAN, 1);
307 }
308
309 static int eeepc_wlan_rfkill_state(void *data, enum rfkill_state *state)
310 {
311         if (get_acpi(CM_ASL_WLAN) == 1)
312                 *state = RFKILL_STATE_UNBLOCKED;
313         else
314                 *state = RFKILL_STATE_SOFT_BLOCKED;
315         return 0;
316 }
317
318 static int eeepc_bluetooth_rfkill_set(void *data, enum rfkill_state state)
319 {
320         if (state == RFKILL_STATE_SOFT_BLOCKED)
321                 return set_acpi(CM_ASL_BLUETOOTH, 0);
322         else
323                 return set_acpi(CM_ASL_BLUETOOTH, 1);
324 }
325
326 static int eeepc_bluetooth_rfkill_state(void *data, enum rfkill_state *state)
327 {
328         if (get_acpi(CM_ASL_BLUETOOTH) == 1)
329                 *state = RFKILL_STATE_UNBLOCKED;
330         else
331                 *state = RFKILL_STATE_SOFT_BLOCKED;
332         return 0;
333 }
334
335 /*
336  * Sys helpers
337  */
338 static int parse_arg(const char *buf, unsigned long count, int *val)
339 {
340         if (!count)
341                 return 0;
342         if (sscanf(buf, "%i", val) != 1)
343                 return -EINVAL;
344         return count;
345 }
346
347 static ssize_t store_sys_acpi(int cm, const char *buf, size_t count)
348 {
349         int rv, value;
350
351         rv = parse_arg(buf, count, &value);
352         if (rv > 0)
353                 set_acpi(cm, value);
354         return rv;
355 }
356
357 static ssize_t show_sys_acpi(int cm, char *buf)
358 {
359         return sprintf(buf, "%d\n", get_acpi(cm));
360 }
361
362 #define EEEPC_CREATE_DEVICE_ATTR(_name, _cm)                            \
363         static ssize_t show_##_name(struct device *dev,                 \
364                                     struct device_attribute *attr,      \
365                                     char *buf)                          \
366         {                                                               \
367                 return show_sys_acpi(_cm, buf);                         \
368         }                                                               \
369         static ssize_t store_##_name(struct device *dev,                \
370                                      struct device_attribute *attr,     \
371                                      const char *buf, size_t count)     \
372         {                                                               \
373                 return store_sys_acpi(_cm, buf, count);                 \
374         }                                                               \
375         static struct device_attribute dev_attr_##_name = {             \
376                 .attr = {                                               \
377                         .name = __stringify(_name),                     \
378                         .mode = 0644 },                                 \
379                 .show   = show_##_name,                                 \
380                 .store  = store_##_name,                                \
381         }
382
383 EEEPC_CREATE_DEVICE_ATTR(camera, CM_ASL_CAMERA);
384 EEEPC_CREATE_DEVICE_ATTR(cardr, CM_ASL_CARDREADER);
385 EEEPC_CREATE_DEVICE_ATTR(disp, CM_ASL_DISPLAYSWITCH);
386
387 static struct attribute *platform_attributes[] = {
388         &dev_attr_camera.attr,
389         &dev_attr_cardr.attr,
390         &dev_attr_disp.attr,
391         NULL
392 };
393
394 static struct attribute_group platform_attribute_group = {
395         .attrs = platform_attributes
396 };
397
398 /*
399  * Hotkey functions
400  */
401 static struct key_entry *eepc_get_entry_by_scancode(int code)
402 {
403         struct key_entry *key;
404
405         for (key = eeepc_keymap; key->type != KE_END; key++)
406                 if (code == key->code)
407                         return key;
408
409         return NULL;
410 }
411
412 static struct key_entry *eepc_get_entry_by_keycode(int code)
413 {
414         struct key_entry *key;
415
416         for (key = eeepc_keymap; key->type != KE_END; key++)
417                 if (code == key->keycode && key->type == KE_KEY)
418                         return key;
419
420         return NULL;
421 }
422
423 static int eeepc_getkeycode(struct input_dev *dev, int scancode, int *keycode)
424 {
425         struct key_entry *key = eepc_get_entry_by_scancode(scancode);
426
427         if (key && key->type == KE_KEY) {
428                 *keycode = key->keycode;
429                 return 0;
430         }
431
432         return -EINVAL;
433 }
434
435 static int eeepc_setkeycode(struct input_dev *dev, int scancode, int keycode)
436 {
437         struct key_entry *key;
438         int old_keycode;
439
440         if (keycode < 0 || keycode > KEY_MAX)
441                 return -EINVAL;
442
443         key = eepc_get_entry_by_scancode(scancode);
444         if (key && key->type == KE_KEY) {
445                 old_keycode = key->keycode;
446                 key->keycode = keycode;
447                 set_bit(keycode, dev->keybit);
448                 if (!eepc_get_entry_by_keycode(old_keycode))
449                         clear_bit(old_keycode, dev->keybit);
450                 return 0;
451         }
452
453         return -EINVAL;
454 }
455
456 static int eeepc_hotk_check(void)
457 {
458         const struct key_entry *key;
459         struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
460         int result;
461
462         result = acpi_bus_get_status(ehotk->device);
463         if (result)
464                 return result;
465         if (ehotk->device->status.present) {
466                 if (write_acpi_int(ehotk->handle, "INIT", ehotk->init_flag,
467                                     &buffer)) {
468                         printk(EEEPC_ERR "Hotkey initialization failed\n");
469                         return -ENODEV;
470                 } else {
471                         printk(EEEPC_NOTICE "Hotkey init flags 0x%x\n",
472                                ehotk->init_flag);
473                 }
474                 /* get control methods supported */
475                 if (read_acpi_int(ehotk->handle, "CMSG"
476                                    , &ehotk->cm_supported)) {
477                         printk(EEEPC_ERR
478                                "Get control methods supported failed\n");
479                         return -ENODEV;
480                 } else {
481                         printk(EEEPC_INFO
482                                "Get control methods supported: 0x%x\n",
483                                ehotk->cm_supported);
484                 }
485                 ehotk->inputdev = input_allocate_device();
486                 if (!ehotk->inputdev) {
487                         printk(EEEPC_INFO "Unable to allocate input device\n");
488                         return 0;
489                 }
490                 ehotk->inputdev->name = "Asus EeePC extra buttons";
491                 ehotk->inputdev->phys = EEEPC_HOTK_FILE "/input0";
492                 ehotk->inputdev->id.bustype = BUS_HOST;
493                 ehotk->inputdev->getkeycode = eeepc_getkeycode;
494                 ehotk->inputdev->setkeycode = eeepc_setkeycode;
495
496                 for (key = eeepc_keymap; key->type != KE_END; key++) {
497                         switch (key->type) {
498                         case KE_KEY:
499                                 set_bit(EV_KEY, ehotk->inputdev->evbit);
500                                 set_bit(key->keycode, ehotk->inputdev->keybit);
501                                 break;
502                         }
503                 }
504                 result = input_register_device(ehotk->inputdev);
505                 if (result) {
506                         printk(EEEPC_INFO "Unable to register input device\n");
507                         input_free_device(ehotk->inputdev);
508                         return 0;
509                 }
510         } else {
511                 printk(EEEPC_ERR "Hotkey device not present, aborting\n");
512                 return -EINVAL;
513         }
514         return 0;
515 }
516
517 static int notify_brn(void)
518 {
519         /* returns the *previous* brightness, or -1 */
520         struct backlight_device *bd = eeepc_backlight_device;
521         if (bd) {
522                 int old = bd->props.brightness;
523                 bd->props.brightness = read_brightness(bd);
524                 return old;
525         }
526         return -1;
527 }
528
529 static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
530 {
531         struct pci_dev *dev;
532         struct pci_bus *bus = pci_find_bus(0, 1);
533
534         if (event != ACPI_NOTIFY_BUS_CHECK)
535                 return;
536
537         if (!bus) {
538                 printk(EEEPC_WARNING "Unable to find PCI bus 1?\n");
539                 return;
540         }
541
542         if (get_acpi(CM_ASL_WLAN) == 1) {
543                 dev = pci_get_slot(bus, 0);
544                 if (dev) {
545                         /* Device already present */
546                         pci_dev_put(dev);
547                         return;
548                 }
549                 dev = pci_scan_single_device(bus, 0);
550                 if (dev) {
551                         pci_bus_assign_resources(bus);
552                         if (pci_bus_add_device(dev))
553                                 printk(EEEPC_ERR "Unable to hotplug wifi\n");
554                 }
555         } else {
556                 dev = pci_get_slot(bus, 0);
557                 if (dev) {
558                         pci_remove_bus_device(dev);
559                         pci_dev_put(dev);
560                 }
561         }
562 }
563
564 static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data)
565 {
566         static struct key_entry *key;
567         u16 count;
568         int brn = -ENODEV;
569
570         if (!ehotk)
571                 return;
572         if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX)
573                 brn = notify_brn();
574         count = ehotk->event_count[event % 128]++;
575         acpi_bus_generate_proc_event(ehotk->device, event, count);
576         acpi_bus_generate_netlink_event(ehotk->device->pnp.device_class,
577                                         dev_name(&ehotk->device->dev), event,
578                                         count);
579         if (ehotk->inputdev) {
580                 if (brn != -ENODEV) {
581                         /* brightness-change events need special
582                          * handling for conversion to key events
583                          */
584                         if (brn < 0)
585                                 brn = event;
586                         else
587                                 brn += NOTIFY_BRN_MIN;
588                         if (event < brn)
589                                 event = NOTIFY_BRN_MIN; /* brightness down */
590                         else if (event > brn)
591                                 event = NOTIFY_BRN_MIN + 2; /* ... up */
592                         else
593                                 event = NOTIFY_BRN_MIN + 1; /* ... unchanged */
594                 }
595                 key = eepc_get_entry_by_scancode(event);
596                 if (key) {
597                         switch (key->type) {
598                         case KE_KEY:
599                                 input_report_key(ehotk->inputdev, key->keycode,
600                                                  1);
601                                 input_sync(ehotk->inputdev);
602                                 input_report_key(ehotk->inputdev, key->keycode,
603                                                  0);
604                                 input_sync(ehotk->inputdev);
605                                 break;
606                         }
607                 }
608         }
609 }
610
611 static int eeepc_register_rfkill_notifier(char *node)
612 {
613         acpi_status status = AE_OK;
614         acpi_handle handle;
615
616         status = acpi_get_handle(NULL, node, &handle);
617
618         if (ACPI_SUCCESS(status)) {
619                 status = acpi_install_notify_handler(handle,
620                                                      ACPI_SYSTEM_NOTIFY,
621                                                      eeepc_rfkill_notify,
622                                                      NULL);
623                 if (ACPI_FAILURE(status))
624                         printk(EEEPC_WARNING
625                                "Failed to register notify on %s\n", node);
626         } else
627                 return -ENODEV;
628
629         return 0;
630 }
631
632 static void eeepc_unregister_rfkill_notifier(char *node)
633 {
634         acpi_status status = AE_OK;
635         acpi_handle handle;
636
637         status = acpi_get_handle(NULL, node, &handle);
638
639         if (ACPI_SUCCESS(status)) {
640                 status = acpi_remove_notify_handler(handle,
641                                                      ACPI_SYSTEM_NOTIFY,
642                                                      eeepc_rfkill_notify);
643                 if (ACPI_FAILURE(status))
644                         printk(EEEPC_ERR
645                                "Error removing rfkill notify handler %s\n",
646                                 node);
647         }
648 }
649
650 static int eeepc_hotk_add(struct acpi_device *device)
651 {
652         acpi_status status = AE_OK;
653         int result;
654
655         if (!device)
656                  return -EINVAL;
657         printk(EEEPC_NOTICE EEEPC_HOTK_NAME "\n");
658         ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL);
659         if (!ehotk)
660                 return -ENOMEM;
661         ehotk->init_flag = DISABLE_ASL_WLAN | DISABLE_ASL_DISPLAYSWITCH;
662         ehotk->handle = device->handle;
663         strcpy(acpi_device_name(device), EEEPC_HOTK_DEVICE_NAME);
664         strcpy(acpi_device_class(device), EEEPC_HOTK_CLASS);
665         device->driver_data = ehotk;
666         ehotk->device = device;
667         result = eeepc_hotk_check();
668         if (result)
669                 goto ehotk_fail;
670         status = acpi_install_notify_handler(ehotk->handle, ACPI_SYSTEM_NOTIFY,
671                                              eeepc_hotk_notify, ehotk);
672         if (ACPI_FAILURE(status))
673                 printk(EEEPC_ERR "Error installing notify handler\n");
674
675         eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6");
676         eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7");
677
678         if (get_acpi(CM_ASL_WLAN) != -1) {
679                 ehotk->eeepc_wlan_rfkill = rfkill_allocate(&device->dev,
680                                                            RFKILL_TYPE_WLAN);
681
682                 if (!ehotk->eeepc_wlan_rfkill)
683                         goto wlan_fail;
684
685                 ehotk->eeepc_wlan_rfkill->name = "eeepc-wlan";
686                 ehotk->eeepc_wlan_rfkill->toggle_radio = eeepc_wlan_rfkill_set;
687                 ehotk->eeepc_wlan_rfkill->get_state = eeepc_wlan_rfkill_state;
688                 if (get_acpi(CM_ASL_WLAN) == 1) {
689                         ehotk->eeepc_wlan_rfkill->state =
690                                 RFKILL_STATE_UNBLOCKED;
691                         rfkill_set_default(RFKILL_TYPE_WLAN,
692                                            RFKILL_STATE_UNBLOCKED);
693                 } else {
694                         ehotk->eeepc_wlan_rfkill->state =
695                                 RFKILL_STATE_SOFT_BLOCKED;
696                         rfkill_set_default(RFKILL_TYPE_WLAN,
697                                            RFKILL_STATE_SOFT_BLOCKED);
698                 }
699                 result = rfkill_register(ehotk->eeepc_wlan_rfkill);
700                 if (result)
701                         goto wlan_fail;
702         }
703
704         if (get_acpi(CM_ASL_BLUETOOTH) != -1) {
705                 ehotk->eeepc_bluetooth_rfkill =
706                         rfkill_allocate(&device->dev, RFKILL_TYPE_BLUETOOTH);
707
708                 if (!ehotk->eeepc_bluetooth_rfkill)
709                         goto bluetooth_fail;
710
711                 ehotk->eeepc_bluetooth_rfkill->name = "eeepc-bluetooth";
712                 ehotk->eeepc_bluetooth_rfkill->toggle_radio =
713                         eeepc_bluetooth_rfkill_set;
714                 ehotk->eeepc_bluetooth_rfkill->get_state =
715                         eeepc_bluetooth_rfkill_state;
716                 if (get_acpi(CM_ASL_BLUETOOTH) == 1) {
717                         ehotk->eeepc_bluetooth_rfkill->state =
718                                 RFKILL_STATE_UNBLOCKED;
719                         rfkill_set_default(RFKILL_TYPE_BLUETOOTH,
720                                            RFKILL_STATE_UNBLOCKED);
721                 } else {
722                         ehotk->eeepc_bluetooth_rfkill->state =
723                                 RFKILL_STATE_SOFT_BLOCKED;
724                         rfkill_set_default(RFKILL_TYPE_BLUETOOTH,
725                                            RFKILL_STATE_SOFT_BLOCKED);
726                 }
727
728                 result = rfkill_register(ehotk->eeepc_bluetooth_rfkill);
729                 if (result)
730                         goto bluetooth_fail;
731         }
732
733         return 0;
734
735  bluetooth_fail:
736         if (ehotk->eeepc_bluetooth_rfkill)
737                 rfkill_free(ehotk->eeepc_bluetooth_rfkill);
738         rfkill_unregister(ehotk->eeepc_wlan_rfkill);
739         ehotk->eeepc_wlan_rfkill = NULL;
740  wlan_fail:
741         if (ehotk->eeepc_wlan_rfkill)
742                 rfkill_free(ehotk->eeepc_wlan_rfkill);
743  ehotk_fail:
744         kfree(ehotk);
745         ehotk = NULL;
746
747         return result;
748 }
749
750 static int eeepc_hotk_remove(struct acpi_device *device, int type)
751 {
752         acpi_status status = 0;
753
754         if (!device || !acpi_driver_data(device))
755                  return -EINVAL;
756         status = acpi_remove_notify_handler(ehotk->handle, ACPI_SYSTEM_NOTIFY,
757                                             eeepc_hotk_notify);
758         if (ACPI_FAILURE(status))
759                 printk(EEEPC_ERR "Error removing notify handler\n");
760
761         eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6");
762         eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7");
763
764         kfree(ehotk);
765         return 0;
766 }
767
768 /*
769  * Hwmon
770  */
771 static int eeepc_get_fan_pwm(void)
772 {
773         int value = 0;
774
775         read_acpi_int(NULL, EEEPC_EC_FAN_PWM, &value);
776         value = value * 255 / 100;
777         return (value);
778 }
779
780 static void eeepc_set_fan_pwm(int value)
781 {
782         value = SENSORS_LIMIT(value, 0, 255);
783         value = value * 100 / 255;
784         ec_write(EEEPC_EC_SC02, value);
785 }
786
787 static int eeepc_get_fan_rpm(void)
788 {
789         int high = 0;
790         int low = 0;
791
792         read_acpi_int(NULL, EEEPC_EC_FAN_HRPM, &high);
793         read_acpi_int(NULL, EEEPC_EC_FAN_LRPM, &low);
794         return (high << 8 | low);
795 }
796
797 static int eeepc_get_fan_ctrl(void)
798 {
799         int value = 0;
800
801         read_acpi_int(NULL, EEEPC_EC_FAN_CTRL, &value);
802         return ((value & 0x02 ? 1 : 0));
803 }
804
805 static void eeepc_set_fan_ctrl(int manual)
806 {
807         int value = 0;
808
809         read_acpi_int(NULL, EEEPC_EC_FAN_CTRL, &value);
810         if (manual)
811                 value |= 0x02;
812         else
813                 value &= ~0x02;
814         ec_write(EEEPC_EC_SFB3, value);
815 }
816
817 static ssize_t store_sys_hwmon(void (*set)(int), const char *buf, size_t count)
818 {
819         int rv, value;
820
821         rv = parse_arg(buf, count, &value);
822         if (rv > 0)
823                 set(value);
824         return rv;
825 }
826
827 static ssize_t show_sys_hwmon(int (*get)(void), char *buf)
828 {
829         return sprintf(buf, "%d\n", get());
830 }
831
832 #define EEEPC_CREATE_SENSOR_ATTR(_name, _mode, _set, _get)              \
833         static ssize_t show_##_name(struct device *dev,                 \
834                                     struct device_attribute *attr,      \
835                                     char *buf)                          \
836         {                                                               \
837                 return show_sys_hwmon(_set, buf);                       \
838         }                                                               \
839         static ssize_t store_##_name(struct device *dev,                \
840                                      struct device_attribute *attr,     \
841                                      const char *buf, size_t count)     \
842         {                                                               \
843                 return store_sys_hwmon(_get, buf, count);               \
844         }                                                               \
845         static SENSOR_DEVICE_ATTR(_name, _mode, show_##_name, store_##_name, 0);
846
847 EEEPC_CREATE_SENSOR_ATTR(fan1_input, S_IRUGO, eeepc_get_fan_rpm, NULL);
848 EEEPC_CREATE_SENSOR_ATTR(pwm1, S_IRUGO | S_IWUSR,
849                          eeepc_get_fan_pwm, eeepc_set_fan_pwm);
850 EEEPC_CREATE_SENSOR_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
851                          eeepc_get_fan_ctrl, eeepc_set_fan_ctrl);
852
853 static ssize_t
854 show_name(struct device *dev, struct device_attribute *attr, char *buf)
855 {
856         return sprintf(buf, "eeepc\n");
857 }
858 static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0);
859
860 static struct attribute *hwmon_attributes[] = {
861         &sensor_dev_attr_pwm1.dev_attr.attr,
862         &sensor_dev_attr_fan1_input.dev_attr.attr,
863         &sensor_dev_attr_pwm1_enable.dev_attr.attr,
864         &sensor_dev_attr_name.dev_attr.attr,
865         NULL
866 };
867
868 static struct attribute_group hwmon_attribute_group = {
869         .attrs = hwmon_attributes
870 };
871
872 /*
873  * exit/init
874  */
875 static void eeepc_backlight_exit(void)
876 {
877         if (eeepc_backlight_device)
878                 backlight_device_unregister(eeepc_backlight_device);
879         eeepc_backlight_device = NULL;
880 }
881
882 static void eeepc_rfkill_exit(void)
883 {
884         if (ehotk->eeepc_wlan_rfkill)
885                 rfkill_unregister(ehotk->eeepc_wlan_rfkill);
886         if (ehotk->eeepc_bluetooth_rfkill)
887                 rfkill_unregister(ehotk->eeepc_bluetooth_rfkill);
888 }
889
890 static void eeepc_input_exit(void)
891 {
892         if (ehotk->inputdev)
893                 input_unregister_device(ehotk->inputdev);
894 }
895
896 static void eeepc_hwmon_exit(void)
897 {
898         struct device *hwmon;
899
900         hwmon = eeepc_hwmon_device;
901         if (!hwmon)
902                 return ;
903         sysfs_remove_group(&hwmon->kobj,
904                            &hwmon_attribute_group);
905         hwmon_device_unregister(hwmon);
906         eeepc_hwmon_device = NULL;
907 }
908
909 static void __exit eeepc_laptop_exit(void)
910 {
911         eeepc_backlight_exit();
912         eeepc_rfkill_exit();
913         eeepc_input_exit();
914         eeepc_hwmon_exit();
915         acpi_bus_unregister_driver(&eeepc_hotk_driver);
916         sysfs_remove_group(&platform_device->dev.kobj,
917                            &platform_attribute_group);
918         platform_device_unregister(platform_device);
919         platform_driver_unregister(&platform_driver);
920 }
921
922 static int eeepc_backlight_init(struct device *dev)
923 {
924         struct backlight_device *bd;
925
926         bd = backlight_device_register(EEEPC_HOTK_FILE, dev,
927                                        NULL, &eeepcbl_ops);
928         if (IS_ERR(bd)) {
929                 printk(EEEPC_ERR
930                        "Could not register eeepc backlight device\n");
931                 eeepc_backlight_device = NULL;
932                 return PTR_ERR(bd);
933         }
934         eeepc_backlight_device = bd;
935         bd->props.max_brightness = 15;
936         bd->props.brightness = read_brightness(NULL);
937         bd->props.power = FB_BLANK_UNBLANK;
938         backlight_update_status(bd);
939         return 0;
940 }
941
942 static int eeepc_hwmon_init(struct device *dev)
943 {
944         struct device *hwmon;
945         int result;
946
947         hwmon = hwmon_device_register(dev);
948         if (IS_ERR(hwmon)) {
949                 printk(EEEPC_ERR
950                        "Could not register eeepc hwmon device\n");
951                 eeepc_hwmon_device = NULL;
952                 return PTR_ERR(hwmon);
953         }
954         eeepc_hwmon_device = hwmon;
955         result = sysfs_create_group(&hwmon->kobj,
956                                     &hwmon_attribute_group);
957         if (result)
958                 eeepc_hwmon_exit();
959         return result;
960 }
961
962 static int __init eeepc_laptop_init(void)
963 {
964         struct device *dev;
965         int result;
966
967         if (acpi_disabled)
968                 return -ENODEV;
969         result = acpi_bus_register_driver(&eeepc_hotk_driver);
970         if (result < 0)
971                 return result;
972         if (!ehotk) {
973                 acpi_bus_unregister_driver(&eeepc_hotk_driver);
974                 return -ENODEV;
975         }
976         dev = acpi_get_physical_device(ehotk->device->handle);
977
978         if (!acpi_video_backlight_support()) {
979                 result = eeepc_backlight_init(dev);
980                 if (result)
981                         goto fail_backlight;
982         } else
983                 printk(EEEPC_INFO "Backlight controlled by ACPI video "
984                        "driver\n");
985
986         result = eeepc_hwmon_init(dev);
987         if (result)
988                 goto fail_hwmon;
989         /* Register platform stuff */
990         result = platform_driver_register(&platform_driver);
991         if (result)
992                 goto fail_platform_driver;
993         platform_device = platform_device_alloc(EEEPC_HOTK_FILE, -1);
994         if (!platform_device) {
995                 result = -ENOMEM;
996                 goto fail_platform_device1;
997         }
998         result = platform_device_add(platform_device);
999         if (result)
1000                 goto fail_platform_device2;
1001         result = sysfs_create_group(&platform_device->dev.kobj,
1002                                     &platform_attribute_group);
1003         if (result)
1004                 goto fail_sysfs;
1005         return 0;
1006 fail_sysfs:
1007         platform_device_del(platform_device);
1008 fail_platform_device2:
1009         platform_device_put(platform_device);
1010 fail_platform_device1:
1011         platform_driver_unregister(&platform_driver);
1012 fail_platform_driver:
1013         eeepc_hwmon_exit();
1014 fail_hwmon:
1015         eeepc_backlight_exit();
1016 fail_backlight:
1017         eeepc_input_exit();
1018         eeepc_rfkill_exit();
1019         return result;
1020 }
1021
1022 module_init(eeepc_laptop_init);
1023 module_exit(eeepc_laptop_exit);