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