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