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