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