Linux 2.6.31-rc5
[deliverable/linux.git] / drivers / platform / x86 / eeepc-laptop.c
CommitLineData
e59f8796
EC
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
19b53289
JP
19#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
20
e59f8796
EC
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>
a5fa429b
CC
26#include <linux/backlight.h>
27#include <linux/fb.h>
e1faa9da
CC
28#include <linux/hwmon.h>
29#include <linux/hwmon-sysfs.h>
e59f8796
EC
30#include <acpi/acpi_drivers.h>
31#include <acpi/acpi_bus.h>
32#include <linux/uaccess.h>
a195dcdc
MG
33#include <linux/input.h>
34#include <linux/rfkill.h>
5740294c 35#include <linux/pci.h>
2b121bc2 36#include <linux/pci_hotplug.h>
e59f8796
EC
37
38#define EEEPC_LAPTOP_VERSION "0.1"
39
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"
45
e59f8796
EC
46
47/*
48 * Definitions for Asus EeePC
49 */
50#define NOTIFY_WLAN_ON 0x10
a5fa429b
CC
51#define NOTIFY_BRN_MIN 0x20
52#define NOTIFY_BRN_MAX 0x2f
e59f8796
EC
53
54enum {
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,
b7b700d4
CC
63 DISABLE_ASL_CARDREADER = 0x0100,
64 DISABLE_ASL_3G = 0x0200,
65 DISABLE_ASL_WIMAX = 0x0400,
66 DISABLE_ASL_HWCF = 0x0800
e59f8796
EC
67};
68
69enum {
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,
b7b700d4
CC
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
e59f8796
EC
98};
99
14109461 100static const char *cm_getv[] = {
3af9bfcb 101 "WLDG", "BTHG", NULL, NULL,
e59f8796
EC
102 "CAMG", NULL, NULL, NULL,
103 NULL, "PBLG", NULL, NULL,
104 "CFVG", NULL, NULL, NULL,
105 "USBG", NULL, NULL, "MODG",
b7b700d4
CC
106 "CRDG", "M3GG", "WIMG", "HWCF",
107 "LIDG", "TYPE", "PBPG", "TPDG"
e59f8796
EC
108};
109
14109461 110static const char *cm_setv[] = {
3af9bfcb 111 "WLDS", "BTHS", NULL, NULL,
e59f8796
EC
112 "CAMS", NULL, NULL, NULL,
113 "SDSP", "PBLS", "HDPS", NULL,
114 "CFVS", NULL, NULL, NULL,
115 "USBG", NULL, NULL, "MODS",
b7b700d4
CC
116 "CRDS", "M3GS", "WIMS", NULL,
117 NULL, NULL, "PBPS", "TPDS"
e59f8796
EC
118};
119
e1faa9da
CC
120#define EEEPC_EC "\\_SB.PCI0.SBRG.EC0."
121
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
128
e59f8796
EC
129/*
130 * This is the main structure, we can use it to store useful information
131 * about the hotk device
132 */
133struct 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 */
a195dcdc
MG
140 struct input_dev *inputdev;
141 u16 *keycode_map;
7de39389
CC
142 struct rfkill *wlan_rfkill;
143 struct rfkill *bluetooth_rfkill;
3cd530b5 144 struct rfkill *wwan3g_rfkill;
2b121bc2 145 struct hotplug_slot *hotplug_slot;
e59f8796
EC
146};
147
148/* The actual device the driver binds to */
149static struct eeepc_hotk *ehotk;
150
151/* Platform device/driver */
152static struct platform_driver platform_driver = {
153 .driver = {
154 .name = EEEPC_HOTK_FILE,
155 .owner = THIS_MODULE,
156 }
157};
158
159static struct platform_device *platform_device;
160
a195dcdc
MG
161struct key_entry {
162 char type;
163 u8 code;
164 u16 keycode;
165};
166
167enum { KE_KEY, KE_END };
168
169static struct key_entry eeepc_keymap[] = {
170 /* Sleep already handled via generic ACPI code */
171 {KE_KEY, 0x10, KEY_WLAN },
978605c4 172 {KE_KEY, 0x11, KEY_WLAN },
a195dcdc
MG
173 {KE_KEY, 0x12, KEY_PROG1 },
174 {KE_KEY, 0x13, KEY_MUTE },
175 {KE_KEY, 0x14, KEY_VOLUMEDOWN },
176 {KE_KEY, 0x15, KEY_VOLUMEUP },
b5f6f265
MG
177 {KE_KEY, 0x1a, KEY_COFFEE },
178 {KE_KEY, 0x1b, KEY_ZOOM },
179 {KE_KEY, 0x1c, KEY_PROG2 },
180 {KE_KEY, 0x1d, KEY_PROG3 },
64b86b65
DS
181 {KE_KEY, NOTIFY_BRN_MIN, KEY_BRIGHTNESSDOWN },
182 {KE_KEY, NOTIFY_BRN_MIN + 2, KEY_BRIGHTNESSUP },
a195dcdc
MG
183 {KE_KEY, 0x30, KEY_SWITCHVIDEOMODE },
184 {KE_KEY, 0x31, KEY_SWITCHVIDEOMODE },
185 {KE_KEY, 0x32, KEY_SWITCHVIDEOMODE },
186 {KE_END, 0},
187};
188
e59f8796
EC
189/*
190 * The hotkey driver declaration
191 */
192static int eeepc_hotk_add(struct acpi_device *device);
193static int eeepc_hotk_remove(struct acpi_device *device, int type);
96e9cfeb 194static int eeepc_hotk_resume(struct acpi_device *device);
d9b9bd7b 195static void eeepc_hotk_notify(struct acpi_device *device, u32 event);
e59f8796
EC
196
197static const struct acpi_device_id eeepc_device_ids[] = {
198 {EEEPC_HOTK_HID, 0},
199 {"", 0},
200};
201MODULE_DEVICE_TABLE(acpi, eeepc_device_ids);
202
203static struct acpi_driver eeepc_hotk_driver = {
204 .name = EEEPC_HOTK_NAME,
205 .class = EEEPC_HOTK_CLASS,
206 .ids = eeepc_device_ids,
d9b9bd7b 207 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
e59f8796
EC
208 .ops = {
209 .add = eeepc_hotk_add,
210 .remove = eeepc_hotk_remove,
96e9cfeb 211 .resume = eeepc_hotk_resume,
d9b9bd7b 212 .notify = eeepc_hotk_notify,
e59f8796
EC
213 },
214};
215
2b121bc2
CC
216/* PCI hotplug ops */
217static int eeepc_get_adapter_status(struct hotplug_slot *slot, u8 *value);
218
219static struct hotplug_slot_ops eeepc_hotplug_slot_ops = {
220 .owner = THIS_MODULE,
221 .get_adapter_status = eeepc_get_adapter_status,
222 .get_power_status = eeepc_get_adapter_status,
223};
224
a5fa429b
CC
225/* The backlight device /sys/class/backlight */
226static struct backlight_device *eeepc_backlight_device;
227
e1faa9da
CC
228/* The hwmon device */
229static struct device *eeepc_hwmon_device;
230
a5fa429b
CC
231/*
232 * The backlight class declaration
233 */
234static int read_brightness(struct backlight_device *bd);
235static int update_bl_status(struct backlight_device *bd);
236static struct backlight_ops eeepcbl_ops = {
237 .get_brightness = read_brightness,
238 .update_status = update_bl_status,
239};
240
e59f8796
EC
241MODULE_AUTHOR("Corentin Chary, Eric Cooper");
242MODULE_DESCRIPTION(EEEPC_HOTK_NAME);
243MODULE_LICENSE("GPL");
244
245/*
246 * ACPI Helpers
247 */
248static int write_acpi_int(acpi_handle handle, const char *method, int val,
249 struct acpi_buffer *output)
250{
251 struct acpi_object_list params;
252 union acpi_object in_obj;
253 acpi_status status;
254
255 params.count = 1;
256 params.pointer = &in_obj;
257 in_obj.type = ACPI_TYPE_INTEGER;
258 in_obj.integer.value = val;
259
260 status = acpi_evaluate_object(handle, (char *)method, &params, output);
261 return (status == AE_OK ? 0 : -1);
262}
263
264static int read_acpi_int(acpi_handle handle, const char *method, int *val)
265{
266 acpi_status status;
27663c58 267 unsigned long long result;
e59f8796
EC
268
269 status = acpi_evaluate_integer(handle, (char *)method, NULL, &result);
270 if (ACPI_FAILURE(status)) {
271 *val = -1;
272 return -1;
273 } else {
274 *val = result;
275 return 0;
276 }
277}
278
279static int set_acpi(int cm, int value)
280{
281 if (ehotk->cm_supported & (0x1 << cm)) {
282 const char *method = cm_setv[cm];
283 if (method == NULL)
284 return -ENODEV;
285 if (write_acpi_int(ehotk->handle, method, value, NULL))
19b53289 286 pr_warning("Error writing %s\n", method);
e59f8796
EC
287 }
288 return 0;
289}
290
291static int get_acpi(int cm)
292{
f36509e7 293 int value = -ENODEV;
e59f8796
EC
294 if ((ehotk->cm_supported & (0x1 << cm))) {
295 const char *method = cm_getv[cm];
296 if (method == NULL)
297 return -ENODEV;
298 if (read_acpi_int(ehotk->handle, method, &value))
19b53289 299 pr_warning("Error reading %s\n", method);
e59f8796
EC
300 }
301 return value;
302}
303
a5fa429b
CC
304/*
305 * Backlight
306 */
307static int read_brightness(struct backlight_device *bd)
308{
309 return get_acpi(CM_ASL_PANELBRIGHT);
310}
311
312static int set_brightness(struct backlight_device *bd, int value)
313{
314 value = max(0, min(15, value));
315 return set_acpi(CM_ASL_PANELBRIGHT, value);
316}
317
318static int update_bl_status(struct backlight_device *bd)
319{
320 return set_brightness(bd, bd->props.brightness);
321}
322
a195dcdc
MG
323/*
324 * Rfkill helpers
325 */
326
19d337df 327static bool eeepc_wlan_rfkill_blocked(void)
a195dcdc
MG
328{
329 if (get_acpi(CM_ASL_WLAN) == 1)
19d337df
JB
330 return false;
331 return true;
a195dcdc
MG
332}
333
19d337df 334static int eeepc_rfkill_set(void *data, bool blocked)
a195dcdc 335{
19d337df
JB
336 unsigned long asl = (unsigned long)data;
337 return set_acpi(asl, !blocked);
a195dcdc
MG
338}
339
19d337df
JB
340static const struct rfkill_ops eeepc_rfkill_ops = {
341 .set_block = eeepc_rfkill_set,
342};
a195dcdc 343
cede2cb6
PE
344static void __init eeepc_enable_camera(void)
345{
346 /*
347 * If the following call to set_acpi() fails, it's because there's no
348 * camera so we can ignore the error.
349 */
350 set_acpi(CM_ASL_CAMERA, 1);
351}
352
e59f8796
EC
353/*
354 * Sys helpers
355 */
356static int parse_arg(const char *buf, unsigned long count, int *val)
357{
358 if (!count)
359 return 0;
360 if (sscanf(buf, "%i", val) != 1)
361 return -EINVAL;
362 return count;
363}
364
365static ssize_t store_sys_acpi(int cm, const char *buf, size_t count)
366{
367 int rv, value;
368
369 rv = parse_arg(buf, count, &value);
370 if (rv > 0)
f36509e7
CC
371 value = set_acpi(cm, value);
372 if (value < 0)
373 return value;
e59f8796
EC
374 return rv;
375}
376
377static ssize_t show_sys_acpi(int cm, char *buf)
378{
f36509e7
CC
379 int value = get_acpi(cm);
380
381 if (value < 0)
382 return value;
383 return sprintf(buf, "%d\n", value);
e59f8796
EC
384}
385
386#define EEEPC_CREATE_DEVICE_ATTR(_name, _cm) \
387 static ssize_t show_##_name(struct device *dev, \
388 struct device_attribute *attr, \
389 char *buf) \
390 { \
391 return show_sys_acpi(_cm, buf); \
392 } \
393 static ssize_t store_##_name(struct device *dev, \
394 struct device_attribute *attr, \
395 const char *buf, size_t count) \
396 { \
397 return store_sys_acpi(_cm, buf, count); \
398 } \
399 static struct device_attribute dev_attr_##_name = { \
400 .attr = { \
401 .name = __stringify(_name), \
402 .mode = 0644 }, \
403 .show = show_##_name, \
404 .store = store_##_name, \
405 }
406
407EEEPC_CREATE_DEVICE_ATTR(camera, CM_ASL_CAMERA);
408EEEPC_CREATE_DEVICE_ATTR(cardr, CM_ASL_CARDREADER);
409EEEPC_CREATE_DEVICE_ATTR(disp, CM_ASL_DISPLAYSWITCH);
b31d0fde
CC
410
411struct eeepc_cpufv {
412 int num;
413 int cur;
414};
415
416static int get_cpufv(struct eeepc_cpufv *c)
417{
418 c->cur = get_acpi(CM_ASL_CPUFV);
419 c->num = (c->cur >> 8) & 0xff;
420 c->cur &= 0xff;
421 if (c->cur < 0 || c->num <= 0 || c->num > 12)
422 return -ENODEV;
423 return 0;
424}
425
426static ssize_t show_available_cpufv(struct device *dev,
427 struct device_attribute *attr,
428 char *buf)
429{
430 struct eeepc_cpufv c;
431 int i;
432 ssize_t len = 0;
433
434 if (get_cpufv(&c))
435 return -ENODEV;
436 for (i = 0; i < c.num; i++)
437 len += sprintf(buf + len, "%d ", i);
438 len += sprintf(buf + len, "\n");
439 return len;
440}
441
442static ssize_t show_cpufv(struct device *dev,
443 struct device_attribute *attr,
444 char *buf)
445{
446 struct eeepc_cpufv c;
447
448 if (get_cpufv(&c))
449 return -ENODEV;
450 return sprintf(buf, "%#x\n", (c.num << 8) | c.cur);
451}
452
453static ssize_t store_cpufv(struct device *dev,
454 struct device_attribute *attr,
455 const char *buf, size_t count)
456{
457 struct eeepc_cpufv c;
458 int rv, value;
459
460 if (get_cpufv(&c))
461 return -ENODEV;
462 rv = parse_arg(buf, count, &value);
463 if (rv < 0)
464 return rv;
465 if (!rv || value < 0 || value >= c.num)
466 return -EINVAL;
467 set_acpi(CM_ASL_CPUFV, value);
468 return rv;
469}
470
471static struct device_attribute dev_attr_cpufv = {
472 .attr = {
473 .name = "cpufv",
474 .mode = 0644 },
475 .show = show_cpufv,
476 .store = store_cpufv
477};
478
479static struct device_attribute dev_attr_available_cpufv = {
480 .attr = {
481 .name = "available_cpufv",
482 .mode = 0444 },
483 .show = show_available_cpufv
484};
e59f8796
EC
485
486static struct attribute *platform_attributes[] = {
487 &dev_attr_camera.attr,
488 &dev_attr_cardr.attr,
489 &dev_attr_disp.attr,
158ca1d7 490 &dev_attr_cpufv.attr,
b31d0fde 491 &dev_attr_available_cpufv.attr,
e59f8796
EC
492 NULL
493};
494
495static struct attribute_group platform_attribute_group = {
496 .attrs = platform_attributes
497};
498
499/*
500 * Hotkey functions
501 */
a195dcdc
MG
502static struct key_entry *eepc_get_entry_by_scancode(int code)
503{
504 struct key_entry *key;
505
506 for (key = eeepc_keymap; key->type != KE_END; key++)
507 if (code == key->code)
508 return key;
509
510 return NULL;
511}
512
513static struct key_entry *eepc_get_entry_by_keycode(int code)
514{
515 struct key_entry *key;
516
517 for (key = eeepc_keymap; key->type != KE_END; key++)
518 if (code == key->keycode && key->type == KE_KEY)
519 return key;
520
521 return NULL;
522}
523
524static int eeepc_getkeycode(struct input_dev *dev, int scancode, int *keycode)
525{
526 struct key_entry *key = eepc_get_entry_by_scancode(scancode);
527
528 if (key && key->type == KE_KEY) {
529 *keycode = key->keycode;
530 return 0;
531 }
532
533 return -EINVAL;
534}
535
536static int eeepc_setkeycode(struct input_dev *dev, int scancode, int keycode)
537{
538 struct key_entry *key;
539 int old_keycode;
540
541 if (keycode < 0 || keycode > KEY_MAX)
542 return -EINVAL;
543
544 key = eepc_get_entry_by_scancode(scancode);
545 if (key && key->type == KE_KEY) {
546 old_keycode = key->keycode;
547 key->keycode = keycode;
548 set_bit(keycode, dev->keybit);
549 if (!eepc_get_entry_by_keycode(old_keycode))
550 clear_bit(old_keycode, dev->keybit);
551 return 0;
552 }
553
554 return -EINVAL;
555}
556
dbfa3ba9
CC
557static void cmsg_quirk(int cm, const char *name)
558{
559 int dummy;
560
561 /* Some BIOSes do not report cm although it is avaliable.
562 Check if cm_getv[cm] works and, if yes, assume cm should be set. */
563 if (!(ehotk->cm_supported & (1 << cm))
564 && !read_acpi_int(ehotk->handle, cm_getv[cm], &dummy)) {
565 pr_info("%s (%x) not reported by BIOS,"
566 " enabling anyway\n", name, 1 << cm);
567 ehotk->cm_supported |= 1 << cm;
568 }
569}
570
571static void cmsg_quirks(void)
572{
573 cmsg_quirk(CM_ASL_LID, "LID");
574 cmsg_quirk(CM_ASL_TYPE, "TYPE");
575 cmsg_quirk(CM_ASL_PANELPOWER, "PANELPOWER");
576 cmsg_quirk(CM_ASL_TPD, "TPD");
577}
578
e59f8796
EC
579static int eeepc_hotk_check(void)
580{
a195dcdc 581 const struct key_entry *key;
e59f8796
EC
582 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
583 int result;
584
585 result = acpi_bus_get_status(ehotk->device);
586 if (result)
587 return result;
588 if (ehotk->device->status.present) {
589 if (write_acpi_int(ehotk->handle, "INIT", ehotk->init_flag,
590 &buffer)) {
19b53289 591 pr_err("Hotkey initialization failed\n");
e59f8796
EC
592 return -ENODEV;
593 } else {
19b53289 594 pr_notice("Hotkey init flags 0x%x\n", ehotk->init_flag);
e59f8796
EC
595 }
596 /* get control methods supported */
597 if (read_acpi_int(ehotk->handle, "CMSG"
598 , &ehotk->cm_supported)) {
19b53289 599 pr_err("Get control methods supported failed\n");
e59f8796
EC
600 return -ENODEV;
601 } else {
dbfa3ba9 602 cmsg_quirks();
19b53289
JP
603 pr_info("Get control methods supported: 0x%x\n",
604 ehotk->cm_supported);
e59f8796 605 }
a195dcdc
MG
606 ehotk->inputdev = input_allocate_device();
607 if (!ehotk->inputdev) {
19b53289 608 pr_info("Unable to allocate input device\n");
a195dcdc
MG
609 return 0;
610 }
611 ehotk->inputdev->name = "Asus EeePC extra buttons";
612 ehotk->inputdev->phys = EEEPC_HOTK_FILE "/input0";
613 ehotk->inputdev->id.bustype = BUS_HOST;
614 ehotk->inputdev->getkeycode = eeepc_getkeycode;
615 ehotk->inputdev->setkeycode = eeepc_setkeycode;
616
617 for (key = eeepc_keymap; key->type != KE_END; key++) {
618 switch (key->type) {
619 case KE_KEY:
620 set_bit(EV_KEY, ehotk->inputdev->evbit);
621 set_bit(key->keycode, ehotk->inputdev->keybit);
622 break;
623 }
624 }
625 result = input_register_device(ehotk->inputdev);
626 if (result) {
19b53289 627 pr_info("Unable to register input device\n");
a195dcdc
MG
628 input_free_device(ehotk->inputdev);
629 return 0;
630 }
e59f8796 631 } else {
19b53289 632 pr_err("Hotkey device not present, aborting\n");
e59f8796
EC
633 return -EINVAL;
634 }
635 return 0;
636}
637
64b86b65 638static int notify_brn(void)
a5fa429b 639{
64b86b65 640 /* returns the *previous* brightness, or -1 */
a5fa429b 641 struct backlight_device *bd = eeepc_backlight_device;
64b86b65
DS
642 if (bd) {
643 int old = bd->props.brightness;
7695fb04 644 bd->props.brightness = read_brightness(bd);
64b86b65
DS
645 return old;
646 }
647 return -1;
a5fa429b
CC
648}
649
2b121bc2
CC
650static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot,
651 u8 *value)
652{
653 int val = get_acpi(CM_ASL_WLAN);
654
655 if (val == 1 || val == 0)
656 *value = val;
657 else
658 return -EINVAL;
659
660 return 0;
661}
662
96e9cfeb 663static void eeepc_rfkill_hotplug(void)
5740294c
MG
664{
665 struct pci_dev *dev;
666 struct pci_bus *bus = pci_find_bus(0, 1);
19d337df 667 bool blocked;
5740294c 668
5740294c 669 if (!bus) {
19b53289 670 pr_warning("Unable to find PCI bus 1?\n");
5740294c
MG
671 return;
672 }
673
19d337df
JB
674 blocked = eeepc_wlan_rfkill_blocked();
675 if (!blocked) {
5740294c
MG
676 dev = pci_get_slot(bus, 0);
677 if (dev) {
678 /* Device already present */
679 pci_dev_put(dev);
680 return;
681 }
682 dev = pci_scan_single_device(bus, 0);
683 if (dev) {
684 pci_bus_assign_resources(bus);
685 if (pci_bus_add_device(dev))
19b53289 686 pr_err("Unable to hotplug wifi\n");
5740294c
MG
687 }
688 } else {
689 dev = pci_get_slot(bus, 0);
690 if (dev) {
691 pci_remove_bus_device(dev);
692 pci_dev_put(dev);
693 }
694 }
978605c4 695
7de39389 696 rfkill_set_sw_state(ehotk->wlan_rfkill, blocked);
5740294c
MG
697}
698
96e9cfeb
AJ
699static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
700{
701 if (event != ACPI_NOTIFY_BUS_CHECK)
702 return;
703
704 eeepc_rfkill_hotplug();
705}
706
d9b9bd7b 707static void eeepc_hotk_notify(struct acpi_device *device, u32 event)
e59f8796 708{
a195dcdc 709 static struct key_entry *key;
7950b71c 710 u16 count;
64b86b65 711 int brn = -ENODEV;
7950b71c 712
e59f8796
EC
713 if (!ehotk)
714 return;
d9b9bd7b
BH
715 if (event > ACPI_MAX_SYS_NOTIFY)
716 return;
a5fa429b 717 if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX)
64b86b65 718 brn = notify_brn();
7950b71c
CC
719 count = ehotk->event_count[event % 128]++;
720 acpi_bus_generate_proc_event(ehotk->device, event, count);
2b25c9f0
CC
721 acpi_bus_generate_netlink_event(ehotk->device->pnp.device_class,
722 dev_name(&ehotk->device->dev), event,
7950b71c 723 count);
a195dcdc 724 if (ehotk->inputdev) {
64b86b65
DS
725 if (brn != -ENODEV) {
726 /* brightness-change events need special
727 * handling for conversion to key events
728 */
729 if (brn < 0)
730 brn = event;
731 else
732 brn += NOTIFY_BRN_MIN;
733 if (event < brn)
734 event = NOTIFY_BRN_MIN; /* brightness down */
735 else if (event > brn)
736 event = NOTIFY_BRN_MIN + 2; /* ... up */
737 else
738 event = NOTIFY_BRN_MIN + 1; /* ... unchanged */
739 }
a195dcdc
MG
740 key = eepc_get_entry_by_scancode(event);
741 if (key) {
742 switch (key->type) {
743 case KE_KEY:
744 input_report_key(ehotk->inputdev, key->keycode,
745 1);
746 input_sync(ehotk->inputdev);
747 input_report_key(ehotk->inputdev, key->keycode,
748 0);
749 input_sync(ehotk->inputdev);
750 break;
751 }
752 }
753 }
e59f8796
EC
754}
755
5740294c
MG
756static int eeepc_register_rfkill_notifier(char *node)
757{
758 acpi_status status = AE_OK;
759 acpi_handle handle;
760
761 status = acpi_get_handle(NULL, node, &handle);
762
763 if (ACPI_SUCCESS(status)) {
764 status = acpi_install_notify_handler(handle,
765 ACPI_SYSTEM_NOTIFY,
766 eeepc_rfkill_notify,
767 NULL);
768 if (ACPI_FAILURE(status))
19b53289 769 pr_warning("Failed to register notify on %s\n", node);
5740294c
MG
770 } else
771 return -ENODEV;
772
773 return 0;
774}
775
776static void eeepc_unregister_rfkill_notifier(char *node)
777{
778 acpi_status status = AE_OK;
779 acpi_handle handle;
780
781 status = acpi_get_handle(NULL, node, &handle);
782
783 if (ACPI_SUCCESS(status)) {
784 status = acpi_remove_notify_handler(handle,
785 ACPI_SYSTEM_NOTIFY,
786 eeepc_rfkill_notify);
787 if (ACPI_FAILURE(status))
19b53289 788 pr_err("Error removing rfkill notify handler %s\n",
5740294c
MG
789 node);
790 }
791}
792
2b121bc2
CC
793static void eeepc_cleanup_pci_hotplug(struct hotplug_slot *hotplug_slot)
794{
795 kfree(hotplug_slot->info);
796 kfree(hotplug_slot);
797}
798
799static int eeepc_setup_pci_hotplug(void)
800{
801 int ret = -ENOMEM;
802 struct pci_bus *bus = pci_find_bus(0, 1);
803
804 if (!bus) {
19b53289 805 pr_err("Unable to find wifi PCI bus\n");
2b121bc2
CC
806 return -ENODEV;
807 }
808
809 ehotk->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
810 if (!ehotk->hotplug_slot)
811 goto error_slot;
812
813 ehotk->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info),
814 GFP_KERNEL);
815 if (!ehotk->hotplug_slot->info)
816 goto error_info;
817
818 ehotk->hotplug_slot->private = ehotk;
819 ehotk->hotplug_slot->release = &eeepc_cleanup_pci_hotplug;
820 ehotk->hotplug_slot->ops = &eeepc_hotplug_slot_ops;
821 eeepc_get_adapter_status(ehotk->hotplug_slot,
822 &ehotk->hotplug_slot->info->adapter_status);
823
824 ret = pci_hp_register(ehotk->hotplug_slot, bus, 0, "eeepc-wifi");
825 if (ret) {
19b53289 826 pr_err("Unable to register hotplug slot - %d\n", ret);
2b121bc2
CC
827 goto error_register;
828 }
829
830 return 0;
831
832error_register:
833 kfree(ehotk->hotplug_slot->info);
834error_info:
835 kfree(ehotk->hotplug_slot);
836 ehotk->hotplug_slot = NULL;
837error_slot:
838 return ret;
839}
840
e59f8796
EC
841static int eeepc_hotk_add(struct acpi_device *device)
842{
e59f8796
EC
843 int result;
844
845 if (!device)
846 return -EINVAL;
19b53289 847 pr_notice(EEEPC_HOTK_NAME "\n");
e59f8796
EC
848 ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL);
849 if (!ehotk)
850 return -ENOMEM;
851 ehotk->init_flag = DISABLE_ASL_WLAN | DISABLE_ASL_DISPLAYSWITCH;
852 ehotk->handle = device->handle;
853 strcpy(acpi_device_name(device), EEEPC_HOTK_DEVICE_NAME);
854 strcpy(acpi_device_class(device), EEEPC_HOTK_CLASS);
db89b4f0 855 device->driver_data = ehotk;
e59f8796
EC
856 ehotk->device = device;
857 result = eeepc_hotk_check();
858 if (result)
c9ddf8fe 859 goto ehotk_fail;
a195dcdc 860
c9ddf8fe
MG
861 return 0;
862
c9ddf8fe
MG
863 ehotk_fail:
864 kfree(ehotk);
865 ehotk = NULL;
866
e59f8796
EC
867 return result;
868}
869
870static int eeepc_hotk_remove(struct acpi_device *device, int type)
871{
e59f8796
EC
872 if (!device || !acpi_driver_data(device))
873 return -EINVAL;
5740294c 874
e59f8796
EC
875 kfree(ehotk);
876 return 0;
877}
878
96e9cfeb
AJ
879static int eeepc_hotk_resume(struct acpi_device *device)
880{
7de39389 881 if (ehotk->wlan_rfkill) {
96e9cfeb
AJ
882 bool wlan;
883
884 /* Workaround - it seems that _PTS disables the wireless
885 without notification or changing the value read by WLAN.
886 Normally this is fine because the correct value is restored
887 from the non-volatile storage on resume, but we need to do
888 it ourself if case suspend is aborted, or we lose wireless.
889 */
890 wlan = get_acpi(CM_ASL_WLAN);
891 set_acpi(CM_ASL_WLAN, wlan);
892
7de39389 893 rfkill_set_sw_state(ehotk->wlan_rfkill, wlan != 1);
96e9cfeb
AJ
894
895 eeepc_rfkill_hotplug();
896 }
897
7de39389
CC
898 if (ehotk->bluetooth_rfkill)
899 rfkill_set_sw_state(ehotk->bluetooth_rfkill,
96e9cfeb
AJ
900 get_acpi(CM_ASL_BLUETOOTH) != 1);
901
902 return 0;
903}
904
e1faa9da
CC
905/*
906 * Hwmon
907 */
908static int eeepc_get_fan_pwm(void)
909{
910 int value = 0;
911
912 read_acpi_int(NULL, EEEPC_EC_FAN_PWM, &value);
04dcd84b 913 value = value * 255 / 100;
e1faa9da
CC
914 return (value);
915}
916
917static void eeepc_set_fan_pwm(int value)
918{
04dcd84b
CC
919 value = SENSORS_LIMIT(value, 0, 255);
920 value = value * 100 / 255;
e1faa9da
CC
921 ec_write(EEEPC_EC_SC02, value);
922}
923
924static int eeepc_get_fan_rpm(void)
925{
926 int high = 0;
927 int low = 0;
928
929 read_acpi_int(NULL, EEEPC_EC_FAN_HRPM, &high);
930 read_acpi_int(NULL, EEEPC_EC_FAN_LRPM, &low);
931 return (high << 8 | low);
932}
933
934static int eeepc_get_fan_ctrl(void)
935{
936 int value = 0;
937
938 read_acpi_int(NULL, EEEPC_EC_FAN_CTRL, &value);
939 return ((value & 0x02 ? 1 : 0));
940}
941
942static void eeepc_set_fan_ctrl(int manual)
943{
944 int value = 0;
945
946 read_acpi_int(NULL, EEEPC_EC_FAN_CTRL, &value);
947 if (manual)
948 value |= 0x02;
949 else
950 value &= ~0x02;
951 ec_write(EEEPC_EC_SFB3, value);
952}
953
954static ssize_t store_sys_hwmon(void (*set)(int), const char *buf, size_t count)
955{
956 int rv, value;
957
958 rv = parse_arg(buf, count, &value);
959 if (rv > 0)
960 set(value);
961 return rv;
962}
963
964static ssize_t show_sys_hwmon(int (*get)(void), char *buf)
965{
966 return sprintf(buf, "%d\n", get());
967}
968
969#define EEEPC_CREATE_SENSOR_ATTR(_name, _mode, _set, _get) \
970 static ssize_t show_##_name(struct device *dev, \
971 struct device_attribute *attr, \
972 char *buf) \
973 { \
974 return show_sys_hwmon(_set, buf); \
975 } \
976 static ssize_t store_##_name(struct device *dev, \
977 struct device_attribute *attr, \
978 const char *buf, size_t count) \
979 { \
980 return store_sys_hwmon(_get, buf, count); \
981 } \
982 static SENSOR_DEVICE_ATTR(_name, _mode, show_##_name, store_##_name, 0);
983
984EEEPC_CREATE_SENSOR_ATTR(fan1_input, S_IRUGO, eeepc_get_fan_rpm, NULL);
04dcd84b 985EEEPC_CREATE_SENSOR_ATTR(pwm1, S_IRUGO | S_IWUSR,
e1faa9da
CC
986 eeepc_get_fan_pwm, eeepc_set_fan_pwm);
987EEEPC_CREATE_SENSOR_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
988 eeepc_get_fan_ctrl, eeepc_set_fan_ctrl);
989
04dcd84b
CC
990static ssize_t
991show_name(struct device *dev, struct device_attribute *attr, char *buf)
992{
993 return sprintf(buf, "eeepc\n");
994}
995static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0);
996
e1faa9da 997static struct attribute *hwmon_attributes[] = {
04dcd84b 998 &sensor_dev_attr_pwm1.dev_attr.attr,
e1faa9da
CC
999 &sensor_dev_attr_fan1_input.dev_attr.attr,
1000 &sensor_dev_attr_pwm1_enable.dev_attr.attr,
04dcd84b 1001 &sensor_dev_attr_name.dev_attr.attr,
e1faa9da
CC
1002 NULL
1003};
1004
1005static struct attribute_group hwmon_attribute_group = {
1006 .attrs = hwmon_attributes
1007};
1008
e59f8796
EC
1009/*
1010 * exit/init
1011 */
a5fa429b
CC
1012static void eeepc_backlight_exit(void)
1013{
1014 if (eeepc_backlight_device)
1015 backlight_device_unregister(eeepc_backlight_device);
a9df80c5
CC
1016 eeepc_backlight_device = NULL;
1017}
1018
1019static void eeepc_rfkill_exit(void)
1020{
7de39389
CC
1021 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6");
1022 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7");
1023 if (ehotk->wlan_rfkill)
1024 rfkill_unregister(ehotk->wlan_rfkill);
1025 if (ehotk->bluetooth_rfkill)
1026 rfkill_unregister(ehotk->bluetooth_rfkill);
3cd530b5
CC
1027 if (ehotk->wwan3g_rfkill)
1028 rfkill_unregister(ehotk->wwan3g_rfkill);
7de39389
CC
1029 if (ehotk->hotplug_slot)
1030 pci_hp_deregister(ehotk->hotplug_slot);
a9df80c5
CC
1031}
1032
1033static void eeepc_input_exit(void)
1034{
1035 if (ehotk->inputdev)
1036 input_unregister_device(ehotk->inputdev);
a5fa429b
CC
1037}
1038
e1faa9da
CC
1039static void eeepc_hwmon_exit(void)
1040{
1041 struct device *hwmon;
1042
1043 hwmon = eeepc_hwmon_device;
1044 if (!hwmon)
1045 return ;
e1faa9da
CC
1046 sysfs_remove_group(&hwmon->kobj,
1047 &hwmon_attribute_group);
f1441318 1048 hwmon_device_unregister(hwmon);
e1faa9da
CC
1049 eeepc_hwmon_device = NULL;
1050}
1051
e59f8796
EC
1052static void __exit eeepc_laptop_exit(void)
1053{
a5fa429b 1054 eeepc_backlight_exit();
a9df80c5
CC
1055 eeepc_rfkill_exit();
1056 eeepc_input_exit();
e1faa9da 1057 eeepc_hwmon_exit();
e59f8796
EC
1058 acpi_bus_unregister_driver(&eeepc_hotk_driver);
1059 sysfs_remove_group(&platform_device->dev.kobj,
1060 &platform_attribute_group);
1061 platform_device_unregister(platform_device);
1062 platform_driver_unregister(&platform_driver);
1063}
1064
7de39389
CC
1065static int eeepc_new_rfkill(struct rfkill **rfkill,
1066 const char *name, struct device *dev,
1067 enum rfkill_type type, int cm)
1068{
1069 int result;
1070
f36509e7
CC
1071 result = get_acpi(cm);
1072 if (result < 0)
1073 return result;
7de39389
CC
1074
1075 *rfkill = rfkill_alloc(name, dev, type,
1076 &eeepc_rfkill_ops, (void *)(unsigned long)cm);
1077
1078 if (!*rfkill)
1079 return -EINVAL;
1080
1081 rfkill_init_sw_state(*rfkill, get_acpi(cm) != 1);
1082 result = rfkill_register(*rfkill);
1083 if (result) {
1084 rfkill_destroy(*rfkill);
1085 *rfkill = NULL;
1086 return result;
1087 }
1088 return 0;
1089}
1090
1091
1092static int eeepc_rfkill_init(struct device *dev)
1093{
1094 int result = 0;
1095
1096 eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6");
1097 eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7");
1098
1099 result = eeepc_new_rfkill(&ehotk->wlan_rfkill,
1100 "eeepc-wlan", dev,
1101 RFKILL_TYPE_WLAN, CM_ASL_WLAN);
1102
1103 if (result && result != -ENODEV)
1104 goto exit;
1105
1106 result = eeepc_new_rfkill(&ehotk->bluetooth_rfkill,
1107 "eeepc-bluetooth", dev,
1108 RFKILL_TYPE_BLUETOOTH, CM_ASL_BLUETOOTH);
1109
1110 if (result && result != -ENODEV)
1111 goto exit;
1112
3cd530b5
CC
1113 result = eeepc_new_rfkill(&ehotk->wwan3g_rfkill,
1114 "eeepc-wwan3g", dev,
1115 RFKILL_TYPE_WWAN, CM_ASL_3G);
1116
1117 if (result && result != -ENODEV)
1118 goto exit;
1119
7de39389
CC
1120 result = eeepc_setup_pci_hotplug();
1121 /*
1122 * If we get -EBUSY then something else is handling the PCI hotplug -
1123 * don't fail in this case
1124 */
1125 if (result == -EBUSY)
1126 result = 0;
1127
1128exit:
1129 if (result && result != -ENODEV)
1130 eeepc_rfkill_exit();
1131 return result;
1132}
1133
a5fa429b
CC
1134static int eeepc_backlight_init(struct device *dev)
1135{
1136 struct backlight_device *bd;
1137
1138 bd = backlight_device_register(EEEPC_HOTK_FILE, dev,
1139 NULL, &eeepcbl_ops);
1140 if (IS_ERR(bd)) {
19b53289 1141 pr_err("Could not register eeepc backlight device\n");
a5fa429b
CC
1142 eeepc_backlight_device = NULL;
1143 return PTR_ERR(bd);
1144 }
1145 eeepc_backlight_device = bd;
1146 bd->props.max_brightness = 15;
1147 bd->props.brightness = read_brightness(NULL);
1148 bd->props.power = FB_BLANK_UNBLANK;
1149 backlight_update_status(bd);
1150 return 0;
1151}
1152
e1faa9da
CC
1153static int eeepc_hwmon_init(struct device *dev)
1154{
1155 struct device *hwmon;
1156 int result;
1157
1158 hwmon = hwmon_device_register(dev);
1159 if (IS_ERR(hwmon)) {
19b53289 1160 pr_err("Could not register eeepc hwmon device\n");
e1faa9da
CC
1161 eeepc_hwmon_device = NULL;
1162 return PTR_ERR(hwmon);
1163 }
1164 eeepc_hwmon_device = hwmon;
1165 result = sysfs_create_group(&hwmon->kobj,
1166 &hwmon_attribute_group);
1167 if (result)
1168 eeepc_hwmon_exit();
1169 return result;
1170}
1171
e59f8796
EC
1172static int __init eeepc_laptop_init(void)
1173{
1174 struct device *dev;
1175 int result;
1176
1177 if (acpi_disabled)
1178 return -ENODEV;
1179 result = acpi_bus_register_driver(&eeepc_hotk_driver);
1180 if (result < 0)
1181 return result;
1182 if (!ehotk) {
1183 acpi_bus_unregister_driver(&eeepc_hotk_driver);
1184 return -ENODEV;
1185 }
cede2cb6
PE
1186
1187 eeepc_enable_camera();
1188
e59f8796
EC
1189 /* Register platform stuff */
1190 result = platform_driver_register(&platform_driver);
1191 if (result)
1192 goto fail_platform_driver;
1193 platform_device = platform_device_alloc(EEEPC_HOTK_FILE, -1);
1194 if (!platform_device) {
1195 result = -ENOMEM;
1196 goto fail_platform_device1;
1197 }
1198 result = platform_device_add(platform_device);
1199 if (result)
1200 goto fail_platform_device2;
1201 result = sysfs_create_group(&platform_device->dev.kobj,
1202 &platform_attribute_group);
1203 if (result)
1204 goto fail_sysfs;
7de39389 1205
1ddec2f9
CC
1206 dev = &platform_device->dev;
1207
1208 if (!acpi_video_backlight_support()) {
1209 result = eeepc_backlight_init(dev);
1210 if (result)
1211 goto fail_backlight;
1212 } else
1213 pr_info("Backlight controlled by ACPI video "
1214 "driver\n");
1215
1216 result = eeepc_hwmon_init(dev);
1217 if (result)
1218 goto fail_hwmon;
1219
7de39389
CC
1220 result = eeepc_rfkill_init(dev);
1221 if (result)
1222 goto fail_rfkill;
1223
e59f8796 1224 return 0;
7de39389 1225fail_rfkill:
1ddec2f9
CC
1226 eeepc_hwmon_exit();
1227fail_hwmon:
1228 eeepc_backlight_exit();
1229fail_backlight:
7de39389
CC
1230 sysfs_remove_group(&platform_device->dev.kobj,
1231 &platform_attribute_group);
e59f8796
EC
1232fail_sysfs:
1233 platform_device_del(platform_device);
1234fail_platform_device2:
1235 platform_device_put(platform_device);
1236fail_platform_device1:
1237 platform_driver_unregister(&platform_driver);
1238fail_platform_driver:
a9df80c5 1239 eeepc_input_exit();
e59f8796
EC
1240 return result;
1241}
1242
1243module_init(eeepc_laptop_init);
1244module_exit(eeepc_laptop_exit);
This page took 0.191015 seconds and 5 git commands to generate.