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 & 0x7F;
 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_stop_and_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 &&
 788            asus->driver->quirks->hotplug_wireless)
 789                *rfkill = rfkill_alloc(name, &asus->platform_device->dev, type,
 790                                       &asus_rfkill_wlan_ops, arfkill);
 791        else
 792                *rfkill = rfkill_alloc(name, &asus->platform_device->dev, type,
 793                                       &asus_rfkill_ops, arfkill);
 794
 795        if (!*rfkill)
 796                return -EINVAL;
 797
 798        rfkill_init_sw_state(*rfkill, !result);
 799        result = rfkill_register(*rfkill);
 800        if (result) {
 801                rfkill_destroy(*rfkill);
 802                *rfkill = NULL;
 803                return result;
 804        }
 805        return 0;
 806}
 807
 808static void asus_wmi_rfkill_exit(struct asus_wmi *asus)
 809{
 810        asus_unregister_rfkill_notifier(asus, "\\_SB.PCI0.P0P5");
 811        asus_unregister_rfkill_notifier(asus, "\\_SB.PCI0.P0P6");
 812        asus_unregister_rfkill_notifier(asus, "\\_SB.PCI0.P0P7");
 813        if (asus->wlan.rfkill) {
 814                rfkill_unregister(asus->wlan.rfkill);
 815                rfkill_destroy(asus->wlan.rfkill);
 816                asus->wlan.rfkill = NULL;
 817        }
 818        /*
 819         * Refresh pci hotplug in case the rfkill state was changed after
 820         * asus_unregister_rfkill_notifier()
 821         */
 822        asus_rfkill_hotplug(asus);
 823        if (asus->hotplug_slot)
 824                pci_hp_deregister(asus->hotplug_slot);
 825        if (asus->hotplug_workqueue)
 826                destroy_workqueue(asus->hotplug_workqueue);
 827
 828        if (asus->bluetooth.rfkill) {
 829                rfkill_unregister(asus->bluetooth.rfkill);
 830                rfkill_destroy(asus->bluetooth.rfkill);
 831                asus->bluetooth.rfkill = NULL;
 832        }
 833        if (asus->wimax.rfkill) {
 834                rfkill_unregister(asus->wimax.rfkill);
 835                rfkill_destroy(asus->wimax.rfkill);
 836                asus->wimax.rfkill = NULL;
 837        }
 838        if (asus->wwan3g.rfkill) {
 839                rfkill_unregister(asus->wwan3g.rfkill);
 840                rfkill_destroy(asus->wwan3g.rfkill);
 841                asus->wwan3g.rfkill = NULL;
 842        }
 843        if (asus->gps.rfkill) {
 844                rfkill_unregister(asus->gps.rfkill);
 845                rfkill_destroy(asus->gps.rfkill);
 846                asus->gps.rfkill = NULL;
 847        }
 848        if (asus->uwb.rfkill) {
 849                rfkill_unregister(asus->uwb.rfkill);
 850                rfkill_destroy(asus->uwb.rfkill);
 851                asus->uwb.rfkill = NULL;
 852        }
 853}
 854
 855static int asus_wmi_rfkill_init(struct asus_wmi *asus)
 856{
 857        int result = 0;
 858
 859        mutex_init(&asus->hotplug_lock);
 860        mutex_init(&asus->wmi_lock);
 861
 862        result = asus_new_rfkill(asus, &asus->wlan, "asus-wlan",
 863                                 RFKILL_TYPE_WLAN, ASUS_WMI_DEVID_WLAN);
 864
 865        if (result && result != -ENODEV)
 866                goto exit;
 867
 868        result = asus_new_rfkill(asus, &asus->bluetooth,
 869                                 "asus-bluetooth", RFKILL_TYPE_BLUETOOTH,
 870                                 ASUS_WMI_DEVID_BLUETOOTH);
 871
 872        if (result && result != -ENODEV)
 873                goto exit;
 874
 875        result = asus_new_rfkill(asus, &asus->wimax, "asus-wimax",
 876                                 RFKILL_TYPE_WIMAX, ASUS_WMI_DEVID_WIMAX);
 877
 878        if (result && result != -ENODEV)
 879                goto exit;
 880
 881        result = asus_new_rfkill(asus, &asus->wwan3g, "asus-wwan3g",
 882                                 RFKILL_TYPE_WWAN, ASUS_WMI_DEVID_WWAN3G);
 883
 884        if (result && result != -ENODEV)
 885                goto exit;
 886
 887        result = asus_new_rfkill(asus, &asus->gps, "asus-gps",
 888                                 RFKILL_TYPE_GPS, ASUS_WMI_DEVID_GPS);
 889
 890        if (result && result != -ENODEV)
 891                goto exit;
 892
 893        result = asus_new_rfkill(asus, &asus->uwb, "asus-uwb",
 894                                 RFKILL_TYPE_UWB, ASUS_WMI_DEVID_UWB);
 895
 896        if (result && result != -ENODEV)
 897                goto exit;
 898
 899        if (!asus->driver->quirks->hotplug_wireless)
 900                goto exit;
 901
 902        result = asus_setup_pci_hotplug(asus);
 903        /*
 904         * If we get -EBUSY then something else is handling the PCI hotplug -
 905         * don't fail in this case
 906         */
 907        if (result == -EBUSY)
 908                result = 0;
 909
 910        asus_register_rfkill_notifier(asus, "\\_SB.PCI0.P0P5");
 911        asus_register_rfkill_notifier(asus, "\\_SB.PCI0.P0P6");
 912        asus_register_rfkill_notifier(asus, "\\_SB.PCI0.P0P7");
 913        /*
 914         * Refresh pci hotplug in case the rfkill state was changed during
 915         * setup.
 916         */
 917        asus_rfkill_hotplug(asus);
 918
 919exit:
 920        if (result && result != -ENODEV)
 921                asus_wmi_rfkill_exit(asus);
 922
 923        if (result == -ENODEV)
 924                result = 0;
 925
 926        return result;
 927}
 928
 929/*
 930 * Hwmon device
 931 */
 932static ssize_t asus_hwmon_pwm1(struct device *dev,
 933                               struct device_attribute *attr,
 934                               char *buf)
 935{
 936        struct asus_wmi *asus = dev_get_drvdata(dev);
 937        u32 value;
 938        int err;
 939
 940        err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_FAN_CTRL, &value);
 941
 942        if (err < 0)
 943                return err;
 944
 945        value &= 0xFF;
 946
 947        if (value == 1) /* Low Speed */
 948                value = 85;
 949        else if (value == 2)
 950                value = 170;
 951        else if (value == 3)
 952                value = 255;
 953        else if (value != 0) {
 954                pr_err("Unknown fan speed %#x", value);
 955                value = -1;
 956        }
 957
 958        return sprintf(buf, "%d\n", value);
 959}
 960
 961static ssize_t asus_hwmon_temp1(struct device *dev,
 962                                struct device_attribute *attr,
 963                                char *buf)
 964{
 965        struct asus_wmi *asus = dev_get_drvdata(dev);
 966        u32 value;
 967        int err;
 968
 969        err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_THERMAL_CTRL, &value);
 970
 971        if (err < 0)
 972                return err;
 973
 974        value = KELVIN_TO_CELSIUS((value & 0xFFFF)) * 1000;
 975
 976        return sprintf(buf, "%d\n", value);
 977}
 978
 979static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO, asus_hwmon_pwm1, NULL, 0);
 980static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, asus_hwmon_temp1, NULL, 0);
 981
 982static ssize_t
 983show_name(struct device *dev, struct device_attribute *attr, char *buf)
 984{
 985        return sprintf(buf, "asus\n");
 986}
 987static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0);
 988
 989static struct attribute *hwmon_attributes[] = {
 990        &sensor_dev_attr_pwm1.dev_attr.attr,
 991        &sensor_dev_attr_temp1_input.dev_attr.attr,
 992        &sensor_dev_attr_name.dev_attr.attr,
 993        NULL
 994};
 995
 996static umode_t asus_hwmon_sysfs_is_visible(struct kobject *kobj,
 997                                          struct attribute *attr, int idx)
 998{
 999        struct device *dev = container_of(kobj, struct device, kobj);
1000        struct platform_device *pdev = to_platform_device(dev->parent);
1001        struct asus_wmi *asus = platform_get_drvdata(pdev);
1002        bool ok = true;
1003        int dev_id = -1;
1004        u32 value = ASUS_WMI_UNSUPPORTED_METHOD;
1005
1006        if (attr == &sensor_dev_attr_pwm1.dev_attr.attr)
1007                dev_id = ASUS_WMI_DEVID_FAN_CTRL;
1008        else if (attr == &sensor_dev_attr_temp1_input.dev_attr.attr)
1009                dev_id = ASUS_WMI_DEVID_THERMAL_CTRL;
1010
1011        if (dev_id != -1) {
1012                int err = asus_wmi_get_devstate(asus, dev_id, &value);
1013
1014                if (err < 0)
1015                        return 0; /* can't return negative here */
1016        }
1017
1018        if (dev_id == ASUS_WMI_DEVID_FAN_CTRL) {
1019                /*
1020                 * We need to find a better way, probably using sfun,
1021                 * bits or spec ...
1022                 * Currently we disable it if:
1023                 * - ASUS_WMI_UNSUPPORTED_METHOD is returned
1024                 * - reverved bits are non-zero
1025                 * - sfun and presence bit are not set
1026                 */
1027                if (value == ASUS_WMI_UNSUPPORTED_METHOD || value & 0xFFF80000
1028                    || (!asus->sfun && !(value & ASUS_WMI_DSTS_PRESENCE_BIT)))
1029                        ok = false;
1030        } else if (dev_id == ASUS_WMI_DEVID_THERMAL_CTRL) {
1031                /* If value is zero, something is clearly wrong */
1032                if (value == 0)
1033                        ok = false;
1034        }
1035
1036        return ok ? attr->mode : 0;
1037}
1038
1039static struct attribute_group hwmon_attribute_group = {
1040        .is_visible = asus_hwmon_sysfs_is_visible,
1041        .attrs = hwmon_attributes
1042};
1043
1044static void asus_wmi_hwmon_exit(struct asus_wmi *asus)
1045{
1046        struct device *hwmon;
1047
1048        hwmon = asus->hwmon_device;
1049        if (!hwmon)
1050                return;
1051        sysfs_remove_group(&hwmon->kobj, &hwmon_attribute_group);
1052        hwmon_device_unregister(hwmon);
1053        asus->hwmon_device = NULL;
1054}
1055
1056static int asus_wmi_hwmon_init(struct asus_wmi *asus)
1057{
1058        struct device *hwmon;
1059        int result;
1060
1061        hwmon = hwmon_device_register(&asus->platform_device->dev);
1062        if (IS_ERR(hwmon)) {
1063                pr_err("Could not register asus hwmon device\n");
1064                return PTR_ERR(hwmon);
1065        }
1066        dev_set_drvdata(hwmon, asus);
1067        asus->hwmon_device = hwmon;
1068        result = sysfs_create_group(&hwmon->kobj, &hwmon_attribute_group);
1069        if (result)
1070                asus_wmi_hwmon_exit(asus);
1071        return result;
1072}
1073
1074/*
1075 * Backlight
1076 */
1077static int read_backlight_power(struct asus_wmi *asus)
1078{
1079        int ret;
1080        if (asus->driver->quirks->store_backlight_power)
1081                ret = !asus->driver->panel_power;
1082        else
1083                ret = asus_wmi_get_devstate_simple(asus,
1084                                                   ASUS_WMI_DEVID_BACKLIGHT);
1085
1086        if (ret < 0)
1087                return ret;
1088
1089        return ret ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
1090}
1091
1092static int read_brightness_max(struct asus_wmi *asus)
1093{
1094        u32 retval;
1095        int err;
1096
1097        err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_BRIGHTNESS, &retval);
1098
1099        if (err < 0)
1100                return err;
1101
1102        retval = retval & ASUS_WMI_DSTS_MAX_BRIGTH_MASK;
1103        retval >>= 8;
1104
1105        if (!retval)
1106                return -ENODEV;
1107
1108        return retval;
1109}
1110
1111static int read_brightness(struct backlight_device *bd)
1112{
1113        struct asus_wmi *asus = bl_get_data(bd);
1114        u32 retval;
1115        int err;
1116
1117        err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_BRIGHTNESS, &retval);
1118
1119        if (err < 0)
1120                return err;
1121
1122        return retval & ASUS_WMI_DSTS_BRIGHTNESS_MASK;
1123}
1124
1125static u32 get_scalar_command(struct backlight_device *bd)
1126{
1127        struct asus_wmi *asus = bl_get_data(bd);
1128        u32 ctrl_param = 0;
1129
1130        if ((asus->driver->brightness < bd->props.brightness) ||
1131            bd->props.brightness == bd->props.max_brightness)
1132                ctrl_param = 0x00008001;
1133        else if ((asus->driver->brightness > bd->props.brightness) ||
1134                 bd->props.brightness == 0)
1135                ctrl_param = 0x00008000;
1136
1137        asus->driver->brightness = bd->props.brightness;
1138
1139        return ctrl_param;
1140}
1141
1142static int update_bl_status(struct backlight_device *bd)
1143{
1144        struct asus_wmi *asus = bl_get_data(bd);
1145        u32 ctrl_param;
1146        int power, err = 0;
1147
1148        power = read_backlight_power(asus);
1149        if (power != -ENODEV && bd->props.power != power) {
1150                ctrl_param = !!(bd->props.power == FB_BLANK_UNBLANK);
1151                err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BACKLIGHT,
1152                                            ctrl_param, NULL);
1153                if (asus->driver->quirks->store_backlight_power)
1154                        asus->driver->panel_power = bd->props.power;
1155
1156                /* When using scalar brightness, updating the brightness
1157                 * will mess with the backlight power */
1158                if (asus->driver->quirks->scalar_panel_brightness)
1159                        return err;
1160        }
1161
1162        if (asus->driver->quirks->scalar_panel_brightness)
1163                ctrl_param = get_scalar_command(bd);
1164        else
1165                ctrl_param = bd->props.brightness;
1166
1167        err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BRIGHTNESS,
1168                                    ctrl_param, NULL);
1169
1170        return err;
1171}
1172
1173static const struct backlight_ops asus_wmi_bl_ops = {
1174        .get_brightness = read_brightness,
1175        .update_status = update_bl_status,
1176};
1177
1178static int asus_wmi_backlight_notify(struct asus_wmi *asus, int code)
1179{
1180        struct backlight_device *bd = asus->backlight_device;
1181        int old = bd->props.brightness;
1182        int new = old;
1183
1184        if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX)
1185                new = code - NOTIFY_BRNUP_MIN + 1;
1186        else if (code >= NOTIFY_BRNDOWN_MIN && code <= NOTIFY_BRNDOWN_MAX)
1187                new = code - NOTIFY_BRNDOWN_MIN;
1188
1189        bd->props.brightness = new;
1190        backlight_update_status(bd);
1191        backlight_force_update(bd, BACKLIGHT_UPDATE_HOTKEY);
1192
1193        return old;
1194}
1195
1196static int asus_wmi_backlight_init(struct asus_wmi *asus)
1197{
1198        struct backlight_device *bd;
1199        struct backlight_properties props;
1200        int max;
1201        int power;
1202
1203        max = read_brightness_max(asus);
1204
1205        if (max == -ENODEV)
1206                max = 0;
1207        else if (max < 0)
1208                return max;
1209
1210        power = read_backlight_power(asus);
1211
1212        if (power == -ENODEV)
1213                power = FB_BLANK_UNBLANK;
1214        else if (power < 0)
1215                return power;
1216
1217        memset(&props, 0, sizeof(struct backlight_properties));
1218        props.type = BACKLIGHT_PLATFORM;
1219        props.max_brightness = max;
1220        bd = backlight_device_register(asus->driver->name,
1221                                       &asus->platform_device->dev, asus,
1222                                       &asus_wmi_bl_ops, &props);
1223        if (IS_ERR(bd)) {
1224                pr_err("Could not register backlight device\n");
1225                return PTR_ERR(bd);
1226        }
1227
1228        asus->backlight_device = bd;
1229
1230        if (asus->driver->quirks->store_backlight_power)
1231                asus->driver->panel_power = power;
1232
1233        bd->props.brightness = read_brightness(bd);
1234        bd->props.power = power;
1235        backlight_update_status(bd);
1236
1237        asus->driver->brightness = bd->props.brightness;
1238
1239        return 0;
1240}
1241
1242static void asus_wmi_backlight_exit(struct asus_wmi *asus)
1243{
1244        if (asus->backlight_device)
1245                backlight_device_unregister(asus->backlight_device);
1246
1247        asus->backlight_device = NULL;
1248}
1249
1250static void asus_wmi_notify(u32 value, void *context)
1251{
1252        struct asus_wmi *asus = context;
1253        struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
1254        union acpi_object *obj;
1255        acpi_status status;
1256        int code;
1257        int orig_code;
1258        unsigned int key_value = 1;
1259        bool autorelease = 1;
1260
1261        status = wmi_get_event_data(value, &response);
1262        if (status != AE_OK) {
1263                pr_err("bad event status 0x%x\n", status);
1264                return;
1265        }
1266
1267        obj = (union acpi_object *)response.pointer;
1268
1269        if (!obj || obj->type != ACPI_TYPE_INTEGER)
1270                goto exit;
1271
1272        code = obj->integer.value;
1273        orig_code = code;
1274
1275        if (asus->driver->key_filter) {
1276                asus->driver->key_filter(asus->driver, &code, &key_value,
1277                                         &autorelease);
1278                if (code == ASUS_WMI_KEY_IGNORE)
1279                        goto exit;
1280        }
1281
1282        if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX)
1283                code = NOTIFY_BRNUP_MIN;
1284        else if (code >= NOTIFY_BRNDOWN_MIN &&
1285                 code <= NOTIFY_BRNDOWN_MAX)
1286                code = NOTIFY_BRNDOWN_MIN;
1287
1288        if (code == NOTIFY_BRNUP_MIN || code == NOTIFY_BRNDOWN_MIN) {
1289                if (!acpi_video_backlight_support())
1290                        asus_wmi_backlight_notify(asus, orig_code);
1291        } else if (!sparse_keymap_report_event(asus->inputdev, code,
1292                                               key_value, autorelease))
1293                pr_info("Unknown key %x pressed\n", code);
1294
1295exit:
1296        kfree(obj);
1297}
1298
1299/*
1300 * Sys helpers
1301 */
1302static int parse_arg(const char *buf, unsigned long count, int *val)
1303{
1304        if (!count)
1305                return 0;
1306        if (sscanf(buf, "%i", val) != 1)
1307                return -EINVAL;
1308        return count;
1309}
1310
1311static ssize_t store_sys_wmi(struct asus_wmi *asus, int devid,
1312                             const char *buf, size_t count)
1313{
1314        u32 retval;
1315        int rv, err, value;
1316
1317        value = asus_wmi_get_devstate_simple(asus, devid);
1318        if (value == -ENODEV)   /* Check device presence */
1319                return value;
1320
1321        rv = parse_arg(buf, count, &value);
1322        err = asus_wmi_set_devstate(devid, value, &retval);
1323
1324        if (err < 0)
1325                return err;
1326
1327        return rv;
1328}
1329
1330static ssize_t show_sys_wmi(struct asus_wmi *asus, int devid, char *buf)
1331{
1332        int value = asus_wmi_get_devstate_simple(asus, devid);
1333
1334        if (value < 0)
1335                return value;
1336
1337        return sprintf(buf, "%d\n", value);
1338}
1339
1340#define ASUS_WMI_CREATE_DEVICE_ATTR(_name, _mode, _cm)                  \
1341        static ssize_t show_##_name(struct device *dev,                 \
1342                                    struct device_attribute *attr,      \
1343                                    char *buf)                          \
1344        {                                                               \
1345                struct asus_wmi *asus = dev_get_drvdata(dev);           \
1346                                                                        \
1347                return show_sys_wmi(asus, _cm, buf);                    \
1348        }                                                               \
1349        static ssize_t store_##_name(struct device *dev,                \
1350                                     struct device_attribute *attr,     \
1351                                     const char *buf, size_t count)     \
1352        {                                                               \
1353                struct asus_wmi *asus = dev_get_drvdata(dev);           \
1354                                                                        \
1355                return store_sys_wmi(asus, _cm, buf, count);            \
1356        }                                                               \
1357        static struct device_attribute dev_attr_##_name = {             \
1358                .attr = {                                               \
1359                        .name = __stringify(_name),                     \
1360                        .mode = _mode },                                \
1361                .show   = show_##_name,                                 \
1362                .store  = store_##_name,                                \
1363        }
1364
1365ASUS_WMI_CREATE_DEVICE_ATTR(touchpad, 0644, ASUS_WMI_DEVID_TOUCHPAD);
1366ASUS_WMI_CREATE_DEVICE_ATTR(camera, 0644, ASUS_WMI_DEVID_CAMERA);
1367ASUS_WMI_CREATE_DEVICE_ATTR(cardr, 0644, ASUS_WMI_DEVID_CARDREADER);
1368
1369static ssize_t store_cpufv(struct device *dev, struct device_attribute *attr,
1370                           const char *buf, size_t count)
1371{
1372        int value, rv;
1373
1374        if (!count || sscanf(buf, "%i", &value) != 1)
1375                return -EINVAL;
1376        if (value < 0 || value > 2)
1377                return -EINVAL;
1378
1379        rv = asus_wmi_evaluate_method(ASUS_WMI_METHODID_CFVS, value, 0, NULL);
1380        if (rv < 0)
1381                return rv;
1382
1383        return count;
1384}
1385
1386static DEVICE_ATTR(cpufv, S_IRUGO | S_IWUSR, NULL, store_cpufv);
1387
1388static struct attribute *platform_attributes[] = {
1389        &dev_attr_cpufv.attr,
1390        &dev_attr_camera.attr,
1391        &dev_attr_cardr.attr,
1392        &dev_attr_touchpad.attr,
1393        NULL
1394};
1395
1396static umode_t asus_sysfs_is_visible(struct kobject *kobj,
1397                                    struct attribute *attr, int idx)
1398{
1399        struct device *dev = container_of(kobj, struct device, kobj);
1400        struct platform_device *pdev = to_platform_device(dev);
1401        struct asus_wmi *asus = platform_get_drvdata(pdev);
1402        bool ok = true;
1403        int devid = -1;
1404
1405        if (attr == &dev_attr_camera.attr)
1406                devid = ASUS_WMI_DEVID_CAMERA;
1407        else if (attr == &dev_attr_cardr.attr)
1408                devid = ASUS_WMI_DEVID_CARDREADER;
1409        else if (attr == &dev_attr_touchpad.attr)
1410                devid = ASUS_WMI_DEVID_TOUCHPAD;
1411
1412        if (devid != -1)
1413                ok = !(asus_wmi_get_devstate_simple(asus, devid) < 0);
1414
1415        return ok ? attr->mode : 0;
1416}
1417
1418static struct attribute_group platform_attribute_group = {
1419        .is_visible = asus_sysfs_is_visible,
1420        .attrs = platform_attributes
1421};
1422
1423static void asus_wmi_sysfs_exit(struct platform_device *device)
1424{
1425        sysfs_remove_group(&device->dev.kobj, &platform_attribute_group);
1426}
1427
1428static int asus_wmi_sysfs_init(struct platform_device *device)
1429{
1430        return sysfs_create_group(&device->dev.kobj, &platform_attribute_group);
1431}
1432
1433/*
1434 * Platform device
1435 */
1436static int asus_wmi_platform_init(struct asus_wmi *asus)
1437{
1438        int rv;
1439
1440        /* INIT enable hotkeys on some models */
1441        if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_INIT, 0, 0, &rv))
1442                pr_info("Initialization: %#x", rv);
1443
1444        /* We don't know yet what to do with this version... */
1445        if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_SPEC, 0, 0x9, &rv)) {
1446                pr_info("BIOS WMI version: %d.%d", rv >> 16, rv & 0xFF);
1447                asus->spec = rv;
1448        }
1449
1450        /*
1451         * The SFUN method probably allows the original driver to get the list
1452         * of features supported by a given model. For now, 0x0100 or 0x0800
1453         * bit signifies that the laptop is equipped with a Wi-Fi MiniPCI card.
1454         * The significance of others is yet to be found.
1455         */
1456        if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_SFUN, 0, 0, &rv)) {
1457                pr_info("SFUN value: %#x", rv);
1458                asus->sfun = rv;
1459        }
1460
1461        /*
1462         * Eee PC and Notebooks seems to have different method_id for DSTS,
1463         * but it may also be related to the BIOS's SPEC.
1464         * Note, on most Eeepc, there is no way to check if a method exist
1465         * or note, while on notebooks, they returns 0xFFFFFFFE on failure,
1466         * but once again, SPEC may probably be used for that kind of things.
1467         */
1468        if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS, 0, 0, NULL))
1469                asus->dsts_id = ASUS_WMI_METHODID_DSTS;
1470        else if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS2, 0, 0, NULL))
1471                asus->dsts_id = ASUS_WMI_METHODID_DSTS2;
1472
1473        if (!asus->dsts_id) {
1474                pr_err("Can't find DSTS");
1475                return -ENODEV;
1476        }
1477
1478        /* CWAP allow to define the behavior of the Fn+F2 key,
1479         * this method doesn't seems to be present on Eee PCs */
1480        if (asus->driver->quirks->wapf >= 0)
1481                asus_wmi_set_devstate(ASUS_WMI_DEVID_CWAP,
1482                                      asus->driver->quirks->wapf, NULL);
1483
1484        return asus_wmi_sysfs_init(asus->platform_device);
1485}
1486
1487static void asus_wmi_platform_exit(struct asus_wmi *asus)
1488{
1489        asus_wmi_sysfs_exit(asus->platform_device);
1490}
1491
1492/*
1493 * debugfs
1494 */
1495struct asus_wmi_debugfs_node {
1496        struct asus_wmi *asus;
1497        char *name;
1498        int (*show) (struct seq_file *m, void *data);
1499};
1500
1501static int show_dsts(struct seq_file *m, void *data)
1502{
1503        struct asus_wmi *asus = m->private;
1504        int err;
1505        u32 retval = -1;
1506
1507        err = asus_wmi_get_devstate(asus, asus->debug.dev_id, &retval);
1508
1509        if (err < 0)
1510                return err;
1511
1512        seq_printf(m, "DSTS(%#x) = %#x\n", asus->debug.dev_id, retval);
1513
1514        return 0;
1515}
1516
1517static int show_devs(struct seq_file *m, void *data)
1518{
1519        struct asus_wmi *asus = m->private;
1520        int err;
1521        u32 retval = -1;
1522
1523        err = asus_wmi_set_devstate(asus->debug.dev_id, asus->debug.ctrl_param,
1524                                    &retval);
1525
1526        if (err < 0)
1527                return err;
1528
1529        seq_printf(m, "DEVS(%#x, %#x) = %#x\n", asus->debug.dev_id,
1530                   asus->debug.ctrl_param, retval);
1531
1532        return 0;
1533}
1534
1535static int show_call(struct seq_file *m, void *data)
1536{
1537        struct asus_wmi *asus = m->private;
1538        struct bios_args args = {
1539                .arg0 = asus->debug.dev_id,
1540                .arg1 = asus->debug.ctrl_param,
1541        };
1542        struct acpi_buffer input = { (acpi_size) sizeof(args), &args };
1543        struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
1544        union acpi_object *obj;
1545        acpi_status status;
1546
1547        status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID,
1548                                     1, asus->debug.method_id,
1549                                     &input, &output);
1550
1551        if (ACPI_FAILURE(status))
1552                return -EIO;
1553
1554        obj = (union acpi_object *)output.pointer;
1555        if (obj && obj->type == ACPI_TYPE_INTEGER)
1556                seq_printf(m, "%#x(%#x, %#x) = %#x\n", asus->debug.method_id,
1557                           asus->debug.dev_id, asus->debug.ctrl_param,
1558                           (u32) obj->integer.value);
1559        else
1560                seq_printf(m, "%#x(%#x, %#x) = t:%d\n", asus->debug.method_id,
1561                           asus->debug.dev_id, asus->debug.ctrl_param,
1562                           obj ? obj->type : -1);
1563
1564        kfree(obj);
1565
1566        return 0;
1567}
1568
1569static struct asus_wmi_debugfs_node asus_wmi_debug_files[] = {
1570        {NULL, "devs", show_devs},
1571        {NULL, "dsts", show_dsts},
1572        {NULL, "call", show_call},
1573};
1574
1575static int asus_wmi_debugfs_open(struct inode *inode, struct file *file)
1576{
1577        struct asus_wmi_debugfs_node *node = inode->i_private;
1578
1579        return single_open(file, node->show, node->asus);
1580}
1581
1582static const struct file_operations asus_wmi_debugfs_io_ops = {
1583        .owner = THIS_MODULE,
1584        .open = asus_wmi_debugfs_open,
1585        .read = seq_read,
1586        .llseek = seq_lseek,
1587        .release = single_release,
1588};
1589
1590static void asus_wmi_debugfs_exit(struct asus_wmi *asus)
1591{
1592        debugfs_remove_recursive(asus->debug.root);
1593}
1594
1595static int asus_wmi_debugfs_init(struct asus_wmi *asus)
1596{
1597        struct dentry *dent;
1598        int i;
1599
1600        asus->debug.root = debugfs_create_dir(asus->driver->name, NULL);
1601        if (!asus->debug.root) {
1602                pr_err("failed to create debugfs directory");
1603                goto error_debugfs;
1604        }
1605
1606        dent = debugfs_create_x32("method_id", S_IRUGO | S_IWUSR,
1607                                  asus->debug.root, &asus->debug.method_id);
1608        if (!dent)
1609                goto error_debugfs;
1610
1611        dent = debugfs_create_x32("dev_id", S_IRUGO | S_IWUSR,
1612                                  asus->debug.root, &asus->debug.dev_id);
1613        if (!dent)
1614                goto error_debugfs;
1615
1616        dent = debugfs_create_x32("ctrl_param", S_IRUGO | S_IWUSR,
1617                                  asus->debug.root, &asus->debug.ctrl_param);
1618        if (!dent)
1619                goto error_debugfs;
1620
1621        for (i = 0; i < ARRAY_SIZE(asus_wmi_debug_files); i++) {
1622                struct asus_wmi_debugfs_node *node = &asus_wmi_debug_files[i];
1623
1624                node->asus = asus;
1625                dent = debugfs_create_file(node->name, S_IFREG | S_IRUGO,
1626                                           asus->debug.root, node,
1627                                           &asus_wmi_debugfs_io_ops);
1628                if (!dent) {
1629                        pr_err("failed to create debug file: %s\n", node->name);
1630                        goto error_debugfs;
1631                }
1632        }
1633
1634        return 0;
1635
1636error_debugfs:
1637        asus_wmi_debugfs_exit(asus);
1638        return -ENOMEM;
1639}
1640
1641/*
1642 * WMI Driver
1643 */
1644static int asus_wmi_add(struct platform_device *pdev)
1645{
1646        struct platform_driver *pdrv = to_platform_driver(pdev->dev.driver);
1647        struct asus_wmi_driver *wdrv = to_asus_wmi_driver(pdrv);
1648        struct asus_wmi *asus;
1649        acpi_status status;
1650        int err;
1651
1652        asus = kzalloc(sizeof(struct asus_wmi), GFP_KERNEL);
1653        if (!asus)
1654                return -ENOMEM;
1655
1656        asus->driver = wdrv;
1657        asus->platform_device = pdev;
1658        wdrv->platform_device = pdev;
1659        platform_set_drvdata(asus->platform_device, asus);
1660
1661        if (wdrv->detect_quirks)
1662                wdrv->detect_quirks(asus->driver);
1663
1664        err = asus_wmi_platform_init(asus);
1665        if (err)
1666                goto fail_platform;
1667
1668        err = asus_wmi_input_init(asus);
1669        if (err)
1670                goto fail_input;
1671
1672        err = asus_wmi_hwmon_init(asus);
1673        if (err)
1674                goto fail_hwmon;
1675
1676        err = asus_wmi_led_init(asus);
1677        if (err)
1678                goto fail_leds;
1679
1680        err = asus_wmi_rfkill_init(asus);
1681        if (err)
1682                goto fail_rfkill;
1683
1684        if (!acpi_video_backlight_support()) {
1685                err = asus_wmi_backlight_init(asus);
1686                if (err && err != -ENODEV)
1687                        goto fail_backlight;
1688        } else
1689                pr_info("Backlight controlled by ACPI video driver\n");
1690
1691        status = wmi_install_notify_handler(asus->driver->event_guid,
1692                                            asus_wmi_notify, asus);
1693        if (ACPI_FAILURE(status)) {
1694                pr_err("Unable to register notify handler - %d\n", status);
1695                err = -ENODEV;
1696                goto fail_wmi_handler;
1697        }
1698
1699        err = asus_wmi_debugfs_init(asus);
1700        if (err)
1701                goto fail_debugfs;
1702
1703        return 0;
1704
1705fail_debugfs:
1706        wmi_remove_notify_handler(asus->driver->event_guid);
1707fail_wmi_handler:
1708        asus_wmi_backlight_exit(asus);
1709fail_backlight:
1710        asus_wmi_rfkill_exit(asus);
1711fail_rfkill:
1712        asus_wmi_led_exit(asus);
1713fail_leds:
1714        asus_wmi_hwmon_exit(asus);
1715fail_hwmon:
1716        asus_wmi_input_exit(asus);
1717fail_input:
1718        asus_wmi_platform_exit(asus);
1719fail_platform:
1720        kfree(asus);
1721        return err;
1722}
1723
1724static int asus_wmi_remove(struct platform_device *device)
1725{
1726        struct asus_wmi *asus;
1727
1728        asus = platform_get_drvdata(device);
1729        wmi_remove_notify_handler(asus->driver->event_guid);
1730        asus_wmi_backlight_exit(asus);
1731        asus_wmi_input_exit(asus);
1732        asus_wmi_hwmon_exit(asus);
1733        asus_wmi_led_exit(asus);
1734        asus_wmi_rfkill_exit(asus);
1735        asus_wmi_debugfs_exit(asus);
1736        asus_wmi_platform_exit(asus);
1737
1738        kfree(asus);
1739        return 0;
1740}
1741
1742/*
1743 * Platform driver - hibernate/resume callbacks
1744 */
1745static int asus_hotk_thaw(struct device *device)
1746{
1747        struct asus_wmi *asus = dev_get_drvdata(device);
1748
1749        if (asus->wlan.rfkill) {
1750                bool wlan;
1751
1752                /*
1753                 * Work around bios bug - acpi _PTS turns off the wireless led
1754                 * during suspend.  Normally it restores it on resume, but
1755                 * we should kick it ourselves in case hibernation is aborted.
1756                 */
1757                wlan = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WLAN);
1758                asus_wmi_set_devstate(ASUS_WMI_DEVID_WLAN, wlan, NULL);
1759        }
1760
1761        return 0;
1762}
1763
1764static int asus_hotk_restore(struct device *device)
1765{
1766        struct asus_wmi *asus = dev_get_drvdata(device);
1767        int bl;
1768
1769        /* Refresh both wlan rfkill state and pci hotplug */
1770        if (asus->wlan.rfkill)
1771                asus_rfkill_hotplug(asus);
1772
1773        if (asus->bluetooth.rfkill) {
1774                bl = !asus_wmi_get_devstate_simple(asus,
1775                                                   ASUS_WMI_DEVID_BLUETOOTH);
1776                rfkill_set_sw_state(asus->bluetooth.rfkill, bl);
1777        }
1778        if (asus->wimax.rfkill) {
1779                bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WIMAX);
1780                rfkill_set_sw_state(asus->wimax.rfkill, bl);
1781        }
1782        if (asus->wwan3g.rfkill) {
1783                bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WWAN3G);
1784                rfkill_set_sw_state(asus->wwan3g.rfkill, bl);
1785        }
1786        if (asus->gps.rfkill) {
1787                bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_GPS);
1788                rfkill_set_sw_state(asus->gps.rfkill, bl);
1789        }
1790        if (asus->uwb.rfkill) {
1791                bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_UWB);
1792                rfkill_set_sw_state(asus->uwb.rfkill, bl);
1793        }
1794
1795        return 0;
1796}
1797
1798static const struct dev_pm_ops asus_pm_ops = {
1799        .thaw = asus_hotk_thaw,
1800        .restore = asus_hotk_restore,
1801};
1802
1803static int asus_wmi_probe(struct platform_device *pdev)
1804{
1805        struct platform_driver *pdrv = to_platform_driver(pdev->dev.driver);
1806        struct asus_wmi_driver *wdrv = to_asus_wmi_driver(pdrv);
1807        int ret;
1808
1809        if (!wmi_has_guid(ASUS_WMI_MGMT_GUID)) {
1810                pr_warn("Management GUID not found\n");
1811                return -ENODEV;
1812        }
1813
1814        if (wdrv->event_guid && !wmi_has_guid(wdrv->event_guid)) {
1815                pr_warn("Event GUID not found\n");
1816                return -ENODEV;
1817        }
1818
1819        if (wdrv->probe) {
1820                ret = wdrv->probe(pdev);
1821                if (ret)
1822                        return ret;
1823        }
1824
1825        return asus_wmi_add(pdev);
1826}
1827
1828static bool used;
1829
1830int __init_or_module asus_wmi_register_driver(struct asus_wmi_driver *driver)
1831{
1832        struct platform_driver *platform_driver;
1833        struct platform_device *platform_device;
1834
1835        if (used)
1836                return -EBUSY;
1837
1838        platform_driver = &driver->platform_driver;
1839        platform_driver->remove = asus_wmi_remove;
1840        platform_driver->driver.owner = driver->owner;
1841        platform_driver->driver.name = driver->name;
1842        platform_driver->driver.pm = &asus_pm_ops;
1843
1844        platform_device = platform_create_bundle(platform_driver,
1845                                                 asus_wmi_probe,
1846                                                 NULL, 0, NULL, 0);
1847        if (IS_ERR(platform_device))
1848                return PTR_ERR(platform_device);
1849
1850        used = true;
1851        return 0;
1852}
1853EXPORT_SYMBOL_GPL(asus_wmi_register_driver);
1854
1855void asus_wmi_unregister_driver(struct asus_wmi_driver *driver)
1856{
1857        platform_device_unregister(driver->platform_device);
1858        platform_driver_unregister(&driver->platform_driver);
1859        used = false;
1860}
1861EXPORT_SYMBOL_GPL(asus_wmi_unregister_driver);
1862
1863static int __init asus_wmi_init(void)
1864{
1865        if (!wmi_has_guid(ASUS_WMI_MGMT_GUID)) {
1866                pr_info("Asus Management GUID not found");
1867                return -ENODEV;
1868        }
1869
1870        pr_info("ASUS WMI generic driver loaded");
1871        return 0;
1872}
1873
1874static void __exit asus_wmi_exit(void)
1875{
1876        pr_info("ASUS WMI generic driver unloaded");
1877}
1878
1879module_init(asus_wmi_init);
1880module_exit(asus_wmi_exit);
1881