linux/drivers/platform/x86/asus-wmi.c
<<
>>
Prefs
   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/hwmon.h>
  43#include <linux/hwmon-sysfs.h>
  44#include <linux/debugfs.h>
  45#include <linux/seq_file.h>
  46#include <linux/platform_device.h>
  47#include <linux/thermal.h>
  48#include <linux/acpi.h>
  49#include <acpi/video.h>
  50
  51#include "asus-wmi.h"
  52
  53MODULE_AUTHOR("Corentin Chary <corentin.chary@gmail.com>, "
  54              "Yong Wang <yong.y.wang@intel.com>");
  55MODULE_DESCRIPTION("Asus Generic WMI Driver");
  56MODULE_LICENSE("GPL");
  57
  58#define to_platform_driver(drv)                                 \
  59        (container_of((drv), struct platform_driver, driver))
  60
  61#define to_asus_wmi_driver(pdrv)                                        \
  62        (container_of((pdrv), struct asus_wmi_driver, platform_driver))
  63
  64#define ASUS_WMI_MGMT_GUID      "97845ED0-4E6D-11DE-8A39-0800200C9A66"
  65
  66#define NOTIFY_BRNUP_MIN                0x11
  67#define NOTIFY_BRNUP_MAX                0x1f
  68#define NOTIFY_BRNDOWN_MIN              0x20
  69#define NOTIFY_BRNDOWN_MAX              0x2e
  70#define NOTIFY_KBD_BRTUP                0xc4
  71#define NOTIFY_KBD_BRTDWN               0xc5
  72
  73/* WMI Methods */
  74#define ASUS_WMI_METHODID_SPEC          0x43455053 /* BIOS SPECification */
  75#define ASUS_WMI_METHODID_SFBD          0x44424653 /* Set First Boot Device */
  76#define ASUS_WMI_METHODID_GLCD          0x44434C47 /* Get LCD status */
  77#define ASUS_WMI_METHODID_GPID          0x44495047 /* Get Panel ID?? (Resol) */
  78#define ASUS_WMI_METHODID_QMOD          0x444F4D51 /* Quiet MODe */
  79#define ASUS_WMI_METHODID_SPLV          0x4C425053 /* Set Panel Light Value */
  80#define ASUS_WMI_METHODID_SFUN          0x4E554653 /* FUNCtionalities */
  81#define ASUS_WMI_METHODID_SDSP          0x50534453 /* Set DiSPlay output */
  82#define ASUS_WMI_METHODID_GDSP          0x50534447 /* Get DiSPlay output */
  83#define ASUS_WMI_METHODID_DEVP          0x50564544 /* DEVice Policy */
  84#define ASUS_WMI_METHODID_OSVR          0x5256534F /* OS VeRsion */
  85#define ASUS_WMI_METHODID_DSTS          0x53544344 /* Device STatuS */
  86#define ASUS_WMI_METHODID_DSTS2         0x53545344 /* Device STatuS #2*/
  87#define ASUS_WMI_METHODID_BSTS          0x53545342 /* Bios STatuS ? */
  88#define ASUS_WMI_METHODID_DEVS          0x53564544 /* DEVice Set */
  89#define ASUS_WMI_METHODID_CFVS          0x53564643 /* CPU Frequency Volt Set */
  90#define ASUS_WMI_METHODID_KBFT          0x5446424B /* KeyBoard FilTer */
  91#define ASUS_WMI_METHODID_INIT          0x54494E49 /* INITialize */
  92#define ASUS_WMI_METHODID_HKEY          0x59454B48 /* Hot KEY ?? */
  93
  94#define ASUS_WMI_UNSUPPORTED_METHOD     0xFFFFFFFE
  95
  96/* Wireless */
  97#define ASUS_WMI_DEVID_HW_SWITCH        0x00010001
  98#define ASUS_WMI_DEVID_WIRELESS_LED     0x00010002
  99#define ASUS_WMI_DEVID_CWAP             0x00010003
 100#define ASUS_WMI_DEVID_WLAN             0x00010011
 101#define ASUS_WMI_DEVID_WLAN_LED         0x00010012
 102#define ASUS_WMI_DEVID_BLUETOOTH        0x00010013
 103#define ASUS_WMI_DEVID_GPS              0x00010015
 104#define ASUS_WMI_DEVID_WIMAX            0x00010017
 105#define ASUS_WMI_DEVID_WWAN3G           0x00010019
 106#define ASUS_WMI_DEVID_UWB              0x00010021
 107
 108/* Leds */
 109/* 0x000200XX and 0x000400XX */
 110#define ASUS_WMI_DEVID_LED1             0x00020011
 111#define ASUS_WMI_DEVID_LED2             0x00020012
 112#define ASUS_WMI_DEVID_LED3             0x00020013
 113#define ASUS_WMI_DEVID_LED4             0x00020014
 114#define ASUS_WMI_DEVID_LED5             0x00020015
 115#define ASUS_WMI_DEVID_LED6             0x00020016
 116
 117/* Backlight and Brightness */
 118#define ASUS_WMI_DEVID_BACKLIGHT        0x00050011
 119#define ASUS_WMI_DEVID_BRIGHTNESS       0x00050012
 120#define ASUS_WMI_DEVID_KBD_BACKLIGHT    0x00050021
 121#define ASUS_WMI_DEVID_LIGHT_SENSOR     0x00050022 /* ?? */
 122
 123/* Misc */
 124#define ASUS_WMI_DEVID_CAMERA           0x00060013
 125
 126/* Storage */
 127#define ASUS_WMI_DEVID_CARDREADER       0x00080013
 128
 129/* Input */
 130#define ASUS_WMI_DEVID_TOUCHPAD         0x00100011
 131#define ASUS_WMI_DEVID_TOUCHPAD_LED     0x00100012
 132
 133/* Fan, Thermal */
 134#define ASUS_WMI_DEVID_THERMAL_CTRL     0x00110011
 135#define ASUS_WMI_DEVID_FAN_CTRL         0x00110012
 136
 137/* Power */
 138#define ASUS_WMI_DEVID_PROCESSOR_STATE  0x00120012
 139
 140/* Deep S3 / Resume on LID open */
 141#define ASUS_WMI_DEVID_LID_RESUME       0x00120031
 142
 143/* DSTS masks */
 144#define ASUS_WMI_DSTS_STATUS_BIT        0x00000001
 145#define ASUS_WMI_DSTS_UNKNOWN_BIT       0x00000002
 146#define ASUS_WMI_DSTS_PRESENCE_BIT      0x00010000
 147#define ASUS_WMI_DSTS_USER_BIT          0x00020000
 148#define ASUS_WMI_DSTS_BIOS_BIT          0x00040000
 149#define ASUS_WMI_DSTS_BRIGHTNESS_MASK   0x000000FF
 150#define ASUS_WMI_DSTS_MAX_BRIGTH_MASK   0x0000FF00
 151
 152struct bios_args {
 153        u32 arg0;
 154        u32 arg1;
 155} __packed;
 156
 157/*
 158 * <platform>/    - debugfs root directory
 159 *   dev_id      - current dev_id
 160 *   ctrl_param  - current ctrl_param
 161 *   method_id   - current method_id
 162 *   devs        - call DEVS(dev_id, ctrl_param) and print result
 163 *   dsts        - call DSTS(dev_id)  and print result
 164 *   call        - call method_id(dev_id, ctrl_param) and print result
 165 */
 166struct asus_wmi_debug {
 167        struct dentry *root;
 168        u32 method_id;
 169        u32 dev_id;
 170        u32 ctrl_param;
 171};
 172
 173struct asus_rfkill {
 174        struct asus_wmi *asus;
 175        struct rfkill *rfkill;
 176        u32 dev_id;
 177};
 178
 179struct asus_wmi {
 180        int dsts_id;
 181        int spec;
 182        int sfun;
 183
 184        struct input_dev *inputdev;
 185        struct backlight_device *backlight_device;
 186        struct platform_device *platform_device;
 187
 188        struct led_classdev wlan_led;
 189        int wlan_led_wk;
 190        struct led_classdev tpd_led;
 191        int tpd_led_wk;
 192        struct led_classdev kbd_led;
 193        int kbd_led_wk;
 194        struct workqueue_struct *led_workqueue;
 195        struct work_struct tpd_led_work;
 196        struct work_struct kbd_led_work;
 197        struct work_struct wlan_led_work;
 198
 199        struct asus_rfkill wlan;
 200        struct asus_rfkill bluetooth;
 201        struct asus_rfkill wimax;
 202        struct asus_rfkill wwan3g;
 203        struct asus_rfkill gps;
 204        struct asus_rfkill uwb;
 205
 206        struct hotplug_slot *hotplug_slot;
 207        struct mutex hotplug_lock;
 208        struct mutex wmi_lock;
 209        struct workqueue_struct *hotplug_workqueue;
 210        struct work_struct hotplug_work;
 211
 212        struct asus_wmi_debug debug;
 213
 214        struct asus_wmi_driver *driver;
 215};
 216
 217static int asus_wmi_input_init(struct asus_wmi *asus)
 218{
 219        int err;
 220
 221        asus->inputdev = input_allocate_device();
 222        if (!asus->inputdev)
 223                return -ENOMEM;
 224
 225        asus->inputdev->name = asus->driver->input_name;
 226        asus->inputdev->phys = asus->driver->input_phys;
 227        asus->inputdev->id.bustype = BUS_HOST;
 228        asus->inputdev->dev.parent = &asus->platform_device->dev;
 229        set_bit(EV_REP, asus->inputdev->evbit);
 230
 231        err = sparse_keymap_setup(asus->inputdev, asus->driver->keymap, NULL);
 232        if (err)
 233                goto err_free_dev;
 234
 235        err = input_register_device(asus->inputdev);
 236        if (err)
 237                goto err_free_keymap;
 238
 239        return 0;
 240
 241err_free_keymap:
 242        sparse_keymap_free(asus->inputdev);
 243err_free_dev:
 244        input_free_device(asus->inputdev);
 245        return err;
 246}
 247
 248static void asus_wmi_input_exit(struct asus_wmi *asus)
 249{
 250        if (asus->inputdev) {
 251                sparse_keymap_free(asus->inputdev);
 252                input_unregister_device(asus->inputdev);
 253        }
 254
 255        asus->inputdev = NULL;
 256}
 257
 258static int asus_wmi_evaluate_method(u32 method_id, u32 arg0, u32 arg1,
 259                                    u32 *retval)
 260{
 261        struct bios_args args = {
 262                .arg0 = arg0,
 263                .arg1 = arg1,
 264        };
 265        struct acpi_buffer input = { (acpi_size) sizeof(args), &args };
 266        struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
 267        acpi_status status;
 268        union acpi_object *obj;
 269        u32 tmp;
 270
 271        status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID, 1, method_id,
 272                                     &input, &output);
 273
 274        if (ACPI_FAILURE(status))
 275                goto exit;
 276
 277        obj = (union acpi_object *)output.pointer;
 278        if (obj && obj->type == ACPI_TYPE_INTEGER)
 279                tmp = (u32) obj->integer.value;
 280        else
 281                tmp = 0;
 282
 283        if (retval)
 284                *retval = tmp;
 285
 286        kfree(obj);
 287
 288exit:
 289        if (ACPI_FAILURE(status))
 290                return -EIO;
 291
 292        if (tmp == ASUS_WMI_UNSUPPORTED_METHOD)
 293                return -ENODEV;
 294
 295        return 0;
 296}
 297
 298static int asus_wmi_get_devstate(struct asus_wmi *asus, u32 dev_id, u32 *retval)
 299{
 300        return asus_wmi_evaluate_method(asus->dsts_id, dev_id, 0, retval);
 301}
 302
 303static int asus_wmi_set_devstate(u32 dev_id, u32 ctrl_param,
 304                                 u32 *retval)
 305{
 306        return asus_wmi_evaluate_method(ASUS_WMI_METHODID_DEVS, dev_id,
 307                                        ctrl_param, retval);
 308}
 309
 310/* Helper for special devices with magic return codes */
 311static int asus_wmi_get_devstate_bits(struct asus_wmi *asus,
 312                                      u32 dev_id, u32 mask)
 313{
 314        u32 retval = 0;
 315        int err;
 316
 317        err = asus_wmi_get_devstate(asus, dev_id, &retval);
 318
 319        if (err < 0)
 320                return err;
 321
 322        if (!(retval & ASUS_WMI_DSTS_PRESENCE_BIT))
 323                return -ENODEV;
 324
 325        if (mask == ASUS_WMI_DSTS_STATUS_BIT) {
 326                if (retval & ASUS_WMI_DSTS_UNKNOWN_BIT)
 327                        return -ENODEV;
 328        }
 329
 330        return retval & mask;
 331}
 332
 333static int asus_wmi_get_devstate_simple(struct asus_wmi *asus, u32 dev_id)
 334{
 335        return asus_wmi_get_devstate_bits(asus, dev_id,
 336                                          ASUS_WMI_DSTS_STATUS_BIT);
 337}
 338
 339/*
 340 * LEDs
 341 */
 342/*
 343 * These functions actually update the LED's, and are called from a
 344 * workqueue. By doing this as separate work rather than when the LED
 345 * subsystem asks, we avoid messing with the Asus ACPI stuff during a
 346 * potentially bad time, such as a timer interrupt.
 347 */
 348static void tpd_led_update(struct work_struct *work)
 349{
 350        int ctrl_param;
 351        struct asus_wmi *asus;
 352
 353        asus = container_of(work, struct asus_wmi, tpd_led_work);
 354
 355        ctrl_param = asus->tpd_led_wk;
 356        asus_wmi_set_devstate(ASUS_WMI_DEVID_TOUCHPAD_LED, ctrl_param, NULL);
 357}
 358
 359static void tpd_led_set(struct led_classdev *led_cdev,
 360                        enum led_brightness value)
 361{
 362        struct asus_wmi *asus;
 363
 364        asus = container_of(led_cdev, struct asus_wmi, tpd_led);
 365
 366        asus->tpd_led_wk = !!value;
 367        queue_work(asus->led_workqueue, &asus->tpd_led_work);
 368}
 369
 370static int read_tpd_led_state(struct asus_wmi *asus)
 371{
 372        return asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_TOUCHPAD_LED);
 373}
 374
 375static enum led_brightness tpd_led_get(struct led_classdev *led_cdev)
 376{
 377        struct asus_wmi *asus;
 378
 379        asus = container_of(led_cdev, struct asus_wmi, tpd_led);
 380
 381        return read_tpd_led_state(asus);
 382}
 383
 384static void kbd_led_update(struct work_struct *work)
 385{
 386        int ctrl_param = 0;
 387        struct asus_wmi *asus;
 388
 389        asus = container_of(work, struct asus_wmi, kbd_led_work);
 390
 391        /*
 392         * bits 0-2: level
 393         * bit 7: light on/off
 394         */
 395        if (asus->kbd_led_wk > 0)
 396                ctrl_param = 0x80 | (asus->kbd_led_wk & 0x7F);
 397
 398        asus_wmi_set_devstate(ASUS_WMI_DEVID_KBD_BACKLIGHT, ctrl_param, NULL);
 399}
 400
 401static int kbd_led_read(struct asus_wmi *asus, int *level, int *env)
 402{
 403        int retval;
 404
 405        /*
 406         * bits 0-2: level
 407         * bit 7: light on/off
 408         * bit 8-10: environment (0: dark, 1: normal, 2: light)
 409         * bit 17: status unknown
 410         */
 411        retval = asus_wmi_get_devstate_bits(asus, ASUS_WMI_DEVID_KBD_BACKLIGHT,
 412                                            0xFFFF);
 413
 414        /* Unknown status is considered as off */
 415        if (retval == 0x8000)
 416                retval = 0;
 417
 418        if (retval >= 0) {
 419                if (level)
 420                        *level = retval & 0x7F;
 421                if (env)
 422                        *env = (retval >> 8) & 0x7F;
 423                retval = 0;
 424        }
 425
 426        return retval;
 427}
 428
 429static void kbd_led_set(struct led_classdev *led_cdev,
 430                        enum led_brightness value)
 431{
 432        struct asus_wmi *asus;
 433
 434        asus = container_of(led_cdev, struct asus_wmi, kbd_led);
 435
 436        if (value > asus->kbd_led.max_brightness)
 437                value = asus->kbd_led.max_brightness;
 438        else if (value < 0)
 439                value = 0;
 440
 441        asus->kbd_led_wk = value;
 442        queue_work(asus->led_workqueue, &asus->kbd_led_work);
 443}
 444
 445static enum led_brightness kbd_led_get(struct led_classdev *led_cdev)
 446{
 447        struct asus_wmi *asus;
 448        int retval, value;
 449
 450        asus = container_of(led_cdev, struct asus_wmi, kbd_led);
 451
 452        retval = kbd_led_read(asus, &value, NULL);
 453
 454        if (retval < 0)
 455                return retval;
 456
 457        return value;
 458}
 459
 460static int wlan_led_unknown_state(struct asus_wmi *asus)
 461{
 462        u32 result;
 463
 464        asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WIRELESS_LED, &result);
 465
 466        return result & ASUS_WMI_DSTS_UNKNOWN_BIT;
 467}
 468
 469static int wlan_led_presence(struct asus_wmi *asus)
 470{
 471        u32 result;
 472
 473        asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WIRELESS_LED, &result);
 474
 475        return result & ASUS_WMI_DSTS_PRESENCE_BIT;
 476}
 477
 478static void wlan_led_update(struct work_struct *work)
 479{
 480        int ctrl_param;
 481        struct asus_wmi *asus;
 482
 483        asus = container_of(work, struct asus_wmi, wlan_led_work);
 484
 485        ctrl_param = asus->wlan_led_wk;
 486        asus_wmi_set_devstate(ASUS_WMI_DEVID_WIRELESS_LED, ctrl_param, NULL);
 487}
 488
 489static void wlan_led_set(struct led_classdev *led_cdev,
 490                         enum led_brightness value)
 491{
 492        struct asus_wmi *asus;
 493
 494        asus = container_of(led_cdev, struct asus_wmi, wlan_led);
 495
 496        asus->wlan_led_wk = !!value;
 497        queue_work(asus->led_workqueue, &asus->wlan_led_work);
 498}
 499
 500static enum led_brightness wlan_led_get(struct led_classdev *led_cdev)
 501{
 502        struct asus_wmi *asus;
 503        u32 result;
 504
 505        asus = container_of(led_cdev, struct asus_wmi, wlan_led);
 506        asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WIRELESS_LED, &result);
 507
 508        return result & ASUS_WMI_DSTS_BRIGHTNESS_MASK;
 509}
 510
 511static void asus_wmi_led_exit(struct asus_wmi *asus)
 512{
 513        if (!IS_ERR_OR_NULL(asus->kbd_led.dev))
 514                led_classdev_unregister(&asus->kbd_led);
 515        if (!IS_ERR_OR_NULL(asus->tpd_led.dev))
 516                led_classdev_unregister(&asus->tpd_led);
 517        if (!IS_ERR_OR_NULL(asus->wlan_led.dev))
 518                led_classdev_unregister(&asus->wlan_led);
 519        if (asus->led_workqueue)
 520                destroy_workqueue(asus->led_workqueue);
 521}
 522
 523static int asus_wmi_led_init(struct asus_wmi *asus)
 524{
 525        int rv = 0;
 526
 527        asus->led_workqueue = create_singlethread_workqueue("led_workqueue");
 528        if (!asus->led_workqueue)
 529                return -ENOMEM;
 530
 531        if (read_tpd_led_state(asus) >= 0) {
 532                INIT_WORK(&asus->tpd_led_work, tpd_led_update);
 533
 534                asus->tpd_led.name = "asus::touchpad";
 535                asus->tpd_led.brightness_set = tpd_led_set;
 536                asus->tpd_led.brightness_get = tpd_led_get;
 537                asus->tpd_led.max_brightness = 1;
 538
 539                rv = led_classdev_register(&asus->platform_device->dev,
 540                                           &asus->tpd_led);
 541                if (rv)
 542                        goto error;
 543        }
 544
 545        if (kbd_led_read(asus, NULL, NULL) >= 0) {
 546                INIT_WORK(&asus->kbd_led_work, kbd_led_update);
 547
 548                asus->kbd_led.name = "asus::kbd_backlight";
 549                asus->kbd_led.brightness_set = kbd_led_set;
 550                asus->kbd_led.brightness_get = kbd_led_get;
 551                asus->kbd_led.max_brightness = 3;
 552
 553                rv = led_classdev_register(&asus->platform_device->dev,
 554                                           &asus->kbd_led);
 555                if (rv)
 556                        goto error;
 557        }
 558
 559        if (wlan_led_presence(asus) && (asus->driver->quirks->wapf == 4)) {
 560                INIT_WORK(&asus->wlan_led_work, wlan_led_update);
 561
 562                asus->wlan_led.name = "asus::wlan";
 563                asus->wlan_led.brightness_set = wlan_led_set;
 564                if (!wlan_led_unknown_state(asus))
 565                        asus->wlan_led.brightness_get = wlan_led_get;
 566                asus->wlan_led.flags = LED_CORE_SUSPENDRESUME;
 567                asus->wlan_led.max_brightness = 1;
 568                asus->wlan_led.default_trigger = "asus-wlan";
 569
 570                rv = led_classdev_register(&asus->platform_device->dev,
 571                                           &asus->wlan_led);
 572        }
 573
 574error:
 575        if (rv)
 576                asus_wmi_led_exit(asus);
 577
 578        return rv;
 579}
 580
 581
 582/*
 583 * PCI hotplug (for wlan rfkill)
 584 */
 585static bool asus_wlan_rfkill_blocked(struct asus_wmi *asus)
 586{
 587        int result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WLAN);
 588
 589        if (result < 0)
 590                return false;
 591        return !result;
 592}
 593
 594static void asus_rfkill_hotplug(struct asus_wmi *asus)
 595{
 596        struct pci_dev *dev;
 597        struct pci_bus *bus;
 598        bool blocked;
 599        bool absent;
 600        u32 l;
 601
 602        mutex_lock(&asus->wmi_lock);
 603        blocked = asus_wlan_rfkill_blocked(asus);
 604        mutex_unlock(&asus->wmi_lock);
 605
 606        mutex_lock(&asus->hotplug_lock);
 607        pci_lock_rescan_remove();
 608
 609        if (asus->wlan.rfkill)
 610                rfkill_set_sw_state(asus->wlan.rfkill, blocked);
 611
 612        if (asus->hotplug_slot) {
 613                bus = pci_find_bus(0, 1);
 614                if (!bus) {
 615                        pr_warn("Unable to find PCI bus 1?\n");
 616                        goto out_unlock;
 617                }
 618
 619                if (pci_bus_read_config_dword(bus, 0, PCI_VENDOR_ID, &l)) {
 620                        pr_err("Unable to read PCI config space?\n");
 621                        goto out_unlock;
 622                }
 623                absent = (l == 0xffffffff);
 624
 625                if (blocked != absent) {
 626                        pr_warn("BIOS says wireless lan is %s, "
 627                                "but the pci device is %s\n",
 628                                blocked ? "blocked" : "unblocked",
 629                                absent ? "absent" : "present");
 630                        pr_warn("skipped wireless hotplug as probably "
 631                                "inappropriate for this model\n");
 632                        goto out_unlock;
 633                }
 634
 635                if (!blocked) {
 636                        dev = pci_get_slot(bus, 0);
 637                        if (dev) {
 638                                /* Device already present */
 639                                pci_dev_put(dev);
 640                                goto out_unlock;
 641                        }
 642                        dev = pci_scan_single_device(bus, 0);
 643                        if (dev) {
 644                                pci_bus_assign_resources(bus);
 645                                if (pci_bus_add_device(dev))
 646                                        pr_err("Unable to hotplug wifi\n");
 647                        }
 648                } else {
 649                        dev = pci_get_slot(bus, 0);
 650                        if (dev) {
 651                                pci_stop_and_remove_bus_device(dev);
 652                                pci_dev_put(dev);
 653                        }
 654                }
 655        }
 656
 657out_unlock:
 658        pci_unlock_rescan_remove();
 659        mutex_unlock(&asus->hotplug_lock);
 660}
 661
 662static void asus_rfkill_notify(acpi_handle handle, u32 event, void *data)
 663{
 664        struct asus_wmi *asus = data;
 665
 666        if (event != ACPI_NOTIFY_BUS_CHECK)
 667                return;
 668
 669        /*
 670         * We can't call directly asus_rfkill_hotplug because most
 671         * of the time WMBC is still being executed and not reetrant.
 672         * There is currently no way to tell ACPICA that  we want this
 673         * method to be serialized, we schedule a asus_rfkill_hotplug
 674         * call later, in a safer context.
 675         */
 676        queue_work(asus->hotplug_workqueue, &asus->hotplug_work);
 677}
 678
 679static int asus_register_rfkill_notifier(struct asus_wmi *asus, char *node)
 680{
 681        acpi_status status;
 682        acpi_handle handle;
 683
 684        status = acpi_get_handle(NULL, node, &handle);
 685
 686        if (ACPI_SUCCESS(status)) {
 687                status = acpi_install_notify_handler(handle,
 688                                                     ACPI_SYSTEM_NOTIFY,
 689                                                     asus_rfkill_notify, asus);
 690                if (ACPI_FAILURE(status))
 691                        pr_warn("Failed to register notify on %s\n", node);
 692        } else
 693                return -ENODEV;
 694
 695        return 0;
 696}
 697
 698static void asus_unregister_rfkill_notifier(struct asus_wmi *asus, char *node)
 699{
 700        acpi_status status = AE_OK;
 701        acpi_handle handle;
 702
 703        status = acpi_get_handle(NULL, node, &handle);
 704
 705        if (ACPI_SUCCESS(status)) {
 706                status = acpi_remove_notify_handler(handle,
 707                                                    ACPI_SYSTEM_NOTIFY,
 708                                                    asus_rfkill_notify);
 709                if (ACPI_FAILURE(status))
 710                        pr_err("Error removing rfkill notify handler %s\n",
 711                               node);
 712        }
 713}
 714
 715static int asus_get_adapter_status(struct hotplug_slot *hotplug_slot,
 716                                   u8 *value)
 717{
 718        struct asus_wmi *asus = hotplug_slot->private;
 719        int result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WLAN);
 720
 721        if (result < 0)
 722                return result;
 723
 724        *value = !!result;
 725        return 0;
 726}
 727
 728static void asus_cleanup_pci_hotplug(struct hotplug_slot *hotplug_slot)
 729{
 730        kfree(hotplug_slot->info);
 731        kfree(hotplug_slot);
 732}
 733
 734static struct hotplug_slot_ops asus_hotplug_slot_ops = {
 735        .owner = THIS_MODULE,
 736        .get_adapter_status = asus_get_adapter_status,
 737        .get_power_status = asus_get_adapter_status,
 738};
 739
 740static void asus_hotplug_work(struct work_struct *work)
 741{
 742        struct asus_wmi *asus;
 743
 744        asus = container_of(work, struct asus_wmi, hotplug_work);
 745        asus_rfkill_hotplug(asus);
 746}
 747
 748static int asus_setup_pci_hotplug(struct asus_wmi *asus)
 749{
 750        int ret = -ENOMEM;
 751        struct pci_bus *bus = pci_find_bus(0, 1);
 752
 753        if (!bus) {
 754                pr_err("Unable to find wifi PCI bus\n");
 755                return -ENODEV;
 756        }
 757
 758        asus->hotplug_workqueue =
 759            create_singlethread_workqueue("hotplug_workqueue");
 760        if (!asus->hotplug_workqueue)
 761                goto error_workqueue;
 762
 763        INIT_WORK(&asus->hotplug_work, asus_hotplug_work);
 764
 765        asus->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
 766        if (!asus->hotplug_slot)
 767                goto error_slot;
 768
 769        asus->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info),
 770                                           GFP_KERNEL);
 771        if (!asus->hotplug_slot->info)
 772                goto error_info;
 773
 774        asus->hotplug_slot->private = asus;
 775        asus->hotplug_slot->release = &asus_cleanup_pci_hotplug;
 776        asus->hotplug_slot->ops = &asus_hotplug_slot_ops;
 777        asus_get_adapter_status(asus->hotplug_slot,
 778                                &asus->hotplug_slot->info->adapter_status);
 779
 780        ret = pci_hp_register(asus->hotplug_slot, bus, 0, "asus-wifi");
 781        if (ret) {
 782                pr_err("Unable to register hotplug slot - %d\n", ret);
 783                goto error_register;
 784        }
 785
 786        return 0;
 787
 788error_register:
 789        kfree(asus->hotplug_slot->info);
 790error_info:
 791        kfree(asus->hotplug_slot);
 792        asus->hotplug_slot = NULL;
 793error_slot:
 794        destroy_workqueue(asus->hotplug_workqueue);
 795error_workqueue:
 796        return ret;
 797}
 798
 799/*
 800 * Rfkill devices
 801 */
 802static int asus_rfkill_set(void *data, bool blocked)
 803{
 804        struct asus_rfkill *priv = data;
 805        u32 ctrl_param = !blocked;
 806        u32 dev_id = priv->dev_id;
 807
 808        /*
 809         * If the user bit is set, BIOS can't set and record the wlan status,
 810         * it will report the value read from id ASUS_WMI_DEVID_WLAN_LED
 811         * while we query the wlan status through WMI(ASUS_WMI_DEVID_WLAN).
 812         * So, we have to record wlan status in id ASUS_WMI_DEVID_WLAN_LED
 813         * while setting the wlan status through WMI.
 814         * This is also the behavior that windows app will do.
 815         */
 816        if ((dev_id == ASUS_WMI_DEVID_WLAN) &&
 817             priv->asus->driver->wlan_ctrl_by_user)
 818                dev_id = ASUS_WMI_DEVID_WLAN_LED;
 819
 820        return asus_wmi_set_devstate(dev_id, ctrl_param, NULL);
 821}
 822
 823static void asus_rfkill_query(struct rfkill *rfkill, void *data)
 824{
 825        struct asus_rfkill *priv = data;
 826        int result;
 827
 828        result = asus_wmi_get_devstate_simple(priv->asus, priv->dev_id);
 829
 830        if (result < 0)
 831                return;
 832
 833        rfkill_set_sw_state(priv->rfkill, !result);
 834}
 835
 836static int asus_rfkill_wlan_set(void *data, bool blocked)
 837{
 838        struct asus_rfkill *priv = data;
 839        struct asus_wmi *asus = priv->asus;
 840        int ret;
 841
 842        /*
 843         * This handler is enabled only if hotplug is enabled.
 844         * In this case, the asus_wmi_set_devstate() will
 845         * trigger a wmi notification and we need to wait
 846         * this call to finish before being able to call
 847         * any wmi method
 848         */
 849        mutex_lock(&asus->wmi_lock);
 850        ret = asus_rfkill_set(data, blocked);
 851        mutex_unlock(&asus->wmi_lock);
 852        return ret;
 853}
 854
 855static const struct rfkill_ops asus_rfkill_wlan_ops = {
 856        .set_block = asus_rfkill_wlan_set,
 857        .query = asus_rfkill_query,
 858};
 859
 860static const struct rfkill_ops asus_rfkill_ops = {
 861        .set_block = asus_rfkill_set,
 862        .query = asus_rfkill_query,
 863};
 864
 865static int asus_new_rfkill(struct asus_wmi *asus,
 866                           struct asus_rfkill *arfkill,
 867                           const char *name, enum rfkill_type type, int dev_id)
 868{
 869        int result = asus_wmi_get_devstate_simple(asus, dev_id);
 870        struct rfkill **rfkill = &arfkill->rfkill;
 871
 872        if (result < 0)
 873                return result;
 874
 875        arfkill->dev_id = dev_id;
 876        arfkill->asus = asus;
 877
 878        if (dev_id == ASUS_WMI_DEVID_WLAN &&
 879            asus->driver->quirks->hotplug_wireless)
 880                *rfkill = rfkill_alloc(name, &asus->platform_device->dev, type,
 881                                       &asus_rfkill_wlan_ops, arfkill);
 882        else
 883                *rfkill = rfkill_alloc(name, &asus->platform_device->dev, type,
 884                                       &asus_rfkill_ops, arfkill);
 885
 886        if (!*rfkill)
 887                return -EINVAL;
 888
 889        if ((dev_id == ASUS_WMI_DEVID_WLAN) &&
 890                        (asus->driver->quirks->wapf == 4))
 891                rfkill_set_led_trigger_name(*rfkill, "asus-wlan");
 892
 893        rfkill_init_sw_state(*rfkill, !result);
 894        result = rfkill_register(*rfkill);
 895        if (result) {
 896                rfkill_destroy(*rfkill);
 897                *rfkill = NULL;
 898                return result;
 899        }
 900        return 0;
 901}
 902
 903static void asus_wmi_rfkill_exit(struct asus_wmi *asus)
 904{
 905        asus_unregister_rfkill_notifier(asus, "\\_SB.PCI0.P0P5");
 906        asus_unregister_rfkill_notifier(asus, "\\_SB.PCI0.P0P6");
 907        asus_unregister_rfkill_notifier(asus, "\\_SB.PCI0.P0P7");
 908        if (asus->wlan.rfkill) {
 909                rfkill_unregister(asus->wlan.rfkill);
 910                rfkill_destroy(asus->wlan.rfkill);
 911                asus->wlan.rfkill = NULL;
 912        }
 913        /*
 914         * Refresh pci hotplug in case the rfkill state was changed after
 915         * asus_unregister_rfkill_notifier()
 916         */
 917        asus_rfkill_hotplug(asus);
 918        if (asus->hotplug_slot)
 919                pci_hp_deregister(asus->hotplug_slot);
 920        if (asus->hotplug_workqueue)
 921                destroy_workqueue(asus->hotplug_workqueue);
 922
 923        if (asus->bluetooth.rfkill) {
 924                rfkill_unregister(asus->bluetooth.rfkill);
 925                rfkill_destroy(asus->bluetooth.rfkill);
 926                asus->bluetooth.rfkill = NULL;
 927        }
 928        if (asus->wimax.rfkill) {
 929                rfkill_unregister(asus->wimax.rfkill);
 930                rfkill_destroy(asus->wimax.rfkill);
 931                asus->wimax.rfkill = NULL;
 932        }
 933        if (asus->wwan3g.rfkill) {
 934                rfkill_unregister(asus->wwan3g.rfkill);
 935                rfkill_destroy(asus->wwan3g.rfkill);
 936                asus->wwan3g.rfkill = NULL;
 937        }
 938        if (asus->gps.rfkill) {
 939                rfkill_unregister(asus->gps.rfkill);
 940                rfkill_destroy(asus->gps.rfkill);
 941                asus->gps.rfkill = NULL;
 942        }
 943        if (asus->uwb.rfkill) {
 944                rfkill_unregister(asus->uwb.rfkill);
 945                rfkill_destroy(asus->uwb.rfkill);
 946                asus->uwb.rfkill = NULL;
 947        }
 948}
 949
 950static int asus_wmi_rfkill_init(struct asus_wmi *asus)
 951{
 952        int result = 0;
 953
 954        mutex_init(&asus->hotplug_lock);
 955        mutex_init(&asus->wmi_lock);
 956
 957        result = asus_new_rfkill(asus, &asus->wlan, "asus-wlan",
 958                                 RFKILL_TYPE_WLAN, ASUS_WMI_DEVID_WLAN);
 959
 960        if (result && result != -ENODEV)
 961                goto exit;
 962
 963        result = asus_new_rfkill(asus, &asus->bluetooth,
 964                                 "asus-bluetooth", RFKILL_TYPE_BLUETOOTH,
 965                                 ASUS_WMI_DEVID_BLUETOOTH);
 966
 967        if (result && result != -ENODEV)
 968                goto exit;
 969
 970        result = asus_new_rfkill(asus, &asus->wimax, "asus-wimax",
 971                                 RFKILL_TYPE_WIMAX, ASUS_WMI_DEVID_WIMAX);
 972
 973        if (result && result != -ENODEV)
 974                goto exit;
 975
 976        result = asus_new_rfkill(asus, &asus->wwan3g, "asus-wwan3g",
 977                                 RFKILL_TYPE_WWAN, ASUS_WMI_DEVID_WWAN3G);
 978
 979        if (result && result != -ENODEV)
 980                goto exit;
 981
 982        result = asus_new_rfkill(asus, &asus->gps, "asus-gps",
 983                                 RFKILL_TYPE_GPS, ASUS_WMI_DEVID_GPS);
 984
 985        if (result && result != -ENODEV)
 986                goto exit;
 987
 988        result = asus_new_rfkill(asus, &asus->uwb, "asus-uwb",
 989                                 RFKILL_TYPE_UWB, ASUS_WMI_DEVID_UWB);
 990
 991        if (result && result != -ENODEV)
 992                goto exit;
 993
 994        if (!asus->driver->quirks->hotplug_wireless)
 995                goto exit;
 996
 997        result = asus_setup_pci_hotplug(asus);
 998        /*
 999         * If we get -EBUSY then something else is handling the PCI hotplug -
1000         * don't fail in this case
1001         */
1002        if (result == -EBUSY)
1003                result = 0;
1004
1005        asus_register_rfkill_notifier(asus, "\\_SB.PCI0.P0P5");
1006        asus_register_rfkill_notifier(asus, "\\_SB.PCI0.P0P6");
1007        asus_register_rfkill_notifier(asus, "\\_SB.PCI0.P0P7");
1008        /*
1009         * Refresh pci hotplug in case the rfkill state was changed during
1010         * setup.
1011         */
1012        asus_rfkill_hotplug(asus);
1013
1014exit:
1015        if (result && result != -ENODEV)
1016                asus_wmi_rfkill_exit(asus);
1017
1018        if (result == -ENODEV)
1019                result = 0;
1020
1021        return result;
1022}
1023
1024/*
1025 * Hwmon device
1026 */
1027static ssize_t asus_hwmon_pwm1(struct device *dev,
1028                               struct device_attribute *attr,
1029                               char *buf)
1030{
1031        struct asus_wmi *asus = dev_get_drvdata(dev);
1032        u32 value;
1033        int err;
1034
1035        err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_FAN_CTRL, &value);
1036
1037        if (err < 0)
1038                return err;
1039
1040        value &= 0xFF;
1041
1042        if (value == 1) /* Low Speed */
1043                value = 85;
1044        else if (value == 2)
1045                value = 170;
1046        else if (value == 3)
1047                value = 255;
1048        else if (value != 0) {
1049                pr_err("Unknown fan speed %#x\n", value);
1050                value = -1;
1051        }
1052
1053        return sprintf(buf, "%d\n", value);
1054}
1055
1056static ssize_t asus_hwmon_temp1(struct device *dev,
1057                                struct device_attribute *attr,
1058                                char *buf)
1059{
1060        struct asus_wmi *asus = dev_get_drvdata(dev);
1061        u32 value;
1062        int err;
1063
1064        err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_THERMAL_CTRL, &value);
1065
1066        if (err < 0)
1067                return err;
1068
1069        value = KELVIN_TO_CELSIUS((value & 0xFFFF)) * 1000;
1070
1071        return sprintf(buf, "%d\n", value);
1072}
1073
1074static DEVICE_ATTR(pwm1, S_IRUGO, asus_hwmon_pwm1, NULL);
1075static DEVICE_ATTR(temp1_input, S_IRUGO, asus_hwmon_temp1, NULL);
1076
1077static struct attribute *hwmon_attributes[] = {
1078        &dev_attr_pwm1.attr,
1079        &dev_attr_temp1_input.attr,
1080        NULL
1081};
1082
1083static umode_t asus_hwmon_sysfs_is_visible(struct kobject *kobj,
1084                                          struct attribute *attr, int idx)
1085{
1086        struct device *dev = container_of(kobj, struct device, kobj);
1087        struct platform_device *pdev = to_platform_device(dev->parent);
1088        struct asus_wmi *asus = platform_get_drvdata(pdev);
1089        bool ok = true;
1090        int dev_id = -1;
1091        u32 value = ASUS_WMI_UNSUPPORTED_METHOD;
1092
1093        if (attr == &dev_attr_pwm1.attr)
1094                dev_id = ASUS_WMI_DEVID_FAN_CTRL;
1095        else if (attr == &dev_attr_temp1_input.attr)
1096                dev_id = ASUS_WMI_DEVID_THERMAL_CTRL;
1097
1098        if (dev_id != -1) {
1099                int err = asus_wmi_get_devstate(asus, dev_id, &value);
1100
1101                if (err < 0)
1102                        return 0; /* can't return negative here */
1103        }
1104
1105        if (dev_id == ASUS_WMI_DEVID_FAN_CTRL) {
1106                /*
1107                 * We need to find a better way, probably using sfun,
1108                 * bits or spec ...
1109                 * Currently we disable it if:
1110                 * - ASUS_WMI_UNSUPPORTED_METHOD is returned
1111                 * - reverved bits are non-zero
1112                 * - sfun and presence bit are not set
1113                 */
1114                if (value == ASUS_WMI_UNSUPPORTED_METHOD || value & 0xFFF80000
1115                    || (!asus->sfun && !(value & ASUS_WMI_DSTS_PRESENCE_BIT)))
1116                        ok = false;
1117        } else if (dev_id == ASUS_WMI_DEVID_THERMAL_CTRL) {
1118                /* If value is zero, something is clearly wrong */
1119                if (value == 0)
1120                        ok = false;
1121        }
1122
1123        return ok ? attr->mode : 0;
1124}
1125
1126static struct attribute_group hwmon_attribute_group = {
1127        .is_visible = asus_hwmon_sysfs_is_visible,
1128        .attrs = hwmon_attributes
1129};
1130__ATTRIBUTE_GROUPS(hwmon_attribute);
1131
1132static int asus_wmi_hwmon_init(struct asus_wmi *asus)
1133{
1134        struct device *hwmon;
1135
1136        hwmon = hwmon_device_register_with_groups(&asus->platform_device->dev,
1137                                                  "asus", asus,
1138                                                  hwmon_attribute_groups);
1139        if (IS_ERR(hwmon)) {
1140                pr_err("Could not register asus hwmon device\n");
1141                return PTR_ERR(hwmon);
1142        }
1143        return 0;
1144}
1145
1146/*
1147 * Backlight
1148 */
1149static int read_backlight_power(struct asus_wmi *asus)
1150{
1151        int ret;
1152        if (asus->driver->quirks->store_backlight_power)
1153                ret = !asus->driver->panel_power;
1154        else
1155                ret = asus_wmi_get_devstate_simple(asus,
1156                                                   ASUS_WMI_DEVID_BACKLIGHT);
1157
1158        if (ret < 0)
1159                return ret;
1160
1161        return ret ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
1162}
1163
1164static int read_brightness_max(struct asus_wmi *asus)
1165{
1166        u32 retval;
1167        int err;
1168
1169        err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_BRIGHTNESS, &retval);
1170
1171        if (err < 0)
1172                return err;
1173
1174        retval = retval & ASUS_WMI_DSTS_MAX_BRIGTH_MASK;
1175        retval >>= 8;
1176
1177        if (!retval)
1178                return -ENODEV;
1179
1180        return retval;
1181}
1182
1183static int read_brightness(struct backlight_device *bd)
1184{
1185        struct asus_wmi *asus = bl_get_data(bd);
1186        u32 retval;
1187        int err;
1188
1189        err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_BRIGHTNESS, &retval);
1190
1191        if (err < 0)
1192                return err;
1193
1194        return retval & ASUS_WMI_DSTS_BRIGHTNESS_MASK;
1195}
1196
1197static u32 get_scalar_command(struct backlight_device *bd)
1198{
1199        struct asus_wmi *asus = bl_get_data(bd);
1200        u32 ctrl_param = 0;
1201
1202        if ((asus->driver->brightness < bd->props.brightness) ||
1203            bd->props.brightness == bd->props.max_brightness)
1204                ctrl_param = 0x00008001;
1205        else if ((asus->driver->brightness > bd->props.brightness) ||
1206                 bd->props.brightness == 0)
1207                ctrl_param = 0x00008000;
1208
1209        asus->driver->brightness = bd->props.brightness;
1210
1211        return ctrl_param;
1212}
1213
1214static int update_bl_status(struct backlight_device *bd)
1215{
1216        struct asus_wmi *asus = bl_get_data(bd);
1217        u32 ctrl_param;
1218        int power, err = 0;
1219
1220        power = read_backlight_power(asus);
1221        if (power != -ENODEV && bd->props.power != power) {
1222                ctrl_param = !!(bd->props.power == FB_BLANK_UNBLANK);
1223                err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BACKLIGHT,
1224                                            ctrl_param, NULL);
1225                if (asus->driver->quirks->store_backlight_power)
1226                        asus->driver->panel_power = bd->props.power;
1227
1228                /* When using scalar brightness, updating the brightness
1229                 * will mess with the backlight power */
1230                if (asus->driver->quirks->scalar_panel_brightness)
1231                        return err;
1232        }
1233
1234        if (asus->driver->quirks->scalar_panel_brightness)
1235                ctrl_param = get_scalar_command(bd);
1236        else
1237                ctrl_param = bd->props.brightness;
1238
1239        err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BRIGHTNESS,
1240                                    ctrl_param, NULL);
1241
1242        return err;
1243}
1244
1245static const struct backlight_ops asus_wmi_bl_ops = {
1246        .get_brightness = read_brightness,
1247        .update_status = update_bl_status,
1248};
1249
1250static int asus_wmi_backlight_notify(struct asus_wmi *asus, int code)
1251{
1252        struct backlight_device *bd = asus->backlight_device;
1253        int old = bd->props.brightness;
1254        int new = old;
1255
1256        if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX)
1257                new = code - NOTIFY_BRNUP_MIN + 1;
1258        else if (code >= NOTIFY_BRNDOWN_MIN && code <= NOTIFY_BRNDOWN_MAX)
1259                new = code - NOTIFY_BRNDOWN_MIN;
1260
1261        bd->props.brightness = new;
1262        backlight_update_status(bd);
1263        backlight_force_update(bd, BACKLIGHT_UPDATE_HOTKEY);
1264
1265        return old;
1266}
1267
1268static int asus_wmi_backlight_init(struct asus_wmi *asus)
1269{
1270        struct backlight_device *bd;
1271        struct backlight_properties props;
1272        int max;
1273        int power;
1274
1275        max = read_brightness_max(asus);
1276
1277        if (max == -ENODEV)
1278                max = 0;
1279        else if (max < 0)
1280                return max;
1281
1282        power = read_backlight_power(asus);
1283
1284        if (power == -ENODEV)
1285                power = FB_BLANK_UNBLANK;
1286        else if (power < 0)
1287                return power;
1288
1289        memset(&props, 0, sizeof(struct backlight_properties));
1290        props.type = BACKLIGHT_PLATFORM;
1291        props.max_brightness = max;
1292        bd = backlight_device_register(asus->driver->name,
1293                                       &asus->platform_device->dev, asus,
1294                                       &asus_wmi_bl_ops, &props);
1295        if (IS_ERR(bd)) {
1296                pr_err("Could not register backlight device\n");
1297                return PTR_ERR(bd);
1298        }
1299
1300        asus->backlight_device = bd;
1301
1302        if (asus->driver->quirks->store_backlight_power)
1303                asus->driver->panel_power = power;
1304
1305        bd->props.brightness = read_brightness(bd);
1306        bd->props.power = power;
1307        backlight_update_status(bd);
1308
1309        asus->driver->brightness = bd->props.brightness;
1310
1311        return 0;
1312}
1313
1314static void asus_wmi_backlight_exit(struct asus_wmi *asus)
1315{
1316        if (asus->backlight_device)
1317                backlight_device_unregister(asus->backlight_device);
1318
1319        asus->backlight_device = NULL;
1320}
1321
1322static int is_display_toggle(int code)
1323{
1324        /* display toggle keys */
1325        if ((code >= 0x61 && code <= 0x67) ||
1326            (code >= 0x8c && code <= 0x93) ||
1327            (code >= 0xa0 && code <= 0xa7) ||
1328            (code >= 0xd0 && code <= 0xd5))
1329                return 1;
1330
1331        return 0;
1332}
1333
1334static void asus_wmi_notify(u32 value, void *context)
1335{
1336        struct asus_wmi *asus = context;
1337        struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
1338        union acpi_object *obj;
1339        acpi_status status;
1340        int code;
1341        int orig_code;
1342        unsigned int key_value = 1;
1343        bool autorelease = 1;
1344
1345        status = wmi_get_event_data(value, &response);
1346        if (status != AE_OK) {
1347                pr_err("bad event status 0x%x\n", status);
1348                return;
1349        }
1350
1351        obj = (union acpi_object *)response.pointer;
1352
1353        if (!obj || obj->type != ACPI_TYPE_INTEGER)
1354                goto exit;
1355
1356        code = obj->integer.value;
1357        orig_code = code;
1358
1359        if (asus->driver->key_filter) {
1360                asus->driver->key_filter(asus->driver, &code, &key_value,
1361                                         &autorelease);
1362                if (code == ASUS_WMI_KEY_IGNORE)
1363                        goto exit;
1364        }
1365
1366        if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX)
1367                code = ASUS_WMI_BRN_UP;
1368        else if (code >= NOTIFY_BRNDOWN_MIN &&
1369                 code <= NOTIFY_BRNDOWN_MAX)
1370                code = ASUS_WMI_BRN_DOWN;
1371
1372        if (code == ASUS_WMI_BRN_DOWN || code == ASUS_WMI_BRN_UP) {
1373                if (!acpi_video_backlight_support()) {
1374                        asus_wmi_backlight_notify(asus, orig_code);
1375                        goto exit;
1376                }
1377        }
1378
1379        if (is_display_toggle(code) &&
1380            asus->driver->quirks->no_display_toggle)
1381                goto exit;
1382
1383        if (!sparse_keymap_report_event(asus->inputdev, code,
1384                                        key_value, autorelease))
1385                pr_info("Unknown key %x pressed\n", code);
1386
1387exit:
1388        kfree(obj);
1389}
1390
1391/*
1392 * Sys helpers
1393 */
1394static int parse_arg(const char *buf, unsigned long count, int *val)
1395{
1396        if (!count)
1397                return 0;
1398        if (sscanf(buf, "%i", val) != 1)
1399                return -EINVAL;
1400        return count;
1401}
1402
1403static ssize_t store_sys_wmi(struct asus_wmi *asus, int devid,
1404                             const char *buf, size_t count)
1405{
1406        u32 retval;
1407        int rv, err, value;
1408
1409        value = asus_wmi_get_devstate_simple(asus, devid);
1410        if (value == -ENODEV)   /* Check device presence */
1411                return value;
1412
1413        rv = parse_arg(buf, count, &value);
1414        err = asus_wmi_set_devstate(devid, value, &retval);
1415
1416        if (err < 0)
1417                return err;
1418
1419        return rv;
1420}
1421
1422static ssize_t show_sys_wmi(struct asus_wmi *asus, int devid, char *buf)
1423{
1424        int value = asus_wmi_get_devstate_simple(asus, devid);
1425
1426        if (value < 0)
1427                return value;
1428
1429        return sprintf(buf, "%d\n", value);
1430}
1431
1432#define ASUS_WMI_CREATE_DEVICE_ATTR(_name, _mode, _cm)                  \
1433        static ssize_t show_##_name(struct device *dev,                 \
1434                                    struct device_attribute *attr,      \
1435                                    char *buf)                          \
1436        {                                                               \
1437                struct asus_wmi *asus = dev_get_drvdata(dev);           \
1438                                                                        \
1439                return show_sys_wmi(asus, _cm, buf);                    \
1440        }                                                               \
1441        static ssize_t store_##_name(struct device *dev,                \
1442                                     struct device_attribute *attr,     \
1443                                     const char *buf, size_t count)     \
1444        {                                                               \
1445                struct asus_wmi *asus = dev_get_drvdata(dev);           \
1446                                                                        \
1447                return store_sys_wmi(asus, _cm, buf, count);            \
1448        }                                                               \
1449        static struct device_attribute dev_attr_##_name = {             \
1450                .attr = {                                               \
1451                        .name = __stringify(_name),                     \
1452                        .mode = _mode },                                \
1453                .show   = show_##_name,                                 \
1454                .store  = store_##_name,                                \
1455        }
1456
1457ASUS_WMI_CREATE_DEVICE_ATTR(touchpad, 0644, ASUS_WMI_DEVID_TOUCHPAD);
1458ASUS_WMI_CREATE_DEVICE_ATTR(camera, 0644, ASUS_WMI_DEVID_CAMERA);
1459ASUS_WMI_CREATE_DEVICE_ATTR(cardr, 0644, ASUS_WMI_DEVID_CARDREADER);
1460ASUS_WMI_CREATE_DEVICE_ATTR(lid_resume, 0644, ASUS_WMI_DEVID_LID_RESUME);
1461
1462static ssize_t store_cpufv(struct device *dev, struct device_attribute *attr,
1463                           const char *buf, size_t count)
1464{
1465        int value, rv;
1466
1467        if (!count || sscanf(buf, "%i", &value) != 1)
1468                return -EINVAL;
1469        if (value < 0 || value > 2)
1470                return -EINVAL;
1471
1472        rv = asus_wmi_evaluate_method(ASUS_WMI_METHODID_CFVS, value, 0, NULL);
1473        if (rv < 0)
1474                return rv;
1475
1476        return count;
1477}
1478
1479static DEVICE_ATTR(cpufv, S_IRUGO | S_IWUSR, NULL, store_cpufv);
1480
1481static struct attribute *platform_attributes[] = {
1482        &dev_attr_cpufv.attr,
1483        &dev_attr_camera.attr,
1484        &dev_attr_cardr.attr,
1485        &dev_attr_touchpad.attr,
1486        &dev_attr_lid_resume.attr,
1487        NULL
1488};
1489
1490static umode_t asus_sysfs_is_visible(struct kobject *kobj,
1491                                    struct attribute *attr, int idx)
1492{
1493        struct device *dev = container_of(kobj, struct device, kobj);
1494        struct platform_device *pdev = to_platform_device(dev);
1495        struct asus_wmi *asus = platform_get_drvdata(pdev);
1496        bool ok = true;
1497        int devid = -1;
1498
1499        if (attr == &dev_attr_camera.attr)
1500                devid = ASUS_WMI_DEVID_CAMERA;
1501        else if (attr == &dev_attr_cardr.attr)
1502                devid = ASUS_WMI_DEVID_CARDREADER;
1503        else if (attr == &dev_attr_touchpad.attr)
1504                devid = ASUS_WMI_DEVID_TOUCHPAD;
1505        else if (attr == &dev_attr_lid_resume.attr)
1506                devid = ASUS_WMI_DEVID_LID_RESUME;
1507
1508        if (devid != -1)
1509                ok = !(asus_wmi_get_devstate_simple(asus, devid) < 0);
1510
1511        return ok ? attr->mode : 0;
1512}
1513
1514static struct attribute_group platform_attribute_group = {
1515        .is_visible = asus_sysfs_is_visible,
1516        .attrs = platform_attributes
1517};
1518
1519static void asus_wmi_sysfs_exit(struct platform_device *device)
1520{
1521        sysfs_remove_group(&device->dev.kobj, &platform_attribute_group);
1522}
1523
1524static int asus_wmi_sysfs_init(struct platform_device *device)
1525{
1526        return sysfs_create_group(&device->dev.kobj, &platform_attribute_group);
1527}
1528
1529/*
1530 * Platform device
1531 */
1532static int asus_wmi_platform_init(struct asus_wmi *asus)
1533{
1534        int rv;
1535
1536        /* INIT enable hotkeys on some models */
1537        if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_INIT, 0, 0, &rv))
1538                pr_info("Initialization: %#x\n", rv);
1539
1540        /* We don't know yet what to do with this version... */
1541        if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_SPEC, 0, 0x9, &rv)) {
1542                pr_info("BIOS WMI version: %d.%d\n", rv >> 16, rv & 0xFF);
1543                asus->spec = rv;
1544        }
1545
1546        /*
1547         * The SFUN method probably allows the original driver to get the list
1548         * of features supported by a given model. For now, 0x0100 or 0x0800
1549         * bit signifies that the laptop is equipped with a Wi-Fi MiniPCI card.
1550         * The significance of others is yet to be found.
1551         */
1552        if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_SFUN, 0, 0, &rv)) {
1553                pr_info("SFUN value: %#x\n", rv);
1554                asus->sfun = rv;
1555        }
1556
1557        /*
1558         * Eee PC and Notebooks seems to have different method_id for DSTS,
1559         * but it may also be related to the BIOS's SPEC.
1560         * Note, on most Eeepc, there is no way to check if a method exist
1561         * or note, while on notebooks, they returns 0xFFFFFFFE on failure,
1562         * but once again, SPEC may probably be used for that kind of things.
1563         */
1564        if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS, 0, 0, NULL))
1565                asus->dsts_id = ASUS_WMI_METHODID_DSTS;
1566        else
1567                asus->dsts_id = ASUS_WMI_METHODID_DSTS2;
1568
1569        /* CWAP allow to define the behavior of the Fn+F2 key,
1570         * this method doesn't seems to be present on Eee PCs */
1571        if (asus->driver->quirks->wapf >= 0)
1572                asus_wmi_set_devstate(ASUS_WMI_DEVID_CWAP,
1573                                      asus->driver->quirks->wapf, NULL);
1574
1575        return asus_wmi_sysfs_init(asus->platform_device);
1576}
1577
1578static void asus_wmi_platform_exit(struct asus_wmi *asus)
1579{
1580        asus_wmi_sysfs_exit(asus->platform_device);
1581}
1582
1583/*
1584 * debugfs
1585 */
1586struct asus_wmi_debugfs_node {
1587        struct asus_wmi *asus;
1588        char *name;
1589        int (*show) (struct seq_file *m, void *data);
1590};
1591
1592static int show_dsts(struct seq_file *m, void *data)
1593{
1594        struct asus_wmi *asus = m->private;
1595        int err;
1596        u32 retval = -1;
1597
1598        err = asus_wmi_get_devstate(asus, asus->debug.dev_id, &retval);
1599
1600        if (err < 0)
1601                return err;
1602
1603        seq_printf(m, "DSTS(%#x) = %#x\n", asus->debug.dev_id, retval);
1604
1605        return 0;
1606}
1607
1608static int show_devs(struct seq_file *m, void *data)
1609{
1610        struct asus_wmi *asus = m->private;
1611        int err;
1612        u32 retval = -1;
1613
1614        err = asus_wmi_set_devstate(asus->debug.dev_id, asus->debug.ctrl_param,
1615                                    &retval);
1616
1617        if (err < 0)
1618                return err;
1619
1620        seq_printf(m, "DEVS(%#x, %#x) = %#x\n", asus->debug.dev_id,
1621                   asus->debug.ctrl_param, retval);
1622
1623        return 0;
1624}
1625
1626static int show_call(struct seq_file *m, void *data)
1627{
1628        struct asus_wmi *asus = m->private;
1629        struct bios_args args = {
1630                .arg0 = asus->debug.dev_id,
1631                .arg1 = asus->debug.ctrl_param,
1632        };
1633        struct acpi_buffer input = { (acpi_size) sizeof(args), &args };
1634        struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
1635        union acpi_object *obj;
1636        acpi_status status;
1637
1638        status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID,
1639                                     1, asus->debug.method_id,
1640                                     &input, &output);
1641
1642        if (ACPI_FAILURE(status))
1643                return -EIO;
1644
1645        obj = (union acpi_object *)output.pointer;
1646        if (obj && obj->type == ACPI_TYPE_INTEGER)
1647                seq_printf(m, "%#x(%#x, %#x) = %#x\n", asus->debug.method_id,
1648                           asus->debug.dev_id, asus->debug.ctrl_param,
1649                           (u32) obj->integer.value);
1650        else
1651                seq_printf(m, "%#x(%#x, %#x) = t:%d\n", asus->debug.method_id,
1652                           asus->debug.dev_id, asus->debug.ctrl_param,
1653                           obj ? obj->type : -1);
1654
1655        kfree(obj);
1656
1657        return 0;
1658}
1659
1660static struct asus_wmi_debugfs_node asus_wmi_debug_files[] = {
1661        {NULL, "devs", show_devs},
1662        {NULL, "dsts", show_dsts},
1663        {NULL, "call", show_call},
1664};
1665
1666static int asus_wmi_debugfs_open(struct inode *inode, struct file *file)
1667{
1668        struct asus_wmi_debugfs_node *node = inode->i_private;
1669
1670        return single_open(file, node->show, node->asus);
1671}
1672
1673static const struct file_operations asus_wmi_debugfs_io_ops = {
1674        .owner = THIS_MODULE,
1675        .open = asus_wmi_debugfs_open,
1676        .read = seq_read,
1677        .llseek = seq_lseek,
1678        .release = single_release,
1679};
1680
1681static void asus_wmi_debugfs_exit(struct asus_wmi *asus)
1682{
1683        debugfs_remove_recursive(asus->debug.root);
1684}
1685
1686static int asus_wmi_debugfs_init(struct asus_wmi *asus)
1687{
1688        struct dentry *dent;
1689        int i;
1690
1691        asus->debug.root = debugfs_create_dir(asus->driver->name, NULL);
1692        if (!asus->debug.root) {
1693                pr_err("failed to create debugfs directory\n");
1694                goto error_debugfs;
1695        }
1696
1697        dent = debugfs_create_x32("method_id", S_IRUGO | S_IWUSR,
1698                                  asus->debug.root, &asus->debug.method_id);
1699        if (!dent)
1700                goto error_debugfs;
1701
1702        dent = debugfs_create_x32("dev_id", S_IRUGO | S_IWUSR,
1703                                  asus->debug.root, &asus->debug.dev_id);
1704        if (!dent)
1705                goto error_debugfs;
1706
1707        dent = debugfs_create_x32("ctrl_param", S_IRUGO | S_IWUSR,
1708                                  asus->debug.root, &asus->debug.ctrl_param);
1709        if (!dent)
1710                goto error_debugfs;
1711
1712        for (i = 0; i < ARRAY_SIZE(asus_wmi_debug_files); i++) {
1713                struct asus_wmi_debugfs_node *node = &asus_wmi_debug_files[i];
1714
1715                node->asus = asus;
1716                dent = debugfs_create_file(node->name, S_IFREG | S_IRUGO,
1717                                           asus->debug.root, node,
1718                                           &asus_wmi_debugfs_io_ops);
1719                if (!dent) {
1720                        pr_err("failed to create debug file: %s\n", node->name);
1721                        goto error_debugfs;
1722                }
1723        }
1724
1725        return 0;
1726
1727error_debugfs:
1728        asus_wmi_debugfs_exit(asus);
1729        return -ENOMEM;
1730}
1731
1732/*
1733 * WMI Driver
1734 */
1735static int asus_wmi_add(struct platform_device *pdev)
1736{
1737        struct platform_driver *pdrv = to_platform_driver(pdev->dev.driver);
1738        struct asus_wmi_driver *wdrv = to_asus_wmi_driver(pdrv);
1739        struct asus_wmi *asus;
1740        acpi_status status;
1741        int err;
1742        u32 result;
1743
1744        asus = kzalloc(sizeof(struct asus_wmi), GFP_KERNEL);
1745        if (!asus)
1746                return -ENOMEM;
1747
1748        asus->driver = wdrv;
1749        asus->platform_device = pdev;
1750        wdrv->platform_device = pdev;
1751        platform_set_drvdata(asus->platform_device, asus);
1752
1753        if (wdrv->detect_quirks)
1754                wdrv->detect_quirks(asus->driver);
1755
1756        err = asus_wmi_platform_init(asus);
1757        if (err)
1758                goto fail_platform;
1759
1760        err = asus_wmi_input_init(asus);
1761        if (err)
1762                goto fail_input;
1763
1764        err = asus_wmi_hwmon_init(asus);
1765        if (err)
1766                goto fail_hwmon;
1767
1768        err = asus_wmi_led_init(asus);
1769        if (err)
1770                goto fail_leds;
1771
1772        err = asus_wmi_rfkill_init(asus);
1773        if (err)
1774                goto fail_rfkill;
1775
1776        if (asus->driver->quirks->wmi_backlight_power)
1777                acpi_video_dmi_promote_vendor();
1778        if (!acpi_video_backlight_support()) {
1779                pr_info("Disabling ACPI video driver\n");
1780                acpi_video_unregister();
1781                err = asus_wmi_backlight_init(asus);
1782                if (err && err != -ENODEV)
1783                        goto fail_backlight;
1784        } else
1785                pr_info("Backlight controlled by ACPI video driver\n");
1786
1787        status = wmi_install_notify_handler(asus->driver->event_guid,
1788                                            asus_wmi_notify, asus);
1789        if (ACPI_FAILURE(status)) {
1790                pr_err("Unable to register notify handler - %d\n", status);
1791                err = -ENODEV;
1792                goto fail_wmi_handler;
1793        }
1794
1795        err = asus_wmi_debugfs_init(asus);
1796        if (err)
1797                goto fail_debugfs;
1798
1799        asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WLAN, &result);
1800        if (result & (ASUS_WMI_DSTS_PRESENCE_BIT | ASUS_WMI_DSTS_USER_BIT))
1801                asus->driver->wlan_ctrl_by_user = 1;
1802
1803        return 0;
1804
1805fail_debugfs:
1806        wmi_remove_notify_handler(asus->driver->event_guid);
1807fail_wmi_handler:
1808        asus_wmi_backlight_exit(asus);
1809fail_backlight:
1810        asus_wmi_rfkill_exit(asus);
1811fail_rfkill:
1812        asus_wmi_led_exit(asus);
1813fail_leds:
1814fail_hwmon:
1815        asus_wmi_input_exit(asus);
1816fail_input:
1817        asus_wmi_platform_exit(asus);
1818fail_platform:
1819        kfree(asus);
1820        return err;
1821}
1822
1823static int asus_wmi_remove(struct platform_device *device)
1824{
1825        struct asus_wmi *asus;
1826
1827        asus = platform_get_drvdata(device);
1828        wmi_remove_notify_handler(asus->driver->event_guid);
1829        asus_wmi_backlight_exit(asus);
1830        asus_wmi_input_exit(asus);
1831        asus_wmi_led_exit(asus);
1832        asus_wmi_rfkill_exit(asus);
1833        asus_wmi_debugfs_exit(asus);
1834        asus_wmi_platform_exit(asus);
1835
1836        kfree(asus);
1837        return 0;
1838}
1839
1840/*
1841 * Platform driver - hibernate/resume callbacks
1842 */
1843static int asus_hotk_thaw(struct device *device)
1844{
1845        struct asus_wmi *asus = dev_get_drvdata(device);
1846
1847        if (asus->wlan.rfkill) {
1848                bool wlan;
1849
1850                /*
1851                 * Work around bios bug - acpi _PTS turns off the wireless led
1852                 * during suspend.  Normally it restores it on resume, but
1853                 * we should kick it ourselves in case hibernation is aborted.
1854                 */
1855                wlan = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WLAN);
1856                asus_wmi_set_devstate(ASUS_WMI_DEVID_WLAN, wlan, NULL);
1857        }
1858
1859        return 0;
1860}
1861
1862static int asus_hotk_restore(struct device *device)
1863{
1864        struct asus_wmi *asus = dev_get_drvdata(device);
1865        int bl;
1866
1867        /* Refresh both wlan rfkill state and pci hotplug */
1868        if (asus->wlan.rfkill)
1869                asus_rfkill_hotplug(asus);
1870
1871        if (asus->bluetooth.rfkill) {
1872                bl = !asus_wmi_get_devstate_simple(asus,
1873                                                   ASUS_WMI_DEVID_BLUETOOTH);
1874                rfkill_set_sw_state(asus->bluetooth.rfkill, bl);
1875        }
1876        if (asus->wimax.rfkill) {
1877                bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WIMAX);
1878                rfkill_set_sw_state(asus->wimax.rfkill, bl);
1879        }
1880        if (asus->wwan3g.rfkill) {
1881                bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WWAN3G);
1882                rfkill_set_sw_state(asus->wwan3g.rfkill, bl);
1883        }
1884        if (asus->gps.rfkill) {
1885                bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_GPS);
1886                rfkill_set_sw_state(asus->gps.rfkill, bl);
1887        }
1888        if (asus->uwb.rfkill) {
1889                bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_UWB);
1890                rfkill_set_sw_state(asus->uwb.rfkill, bl);
1891        }
1892
1893        return 0;
1894}
1895
1896static const struct dev_pm_ops asus_pm_ops = {
1897        .thaw = asus_hotk_thaw,
1898        .restore = asus_hotk_restore,
1899};
1900
1901static int asus_wmi_probe(struct platform_device *pdev)
1902{
1903        struct platform_driver *pdrv = to_platform_driver(pdev->dev.driver);
1904        struct asus_wmi_driver *wdrv = to_asus_wmi_driver(pdrv);
1905        int ret;
1906
1907        if (!wmi_has_guid(ASUS_WMI_MGMT_GUID)) {
1908                pr_warn("Management GUID not found\n");
1909                return -ENODEV;
1910        }
1911
1912        if (wdrv->event_guid && !wmi_has_guid(wdrv->event_guid)) {
1913                pr_warn("Event GUID not found\n");
1914                return -ENODEV;
1915        }
1916
1917        if (wdrv->probe) {
1918                ret = wdrv->probe(pdev);
1919                if (ret)
1920                        return ret;
1921        }
1922
1923        return asus_wmi_add(pdev);
1924}
1925
1926static bool used;
1927
1928int __init_or_module asus_wmi_register_driver(struct asus_wmi_driver *driver)
1929{
1930        struct platform_driver *platform_driver;
1931        struct platform_device *platform_device;
1932
1933        if (used)
1934                return -EBUSY;
1935
1936        platform_driver = &driver->platform_driver;
1937        platform_driver->remove = asus_wmi_remove;
1938        platform_driver->driver.owner = driver->owner;
1939        platform_driver->driver.name = driver->name;
1940        platform_driver->driver.pm = &asus_pm_ops;
1941
1942        platform_device = platform_create_bundle(platform_driver,
1943                                                 asus_wmi_probe,
1944                                                 NULL, 0, NULL, 0);
1945        if (IS_ERR(platform_device))
1946                return PTR_ERR(platform_device);
1947
1948        used = true;
1949        return 0;
1950}
1951EXPORT_SYMBOL_GPL(asus_wmi_register_driver);
1952
1953void asus_wmi_unregister_driver(struct asus_wmi_driver *driver)
1954{
1955        platform_device_unregister(driver->platform_device);
1956        platform_driver_unregister(&driver->platform_driver);
1957        used = false;
1958}
1959EXPORT_SYMBOL_GPL(asus_wmi_unregister_driver);
1960
1961static int __init asus_wmi_init(void)
1962{
1963        if (!wmi_has_guid(ASUS_WMI_MGMT_GUID)) {
1964                pr_info("Asus Management GUID not found\n");
1965                return -ENODEV;
1966        }
1967
1968        pr_info("ASUS WMI generic driver loaded\n");
1969        return 0;
1970}
1971
1972static void __exit asus_wmi_exit(void)
1973{
1974        pr_info("ASUS WMI generic driver unloaded\n");
1975}
1976
1977module_init(asus_wmi_init);
1978module_exit(asus_wmi_exit);
1979