]> git.karo-electronics.de Git - mv-sheeva.git/blob - drivers/platform/x86/asus-wmi.c
asus-wmi: add some common device ids and method ids
[mv-sheeva.git] / drivers / platform / x86 / asus-wmi.c
1 /*
2  * Asus PC WMI hotkey driver
3  *
4  * Copyright(C) 2010 Intel Corporation.
5  * Copyright(C) 2010-2011 Corentin Chary <corentin.chary@gmail.com>
6  *
7  * Portions based on wistron_btns.c:
8  * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz>
9  * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org>
10  * Copyright (C) 2005 Dmitry Torokhov <dtor@mail.ru>
11  *
12  *  This program is free software; you can redistribute it and/or modify
13  *  it under the terms of the GNU General Public License as published by
14  *  the Free Software Foundation; either version 2 of the License, or
15  *  (at your option) any later version.
16  *
17  *  This program is distributed in the hope that it will be useful,
18  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  *  GNU General Public License for more details.
21  *
22  *  You should have received a copy of the GNU General Public License
23  *  along with this program; if not, write to the Free Software
24  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25  */
26
27 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
28
29 #include <linux/kernel.h>
30 #include <linux/module.h>
31 #include <linux/init.h>
32 #include <linux/types.h>
33 #include <linux/slab.h>
34 #include <linux/input.h>
35 #include <linux/input/sparse-keymap.h>
36 #include <linux/fb.h>
37 #include <linux/backlight.h>
38 #include <linux/leds.h>
39 #include <linux/rfkill.h>
40 #include <linux/pci.h>
41 #include <linux/pci_hotplug.h>
42 #include <linux/debugfs.h>
43 #include <linux/seq_file.h>
44 #include <linux/platform_device.h>
45 #include <acpi/acpi_bus.h>
46 #include <acpi/acpi_drivers.h>
47
48 #include "asus-wmi.h"
49
50 MODULE_AUTHOR("Corentin Chary <corentincj@iksaif.net>, "
51               "Yong Wang <yong.y.wang@intel.com>");
52 MODULE_DESCRIPTION("Asus Generic WMI Driver");
53 MODULE_LICENSE("GPL");
54
55 #define to_platform_driver(drv)                                 \
56         (container_of((drv), struct platform_driver, driver))
57
58 #define to_asus_wmi_driver(pdrv)                                        \
59         (container_of((pdrv), struct asus_wmi_driver, platform_driver))
60
61 #define ASUS_WMI_MGMT_GUID      "97845ED0-4E6D-11DE-8A39-0800200C9A66"
62
63 #define NOTIFY_BRNUP_MIN                0x11
64 #define NOTIFY_BRNUP_MAX                0x1f
65 #define NOTIFY_BRNDOWN_MIN              0x20
66 #define NOTIFY_BRNDOWN_MAX              0x2e
67
68 /* WMI Methods */
69 #define ASUS_WMI_METHODID_SPEC          0x43455053 /* BIOS SPECification */
70 #define ASUS_WMI_METHODID_SFBD          0x44424653 /* Set First Boot Device */
71 #define ASUS_WMI_METHODID_GLCD          0x44434C47 /* Get LCD status */
72 #define ASUS_WMI_METHODID_GPID          0x44495047 /* Get Panel ID?? (Resol) */
73 #define ASUS_WMI_METHODID_QMOD          0x444F4D51 /* Quiet MODe */
74 #define ASUS_WMI_METHODID_SPLV          0x4C425053 /* Set Panel Light Value */
75 #define ASUS_WMI_METHODID_SFUN          0x4E554653 /* FUNCtionalities */
76 #define ASUS_WMI_METHODID_SDSP          0x50534453 /* Set DiSPlay output */
77 #define ASUS_WMI_METHODID_GDSP          0x50534447 /* Get DiSPlay output */
78 #define ASUS_WMI_METHODID_DEVP          0x50564544 /* DEVice Policy */
79 #define ASUS_WMI_METHODID_OSVR          0x5256534F /* OS VeRsion */
80 #define ASUS_WMI_METHODID_DSTS          0x53544344 /* Device STatuS */
81 #define ASUS_WMI_METHODID_DSTS2         0x53545344 /* Device STatuS #2*/
82 #define ASUS_WMI_METHODID_BSTS          0x53545342 /* Bios STatuS ? */
83 #define ASUS_WMI_METHODID_DEVS          0x53564544 /* DEVice Set */
84 #define ASUS_WMI_METHODID_CFVS          0x53564643 /* CPU Frequency Volt Set */
85 #define ASUS_WMI_METHODID_KBFT          0x5446424B /* KeyBoard FilTer */
86 #define ASUS_WMI_METHODID_INIT          0x54494E49 /* INITialize */
87 #define ASUS_WMI_METHODID_HKEY          0x59454B48 /* Hot KEY ?? */
88
89 #define ASUS_WMI_UNSUPPORTED_METHOD     0xFFFFFFFE
90
91 /* Wireless */
92 #define ASUS_WMI_DEVID_HW_SWITCH        0x00010001
93 #define ASUS_WMI_DEVID_WIRELESS_LED     0x00010002
94 #define ASUS_WMI_DEVID_WLAN             0x00010011
95 #define ASUS_WMI_DEVID_BLUETOOTH        0x00010013
96 #define ASUS_WMI_DEVID_GPS              0x00010015
97 #define ASUS_WMI_DEVID_WIMAX            0x00010017
98 #define ASUS_WMI_DEVID_WWAN3G           0x00010019
99 #define ASUS_WMI_DEVID_UWB              0x00010021
100
101 /* Leds */
102 /* 0x000200XX and 0x000400XX */
103
104 /* Backlight and Brightness */
105 #define ASUS_WMI_DEVID_BACKLIGHT        0x00050011
106 #define ASUS_WMI_DEVID_BRIGHTNESS       0x00050012
107 #define ASUS_WMI_DEVID_KBD_BACKLIGHT    0x00050021
108 #define ASUS_WMI_DEVID_LIGHT_SENSOR     0x00050022 /* ?? */
109
110 /* Misc */
111 #define ASUS_WMI_DEVID_CAMERA           0x00060013
112
113 /* Storage */
114 #define ASUS_WMI_DEVID_CARDREADER       0x00080013
115
116 /* Input */
117 #define ASUS_WMI_DEVID_TOUCHPAD         0x00100011
118 #define ASUS_WMI_DEVID_TOUCHPAD_LED     0x00100012
119
120 /* Fan, Thermal */
121 #define ASUS_WMI_DEVID_THERMAL_CTRL     0x00110011
122 #define ASUS_WMI_DEVID_FAN_CTRL         0x00110012
123
124 /* Power */
125 #define ASUS_WMI_DEVID_PROCESSOR_STATE  0x00120012
126
127 /* DSTS masks */
128 #define ASUS_WMI_DSTS_STATUS_BIT        0x00000001
129 #define ASUS_WMI_DSTS_UNKNOWN_BIT       0x00000002
130 #define ASUS_WMI_DSTS_PRESENCE_BIT      0x00010000
131 #define ASUS_WMI_DSTS_USER_BIT          0x00020000
132 #define ASUS_WMI_DSTS_BIOS_BIT          0x00040000
133 #define ASUS_WMI_DSTS_BRIGHTNESS_MASK   0x000000FF
134 #define ASUS_WMI_DSTS_MAX_BRIGTH_MASK   0x0000FF00
135
136 struct bios_args {
137         u32 arg0;
138         u32 arg1;
139 } __packed;
140
141 /*
142  * <platform>/    - debugfs root directory
143  *   dev_id      - current dev_id
144  *   ctrl_param  - current ctrl_param
145  *   method_id   - current method_id
146  *   devs        - call DEVS(dev_id, ctrl_param) and print result
147  *   dsts        - call DSTS(dev_id)  and print result
148  *   call        - call method_id(dev_id, ctrl_param) and print result
149  */
150 struct asus_wmi_debug {
151         struct dentry *root;
152         u32 method_id;
153         u32 dev_id;
154         u32 ctrl_param;
155 };
156
157 struct asus_rfkill {
158         struct asus_wmi *asus;
159         struct rfkill *rfkill;
160         u32 dev_id;
161 };
162
163 struct asus_wmi {
164         int dsts_id;
165         int spec;
166         int sfun;
167
168         struct input_dev *inputdev;
169         struct backlight_device *backlight_device;
170         struct platform_device *platform_device;
171
172         struct led_classdev tpd_led;
173         int tpd_led_wk;
174         struct workqueue_struct *led_workqueue;
175         struct work_struct tpd_led_work;
176
177         struct asus_rfkill wlan;
178         struct asus_rfkill bluetooth;
179         struct asus_rfkill wimax;
180         struct asus_rfkill wwan3g;
181
182         struct hotplug_slot *hotplug_slot;
183         struct mutex hotplug_lock;
184         struct mutex wmi_lock;
185         struct workqueue_struct *hotplug_workqueue;
186         struct work_struct hotplug_work;
187
188         struct asus_wmi_debug debug;
189
190         struct asus_wmi_driver *driver;
191 };
192
193 static int asus_wmi_input_init(struct asus_wmi *asus)
194 {
195         int err;
196
197         asus->inputdev = input_allocate_device();
198         if (!asus->inputdev)
199                 return -ENOMEM;
200
201         asus->inputdev->name = asus->driver->input_phys;
202         asus->inputdev->phys = asus->driver->input_name;
203         asus->inputdev->id.bustype = BUS_HOST;
204         asus->inputdev->dev.parent = &asus->platform_device->dev;
205
206         err = sparse_keymap_setup(asus->inputdev, asus->driver->keymap, NULL);
207         if (err)
208                 goto err_free_dev;
209
210         err = input_register_device(asus->inputdev);
211         if (err)
212                 goto err_free_keymap;
213
214         return 0;
215
216 err_free_keymap:
217         sparse_keymap_free(asus->inputdev);
218 err_free_dev:
219         input_free_device(asus->inputdev);
220         return err;
221 }
222
223 static void asus_wmi_input_exit(struct asus_wmi *asus)
224 {
225         if (asus->inputdev) {
226                 sparse_keymap_free(asus->inputdev);
227                 input_unregister_device(asus->inputdev);
228         }
229
230         asus->inputdev = NULL;
231 }
232
233 static int asus_wmi_evaluate_method(u32 method_id, u32 arg0, u32 arg1,
234                                     u32 *retval)
235 {
236         struct bios_args args = {
237                 .arg0 = arg0,
238                 .arg1 = arg1,
239         };
240         struct acpi_buffer input = { (acpi_size) sizeof(args), &args };
241         struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
242         acpi_status status;
243         union acpi_object *obj;
244         u32 tmp;
245
246         status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID, 1, method_id,
247                                      &input, &output);
248
249         if (ACPI_FAILURE(status))
250                 goto exit;
251
252         obj = (union acpi_object *)output.pointer;
253         if (obj && obj->type == ACPI_TYPE_INTEGER)
254                 tmp = (u32) obj->integer.value;
255         else
256                 tmp = 0;
257
258         if (retval)
259                 *retval = tmp;
260
261         kfree(obj);
262
263 exit:
264         if (ACPI_FAILURE(status))
265                 return -EIO;
266
267         if (tmp == ASUS_WMI_UNSUPPORTED_METHOD)
268                 return -ENODEV;
269
270         return 0;
271 }
272
273 static int asus_wmi_get_devstate(struct asus_wmi *asus, u32 dev_id, u32 *retval)
274 {
275         return asus_wmi_evaluate_method(asus->dsts_id, dev_id, 0, retval);
276 }
277
278 static int asus_wmi_set_devstate(u32 dev_id, u32 ctrl_param,
279                                  u32 *retval)
280 {
281         return asus_wmi_evaluate_method(ASUS_WMI_METHODID_DEVS, dev_id,
282                                         ctrl_param, retval);
283 }
284
285 /* Helper for special devices with magic return codes */
286 static int asus_wmi_get_devstate_bits(struct asus_wmi *asus,
287                                       u32 dev_id, u32 mask)
288 {
289         u32 retval = 0;
290         int err;
291
292         err = asus_wmi_get_devstate(asus, dev_id, &retval);
293
294         if (err < 0)
295                 return err;
296
297         if (!(retval & ASUS_WMI_DSTS_PRESENCE_BIT))
298                 return -ENODEV;
299
300         if (mask == ASUS_WMI_DSTS_STATUS_BIT) {
301                 if (retval & ASUS_WMI_DSTS_UNKNOWN_BIT)
302                         return -ENODEV;
303         }
304
305         return retval & mask;
306 }
307
308 static int asus_wmi_get_devstate_simple(struct asus_wmi *asus, u32 dev_id)
309 {
310         return asus_wmi_get_devstate_bits(asus, dev_id,
311                                           ASUS_WMI_DSTS_STATUS_BIT);
312 }
313
314 /*
315  * LEDs
316  */
317 /*
318  * These functions actually update the LED's, and are called from a
319  * workqueue. By doing this as separate work rather than when the LED
320  * subsystem asks, we avoid messing with the Asus ACPI stuff during a
321  * potentially bad time, such as a timer interrupt.
322  */
323 static void tpd_led_update(struct work_struct *work)
324 {
325         int ctrl_param;
326         struct asus_wmi *asus;
327
328         asus = container_of(work, struct asus_wmi, tpd_led_work);
329
330         ctrl_param = asus->tpd_led_wk;
331         asus_wmi_set_devstate(ASUS_WMI_DEVID_TOUCHPAD_LED, ctrl_param, NULL);
332 }
333
334 static void tpd_led_set(struct led_classdev *led_cdev,
335                         enum led_brightness value)
336 {
337         struct asus_wmi *asus;
338
339         asus = container_of(led_cdev, struct asus_wmi, tpd_led);
340
341         asus->tpd_led_wk = !!value;
342         queue_work(asus->led_workqueue, &asus->tpd_led_work);
343 }
344
345 static int read_tpd_led_state(struct asus_wmi *asus)
346 {
347         return asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_TOUCHPAD_LED);
348 }
349
350 static enum led_brightness tpd_led_get(struct led_classdev *led_cdev)
351 {
352         struct asus_wmi *asus;
353
354         asus = container_of(led_cdev, struct asus_wmi, tpd_led);
355
356         return read_tpd_led_state(asus);
357 }
358
359 static int asus_wmi_led_init(struct asus_wmi *asus)
360 {
361         int rv;
362
363         if (read_tpd_led_state(asus) < 0)
364                 return 0;
365
366         asus->led_workqueue = create_singlethread_workqueue("led_workqueue");
367         if (!asus->led_workqueue)
368                 return -ENOMEM;
369         INIT_WORK(&asus->tpd_led_work, tpd_led_update);
370
371         asus->tpd_led.name = "asus::touchpad";
372         asus->tpd_led.brightness_set = tpd_led_set;
373         asus->tpd_led.brightness_get = tpd_led_get;
374         asus->tpd_led.max_brightness = 1;
375
376         rv = led_classdev_register(&asus->platform_device->dev, &asus->tpd_led);
377         if (rv) {
378                 destroy_workqueue(asus->led_workqueue);
379                 return rv;
380         }
381
382         return 0;
383 }
384
385 static void asus_wmi_led_exit(struct asus_wmi *asus)
386 {
387         if (asus->tpd_led.dev)
388                 led_classdev_unregister(&asus->tpd_led);
389         if (asus->led_workqueue)
390                 destroy_workqueue(asus->led_workqueue);
391 }
392
393 /*
394  * PCI hotplug (for wlan rfkill)
395  */
396 static bool asus_wlan_rfkill_blocked(struct asus_wmi *asus)
397 {
398         int result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WLAN);
399
400         if (result < 0)
401                 return false;
402         return !result;
403 }
404
405 static void asus_rfkill_hotplug(struct asus_wmi *asus)
406 {
407         struct pci_dev *dev;
408         struct pci_bus *bus;
409         bool blocked;
410         bool absent;
411         u32 l;
412
413         mutex_lock(&asus->wmi_lock);
414         blocked = asus_wlan_rfkill_blocked(asus);
415         mutex_unlock(&asus->wmi_lock);
416
417         mutex_lock(&asus->hotplug_lock);
418
419         if (asus->wlan.rfkill)
420                 rfkill_set_sw_state(asus->wlan.rfkill, blocked);
421
422         if (asus->hotplug_slot) {
423                 bus = pci_find_bus(0, 1);
424                 if (!bus) {
425                         pr_warning("Unable to find PCI bus 1?\n");
426                         goto out_unlock;
427                 }
428
429                 if (pci_bus_read_config_dword(bus, 0, PCI_VENDOR_ID, &l)) {
430                         pr_err("Unable to read PCI config space?\n");
431                         goto out_unlock;
432                 }
433                 absent = (l == 0xffffffff);
434
435                 if (blocked != absent) {
436                         pr_warning("BIOS says wireless lan is %s, "
437                                    "but the pci device is %s\n",
438                                    blocked ? "blocked" : "unblocked",
439                                    absent ? "absent" : "present");
440                         pr_warning("skipped wireless hotplug as probably "
441                                    "inappropriate for this model\n");
442                         goto out_unlock;
443                 }
444
445                 if (!blocked) {
446                         dev = pci_get_slot(bus, 0);
447                         if (dev) {
448                                 /* Device already present */
449                                 pci_dev_put(dev);
450                                 goto out_unlock;
451                         }
452                         dev = pci_scan_single_device(bus, 0);
453                         if (dev) {
454                                 pci_bus_assign_resources(bus);
455                                 if (pci_bus_add_device(dev))
456                                         pr_err("Unable to hotplug wifi\n");
457                         }
458                 } else {
459                         dev = pci_get_slot(bus, 0);
460                         if (dev) {
461                                 pci_remove_bus_device(dev);
462                                 pci_dev_put(dev);
463                         }
464                 }
465         }
466
467 out_unlock:
468         mutex_unlock(&asus->hotplug_lock);
469 }
470
471 static void asus_rfkill_notify(acpi_handle handle, u32 event, void *data)
472 {
473         struct asus_wmi *asus = data;
474
475         if (event != ACPI_NOTIFY_BUS_CHECK)
476                 return;
477
478         /*
479          * We can't call directly asus_rfkill_hotplug because most
480          * of the time WMBC is still being executed and not reetrant.
481          * There is currently no way to tell ACPICA that  we want this
482          * method to be serialized, we schedule a asus_rfkill_hotplug
483          * call later, in a safer context.
484          */
485         queue_work(asus->hotplug_workqueue, &asus->hotplug_work);
486 }
487
488 static int asus_register_rfkill_notifier(struct asus_wmi *asus, char *node)
489 {
490         acpi_status status;
491         acpi_handle handle;
492
493         status = acpi_get_handle(NULL, node, &handle);
494
495         if (ACPI_SUCCESS(status)) {
496                 status = acpi_install_notify_handler(handle,
497                                                      ACPI_SYSTEM_NOTIFY,
498                                                      asus_rfkill_notify, asus);
499                 if (ACPI_FAILURE(status))
500                         pr_warning("Failed to register notify on %s\n", node);
501         } else
502                 return -ENODEV;
503
504         return 0;
505 }
506
507 static void asus_unregister_rfkill_notifier(struct asus_wmi *asus, char *node)
508 {
509         acpi_status status = AE_OK;
510         acpi_handle handle;
511
512         status = acpi_get_handle(NULL, node, &handle);
513
514         if (ACPI_SUCCESS(status)) {
515                 status = acpi_remove_notify_handler(handle,
516                                                     ACPI_SYSTEM_NOTIFY,
517                                                     asus_rfkill_notify);
518                 if (ACPI_FAILURE(status))
519                         pr_err("Error removing rfkill notify handler %s\n",
520                                node);
521         }
522 }
523
524 static int asus_get_adapter_status(struct hotplug_slot *hotplug_slot,
525                                    u8 *value)
526 {
527         struct asus_wmi *asus = hotplug_slot->private;
528         int result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WLAN);
529
530         if (result < 0)
531                 return result;
532
533         *value = !!result;
534         return 0;
535 }
536
537 static void asus_cleanup_pci_hotplug(struct hotplug_slot *hotplug_slot)
538 {
539         kfree(hotplug_slot->info);
540         kfree(hotplug_slot);
541 }
542
543 static struct hotplug_slot_ops asus_hotplug_slot_ops = {
544         .owner = THIS_MODULE,
545         .get_adapter_status = asus_get_adapter_status,
546         .get_power_status = asus_get_adapter_status,
547 };
548
549 static void asus_hotplug_work(struct work_struct *work)
550 {
551         struct asus_wmi *asus;
552
553         asus = container_of(work, struct asus_wmi, hotplug_work);
554         asus_rfkill_hotplug(asus);
555 }
556
557 static int asus_setup_pci_hotplug(struct asus_wmi *asus)
558 {
559         int ret = -ENOMEM;
560         struct pci_bus *bus = pci_find_bus(0, 1);
561
562         if (!bus) {
563                 pr_err("Unable to find wifi PCI bus\n");
564                 return -ENODEV;
565         }
566
567         asus->hotplug_workqueue =
568             create_singlethread_workqueue("hotplug_workqueue");
569         if (!asus->hotplug_workqueue)
570                 goto error_workqueue;
571
572         INIT_WORK(&asus->hotplug_work, asus_hotplug_work);
573
574         asus->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
575         if (!asus->hotplug_slot)
576                 goto error_slot;
577
578         asus->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info),
579                                            GFP_KERNEL);
580         if (!asus->hotplug_slot->info)
581                 goto error_info;
582
583         asus->hotplug_slot->private = asus;
584         asus->hotplug_slot->release = &asus_cleanup_pci_hotplug;
585         asus->hotplug_slot->ops = &asus_hotplug_slot_ops;
586         asus_get_adapter_status(asus->hotplug_slot,
587                                 &asus->hotplug_slot->info->adapter_status);
588
589         ret = pci_hp_register(asus->hotplug_slot, bus, 0, "asus-wifi");
590         if (ret) {
591                 pr_err("Unable to register hotplug slot - %d\n", ret);
592                 goto error_register;
593         }
594
595         return 0;
596
597 error_register:
598         kfree(asus->hotplug_slot->info);
599 error_info:
600         kfree(asus->hotplug_slot);
601         asus->hotplug_slot = NULL;
602 error_slot:
603         destroy_workqueue(asus->hotplug_workqueue);
604 error_workqueue:
605         return ret;
606 }
607
608 /*
609  * Rfkill devices
610  */
611 static int asus_rfkill_set(void *data, bool blocked)
612 {
613         struct asus_rfkill *priv = data;
614         u32 ctrl_param = !blocked;
615
616         return asus_wmi_set_devstate(priv->dev_id, ctrl_param, NULL);
617 }
618
619 static void asus_rfkill_query(struct rfkill *rfkill, void *data)
620 {
621         struct asus_rfkill *priv = data;
622         int result;
623
624         result = asus_wmi_get_devstate_simple(priv->asus, priv->dev_id);
625
626         if (result < 0)
627                 return;
628
629         rfkill_set_sw_state(priv->rfkill, !result);
630 }
631
632 static int asus_rfkill_wlan_set(void *data, bool blocked)
633 {
634         struct asus_rfkill *priv = data;
635         struct asus_wmi *asus = priv->asus;
636         int ret;
637
638         /*
639          * This handler is enabled only if hotplug is enabled.
640          * In this case, the asus_wmi_set_devstate() will
641          * trigger a wmi notification and we need to wait
642          * this call to finish before being able to call
643          * any wmi method
644          */
645         mutex_lock(&asus->wmi_lock);
646         ret = asus_rfkill_set(data, blocked);
647         mutex_unlock(&asus->wmi_lock);
648         return ret;
649 }
650
651 static const struct rfkill_ops asus_rfkill_wlan_ops = {
652         .set_block = asus_rfkill_wlan_set,
653         .query = asus_rfkill_query,
654 };
655
656 static const struct rfkill_ops asus_rfkill_ops = {
657         .set_block = asus_rfkill_set,
658         .query = asus_rfkill_query,
659 };
660
661 static int asus_new_rfkill(struct asus_wmi *asus,
662                            struct asus_rfkill *arfkill,
663                            const char *name, enum rfkill_type type, int dev_id)
664 {
665         int result = asus_wmi_get_devstate_simple(asus, dev_id);
666         struct rfkill **rfkill = &arfkill->rfkill;
667
668         if (result < 0)
669                 return result;
670
671         arfkill->dev_id = dev_id;
672         arfkill->asus = asus;
673
674         if (dev_id == ASUS_WMI_DEVID_WLAN && asus->driver->hotplug_wireless)
675                 *rfkill = rfkill_alloc(name, &asus->platform_device->dev, type,
676                                        &asus_rfkill_wlan_ops, arfkill);
677         else
678                 *rfkill = rfkill_alloc(name, &asus->platform_device->dev, type,
679                                        &asus_rfkill_ops, arfkill);
680
681         if (!*rfkill)
682                 return -EINVAL;
683
684         rfkill_init_sw_state(*rfkill, !result);
685         result = rfkill_register(*rfkill);
686         if (result) {
687                 rfkill_destroy(*rfkill);
688                 *rfkill = NULL;
689                 return result;
690         }
691         return 0;
692 }
693
694 static void asus_wmi_rfkill_exit(struct asus_wmi *asus)
695 {
696         asus_unregister_rfkill_notifier(asus, "\\_SB.PCI0.P0P5");
697         asus_unregister_rfkill_notifier(asus, "\\_SB.PCI0.P0P6");
698         asus_unregister_rfkill_notifier(asus, "\\_SB.PCI0.P0P7");
699         if (asus->wlan.rfkill) {
700                 rfkill_unregister(asus->wlan.rfkill);
701                 rfkill_destroy(asus->wlan.rfkill);
702                 asus->wlan.rfkill = NULL;
703         }
704         /*
705          * Refresh pci hotplug in case the rfkill state was changed after
706          * asus_unregister_rfkill_notifier()
707          */
708         asus_rfkill_hotplug(asus);
709         if (asus->hotplug_slot)
710                 pci_hp_deregister(asus->hotplug_slot);
711         if (asus->hotplug_workqueue)
712                 destroy_workqueue(asus->hotplug_workqueue);
713
714         if (asus->bluetooth.rfkill) {
715                 rfkill_unregister(asus->bluetooth.rfkill);
716                 rfkill_destroy(asus->bluetooth.rfkill);
717                 asus->bluetooth.rfkill = NULL;
718         }
719         if (asus->wimax.rfkill) {
720                 rfkill_unregister(asus->wimax.rfkill);
721                 rfkill_destroy(asus->wimax.rfkill);
722                 asus->wimax.rfkill = NULL;
723         }
724         if (asus->wwan3g.rfkill) {
725                 rfkill_unregister(asus->wwan3g.rfkill);
726                 rfkill_destroy(asus->wwan3g.rfkill);
727                 asus->wwan3g.rfkill = NULL;
728         }
729 }
730
731 static int asus_wmi_rfkill_init(struct asus_wmi *asus)
732 {
733         int result = 0;
734
735         mutex_init(&asus->hotplug_lock);
736         mutex_init(&asus->wmi_lock);
737
738         result = asus_new_rfkill(asus, &asus->wlan, "asus-wlan",
739                                  RFKILL_TYPE_WLAN, ASUS_WMI_DEVID_WLAN);
740
741         if (result && result != -ENODEV)
742                 goto exit;
743
744         result = asus_new_rfkill(asus, &asus->bluetooth,
745                                  "asus-bluetooth", RFKILL_TYPE_BLUETOOTH,
746                                  ASUS_WMI_DEVID_BLUETOOTH);
747
748         if (result && result != -ENODEV)
749                 goto exit;
750
751         result = asus_new_rfkill(asus, &asus->wimax, "asus-wimax",
752                                  RFKILL_TYPE_WIMAX, ASUS_WMI_DEVID_WIMAX);
753
754         if (result && result != -ENODEV)
755                 goto exit;
756
757         result = asus_new_rfkill(asus, &asus->wwan3g, "asus-wwan3g",
758                                  RFKILL_TYPE_WWAN, ASUS_WMI_DEVID_WWAN3G);
759
760         if (result && result != -ENODEV)
761                 goto exit;
762
763         if (!asus->driver->hotplug_wireless)
764                 goto exit;
765
766         result = asus_setup_pci_hotplug(asus);
767         /*
768          * If we get -EBUSY then something else is handling the PCI hotplug -
769          * don't fail in this case
770          */
771         if (result == -EBUSY)
772                 result = 0;
773
774         asus_register_rfkill_notifier(asus, "\\_SB.PCI0.P0P5");
775         asus_register_rfkill_notifier(asus, "\\_SB.PCI0.P0P6");
776         asus_register_rfkill_notifier(asus, "\\_SB.PCI0.P0P7");
777         /*
778          * Refresh pci hotplug in case the rfkill state was changed during
779          * setup.
780          */
781         asus_rfkill_hotplug(asus);
782
783 exit:
784         if (result && result != -ENODEV)
785                 asus_wmi_rfkill_exit(asus);
786
787         if (result == -ENODEV)
788                 result = 0;
789
790         return result;
791 }
792
793 /*
794  * Backlight
795  */
796 static int read_backlight_power(struct asus_wmi *asus)
797 {
798         int ret = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_BACKLIGHT);
799
800         if (ret < 0)
801                 return ret;
802
803         return ret ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
804 }
805
806 static int read_brightness_max(struct asus_wmi *asus)
807 {
808         u32 retval;
809         int err;
810
811         err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_BRIGHTNESS, &retval);
812
813         if (err < 0)
814                 return err;
815
816         retval = retval & ASUS_WMI_DSTS_MAX_BRIGTH_MASK;
817         retval >>= 8;
818
819         if (!retval)
820                 return -ENODEV;
821
822         return retval;
823 }
824
825 static int read_brightness(struct backlight_device *bd)
826 {
827         struct asus_wmi *asus = bl_get_data(bd);
828         u32 retval, err;
829
830         err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_BRIGHTNESS, &retval);
831
832         if (err < 0)
833                 return err;
834
835         return retval & ASUS_WMI_DSTS_BRIGHTNESS_MASK;
836 }
837
838 static int update_bl_status(struct backlight_device *bd)
839 {
840         struct asus_wmi *asus = bl_get_data(bd);
841         u32 ctrl_param;
842         int power, err;
843
844         ctrl_param = bd->props.brightness;
845
846         err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BRIGHTNESS,
847                                     ctrl_param, NULL);
848
849         if (err < 0)
850                 return err;
851
852         power = read_backlight_power(asus);
853         if (power != -ENODEV && bd->props.power != power) {
854                 ctrl_param = !!(bd->props.power == FB_BLANK_UNBLANK);
855                 err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BACKLIGHT,
856                                             ctrl_param, NULL);
857         }
858         return err;
859 }
860
861 static const struct backlight_ops asus_wmi_bl_ops = {
862         .get_brightness = read_brightness,
863         .update_status = update_bl_status,
864 };
865
866 static int asus_wmi_backlight_notify(struct asus_wmi *asus, int code)
867 {
868         struct backlight_device *bd = asus->backlight_device;
869         int old = bd->props.brightness;
870         int new = old;
871
872         if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX)
873                 new = code - NOTIFY_BRNUP_MIN + 1;
874         else if (code >= NOTIFY_BRNDOWN_MIN && code <= NOTIFY_BRNDOWN_MAX)
875                 new = code - NOTIFY_BRNDOWN_MIN;
876
877         bd->props.brightness = new;
878         backlight_update_status(bd);
879         backlight_force_update(bd, BACKLIGHT_UPDATE_HOTKEY);
880
881         return old;
882 }
883
884 static int asus_wmi_backlight_init(struct asus_wmi *asus)
885 {
886         struct backlight_device *bd;
887         struct backlight_properties props;
888         int max;
889         int power;
890
891         max = read_brightness_max(asus);
892
893         if (max == -ENODEV)
894                 max = 0;
895         else if (max < 0)
896                 return max;
897
898         power = read_backlight_power(asus);
899
900         if (power == -ENODEV)
901                 power = FB_BLANK_UNBLANK;
902         else if (power < 0)
903                 return power;
904
905         memset(&props, 0, sizeof(struct backlight_properties));
906         props.max_brightness = max;
907         bd = backlight_device_register(asus->driver->name,
908                                        &asus->platform_device->dev, asus,
909                                        &asus_wmi_bl_ops, &props);
910         if (IS_ERR(bd)) {
911                 pr_err("Could not register backlight device\n");
912                 return PTR_ERR(bd);
913         }
914
915         asus->backlight_device = bd;
916
917         bd->props.brightness = read_brightness(bd);
918         bd->props.power = power;
919         backlight_update_status(bd);
920
921         return 0;
922 }
923
924 static void asus_wmi_backlight_exit(struct asus_wmi *asus)
925 {
926         if (asus->backlight_device)
927                 backlight_device_unregister(asus->backlight_device);
928
929         asus->backlight_device = NULL;
930 }
931
932 static void asus_wmi_notify(u32 value, void *context)
933 {
934         struct asus_wmi *asus = context;
935         struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
936         union acpi_object *obj;
937         acpi_status status;
938         int code;
939         int orig_code;
940
941         status = wmi_get_event_data(value, &response);
942         if (status != AE_OK) {
943                 pr_err("bad event status 0x%x\n", status);
944                 return;
945         }
946
947         obj = (union acpi_object *)response.pointer;
948
949         if (!obj || obj->type != ACPI_TYPE_INTEGER)
950                 goto exit;
951
952         code = obj->integer.value;
953         orig_code = code;
954
955         if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX)
956                 code = NOTIFY_BRNUP_MIN;
957         else if (code >= NOTIFY_BRNDOWN_MIN &&
958                  code <= NOTIFY_BRNDOWN_MAX)
959                 code = NOTIFY_BRNDOWN_MIN;
960
961         if (code == NOTIFY_BRNUP_MIN || code == NOTIFY_BRNDOWN_MIN) {
962                 if (!acpi_video_backlight_support())
963                         asus_wmi_backlight_notify(asus, orig_code);
964         } else if (!sparse_keymap_report_event(asus->inputdev, code, 1, true))
965                 pr_info("Unknown key %x pressed\n", code);
966
967 exit:
968         kfree(obj);
969 }
970
971 /*
972  * Sys helpers
973  */
974 static int parse_arg(const char *buf, unsigned long count, int *val)
975 {
976         if (!count)
977                 return 0;
978         if (sscanf(buf, "%i", val) != 1)
979                 return -EINVAL;
980         return count;
981 }
982
983 static ssize_t store_sys_wmi(struct asus_wmi *asus, int devid,
984                              const char *buf, size_t count)
985 {
986         u32 retval;
987         int rv, err, value;
988
989         value = asus_wmi_get_devstate_simple(asus, devid);
990         if (value == -ENODEV)   /* Check device presence */
991                 return value;
992
993         rv = parse_arg(buf, count, &value);
994         err = asus_wmi_set_devstate(devid, value, &retval);
995
996         if (err < 0)
997                 return err;
998
999         return rv;
1000 }
1001
1002 static ssize_t show_sys_wmi(struct asus_wmi *asus, int devid, char *buf)
1003 {
1004         int value = asus_wmi_get_devstate_simple(asus, devid);
1005
1006         if (value < 0)
1007                 return value;
1008
1009         return sprintf(buf, "%d\n", value);
1010 }
1011
1012 #define ASUS_WMI_CREATE_DEVICE_ATTR(_name, _mode, _cm)                  \
1013         static ssize_t show_##_name(struct device *dev,                 \
1014                                     struct device_attribute *attr,      \
1015                                     char *buf)                          \
1016         {                                                               \
1017                 struct asus_wmi *asus = dev_get_drvdata(dev);           \
1018                                                                         \
1019                 return show_sys_wmi(asus, _cm, buf);                    \
1020         }                                                               \
1021         static ssize_t store_##_name(struct device *dev,                \
1022                                      struct device_attribute *attr,     \
1023                                      const char *buf, size_t count)     \
1024         {                                                               \
1025                 struct asus_wmi *asus = dev_get_drvdata(dev);           \
1026                                                                         \
1027                 return store_sys_wmi(asus, _cm, buf, count);            \
1028         }                                                               \
1029         static struct device_attribute dev_attr_##_name = {             \
1030                 .attr = {                                               \
1031                         .name = __stringify(_name),                     \
1032                         .mode = _mode },                                \
1033                 .show   = show_##_name,                                 \
1034                 .store  = store_##_name,                                \
1035         }
1036
1037 ASUS_WMI_CREATE_DEVICE_ATTR(touchpad, 0644, ASUS_WMI_DEVID_TOUCHPAD);
1038 ASUS_WMI_CREATE_DEVICE_ATTR(camera, 0644, ASUS_WMI_DEVID_CAMERA);
1039 ASUS_WMI_CREATE_DEVICE_ATTR(cardr, 0644, ASUS_WMI_DEVID_CARDREADER);
1040
1041 static ssize_t store_cpufv(struct device *dev, struct device_attribute *attr,
1042                            const char *buf, size_t count)
1043 {
1044         int value;
1045
1046         if (!count || sscanf(buf, "%i", &value) != 1)
1047                 return -EINVAL;
1048         if (value < 0 || value > 2)
1049                 return -EINVAL;
1050
1051         return asus_wmi_evaluate_method(ASUS_WMI_METHODID_CFVS, value, 0, NULL);
1052 }
1053
1054 static DEVICE_ATTR(cpufv, S_IRUGO | S_IWUSR, NULL, store_cpufv);
1055
1056 static struct attribute *platform_attributes[] = {
1057         &dev_attr_cpufv.attr,
1058         &dev_attr_camera.attr,
1059         &dev_attr_cardr.attr,
1060         &dev_attr_touchpad.attr,
1061         NULL
1062 };
1063
1064 static mode_t asus_sysfs_is_visible(struct kobject *kobj,
1065                                     struct attribute *attr, int idx)
1066 {
1067         struct device *dev = container_of(kobj, struct device, kobj);
1068         struct platform_device *pdev = to_platform_device(dev);
1069         struct asus_wmi *asus = platform_get_drvdata(pdev);
1070         bool ok = true;
1071         int devid = -1;
1072
1073         if (attr == &dev_attr_camera.attr)
1074                 devid = ASUS_WMI_DEVID_CAMERA;
1075         else if (attr == &dev_attr_cardr.attr)
1076                 devid = ASUS_WMI_DEVID_CARDREADER;
1077         else if (attr == &dev_attr_touchpad.attr)
1078                 devid = ASUS_WMI_DEVID_TOUCHPAD;
1079
1080         if (devid != -1)
1081                 ok = !(asus_wmi_get_devstate_simple(asus, devid) < 0);
1082
1083         return ok ? attr->mode : 0;
1084 }
1085
1086 static struct attribute_group platform_attribute_group = {
1087         .is_visible = asus_sysfs_is_visible,
1088         .attrs = platform_attributes
1089 };
1090
1091 static void asus_wmi_sysfs_exit(struct platform_device *device)
1092 {
1093         sysfs_remove_group(&device->dev.kobj, &platform_attribute_group);
1094 }
1095
1096 static int asus_wmi_sysfs_init(struct platform_device *device)
1097 {
1098         return sysfs_create_group(&device->dev.kobj, &platform_attribute_group);
1099 }
1100
1101 /*
1102  * Platform device
1103  */
1104 static int __init asus_wmi_platform_init(struct asus_wmi *asus)
1105 {
1106         int rv;
1107
1108         /* INIT enable hotkeys on some models */
1109         if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_INIT, 0, 0, &rv))
1110                 pr_info("Initialization: %#x", rv);
1111
1112         /* We don't know yet what to do with this version... */
1113         if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_SPEC, 0, 0x9, &rv)) {
1114                 pr_info("BIOS WMI version: %d.%d", rv >> 8, rv & 0xFF);
1115                 asus->spec = rv;
1116         }
1117
1118         /*
1119          * The SFUN method probably allows the original driver to get the list
1120          * of features supported by a given model. For now, 0x0100 or 0x0800
1121          * bit signifies that the laptop is equipped with a Wi-Fi MiniPCI card.
1122          * The significance of others is yet to be found.
1123          */
1124         if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_SFUN, 0, 0, &rv)) {
1125                 pr_info("SFUN value: %#x", rv);
1126                 asus->sfun = rv;
1127         }
1128
1129         /*
1130          * Eee PC and Notebooks seems to have different method_id for DSTS,
1131          * but it may also be related to the BIOS's SPEC.
1132          * Note, on most Eeepc, there is no way to check if a method exist
1133          * or note, while on notebooks, they returns 0xFFFFFFFE on failure,
1134          * but once again, SPEC may probably be used for that kind of things.
1135          */
1136         if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS, 0, 0, NULL))
1137                 asus->dsts_id = ASUS_WMI_METHODID_DSTS;
1138         else if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS2, 0, 0, NULL))
1139                 asus->dsts_id = ASUS_WMI_METHODID_DSTS2;
1140
1141         if (!asus->dsts_id) {
1142                 pr_err("Can't find DSTS");
1143                 return -ENODEV;
1144         }
1145
1146         return asus_wmi_sysfs_init(asus->platform_device);
1147 }
1148
1149 static void asus_wmi_platform_exit(struct asus_wmi *asus)
1150 {
1151         asus_wmi_sysfs_exit(asus->platform_device);
1152 }
1153
1154 /*
1155  * debugfs
1156  */
1157 struct asus_wmi_debugfs_node {
1158         struct asus_wmi *asus;
1159         char *name;
1160         int (*show) (struct seq_file *m, void *data);
1161 };
1162
1163 static int show_dsts(struct seq_file *m, void *data)
1164 {
1165         struct asus_wmi *asus = m->private;
1166         int err;
1167         u32 retval = -1;
1168
1169         err = asus_wmi_get_devstate(asus, asus->debug.dev_id, &retval);
1170
1171         if (err < 0)
1172                 return err;
1173
1174         seq_printf(m, "DSTS(%#x) = %#x\n", asus->debug.dev_id, retval);
1175
1176         return 0;
1177 }
1178
1179 static int show_devs(struct seq_file *m, void *data)
1180 {
1181         struct asus_wmi *asus = m->private;
1182         int err;
1183         u32 retval = -1;
1184
1185         err = asus_wmi_set_devstate(asus->debug.dev_id, asus->debug.ctrl_param,
1186                                     &retval);
1187
1188         if (err < 0)
1189                 return err;
1190
1191         seq_printf(m, "DEVS(%#x, %#x) = %#x\n", asus->debug.dev_id,
1192                    asus->debug.ctrl_param, retval);
1193
1194         return 0;
1195 }
1196
1197 static int show_call(struct seq_file *m, void *data)
1198 {
1199         struct asus_wmi *asus = m->private;
1200         struct bios_args args = {
1201                 .arg0 = asus->debug.dev_id,
1202                 .arg1 = asus->debug.ctrl_param,
1203         };
1204         struct acpi_buffer input = { (acpi_size) sizeof(args), &args };
1205         struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
1206         union acpi_object *obj;
1207         acpi_status status;
1208
1209         status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID,
1210                                      1, asus->debug.method_id,
1211                                      &input, &output);
1212
1213         if (ACPI_FAILURE(status))
1214                 return -EIO;
1215
1216         obj = (union acpi_object *)output.pointer;
1217         if (obj && obj->type == ACPI_TYPE_INTEGER)
1218                 seq_printf(m, "%#x(%#x, %#x) = %#x\n", asus->debug.method_id,
1219                            asus->debug.dev_id, asus->debug.ctrl_param,
1220                            (u32) obj->integer.value);
1221         else
1222                 seq_printf(m, "%#x(%#x, %#x) = t:%d\n", asus->debug.method_id,
1223                            asus->debug.dev_id, asus->debug.ctrl_param,
1224                            obj->type);
1225
1226         kfree(obj);
1227
1228         return 0;
1229 }
1230
1231 static struct asus_wmi_debugfs_node asus_wmi_debug_files[] = {
1232         {NULL, "devs", show_devs},
1233         {NULL, "dsts", show_dsts},
1234         {NULL, "call", show_call},
1235 };
1236
1237 static int asus_wmi_debugfs_open(struct inode *inode, struct file *file)
1238 {
1239         struct asus_wmi_debugfs_node *node = inode->i_private;
1240
1241         return single_open(file, node->show, node->asus);
1242 }
1243
1244 static const struct file_operations asus_wmi_debugfs_io_ops = {
1245         .owner = THIS_MODULE,
1246         .open = asus_wmi_debugfs_open,
1247         .read = seq_read,
1248         .llseek = seq_lseek,
1249         .release = single_release,
1250 };
1251
1252 static void asus_wmi_debugfs_exit(struct asus_wmi *asus)
1253 {
1254         debugfs_remove_recursive(asus->debug.root);
1255 }
1256
1257 static int asus_wmi_debugfs_init(struct asus_wmi *asus)
1258 {
1259         struct dentry *dent;
1260         int i;
1261
1262         asus->debug.root = debugfs_create_dir(asus->driver->name, NULL);
1263         if (!asus->debug.root) {
1264                 pr_err("failed to create debugfs directory");
1265                 goto error_debugfs;
1266         }
1267
1268         dent = debugfs_create_x32("method_id", S_IRUGO | S_IWUSR,
1269                                   asus->debug.root, &asus->debug.method_id);
1270         if (!dent)
1271                 goto error_debugfs;
1272
1273         dent = debugfs_create_x32("dev_id", S_IRUGO | S_IWUSR,
1274                                   asus->debug.root, &asus->debug.dev_id);
1275         if (!dent)
1276                 goto error_debugfs;
1277
1278         dent = debugfs_create_x32("ctrl_param", S_IRUGO | S_IWUSR,
1279                                   asus->debug.root, &asus->debug.ctrl_param);
1280         if (!dent)
1281                 goto error_debugfs;
1282
1283         for (i = 0; i < ARRAY_SIZE(asus_wmi_debug_files); i++) {
1284                 struct asus_wmi_debugfs_node *node = &asus_wmi_debug_files[i];
1285
1286                 node->asus = asus;
1287                 dent = debugfs_create_file(node->name, S_IFREG | S_IRUGO,
1288                                            asus->debug.root, node,
1289                                            &asus_wmi_debugfs_io_ops);
1290                 if (!dent) {
1291                         pr_err("failed to create debug file: %s\n", node->name);
1292                         goto error_debugfs;
1293                 }
1294         }
1295
1296         return 0;
1297
1298 error_debugfs:
1299         asus_wmi_debugfs_exit(asus);
1300         return -ENOMEM;
1301 }
1302
1303 /*
1304  * WMI Driver
1305  */
1306 static int asus_wmi_add(struct platform_device *pdev)
1307 {
1308         struct platform_driver *pdrv = to_platform_driver(pdev->dev.driver);
1309         struct asus_wmi_driver *wdrv = to_asus_wmi_driver(pdrv);
1310         struct asus_wmi *asus;
1311         acpi_status status;
1312         int err;
1313
1314         asus = kzalloc(sizeof(struct asus_wmi), GFP_KERNEL);
1315         if (!asus)
1316                 return -ENOMEM;
1317
1318         asus->driver = wdrv;
1319         asus->platform_device = pdev;
1320         wdrv->platform_device = pdev;
1321         platform_set_drvdata(asus->platform_device, asus);
1322
1323         if (wdrv->quirks)
1324                 wdrv->quirks(asus->driver);
1325
1326         err = asus_wmi_platform_init(asus);
1327         if (err)
1328                 goto fail_platform;
1329
1330         err = asus_wmi_input_init(asus);
1331         if (err)
1332                 goto fail_input;
1333
1334         err = asus_wmi_led_init(asus);
1335         if (err)
1336                 goto fail_leds;
1337
1338         err = asus_wmi_rfkill_init(asus);
1339         if (err)
1340                 goto fail_rfkill;
1341
1342         if (!acpi_video_backlight_support()) {
1343                 err = asus_wmi_backlight_init(asus);
1344                 if (err && err != -ENODEV)
1345                         goto fail_backlight;
1346         } else
1347                 pr_info("Backlight controlled by ACPI video driver\n");
1348
1349         status = wmi_install_notify_handler(asus->driver->event_guid,
1350                                             asus_wmi_notify, asus);
1351         if (ACPI_FAILURE(status)) {
1352                 pr_err("Unable to register notify handler - %d\n", status);
1353                 err = -ENODEV;
1354                 goto fail_wmi_handler;
1355         }
1356
1357         err = asus_wmi_debugfs_init(asus);
1358         if (err)
1359                 goto fail_debugfs;
1360
1361         return 0;
1362
1363 fail_debugfs:
1364         wmi_remove_notify_handler(asus->driver->event_guid);
1365 fail_wmi_handler:
1366         asus_wmi_backlight_exit(asus);
1367 fail_backlight:
1368         asus_wmi_rfkill_exit(asus);
1369 fail_rfkill:
1370         asus_wmi_led_exit(asus);
1371 fail_leds:
1372         asus_wmi_input_exit(asus);
1373 fail_input:
1374         asus_wmi_platform_exit(asus);
1375 fail_platform:
1376         kfree(asus);
1377         return err;
1378 }
1379
1380 static int asus_wmi_remove(struct platform_device *device)
1381 {
1382         struct asus_wmi *asus;
1383
1384         asus = platform_get_drvdata(device);
1385         wmi_remove_notify_handler(asus->driver->event_guid);
1386         asus_wmi_backlight_exit(asus);
1387         asus_wmi_input_exit(asus);
1388         asus_wmi_led_exit(asus);
1389         asus_wmi_rfkill_exit(asus);
1390         asus_wmi_debugfs_exit(asus);
1391         asus_wmi_platform_exit(asus);
1392
1393         kfree(asus);
1394         return 0;
1395 }
1396
1397 /*
1398  * Platform driver - hibernate/resume callbacks
1399  */
1400 static int asus_hotk_thaw(struct device *device)
1401 {
1402         struct asus_wmi *asus = dev_get_drvdata(device);
1403
1404         if (asus->wlan.rfkill) {
1405                 bool wlan;
1406
1407                 /*
1408                  * Work around bios bug - acpi _PTS turns off the wireless led
1409                  * during suspend.  Normally it restores it on resume, but
1410                  * we should kick it ourselves in case hibernation is aborted.
1411                  */
1412                 wlan = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WLAN);
1413                 asus_wmi_set_devstate(ASUS_WMI_DEVID_WLAN, wlan, NULL);
1414         }
1415
1416         return 0;
1417 }
1418
1419 static int asus_hotk_restore(struct device *device)
1420 {
1421         struct asus_wmi *asus = dev_get_drvdata(device);
1422         int bl;
1423
1424         /* Refresh both wlan rfkill state and pci hotplug */
1425         if (asus->wlan.rfkill)
1426                 asus_rfkill_hotplug(asus);
1427
1428         if (asus->bluetooth.rfkill) {
1429                 bl = !asus_wmi_get_devstate_simple(asus,
1430                                                    ASUS_WMI_DEVID_BLUETOOTH);
1431                 rfkill_set_sw_state(asus->bluetooth.rfkill, bl);
1432         }
1433         if (asus->wimax.rfkill) {
1434                 bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WIMAX);
1435                 rfkill_set_sw_state(asus->wimax.rfkill, bl);
1436         }
1437         if (asus->wwan3g.rfkill) {
1438                 bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WWAN3G);
1439                 rfkill_set_sw_state(asus->wwan3g.rfkill, bl);
1440         }
1441
1442         return 0;
1443 }
1444
1445 static const struct dev_pm_ops asus_pm_ops = {
1446         .thaw = asus_hotk_thaw,
1447         .restore = asus_hotk_restore,
1448 };
1449
1450 static int asus_wmi_probe(struct platform_device *pdev)
1451 {
1452         struct platform_driver *pdrv = to_platform_driver(pdev->dev.driver);
1453         struct asus_wmi_driver *wdrv = to_asus_wmi_driver(pdrv);
1454         int ret;
1455
1456         if (!wmi_has_guid(ASUS_WMI_MGMT_GUID)) {
1457                 pr_warning("Management GUID not found\n");
1458                 return -ENODEV;
1459         }
1460
1461         if (wdrv->event_guid && !wmi_has_guid(wdrv->event_guid)) {
1462                 pr_warning("Event GUID not found\n");
1463                 return -ENODEV;
1464         }
1465
1466         if (wdrv->probe) {
1467                 ret = wdrv->probe(pdev);
1468                 if (ret)
1469                         return ret;
1470         }
1471
1472         return asus_wmi_add(pdev);
1473 }
1474
1475 static bool used;
1476
1477 int asus_wmi_register_driver(struct asus_wmi_driver *driver)
1478 {
1479         struct platform_driver *platform_driver;
1480         struct platform_device *platform_device;
1481
1482         if (used)
1483                 return -EBUSY;
1484
1485         platform_driver = &driver->platform_driver;
1486         platform_driver->remove = asus_wmi_remove;
1487         platform_driver->driver.owner = driver->owner;
1488         platform_driver->driver.name = driver->name;
1489         platform_driver->driver.pm = &asus_pm_ops;
1490
1491         platform_device = platform_create_bundle(platform_driver,
1492                                                  asus_wmi_probe,
1493                                                  NULL, 0, NULL, 0);
1494         if (IS_ERR(platform_device))
1495                 return PTR_ERR(platform_device);
1496
1497         used = true;
1498         return 0;
1499 }
1500 EXPORT_SYMBOL_GPL(asus_wmi_register_driver);
1501
1502 void asus_wmi_unregister_driver(struct asus_wmi_driver *driver)
1503 {
1504         platform_device_unregister(driver->platform_device);
1505         platform_driver_unregister(&driver->platform_driver);
1506         used = false;
1507 }
1508 EXPORT_SYMBOL_GPL(asus_wmi_unregister_driver);
1509
1510 static int __init asus_wmi_init(void)
1511 {
1512         if (!wmi_has_guid(ASUS_WMI_MGMT_GUID)) {
1513                 pr_info("Asus Management GUID not found");
1514                 return -ENODEV;
1515         }
1516
1517         pr_info("ASUS WMI generic driver loaded");
1518         return 0;
1519 }
1520
1521 static void __exit asus_wmi_exit(void)
1522 {
1523         pr_info("ASUS WMI generic driver unloaded");
1524 }
1525
1526 module_init(asus_wmi_init);
1527 module_exit(asus_wmi_exit);