Commit 5b799d4fb787bb94f1068352220ab033ac7969f8

Authored by Corentin Chary
Committed by Matthew Garrett
1 parent f017fbe799

asus-wmi: move generic code to asus-wmi

New Asus notebooks are using a WMI device similar to
the one used in Eee PCs. Since we don't want to load
a module named eeepc-laptop on Asus Notebooks, start by
copying all the code to asus-wmi.c.

Signed-off-by: Corentin Chary <corentincj@iksaif.net>
Signed-off-by: Matthew Garrett <mjg@redhat.com>

Showing 3 changed files with 1455 additions and 1455 deletions Side-by-side Diff

drivers/platform/x86/Makefile
... ... @@ -4,7 +4,7 @@
4 4 #
5 5 obj-$(CONFIG_ASUS_LAPTOP) += asus-laptop.o
6 6 obj-$(CONFIG_EEEPC_LAPTOP) += eeepc-laptop.o
7   -obj-$(CONFIG_EEEPC_WMI) += eeepc-wmi.o
  7 +obj-$(CONFIG_EEEPC_WMI) += asus-wmi.o eeepc-wmi.o
8 8 obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o
9 9 obj-$(CONFIG_ACPI_CMPC) += classmate-laptop.o
10 10 obj-$(CONFIG_COMPAL_LAPTOP) += compal-laptop.o
drivers/platform/x86/asus-wmi.c
Changes suppressed. Click to show
  1 +/*
  2 + * Eee PC WMI hotkey driver
  3 + *
  4 + * Copyright(C) 2010 Intel Corporation.
  5 + * Copyright(C) 2010 Corentin Chary <corentin.chary@gmail.com>
  6 + *
  7 + * Portions based on wistron_btns.c:
  8 + * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz>
  9 + * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org>
  10 + * Copyright (C) 2005 Dmitry Torokhov <dtor@mail.ru>
  11 + *
  12 + * This program is free software; you can redistribute it and/or modify
  13 + * it under the terms of the GNU General Public License as published by
  14 + * the Free Software Foundation; either version 2 of the License, or
  15 + * (at your option) any later version.
  16 + *
  17 + * This program is distributed in the hope that it will be useful,
  18 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20 + * GNU General Public License for more details.
  21 + *
  22 + * You should have received a copy of the GNU General Public License
  23 + * along with this program; if not, write to the Free Software
  24 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  25 + */
  26 +
  27 +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  28 +
  29 +#include <linux/kernel.h>
  30 +#include <linux/module.h>
  31 +#include <linux/init.h>
  32 +#include <linux/types.h>
  33 +#include <linux/slab.h>
  34 +#include <linux/input.h>
  35 +#include <linux/input/sparse-keymap.h>
  36 +#include <linux/fb.h>
  37 +#include <linux/backlight.h>
  38 +#include <linux/leds.h>
  39 +#include <linux/rfkill.h>
  40 +#include <linux/pci.h>
  41 +#include <linux/pci_hotplug.h>
  42 +#include <linux/debugfs.h>
  43 +#include <linux/seq_file.h>
  44 +#include <linux/platform_device.h>
  45 +#include <linux/dmi.h>
  46 +#include <acpi/acpi_bus.h>
  47 +#include <acpi/acpi_drivers.h>
  48 +
  49 +#define EEEPC_WMI_FILE "eeepc-wmi"
  50 +
  51 +MODULE_AUTHOR("Yong Wang <yong.y.wang@intel.com>");
  52 +MODULE_DESCRIPTION("Eee PC WMI Hotkey Driver");
  53 +MODULE_LICENSE("GPL");
  54 +
  55 +#define EEEPC_ACPI_HID "ASUS010" /* old _HID used in eeepc-laptop */
  56 +
  57 +#define EEEPC_WMI_EVENT_GUID "ABBC0F72-8EA1-11D1-00A0-C90629100000"
  58 +#define EEEPC_WMI_MGMT_GUID "97845ED0-4E6D-11DE-8A39-0800200C9A66"
  59 +
  60 +MODULE_ALIAS("wmi:"EEEPC_WMI_EVENT_GUID);
  61 +MODULE_ALIAS("wmi:"EEEPC_WMI_MGMT_GUID);
  62 +
  63 +#define NOTIFY_BRNUP_MIN 0x11
  64 +#define NOTIFY_BRNUP_MAX 0x1f
  65 +#define NOTIFY_BRNDOWN_MIN 0x20
  66 +#define NOTIFY_BRNDOWN_MAX 0x2e
  67 +
  68 +/* WMI Methods */
  69 +#define EEEPC_WMI_METHODID_DSTS 0x53544344
  70 +#define EEEPC_WMI_METHODID_DEVS 0x53564544
  71 +#define EEEPC_WMI_METHODID_CFVS 0x53564643
  72 +
  73 +/* Wireless */
  74 +#define EEEPC_WMI_DEVID_WLAN 0x00010011
  75 +#define EEEPC_WMI_DEVID_BLUETOOTH 0x00010013
  76 +#define EEEPC_WMI_DEVID_WIMAX 0x00010017
  77 +#define EEEPC_WMI_DEVID_WWAN3G 0x00010019
  78 +
  79 +/* Backlight and Brightness */
  80 +#define EEEPC_WMI_DEVID_BACKLIGHT 0x00050011
  81 +#define EEEPC_WMI_DEVID_BRIGHTNESS 0x00050012
  82 +
  83 +/* Misc */
  84 +#define EEEPC_WMI_DEVID_CAMERA 0x00060013
  85 +
  86 +/* Storage */
  87 +#define EEEPC_WMI_DEVID_CARDREADER 0x00080013
  88 +
  89 +/* Input */
  90 +#define EEEPC_WMI_DEVID_TOUCHPAD 0x00100011
  91 +#define EEEPC_WMI_DEVID_TOUCHPAD_LED 0x00100012
  92 +
  93 +/* DSTS masks */
  94 +#define EEEPC_WMI_DSTS_STATUS_BIT 0x00000001
  95 +#define EEEPC_WMI_DSTS_PRESENCE_BIT 0x00010000
  96 +#define EEEPC_WMI_DSTS_BRIGHTNESS_MASK 0x000000FF
  97 +#define EEEPC_WMI_DSTS_MAX_BRIGTH_MASK 0x0000FF00
  98 +
  99 +static bool hotplug_wireless;
  100 +
  101 +module_param(hotplug_wireless, bool, 0444);
  102 +MODULE_PARM_DESC(hotplug_wireless,
  103 + "Enable hotplug for wireless device. "
  104 + "If your laptop needs that, please report to "
  105 + "acpi4asus-user@lists.sourceforge.net.");
  106 +
  107 +static const struct key_entry eeepc_wmi_keymap[] = {
  108 + /* Sleep already handled via generic ACPI code */
  109 + { KE_IGNORE, NOTIFY_BRNDOWN_MIN, { KEY_BRIGHTNESSDOWN } },
  110 + { KE_IGNORE, NOTIFY_BRNUP_MIN, { KEY_BRIGHTNESSUP } },
  111 + { KE_KEY, 0x30, { KEY_VOLUMEUP } },
  112 + { KE_KEY, 0x31, { KEY_VOLUMEDOWN } },
  113 + { KE_KEY, 0x32, { KEY_MUTE } },
  114 + { KE_KEY, 0x5c, { KEY_F15 } }, /* Power Gear key */
  115 + { KE_KEY, 0x5d, { KEY_WLAN } },
  116 + { KE_KEY, 0x6b, { KEY_F13 } }, /* Disable Touchpad */
  117 + { KE_KEY, 0x82, { KEY_CAMERA } },
  118 + { KE_KEY, 0x83, { KEY_CAMERA_ZOOMIN } },
  119 + { KE_KEY, 0x88, { KEY_WLAN } },
  120 + { KE_KEY, 0xcc, { KEY_SWITCHVIDEOMODE } },
  121 + { KE_KEY, 0xe0, { KEY_PROG1 } }, /* Task Manager */
  122 + { KE_KEY, 0xe1, { KEY_F14 } }, /* Change Resolution */
  123 + { KE_KEY, 0xe9, { KEY_BRIGHTNESS_ZERO } },
  124 + { KE_KEY, 0xeb, { KEY_CAMERA_ZOOMOUT } },
  125 + { KE_KEY, 0xec, { KEY_CAMERA_UP } },
  126 + { KE_KEY, 0xed, { KEY_CAMERA_DOWN } },
  127 + { KE_KEY, 0xee, { KEY_CAMERA_LEFT } },
  128 + { KE_KEY, 0xef, { KEY_CAMERA_RIGHT } },
  129 + { KE_END, 0},
  130 +};
  131 +
  132 +struct bios_args {
  133 + u32 dev_id;
  134 + u32 ctrl_param;
  135 +};
  136 +
  137 +/*
  138 + * eeepc-wmi/ - debugfs root directory
  139 + * dev_id - current dev_id
  140 + * ctrl_param - current ctrl_param
  141 + * devs - call DEVS(dev_id, ctrl_param) and print result
  142 + * dsts - call DSTS(dev_id) and print result
  143 + */
  144 +struct eeepc_wmi_debug {
  145 + struct dentry *root;
  146 + u32 dev_id;
  147 + u32 ctrl_param;
  148 +};
  149 +
  150 +struct eeepc_wmi {
  151 + bool hotplug_wireless;
  152 +
  153 + struct input_dev *inputdev;
  154 + struct backlight_device *backlight_device;
  155 + struct platform_device *platform_device;
  156 +
  157 + struct led_classdev tpd_led;
  158 + int tpd_led_wk;
  159 + struct workqueue_struct *led_workqueue;
  160 + struct work_struct tpd_led_work;
  161 +
  162 + struct rfkill *wlan_rfkill;
  163 + struct rfkill *bluetooth_rfkill;
  164 + struct rfkill *wimax_rfkill;
  165 + struct rfkill *wwan3g_rfkill;
  166 +
  167 + struct hotplug_slot *hotplug_slot;
  168 + struct mutex hotplug_lock;
  169 + struct mutex wmi_lock;
  170 + struct workqueue_struct *hotplug_workqueue;
  171 + struct work_struct hotplug_work;
  172 +
  173 + struct eeepc_wmi_debug debug;
  174 +};
  175 +
  176 +static int eeepc_wmi_input_init(struct eeepc_wmi *eeepc)
  177 +{
  178 + int err;
  179 +
  180 + eeepc->inputdev = input_allocate_device();
  181 + if (!eeepc->inputdev)
  182 + return -ENOMEM;
  183 +
  184 + eeepc->inputdev->name = "Eee PC WMI hotkeys";
  185 + eeepc->inputdev->phys = EEEPC_WMI_FILE "/input0";
  186 + eeepc->inputdev->id.bustype = BUS_HOST;
  187 + eeepc->inputdev->dev.parent = &eeepc->platform_device->dev;
  188 +
  189 + err = sparse_keymap_setup(eeepc->inputdev, eeepc_wmi_keymap, NULL);
  190 + if (err)
  191 + goto err_free_dev;
  192 +
  193 + err = input_register_device(eeepc->inputdev);
  194 + if (err)
  195 + goto err_free_keymap;
  196 +
  197 + return 0;
  198 +
  199 +err_free_keymap:
  200 + sparse_keymap_free(eeepc->inputdev);
  201 +err_free_dev:
  202 + input_free_device(eeepc->inputdev);
  203 + return err;
  204 +}
  205 +
  206 +static void eeepc_wmi_input_exit(struct eeepc_wmi *eeepc)
  207 +{
  208 + if (eeepc->inputdev) {
  209 + sparse_keymap_free(eeepc->inputdev);
  210 + input_unregister_device(eeepc->inputdev);
  211 + }
  212 +
  213 + eeepc->inputdev = NULL;
  214 +}
  215 +
  216 +static acpi_status eeepc_wmi_get_devstate(u32 dev_id, u32 *retval)
  217 +{
  218 + struct acpi_buffer input = { (acpi_size)sizeof(u32), &dev_id };
  219 + struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
  220 + union acpi_object *obj;
  221 + acpi_status status;
  222 + u32 tmp;
  223 +
  224 + status = wmi_evaluate_method(EEEPC_WMI_MGMT_GUID,
  225 + 1, EEEPC_WMI_METHODID_DSTS,
  226 + &input, &output);
  227 +
  228 + if (ACPI_FAILURE(status))
  229 + return status;
  230 +
  231 + obj = (union acpi_object *)output.pointer;
  232 + if (obj && obj->type == ACPI_TYPE_INTEGER)
  233 + tmp = (u32)obj->integer.value;
  234 + else
  235 + tmp = 0;
  236 +
  237 + if (retval)
  238 + *retval = tmp;
  239 +
  240 + kfree(obj);
  241 +
  242 + return status;
  243 +
  244 +}
  245 +
  246 +static acpi_status eeepc_wmi_set_devstate(u32 dev_id, u32 ctrl_param,
  247 + u32 *retval)
  248 +{
  249 + struct bios_args args = {
  250 + .dev_id = dev_id,
  251 + .ctrl_param = ctrl_param,
  252 + };
  253 + struct acpi_buffer input = { (acpi_size)sizeof(args), &args };
  254 + acpi_status status;
  255 +
  256 + if (!retval) {
  257 + status = wmi_evaluate_method(EEEPC_WMI_MGMT_GUID, 1,
  258 + EEEPC_WMI_METHODID_DEVS,
  259 + &input, NULL);
  260 + } else {
  261 + struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
  262 + union acpi_object *obj;
  263 + u32 tmp;
  264 +
  265 + status = wmi_evaluate_method(EEEPC_WMI_MGMT_GUID, 1,
  266 + EEEPC_WMI_METHODID_DEVS,
  267 + &input, &output);
  268 +
  269 + if (ACPI_FAILURE(status))
  270 + return status;
  271 +
  272 + obj = (union acpi_object *)output.pointer;
  273 + if (obj && obj->type == ACPI_TYPE_INTEGER)
  274 + tmp = (u32)obj->integer.value;
  275 + else
  276 + tmp = 0;
  277 +
  278 + *retval = tmp;
  279 +
  280 + kfree(obj);
  281 + }
  282 +
  283 + return status;
  284 +}
  285 +
  286 +/* Helper for special devices with magic return codes */
  287 +static int eeepc_wmi_get_devstate_bits(u32 dev_id, u32 mask)
  288 +{
  289 + u32 retval = 0;
  290 + acpi_status status;
  291 +
  292 + status = eeepc_wmi_get_devstate(dev_id, &retval);
  293 +
  294 + if (ACPI_FAILURE(status))
  295 + return -EINVAL;
  296 +
  297 + if (!(retval & EEEPC_WMI_DSTS_PRESENCE_BIT))
  298 + return -ENODEV;
  299 +
  300 + return retval & mask;
  301 +}
  302 +
  303 +static int eeepc_wmi_get_devstate_simple(u32 dev_id)
  304 +{
  305 + return eeepc_wmi_get_devstate_bits(dev_id, EEEPC_WMI_DSTS_STATUS_BIT);
  306 +}
  307 +
  308 +/*
  309 + * LEDs
  310 + */
  311 +/*
  312 + * These functions actually update the LED's, and are called from a
  313 + * workqueue. By doing this as separate work rather than when the LED
  314 + * subsystem asks, we avoid messing with the Eeepc ACPI stuff during a
  315 + * potentially bad time, such as a timer interrupt.
  316 + */
  317 +static void tpd_led_update(struct work_struct *work)
  318 +{
  319 + int ctrl_param;
  320 + struct eeepc_wmi *eeepc;
  321 +
  322 + eeepc = container_of(work, struct eeepc_wmi, tpd_led_work);
  323 +
  324 + ctrl_param = eeepc->tpd_led_wk;
  325 + eeepc_wmi_set_devstate(EEEPC_WMI_DEVID_TOUCHPAD_LED, ctrl_param, NULL);
  326 +}
  327 +
  328 +static void tpd_led_set(struct led_classdev *led_cdev,
  329 + enum led_brightness value)
  330 +{
  331 + struct eeepc_wmi *eeepc;
  332 +
  333 + eeepc = container_of(led_cdev, struct eeepc_wmi, tpd_led);
  334 +
  335 + eeepc->tpd_led_wk = !!value;
  336 + queue_work(eeepc->led_workqueue, &eeepc->tpd_led_work);
  337 +}
  338 +
  339 +static int read_tpd_led_state(struct eeepc_wmi *eeepc)
  340 +{
  341 + return eeepc_wmi_get_devstate_simple(EEEPC_WMI_DEVID_TOUCHPAD_LED);
  342 +}
  343 +
  344 +static enum led_brightness tpd_led_get(struct led_classdev *led_cdev)
  345 +{
  346 + struct eeepc_wmi *eeepc;
  347 +
  348 + eeepc = container_of(led_cdev, struct eeepc_wmi, tpd_led);
  349 +
  350 + return read_tpd_led_state(eeepc);
  351 +}
  352 +
  353 +static int eeepc_wmi_led_init(struct eeepc_wmi *eeepc)
  354 +{
  355 + int rv;
  356 +
  357 + if (read_tpd_led_state(eeepc) < 0)
  358 + return 0;
  359 +
  360 + eeepc->led_workqueue = create_singlethread_workqueue("led_workqueue");
  361 + if (!eeepc->led_workqueue)
  362 + return -ENOMEM;
  363 + INIT_WORK(&eeepc->tpd_led_work, tpd_led_update);
  364 +
  365 + eeepc->tpd_led.name = "eeepc::touchpad";
  366 + eeepc->tpd_led.brightness_set = tpd_led_set;
  367 + eeepc->tpd_led.brightness_get = tpd_led_get;
  368 + eeepc->tpd_led.max_brightness = 1;
  369 +
  370 + rv = led_classdev_register(&eeepc->platform_device->dev,
  371 + &eeepc->tpd_led);
  372 + if (rv) {
  373 + destroy_workqueue(eeepc->led_workqueue);
  374 + return rv;
  375 + }
  376 +
  377 + return 0;
  378 +}
  379 +
  380 +static void eeepc_wmi_led_exit(struct eeepc_wmi *eeepc)
  381 +{
  382 + if (eeepc->tpd_led.dev)
  383 + led_classdev_unregister(&eeepc->tpd_led);
  384 + if (eeepc->led_workqueue)
  385 + destroy_workqueue(eeepc->led_workqueue);
  386 +}
  387 +
  388 +/*
  389 + * PCI hotplug (for wlan rfkill)
  390 + */
  391 +static bool eeepc_wlan_rfkill_blocked(struct eeepc_wmi *eeepc)
  392 +{
  393 + int result = eeepc_wmi_get_devstate_simple(EEEPC_WMI_DEVID_WLAN);
  394 +
  395 + if (result < 0)
  396 + return false;
  397 + return !result;
  398 +}
  399 +
  400 +static void eeepc_rfkill_hotplug(struct eeepc_wmi *eeepc)
  401 +{
  402 + struct pci_dev *dev;
  403 + struct pci_bus *bus;
  404 + bool blocked;
  405 + bool absent;
  406 + u32 l;
  407 +
  408 + mutex_lock(&eeepc->wmi_lock);
  409 + blocked = eeepc_wlan_rfkill_blocked(eeepc);
  410 + mutex_unlock(&eeepc->wmi_lock);
  411 +
  412 + mutex_lock(&eeepc->hotplug_lock);
  413 +
  414 + if (eeepc->wlan_rfkill)
  415 + rfkill_set_sw_state(eeepc->wlan_rfkill, blocked);
  416 +
  417 + if (eeepc->hotplug_slot) {
  418 + bus = pci_find_bus(0, 1);
  419 + if (!bus) {
  420 + pr_warning("Unable to find PCI bus 1?\n");
  421 + goto out_unlock;
  422 + }
  423 +
  424 + if (pci_bus_read_config_dword(bus, 0, PCI_VENDOR_ID, &l)) {
  425 + pr_err("Unable to read PCI config space?\n");
  426 + goto out_unlock;
  427 + }
  428 + absent = (l == 0xffffffff);
  429 +
  430 + if (blocked != absent) {
  431 + pr_warning("BIOS says wireless lan is %s, "
  432 + "but the pci device is %s\n",
  433 + blocked ? "blocked" : "unblocked",
  434 + absent ? "absent" : "present");
  435 + pr_warning("skipped wireless hotplug as probably "
  436 + "inappropriate for this model\n");
  437 + goto out_unlock;
  438 + }
  439 +
  440 + if (!blocked) {
  441 + dev = pci_get_slot(bus, 0);
  442 + if (dev) {
  443 + /* Device already present */
  444 + pci_dev_put(dev);
  445 + goto out_unlock;
  446 + }
  447 + dev = pci_scan_single_device(bus, 0);
  448 + if (dev) {
  449 + pci_bus_assign_resources(bus);
  450 + if (pci_bus_add_device(dev))
  451 + pr_err("Unable to hotplug wifi\n");
  452 + }
  453 + } else {
  454 + dev = pci_get_slot(bus, 0);
  455 + if (dev) {
  456 + pci_remove_bus_device(dev);
  457 + pci_dev_put(dev);
  458 + }
  459 + }
  460 + }
  461 +
  462 +out_unlock:
  463 + mutex_unlock(&eeepc->hotplug_lock);
  464 +}
  465 +
  466 +static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
  467 +{
  468 + struct eeepc_wmi *eeepc = data;
  469 +
  470 + if (event != ACPI_NOTIFY_BUS_CHECK)
  471 + return;
  472 +
  473 + /*
  474 + * We can't call directly eeepc_rfkill_hotplug because most
  475 + * of the time WMBC is still being executed and not reetrant.
  476 + * There is currently no way to tell ACPICA that we want this
  477 + * method to be serialized, we schedule a eeepc_rfkill_hotplug
  478 + * call later, in a safer context.
  479 + */
  480 + queue_work(eeepc->hotplug_workqueue, &eeepc->hotplug_work);
  481 +}
  482 +
  483 +static int eeepc_register_rfkill_notifier(struct eeepc_wmi *eeepc,
  484 + char *node)
  485 +{
  486 + acpi_status status;
  487 + acpi_handle handle;
  488 +
  489 + status = acpi_get_handle(NULL, node, &handle);
  490 +
  491 + if (ACPI_SUCCESS(status)) {
  492 + status = acpi_install_notify_handler(handle,
  493 + ACPI_SYSTEM_NOTIFY,
  494 + eeepc_rfkill_notify,
  495 + eeepc);
  496 + if (ACPI_FAILURE(status))
  497 + pr_warning("Failed to register notify on %s\n", node);
  498 + } else
  499 + return -ENODEV;
  500 +
  501 + return 0;
  502 +}
  503 +
  504 +static void eeepc_unregister_rfkill_notifier(struct eeepc_wmi *eeepc,
  505 + char *node)
  506 +{
  507 + acpi_status status = AE_OK;
  508 + acpi_handle handle;
  509 +
  510 + status = acpi_get_handle(NULL, node, &handle);
  511 +
  512 + if (ACPI_SUCCESS(status)) {
  513 + status = acpi_remove_notify_handler(handle,
  514 + ACPI_SYSTEM_NOTIFY,
  515 + eeepc_rfkill_notify);
  516 + if (ACPI_FAILURE(status))
  517 + pr_err("Error removing rfkill notify handler %s\n",
  518 + node);
  519 + }
  520 +}
  521 +
  522 +static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot,
  523 + u8 *value)
  524 +{
  525 + int result = eeepc_wmi_get_devstate_simple(EEEPC_WMI_DEVID_WLAN);
  526 +
  527 + if (result < 0)
  528 + return result;
  529 +
  530 + *value = !!result;
  531 + return 0;
  532 +}
  533 +
  534 +static void eeepc_cleanup_pci_hotplug(struct hotplug_slot *hotplug_slot)
  535 +{
  536 + kfree(hotplug_slot->info);
  537 + kfree(hotplug_slot);
  538 +}
  539 +
  540 +static struct hotplug_slot_ops eeepc_hotplug_slot_ops = {
  541 + .owner = THIS_MODULE,
  542 + .get_adapter_status = eeepc_get_adapter_status,
  543 + .get_power_status = eeepc_get_adapter_status,
  544 +};
  545 +
  546 +static void eeepc_hotplug_work(struct work_struct *work)
  547 +{
  548 + struct eeepc_wmi *eeepc;
  549 +
  550 + eeepc = container_of(work, struct eeepc_wmi, hotplug_work);
  551 + eeepc_rfkill_hotplug(eeepc);
  552 +}
  553 +
  554 +static int eeepc_setup_pci_hotplug(struct eeepc_wmi *eeepc)
  555 +{
  556 + int ret = -ENOMEM;
  557 + struct pci_bus *bus = pci_find_bus(0, 1);
  558 +
  559 + if (!bus) {
  560 + pr_err("Unable to find wifi PCI bus\n");
  561 + return -ENODEV;
  562 + }
  563 +
  564 + eeepc->hotplug_workqueue =
  565 + create_singlethread_workqueue("hotplug_workqueue");
  566 + if (!eeepc->hotplug_workqueue)
  567 + goto error_workqueue;
  568 +
  569 + INIT_WORK(&eeepc->hotplug_work, eeepc_hotplug_work);
  570 +
  571 + eeepc->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
  572 + if (!eeepc->hotplug_slot)
  573 + goto error_slot;
  574 +
  575 + eeepc->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info),
  576 + GFP_KERNEL);
  577 + if (!eeepc->hotplug_slot->info)
  578 + goto error_info;
  579 +
  580 + eeepc->hotplug_slot->private = eeepc;
  581 + eeepc->hotplug_slot->release = &eeepc_cleanup_pci_hotplug;
  582 + eeepc->hotplug_slot->ops = &eeepc_hotplug_slot_ops;
  583 + eeepc_get_adapter_status(eeepc->hotplug_slot,
  584 + &eeepc->hotplug_slot->info->adapter_status);
  585 +
  586 + ret = pci_hp_register(eeepc->hotplug_slot, bus, 0, "eeepc-wifi");
  587 + if (ret) {
  588 + pr_err("Unable to register hotplug slot - %d\n", ret);
  589 + goto error_register;
  590 + }
  591 +
  592 + return 0;
  593 +
  594 +error_register:
  595 + kfree(eeepc->hotplug_slot->info);
  596 +error_info:
  597 + kfree(eeepc->hotplug_slot);
  598 + eeepc->hotplug_slot = NULL;
  599 +error_slot:
  600 + destroy_workqueue(eeepc->hotplug_workqueue);
  601 +error_workqueue:
  602 + return ret;
  603 +}
  604 +
  605 +/*
  606 + * Rfkill devices
  607 + */
  608 +static int eeepc_rfkill_set(void *data, bool blocked)
  609 +{
  610 + int dev_id = (unsigned long)data;
  611 + u32 ctrl_param = !blocked;
  612 + acpi_status status;
  613 +
  614 + status = eeepc_wmi_set_devstate(dev_id, ctrl_param, NULL);
  615 +
  616 + if (ACPI_FAILURE(status))
  617 + return -EIO;
  618 +
  619 + return 0;
  620 +}
  621 +
  622 +static void eeepc_rfkill_query(struct rfkill *rfkill, void *data)
  623 +{
  624 + int dev_id = (unsigned long)data;
  625 + int result;
  626 +
  627 + result = eeepc_wmi_get_devstate_simple(dev_id);
  628 +
  629 + if (result < 0)
  630 + return ;
  631 +
  632 + rfkill_set_sw_state(rfkill, !result);
  633 +}
  634 +
  635 +static int eeepc_rfkill_wlan_set(void *data, bool blocked)
  636 +{
  637 + struct eeepc_wmi *eeepc = data;
  638 + int ret;
  639 +
  640 + /*
  641 + * This handler is enabled only if hotplug is enabled.
  642 + * In this case, the eeepc_wmi_set_devstate() will
  643 + * trigger a wmi notification and we need to wait
  644 + * this call to finish before being able to call
  645 + * any wmi method
  646 + */
  647 + mutex_lock(&eeepc->wmi_lock);
  648 + ret = eeepc_rfkill_set((void *)(long)EEEPC_WMI_DEVID_WLAN, blocked);
  649 + mutex_unlock(&eeepc->wmi_lock);
  650 + return ret;
  651 +}
  652 +
  653 +static void eeepc_rfkill_wlan_query(struct rfkill *rfkill, void *data)
  654 +{
  655 + eeepc_rfkill_query(rfkill, (void *)(long)EEEPC_WMI_DEVID_WLAN);
  656 +}
  657 +
  658 +static const struct rfkill_ops eeepc_rfkill_wlan_ops = {
  659 + .set_block = eeepc_rfkill_wlan_set,
  660 + .query = eeepc_rfkill_wlan_query,
  661 +};
  662 +
  663 +static const struct rfkill_ops eeepc_rfkill_ops = {
  664 + .set_block = eeepc_rfkill_set,
  665 + .query = eeepc_rfkill_query,
  666 +};
  667 +
  668 +static int eeepc_new_rfkill(struct eeepc_wmi *eeepc,
  669 + struct rfkill **rfkill,
  670 + const char *name,
  671 + enum rfkill_type type, int dev_id)
  672 +{
  673 + int result = eeepc_wmi_get_devstate_simple(dev_id);
  674 +
  675 + if (result < 0)
  676 + return result;
  677 +
  678 + if (dev_id == EEEPC_WMI_DEVID_WLAN && eeepc->hotplug_wireless)
  679 + *rfkill = rfkill_alloc(name, &eeepc->platform_device->dev, type,
  680 + &eeepc_rfkill_wlan_ops, eeepc);
  681 + else
  682 + *rfkill = rfkill_alloc(name, &eeepc->platform_device->dev, type,
  683 + &eeepc_rfkill_ops, (void *)(long)dev_id);
  684 +
  685 + if (!*rfkill)
  686 + return -EINVAL;
  687 +
  688 + rfkill_init_sw_state(*rfkill, !result);
  689 + result = rfkill_register(*rfkill);
  690 + if (result) {
  691 + rfkill_destroy(*rfkill);
  692 + *rfkill = NULL;
  693 + return result;
  694 + }
  695 + return 0;
  696 +}
  697 +
  698 +static void eeepc_wmi_rfkill_exit(struct eeepc_wmi *eeepc)
  699 +{
  700 + eeepc_unregister_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P5");
  701 + eeepc_unregister_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P6");
  702 + eeepc_unregister_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P7");
  703 + if (eeepc->wlan_rfkill) {
  704 + rfkill_unregister(eeepc->wlan_rfkill);
  705 + rfkill_destroy(eeepc->wlan_rfkill);
  706 + eeepc->wlan_rfkill = NULL;
  707 + }
  708 + /*
  709 + * Refresh pci hotplug in case the rfkill state was changed after
  710 + * eeepc_unregister_rfkill_notifier()
  711 + */
  712 + eeepc_rfkill_hotplug(eeepc);
  713 + if (eeepc->hotplug_slot)
  714 + pci_hp_deregister(eeepc->hotplug_slot);
  715 + if (eeepc->hotplug_workqueue)
  716 + destroy_workqueue(eeepc->hotplug_workqueue);
  717 +
  718 + if (eeepc->bluetooth_rfkill) {
  719 + rfkill_unregister(eeepc->bluetooth_rfkill);
  720 + rfkill_destroy(eeepc->bluetooth_rfkill);
  721 + eeepc->bluetooth_rfkill = NULL;
  722 + }
  723 + if (eeepc->wimax_rfkill) {
  724 + rfkill_unregister(eeepc->wimax_rfkill);
  725 + rfkill_destroy(eeepc->wimax_rfkill);
  726 + eeepc->wimax_rfkill = NULL;
  727 + }
  728 + if (eeepc->wwan3g_rfkill) {
  729 + rfkill_unregister(eeepc->wwan3g_rfkill);
  730 + rfkill_destroy(eeepc->wwan3g_rfkill);
  731 + eeepc->wwan3g_rfkill = NULL;
  732 + }
  733 +}
  734 +
  735 +static int eeepc_wmi_rfkill_init(struct eeepc_wmi *eeepc)
  736 +{
  737 + int result = 0;
  738 +
  739 + mutex_init(&eeepc->hotplug_lock);
  740 + mutex_init(&eeepc->wmi_lock);
  741 +
  742 + result = eeepc_new_rfkill(eeepc, &eeepc->wlan_rfkill,
  743 + "eeepc-wlan", RFKILL_TYPE_WLAN,
  744 + EEEPC_WMI_DEVID_WLAN);
  745 +
  746 + if (result && result != -ENODEV)
  747 + goto exit;
  748 +
  749 + result = eeepc_new_rfkill(eeepc, &eeepc->bluetooth_rfkill,
  750 + "eeepc-bluetooth", RFKILL_TYPE_BLUETOOTH,
  751 + EEEPC_WMI_DEVID_BLUETOOTH);
  752 +
  753 + if (result && result != -ENODEV)
  754 + goto exit;
  755 +
  756 + result = eeepc_new_rfkill(eeepc, &eeepc->wimax_rfkill,
  757 + "eeepc-wimax", RFKILL_TYPE_WIMAX,
  758 + EEEPC_WMI_DEVID_WIMAX);
  759 +
  760 + if (result && result != -ENODEV)
  761 + goto exit;
  762 +
  763 + result = eeepc_new_rfkill(eeepc, &eeepc->wwan3g_rfkill,
  764 + "eeepc-wwan3g", RFKILL_TYPE_WWAN,
  765 + EEEPC_WMI_DEVID_WWAN3G);
  766 +
  767 + if (result && result != -ENODEV)
  768 + goto exit;
  769 +
  770 + if (!eeepc->hotplug_wireless)
  771 + goto exit;
  772 +
  773 + result = eeepc_setup_pci_hotplug(eeepc);
  774 + /*
  775 + * If we get -EBUSY then something else is handling the PCI hotplug -
  776 + * don't fail in this case
  777 + */
  778 + if (result == -EBUSY)
  779 + result = 0;
  780 +
  781 + eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P5");
  782 + eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P6");
  783 + eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P7");
  784 + /*
  785 + * Refresh pci hotplug in case the rfkill state was changed during
  786 + * setup.
  787 + */
  788 + eeepc_rfkill_hotplug(eeepc);
  789 +
  790 +exit:
  791 + if (result && result != -ENODEV)
  792 + eeepc_wmi_rfkill_exit(eeepc);
  793 +
  794 + if (result == -ENODEV)
  795 + result = 0;
  796 +
  797 + return result;
  798 +}
  799 +
  800 +/*
  801 + * Backlight
  802 + */
  803 +static int read_backlight_power(void)
  804 +{
  805 + int ret = eeepc_wmi_get_devstate_simple(EEEPC_WMI_DEVID_BACKLIGHT);
  806 +
  807 + if (ret < 0)
  808 + return ret;
  809 +
  810 + return ret ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
  811 +}
  812 +
  813 +static int read_brightness(struct backlight_device *bd)
  814 +{
  815 + u32 retval;
  816 + acpi_status status;
  817 +
  818 + status = eeepc_wmi_get_devstate(EEEPC_WMI_DEVID_BRIGHTNESS, &retval);
  819 +
  820 + if (ACPI_FAILURE(status))
  821 + return -EIO;
  822 + else
  823 + return retval & EEEPC_WMI_DSTS_BRIGHTNESS_MASK;
  824 +}
  825 +
  826 +static int update_bl_status(struct backlight_device *bd)
  827 +{
  828 + u32 ctrl_param;
  829 + acpi_status status;
  830 + int power;
  831 +
  832 + ctrl_param = bd->props.brightness;
  833 +
  834 + status = eeepc_wmi_set_devstate(EEEPC_WMI_DEVID_BRIGHTNESS,
  835 + ctrl_param, NULL);
  836 +
  837 + if (ACPI_FAILURE(status))
  838 + return -EIO;
  839 +
  840 + power = read_backlight_power();
  841 + if (power != -ENODEV && bd->props.power != power) {
  842 + ctrl_param = !!(bd->props.power == FB_BLANK_UNBLANK);
  843 + status = eeepc_wmi_set_devstate(EEEPC_WMI_DEVID_BACKLIGHT,
  844 + ctrl_param, NULL);
  845 +
  846 + if (ACPI_FAILURE(status))
  847 + return -EIO;
  848 + }
  849 + return 0;
  850 +}
  851 +
  852 +static const struct backlight_ops eeepc_wmi_bl_ops = {
  853 + .get_brightness = read_brightness,
  854 + .update_status = update_bl_status,
  855 +};
  856 +
  857 +static int eeepc_wmi_backlight_notify(struct eeepc_wmi *eeepc, int code)
  858 +{
  859 + struct backlight_device *bd = eeepc->backlight_device;
  860 + int old = bd->props.brightness;
  861 + int new = old;
  862 +
  863 + if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX)
  864 + new = code - NOTIFY_BRNUP_MIN + 1;
  865 + else if (code >= NOTIFY_BRNDOWN_MIN && code <= NOTIFY_BRNDOWN_MAX)
  866 + new = code - NOTIFY_BRNDOWN_MIN;
  867 +
  868 + bd->props.brightness = new;
  869 + backlight_update_status(bd);
  870 + backlight_force_update(bd, BACKLIGHT_UPDATE_HOTKEY);
  871 +
  872 + return old;
  873 +}
  874 +
  875 +static int eeepc_wmi_backlight_init(struct eeepc_wmi *eeepc)
  876 +{
  877 + struct backlight_device *bd;
  878 + struct backlight_properties props;
  879 + int max;
  880 + int power;
  881 +
  882 + max = eeepc_wmi_get_devstate_bits(EEEPC_WMI_DEVID_BRIGHTNESS,
  883 + EEEPC_WMI_DSTS_MAX_BRIGTH_MASK);
  884 + power = read_backlight_power();
  885 +
  886 + if (max < 0 && power < 0) {
  887 + /* Try to keep the original error */
  888 + if (max == -ENODEV && power == -ENODEV)
  889 + return -ENODEV;
  890 + if (max != -ENODEV)
  891 + return max;
  892 + else
  893 + return power;
  894 + }
  895 + if (max == -ENODEV)
  896 + max = 0;
  897 + if (power == -ENODEV)
  898 + power = FB_BLANK_UNBLANK;
  899 +
  900 + memset(&props, 0, sizeof(struct backlight_properties));
  901 + props.max_brightness = max;
  902 + bd = backlight_device_register(EEEPC_WMI_FILE,
  903 + &eeepc->platform_device->dev, eeepc,
  904 + &eeepc_wmi_bl_ops, &props);
  905 + if (IS_ERR(bd)) {
  906 + pr_err("Could not register backlight device\n");
  907 + return PTR_ERR(bd);
  908 + }
  909 +
  910 + eeepc->backlight_device = bd;
  911 +
  912 + bd->props.brightness = read_brightness(bd);
  913 + bd->props.power = power;
  914 + backlight_update_status(bd);
  915 +
  916 + return 0;
  917 +}
  918 +
  919 +static void eeepc_wmi_backlight_exit(struct eeepc_wmi *eeepc)
  920 +{
  921 + if (eeepc->backlight_device)
  922 + backlight_device_unregister(eeepc->backlight_device);
  923 +
  924 + eeepc->backlight_device = NULL;
  925 +}
  926 +
  927 +static void eeepc_wmi_notify(u32 value, void *context)
  928 +{
  929 + struct eeepc_wmi *eeepc = context;
  930 + struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
  931 + union acpi_object *obj;
  932 + acpi_status status;
  933 + int code;
  934 + int orig_code;
  935 +
  936 + status = wmi_get_event_data(value, &response);
  937 + if (status != AE_OK) {
  938 + pr_err("bad event status 0x%x\n", status);
  939 + return;
  940 + }
  941 +
  942 + obj = (union acpi_object *)response.pointer;
  943 +
  944 + if (obj && obj->type == ACPI_TYPE_INTEGER) {
  945 + code = obj->integer.value;
  946 + orig_code = code;
  947 +
  948 + if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX)
  949 + code = NOTIFY_BRNUP_MIN;
  950 + else if (code >= NOTIFY_BRNDOWN_MIN &&
  951 + code <= NOTIFY_BRNDOWN_MAX)
  952 + code = NOTIFY_BRNDOWN_MIN;
  953 +
  954 + if (code == NOTIFY_BRNUP_MIN || code == NOTIFY_BRNDOWN_MIN) {
  955 + if (!acpi_video_backlight_support())
  956 + eeepc_wmi_backlight_notify(eeepc, orig_code);
  957 + }
  958 +
  959 + if (!sparse_keymap_report_event(eeepc->inputdev,
  960 + code, 1, true))
  961 + pr_info("Unknown key %x pressed\n", code);
  962 + }
  963 +
  964 + kfree(obj);
  965 +}
  966 +
  967 +/*
  968 + * Sys helpers
  969 + */
  970 +static int parse_arg(const char *buf, unsigned long count, int *val)
  971 +{
  972 + if (!count)
  973 + return 0;
  974 + if (sscanf(buf, "%i", val) != 1)
  975 + return -EINVAL;
  976 + return count;
  977 +}
  978 +
  979 +static ssize_t store_sys_wmi(int devid, const char *buf, size_t count)
  980 +{
  981 + acpi_status status;
  982 + u32 retval;
  983 + int rv, value;
  984 +
  985 + value = eeepc_wmi_get_devstate_simple(devid);
  986 + if (value == -ENODEV) /* Check device presence */
  987 + return value;
  988 +
  989 + rv = parse_arg(buf, count, &value);
  990 + status = eeepc_wmi_set_devstate(devid, value, &retval);
  991 +
  992 + if (ACPI_FAILURE(status))
  993 + return -EIO;
  994 + return rv;
  995 +}
  996 +
  997 +static ssize_t show_sys_wmi(int devid, char *buf)
  998 +{
  999 + int value = eeepc_wmi_get_devstate_simple(devid);
  1000 +
  1001 + if (value < 0)
  1002 + return value;
  1003 +
  1004 + return sprintf(buf, "%d\n", value);
  1005 +}
  1006 +
  1007 +#define EEEPC_WMI_CREATE_DEVICE_ATTR(_name, _mode, _cm) \
  1008 + static ssize_t show_##_name(struct device *dev, \
  1009 + struct device_attribute *attr, \
  1010 + char *buf) \
  1011 + { \
  1012 + return show_sys_wmi(_cm, buf); \
  1013 + } \
  1014 + static ssize_t store_##_name(struct device *dev, \
  1015 + struct device_attribute *attr, \
  1016 + const char *buf, size_t count) \
  1017 + { \
  1018 + return store_sys_wmi(_cm, buf, count); \
  1019 + } \
  1020 + static struct device_attribute dev_attr_##_name = { \
  1021 + .attr = { \
  1022 + .name = __stringify(_name), \
  1023 + .mode = _mode }, \
  1024 + .show = show_##_name, \
  1025 + .store = store_##_name, \
  1026 + }
  1027 +
  1028 +EEEPC_WMI_CREATE_DEVICE_ATTR(touchpad, 0644, EEEPC_WMI_DEVID_TOUCHPAD);
  1029 +EEEPC_WMI_CREATE_DEVICE_ATTR(camera, 0644, EEEPC_WMI_DEVID_CAMERA);
  1030 +EEEPC_WMI_CREATE_DEVICE_ATTR(cardr, 0644, EEEPC_WMI_DEVID_CARDREADER);
  1031 +
  1032 +static ssize_t store_cpufv(struct device *dev, struct device_attribute *attr,
  1033 + const char *buf, size_t count)
  1034 +{
  1035 + int value;
  1036 + struct acpi_buffer input = { (acpi_size)sizeof(value), &value };
  1037 + acpi_status status;
  1038 +
  1039 + if (!count || sscanf(buf, "%i", &value) != 1)
  1040 + return -EINVAL;
  1041 + if (value < 0 || value > 2)
  1042 + return -EINVAL;
  1043 +
  1044 + status = wmi_evaluate_method(EEEPC_WMI_MGMT_GUID,
  1045 + 1, EEEPC_WMI_METHODID_CFVS, &input, NULL);
  1046 +
  1047 + if (ACPI_FAILURE(status))
  1048 + return -EIO;
  1049 + else
  1050 + return count;
  1051 +}
  1052 +
  1053 +static DEVICE_ATTR(cpufv, S_IRUGO | S_IWUSR, NULL, store_cpufv);
  1054 +
  1055 +static struct attribute *platform_attributes[] = {
  1056 + &dev_attr_cpufv.attr,
  1057 + &dev_attr_camera.attr,
  1058 + &dev_attr_cardr.attr,
  1059 + &dev_attr_touchpad.attr,
  1060 + NULL
  1061 +};
  1062 +
  1063 +static mode_t eeepc_sysfs_is_visible(struct kobject *kobj,
  1064 + struct attribute *attr,
  1065 + int idx)
  1066 +{
  1067 + bool supported = true;
  1068 + int devid = -1;
  1069 +
  1070 + if (attr == &dev_attr_camera.attr)
  1071 + devid = EEEPC_WMI_DEVID_CAMERA;
  1072 + else if (attr == &dev_attr_cardr.attr)
  1073 + devid = EEEPC_WMI_DEVID_CARDREADER;
  1074 + else if (attr == &dev_attr_touchpad.attr)
  1075 + devid = EEEPC_WMI_DEVID_TOUCHPAD;
  1076 +
  1077 + if (devid != -1)
  1078 + supported = eeepc_wmi_get_devstate_simple(devid) != -ENODEV;
  1079 +
  1080 + return supported ? attr->mode : 0;
  1081 +}
  1082 +
  1083 +static struct attribute_group platform_attribute_group = {
  1084 + .is_visible = eeepc_sysfs_is_visible,
  1085 + .attrs = platform_attributes
  1086 +};
  1087 +
  1088 +static void eeepc_wmi_sysfs_exit(struct platform_device *device)
  1089 +{
  1090 + sysfs_remove_group(&device->dev.kobj, &platform_attribute_group);
  1091 +}
  1092 +
  1093 +static int eeepc_wmi_sysfs_init(struct platform_device *device)
  1094 +{
  1095 + return sysfs_create_group(&device->dev.kobj, &platform_attribute_group);
  1096 +}
  1097 +
  1098 +/*
  1099 + * Platform device
  1100 + */
  1101 +static int __init eeepc_wmi_platform_init(struct eeepc_wmi *eeepc)
  1102 +{
  1103 + return eeepc_wmi_sysfs_init(eeepc->platform_device);
  1104 +}
  1105 +
  1106 +static void eeepc_wmi_platform_exit(struct eeepc_wmi *eeepc)
  1107 +{
  1108 + eeepc_wmi_sysfs_exit(eeepc->platform_device);
  1109 +}
  1110 +
  1111 +/*
  1112 + * debugfs
  1113 + */
  1114 +struct eeepc_wmi_debugfs_node {
  1115 + struct eeepc_wmi *eeepc;
  1116 + char *name;
  1117 + int (*show)(struct seq_file *m, void *data);
  1118 +};
  1119 +
  1120 +static int show_dsts(struct seq_file *m, void *data)
  1121 +{
  1122 + struct eeepc_wmi *eeepc = m->private;
  1123 + acpi_status status;
  1124 + u32 retval = -1;
  1125 +
  1126 + status = eeepc_wmi_get_devstate(eeepc->debug.dev_id, &retval);
  1127 +
  1128 + if (ACPI_FAILURE(status))
  1129 + return -EIO;
  1130 +
  1131 + seq_printf(m, "DSTS(%x) = %x\n", eeepc->debug.dev_id, retval);
  1132 +
  1133 + return 0;
  1134 +}
  1135 +
  1136 +static int show_devs(struct seq_file *m, void *data)
  1137 +{
  1138 + struct eeepc_wmi *eeepc = m->private;
  1139 + acpi_status status;
  1140 + u32 retval = -1;
  1141 +
  1142 + status = eeepc_wmi_set_devstate(eeepc->debug.dev_id,
  1143 + eeepc->debug.ctrl_param, &retval);
  1144 + if (ACPI_FAILURE(status))
  1145 + return -EIO;
  1146 +
  1147 + seq_printf(m, "DEVS(%x, %x) = %x\n", eeepc->debug.dev_id,
  1148 + eeepc->debug.ctrl_param, retval);
  1149 +
  1150 + return 0;
  1151 +}
  1152 +
  1153 +static struct eeepc_wmi_debugfs_node eeepc_wmi_debug_files[] = {
  1154 + { NULL, "devs", show_devs },
  1155 + { NULL, "dsts", show_dsts },
  1156 +};
  1157 +
  1158 +static int eeepc_wmi_debugfs_open(struct inode *inode, struct file *file)
  1159 +{
  1160 + struct eeepc_wmi_debugfs_node *node = inode->i_private;
  1161 +
  1162 + return single_open(file, node->show, node->eeepc);
  1163 +}
  1164 +
  1165 +static const struct file_operations eeepc_wmi_debugfs_io_ops = {
  1166 + .owner = THIS_MODULE,
  1167 + .open = eeepc_wmi_debugfs_open,
  1168 + .read = seq_read,
  1169 + .llseek = seq_lseek,
  1170 + .release = single_release,
  1171 +};
  1172 +
  1173 +static void eeepc_wmi_debugfs_exit(struct eeepc_wmi *eeepc)
  1174 +{
  1175 + debugfs_remove_recursive(eeepc->debug.root);
  1176 +}
  1177 +
  1178 +static int eeepc_wmi_debugfs_init(struct eeepc_wmi *eeepc)
  1179 +{
  1180 + struct dentry *dent;
  1181 + int i;
  1182 +
  1183 + eeepc->debug.root = debugfs_create_dir(EEEPC_WMI_FILE, NULL);
  1184 + if (!eeepc->debug.root) {
  1185 + pr_err("failed to create debugfs directory");
  1186 + goto error_debugfs;
  1187 + }
  1188 +
  1189 + dent = debugfs_create_x32("dev_id", S_IRUGO|S_IWUSR,
  1190 + eeepc->debug.root, &eeepc->debug.dev_id);
  1191 + if (!dent)
  1192 + goto error_debugfs;
  1193 +
  1194 + dent = debugfs_create_x32("ctrl_param", S_IRUGO|S_IWUSR,
  1195 + eeepc->debug.root, &eeepc->debug.ctrl_param);
  1196 + if (!dent)
  1197 + goto error_debugfs;
  1198 +
  1199 + for (i = 0; i < ARRAY_SIZE(eeepc_wmi_debug_files); i++) {
  1200 + struct eeepc_wmi_debugfs_node *node = &eeepc_wmi_debug_files[i];
  1201 +
  1202 + node->eeepc = eeepc;
  1203 + dent = debugfs_create_file(node->name, S_IFREG | S_IRUGO,
  1204 + eeepc->debug.root, node,
  1205 + &eeepc_wmi_debugfs_io_ops);
  1206 + if (!dent) {
  1207 + pr_err("failed to create debug file: %s\n", node->name);
  1208 + goto error_debugfs;
  1209 + }
  1210 + }
  1211 +
  1212 + return 0;
  1213 +
  1214 +error_debugfs:
  1215 + eeepc_wmi_debugfs_exit(eeepc);
  1216 + return -ENOMEM;
  1217 +}
  1218 +
  1219 +/*
  1220 + * WMI Driver
  1221 + */
  1222 +static void eeepc_dmi_check(struct eeepc_wmi *eeepc)
  1223 +{
  1224 + const char *model;
  1225 +
  1226 + model = dmi_get_system_info(DMI_PRODUCT_NAME);
  1227 + if (!model)
  1228 + return;
  1229 +
  1230 + /*
  1231 + * Whitelist for wlan hotplug
  1232 + *
  1233 + * Eeepc 1000H needs the current hotplug code to handle
  1234 + * Fn+F2 correctly. We may add other Eeepc here later, but
  1235 + * it seems that most of the laptops supported by eeepc-wmi
  1236 + * don't need to be on this list
  1237 + */
  1238 + if (strcmp(model, "1000H") == 0) {
  1239 + eeepc->hotplug_wireless = true;
  1240 + pr_info("wlan hotplug enabled\n");
  1241 + }
  1242 +}
  1243 +
  1244 +static int __init eeepc_wmi_add(struct platform_device *pdev)
  1245 +{
  1246 + struct eeepc_wmi *eeepc;
  1247 + acpi_status status;
  1248 + int err;
  1249 +
  1250 + eeepc = kzalloc(sizeof(struct eeepc_wmi), GFP_KERNEL);
  1251 + if (!eeepc)
  1252 + return -ENOMEM;
  1253 +
  1254 + eeepc->platform_device = pdev;
  1255 + platform_set_drvdata(eeepc->platform_device, eeepc);
  1256 +
  1257 + eeepc->hotplug_wireless = hotplug_wireless;
  1258 + eeepc_dmi_check(eeepc);
  1259 +
  1260 + err = eeepc_wmi_platform_init(eeepc);
  1261 + if (err)
  1262 + goto fail_platform;
  1263 +
  1264 + err = eeepc_wmi_input_init(eeepc);
  1265 + if (err)
  1266 + goto fail_input;
  1267 +
  1268 + err = eeepc_wmi_led_init(eeepc);
  1269 + if (err)
  1270 + goto fail_leds;
  1271 +
  1272 + err = eeepc_wmi_rfkill_init(eeepc);
  1273 + if (err)
  1274 + goto fail_rfkill;
  1275 +
  1276 + if (!acpi_video_backlight_support()) {
  1277 + err = eeepc_wmi_backlight_init(eeepc);
  1278 + if (err && err != -ENODEV)
  1279 + goto fail_backlight;
  1280 + } else
  1281 + pr_info("Backlight controlled by ACPI video driver\n");
  1282 +
  1283 + status = wmi_install_notify_handler(EEEPC_WMI_EVENT_GUID,
  1284 + eeepc_wmi_notify, eeepc);
  1285 + if (ACPI_FAILURE(status)) {
  1286 + pr_err("Unable to register notify handler - %d\n",
  1287 + status);
  1288 + err = -ENODEV;
  1289 + goto fail_wmi_handler;
  1290 + }
  1291 +
  1292 + err = eeepc_wmi_debugfs_init(eeepc);
  1293 + if (err)
  1294 + goto fail_debugfs;
  1295 +
  1296 + return 0;
  1297 +
  1298 +fail_debugfs:
  1299 + wmi_remove_notify_handler(EEEPC_WMI_EVENT_GUID);
  1300 +fail_wmi_handler:
  1301 + eeepc_wmi_backlight_exit(eeepc);
  1302 +fail_backlight:
  1303 + eeepc_wmi_rfkill_exit(eeepc);
  1304 +fail_rfkill:
  1305 + eeepc_wmi_led_exit(eeepc);
  1306 +fail_leds:
  1307 + eeepc_wmi_input_exit(eeepc);
  1308 +fail_input:
  1309 + eeepc_wmi_platform_exit(eeepc);
  1310 +fail_platform:
  1311 + kfree(eeepc);
  1312 + return err;
  1313 +}
  1314 +
  1315 +static int __exit eeepc_wmi_remove(struct platform_device *device)
  1316 +{
  1317 + struct eeepc_wmi *eeepc;
  1318 +
  1319 + eeepc = platform_get_drvdata(device);
  1320 + wmi_remove_notify_handler(EEEPC_WMI_EVENT_GUID);
  1321 + eeepc_wmi_backlight_exit(eeepc);
  1322 + eeepc_wmi_input_exit(eeepc);
  1323 + eeepc_wmi_led_exit(eeepc);
  1324 + eeepc_wmi_rfkill_exit(eeepc);
  1325 + eeepc_wmi_debugfs_exit(eeepc);
  1326 + eeepc_wmi_platform_exit(eeepc);
  1327 +
  1328 + kfree(eeepc);
  1329 + return 0;
  1330 +}
  1331 +
  1332 +/*
  1333 + * Platform driver - hibernate/resume callbacks
  1334 + */
  1335 +static int eeepc_hotk_thaw(struct device *device)
  1336 +{
  1337 + struct eeepc_wmi *eeepc = dev_get_drvdata(device);
  1338 +
  1339 + if (eeepc->wlan_rfkill) {
  1340 + bool wlan;
  1341 +
  1342 + /*
  1343 + * Work around bios bug - acpi _PTS turns off the wireless led
  1344 + * during suspend. Normally it restores it on resume, but
  1345 + * we should kick it ourselves in case hibernation is aborted.
  1346 + */
  1347 + wlan = eeepc_wmi_get_devstate_simple(EEEPC_WMI_DEVID_WLAN);
  1348 + eeepc_wmi_set_devstate(EEEPC_WMI_DEVID_WLAN, wlan, NULL);
  1349 + }
  1350 +
  1351 + return 0;
  1352 +}
  1353 +
  1354 +static int eeepc_hotk_restore(struct device *device)
  1355 +{
  1356 + struct eeepc_wmi *eeepc = dev_get_drvdata(device);
  1357 + int bl;
  1358 +
  1359 + /* Refresh both wlan rfkill state and pci hotplug */
  1360 + if (eeepc->wlan_rfkill)
  1361 + eeepc_rfkill_hotplug(eeepc);
  1362 +
  1363 + if (eeepc->bluetooth_rfkill) {
  1364 + bl = !eeepc_wmi_get_devstate_simple(EEEPC_WMI_DEVID_BLUETOOTH);
  1365 + rfkill_set_sw_state(eeepc->bluetooth_rfkill, bl);
  1366 + }
  1367 + if (eeepc->wimax_rfkill) {
  1368 + bl = !eeepc_wmi_get_devstate_simple(EEEPC_WMI_DEVID_WIMAX);
  1369 + rfkill_set_sw_state(eeepc->wimax_rfkill, bl);
  1370 + }
  1371 + if (eeepc->wwan3g_rfkill) {
  1372 + bl = !eeepc_wmi_get_devstate_simple(EEEPC_WMI_DEVID_WWAN3G);
  1373 + rfkill_set_sw_state(eeepc->wwan3g_rfkill, bl);
  1374 + }
  1375 +
  1376 + return 0;
  1377 +}
  1378 +
  1379 +static const struct dev_pm_ops eeepc_pm_ops = {
  1380 + .thaw = eeepc_hotk_thaw,
  1381 + .restore = eeepc_hotk_restore,
  1382 +};
  1383 +
  1384 +static struct platform_driver platform_driver = {
  1385 + .remove = __exit_p(eeepc_wmi_remove),
  1386 + .driver = {
  1387 + .name = EEEPC_WMI_FILE,
  1388 + .owner = THIS_MODULE,
  1389 + .pm = &eeepc_pm_ops,
  1390 + },
  1391 +};
  1392 +
  1393 +static acpi_status __init eeepc_wmi_parse_device(acpi_handle handle, u32 level,
  1394 + void *context, void **retval)
  1395 +{
  1396 + pr_warning("Found legacy ATKD device (%s)", EEEPC_ACPI_HID);
  1397 + *(bool *)context = true;
  1398 + return AE_CTRL_TERMINATE;
  1399 +}
  1400 +
  1401 +static int __init eeepc_wmi_check_atkd(void)
  1402 +{
  1403 + acpi_status status;
  1404 + bool found = false;
  1405 +
  1406 + status = acpi_get_devices(EEEPC_ACPI_HID, eeepc_wmi_parse_device,
  1407 + &found, NULL);
  1408 +
  1409 + if (ACPI_FAILURE(status) || !found)
  1410 + return 0;
  1411 + return -1;
  1412 +}
  1413 +
  1414 +static int __init eeepc_wmi_probe(struct platform_device *pdev)
  1415 +{
  1416 + if (!wmi_has_guid(EEEPC_WMI_EVENT_GUID) ||
  1417 + !wmi_has_guid(EEEPC_WMI_MGMT_GUID)) {
  1418 + pr_warning("No known WMI GUID found\n");
  1419 + return -ENODEV;
  1420 + }
  1421 +
  1422 + if (eeepc_wmi_check_atkd()) {
  1423 + pr_warning("WMI device present, but legacy ATKD device is also "
  1424 + "present and enabled.");
  1425 + pr_warning("You probably booted with acpi_osi=\"Linux\" or "
  1426 + "acpi_osi=\"!Windows 2009\"");
  1427 + pr_warning("Can't load eeepc-wmi, use default acpi_osi "
  1428 + "(preferred) or eeepc-laptop");
  1429 + return -ENODEV;
  1430 + }
  1431 +
  1432 + return eeepc_wmi_add(pdev);
  1433 +}
  1434 +
  1435 +static struct platform_device *platform_device;
  1436 +
  1437 +static int __init eeepc_wmi_init(void)
  1438 +{
  1439 + platform_device = platform_create_bundle(&platform_driver,
  1440 + eeepc_wmi_probe,
  1441 + NULL, 0, NULL, 0);
  1442 + if (IS_ERR(platform_device))
  1443 + return PTR_ERR(platform_device);
  1444 + return 0;
  1445 +}
  1446 +
  1447 +static void __exit eeepc_wmi_exit(void)
  1448 +{
  1449 + platform_device_unregister(platform_device);
  1450 + platform_driver_unregister(&platform_driver);
  1451 +}
  1452 +
  1453 +module_init(eeepc_wmi_init);
  1454 +module_exit(eeepc_wmi_exit);
