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