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