drivers/platform/x86/eeepc-wmi.c
Changes suppressed. Click to show
1   -/*
2   - * Eee PC WMI hotkey driver
3   - *
4   - * Copyright(C) 2010 Intel Corporation.
5   - * Copyright(C) 2010 Corentin Chary <corentin.chary@gmail.com>
6   - *
7   - * Portions based on wistron_btns.c:
8   - * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz>
9   - * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org>
10   - * Copyright (C) 2005 Dmitry Torokhov <dtor@mail.ru>
11   - *
12   - * This program is free software; you can redistribute it and/or modify
13   - * it under the terms of the GNU General Public License as published by
14   - * the Free Software Foundation; either version 2 of the License, or
15   - * (at your option) any later version.
16   - *
17   - * This program is distributed in the hope that it will be useful,
18   - * but WITHOUT ANY WARRANTY; without even the implied warranty of
19   - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20   - * GNU General Public License for more details.
21   - *
22   - * You should have received a copy of the GNU General Public License
23   - * along with this program; if not, write to the Free Software
24   - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25   - */
26   -
27   -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
28   -
29   -#include <linux/kernel.h>
30   -#include <linux/module.h>
31   -#include <linux/init.h>
32   -#include <linux/types.h>
33   -#include <linux/slab.h>
34   -#include <linux/input.h>
35   -#include <linux/input/sparse-keymap.h>
36   -#include <linux/fb.h>
37   -#include <linux/backlight.h>
38   -#include <linux/leds.h>
39   -#include <linux/rfkill.h>
40   -#include <linux/pci.h>
41   -#include <linux/pci_hotplug.h>
42   -#include <linux/debugfs.h>
43   -#include <linux/seq_file.h>
44   -#include <linux/platform_device.h>
45   -#include <linux/dmi.h>
46   -#include <acpi/acpi_bus.h>
47   -#include <acpi/acpi_drivers.h>
48   -
49   -#define EEEPC_WMI_FILE "eeepc-wmi"
50   -
51   -MODULE_AUTHOR("Yong Wang <yong.y.wang@intel.com>");
52   -MODULE_DESCRIPTION("Eee PC WMI Hotkey Driver");
53   -MODULE_LICENSE("GPL");
54   -
55   -#define EEEPC_ACPI_HID "ASUS010" /* old _HID used in eeepc-laptop */
56   -
57   -#define EEEPC_WMI_EVENT_GUID "ABBC0F72-8EA1-11D1-00A0-C90629100000"
58   -#define EEEPC_WMI_MGMT_GUID "97845ED0-4E6D-11DE-8A39-0800200C9A66"
59   -
60   -MODULE_ALIAS("wmi:"EEEPC_WMI_EVENT_GUID);
61   -MODULE_ALIAS("wmi:"EEEPC_WMI_MGMT_GUID);
62   -
63   -#define NOTIFY_BRNUP_MIN 0x11
64   -#define NOTIFY_BRNUP_MAX 0x1f
65   -#define NOTIFY_BRNDOWN_MIN 0x20
66   -#define NOTIFY_BRNDOWN_MAX 0x2e
67   -
68   -/* WMI Methods */
69   -#define EEEPC_WMI_METHODID_DSTS 0x53544344
70   -#define EEEPC_WMI_METHODID_DEVS 0x53564544
71   -#define EEEPC_WMI_METHODID_CFVS 0x53564643
72   -
73   -/* Wireless */
74   -#define EEEPC_WMI_DEVID_WLAN 0x00010011
75   -#define EEEPC_WMI_DEVID_BLUETOOTH 0x00010013
76   -#define EEEPC_WMI_DEVID_WIMAX 0x00010017
77   -#define EEEPC_WMI_DEVID_WWAN3G 0x00010019
78   -
79   -/* Backlight and Brightness */
80   -#define EEEPC_WMI_DEVID_BACKLIGHT 0x00050011
81   -#define EEEPC_WMI_DEVID_BRIGHTNESS 0x00050012
82   -
83   -/* Misc */
84   -#define EEEPC_WMI_DEVID_CAMERA 0x00060013
85   -
86   -/* Storage */
87   -#define EEEPC_WMI_DEVID_CARDREADER 0x00080013
88   -
89   -/* Input */
90   -#define EEEPC_WMI_DEVID_TOUCHPAD 0x00100011
91   -#define EEEPC_WMI_DEVID_TOUCHPAD_LED 0x00100012
92   -
93   -/* DSTS masks */
94   -#define EEEPC_WMI_DSTS_STATUS_BIT 0x00000001
95   -#define EEEPC_WMI_DSTS_PRESENCE_BIT 0x00010000
96   -#define EEEPC_WMI_DSTS_BRIGHTNESS_MASK 0x000000FF
97   -#define EEEPC_WMI_DSTS_MAX_BRIGTH_MASK 0x0000FF00
98   -
99   -static bool hotplug_wireless;
100   -
101   -module_param(hotplug_wireless, bool, 0444);
102   -MODULE_PARM_DESC(hotplug_wireless,
103   - "Enable hotplug for wireless device. "
104   - "If your laptop needs that, please report to "
105   - "acpi4asus-user@lists.sourceforge.net.");
106   -
107   -static const struct key_entry eeepc_wmi_keymap[] = {
108   - /* Sleep already handled via generic ACPI code */
109   - { KE_IGNORE, NOTIFY_BRNDOWN_MIN, { KEY_BRIGHTNESSDOWN } },
110   - { KE_IGNORE, NOTIFY_BRNUP_MIN, { KEY_BRIGHTNESSUP } },
111   - { KE_KEY, 0x30, { KEY_VOLUMEUP } },
112   - { KE_KEY, 0x31, { KEY_VOLUMEDOWN } },
113   - { KE_KEY, 0x32, { KEY_MUTE } },
114   - { KE_KEY, 0x5c, { KEY_F15 } }, /* Power Gear key */
115   - { KE_KEY, 0x5d, { KEY_WLAN } },
116   - { KE_KEY, 0x6b, { KEY_F13 } }, /* Disable Touchpad */
117   - { KE_KEY, 0x82, { KEY_CAMERA } },
118   - { KE_KEY, 0x83, { KEY_CAMERA_ZOOMIN } },
119   - { KE_KEY, 0x88, { KEY_WLAN } },
120   - { KE_KEY, 0xcc, { KEY_SWITCHVIDEOMODE } },
121   - { KE_KEY, 0xe0, { KEY_PROG1 } }, /* Task Manager */
122   - { KE_KEY, 0xe1, { KEY_F14 } }, /* Change Resolution */
123   - { KE_KEY, 0xe9, { KEY_BRIGHTNESS_ZERO } },
124   - { KE_KEY, 0xeb, { KEY_CAMERA_ZOOMOUT } },
125   - { KE_KEY, 0xec, { KEY_CAMERA_UP } },
126   - { KE_KEY, 0xed, { KEY_CAMERA_DOWN } },
127   - { KE_KEY, 0xee, { KEY_CAMERA_LEFT } },
128   - { KE_KEY, 0xef, { KEY_CAMERA_RIGHT } },
129   - { KE_END, 0},
130   -};
131   -
132   -struct bios_args {
133   - u32 dev_id;
134   - u32 ctrl_param;
135   -};
136   -
137   -/*
138   - * eeepc-wmi/ - debugfs root directory
139   - * dev_id - current dev_id
140   - * ctrl_param - current ctrl_param
141   - * devs - call DEVS(dev_id, ctrl_param) and print result
142   - * dsts - call DSTS(dev_id) and print result
143   - */
144   -struct eeepc_wmi_debug {
145   - struct dentry *root;
146   - u32 dev_id;
147   - u32 ctrl_param;
148   -};
149   -
150   -struct eeepc_wmi {
151   - bool hotplug_wireless;
152   -
153   - struct input_dev *inputdev;
154   - struct backlight_device *backlight_device;
155   - struct platform_device *platform_device;
156   -
157   - struct led_classdev tpd_led;
158   - int tpd_led_wk;
159   - struct workqueue_struct *led_workqueue;
160   - struct work_struct tpd_led_work;
161   -
162   - struct rfkill *wlan_rfkill;
163   - struct rfkill *bluetooth_rfkill;
164   - struct rfkill *wimax_rfkill;
165   - struct rfkill *wwan3g_rfkill;
166   -
167   - struct hotplug_slot *hotplug_slot;
168   - struct mutex hotplug_lock;
169   - struct mutex wmi_lock;
170   - struct workqueue_struct *hotplug_workqueue;
171   - struct work_struct hotplug_work;
172   -
173   - struct eeepc_wmi_debug debug;
174   -};
175   -
176   -static int eeepc_wmi_input_init(struct eeepc_wmi *eeepc)
177   -{
178   - int err;
179   -
180   - eeepc->inputdev = input_allocate_device();
181   - if (!eeepc->inputdev)
182   - return -ENOMEM;
183   -
184   - eeepc->inputdev->name = "Eee PC WMI hotkeys";
185   - eeepc->inputdev->phys = EEEPC_WMI_FILE "/input0";
186   - eeepc->inputdev->id.bustype = BUS_HOST;
187   - eeepc->inputdev->dev.parent = &eeepc->platform_device->dev;
188   -
189   - err = sparse_keymap_setup(eeepc->inputdev, eeepc_wmi_keymap, NULL);
190   - if (err)
191   - goto err_free_dev;
192   -
193   - err = input_register_device(eeepc->inputdev);
194   - if (err)
195   - goto err_free_keymap;
196   -
197   - return 0;
198   -
199   -err_free_keymap:
200   - sparse_keymap_free(eeepc->inputdev);
201   -err_free_dev:
202   - input_free_device(eeepc->inputdev);
203   - return err;
204   -}
205   -
206   -static void eeepc_wmi_input_exit(struct eeepc_wmi *eeepc)
207   -{
208   - if (eeepc->inputdev) {
209   - sparse_keymap_free(eeepc->inputdev);
210   - input_unregister_device(eeepc->inputdev);
211   - }
212   -
213   - eeepc->inputdev = NULL;
214   -}
215   -
216   -static acpi_status eeepc_wmi_get_devstate(u32 dev_id, u32 *retval)
217   -{
218   - struct acpi_buffer input = { (acpi_size)sizeof(u32), &dev_id };
219   - struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
220   - union acpi_object *obj;
221   - acpi_status status;
222   - u32 tmp;
223   -
224   - status = wmi_evaluate_method(EEEPC_WMI_MGMT_GUID,
225   - 1, EEEPC_WMI_METHODID_DSTS,
226   - &input, &output);
227   -
228   - if (ACPI_FAILURE(status))
229   - return status;
230   -
231   - obj = (union acpi_object *)output.pointer;
232   - if (obj && obj->type == ACPI_TYPE_INTEGER)
233   - tmp = (u32)obj->integer.value;
234   - else
235   - tmp = 0;
236   -
237   - if (retval)
238   - *retval = tmp;
239   -
240   - kfree(obj);
241   -
242   - return status;
243   -
244   -}
245   -
246   -static acpi_status eeepc_wmi_set_devstate(u32 dev_id, u32 ctrl_param,
247   - u32 *retval)
248   -{
249   - struct bios_args args = {
250   - .dev_id = dev_id,
251   - .ctrl_param = ctrl_param,
252   - };
253   - struct acpi_buffer input = { (acpi_size)sizeof(args), &args };
254   - acpi_status status;
255   -
256   - if (!retval) {
257   - status = wmi_evaluate_method(EEEPC_WMI_MGMT_GUID, 1,
258   - EEEPC_WMI_METHODID_DEVS,
259   - &input, NULL);
260   - } else {
261   - struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
262   - union acpi_object *obj;
263   - u32 tmp;
264   -
265   - status = wmi_evaluate_method(EEEPC_WMI_MGMT_GUID, 1,
266   - EEEPC_WMI_METHODID_DEVS,
267   - &input, &output);
268   -
269   - if (ACPI_FAILURE(status))
270   - return status;
271   -
272   - obj = (union acpi_object *)output.pointer;
273   - if (obj && obj->type == ACPI_TYPE_INTEGER)
274   - tmp = (u32)obj->integer.value;
275   - else
276   - tmp = 0;
277   -
278   - *retval = tmp;
279   -
280   - kfree(obj);
281   - }
282   -
283   - return status;
284   -}
285   -
286   -/* Helper for special devices with magic return codes */
287   -static int eeepc_wmi_get_devstate_bits(u32 dev_id, u32 mask)
288   -{
289   - u32 retval = 0;
290   - acpi_status status;
291   -
292   - status = eeepc_wmi_get_devstate(dev_id, &retval);
293   -
294   - if (ACPI_FAILURE(status))
295   - return -EINVAL;
296   -
297   - if (!(retval & EEEPC_WMI_DSTS_PRESENCE_BIT))
298   - return -ENODEV;
299   -
300   - return retval & mask;
301   -}
302   -
303   -static int eeepc_wmi_get_devstate_simple(u32 dev_id)
304   -{
305   - return eeepc_wmi_get_devstate_bits(dev_id, EEEPC_WMI_DSTS_STATUS_BIT);
306   -}
307   -
308   -/*
309   - * LEDs
310   - */
311   -/*
312   - * These functions actually update the LED's, and are called from a
313   - * workqueue. By doing this as separate work rather than when the LED
314   - * subsystem asks, we avoid messing with the Eeepc ACPI stuff during a
315   - * potentially bad time, such as a timer interrupt.
316   - */
317   -static void tpd_led_update(struct work_struct *work)
318   -{
319   - int ctrl_param;
320   - struct eeepc_wmi *eeepc;
321   -
322   - eeepc = container_of(work, struct eeepc_wmi, tpd_led_work);
323   -
324   - ctrl_param = eeepc->tpd_led_wk;
325   - eeepc_wmi_set_devstate(EEEPC_WMI_DEVID_TOUCHPAD_LED, ctrl_param, NULL);
326   -}
327   -
328   -static void tpd_led_set(struct led_classdev *led_cdev,
329   - enum led_brightness value)
330   -{
331   - struct eeepc_wmi *eeepc;
332   -
333   - eeepc = container_of(led_cdev, struct eeepc_wmi, tpd_led);
334   -
335   - eeepc->tpd_led_wk = !!value;
336   - queue_work(eeepc->led_workqueue, &eeepc->tpd_led_work);
337   -}
338   -
339   -static int read_tpd_led_state(struct eeepc_wmi *eeepc)
340   -{
341   - return eeepc_wmi_get_devstate_simple(EEEPC_WMI_DEVID_TOUCHPAD_LED);
342   -}
343   -
344   -static enum led_brightness tpd_led_get(struct led_classdev *led_cdev)
345   -{
346   - struct eeepc_wmi *eeepc;
347   -
348   - eeepc = container_of(led_cdev, struct eeepc_wmi, tpd_led);
349   -
350   - return read_tpd_led_state(eeepc);
351   -}
352   -
353   -static int eeepc_wmi_led_init(struct eeepc_wmi *eeepc)
354   -{
355   - int rv;
356   -
357   - if (read_tpd_led_state(eeepc) < 0)
358   - return 0;
359   -
360   - eeepc->led_workqueue = create_singlethread_workqueue("led_workqueue");
361   - if (!eeepc->led_workqueue)
362   - return -ENOMEM;
363   - INIT_WORK(&eeepc->tpd_led_work, tpd_led_update);
364   -
365   - eeepc->tpd_led.name = "eeepc::touchpad";
366   - eeepc->tpd_led.brightness_set = tpd_led_set;
367   - eeepc->tpd_led.brightness_get = tpd_led_get;
368   - eeepc->tpd_led.max_brightness = 1;
369   -
370   - rv = led_classdev_register(&eeepc->platform_device->dev,
371   - &eeepc->tpd_led);
372   - if (rv) {
373   - destroy_workqueue(eeepc->led_workqueue);
374   - return rv;
375   - }
376   -
377   - return 0;
378   -}
379   -
380   -static void eeepc_wmi_led_exit(struct eeepc_wmi *eeepc)
381   -{
382   - if (eeepc->tpd_led.dev)
383   - led_classdev_unregister(&eeepc->tpd_led);
384   - if (eeepc->led_workqueue)
385   - destroy_workqueue(eeepc->led_workqueue);
386   -}
387   -
388   -/*
389   - * PCI hotplug (for wlan rfkill)
390   - */
391   -static bool eeepc_wlan_rfkill_blocked(struct eeepc_wmi *eeepc)
392   -{
393   - int result = eeepc_wmi_get_devstate_simple(EEEPC_WMI_DEVID_WLAN);
394   -
395   - if (result < 0)
396   - return false;
397   - return !result;
398   -}
399   -
400   -static void eeepc_rfkill_hotplug(struct eeepc_wmi *eeepc)
401   -{
402   - struct pci_dev *dev;
403   - struct pci_bus *bus;
404   - bool blocked;
405   - bool absent;
406   - u32 l;
407   -
408   - mutex_lock(&eeepc->wmi_lock);
409   - blocked = eeepc_wlan_rfkill_blocked(eeepc);
410   - mutex_unlock(&eeepc->wmi_lock);
411   -
412   - mutex_lock(&eeepc->hotplug_lock);
413   -
414   - if (eeepc->wlan_rfkill)
415   - rfkill_set_sw_state(eeepc->wlan_rfkill, blocked);
416   -
417   - if (eeepc->hotplug_slot) {
418   - bus = pci_find_bus(0, 1);
419   - if (!bus) {
420   - pr_warning("Unable to find PCI bus 1?\n");
421   - goto out_unlock;
422   - }
423   -
424   - if (pci_bus_read_config_dword(bus, 0, PCI_VENDOR_ID, &l)) {
425   - pr_err("Unable to read PCI config space?\n");
426   - goto out_unlock;
427   - }
428   - absent = (l == 0xffffffff);
429   -
430   - if (blocked != absent) {
431   - pr_warning("BIOS says wireless lan is %s, "
432   - "but the pci device is %s\n",
433   - blocked ? "blocked" : "unblocked",
434   - absent ? "absent" : "present");
435   - pr_warning("skipped wireless hotplug as probably "
436   - "inappropriate for this model\n");
437   - goto out_unlock;
438   - }
439   -
440   - if (!blocked) {
441   - dev = pci_get_slot(bus, 0);
442   - if (dev) {
443   - /* Device already present */
444   - pci_dev_put(dev);
445   - goto out_unlock;
446   - }
447   - dev = pci_scan_single_device(bus, 0);
448   - if (dev) {
449   - pci_bus_assign_resources(bus);
450   - if (pci_bus_add_device(dev))
451   - pr_err("Unable to hotplug wifi\n");
452   - }
453   - } else {
454   - dev = pci_get_slot(bus, 0);
455   - if (dev) {
456   - pci_remove_bus_device(dev);
457   - pci_dev_put(dev);
458   - }
459   - }
460   - }
461   -
462   -out_unlock:
463   - mutex_unlock(&eeepc->hotplug_lock);
464   -}
465   -
466   -static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
467   -{
468   - struct eeepc_wmi *eeepc = data;
469   -
470   - if (event != ACPI_NOTIFY_BUS_CHECK)
471   - return;
472   -
473   - /*
474   - * We can't call directly eeepc_rfkill_hotplug because most
475   - * of the time WMBC is still being executed and not reetrant.
476   - * There is currently no way to tell ACPICA that we want this
477   - * method to be serialized, we schedule a eeepc_rfkill_hotplug
478   - * call later, in a safer context.
479   - */
480   - queue_work(eeepc->hotplug_workqueue, &eeepc->hotplug_work);
481   -}
482   -
483   -static int eeepc_register_rfkill_notifier(struct eeepc_wmi *eeepc,
484   - char *node)
485   -{
486   - acpi_status status;
487   - acpi_handle handle;
488   -
489   - status = acpi_get_handle(NULL, node, &handle);
490   -
491   - if (ACPI_SUCCESS(status)) {
492   - status = acpi_install_notify_handler(handle,
493   - ACPI_SYSTEM_NOTIFY,
494   - eeepc_rfkill_notify,
495   - eeepc);
496   - if (ACPI_FAILURE(status))
497   - pr_warning("Failed to register notify on %s\n", node);
498   - } else
499   - return -ENODEV;
500   -
501   - return 0;
502   -}
503   -
504   -static void eeepc_unregister_rfkill_notifier(struct eeepc_wmi *eeepc,
505   - char *node)
506   -{
507   - acpi_status status = AE_OK;
508   - acpi_handle handle;
509   -
510   - status = acpi_get_handle(NULL, node, &handle);
511   -
512   - if (ACPI_SUCCESS(status)) {
513   - status = acpi_remove_notify_handler(handle,
514   - ACPI_SYSTEM_NOTIFY,
515   - eeepc_rfkill_notify);
516   - if (ACPI_FAILURE(status))
517   - pr_err("Error removing rfkill notify handler %s\n",
518   - node);
519   - }
520   -}
521   -
522   -static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot,
523   - u8 *value)
524   -{
525   - int result = eeepc_wmi_get_devstate_simple(EEEPC_WMI_DEVID_WLAN);
526   -
527   - if (result < 0)
528   - return result;
529   -
530   - *value = !!result;
531   - return 0;
532   -}
533   -
534   -static void eeepc_cleanup_pci_hotplug(struct hotplug_slot *hotplug_slot)
535   -{
536   - kfree(hotplug_slot->info);
537   - kfree(hotplug_slot);
538   -}
539   -
540   -static struct hotplug_slot_ops eeepc_hotplug_slot_ops = {
541   - .owner = THIS_MODULE,
542   - .get_adapter_status = eeepc_get_adapter_status,
543   - .get_power_status = eeepc_get_adapter_status,
544   -};
545   -
546   -static void eeepc_hotplug_work(struct work_struct *work)
547   -{
548   - struct eeepc_wmi *eeepc;
549   -
550   - eeepc = container_of(work, struct eeepc_wmi, hotplug_work);
551   - eeepc_rfkill_hotplug(eeepc);
552   -}
553   -
554   -static int eeepc_setup_pci_hotplug(struct eeepc_wmi *eeepc)
555   -{
556   - int ret = -ENOMEM;
557   - struct pci_bus *bus = pci_find_bus(0, 1);
558   -
559   - if (!bus) {
560   - pr_err("Unable to find wifi PCI bus\n");
561   - return -ENODEV;
562   - }
563   -
564   - eeepc->hotplug_workqueue =
565   - create_singlethread_workqueue("hotplug_workqueue");
566   - if (!eeepc->hotplug_workqueue)
567   - goto error_workqueue;
568   -
569   - INIT_WORK(&eeepc->hotplug_work, eeepc_hotplug_work);
570   -
571   - eeepc->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
572   - if (!eeepc->hotplug_slot)
573   - goto error_slot;
574   -
575   - eeepc->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info),
576   - GFP_KERNEL);
577   - if (!eeepc->hotplug_slot->info)
578   - goto error_info;
579   -
580   - eeepc->hotplug_slot->private = eeepc;
581   - eeepc->hotplug_slot->release = &eeepc_cleanup_pci_hotplug;
582   - eeepc->hotplug_slot->ops = &eeepc_hotplug_slot_ops;
583   - eeepc_get_adapter_status(eeepc->hotplug_slot,
584   - &eeepc->hotplug_slot->info->adapter_status);
585   -
586   - ret = pci_hp_register(eeepc->hotplug_slot, bus, 0, "eeepc-wifi");
587   - if (ret) {
588   - pr_err("Unable to register hotplug slot - %d\n", ret);
589   - goto error_register;
590   - }
591   -
592   - return 0;
593   -
594   -error_register:
595   - kfree(eeepc->hotplug_slot->info);
596   -error_info:
597   - kfree(eeepc->hotplug_slot);
598   - eeepc->hotplug_slot = NULL;
599   -error_slot:
600   - destroy_workqueue(eeepc->hotplug_workqueue);
601   -error_workqueue:
602   - return ret;
603   -}
604   -
605   -/*
606   - * Rfkill devices
607   - */
608   -static int eeepc_rfkill_set(void *data, bool blocked)
609   -{
610   - int dev_id = (unsigned long)data;
611   - u32 ctrl_param = !blocked;
612   - acpi_status status;
613   -
614   - status = eeepc_wmi_set_devstate(dev_id, ctrl_param, NULL);
615   -
616   - if (ACPI_FAILURE(status))
617   - return -EIO;
618   -
619   - return 0;
620   -}
621   -
622   -static void eeepc_rfkill_query(struct rfkill *rfkill, void *data)
623   -{
624   - int dev_id = (unsigned long)data;
625   - int result;
626   -
627   - result = eeepc_wmi_get_devstate_simple(dev_id);
628   -
629   - if (result < 0)
630   - return ;
631   -
632   - rfkill_set_sw_state(rfkill, !result);
633   -}
634   -
635   -static int eeepc_rfkill_wlan_set(void *data, bool blocked)
636   -{
637   - struct eeepc_wmi *eeepc = data;
638   - int ret;
639   -
640   - /*
641   - * This handler is enabled only if hotplug is enabled.
642   - * In this case, the eeepc_wmi_set_devstate() will
643   - * trigger a wmi notification and we need to wait
644   - * this call to finish before being able to call
645   - * any wmi method
646   - */
647   - mutex_lock(&eeepc->wmi_lock);
648   - ret = eeepc_rfkill_set((void *)(long)EEEPC_WMI_DEVID_WLAN, blocked);
649   - mutex_unlock(&eeepc->wmi_lock);
650   - return ret;
651   -}
652   -
653   -static void eeepc_rfkill_wlan_query(struct rfkill *rfkill, void *data)
654   -{
655   - eeepc_rfkill_query(rfkill, (void *)(long)EEEPC_WMI_DEVID_WLAN);
656   -}
657   -
658   -static const struct rfkill_ops eeepc_rfkill_wlan_ops = {
659   - .set_block = eeepc_rfkill_wlan_set,
660   - .query = eeepc_rfkill_wlan_query,
661   -};
662   -
663   -static const struct rfkill_ops eeepc_rfkill_ops = {
664   - .set_block = eeepc_rfkill_set,
665   - .query = eeepc_rfkill_query,
666   -};
667   -
668   -static int eeepc_new_rfkill(struct eeepc_wmi *eeepc,
669   - struct rfkill **rfkill,
670   - const char *name,
671   - enum rfkill_type type, int dev_id)
672   -{
673   - int result = eeepc_wmi_get_devstate_simple(dev_id);
674   -
675   - if (result < 0)
676   - return result;
677   -
678   - if (dev_id == EEEPC_WMI_DEVID_WLAN && eeepc->hotplug_wireless)
679   - *rfkill = rfkill_alloc(name, &eeepc->platform_device->dev, type,
680   - &eeepc_rfkill_wlan_ops, eeepc);
681   - else
682   - *rfkill = rfkill_alloc(name, &eeepc->platform_device->dev, type,
683   - &eeepc_rfkill_ops, (void *)(long)dev_id);
684   -
685   - if (!*rfkill)
686   - return -EINVAL;
687   -
688   - rfkill_init_sw_state(*rfkill, !result);
689   - result = rfkill_register(*rfkill);
690   - if (result) {
691   - rfkill_destroy(*rfkill);
692   - *rfkill = NULL;
693   - return result;
694   - }
695   - return 0;
696   -}
697   -
698   -static void eeepc_wmi_rfkill_exit(struct eeepc_wmi *eeepc)
699   -{
700   - eeepc_unregister_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P5");
701   - eeepc_unregister_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P6");
702   - eeepc_unregister_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P7");
703   - if (eeepc->wlan_rfkill) {
704   - rfkill_unregister(eeepc->wlan_rfkill);
705   - rfkill_destroy(eeepc->wlan_rfkill);
706   - eeepc->wlan_rfkill = NULL;
707   - }
708   - /*
709   - * Refresh pci hotplug in case the rfkill state was changed after
710   - * eeepc_unregister_rfkill_notifier()
711   - */
712   - eeepc_rfkill_hotplug(eeepc);
713   - if (eeepc->hotplug_slot)
714   - pci_hp_deregister(eeepc->hotplug_slot);
715   - if (eeepc->hotplug_workqueue)
716   - destroy_workqueue(eeepc->hotplug_workqueue);
717   -
718   - if (eeepc->bluetooth_rfkill) {
719   - rfkill_unregister(eeepc->bluetooth_rfkill);
720   - rfkill_destroy(eeepc->bluetooth_rfkill);
721   - eeepc->bluetooth_rfkill = NULL;
722   - }
723   - if (eeepc->wimax_rfkill) {
724   - rfkill_unregister(eeepc->wimax_rfkill);
725   - rfkill_destroy(eeepc->wimax_rfkill);
726   - eeepc->wimax_rfkill = NULL;
727   - }
728   - if (eeepc->wwan3g_rfkill) {
729   - rfkill_unregister(eeepc->wwan3g_rfkill);
730   - rfkill_destroy(eeepc->wwan3g_rfkill);
731   - eeepc->wwan3g_rfkill = NULL;
732   - }
733   -}
734   -
735   -static int eeepc_wmi_rfkill_init(struct eeepc_wmi *eeepc)
736   -{
737   - int result = 0;
738   -
739   - mutex_init(&eeepc->hotplug_lock);
740   - mutex_init(&eeepc->wmi_lock);
741   -
742   - result = eeepc_new_rfkill(eeepc, &eeepc->wlan_rfkill,
743   - "eeepc-wlan", RFKILL_TYPE_WLAN,
744   - EEEPC_WMI_DEVID_WLAN);
745   -
746   - if (result && result != -ENODEV)
747   - goto exit;
748   -
749   - result = eeepc_new_rfkill(eeepc, &eeepc->bluetooth_rfkill,
750   - "eeepc-bluetooth", RFKILL_TYPE_BLUETOOTH,
751   - EEEPC_WMI_DEVID_BLUETOOTH);
752   -
753   - if (result && result != -ENODEV)
754   - goto exit;
755   -
756   - result = eeepc_new_rfkill(eeepc, &eeepc->wimax_rfkill,
757   - "eeepc-wimax", RFKILL_TYPE_WIMAX,
758   - EEEPC_WMI_DEVID_WIMAX);
759   -
760   - if (result && result != -ENODEV)
761   - goto exit;
762   -
763   - result = eeepc_new_rfkill(eeepc, &eeepc->wwan3g_rfkill,
764   - "eeepc-wwan3g", RFKILL_TYPE_WWAN,
765   - EEEPC_WMI_DEVID_WWAN3G);
766   -
767   - if (result && result != -ENODEV)
768   - goto exit;
769   -
770   - if (!eeepc->hotplug_wireless)
771   - goto exit;
772   -
773   - result = eeepc_setup_pci_hotplug(eeepc);
774   - /*
775   - * If we get -EBUSY then something else is handling the PCI hotplug -
776   - * don't fail in this case
777   - */
778   - if (result == -EBUSY)
779   - result = 0;
780   -
781   - eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P5");
782   - eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P6");
783   - eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P7");
784   - /*
785   - * Refresh pci hotplug in case the rfkill state was changed during
786   - * setup.
787   - */
788   - eeepc_rfkill_hotplug(eeepc);
789   -
790   -exit:
791   - if (result && result != -ENODEV)
792   - eeepc_wmi_rfkill_exit(eeepc);
793   -
794   - if (result == -ENODEV)
795   - result = 0;
796   -
797   - return result;
798   -}
799   -
800   -/*
801   - * Backlight
802   - */
803   -static int read_backlight_power(void)
804   -{
805   - int ret = eeepc_wmi_get_devstate_simple(EEEPC_WMI_DEVID_BACKLIGHT);
806   -
807   - if (ret < 0)
808   - return ret;
809   -
810   - return ret ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
811   -}
812   -
813   -static int read_brightness(struct backlight_device *bd)
814   -{
815   - u32 retval;
816   - acpi_status status;
817   -
818   - status = eeepc_wmi_get_devstate(EEEPC_WMI_DEVID_BRIGHTNESS, &retval);
819   -
820   - if (ACPI_FAILURE(status))
821   - return -EIO;
822   - else
823   - return retval & EEEPC_WMI_DSTS_BRIGHTNESS_MASK;
824   -}
825   -
826   -static int update_bl_status(struct backlight_device *bd)
827   -{
828   - u32 ctrl_param;
829   - acpi_status status;
830   - int power;
831   -
832   - ctrl_param = bd->props.brightness;
833   -
834   - status = eeepc_wmi_set_devstate(EEEPC_WMI_DEVID_BRIGHTNESS,
835   - ctrl_param, NULL);
836   -
837   - if (ACPI_FAILURE(status))
838   - return -EIO;
839   -
840   - power = read_backlight_power();
841   - if (power != -ENODEV && bd->props.power != power) {
842   - ctrl_param = !!(bd->props.power == FB_BLANK_UNBLANK);
843   - status = eeepc_wmi_set_devstate(EEEPC_WMI_DEVID_BACKLIGHT,
844   - ctrl_param, NULL);
845   -
846   - if (ACPI_FAILURE(status))
847   - return -EIO;
848   - }
849   - return 0;
850   -}
851   -
852   -static const struct backlight_ops eeepc_wmi_bl_ops = {
853   - .get_brightness = read_brightness,
854   - .update_status = update_bl_status,
855   -};
856   -
857   -static int eeepc_wmi_backlight_notify(struct eeepc_wmi *eeepc, int code)
858   -{
859   - struct backlight_device *bd = eeepc->backlight_device;
860   - int old = bd->props.brightness;
861   - int new = old;
862   -
863   - if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX)
864   - new = code - NOTIFY_BRNUP_MIN + 1;
865   - else if (code >= NOTIFY_BRNDOWN_MIN && code <= NOTIFY_BRNDOWN_MAX)
866   - new = code - NOTIFY_BRNDOWN_MIN;
867   -
868   - bd->props.brightness = new;
869   - backlight_update_status(bd);
870   - backlight_force_update(bd, BACKLIGHT_UPDATE_HOTKEY);
871   -
872   - return old;
873   -}
874   -
875   -static int eeepc_wmi_backlight_init(struct eeepc_wmi *eeepc)
876   -{
877   - struct backlight_device *bd;
878   - struct backlight_properties props;
879   - int max;
880   - int power;
881   -
882   - max = eeepc_wmi_get_devstate_bits(EEEPC_WMI_DEVID_BRIGHTNESS,
883   - EEEPC_WMI_DSTS_MAX_BRIGTH_MASK);
884   - power = read_backlight_power();
885   -
886   - if (max < 0 && power < 0) {
887   - /* Try to keep the original error */
888   - if (max == -ENODEV && power == -ENODEV)
889   - return -ENODEV;
890   - if (max != -ENODEV)
891   - return max;
892   - else
893   - return power;
894   - }
895   - if (max == -ENODEV)
896   - max = 0;
897   - if (power == -ENODEV)
898   - power = FB_BLANK_UNBLANK;
899   -
900   - memset(&props, 0, sizeof(struct backlight_properties));
901   - props.max_brightness = max;
902   - bd = backlight_device_register(EEEPC_WMI_FILE,
903   - &eeepc->platform_device->dev, eeepc,
904   - &eeepc_wmi_bl_ops, &props);
905   - if (IS_ERR(bd)) {
906   - pr_err("Could not register backlight device\n");
907   - return PTR_ERR(bd);
908   - }
909   -
910   - eeepc->backlight_device = bd;
911   -
912   - bd->props.brightness = read_brightness(bd);
913   - bd->props.power = power;
914   - backlight_update_status(bd);
915   -
916   - return 0;
917   -}
918   -
919   -static void eeepc_wmi_backlight_exit(struct eeepc_wmi *eeepc)
920   -{
921   - if (eeepc->backlight_device)
922   - backlight_device_unregister(eeepc->backlight_device);
923   -
924   - eeepc->backlight_device = NULL;
925   -}
926   -
927   -static void eeepc_wmi_notify(u32 value, void *context)
928   -{
929   - struct eeepc_wmi *eeepc = context;
930   - struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
931   - union acpi_object *obj;
932   - acpi_status status;
933   - int code;
934   - int orig_code;
935   -
936   - status = wmi_get_event_data(value, &response);
937   - if (status != AE_OK) {
938   - pr_err("bad event status 0x%x\n", status);
939   - return;
940   - }
941   -
942   - obj = (union acpi_object *)response.pointer;
943   -
944   - if (obj && obj->type == ACPI_TYPE_INTEGER) {
945   - code = obj->integer.value;
946   - orig_code = code;
947   -
948   - if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX)
949   - code = NOTIFY_BRNUP_MIN;
950   - else if (code >= NOTIFY_BRNDOWN_MIN &&
951   - code <= NOTIFY_BRNDOWN_MAX)
952   - code = NOTIFY_BRNDOWN_MIN;
953   -
954   - if (code == NOTIFY_BRNUP_MIN || code == NOTIFY_BRNDOWN_MIN) {
955   - if (!acpi_video_backlight_support())
956   - eeepc_wmi_backlight_notify(eeepc, orig_code);
957   - }
958   -
959   - if (!sparse_keymap_report_event(eeepc->inputdev,
960   - code, 1, true))
961   - pr_info("Unknown key %x pressed\n", code);
962   - }
963   -
964   - kfree(obj);
965   -}
966   -
967   -/*
968   - * Sys helpers
969   - */
970   -static int parse_arg(const char *buf, unsigned long count, int *val)
971   -{
972   - if (!count)
973   - return 0;
974   - if (sscanf(buf, "%i", val) != 1)
975   - return -EINVAL;
976   - return count;
977   -}
978   -
979   -static ssize_t store_sys_wmi(int devid, const char *buf, size_t count)
980   -{
981   - acpi_status status;
982   - u32 retval;
983   - int rv, value;
984   -
985   - value = eeepc_wmi_get_devstate_simple(devid);
986   - if (value == -ENODEV) /* Check device presence */
987   - return value;
988   -
989   - rv = parse_arg(buf, count, &value);
990   - status = eeepc_wmi_set_devstate(devid, value, &retval);
991   -
992   - if (ACPI_FAILURE(status))
993   - return -EIO;
994   - return rv;
995   -}
996   -
997   -static ssize_t show_sys_wmi(int devid, char *buf)
998   -{
999   - int value = eeepc_wmi_get_devstate_simple(devid);
1000   -
1001   - if (value < 0)
1002   - return value;
1003   -
1004   - return sprintf(buf, "%d\n", value);
1005   -}
1006   -
1007   -#define EEEPC_WMI_CREATE_DEVICE_ATTR(_name, _mode, _cm) \
1008   - static ssize_t show_##_name(struct device *dev, \
1009   - struct device_attribute *attr, \
1010   - char *buf) \
1011   - { \
1012   - return show_sys_wmi(_cm, buf); \
1013   - } \
1014   - static ssize_t store_##_name(struct device *dev, \
1015   - struct device_attribute *attr, \
1016   - const char *buf, size_t count) \
1017   - { \
1018   - return store_sys_wmi(_cm, buf, count); \
1019   - } \
1020   - static struct device_attribute dev_attr_##_name = { \
1021   - .attr = { \
1022   - .name = __stringify(_name), \
1023   - .mode = _mode }, \
1024   - .show = show_##_name, \
1025   - .store = store_##_name, \
1026   - }
1027   -
1028   -EEEPC_WMI_CREATE_DEVICE_ATTR(touchpad, 0644, EEEPC_WMI_DEVID_TOUCHPAD);
1029   -EEEPC_WMI_CREATE_DEVICE_ATTR(camera, 0644, EEEPC_WMI_DEVID_CAMERA);
1030   -EEEPC_WMI_CREATE_DEVICE_ATTR(cardr, 0644, EEEPC_WMI_DEVID_CARDREADER);
1031   -
1032   -static ssize_t store_cpufv(struct device *dev, struct device_attribute *attr,
1033   - const char *buf, size_t count)
1034   -{
1035   - int value;
1036   - struct acpi_buffer input = { (acpi_size)sizeof(value), &value };
1037   - acpi_status status;
1038   -
1039   - if (!count || sscanf(buf, "%i", &value) != 1)
1040   - return -EINVAL;
1041   - if (value < 0 || value > 2)
1042   - return -EINVAL;
1043   -
1044   - status = wmi_evaluate_method(EEEPC_WMI_MGMT_GUID,
1045   - 1, EEEPC_WMI_METHODID_CFVS, &input, NULL);
1046   -
1047   - if (ACPI_FAILURE(status))
1048   - return -EIO;
1049   - else
1050   - return count;
1051   -}
1052   -
1053   -static DEVICE_ATTR(cpufv, S_IRUGO | S_IWUSR, NULL, store_cpufv);
1054   -
1055   -static struct attribute *platform_attributes[] = {
1056   - &dev_attr_cpufv.attr,
1057   - &dev_attr_camera.attr,
1058   - &dev_attr_cardr.attr,
1059   - &dev_attr_touchpad.attr,
1060   - NULL
1061   -};
1062   -
1063   -static mode_t eeepc_sysfs_is_visible(struct kobject *kobj,
1064   - struct attribute *attr,
1065   - int idx)
1066   -{
1067   - bool supported = true;
1068   - int devid = -1;
1069   -
1070   - if (attr == &dev_attr_camera.attr)
1071   - devid = EEEPC_WMI_DEVID_CAMERA;
1072   - else if (attr == &dev_attr_cardr.attr)
1073   - devid = EEEPC_WMI_DEVID_CARDREADER;
1074   - else if (attr == &dev_attr_touchpad.attr)
1075   - devid = EEEPC_WMI_DEVID_TOUCHPAD;
1076   -
1077   - if (devid != -1)
1078   - supported = eeepc_wmi_get_devstate_simple(devid) != -ENODEV;
1079   -
1080   - return supported ? attr->mode : 0;
1081   -}
1082   -
1083   -static struct attribute_group platform_attribute_group = {
1084   - .is_visible = eeepc_sysfs_is_visible,
1085   - .attrs = platform_attributes
1086   -};
1087   -
1088   -static void eeepc_wmi_sysfs_exit(struct platform_device *device)
1089   -{
1090   - sysfs_remove_group(&device->dev.kobj, &platform_attribute_group);
1091   -}
1092   -
1093   -static int eeepc_wmi_sysfs_init(struct platform_device *device)
1094   -{
1095   - return sysfs_create_group(&device->dev.kobj, &platform_attribute_group);
1096   -}
1097   -
1098   -/*
1099   - * Platform device
1100   - */
1101   -static int __init eeepc_wmi_platform_init(struct eeepc_wmi *eeepc)
1102   -{
1103   - return eeepc_wmi_sysfs_init(eeepc->platform_device);
1104   -}
1105   -
1106   -static void eeepc_wmi_platform_exit(struct eeepc_wmi *eeepc)
1107   -{
1108   - eeepc_wmi_sysfs_exit(eeepc->platform_device);
1109   -}
1110   -
1111   -/*
1112   - * debugfs
1113   - */
1114   -struct eeepc_wmi_debugfs_node {
1115   - struct eeepc_wmi *eeepc;
1116   - char *name;
1117   - int (*show)(struct seq_file *m, void *data);
1118   -};
1119   -
1120   -static int show_dsts(struct seq_file *m, void *data)
1121   -{
1122   - struct eeepc_wmi *eeepc = m->private;
1123   - acpi_status status;
1124   - u32 retval = -1;
1125   -
1126   - status = eeepc_wmi_get_devstate(eeepc->debug.dev_id, &retval);
1127   -
1128   - if (ACPI_FAILURE(status))
1129   - return -EIO;
1130   -
1131   - seq_printf(m, "DSTS(%x) = %x\n", eeepc->debug.dev_id, retval);
1132   -
1133   - return 0;
1134   -}
1135   -
1136   -static int show_devs(struct seq_file *m, void *data)
1137   -{
1138   - struct eeepc_wmi *eeepc = m->private;
1139   - acpi_status status;
1140   - u32 retval = -1;
1141   -
1142   - status = eeepc_wmi_set_devstate(eeepc->debug.dev_id,
1143   - eeepc->debug.ctrl_param, &retval);
1144   - if (ACPI_FAILURE(status))
1145   - return -EIO;
1146   -
1147   - seq_printf(m, "DEVS(%x, %x) = %x\n", eeepc->debug.dev_id,
1148   - eeepc->debug.ctrl_param, retval);
1149   -
1150   - return 0;
1151   -}
1152   -
1153   -static struct eeepc_wmi_debugfs_node eeepc_wmi_debug_files[] = {
1154   - { NULL, "devs", show_devs },
1155   - { NULL, "dsts", show_dsts },
1156   -};
1157   -
1158   -static int eeepc_wmi_debugfs_open(struct inode *inode, struct file *file)
1159   -{
1160   - struct eeepc_wmi_debugfs_node *node = inode->i_private;
1161   -
1162   - return single_open(file, node->show, node->eeepc);
1163   -}
1164   -
1165   -static const struct file_operations eeepc_wmi_debugfs_io_ops = {
1166   - .owner = THIS_MODULE,
1167   - .open = eeepc_wmi_debugfs_open,
1168   - .read = seq_read,
1169   - .llseek = seq_lseek,
1170   - .release = single_release,
1171   -};
1172   -
1173   -static void eeepc_wmi_debugfs_exit(struct eeepc_wmi *eeepc)
1174   -{
1175   - debugfs_remove_recursive(eeepc->debug.root);
1176   -}
1177   -
1178   -static int eeepc_wmi_debugfs_init(struct eeepc_wmi *eeepc)
1179   -{
1180   - struct dentry *dent;
1181   - int i;
1182   -
1183   - eeepc->debug.root = debugfs_create_dir(EEEPC_WMI_FILE, NULL);
1184   - if (!eeepc->debug.root) {
1185   - pr_err("failed to create debugfs directory");
1186   - goto error_debugfs;
1187   - }
1188   -
1189   - dent = debugfs_create_x32("dev_id", S_IRUGO|S_IWUSR,
1190   - eeepc->debug.root, &eeepc->debug.dev_id);
1191   - if (!dent)
1192   - goto error_debugfs;
1193   -
1194   - dent = debugfs_create_x32("ctrl_param", S_IRUGO|S_IWUSR,
1195   - eeepc->debug.root, &eeepc->debug.ctrl_param);
1196   - if (!dent)
1197   - goto error_debugfs;
1198   -
1199   - for (i = 0; i < ARRAY_SIZE(eeepc_wmi_debug_files); i++) {
1200   - struct eeepc_wmi_debugfs_node *node = &eeepc_wmi_debug_files[i];
1201   -
1202   - node->eeepc = eeepc;
1203   - dent = debugfs_create_file(node->name, S_IFREG | S_IRUGO,
1204   - eeepc->debug.root, node,
1205   - &eeepc_wmi_debugfs_io_ops);
1206   - if (!dent) {
1207   - pr_err("failed to create debug file: %s\n", node->name);
1208   - goto error_debugfs;
1209   - }
1210   - }
1211   -
1212   - return 0;
1213   -
1214   -error_debugfs:
1215   - eeepc_wmi_debugfs_exit(eeepc);
1216   - return -ENOMEM;
1217   -}
1218   -
1219   -/*
1220   - * WMI Driver
1221   - */
1222   -static void eeepc_dmi_check(struct eeepc_wmi *eeepc)
1223   -{
1224   - const char *model;
1225   -
1226   - model = dmi_get_system_info(DMI_PRODUCT_NAME);
1227   - if (!model)
1228   - return;
1229   -
1230   - /*
1231   - * Whitelist for wlan hotplug
1232   - *
1233   - * Eeepc 1000H needs the current hotplug code to handle
1234   - * Fn+F2 correctly. We may add other Eeepc here later, but
1235   - * it seems that most of the laptops supported by eeepc-wmi
1236   - * don't need to be on this list
1237   - */
1238   - if (strcmp(model, "1000H") == 0) {
1239   - eeepc->hotplug_wireless = true;
1240   - pr_info("wlan hotplug enabled\n");
1241   - }
1242   -}
1243   -
1244   -static int __init eeepc_wmi_add(struct platform_device *pdev)
1245   -{
1246   - struct eeepc_wmi *eeepc;
1247   - acpi_status status;
1248   - int err;
1249   -
1250   - eeepc = kzalloc(sizeof(struct eeepc_wmi), GFP_KERNEL);
1251   - if (!eeepc)
1252   - return -ENOMEM;
1253   -
1254   - eeepc->platform_device = pdev;
1255   - platform_set_drvdata(eeepc->platform_device, eeepc);
1256   -
1257   - eeepc->hotplug_wireless = hotplug_wireless;
1258   - eeepc_dmi_check(eeepc);
1259   -
1260   - err = eeepc_wmi_platform_init(eeepc);
1261   - if (err)
1262   - goto fail_platform;
1263   -
1264   - err = eeepc_wmi_input_init(eeepc);
1265   - if (err)
1266   - goto fail_input;
1267   -
1268   - err = eeepc_wmi_led_init(eeepc);
1269   - if (err)
1270   - goto fail_leds;
1271   -
1272   - err = eeepc_wmi_rfkill_init(eeepc);
1273   - if (err)
1274   - goto fail_rfkill;
1275   -
1276   - if (!acpi_video_backlight_support()) {
1277   - err = eeepc_wmi_backlight_init(eeepc);
1278   - if (err && err != -ENODEV)
1279   - goto fail_backlight;
1280   - } else
1281   - pr_info("Backlight controlled by ACPI video driver\n");
1282   -
1283   - status = wmi_install_notify_handler(EEEPC_WMI_EVENT_GUID,
1284   - eeepc_wmi_notify, eeepc);
1285   - if (ACPI_FAILURE(status)) {
1286   - pr_err("Unable to register notify handler - %d\n",
1287   - status);
1288   - err = -ENODEV;
1289   - goto fail_wmi_handler;
1290   - }
1291   -
1292   - err = eeepc_wmi_debugfs_init(eeepc);
1293   - if (err)
1294   - goto fail_debugfs;
1295   -
1296   - return 0;
1297   -
1298   -fail_debugfs:
1299   - wmi_remove_notify_handler(EEEPC_WMI_EVENT_GUID);
1300   -fail_wmi_handler:
1301   - eeepc_wmi_backlight_exit(eeepc);
1302   -fail_backlight:
1303   - eeepc_wmi_rfkill_exit(eeepc);
1304   -fail_rfkill:
1305   - eeepc_wmi_led_exit(eeepc);
1306   -fail_leds:
1307   - eeepc_wmi_input_exit(eeepc);
1308   -fail_input:
1309   - eeepc_wmi_platform_exit(eeepc);
1310   -fail_platform:
1311   - kfree(eeepc);
1312   - return err;
1313   -}
1314   -
1315   -static int __exit eeepc_wmi_remove(struct platform_device *device)
1316   -{
1317   - struct eeepc_wmi *eeepc;
1318   -
1319   - eeepc = platform_get_drvdata(device);
1320   - wmi_remove_notify_handler(EEEPC_WMI_EVENT_GUID);
1321   - eeepc_wmi_backlight_exit(eeepc);
1322   - eeepc_wmi_input_exit(eeepc);
1323   - eeepc_wmi_led_exit(eeepc);
1324   - eeepc_wmi_rfkill_exit(eeepc);
1325   - eeepc_wmi_debugfs_exit(eeepc);
1326   - eeepc_wmi_platform_exit(eeepc);
1327   -
1328   - kfree(eeepc);
1329   - return 0;
1330   -}
1331   -
1332   -/*
1333   - * Platform driver - hibernate/resume callbacks
1334   - */
1335   -static int eeepc_hotk_thaw(struct device *device)
1336   -{
1337   - struct eeepc_wmi *eeepc = dev_get_drvdata(device);
1338   -
1339   - if (eeepc->wlan_rfkill) {
1340   - bool wlan;
1341   -
1342   - /*
1343   - * Work around bios bug - acpi _PTS turns off the wireless led
1344   - * during suspend. Normally it restores it on resume, but
1345   - * we should kick it ourselves in case hibernation is aborted.
1346   - */
1347   - wlan = eeepc_wmi_get_devstate_simple(EEEPC_WMI_DEVID_WLAN);
1348   - eeepc_wmi_set_devstate(EEEPC_WMI_DEVID_WLAN, wlan, NULL);
1349   - }
1350   -
1351   - return 0;
1352   -}
1353   -
1354   -static int eeepc_hotk_restore(struct device *device)
1355   -{
1356   - struct eeepc_wmi *eeepc = dev_get_drvdata(device);
1357   - int bl;
1358   -
1359   - /* Refresh both wlan rfkill state and pci hotplug */
1360   - if (eeepc->wlan_rfkill)
1361   - eeepc_rfkill_hotplug(eeepc);
1362   -
1363   - if (eeepc->bluetooth_rfkill) {
1364   - bl = !eeepc_wmi_get_devstate_simple(EEEPC_WMI_DEVID_BLUETOOTH);
1365   - rfkill_set_sw_state(eeepc->bluetooth_rfkill, bl);
1366   - }
1367   - if (eeepc->wimax_rfkill) {
1368   - bl = !eeepc_wmi_get_devstate_simple(EEEPC_WMI_DEVID_WIMAX);
1369   - rfkill_set_sw_state(eeepc->wimax_rfkill, bl);
1370   - }
1371   - if (eeepc->wwan3g_rfkill) {
1372   - bl = !eeepc_wmi_get_devstate_simple(EEEPC_WMI_DEVID_WWAN3G);
1373   - rfkill_set_sw_state(eeepc->wwan3g_rfkill, bl);
1374   - }
1375   -
1376   - return 0;
1377   -}
1378   -
1379   -static const struct dev_pm_ops eeepc_pm_ops = {
1380   - .thaw = eeepc_hotk_thaw,
1381   - .restore = eeepc_hotk_restore,
1382   -};
1383   -
1384   -static struct platform_driver platform_driver = {
1385   - .remove = __exit_p(eeepc_wmi_remove),
1386   - .driver = {
1387   - .name = EEEPC_WMI_FILE,
1388   - .owner = THIS_MODULE,
1389   - .pm = &eeepc_pm_ops,
1390   - },
1391   -};
1392   -
1393   -static acpi_status __init eeepc_wmi_parse_device(acpi_handle handle, u32 level,
1394   - void *context, void **retval)
1395   -{
1396   - pr_warning("Found legacy ATKD device (%s)", EEEPC_ACPI_HID);
1397   - *(bool *)context = true;
1398   - return AE_CTRL_TERMINATE;
1399   -}
1400   -
1401   -static int __init eeepc_wmi_check_atkd(void)
1402   -{
1403   - acpi_status status;
1404   - bool found = false;
1405   -
1406   - status = acpi_get_devices(EEEPC_ACPI_HID, eeepc_wmi_parse_device,
1407   - &found, NULL);
1408   -
1409   - if (ACPI_FAILURE(status) || !found)
1410   - return 0;
1411   - return -1;
1412   -}
1413   -
1414   -static int __init eeepc_wmi_probe(struct platform_device *pdev)
1415   -{
1416   - if (!wmi_has_guid(EEEPC_WMI_EVENT_GUID) ||
1417   - !wmi_has_guid(EEEPC_WMI_MGMT_GUID)) {
1418   - pr_warning("No known WMI GUID found\n");
1419   - return -ENODEV;
1420   - }
1421   -
1422   - if (eeepc_wmi_check_atkd()) {
1423   - pr_warning("WMI device present, but legacy ATKD device is also "
1424   - "present and enabled.");
1425   - pr_warning("You probably booted with acpi_osi=\"Linux\" or "
1426   - "acpi_osi=\"!Windows 2009\"");
1427   - pr_warning("Can't load eeepc-wmi, use default acpi_osi "
1428   - "(preferred) or eeepc-laptop");
1429   - return -ENODEV;
1430   - }
1431   -
1432   - return eeepc_wmi_add(pdev);
1433   -}
1434   -
1435   -static struct platform_device *platform_device;
1436   -
1437   -static int __init eeepc_wmi_init(void)
1438   -{
1439   - platform_device = platform_create_bundle(&platform_driver,
1440   - eeepc_wmi_probe,
1441   - NULL, 0, NULL, 0);
1442   - if (IS_ERR(platform_device))
1443   - return PTR_ERR(platform_device);
1444   - return 0;
1445   -}
1446   -
1447   -static void __exit eeepc_wmi_exit(void)
1448   -{
1449   - platform_device_unregister(platform_device);
1450   - platform_driver_unregister(&platform_driver);
1451   -}
1452   -
1453   -module_init(eeepc_wmi_init);
1454   -module_exit(eeepc_wmi_exit);