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