eeepc-laptop.c: use pr_fmt and pr_<level>
[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;
142 struct rfkill *eeepc_wlan_rfkill;
143 struct rfkill *eeepc_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
19d337df 666 rfkill_set_sw_state(ehotk->eeepc_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
fbc97e4c
AJ
831 eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6");
832 eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7");
833
a195dcdc 834 if (get_acpi(CM_ASL_WLAN) != -1) {
19d337df
JB
835 ehotk->eeepc_wlan_rfkill = rfkill_alloc("eeepc-wlan",
836 &device->dev,
837 RFKILL_TYPE_WLAN,
838 &eeepc_rfkill_ops,
839 (void *)CM_ASL_WLAN);
a195dcdc
MG
840
841 if (!ehotk->eeepc_wlan_rfkill)
c9ddf8fe 842 goto wlan_fail;
a195dcdc 843
06d5caf4
AJ
844 rfkill_init_sw_state(ehotk->eeepc_wlan_rfkill,
845 get_acpi(CM_ASL_WLAN) != 1);
c9ddf8fe
MG
846 result = rfkill_register(ehotk->eeepc_wlan_rfkill);
847 if (result)
848 goto wlan_fail;
a195dcdc
MG
849 }
850
851 if (get_acpi(CM_ASL_BLUETOOTH) != -1) {
852 ehotk->eeepc_bluetooth_rfkill =
19d337df
JB
853 rfkill_alloc("eeepc-bluetooth",
854 &device->dev,
855 RFKILL_TYPE_BLUETOOTH,
856 &eeepc_rfkill_ops,
857 (void *)CM_ASL_BLUETOOTH);
a195dcdc
MG
858
859 if (!ehotk->eeepc_bluetooth_rfkill)
c9ddf8fe 860 goto bluetooth_fail;
a195dcdc 861
06d5caf4
AJ
862 rfkill_init_sw_state(ehotk->eeepc_bluetooth_rfkill,
863 get_acpi(CM_ASL_BLUETOOTH) != 1);
c9ddf8fe
MG
864 result = rfkill_register(ehotk->eeepc_bluetooth_rfkill);
865 if (result)
866 goto bluetooth_fail;
e59f8796 867 }
5740294c 868
2b121bc2
CC
869 result = eeepc_setup_pci_hotplug();
870 /*
871 * If we get -EBUSY then something else is handling the PCI hotplug -
872 * don't fail in this case
873 */
874 if (result == -EBUSY)
875 return 0;
876 else if (result)
877 goto pci_fail;
878
c9ddf8fe
MG
879 return 0;
880
2b121bc2
CC
881 pci_fail:
882 if (ehotk->eeepc_bluetooth_rfkill)
883 rfkill_unregister(ehotk->eeepc_bluetooth_rfkill);
c9ddf8fe 884 bluetooth_fail:
19d337df 885 rfkill_destroy(ehotk->eeepc_bluetooth_rfkill);
c9ddf8fe 886 rfkill_unregister(ehotk->eeepc_wlan_rfkill);
c9ddf8fe 887 wlan_fail:
19d337df 888 rfkill_destroy(ehotk->eeepc_wlan_rfkill);
bd32005e
CC
889 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6");
890 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7");
c9ddf8fe
MG
891 ehotk_fail:
892 kfree(ehotk);
893 ehotk = NULL;
894
e59f8796
EC
895 return result;
896}
897
898static int eeepc_hotk_remove(struct acpi_device *device, int type)
899{
e59f8796
EC
900 if (!device || !acpi_driver_data(device))
901 return -EINVAL;
5740294c
MG
902
903 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6");
904 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7");
2b121bc2
CC
905 if (ehotk->hotplug_slot)
906 pci_hp_deregister(ehotk->hotplug_slot);
5740294c 907
e59f8796
EC
908 kfree(ehotk);
909 return 0;
910}
911
96e9cfeb
AJ
912static int eeepc_hotk_resume(struct acpi_device *device)
913{
914 if (ehotk->eeepc_wlan_rfkill) {
915 bool wlan;
916
917 /* Workaround - it seems that _PTS disables the wireless
918 without notification or changing the value read by WLAN.
919 Normally this is fine because the correct value is restored
920 from the non-volatile storage on resume, but we need to do
921 it ourself if case suspend is aborted, or we lose wireless.
922 */
923 wlan = get_acpi(CM_ASL_WLAN);
924 set_acpi(CM_ASL_WLAN, wlan);
925
926 rfkill_set_sw_state(ehotk->eeepc_wlan_rfkill,
927 wlan != 1);
928
929 eeepc_rfkill_hotplug();
930 }
931
932 if (ehotk->eeepc_bluetooth_rfkill)
933 rfkill_set_sw_state(ehotk->eeepc_bluetooth_rfkill,
934 get_acpi(CM_ASL_BLUETOOTH) != 1);
935
936 return 0;
937}
938
e1faa9da
CC
939/*
940 * Hwmon
941 */
942static int eeepc_get_fan_pwm(void)
943{
944 int value = 0;
945
946 read_acpi_int(NULL, EEEPC_EC_FAN_PWM, &value);
04dcd84b 947 value = value * 255 / 100;
e1faa9da
CC
948 return (value);
949}
950
951static void eeepc_set_fan_pwm(int value)
952{
04dcd84b
CC
953 value = SENSORS_LIMIT(value, 0, 255);
954 value = value * 100 / 255;
e1faa9da
CC
955 ec_write(EEEPC_EC_SC02, value);
956}
957
958static int eeepc_get_fan_rpm(void)
959{
960 int high = 0;
961 int low = 0;
962
963 read_acpi_int(NULL, EEEPC_EC_FAN_HRPM, &high);
964 read_acpi_int(NULL, EEEPC_EC_FAN_LRPM, &low);
965 return (high << 8 | low);
966}
967
968static int eeepc_get_fan_ctrl(void)
969{
970 int value = 0;
971
972 read_acpi_int(NULL, EEEPC_EC_FAN_CTRL, &value);
973 return ((value & 0x02 ? 1 : 0));
974}
975
976static void eeepc_set_fan_ctrl(int manual)
977{
978 int value = 0;
979
980 read_acpi_int(NULL, EEEPC_EC_FAN_CTRL, &value);
981 if (manual)
982 value |= 0x02;
983 else
984 value &= ~0x02;
985 ec_write(EEEPC_EC_SFB3, value);
986}
987
988static ssize_t store_sys_hwmon(void (*set)(int), const char *buf, size_t count)
989{
990 int rv, value;
991
992 rv = parse_arg(buf, count, &value);
993 if (rv > 0)
994 set(value);
995 return rv;
996}
997
998static ssize_t show_sys_hwmon(int (*get)(void), char *buf)
999{
1000 return sprintf(buf, "%d\n", get());
1001}
1002
1003#define EEEPC_CREATE_SENSOR_ATTR(_name, _mode, _set, _get) \
1004 static ssize_t show_##_name(struct device *dev, \
1005 struct device_attribute *attr, \
1006 char *buf) \
1007 { \
1008 return show_sys_hwmon(_set, buf); \
1009 } \
1010 static ssize_t store_##_name(struct device *dev, \
1011 struct device_attribute *attr, \
1012 const char *buf, size_t count) \
1013 { \
1014 return store_sys_hwmon(_get, buf, count); \
1015 } \
1016 static SENSOR_DEVICE_ATTR(_name, _mode, show_##_name, store_##_name, 0);
1017
1018EEEPC_CREATE_SENSOR_ATTR(fan1_input, S_IRUGO, eeepc_get_fan_rpm, NULL);
04dcd84b 1019EEEPC_CREATE_SENSOR_ATTR(pwm1, S_IRUGO | S_IWUSR,
e1faa9da
CC
1020 eeepc_get_fan_pwm, eeepc_set_fan_pwm);
1021EEEPC_CREATE_SENSOR_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
1022 eeepc_get_fan_ctrl, eeepc_set_fan_ctrl);
1023
04dcd84b
CC
1024static ssize_t
1025show_name(struct device *dev, struct device_attribute *attr, char *buf)
1026{
1027 return sprintf(buf, "eeepc\n");
1028}
1029static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0);
1030
e1faa9da 1031static struct attribute *hwmon_attributes[] = {
04dcd84b 1032 &sensor_dev_attr_pwm1.dev_attr.attr,
e1faa9da
CC
1033 &sensor_dev_attr_fan1_input.dev_attr.attr,
1034 &sensor_dev_attr_pwm1_enable.dev_attr.attr,
04dcd84b 1035 &sensor_dev_attr_name.dev_attr.attr,
e1faa9da
CC
1036 NULL
1037};
1038
1039static struct attribute_group hwmon_attribute_group = {
1040 .attrs = hwmon_attributes
1041};
1042
e59f8796
EC
1043/*
1044 * exit/init
1045 */
a5fa429b
CC
1046static void eeepc_backlight_exit(void)
1047{
1048 if (eeepc_backlight_device)
1049 backlight_device_unregister(eeepc_backlight_device);
a9df80c5
CC
1050 eeepc_backlight_device = NULL;
1051}
1052
1053static void eeepc_rfkill_exit(void)
1054{
a195dcdc
MG
1055 if (ehotk->eeepc_wlan_rfkill)
1056 rfkill_unregister(ehotk->eeepc_wlan_rfkill);
1057 if (ehotk->eeepc_bluetooth_rfkill)
1058 rfkill_unregister(ehotk->eeepc_bluetooth_rfkill);
a9df80c5
CC
1059}
1060
1061static void eeepc_input_exit(void)
1062{
1063 if (ehotk->inputdev)
1064 input_unregister_device(ehotk->inputdev);
a5fa429b
CC
1065}
1066
e1faa9da
CC
1067static void eeepc_hwmon_exit(void)
1068{
1069 struct device *hwmon;
1070
1071 hwmon = eeepc_hwmon_device;
1072 if (!hwmon)
1073 return ;
e1faa9da
CC
1074 sysfs_remove_group(&hwmon->kobj,
1075 &hwmon_attribute_group);
f1441318 1076 hwmon_device_unregister(hwmon);
e1faa9da
CC
1077 eeepc_hwmon_device = NULL;
1078}
1079
e59f8796
EC
1080static void __exit eeepc_laptop_exit(void)
1081{
a5fa429b 1082 eeepc_backlight_exit();
a9df80c5
CC
1083 eeepc_rfkill_exit();
1084 eeepc_input_exit();
e1faa9da 1085 eeepc_hwmon_exit();
e59f8796
EC
1086 acpi_bus_unregister_driver(&eeepc_hotk_driver);
1087 sysfs_remove_group(&platform_device->dev.kobj,
1088 &platform_attribute_group);
1089 platform_device_unregister(platform_device);
1090 platform_driver_unregister(&platform_driver);
1091}
1092
a5fa429b
CC
1093static int eeepc_backlight_init(struct device *dev)
1094{
1095 struct backlight_device *bd;
1096
1097 bd = backlight_device_register(EEEPC_HOTK_FILE, dev,
1098 NULL, &eeepcbl_ops);
1099 if (IS_ERR(bd)) {
19b53289 1100 pr_err("Could not register eeepc backlight device\n");
a5fa429b
CC
1101 eeepc_backlight_device = NULL;
1102 return PTR_ERR(bd);
1103 }
1104 eeepc_backlight_device = bd;
1105 bd->props.max_brightness = 15;
1106 bd->props.brightness = read_brightness(NULL);
1107 bd->props.power = FB_BLANK_UNBLANK;
1108 backlight_update_status(bd);
1109 return 0;
1110}
1111
e1faa9da
CC
1112static int eeepc_hwmon_init(struct device *dev)
1113{
1114 struct device *hwmon;
1115 int result;
1116
1117 hwmon = hwmon_device_register(dev);
1118 if (IS_ERR(hwmon)) {
19b53289 1119 pr_err("Could not register eeepc hwmon device\n");
e1faa9da
CC
1120 eeepc_hwmon_device = NULL;
1121 return PTR_ERR(hwmon);
1122 }
1123 eeepc_hwmon_device = hwmon;
1124 result = sysfs_create_group(&hwmon->kobj,
1125 &hwmon_attribute_group);
1126 if (result)
1127 eeepc_hwmon_exit();
1128 return result;
1129}
1130
e59f8796
EC
1131static int __init eeepc_laptop_init(void)
1132{
1133 struct device *dev;
1134 int result;
1135
1136 if (acpi_disabled)
1137 return -ENODEV;
1138 result = acpi_bus_register_driver(&eeepc_hotk_driver);
1139 if (result < 0)
1140 return result;
1141 if (!ehotk) {
1142 acpi_bus_unregister_driver(&eeepc_hotk_driver);
1143 return -ENODEV;
1144 }
1145 dev = acpi_get_physical_device(ehotk->device->handle);
a2bf8c01
TR
1146
1147 if (!acpi_video_backlight_support()) {
1148 result = eeepc_backlight_init(dev);
1149 if (result)
1150 goto fail_backlight;
1151 } else
19b53289 1152 pr_info("Backlight controlled by ACPI video driver\n");
a2bf8c01 1153
e1faa9da
CC
1154 result = eeepc_hwmon_init(dev);
1155 if (result)
1156 goto fail_hwmon;
cede2cb6
PE
1157
1158 eeepc_enable_camera();
1159
e59f8796
EC
1160 /* Register platform stuff */
1161 result = platform_driver_register(&platform_driver);
1162 if (result)
1163 goto fail_platform_driver;
1164 platform_device = platform_device_alloc(EEEPC_HOTK_FILE, -1);
1165 if (!platform_device) {
1166 result = -ENOMEM;
1167 goto fail_platform_device1;
1168 }
1169 result = platform_device_add(platform_device);
1170 if (result)
1171 goto fail_platform_device2;
1172 result = sysfs_create_group(&platform_device->dev.kobj,
1173 &platform_attribute_group);
1174 if (result)
1175 goto fail_sysfs;
1176 return 0;
1177fail_sysfs:
1178 platform_device_del(platform_device);
1179fail_platform_device2:
1180 platform_device_put(platform_device);
1181fail_platform_device1:
1182 platform_driver_unregister(&platform_driver);
1183fail_platform_driver:
e1faa9da
CC
1184 eeepc_hwmon_exit();
1185fail_hwmon:
a5fa429b
CC
1186 eeepc_backlight_exit();
1187fail_backlight:
a9df80c5
CC
1188 eeepc_input_exit();
1189 eeepc_rfkill_exit();
e59f8796
EC
1190 return result;
1191}
1192
1193module_init(eeepc_laptop_init);
1194module_exit(eeepc_laptop_exit);
This page took 0.187374 seconds and 5 git commands to generate.