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