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        if (!IS_ERR_OR_NULL(eeepc->tpd_led.dev))
 545                led_classdev_unregister(&eeepc->tpd_led);
 546        if (eeepc->led_workqueue)
 547                destroy_workqueue(eeepc->led_workqueue);
 548}
 549
 550
 551/*
 552 * PCI hotplug (for wlan rfkill)
 553 */
 554static bool eeepc_wlan_rfkill_blocked(struct eeepc_laptop *eeepc)
 555{
 556        if (get_acpi(eeepc, CM_ASL_WLAN) == 1)
 557                return false;
 558        return true;
 559}
 560
 561static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc, acpi_handle handle)
 562{
 563        struct pci_dev *port;
 564        struct pci_dev *dev;
 565        struct pci_bus *bus;
 566        bool blocked = eeepc_wlan_rfkill_blocked(eeepc);
 567        bool absent;
 568        u32 l;
 569
 570        if (eeepc->wlan_rfkill)
 571                rfkill_set_sw_state(eeepc->wlan_rfkill, blocked);
 572
 573        mutex_lock(&eeepc->hotplug_lock);
 574        pci_lock_rescan_remove();
 575
 576        if (!eeepc->hotplug_slot.ops)
 577                goto out_unlock;
 578
 579        port = acpi_get_pci_dev(handle);
 580        if (!port) {
 581                pr_warning("Unable to find port\n");
 582                goto out_unlock;
 583        }
 584
 585        bus = port->subordinate;
 586
 587        if (!bus) {
 588                pr_warn("Unable to find PCI bus 1?\n");
 589                goto out_put_dev;
 590        }
 591
 592        if (pci_bus_read_config_dword(bus, 0, PCI_VENDOR_ID, &l)) {
 593                pr_err("Unable to read PCI config space?\n");
 594                goto out_put_dev;
 595        }
 596
 597        absent = (l == 0xffffffff);
 598
 599        if (blocked != absent) {
 600                pr_warn("BIOS says wireless lan is %s, but the pci device is %s\n",
 601                        blocked ? "blocked" : "unblocked",
 602                        absent ? "absent" : "present");
 603                pr_warn("skipped wireless hotplug as probably inappropriate for this model\n");
 604                goto out_put_dev;
 605        }
 606
 607        if (!blocked) {
 608                dev = pci_get_slot(bus, 0);
 609                if (dev) {
 610                        /* Device already present */
 611                        pci_dev_put(dev);
 612                        goto out_put_dev;
 613                }
 614                dev = pci_scan_single_device(bus, 0);
 615                if (dev) {
 616                        pci_bus_assign_resources(bus);
 617                        pci_bus_add_device(dev);
 618                }
 619        } else {
 620                dev = pci_get_slot(bus, 0);
 621                if (dev) {
 622                        pci_stop_and_remove_bus_device(dev);
 623                        pci_dev_put(dev);
 624                }
 625        }
 626out_put_dev:
 627        pci_dev_put(port);
 628
 629out_unlock:
 630        pci_unlock_rescan_remove();
 631        mutex_unlock(&eeepc->hotplug_lock);
 632}
 633
 634static void eeepc_rfkill_hotplug_update(struct eeepc_laptop *eeepc, char *node)
 635{
 636        acpi_status status = AE_OK;
 637        acpi_handle handle;
 638
 639        status = acpi_get_handle(NULL, node, &handle);
 640
 641        if (ACPI_SUCCESS(status))
 642                eeepc_rfkill_hotplug(eeepc, handle);
 643}
 644
 645static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
 646{
 647        struct eeepc_laptop *eeepc = data;
 648
 649        if (event != ACPI_NOTIFY_BUS_CHECK)
 650                return;
 651
 652        eeepc_rfkill_hotplug(eeepc, handle);
 653}
 654
 655static int eeepc_register_rfkill_notifier(struct eeepc_laptop *eeepc,
 656                                          char *node)
 657{
 658        acpi_status status;
 659        acpi_handle handle;
 660
 661        status = acpi_get_handle(NULL, node, &handle);
 662
 663        if (ACPI_FAILURE(status))
 664                return -ENODEV;
 665
 666        status = acpi_install_notify_handler(handle,
 667                                             ACPI_SYSTEM_NOTIFY,
 668                                             eeepc_rfkill_notify,
 669                                             eeepc);
 670        if (ACPI_FAILURE(status))
 671                pr_warn("Failed to register notify on %s\n", node);
 672
 673        /*
 674         * Refresh pci hotplug in case the rfkill state was
 675         * changed during setup.
 676         */
 677        eeepc_rfkill_hotplug(eeepc, handle);
 678        return 0;
 679}
 680
 681static void eeepc_unregister_rfkill_notifier(struct eeepc_laptop *eeepc,
 682                                             char *node)
 683{
 684        acpi_status status = AE_OK;
 685        acpi_handle handle;
 686
 687        status = acpi_get_handle(NULL, node, &handle);
 688
 689        if (ACPI_FAILURE(status))
 690                return;
 691
 692        status = acpi_remove_notify_handler(handle,
 693                                             ACPI_SYSTEM_NOTIFY,
 694                                             eeepc_rfkill_notify);
 695        if (ACPI_FAILURE(status))
 696                pr_err("Error removing rfkill notify handler %s\n",
 697                        node);
 698                /*
 699                 * Refresh pci hotplug in case the rfkill
 700                 * state was changed after
 701                 * eeepc_unregister_rfkill_notifier()
 702                 */
 703        eeepc_rfkill_hotplug(eeepc, handle);
 704}
 705
 706static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot,
 707                                    u8 *value)
 708{
 709        struct eeepc_laptop *eeepc;
 710        int val;
 711
 712        eeepc = container_of(hotplug_slot, struct eeepc_laptop, hotplug_slot);
 713        val = get_acpi(eeepc, CM_ASL_WLAN);
 714
 715        if (val == 1 || val == 0)
 716                *value = val;
 717        else
 718                return -EINVAL;
 719
 720        return 0;
 721}
 722
 723static const struct hotplug_slot_ops eeepc_hotplug_slot_ops = {
 724        .get_adapter_status = eeepc_get_adapter_status,
 725        .get_power_status = eeepc_get_adapter_status,
 726};
 727
 728static int eeepc_setup_pci_hotplug(struct eeepc_laptop *eeepc)
 729{
 730        int ret = -ENOMEM;
 731        struct pci_bus *bus = pci_find_bus(0, 1);
 732
 733        if (!bus) {
 734                pr_err("Unable to find wifi PCI bus\n");
 735                return -ENODEV;
 736        }
 737
 738        eeepc->hotplug_slot.ops = &eeepc_hotplug_slot_ops;
 739
 740        ret = pci_hp_register(&eeepc->hotplug_slot, bus, 0, "eeepc-wifi");
 741        if (ret) {
 742                pr_err("Unable to register hotplug slot - %d\n", ret);
 743                goto error_register;
 744        }
 745
 746        return 0;
 747
 748error_register:
 749        eeepc->hotplug_slot.ops = NULL;
 750        return ret;
 751}
 752
 753/*
 754 * Rfkill devices
 755 */
 756static int eeepc_rfkill_set(void *data, bool blocked)
 757{
 758        acpi_handle handle = data;
 759
 760        return write_acpi_int(handle, NULL, !blocked);
 761}
 762
 763static const struct rfkill_ops eeepc_rfkill_ops = {
 764        .set_block = eeepc_rfkill_set,
 765};
 766
 767static int eeepc_new_rfkill(struct eeepc_laptop *eeepc,
 768                            struct rfkill **rfkill,
 769                            const char *name,
 770                            enum rfkill_type type, int cm)
 771{
 772        acpi_handle handle;
 773        int result;
 774
 775        result = acpi_setter_handle(eeepc, cm, &handle);
 776        if (result < 0)
 777                return result;
 778
 779        *rfkill = rfkill_alloc(name, &eeepc->platform_device->dev, type,
 780                               &eeepc_rfkill_ops, handle);
 781
 782        if (!*rfkill)
 783                return -EINVAL;
 784
 785        rfkill_init_sw_state(*rfkill, get_acpi(eeepc, cm) != 1);
 786        result = rfkill_register(*rfkill);
 787        if (result) {
 788                rfkill_destroy(*rfkill);
 789                *rfkill = NULL;
 790                return result;
 791        }
 792        return 0;
 793}
 794
 795static char EEEPC_RFKILL_NODE_1[] = "\\_SB.PCI0.P0P5";
 796static char EEEPC_RFKILL_NODE_2[] = "\\_SB.PCI0.P0P6";
 797static char EEEPC_RFKILL_NODE_3[] = "\\_SB.PCI0.P0P7";
 798
 799static void eeepc_rfkill_exit(struct eeepc_laptop *eeepc)
 800{
 801        eeepc_unregister_rfkill_notifier(eeepc, EEEPC_RFKILL_NODE_1);
 802        eeepc_unregister_rfkill_notifier(eeepc, EEEPC_RFKILL_NODE_2);
 803        eeepc_unregister_rfkill_notifier(eeepc, EEEPC_RFKILL_NODE_3);
 804        if (eeepc->wlan_rfkill) {
 805                rfkill_unregister(eeepc->wlan_rfkill);
 806                rfkill_destroy(eeepc->wlan_rfkill);
 807                eeepc->wlan_rfkill = NULL;
 808        }
 809
 810        if (eeepc->hotplug_slot.ops)
 811                pci_hp_deregister(&eeepc->hotplug_slot);
 812
 813        if (eeepc->bluetooth_rfkill) {
 814                rfkill_unregister(eeepc->bluetooth_rfkill);
 815                rfkill_destroy(eeepc->bluetooth_rfkill);
 816                eeepc->bluetooth_rfkill = NULL;
 817        }
 818        if (eeepc->wwan3g_rfkill) {
 819                rfkill_unregister(eeepc->wwan3g_rfkill);
 820                rfkill_destroy(eeepc->wwan3g_rfkill);
 821                eeepc->wwan3g_rfkill = NULL;
 822        }
 823        if (eeepc->wimax_rfkill) {
 824                rfkill_unregister(eeepc->wimax_rfkill);
 825                rfkill_destroy(eeepc->wimax_rfkill);
 826                eeepc->wimax_rfkill = NULL;
 827        }
 828}
 829
 830static int eeepc_rfkill_init(struct eeepc_laptop *eeepc)
 831{
 832        int result = 0;
 833
 834        mutex_init(&eeepc->hotplug_lock);
 835
 836        result = eeepc_new_rfkill(eeepc, &eeepc->wlan_rfkill,
 837                                  "eeepc-wlan", RFKILL_TYPE_WLAN,
 838                                  CM_ASL_WLAN);
 839
 840        if (result && result != -ENODEV)
 841                goto exit;
 842
 843        result = eeepc_new_rfkill(eeepc, &eeepc->bluetooth_rfkill,
 844                                  "eeepc-bluetooth", RFKILL_TYPE_BLUETOOTH,
 845                                  CM_ASL_BLUETOOTH);
 846
 847        if (result && result != -ENODEV)
 848                goto exit;
 849
 850        result = eeepc_new_rfkill(eeepc, &eeepc->wwan3g_rfkill,
 851                                  "eeepc-wwan3g", RFKILL_TYPE_WWAN,
 852                                  CM_ASL_3G);
 853
 854        if (result && result != -ENODEV)
 855                goto exit;
 856
 857        result = eeepc_new_rfkill(eeepc, &eeepc->wimax_rfkill,
 858                                  "eeepc-wimax", RFKILL_TYPE_WIMAX,
 859                                  CM_ASL_WIMAX);
 860
 861        if (result && result != -ENODEV)
 862                goto exit;
 863
 864        if (eeepc->hotplug_disabled)
 865                return 0;
 866
 867        result = eeepc_setup_pci_hotplug(eeepc);
 868        /*
 869         * If we get -EBUSY then something else is handling the PCI hotplug -
 870         * don't fail in this case
 871         */
 872        if (result == -EBUSY)
 873                result = 0;
 874
 875        eeepc_register_rfkill_notifier(eeepc, EEEPC_RFKILL_NODE_1);
 876        eeepc_register_rfkill_notifier(eeepc, EEEPC_RFKILL_NODE_2);
 877        eeepc_register_rfkill_notifier(eeepc, EEEPC_RFKILL_NODE_3);
 878
 879exit:
 880        if (result && result != -ENODEV)
 881                eeepc_rfkill_exit(eeepc);
 882        return result;
 883}
 884
 885/*
 886 * Platform driver - hibernate/resume callbacks
 887 */
 888static int eeepc_hotk_thaw(struct device *device)
 889{
 890        struct eeepc_laptop *eeepc = dev_get_drvdata(device);
 891
 892        if (eeepc->wlan_rfkill) {
 893                int wlan;
 894
 895                /*
 896                 * Work around bios bug - acpi _PTS turns off the wireless led
 897                 * during suspend.  Normally it restores it on resume, but
 898                 * we should kick it ourselves in case hibernation is aborted.
 899                 */
 900                wlan = get_acpi(eeepc, CM_ASL_WLAN);
 901                if (wlan >= 0)
 902                        set_acpi(eeepc, CM_ASL_WLAN, wlan);
 903        }
 904
 905        return 0;
 906}
 907
 908static int eeepc_hotk_restore(struct device *device)
 909{
 910        struct eeepc_laptop *eeepc = dev_get_drvdata(device);
 911
 912        /* Refresh both wlan rfkill state and pci hotplug */
 913        if (eeepc->wlan_rfkill) {
 914                eeepc_rfkill_hotplug_update(eeepc, EEEPC_RFKILL_NODE_1);
 915                eeepc_rfkill_hotplug_update(eeepc, EEEPC_RFKILL_NODE_2);
 916                eeepc_rfkill_hotplug_update(eeepc, EEEPC_RFKILL_NODE_3);
 917        }
 918
 919        if (eeepc->bluetooth_rfkill)
 920                rfkill_set_sw_state(eeepc->bluetooth_rfkill,
 921                                    get_acpi(eeepc, CM_ASL_BLUETOOTH) != 1);
 922        if (eeepc->wwan3g_rfkill)
 923                rfkill_set_sw_state(eeepc->wwan3g_rfkill,
 924                                    get_acpi(eeepc, CM_ASL_3G) != 1);
 925        if (eeepc->wimax_rfkill)
 926                rfkill_set_sw_state(eeepc->wimax_rfkill,
 927                                    get_acpi(eeepc, CM_ASL_WIMAX) != 1);
 928
 929        return 0;
 930}
 931
 932static const struct dev_pm_ops eeepc_pm_ops = {
 933        .thaw = eeepc_hotk_thaw,
 934        .restore = eeepc_hotk_restore,
 935};
 936
 937static struct platform_driver platform_driver = {
 938        .driver = {
 939                .name = EEEPC_LAPTOP_FILE,
 940                .pm = &eeepc_pm_ops,
 941        }
 942};
 943
 944/*
 945 * Hwmon device
 946 */
 947
 948#define EEEPC_EC_SC00      0x61
 949#define EEEPC_EC_FAN_PWM   (EEEPC_EC_SC00 + 2) /* Fan PWM duty cycle (%) */
 950#define EEEPC_EC_FAN_HRPM  (EEEPC_EC_SC00 + 5) /* High byte, fan speed (RPM) */
 951#define EEEPC_EC_FAN_LRPM  (EEEPC_EC_SC00 + 6) /* Low byte, fan speed (RPM) */
 952
 953#define EEEPC_EC_SFB0      0xD0
 954#define EEEPC_EC_FAN_CTRL  (EEEPC_EC_SFB0 + 3) /* Byte containing SF25  */
 955
 956static inline int eeepc_pwm_to_lmsensors(int value)
 957{
 958        return value * 255 / 100;
 959}
 960
 961static inline int eeepc_lmsensors_to_pwm(int value)
 962{
 963        value = clamp_val(value, 0, 255);
 964        return value * 100 / 255;
 965}
 966
 967static int eeepc_get_fan_pwm(void)
 968{
 969        u8 value = 0;
 970
 971        ec_read(EEEPC_EC_FAN_PWM, &value);
 972        return eeepc_pwm_to_lmsensors(value);
 973}
 974
 975static void eeepc_set_fan_pwm(int value)
 976{
 977        value = eeepc_lmsensors_to_pwm(value);
 978        ec_write(EEEPC_EC_FAN_PWM, value);
 979}
 980
 981static int eeepc_get_fan_rpm(void)
 982{
 983        u8 high = 0;
 984        u8 low = 0;
 985
 986        ec_read(EEEPC_EC_FAN_HRPM, &high);
 987        ec_read(EEEPC_EC_FAN_LRPM, &low);
 988        return high << 8 | low;
 989}
 990
 991#define EEEPC_EC_FAN_CTRL_BIT   0x02
 992#define EEEPC_FAN_CTRL_MANUAL   1
 993#define EEEPC_FAN_CTRL_AUTO     2
 994
 995static int eeepc_get_fan_ctrl(void)
 996{
 997        u8 value = 0;
 998
 999        ec_read(EEEPC_EC_FAN_CTRL, &value);
1000        if (value & EEEPC_EC_FAN_CTRL_BIT)
1001                return EEEPC_FAN_CTRL_MANUAL;
1002        else
1003                return EEEPC_FAN_CTRL_AUTO;
1004}
1005
1006static void eeepc_set_fan_ctrl(int manual)
1007{
1008        u8 value = 0;
1009
1010        ec_read(EEEPC_EC_FAN_CTRL, &value);
1011        if (manual == EEEPC_FAN_CTRL_MANUAL)
1012                value |= EEEPC_EC_FAN_CTRL_BIT;
1013        else
1014                value &= ~EEEPC_EC_FAN_CTRL_BIT;
1015        ec_write(EEEPC_EC_FAN_CTRL, value);
1016}
1017
1018static ssize_t store_sys_hwmon(void (*set)(int), const char *buf, size_t count)
1019{
1020        int rv, value;
1021
1022        rv = parse_arg(buf, &value);
1023        if (rv < 0)
1024                return rv;
1025        set(value);
1026        return count;
1027}
1028
1029static ssize_t show_sys_hwmon(int (*get)(void), char *buf)
1030{
1031        return sprintf(buf, "%d\n", get());
1032}
1033
1034#define EEEPC_SENSOR_SHOW_FUNC(_name, _get)                             \
1035        static ssize_t _name##_show(struct device *dev,                 \
1036                                    struct device_attribute *attr,      \
1037                                    char *buf)                          \
1038        {                                                               \
1039                return show_sys_hwmon(_get, buf);                       \
1040        }
1041
1042#define EEEPC_SENSOR_STORE_FUNC(_name, _set)                            \
1043        static ssize_t _name##_store(struct device *dev,                \
1044                                     struct device_attribute *attr,     \
1045                                     const char *buf, size_t count)     \
1046        {                                                               \
1047                return store_sys_hwmon(_set, buf, count);               \
1048        }
1049
1050#define EEEPC_CREATE_SENSOR_ATTR_RW(_name, _get, _set)                  \
1051        EEEPC_SENSOR_SHOW_FUNC(_name, _get)                             \
1052        EEEPC_SENSOR_STORE_FUNC(_name, _set)                            \
1053        static DEVICE_ATTR_RW(_name)
1054
1055#define EEEPC_CREATE_SENSOR_ATTR_RO(_name, _get)                        \
1056        EEEPC_SENSOR_SHOW_FUNC(_name, _get)                             \
1057        static DEVICE_ATTR_RO(_name)
1058
1059EEEPC_CREATE_SENSOR_ATTR_RO(fan1_input, eeepc_get_fan_rpm);
1060EEEPC_CREATE_SENSOR_ATTR_RW(pwm1, eeepc_get_fan_pwm,
1061                            eeepc_set_fan_pwm);
1062EEEPC_CREATE_SENSOR_ATTR_RW(pwm1_enable, eeepc_get_fan_ctrl,
1063                            eeepc_set_fan_ctrl);
1064
1065static struct attribute *hwmon_attrs[] = {
1066        &dev_attr_pwm1.attr,
1067        &dev_attr_fan1_input.attr,
1068        &dev_attr_pwm1_enable.attr,
1069        NULL
1070};
1071ATTRIBUTE_GROUPS(hwmon);
1072
1073static int eeepc_hwmon_init(struct eeepc_laptop *eeepc)
1074{
1075        struct device *dev = &eeepc->platform_device->dev;
1076        struct device *hwmon;
1077
1078        hwmon = devm_hwmon_device_register_with_groups(dev, "eeepc", NULL,
1079                                                       hwmon_groups);
1080        if (IS_ERR(hwmon)) {
1081                pr_err("Could not register eeepc hwmon device\n");
1082                return PTR_ERR(hwmon);
1083        }
1084        return 0;
1085}
1086
1087/*
1088 * Backlight device
1089 */
1090static int read_brightness(struct backlight_device *bd)
1091{
1092        struct eeepc_laptop *eeepc = bl_get_data(bd);
1093
1094        return get_acpi(eeepc, CM_ASL_PANELBRIGHT);
1095}
1096
1097static int set_brightness(struct backlight_device *bd, int value)
1098{
1099        struct eeepc_laptop *eeepc = bl_get_data(bd);
1100
1101        return set_acpi(eeepc, CM_ASL_PANELBRIGHT, value);
1102}
1103
1104static int update_bl_status(struct backlight_device *bd)
1105{
1106        return set_brightness(bd, bd->props.brightness);
1107}
1108
1109static const struct backlight_ops eeepcbl_ops = {
1110        .get_brightness = read_brightness,
1111        .update_status = update_bl_status,
1112};
1113
1114static int eeepc_backlight_notify(struct eeepc_laptop *eeepc)
1115{
1116        struct backlight_device *bd = eeepc->backlight_device;
1117        int old = bd->props.brightness;
1118
1119        backlight_force_update(bd, BACKLIGHT_UPDATE_HOTKEY);
1120
1121        return old;
1122}
1123
1124static int eeepc_backlight_init(struct eeepc_laptop *eeepc)
1125{
1126        struct backlight_properties props;
1127        struct backlight_device *bd;
1128
1129        memset(&props, 0, sizeof(struct backlight_properties));
1130        props.type = BACKLIGHT_PLATFORM;
1131        props.max_brightness = 15;
1132        bd = backlight_device_register(EEEPC_LAPTOP_FILE,
1133                                       &eeepc->platform_device->dev, eeepc,
1134                                       &eeepcbl_ops, &props);
1135        if (IS_ERR(bd)) {
1136                pr_err("Could not register eeepc backlight device\n");
1137                eeepc->backlight_device = NULL;
1138                return PTR_ERR(bd);
1139        }
1140        eeepc->backlight_device = bd;
1141        bd->props.brightness = read_brightness(bd);
1142        bd->props.power = FB_BLANK_UNBLANK;
1143        backlight_update_status(bd);
1144        return 0;
1145}
1146
1147static void eeepc_backlight_exit(struct eeepc_laptop *eeepc)
1148{
1149        backlight_device_unregister(eeepc->backlight_device);
1150        eeepc->backlight_device = NULL;
1151}
1152
1153
1154/*
1155 * Input device (i.e. hotkeys)
1156 */
1157static int eeepc_input_init(struct eeepc_laptop *eeepc)
1158{
1159        struct input_dev *input;
1160        int error;
1161
1162        input = input_allocate_device();
1163        if (!input)
1164                return -ENOMEM;
1165
1166        input->name = "Asus EeePC extra buttons";
1167        input->phys = EEEPC_LAPTOP_FILE "/input0";
1168        input->id.bustype = BUS_HOST;
1169        input->dev.parent = &eeepc->platform_device->dev;
1170
1171        error = sparse_keymap_setup(input, eeepc_keymap, NULL);
1172        if (error) {
1173                pr_err("Unable to setup input device keymap\n");
1174                goto err_free_dev;
1175        }
1176
1177        error = input_register_device(input);
1178        if (error) {
1179                pr_err("Unable to register input device\n");
1180                goto err_free_dev;
1181        }
1182
1183        eeepc->inputdev = input;
1184        return 0;
1185
1186err_free_dev:
1187        input_free_device(input);
1188        return error;
1189}
1190
1191static void eeepc_input_exit(struct eeepc_laptop *eeepc)
1192{
1193        if (eeepc->inputdev)
1194                input_unregister_device(eeepc->inputdev);
1195        eeepc->inputdev = NULL;
1196}
1197
1198/*
1199 * ACPI driver
1200 */
1201static void eeepc_input_notify(struct eeepc_laptop *eeepc, int event)
1202{
1203        if (!eeepc->inputdev)
1204                return;
1205        if (!sparse_keymap_report_event(eeepc->inputdev, event, 1, true))
1206                pr_info("Unknown key %x pressed\n", event);
1207}
1208
1209static void eeepc_acpi_notify(struct acpi_device *device, u32 event)
1210{
1211        struct eeepc_laptop *eeepc = acpi_driver_data(device);
1212        int old_brightness, new_brightness;
1213        u16 count;
1214
1215        if (event > ACPI_MAX_SYS_NOTIFY)
1216                return;
1217        count = eeepc->event_count[event % 128]++;
1218        acpi_bus_generate_netlink_event(device->pnp.device_class,
1219                                        dev_name(&device->dev), event,
1220                                        count);
1221
1222        /* Brightness events are special */
1223        if (event < NOTIFY_BRN_MIN || event > NOTIFY_BRN_MAX) {
1224                eeepc_input_notify(eeepc, event);
1225                return;
1226        }
1227
1228        /* Ignore them completely if the acpi video driver is used */
1229        if (!eeepc->backlight_device)
1230                return;
1231
1232        /* Update the backlight device. */
1233        old_brightness = eeepc_backlight_notify(eeepc);
1234
1235        /* Convert event to keypress (obsolescent hack) */
1236        new_brightness = event - NOTIFY_BRN_MIN;
1237
1238        if (new_brightness < old_brightness) {
1239                event = NOTIFY_BRN_MIN; /* brightness down */
1240        } else if (new_brightness > old_brightness) {
1241                event = NOTIFY_BRN_MAX; /* brightness up */
1242        } else {
1243                /*
1244                 * no change in brightness - already at min/max,
1245                 * event will be desired value (or else ignored)
1246                 */
1247        }
1248        eeepc_input_notify(eeepc, event);
1249}
1250
1251static void eeepc_dmi_check(struct eeepc_laptop *eeepc)
1252{
1253        const char *model;
1254
1255        model = dmi_get_system_info(DMI_PRODUCT_NAME);
1256        if (!model)
1257                return;
1258
1259        /*
1260         * Blacklist for setting cpufv (cpu speed).
1261         *
1262         * EeePC 4G ("701") implements CFVS, but it is not supported
1263         * by the pre-installed OS, and the original option to change it
1264         * in the BIOS setup screen was removed in later versions.
1265         *
1266         * Judging by the lack of "Super Hybrid Engine" on Asus product pages,
1267         * this applies to all "701" models (4G/4G Surf/2G Surf).
1268         *
1269         * So Asus made a deliberate decision not to support it on this model.
1270         * We have several reports that using it can cause the system to hang
1271         *
1272         * The hang has also been reported on a "702" (Model name "8G"?).
1273         *
1274         * We avoid dmi_check_system() / dmi_match(), because they use
1275         * substring matching.  We don't want to affect the "701SD"
1276         * and "701SDX" models, because they do support S.H.E.
1277         */
1278        if (strcmp(model, "701") == 0 || strcmp(model, "702") == 0) {
1279                eeepc->cpufv_disabled = true;
1280                pr_info("model %s does not officially support setting cpu speed\n",
1281                        model);
1282                pr_info("cpufv disabled to avoid instability\n");
1283        }
1284
1285        /*
1286         * Blacklist for wlan hotplug
1287         *
1288         * Eeepc 1005HA doesn't work like others models and don't need the
1289         * hotplug code. In fact, current hotplug code seems to unplug another
1290         * device...
1291         */
1292        if (strcmp(model, "1005HA") == 0 || strcmp(model, "1201N") == 0 ||
1293            strcmp(model, "1005PE") == 0) {
1294                eeepc->hotplug_disabled = true;
1295                pr_info("wlan hotplug disabled\n");
1296        }
1297}
1298
1299static void cmsg_quirk(struct eeepc_laptop *eeepc, int cm, const char *name)
1300{
1301        int dummy;
1302
1303        /* Some BIOSes do not report cm although it is available.
1304           Check if cm_getv[cm] works and, if yes, assume cm should be set. */
1305        if (!(eeepc->cm_supported & (1 << cm))
1306            && !read_acpi_int(eeepc->handle, cm_getv[cm], &dummy)) {
1307                pr_info("%s (%x) not reported by BIOS, enabling anyway\n",
1308                        name, 1 << cm);
1309                eeepc->cm_supported |= 1 << cm;
1310        }
1311}
1312
1313static void cmsg_quirks(struct eeepc_laptop *eeepc)
1314{
1315        cmsg_quirk(eeepc, CM_ASL_LID, "LID");
1316        cmsg_quirk(eeepc, CM_ASL_TYPE, "TYPE");
1317        cmsg_quirk(eeepc, CM_ASL_PANELPOWER, "PANELPOWER");
1318        cmsg_quirk(eeepc, CM_ASL_TPD, "TPD");
1319}
1320
1321static int eeepc_acpi_init(struct eeepc_laptop *eeepc)
1322{
1323        unsigned int init_flags;
1324        int result;
1325
1326        result = acpi_bus_get_status(eeepc->device);
1327        if (result)
1328                return result;
1329        if (!eeepc->device->status.present) {
1330                pr_err("Hotkey device not present, aborting\n");
1331                return -ENODEV;
1332        }
1333
1334        init_flags = DISABLE_ASL_WLAN | DISABLE_ASL_DISPLAYSWITCH;
1335        pr_notice("Hotkey init flags 0x%x\n", init_flags);
1336
1337        if (write_acpi_int(eeepc->handle, "INIT", init_flags)) {
1338                pr_err("Hotkey initialization failed\n");
1339                return -ENODEV;
1340        }
1341
1342        /* get control methods supported */
1343        if (read_acpi_int(eeepc->handle, "CMSG", &eeepc->cm_supported)) {
1344                pr_err("Get control methods supported failed\n");
1345                return -ENODEV;
1346        }
1347        cmsg_quirks(eeepc);
1348        pr_info("Get control methods supported: 0x%x\n", eeepc->cm_supported);
1349
1350        return 0;
1351}
1352
1353static void eeepc_enable_camera(struct eeepc_laptop *eeepc)
1354{
1355        /*
1356         * If the following call to set_acpi() fails, it's because there's no
1357         * camera so we can ignore the error.
1358         */
1359        if (get_acpi(eeepc, CM_ASL_CAMERA) == 0)
1360                set_acpi(eeepc, CM_ASL_CAMERA, 1);
1361}
1362
1363static bool eeepc_device_present;
1364
1365static int eeepc_acpi_add(struct acpi_device *device)
1366{
1367        struct eeepc_laptop *eeepc;
1368        int result;
1369
1370        pr_notice(EEEPC_LAPTOP_NAME "\n");
1371        eeepc = kzalloc(sizeof(struct eeepc_laptop), GFP_KERNEL);
1372        if (!eeepc)
1373                return -ENOMEM;
1374        eeepc->handle = device->handle;
1375        strcpy(acpi_device_name(device), EEEPC_ACPI_DEVICE_NAME);
1376        strcpy(acpi_device_class(device), EEEPC_ACPI_CLASS);
1377        device->driver_data = eeepc;
1378        eeepc->device = device;
1379
1380        eeepc->hotplug_disabled = hotplug_disabled;
1381
1382        eeepc_dmi_check(eeepc);
1383
1384        result = eeepc_acpi_init(eeepc);
1385        if (result)
1386                goto fail_platform;
1387        eeepc_enable_camera(eeepc);
1388
1389        /*
1390         * Register the platform device first.  It is used as a parent for the
1391         * sub-devices below.
1392         *
1393         * Note that if there are multiple instances of this ACPI device it
1394         * will bail out, because the platform device is registered with a
1395         * fixed name.  Of course it doesn't make sense to have more than one,
1396         * and machine-specific scripts find the fixed name convenient.  But
1397         * It's also good for us to exclude multiple instances because both
1398         * our hwmon and our wlan rfkill subdevice use global ACPI objects
1399         * (the EC and the wlan PCI slot respectively).
1400         */
1401        result = eeepc_platform_init(eeepc);
1402        if (result)
1403                goto fail_platform;
1404
1405        if (acpi_video_get_backlight_type() == acpi_backlight_vendor) {
1406                result = eeepc_backlight_init(eeepc);
1407                if (result)
1408                        goto fail_backlight;
1409        }
1410
1411        result = eeepc_input_init(eeepc);
1412        if (result)
1413                goto fail_input;
1414
1415        result = eeepc_hwmon_init(eeepc);
1416        if (result)
1417                goto fail_hwmon;
1418
1419        result = eeepc_led_init(eeepc);
1420        if (result)
1421                goto fail_led;
1422
1423        result = eeepc_rfkill_init(eeepc);
1424        if (result)
1425                goto fail_rfkill;
1426
1427        eeepc_device_present = true;
1428        return 0;
1429
1430fail_rfkill:
1431        eeepc_led_exit(eeepc);
1432fail_led:
1433fail_hwmon:
1434        eeepc_input_exit(eeepc);
1435fail_input:
1436        eeepc_backlight_exit(eeepc);
1437fail_backlight:
1438        eeepc_platform_exit(eeepc);
1439fail_platform:
1440        kfree(eeepc);
1441
1442        return result;
1443}
1444
1445static int eeepc_acpi_remove(struct acpi_device *device)
1446{
1447        struct eeepc_laptop *eeepc = acpi_driver_data(device);
1448
1449        eeepc_backlight_exit(eeepc);
1450        eeepc_rfkill_exit(eeepc);
1451        eeepc_input_exit(eeepc);
1452        eeepc_led_exit(eeepc);
1453        eeepc_platform_exit(eeepc);
1454
1455        kfree(eeepc);
1456        return 0;
1457}
1458
1459
1460static const struct acpi_device_id eeepc_device_ids[] = {
1461        {EEEPC_ACPI_HID, 0},
1462        {"", 0},
1463};
1464MODULE_DEVICE_TABLE(acpi, eeepc_device_ids);
1465
1466static struct acpi_driver eeepc_acpi_driver = {
1467        .name = EEEPC_LAPTOP_NAME,
1468        .class = EEEPC_ACPI_CLASS,
1469        .owner = THIS_MODULE,
1470        .ids = eeepc_device_ids,
1471        .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
1472        .ops = {
1473                .add = eeepc_acpi_add,
1474                .remove = eeepc_acpi_remove,
1475                .notify = eeepc_acpi_notify,
1476        },
1477};
1478
1479
1480static int __init eeepc_laptop_init(void)
1481{
1482        int result;
1483
1484        result = platform_driver_register(&platform_driver);
1485        if (result < 0)
1486                return result;
1487
1488        result = acpi_bus_register_driver(&eeepc_acpi_driver);
1489        if (result < 0)
1490                goto fail_acpi_driver;
1491
1492        if (!eeepc_device_present) {
1493                result = -ENODEV;
1494                goto fail_no_device;
1495        }
1496
1497        return 0;
1498
1499fail_no_device:
1500        acpi_bus_unregister_driver(&eeepc_acpi_driver);
1501fail_acpi_driver:
1502        platform_driver_unregister(&platform_driver);
1503        return result;
1504}
1505
1506static void __exit eeepc_laptop_exit(void)
1507{
1508        acpi_bus_unregister_driver(&eeepc_acpi_driver);
1509        platform_driver_unregister(&platform_driver);
1510}
1511
1512module_init(eeepc_laptop_init);
1513module_exit(eeepc_laptop_exit);
1514