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