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