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