linux/drivers/platform/x86/eeepc-laptop.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 *  eeepc-laptop.c - Asus Eee PC extras
   4 *
   5 *  Based on asus_acpi.c as patched for the Eee PC by Asus:
   6 *  ftp://ftp.asus.com/pub/ASUS/EeePC/701/ASUS_ACPI_071126.rar
   7 *  Based on eee.c from eeepc-linux
   8 */
   9
  10#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  11
  12#include <linux/kernel.h>
  13#include <linux/module.h>
  14#include <linux/init.h>
  15#include <linux/types.h>
  16#include <linux/platform_device.h>
  17#include <linux/backlight.h>
  18#include <linux/fb.h>
  19#include <linux/hwmon.h>
  20#include <linux/hwmon-sysfs.h>
  21#include <linux/slab.h>
  22#include <linux/acpi.h>
  23#include <linux/uaccess.h>
  24#include <linux/input.h>
  25#include <linux/input/sparse-keymap.h>
  26#include <linux/rfkill.h>
  27#include <linux/pci.h>
  28#include <linux/pci_hotplug.h>
  29#include <linux/leds.h>
  30#include <linux/dmi.h>
  31#include <acpi/video.h>
  32
  33#define EEEPC_LAPTOP_VERSION    "0.1"
  34#define EEEPC_LAPTOP_NAME       "Eee PC Hotkey Driver"
  35#define EEEPC_LAPTOP_FILE       "eeepc"
  36
  37#define EEEPC_ACPI_CLASS        "hotkey"
  38#define EEEPC_ACPI_DEVICE_NAME  "Hotkey"
  39#define EEEPC_ACPI_HID          "ASUS010"
  40
  41MODULE_AUTHOR("Corentin Chary, Eric Cooper");
  42MODULE_DESCRIPTION(EEEPC_LAPTOP_NAME);
  43MODULE_LICENSE("GPL");
  44
  45static bool hotplug_disabled;
  46
  47module_param(hotplug_disabled, bool, 0444);
  48MODULE_PARM_DESC(hotplug_disabled,
  49                 "Disable hotplug for wireless device. "
  50                 "If your laptop need that, please report to "
  51                 "acpi4asus-user@lists.sourceforge.net.");
  52
  53/*
  54 * Definitions for Asus EeePC
  55 */
  56#define NOTIFY_BRN_MIN  0x20
  57#define NOTIFY_BRN_MAX  0x2f
  58
  59enum {
  60        DISABLE_ASL_WLAN = 0x0001,
  61        DISABLE_ASL_BLUETOOTH = 0x0002,
  62        DISABLE_ASL_IRDA = 0x0004,
  63        DISABLE_ASL_CAMERA = 0x0008,
  64        DISABLE_ASL_TV = 0x0010,
  65        DISABLE_ASL_GPS = 0x0020,
  66        DISABLE_ASL_DISPLAYSWITCH = 0x0040,
  67        DISABLE_ASL_MODEM = 0x0080,
  68        DISABLE_ASL_CARDREADER = 0x0100,
  69        DISABLE_ASL_3G = 0x0200,
  70        DISABLE_ASL_WIMAX = 0x0400,
  71        DISABLE_ASL_HWCF = 0x0800
  72};
  73
  74enum {
  75        CM_ASL_WLAN = 0,
  76        CM_ASL_BLUETOOTH,
  77        CM_ASL_IRDA,
  78        CM_ASL_1394,
  79        CM_ASL_CAMERA,
  80        CM_ASL_TV,
  81        CM_ASL_GPS,
  82        CM_ASL_DVDROM,
  83        CM_ASL_DISPLAYSWITCH,
  84        CM_ASL_PANELBRIGHT,
  85        CM_ASL_BIOSFLASH,
  86        CM_ASL_ACPIFLASH,
  87        CM_ASL_CPUFV,
  88        CM_ASL_CPUTEMPERATURE,
  89        CM_ASL_FANCPU,
  90        CM_ASL_FANCHASSIS,
  91        CM_ASL_USBPORT1,
  92        CM_ASL_USBPORT2,
  93        CM_ASL_USBPORT3,
  94        CM_ASL_MODEM,
  95        CM_ASL_CARDREADER,
  96        CM_ASL_3G,
  97        CM_ASL_WIMAX,
  98        CM_ASL_HWCF,
  99        CM_ASL_LID,
 100        CM_ASL_TYPE,
 101        CM_ASL_PANELPOWER,      /*P901*/
 102        CM_ASL_TPD
 103};
 104
 105static const char *cm_getv[] = {
 106        "WLDG", "BTHG", NULL, NULL,
 107        "CAMG", NULL, NULL, NULL,
 108        NULL, "PBLG", NULL, NULL,
 109        "CFVG", NULL, NULL, NULL,
 110        "USBG", NULL, NULL, "MODG",
 111        "CRDG", "M3GG", "WIMG", "HWCF",
 112        "LIDG", "TYPE", "PBPG", "TPDG"
 113};
 114
 115static const char *cm_setv[] = {
 116        "WLDS", "BTHS", NULL, NULL,
 117        "CAMS", NULL, NULL, NULL,
 118        "SDSP", "PBLS", "HDPS", NULL,
 119        "CFVS", NULL, NULL, NULL,
 120        "USBG", NULL, NULL, "MODS",
 121        "CRDS", "M3GS", "WIMS", NULL,
 122        NULL, NULL, "PBPS", "TPDS"
 123};
 124
 125static const struct key_entry eeepc_keymap[] = {
 126        { KE_KEY, 0x10, { KEY_WLAN } },
 127        { KE_KEY, 0x11, { KEY_WLAN } },
 128        { KE_KEY, 0x12, { KEY_PROG1 } },
 129        { KE_KEY, 0x13, { KEY_MUTE } },
 130        { KE_KEY, 0x14, { KEY_VOLUMEDOWN } },
 131        { KE_KEY, 0x15, { KEY_VOLUMEUP } },
 132        { KE_KEY, 0x16, { KEY_DISPLAY_OFF } },
 133        { KE_KEY, 0x1a, { KEY_COFFEE } },
 134        { KE_KEY, 0x1b, { KEY_ZOOM } },
 135        { KE_KEY, 0x1c, { KEY_PROG2 } },
 136        { KE_KEY, 0x1d, { KEY_PROG3 } },
 137        { KE_KEY, NOTIFY_BRN_MIN, { KEY_BRIGHTNESSDOWN } },
 138        { KE_KEY, NOTIFY_BRN_MAX, { KEY_BRIGHTNESSUP } },
 139        { KE_KEY, 0x30, { KEY_SWITCHVIDEOMODE } },
 140        { KE_KEY, 0x31, { KEY_SWITCHVIDEOMODE } },
 141        { KE_KEY, 0x32, { KEY_SWITCHVIDEOMODE } },
 142        { KE_KEY, 0x37, { KEY_F13 } }, /* Disable Touchpad */
 143        { KE_KEY, 0x38, { KEY_F14 } },
 144        { KE_IGNORE, 0x50, { KEY_RESERVED } }, /* AC plugged */
 145        { KE_IGNORE, 0x51, { KEY_RESERVED } }, /* AC unplugged */
 146        { KE_END, 0 },
 147};
 148
 149/*
 150 * This is the main structure, we can use it to store useful information
 151 */
 152struct eeepc_laptop {
 153        acpi_handle handle;             /* the handle of the acpi device */
 154        u32 cm_supported;               /* the control methods supported
 155                                           by this BIOS */
 156        bool cpufv_disabled;
 157        bool hotplug_disabled;
 158        u16 event_count[128];           /* count for each event */
 159
 160        struct platform_device *platform_device;
 161        struct acpi_device *device;             /* the device we are in */
 162        struct backlight_device *backlight_device;
 163
 164        struct input_dev *inputdev;
 165
 166        struct rfkill *wlan_rfkill;
 167        struct rfkill *bluetooth_rfkill;
 168        struct rfkill *wwan3g_rfkill;
 169        struct rfkill *wimax_rfkill;
 170
 171        struct hotplug_slot hotplug_slot;
 172        struct mutex hotplug_lock;
 173
 174        struct led_classdev tpd_led;
 175        int tpd_led_wk;
 176        struct workqueue_struct *led_workqueue;
 177        struct work_struct tpd_led_work;
 178};
 179
 180/*
 181 * ACPI Helpers
 182 */
 183static int write_acpi_int(acpi_handle handle, const char *method, int val)
 184{
 185        acpi_status status;
 186
 187        status = acpi_execute_simple_method(handle, (char *)method, val);
 188
 189        return (status == AE_OK ? 0 : -1);
 190}
 191
 192static int read_acpi_int(acpi_handle handle, const char *method, int *val)
 193{
 194        acpi_status status;
 195        unsigned long long result;
 196
 197        status = acpi_evaluate_integer(handle, (char *)method, NULL, &result);
 198        if (ACPI_FAILURE(status)) {
 199                *val = -1;
 200                return -1;
 201        } else {
 202                *val = result;
 203                return 0;
 204        }
 205}
 206
 207static int set_acpi(struct eeepc_laptop *eeepc, int cm, int value)
 208{
 209        const char *method = cm_setv[cm];
 210
 211        if (method == NULL)
 212                return -ENODEV;
 213        if ((eeepc->cm_supported & (0x1 << cm)) == 0)
 214                return -ENODEV;
 215
 216        if (write_acpi_int(eeepc->handle, method, value))
 217                pr_warn("Error writing %s\n", method);
 218        return 0;
 219}
 220
 221static int get_acpi(struct eeepc_laptop *eeepc, int cm)
 222{
 223        const char *method = cm_getv[cm];
 224        int value;
 225
 226        if (method == NULL)
 227                return -ENODEV;
 228        if ((eeepc->cm_supported & (0x1 << cm)) == 0)
 229                return -ENODEV;
 230
 231        if (read_acpi_int(eeepc->handle, method, &value))
 232                pr_warn("Error reading %s\n", method);
 233        return value;
 234}
 235
 236static int acpi_setter_handle(struct eeepc_laptop *eeepc, int cm,
 237                              acpi_handle *handle)
 238{
 239        const char *method = cm_setv[cm];
 240        acpi_status status;
 241
 242        if (method == NULL)
 243                return -ENODEV;
 244        if ((eeepc->cm_supported & (0x1 << cm)) == 0)
 245                return -ENODEV;
 246
 247        status = acpi_get_handle(eeepc->handle, (char *)method,
 248                                 handle);
 249        if (status != AE_OK) {
 250                pr_warn("Error finding %s\n", method);
 251                return -ENODEV;
 252        }
 253        return 0;
 254}
 255
 256
 257/*
 258 * Sys helpers
 259 */
 260static int parse_arg(const char *buf, int *val)
 261{
 262        if (sscanf(buf, "%i", val) != 1)
 263                return -EINVAL;
 264        return 0;
 265}
 266
 267static ssize_t store_sys_acpi(struct device *dev, int cm,
 268                              const char *buf, size_t count)
 269{
 270        struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
 271        int rv, value;
 272
 273        rv = parse_arg(buf, &value);
 274        if (rv < 0)
 275                return rv;
 276        rv = set_acpi(eeepc, cm, value);
 277        if (rv < 0)
 278                return -EIO;
 279        return count;
 280}
 281
 282static ssize_t show_sys_acpi(struct device *dev, int cm, char *buf)
 283{
 284        struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
 285        int value = get_acpi(eeepc, cm);
 286
 287        if (value < 0)
 288                return -EIO;
 289        return sprintf(buf, "%d\n", value);
 290}
 291
 292#define EEEPC_ACPI_SHOW_FUNC(_name, _cm)                                \
 293        static ssize_t _name##_show(struct device *dev,                 \
 294                                    struct device_attribute *attr,      \
 295                                    char *buf)                          \
 296        {                                                               \
 297                return show_sys_acpi(dev, _cm, buf);                    \
 298        }
 299
 300#define EEEPC_ACPI_STORE_FUNC(_name, _cm)                               \
 301        static ssize_t _name##_store(struct device *dev,                \
 302                                     struct device_attribute *attr,     \
 303                                     const char *buf, size_t count)     \
 304        {                                                               \
 305                return store_sys_acpi(dev, _cm, buf, count);            \
 306        }
 307
 308#define EEEPC_CREATE_DEVICE_ATTR_RW(_name, _cm)                         \
 309        EEEPC_ACPI_SHOW_FUNC(_name, _cm)                                \
 310        EEEPC_ACPI_STORE_FUNC(_name, _cm)                               \
 311        static DEVICE_ATTR_RW(_name)
 312
 313#define EEEPC_CREATE_DEVICE_ATTR_WO(_name, _cm)                         \
 314        EEEPC_ACPI_STORE_FUNC(_name, _cm)                               \
 315        static DEVICE_ATTR_WO(_name)
 316
 317EEEPC_CREATE_DEVICE_ATTR_RW(camera, CM_ASL_CAMERA);
 318EEEPC_CREATE_DEVICE_ATTR_RW(cardr, CM_ASL_CARDREADER);
 319EEEPC_CREATE_DEVICE_ATTR_WO(disp, CM_ASL_DISPLAYSWITCH);
 320
 321struct eeepc_cpufv {
 322        int num;
 323        int cur;
 324};
 325
 326static int get_cpufv(struct eeepc_laptop *eeepc, struct eeepc_cpufv *c)
 327{
 328        c->cur = get_acpi(eeepc, CM_ASL_CPUFV);
 329        if (c->cur < 0)
 330                return -ENODEV;
 331
 332        c->num = (c->cur >> 8) & 0xff;
 333        c->cur &= 0xff;
 334        if (c->num == 0 || c->num > 12)
 335                return -ENODEV;
 336        return 0;
 337}
 338
 339static ssize_t available_cpufv_show(struct device *dev,
 340                                    struct device_attribute *attr,
 341                                    char *buf)
 342{
 343        struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
 344        struct eeepc_cpufv c;
 345        int i;
 346        ssize_t len = 0;
 347
 348        if (get_cpufv(eeepc, &c))
 349                return -ENODEV;
 350        for (i = 0; i < c.num; i++)
 351                len += sprintf(buf + len, "%d ", i);
 352        len += sprintf(buf + len, "\n");
 353        return len;
 354}
 355
 356static ssize_t cpufv_show(struct device *dev,
 357                          struct device_attribute *attr,
 358                          char *buf)
 359{
 360        struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
 361        struct eeepc_cpufv c;
 362
 363        if (get_cpufv(eeepc, &c))
 364                return -ENODEV;
 365        return sprintf(buf, "%#x\n", (c.num << 8) | c.cur);
 366}
 367
 368static ssize_t cpufv_store(struct device *dev,
 369                           struct device_attribute *attr,
 370                           const char *buf, size_t count)
 371{
 372        struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
 373        struct eeepc_cpufv c;
 374        int rv, value;
 375
 376        if (eeepc->cpufv_disabled)
 377                return -EPERM;
 378        if (get_cpufv(eeepc, &c))
 379                return -ENODEV;
 380        rv = parse_arg(buf, &value);
 381        if (rv < 0)
 382                return rv;
 383        if (value < 0 || value >= c.num)
 384                return -EINVAL;
 385        rv = set_acpi(eeepc, CM_ASL_CPUFV, value);
 386        if (rv)
 387                return rv;
 388        return count;
 389}
 390
 391static ssize_t cpufv_disabled_show(struct device *dev,
 392                          struct device_attribute *attr,
 393                          char *buf)
 394{
 395        struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
 396
 397        return sprintf(buf, "%d\n", eeepc->cpufv_disabled);
 398}
 399
 400static ssize_t cpufv_disabled_store(struct device *dev,
 401                           struct device_attribute *attr,
 402                           const char *buf, size_t count)
 403{
 404        struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
 405        int rv, value;
 406
 407        rv = parse_arg(buf, &value);
 408        if (rv < 0)
 409                return rv;
 410
 411        switch (value) {
 412        case 0:
 413                if (eeepc->cpufv_disabled)
 414                        pr_warn("cpufv enabled (not officially supported on this model)\n");
 415                eeepc->cpufv_disabled = false;
 416                return count;
 417        case 1:
 418                return -EPERM;
 419        default:
 420                return -EINVAL;
 421        }
 422}
 423
 424
 425static DEVICE_ATTR_RW(cpufv);
 426static DEVICE_ATTR_RO(available_cpufv);
 427static DEVICE_ATTR_RW(cpufv_disabled);
 428
 429static struct attribute *platform_attributes[] = {
 430        &dev_attr_camera.attr,
 431        &dev_attr_cardr.attr,
 432        &dev_attr_disp.attr,
 433        &dev_attr_cpufv.attr,
 434        &dev_attr_available_cpufv.attr,
 435        &dev_attr_cpufv_disabled.attr,
 436        NULL
 437};
 438
 439static const struct attribute_group platform_attribute_group = {
 440        .attrs = platform_attributes
 441};
 442
 443static int eeepc_platform_init(struct eeepc_laptop *eeepc)
 444{
 445        int result;
 446
 447        eeepc->platform_device = platform_device_alloc(EEEPC_LAPTOP_FILE, -1);
 448        if (!eeepc->platform_device)
 449                return -ENOMEM;
 450        platform_set_drvdata(eeepc->platform_device, eeepc);
 451
 452        result = platform_device_add(eeepc->platform_device);
 453        if (result)
 454                goto fail_platform_device;
 455
 456        result = sysfs_create_group(&eeepc->platform_device->dev.kobj,
 457                                    &platform_attribute_group);
 458        if (result)
 459                goto fail_sysfs;
 460        return 0;
 461
 462fail_sysfs:
 463        platform_device_del(eeepc->platform_device);
 464fail_platform_device:
 465        platform_device_put(eeepc->platform_device);
 466        return result;
 467}
 468
 469static void eeepc_platform_exit(struct eeepc_laptop *eeepc)
 470{
 471        sysfs_remove_group(&eeepc->platform_device->dev.kobj,
 472                           &platform_attribute_group);
 473        platform_device_unregister(eeepc->platform_device);
 474}
 475
 476/*
 477 * LEDs
 478 */
 479/*
 480 * These functions actually update the LED's, and are called from a
 481 * workqueue. By doing this as separate work rather than when the LED
 482 * subsystem asks, we avoid messing with the Asus ACPI stuff during a
 483 * potentially bad time, such as a timer interrupt.
 484 */
 485static void tpd_led_update(struct work_struct *work)
 486{
 487        struct eeepc_laptop *eeepc;
 488
 489        eeepc = container_of(work, struct eeepc_laptop, tpd_led_work);
 490
 491        set_acpi(eeepc, CM_ASL_TPD, eeepc->tpd_led_wk);
 492}
 493
 494static void tpd_led_set(struct led_classdev *led_cdev,
 495                        enum led_brightness value)
 496{
 497        struct eeepc_laptop *eeepc;
 498
 499        eeepc = container_of(led_cdev, struct eeepc_laptop, tpd_led);
 500
 501        eeepc->tpd_led_wk = (value > 0) ? 1 : 0;
 502        queue_work(eeepc->led_workqueue, &eeepc->tpd_led_work);
 503}
 504
 505static enum led_brightness tpd_led_get(struct led_classdev *led_cdev)
 506{
 507        struct eeepc_laptop *eeepc;
 508
 509        eeepc = container_of(led_cdev, struct eeepc_laptop, tpd_led);
 510
 511        return get_acpi(eeepc, CM_ASL_TPD);
 512}
 513
 514static int eeepc_led_init(struct eeepc_laptop *eeepc)
 515{
 516        int rv;
 517
 518        if (get_acpi(eeepc, CM_ASL_TPD) == -ENODEV)
 519                return 0;
 520
 521        eeepc->led_workqueue = create_singlethread_workqueue("led_workqueue");
 522        if (!eeepc->led_workqueue)
 523                return -ENOMEM;
 524        INIT_WORK(&eeepc->tpd_led_work, tpd_led_update);
 525
 526        eeepc->tpd_led.name = "eeepc::touchpad";
 527        eeepc->tpd_led.brightness_set = tpd_led_set;
 528        if (get_acpi(eeepc, CM_ASL_TPD) >= 0) /* if method is available */
 529                eeepc->tpd_led.brightness_get = tpd_led_get;
 530        eeepc->tpd_led.max_brightness = 1;
 531
 532        rv = led_classdev_register(&eeepc->platform_device->dev,
 533                                   &eeepc->tpd_led);
 534        if (rv) {
 535                destroy_workqueue(eeepc->led_workqueue);
 536                return rv;
 537        }
 538
 539        return 0;
 540}
 541
 542static void eeepc_led_exit(struct eeepc_laptop *eeepc)
 543{
 544        led_classdev_unregister(&eeepc->tpd_led);
 545        if (eeepc->led_workqueue)
 546                destroy_workqueue(eeepc->led_workqueue);
 547}
 548
 549/*
 550 * PCI hotplug (for wlan rfkill)
 551 */
 552static bool eeepc_wlan_rfkill_blocked(struct eeepc_laptop *eeepc)
 553{
 554        if (get_acpi(eeepc, CM_ASL_WLAN) == 1)
 555                return false;
 556        return true;
 557}
 558
 559static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc, acpi_handle handle)
 560{
 561        struct pci_dev *port;
 562        struct pci_dev *dev;
 563        struct pci_bus *bus;
 564        bool blocked = eeepc_wlan_rfkill_blocked(eeepc);
 565        bool absent;
 566        u32 l;
 567
 568        if (eeepc->wlan_rfkill)
 569                rfkill_set_sw_state(eeepc->wlan_rfkill, blocked);
 570
 571        mutex_lock(&eeepc->hotplug_lock);
 572        pci_lock_rescan_remove();
 573
 574        if (!eeepc->hotplug_slot.ops)
 575                goto out_unlock;
 576
 577        port = acpi_get_pci_dev(handle);
 578        if (!port) {
 579                pr_warn("Unable to find port\n");
 580                goto out_unlock;
 581        }
 582
 583        bus = port->subordinate;
 584
 585        if (!bus) {
 586                pr_warn("Unable to find PCI bus 1?\n");
 587                goto out_put_dev;
 588        }
 589
 590        if (pci_bus_read_config_dword(bus, 0, PCI_VENDOR_ID, &l)) {
 591                pr_err("Unable to read PCI config space?\n");
 592                goto out_put_dev;
 593        }
 594
 595        absent = (l == 0xffffffff);
 596
 597        if (blocked != absent) {
 598                pr_warn("BIOS says wireless lan is %s, but the pci device is %s\n",
 599                        blocked ? "blocked" : "unblocked",
 600                        absent ? "absent" : "present");
 601                pr_warn("skipped wireless hotplug as probably inappropriate for this model\n");
 602                goto out_put_dev;
 603        }
 604
 605        if (!blocked) {
 606                dev = pci_get_slot(bus, 0);
 607                if (dev) {
 608                        /* Device already present */
 609                        pci_dev_put(dev);
 610                        goto out_put_dev;
 611                }
 612                dev = pci_scan_single_device(bus, 0);
 613                if (dev) {
 614                        pci_bus_assign_resources(bus);
 615                        pci_bus_add_device(dev);
 616                }
 617        } else {
 618                dev = pci_get_slot(bus, 0);
 619                if (dev) {
 620                        pci_stop_and_remove_bus_device(dev);
 621                        pci_dev_put(dev);
 622                }
 623        }
 624out_put_dev:
 625        pci_dev_put(port);
 626
 627out_unlock:
 628        pci_unlock_rescan_remove();
 629        mutex_unlock(&eeepc->hotplug_lock);
 630}
 631
 632static void eeepc_rfkill_hotplug_update(struct eeepc_laptop *eeepc, char *node)
 633{
 634        acpi_status status = AE_OK;
 635        acpi_handle handle;
 636
 637        status = acpi_get_handle(NULL, node, &handle);
 638
 639        if (ACPI_SUCCESS(status))
 640                eeepc_rfkill_hotplug(eeepc, handle);
 641}
 642
 643static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
 644{
 645        struct eeepc_laptop *eeepc = data;
 646
 647        if (event != ACPI_NOTIFY_BUS_CHECK)
 648                return;
 649
 650        eeepc_rfkill_hotplug(eeepc, handle);
 651}
 652
 653static int eeepc_register_rfkill_notifier(struct eeepc_laptop *eeepc,
 654                                          char *node)
 655{
 656        acpi_status status;
 657        acpi_handle handle;
 658
 659        status = acpi_get_handle(NULL, node, &handle);
 660
 661        if (ACPI_FAILURE(status))
 662                return -ENODEV;
 663
 664        status = acpi_install_notify_handler(handle,
 665                                             ACPI_SYSTEM_NOTIFY,
 666                                             eeepc_rfkill_notify,
 667                                             eeepc);
 668        if (ACPI_FAILURE(status))
 669                pr_warn("Failed to register notify on %s\n", node);
 670
 671        /*
 672         * Refresh pci hotplug in case the rfkill state was
 673         * changed during setup.
 674         */
 675        eeepc_rfkill_hotplug(eeepc, handle);
 676        return 0;
 677}
 678
 679static void eeepc_unregister_rfkill_notifier(struct eeepc_laptop *eeepc,
 680                                             char *node)
 681{
 682        acpi_status status = AE_OK;
 683        acpi_handle handle;
 684
 685        status = acpi_get_handle(NULL, node, &handle);
 686
 687        if (ACPI_FAILURE(status))
 688                return;
 689
 690        status = acpi_remove_notify_handler(handle,
 691                                             ACPI_SYSTEM_NOTIFY,
 692                                             eeepc_rfkill_notify);
 693        if (ACPI_FAILURE(status))
 694                pr_err("Error removing rfkill notify handler %s\n",
 695                        node);
 696                /*
 697                 * Refresh pci hotplug in case the rfkill
 698                 * state was changed after
 699                 * eeepc_unregister_rfkill_notifier()
 700                 */
 701        eeepc_rfkill_hotplug(eeepc, handle);
 702}
 703
 704static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot,
 705                                    u8 *value)
 706{
 707        struct eeepc_laptop *eeepc;
 708        int val;
 709
 710        eeepc = container_of(hotplug_slot, struct eeepc_laptop, hotplug_slot);
 711        val = get_acpi(eeepc, CM_ASL_WLAN);
 712
 713        if (val == 1 || val == 0)
 714                *value = val;
 715        else
 716                return -EINVAL;
 717
 718        return 0;
 719}
 720
 721static const struct hotplug_slot_ops eeepc_hotplug_slot_ops = {
 722        .get_adapter_status = eeepc_get_adapter_status,
 723        .get_power_status = eeepc_get_adapter_status,
 724};
 725
 726static int eeepc_setup_pci_hotplug(struct eeepc_laptop *eeepc)
 727{
 728        int ret = -ENOMEM;
 729        struct pci_bus *bus = pci_find_bus(0, 1);
 730
 731        if (!bus) {
 732                pr_err("Unable to find wifi PCI bus\n");
 733                return -ENODEV;
 734        }
 735
 736        eeepc->hotplug_slot.ops = &eeepc_hotplug_slot_ops;
 737
 738        ret = pci_hp_register(&eeepc->hotplug_slot, bus, 0, "eeepc-wifi");
 739        if (ret) {
 740                pr_err("Unable to register hotplug slot - %d\n", ret);
 741                goto error_register;
 742        }
 743
 744        return 0;
 745
 746error_register:
 747        eeepc->hotplug_slot.ops = NULL;
 748        return ret;
 749}
 750
 751/*
 752 * Rfkill devices
 753 */
 754static int eeepc_rfkill_set(void *data, bool blocked)
 755{
 756        acpi_handle handle = data;
 757
 758        return write_acpi_int(handle, NULL, !blocked);
 759}
 760
 761static const struct rfkill_ops eeepc_rfkill_ops = {
 762        .set_block = eeepc_rfkill_set,
 763};
 764
 765static int eeepc_new_rfkill(struct eeepc_laptop *eeepc,
 766                            struct rfkill **rfkill,
 767                            const char *name,
 768                            enum rfkill_type type, int cm)
 769{
 770        acpi_handle handle;
 771        int result;
 772
 773        result = acpi_setter_handle(eeepc, cm, &handle);
 774        if (result < 0)
 775                return result;
 776
 777        *rfkill = rfkill_alloc(name, &eeepc->platform_device->dev, type,
 778                               &eeepc_rfkill_ops, handle);
 779
 780        if (!*rfkill)
 781                return -EINVAL;
 782
 783        rfkill_init_sw_state(*rfkill, get_acpi(eeepc, cm) != 1);
 784        result = rfkill_register(*rfkill);
 785        if (result) {
 786                rfkill_destroy(*rfkill);
 787                *rfkill = NULL;
 788                return result;
 789        }
 790        return 0;
 791}
 792
 793static char EEEPC_RFKILL_NODE_1[] = "\\_SB.PCI0.P0P5";
 794static char EEEPC_RFKILL_NODE_2[] = "\\_SB.PCI0.P0P6";
 795static char EEEPC_RFKILL_NODE_3[] = "\\_SB.PCI0.P0P7";
 796
 797static void eeepc_rfkill_exit(struct eeepc_laptop *eeepc)
 798{
 799        eeepc_unregister_rfkill_notifier(eeepc, EEEPC_RFKILL_NODE_1);
 800        eeepc_unregister_rfkill_notifier(eeepc, EEEPC_RFKILL_NODE_2);
 801        eeepc_unregister_rfkill_notifier(eeepc, EEEPC_RFKILL_NODE_3);
 802        if (eeepc->wlan_rfkill) {
 803                rfkill_unregister(eeepc->wlan_rfkill);
 804                rfkill_destroy(eeepc->wlan_rfkill);
 805                eeepc->wlan_rfkill = NULL;
 806        }
 807
 808        if (eeepc->hotplug_slot.ops)
 809                pci_hp_deregister(&eeepc->hotplug_slot);
 810
 811        if (eeepc->bluetooth_rfkill) {
 812                rfkill_unregister(eeepc->bluetooth_rfkill);
 813                rfkill_destroy(eeepc->bluetooth_rfkill);
 814                eeepc->bluetooth_rfkill = NULL;
 815        }
 816        if (eeepc->wwan3g_rfkill) {
 817                rfkill_unregister(eeepc->wwan3g_rfkill);
 818                rfkill_destroy(eeepc->wwan3g_rfkill);
 819                eeepc->wwan3g_rfkill = NULL;
 820        }
 821        if (eeepc->wimax_rfkill) {
 822                rfkill_unregister(eeepc->wimax_rfkill);
 823                rfkill_destroy(eeepc->wimax_rfkill);
 824                eeepc->wimax_rfkill = NULL;
 825        }
 826}
 827
 828static int eeepc_rfkill_init(struct eeepc_laptop *eeepc)
 829{
 830        int result = 0;
 831
 832        mutex_init(&eeepc->hotplug_lock);
 833
 834        result = eeepc_new_rfkill(eeepc, &eeepc->wlan_rfkill,
 835                                  "eeepc-wlan", RFKILL_TYPE_WLAN,
 836                                  CM_ASL_WLAN);
 837
 838        if (result && result != -ENODEV)
 839                goto exit;
 840
 841        result = eeepc_new_rfkill(eeepc, &eeepc->bluetooth_rfkill,
 842                                  "eeepc-bluetooth", RFKILL_TYPE_BLUETOOTH,
 843                                  CM_ASL_BLUETOOTH);
 844
 845        if (result && result != -ENODEV)
 846                goto exit;
 847
 848        result = eeepc_new_rfkill(eeepc, &eeepc->wwan3g_rfkill,
 849                                  "eeepc-wwan3g", RFKILL_TYPE_WWAN,
 850                                  CM_ASL_3G);
 851
 852        if (result && result != -ENODEV)
 853                goto exit;
 854
 855        result = eeepc_new_rfkill(eeepc, &eeepc->wimax_rfkill,
 856                                  "eeepc-wimax", RFKILL_TYPE_WIMAX,
 857                                  CM_ASL_WIMAX);
 858
 859        if (result && result != -ENODEV)
 860                goto exit;
 861
 862        if (eeepc->hotplug_disabled)
 863                return 0;
 864
 865        result = eeepc_setup_pci_hotplug(eeepc);
 866        /*
 867         * If we get -EBUSY then something else is handling the PCI hotplug -
 868         * don't fail in this case
 869         */
 870        if (result == -EBUSY)
 871                result = 0;
 872
 873        eeepc_register_rfkill_notifier(eeepc, EEEPC_RFKILL_NODE_1);
 874        eeepc_register_rfkill_notifier(eeepc, EEEPC_RFKILL_NODE_2);
 875        eeepc_register_rfkill_notifier(eeepc, EEEPC_RFKILL_NODE_3);
 876
 877exit:
 878        if (result && result != -ENODEV)
 879                eeepc_rfkill_exit(eeepc);
 880        return result;
 881}
 882
 883/*
 884 * Platform driver - hibernate/resume callbacks
 885 */
 886static int eeepc_hotk_thaw(struct device *device)
 887{
 888        struct eeepc_laptop *eeepc = dev_get_drvdata(device);
 889
 890        if (eeepc->wlan_rfkill) {
 891                int wlan;
 892
 893                /*
 894                 * Work around bios bug - acpi _PTS turns off the wireless led
 895                 * during suspend.  Normally it restores it on resume, but
 896                 * we should kick it ourselves in case hibernation is aborted.
 897                 */
 898                wlan = get_acpi(eeepc, CM_ASL_WLAN);
 899                if (wlan >= 0)
 900                        set_acpi(eeepc, CM_ASL_WLAN, wlan);
 901        }
 902
 903        return 0;
 904}
 905
 906static int eeepc_hotk_restore(struct device *device)
 907{
 908        struct eeepc_laptop *eeepc = dev_get_drvdata(device);
 909
 910        /* Refresh both wlan rfkill state and pci hotplug */
 911        if (eeepc->wlan_rfkill) {
 912                eeepc_rfkill_hotplug_update(eeepc, EEEPC_RFKILL_NODE_1);
 913                eeepc_rfkill_hotplug_update(eeepc, EEEPC_RFKILL_NODE_2);
 914                eeepc_rfkill_hotplug_update(eeepc, EEEPC_RFKILL_NODE_3);
 915        }
 916
 917        if (eeepc->bluetooth_rfkill)
 918                rfkill_set_sw_state(eeepc->bluetooth_rfkill,
 919                                    get_acpi(eeepc, CM_ASL_BLUETOOTH) != 1);
 920        if (eeepc->wwan3g_rfkill)
 921                rfkill_set_sw_state(eeepc->wwan3g_rfkill,
 922                                    get_acpi(eeepc, CM_ASL_3G) != 1);
 923        if (eeepc->wimax_rfkill)
 924                rfkill_set_sw_state(eeepc->wimax_rfkill,
 925                                    get_acpi(eeepc, CM_ASL_WIMAX) != 1);
 926
 927        return 0;
 928}
 929
 930static const struct dev_pm_ops eeepc_pm_ops = {
 931        .thaw = eeepc_hotk_thaw,
 932        .restore = eeepc_hotk_restore,
 933};
 934
 935static struct platform_driver platform_driver = {
 936        .driver = {
 937                .name = EEEPC_LAPTOP_FILE,
 938                .pm = &eeepc_pm_ops,
 939        }
 940};
 941
 942/*
 943 * Hwmon device
 944 */
 945
 946#define EEEPC_EC_SC00      0x61
 947#define EEEPC_EC_FAN_PWM   (EEEPC_EC_SC00 + 2) /* Fan PWM duty cycle (%) */
 948#define EEEPC_EC_FAN_HRPM  (EEEPC_EC_SC00 + 5) /* High byte, fan speed (RPM) */
 949#define EEEPC_EC_FAN_LRPM  (EEEPC_EC_SC00 + 6) /* Low byte, fan speed (RPM) */
 950
 951#define EEEPC_EC_SFB0      0xD0
 952#define EEEPC_EC_FAN_CTRL  (EEEPC_EC_SFB0 + 3) /* Byte containing SF25  */
 953
 954static inline int eeepc_pwm_to_lmsensors(int value)
 955{
 956        return value * 255 / 100;
 957}
 958
 959static inline int eeepc_lmsensors_to_pwm(int value)
 960{
 961        value = clamp_val(value, 0, 255);
 962        return value * 100 / 255;
 963}
 964
 965static int eeepc_get_fan_pwm(void)
 966{
 967        u8 value = 0;
 968
 969        ec_read(EEEPC_EC_FAN_PWM, &value);
 970        return eeepc_pwm_to_lmsensors(value);
 971}
 972
 973static void eeepc_set_fan_pwm(int value)
 974{
 975        value = eeepc_lmsensors_to_pwm(value);
 976        ec_write(EEEPC_EC_FAN_PWM, value);
 977}
 978
 979static int eeepc_get_fan_rpm(void)
 980{
 981        u8 high = 0;
 982        u8 low = 0;
 983
 984        ec_read(EEEPC_EC_FAN_HRPM, &high);
 985        ec_read(EEEPC_EC_FAN_LRPM, &low);
 986        return high << 8 | low;
 987}
 988
 989#define EEEPC_EC_FAN_CTRL_BIT   0x02
 990#define EEEPC_FAN_CTRL_MANUAL   1
 991#define EEEPC_FAN_CTRL_AUTO     2
 992
 993static int eeepc_get_fan_ctrl(void)
 994{
 995        u8 value = 0;
 996
 997        ec_read(EEEPC_EC_FAN_CTRL, &value);
 998        if (value & EEEPC_EC_FAN_CTRL_BIT)
 999                return EEEPC_FAN_CTRL_MANUAL;
1000        else
1001                return EEEPC_FAN_CTRL_AUTO;
1002}
1003
1004static void eeepc_set_fan_ctrl(int manual)
1005{
1006        u8 value = 0;
1007
1008        ec_read(EEEPC_EC_FAN_CTRL, &value);
1009        if (manual == EEEPC_FAN_CTRL_MANUAL)
1010                value |= EEEPC_EC_FAN_CTRL_BIT;
1011        else
1012                value &= ~EEEPC_EC_FAN_CTRL_BIT;
1013        ec_write(EEEPC_EC_FAN_CTRL, value);
1014}
1015
1016static ssize_t store_sys_hwmon(void (*set)(int), const char *buf, size_t count)
1017{
1018        int rv, value;
1019
1020        rv = parse_arg(buf, &value);
1021        if (rv < 0)
1022                return rv;
1023        set(value);
1024        return count;
1025}
1026
1027static ssize_t show_sys_hwmon(int (*get)(void), char *buf)
1028{
1029        return sprintf(buf, "%d\n", get());
1030}
1031
1032#define EEEPC_SENSOR_SHOW_FUNC(_name, _get)                             \
1033        static ssize_t _name##_show(struct device *dev,                 \
1034                                    struct device_attribute *attr,      \
1035                                    char *buf)                          \
1036        {                                                               \
1037                return show_sys_hwmon(_get, buf);                       \
1038        }
1039
1040#define EEEPC_SENSOR_STORE_FUNC(_name, _set)                            \
1041        static ssize_t _name##_store(struct device *dev,                \
1042                                     struct device_attribute *attr,     \
1043                                     const char *buf, size_t count)     \
1044        {                                                               \
1045                return store_sys_hwmon(_set, buf, count);               \
1046        }
1047
1048#define EEEPC_CREATE_SENSOR_ATTR_RW(_name, _get, _set)                  \
1049        EEEPC_SENSOR_SHOW_FUNC(_name, _get)                             \
1050        EEEPC_SENSOR_STORE_FUNC(_name, _set)                            \
1051        static DEVICE_ATTR_RW(_name)
1052
1053#define EEEPC_CREATE_SENSOR_ATTR_RO(_name, _get)                        \
1054        EEEPC_SENSOR_SHOW_FUNC(_name, _get)                             \
1055        static DEVICE_ATTR_RO(_name)
1056
1057EEEPC_CREATE_SENSOR_ATTR_RO(fan1_input, eeepc_get_fan_rpm);
1058EEEPC_CREATE_SENSOR_ATTR_RW(pwm1, eeepc_get_fan_pwm,
1059                            eeepc_set_fan_pwm);
1060EEEPC_CREATE_SENSOR_ATTR_RW(pwm1_enable, eeepc_get_fan_ctrl,
1061                            eeepc_set_fan_ctrl);
1062
1063static struct attribute *hwmon_attrs[] = {
1064        &dev_attr_pwm1.attr,
1065        &dev_attr_fan1_input.attr,
1066        &dev_attr_pwm1_enable.attr,
1067        NULL
1068};
1069ATTRIBUTE_GROUPS(hwmon);
1070
1071static int eeepc_hwmon_init(struct eeepc_laptop *eeepc)
1072{
1073        struct device *dev = &eeepc->platform_device->dev;
1074        struct device *hwmon;
1075
1076        hwmon = devm_hwmon_device_register_with_groups(dev, "eeepc", NULL,
1077                                                       hwmon_groups);
1078        if (IS_ERR(hwmon)) {
1079                pr_err("Could not register eeepc hwmon device\n");
1080                return PTR_ERR(hwmon);
1081        }
1082        return 0;
1083}
1084
1085/*
1086 * Backlight device
1087 */
1088static int read_brightness(struct backlight_device *bd)
1089{
1090        struct eeepc_laptop *eeepc = bl_get_data(bd);
1091
1092        return get_acpi(eeepc, CM_ASL_PANELBRIGHT);
1093}
1094
1095static int set_brightness(struct backlight_device *bd, int value)
1096{
1097        struct eeepc_laptop *eeepc = bl_get_data(bd);
1098
1099        return set_acpi(eeepc, CM_ASL_PANELBRIGHT, value);
1100}
1101
1102static int update_bl_status(struct backlight_device *bd)
1103{
1104        return set_brightness(bd, bd->props.brightness);
1105}
1106
1107static const struct backlight_ops eeepcbl_ops = {
1108        .get_brightness = read_brightness,
1109        .update_status = update_bl_status,
1110};
1111
1112static int eeepc_backlight_notify(struct eeepc_laptop *eeepc)
1113{
1114        struct backlight_device *bd = eeepc->backlight_device;
1115        int old = bd->props.brightness;
1116
1117        backlight_force_update(bd, BACKLIGHT_UPDATE_HOTKEY);
1118
1119        return old;
1120}
1121
1122static int eeepc_backlight_init(struct eeepc_laptop *eeepc)
1123{
1124        struct backlight_properties props;
1125        struct backlight_device *bd;
1126
1127        memset(&props, 0, sizeof(struct backlight_properties));
1128        props.type = BACKLIGHT_PLATFORM;
1129        props.max_brightness = 15;
1130        bd = backlight_device_register(EEEPC_LAPTOP_FILE,
1131                                       &eeepc->platform_device->dev, eeepc,
1132                                       &eeepcbl_ops, &props);
1133        if (IS_ERR(bd)) {
1134                pr_err("Could not register eeepc backlight device\n");
1135                eeepc->backlight_device = NULL;
1136                return PTR_ERR(bd);
1137        }
1138        eeepc->backlight_device = bd;
1139        bd->props.brightness = read_brightness(bd);
1140        bd->props.power = FB_BLANK_UNBLANK;
1141        backlight_update_status(bd);
1142        return 0;
1143}
1144
1145static void eeepc_backlight_exit(struct eeepc_laptop *eeepc)
1146{
1147        backlight_device_unregister(eeepc->backlight_device);
1148        eeepc->backlight_device = NULL;
1149}
1150
1151
1152/*
1153 * Input device (i.e. hotkeys)
1154 */
1155static int eeepc_input_init(struct eeepc_laptop *eeepc)
1156{
1157        struct input_dev *input;
1158        int error;
1159
1160        input = input_allocate_device();
1161        if (!input)
1162                return -ENOMEM;
1163
1164        input->name = "Asus EeePC extra buttons";
1165        input->phys = EEEPC_LAPTOP_FILE "/input0";
1166        input->id.bustype = BUS_HOST;
1167        input->dev.parent = &eeepc->platform_device->dev;
1168
1169        error = sparse_keymap_setup(input, eeepc_keymap, NULL);
1170        if (error) {
1171                pr_err("Unable to setup input device keymap\n");
1172                goto err_free_dev;
1173        }
1174
1175        error = input_register_device(input);
1176        if (error) {
1177                pr_err("Unable to register input device\n");
1178                goto err_free_dev;
1179        }
1180
1181        eeepc->inputdev = input;
1182        return 0;
1183
1184err_free_dev:
1185        input_free_device(input);
1186        return error;
1187}
1188
1189static void eeepc_input_exit(struct eeepc_laptop *eeepc)
1190{
1191        if (eeepc->inputdev)
1192                input_unregister_device(eeepc->inputdev);
1193        eeepc->inputdev = NULL;
1194}
1195
1196/*
1197 * ACPI driver
1198 */
1199static void eeepc_input_notify(struct eeepc_laptop *eeepc, int event)
1200{
1201        if (!eeepc->inputdev)
1202                return;
1203        if (!sparse_keymap_report_event(eeepc->inputdev, event, 1, true))
1204                pr_info("Unknown key %x pressed\n", event);
1205}
1206
1207static void eeepc_acpi_notify(struct acpi_device *device, u32 event)
1208{
1209        struct eeepc_laptop *eeepc = acpi_driver_data(device);
1210        int old_brightness, new_brightness;
1211        u16 count;
1212
1213        if (event > ACPI_MAX_SYS_NOTIFY)
1214                return;
1215        count = eeepc->event_count[event % 128]++;
1216        acpi_bus_generate_netlink_event(device->pnp.device_class,
1217                                        dev_name(&device->dev), event,
1218                                        count);
1219
1220        /* Brightness events are special */
1221        if (event < NOTIFY_BRN_MIN || event > NOTIFY_BRN_MAX) {
1222                eeepc_input_notify(eeepc, event);
1223                return;
1224        }
1225
1226        /* Ignore them completely if the acpi video driver is used */
1227        if (!eeepc->backlight_device)
1228                return;
1229
1230        /* Update the backlight device. */
1231        old_brightness = eeepc_backlight_notify(eeepc);
1232
1233        /* Convert event to keypress (obsolescent hack) */
1234        new_brightness = event - NOTIFY_BRN_MIN;
1235
1236        if (new_brightness < old_brightness) {
1237                event = NOTIFY_BRN_MIN; /* brightness down */
1238        } else if (new_brightness > old_brightness) {
1239                event = NOTIFY_BRN_MAX; /* brightness up */
1240        } else {
1241                /*
1242                 * no change in brightness - already at min/max,
1243                 * event will be desired value (or else ignored)
1244                 */
1245        }
1246        eeepc_input_notify(eeepc, event);
1247}
1248
1249static void eeepc_dmi_check(struct eeepc_laptop *eeepc)
1250{
1251        const char *model;
1252
1253        model = dmi_get_system_info(DMI_PRODUCT_NAME);
1254        if (!model)
1255                return;
1256
1257        /*
1258         * Blacklist for setting cpufv (cpu speed).
1259         *
1260         * EeePC 4G ("701") implements CFVS, but it is not supported
1261         * by the pre-installed OS, and the original option to change it
1262         * in the BIOS setup screen was removed in later versions.
1263         *
1264         * Judging by the lack of "Super Hybrid Engine" on Asus product pages,
1265         * this applies to all "701" models (4G/4G Surf/2G Surf).
1266         *
1267         * So Asus made a deliberate decision not to support it on this model.
1268         * We have several reports that using it can cause the system to hang
1269         *
1270         * The hang has also been reported on a "702" (Model name "8G"?).
1271         *
1272         * We avoid dmi_check_system() / dmi_match(), because they use
1273         * substring matching.  We don't want to affect the "701SD"
1274         * and "701SDX" models, because they do support S.H.E.
1275         */
1276        if (strcmp(model, "701") == 0 || strcmp(model, "702") == 0) {
1277                eeepc->cpufv_disabled = true;
1278                pr_info("model %s does not officially support setting cpu speed\n",
1279                        model);
1280                pr_info("cpufv disabled to avoid instability\n");
1281        }
1282
1283        /*
1284         * Blacklist for wlan hotplug
1285         *
1286         * Eeepc 1005HA doesn't work like others models and don't need the
1287         * hotplug code. In fact, current hotplug code seems to unplug another
1288         * device...
1289         */
1290        if (strcmp(model, "1005HA") == 0 || strcmp(model, "1201N") == 0 ||
1291            strcmp(model, "1005PE") == 0) {
1292                eeepc->hotplug_disabled = true;
1293                pr_info("wlan hotplug disabled\n");
1294        }
1295}
1296
1297static void cmsg_quirk(struct eeepc_laptop *eeepc, int cm, const char *name)
1298{
1299        int dummy;
1300
1301        /* Some BIOSes do not report cm although it is available.
1302           Check if cm_getv[cm] works and, if yes, assume cm should be set. */
1303        if (!(eeepc->cm_supported & (1 << cm))
1304            && !read_acpi_int(eeepc->handle, cm_getv[cm], &dummy)) {
1305                pr_info("%s (%x) not reported by BIOS, enabling anyway\n",
1306                        name, 1 << cm);
1307                eeepc->cm_supported |= 1 << cm;
1308        }
1309}
1310
1311static void cmsg_quirks(struct eeepc_laptop *eeepc)
1312{
1313        cmsg_quirk(eeepc, CM_ASL_LID, "LID");
1314        cmsg_quirk(eeepc, CM_ASL_TYPE, "TYPE");
1315        cmsg_quirk(eeepc, CM_ASL_PANELPOWER, "PANELPOWER");
1316        cmsg_quirk(eeepc, CM_ASL_TPD, "TPD");
1317}
1318
1319static int eeepc_acpi_init(struct eeepc_laptop *eeepc)
1320{
1321        unsigned int init_flags;
1322        int result;
1323
1324        result = acpi_bus_get_status(eeepc->device);
1325        if (result)
1326                return result;
1327        if (!eeepc->device->status.present) {
1328                pr_err("Hotkey device not present, aborting\n");
1329                return -ENODEV;
1330        }
1331
1332        init_flags = DISABLE_ASL_WLAN | DISABLE_ASL_DISPLAYSWITCH;
1333        pr_notice("Hotkey init flags 0x%x\n", init_flags);
1334
1335        if (write_acpi_int(eeepc->handle, "INIT", init_flags)) {
1336                pr_err("Hotkey initialization failed\n");
1337                return -ENODEV;
1338        }
1339
1340        /* get control methods supported */
1341        if (read_acpi_int(eeepc->handle, "CMSG", &eeepc->cm_supported)) {
1342                pr_err("Get control methods supported failed\n");
1343                return -ENODEV;
1344        }
1345        cmsg_quirks(eeepc);
1346        pr_info("Get control methods supported: 0x%x\n", eeepc->cm_supported);
1347
1348        return 0;
1349}
1350
1351static void eeepc_enable_camera(struct eeepc_laptop *eeepc)
1352{
1353        /*
1354         * If the following call to set_acpi() fails, it's because there's no
1355         * camera so we can ignore the error.
1356         */
1357        if (get_acpi(eeepc, CM_ASL_CAMERA) == 0)
1358                set_acpi(eeepc, CM_ASL_CAMERA, 1);
1359}
1360
1361static bool eeepc_device_present;
1362
1363static int eeepc_acpi_add(struct acpi_device *device)
1364{
1365        struct eeepc_laptop *eeepc;
1366        int result;
1367
1368        pr_notice(EEEPC_LAPTOP_NAME "\n");
1369        eeepc = kzalloc(sizeof(struct eeepc_laptop), GFP_KERNEL);
1370        if (!eeepc)
1371                return -ENOMEM;
1372        eeepc->handle = device->handle;
1373        strcpy(acpi_device_name(device), EEEPC_ACPI_DEVICE_NAME);
1374        strcpy(acpi_device_class(device), EEEPC_ACPI_CLASS);
1375        device->driver_data = eeepc;
1376        eeepc->device = device;
1377
1378        eeepc->hotplug_disabled = hotplug_disabled;
1379
1380        eeepc_dmi_check(eeepc);
1381
1382        result = eeepc_acpi_init(eeepc);
1383        if (result)
1384                goto fail_platform;
1385        eeepc_enable_camera(eeepc);
1386
1387        /*
1388         * Register the platform device first.  It is used as a parent for the
1389         * sub-devices below.
1390         *
1391         * Note that if there are multiple instances of this ACPI device it
1392         * will bail out, because the platform device is registered with a
1393         * fixed name.  Of course it doesn't make sense to have more than one,
1394         * and machine-specific scripts find the fixed name convenient.  But
1395         * It's also good for us to exclude multiple instances because both
1396         * our hwmon and our wlan rfkill subdevice use global ACPI objects
1397         * (the EC and the wlan PCI slot respectively).
1398         */
1399        result = eeepc_platform_init(eeepc);
1400        if (result)
1401                goto fail_platform;
1402
1403        if (acpi_video_get_backlight_type() == acpi_backlight_vendor) {
1404                result = eeepc_backlight_init(eeepc);
1405                if (result)
1406                        goto fail_backlight;
1407        }
1408
1409        result = eeepc_input_init(eeepc);
1410        if (result)
1411                goto fail_input;
1412
1413        result = eeepc_hwmon_init(eeepc);
1414        if (result)
1415                goto fail_hwmon;
1416
1417        result = eeepc_led_init(eeepc);
1418        if (result)
1419                goto fail_led;
1420
1421        result = eeepc_rfkill_init(eeepc);
1422        if (result)
1423                goto fail_rfkill;
1424
1425        eeepc_device_present = true;
1426        return 0;
1427
1428fail_rfkill:
1429        eeepc_led_exit(eeepc);
1430fail_led:
1431fail_hwmon:
1432        eeepc_input_exit(eeepc);
1433fail_input:
1434        eeepc_backlight_exit(eeepc);
1435fail_backlight:
1436        eeepc_platform_exit(eeepc);
1437fail_platform:
1438        kfree(eeepc);
1439
1440        return result;
1441}
1442
1443static int eeepc_acpi_remove(struct acpi_device *device)
1444{
1445        struct eeepc_laptop *eeepc = acpi_driver_data(device);
1446
1447        eeepc_backlight_exit(eeepc);
1448        eeepc_rfkill_exit(eeepc);
1449        eeepc_input_exit(eeepc);
1450        eeepc_led_exit(eeepc);
1451        eeepc_platform_exit(eeepc);
1452
1453        kfree(eeepc);
1454        return 0;
1455}
1456
1457
1458static const struct acpi_device_id eeepc_device_ids[] = {
1459        {EEEPC_ACPI_HID, 0},
1460        {"", 0},
1461};
1462MODULE_DEVICE_TABLE(acpi, eeepc_device_ids);
1463
1464static struct acpi_driver eeepc_acpi_driver = {
1465        .name = EEEPC_LAPTOP_NAME,
1466        .class = EEEPC_ACPI_CLASS,
1467        .owner = THIS_MODULE,
1468        .ids = eeepc_device_ids,
1469        .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
1470        .ops = {
1471                .add = eeepc_acpi_add,
1472                .remove = eeepc_acpi_remove,
1473                .notify = eeepc_acpi_notify,
1474        },
1475};
1476
1477
1478static int __init eeepc_laptop_init(void)
1479{
1480        int result;
1481
1482        result = platform_driver_register(&platform_driver);
1483        if (result < 0)
1484                return result;
1485
1486        result = acpi_bus_register_driver(&eeepc_acpi_driver);
1487        if (result < 0)
1488                goto fail_acpi_driver;
1489
1490        if (!eeepc_device_present) {
1491                result = -ENODEV;
1492                goto fail_no_device;
1493        }
1494
1495        return 0;
1496
1497fail_no_device:
1498        acpi_bus_unregister_driver(&eeepc_acpi_driver);
1499fail_acpi_driver:
1500        platform_driver_unregister(&platform_driver);
1501        return result;
1502}
1503
1504static void __exit eeepc_laptop_exit(void)
1505{
1506        acpi_bus_unregister_driver(&eeepc_acpi_driver);
1507        platform_driver_unregister(&platform_driver);
1508}
1509
1510module_init(eeepc_laptop_init);
1511module_exit(eeepc_laptop_exit);
1512