Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.4-rc6 1880 lines 47 kB view raw
1/* 2 * Asus PC WMI hotkey driver 3 * 4 * Copyright(C) 2010 Intel Corporation. 5 * Copyright(C) 2010-2011 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/hwmon.h> 43#include <linux/hwmon-sysfs.h> 44#include <linux/debugfs.h> 45#include <linux/seq_file.h> 46#include <linux/platform_device.h> 47#include <linux/thermal.h> 48#include <acpi/acpi_bus.h> 49#include <acpi/acpi_drivers.h> 50 51#include "asus-wmi.h" 52 53MODULE_AUTHOR("Corentin Chary <corentincj@iksaif.net>, " 54 "Yong Wang <yong.y.wang@intel.com>"); 55MODULE_DESCRIPTION("Asus Generic WMI Driver"); 56MODULE_LICENSE("GPL"); 57 58#define to_platform_driver(drv) \ 59 (container_of((drv), struct platform_driver, driver)) 60 61#define to_asus_wmi_driver(pdrv) \ 62 (container_of((pdrv), struct asus_wmi_driver, platform_driver)) 63 64#define ASUS_WMI_MGMT_GUID "97845ED0-4E6D-11DE-8A39-0800200C9A66" 65 66#define NOTIFY_BRNUP_MIN 0x11 67#define NOTIFY_BRNUP_MAX 0x1f 68#define NOTIFY_BRNDOWN_MIN 0x20 69#define NOTIFY_BRNDOWN_MAX 0x2e 70#define NOTIFY_KBD_BRTUP 0xc4 71#define NOTIFY_KBD_BRTDWN 0xc5 72 73/* WMI Methods */ 74#define ASUS_WMI_METHODID_SPEC 0x43455053 /* BIOS SPECification */ 75#define ASUS_WMI_METHODID_SFBD 0x44424653 /* Set First Boot Device */ 76#define ASUS_WMI_METHODID_GLCD 0x44434C47 /* Get LCD status */ 77#define ASUS_WMI_METHODID_GPID 0x44495047 /* Get Panel ID?? (Resol) */ 78#define ASUS_WMI_METHODID_QMOD 0x444F4D51 /* Quiet MODe */ 79#define ASUS_WMI_METHODID_SPLV 0x4C425053 /* Set Panel Light Value */ 80#define ASUS_WMI_METHODID_SFUN 0x4E554653 /* FUNCtionalities */ 81#define ASUS_WMI_METHODID_SDSP 0x50534453 /* Set DiSPlay output */ 82#define ASUS_WMI_METHODID_GDSP 0x50534447 /* Get DiSPlay output */ 83#define ASUS_WMI_METHODID_DEVP 0x50564544 /* DEVice Policy */ 84#define ASUS_WMI_METHODID_OSVR 0x5256534F /* OS VeRsion */ 85#define ASUS_WMI_METHODID_DSTS 0x53544344 /* Device STatuS */ 86#define ASUS_WMI_METHODID_DSTS2 0x53545344 /* Device STatuS #2*/ 87#define ASUS_WMI_METHODID_BSTS 0x53545342 /* Bios STatuS ? */ 88#define ASUS_WMI_METHODID_DEVS 0x53564544 /* DEVice Set */ 89#define ASUS_WMI_METHODID_CFVS 0x53564643 /* CPU Frequency Volt Set */ 90#define ASUS_WMI_METHODID_KBFT 0x5446424B /* KeyBoard FilTer */ 91#define ASUS_WMI_METHODID_INIT 0x54494E49 /* INITialize */ 92#define ASUS_WMI_METHODID_HKEY 0x59454B48 /* Hot KEY ?? */ 93 94#define ASUS_WMI_UNSUPPORTED_METHOD 0xFFFFFFFE 95 96/* Wireless */ 97#define ASUS_WMI_DEVID_HW_SWITCH 0x00010001 98#define ASUS_WMI_DEVID_WIRELESS_LED 0x00010002 99#define ASUS_WMI_DEVID_CWAP 0x00010003 100#define ASUS_WMI_DEVID_WLAN 0x00010011 101#define ASUS_WMI_DEVID_BLUETOOTH 0x00010013 102#define ASUS_WMI_DEVID_GPS 0x00010015 103#define ASUS_WMI_DEVID_WIMAX 0x00010017 104#define ASUS_WMI_DEVID_WWAN3G 0x00010019 105#define ASUS_WMI_DEVID_UWB 0x00010021 106 107/* Leds */ 108/* 0x000200XX and 0x000400XX */ 109#define ASUS_WMI_DEVID_LED1 0x00020011 110#define ASUS_WMI_DEVID_LED2 0x00020012 111#define ASUS_WMI_DEVID_LED3 0x00020013 112#define ASUS_WMI_DEVID_LED4 0x00020014 113#define ASUS_WMI_DEVID_LED5 0x00020015 114#define ASUS_WMI_DEVID_LED6 0x00020016 115 116/* Backlight and Brightness */ 117#define ASUS_WMI_DEVID_BACKLIGHT 0x00050011 118#define ASUS_WMI_DEVID_BRIGHTNESS 0x00050012 119#define ASUS_WMI_DEVID_KBD_BACKLIGHT 0x00050021 120#define ASUS_WMI_DEVID_LIGHT_SENSOR 0x00050022 /* ?? */ 121 122/* Misc */ 123#define ASUS_WMI_DEVID_CAMERA 0x00060013 124 125/* Storage */ 126#define ASUS_WMI_DEVID_CARDREADER 0x00080013 127 128/* Input */ 129#define ASUS_WMI_DEVID_TOUCHPAD 0x00100011 130#define ASUS_WMI_DEVID_TOUCHPAD_LED 0x00100012 131 132/* Fan, Thermal */ 133#define ASUS_WMI_DEVID_THERMAL_CTRL 0x00110011 134#define ASUS_WMI_DEVID_FAN_CTRL 0x00110012 135 136/* Power */ 137#define ASUS_WMI_DEVID_PROCESSOR_STATE 0x00120012 138 139/* DSTS masks */ 140#define ASUS_WMI_DSTS_STATUS_BIT 0x00000001 141#define ASUS_WMI_DSTS_UNKNOWN_BIT 0x00000002 142#define ASUS_WMI_DSTS_PRESENCE_BIT 0x00010000 143#define ASUS_WMI_DSTS_USER_BIT 0x00020000 144#define ASUS_WMI_DSTS_BIOS_BIT 0x00040000 145#define ASUS_WMI_DSTS_BRIGHTNESS_MASK 0x000000FF 146#define ASUS_WMI_DSTS_MAX_BRIGTH_MASK 0x0000FF00 147 148struct bios_args { 149 u32 arg0; 150 u32 arg1; 151} __packed; 152 153/* 154 * <platform>/ - debugfs root directory 155 * dev_id - current dev_id 156 * ctrl_param - current ctrl_param 157 * method_id - current method_id 158 * devs - call DEVS(dev_id, ctrl_param) and print result 159 * dsts - call DSTS(dev_id) and print result 160 * call - call method_id(dev_id, ctrl_param) and print result 161 */ 162struct asus_wmi_debug { 163 struct dentry *root; 164 u32 method_id; 165 u32 dev_id; 166 u32 ctrl_param; 167}; 168 169struct asus_rfkill { 170 struct asus_wmi *asus; 171 struct rfkill *rfkill; 172 u32 dev_id; 173}; 174 175struct asus_wmi { 176 int dsts_id; 177 int spec; 178 int sfun; 179 180 struct input_dev *inputdev; 181 struct backlight_device *backlight_device; 182 struct device *hwmon_device; 183 struct platform_device *platform_device; 184 185 struct led_classdev tpd_led; 186 int tpd_led_wk; 187 struct led_classdev kbd_led; 188 int kbd_led_wk; 189 struct workqueue_struct *led_workqueue; 190 struct work_struct tpd_led_work; 191 struct work_struct kbd_led_work; 192 193 struct asus_rfkill wlan; 194 struct asus_rfkill bluetooth; 195 struct asus_rfkill wimax; 196 struct asus_rfkill wwan3g; 197 struct asus_rfkill gps; 198 struct asus_rfkill uwb; 199 200 struct hotplug_slot *hotplug_slot; 201 struct mutex hotplug_lock; 202 struct mutex wmi_lock; 203 struct workqueue_struct *hotplug_workqueue; 204 struct work_struct hotplug_work; 205 206 struct asus_wmi_debug debug; 207 208 struct asus_wmi_driver *driver; 209}; 210 211static int asus_wmi_input_init(struct asus_wmi *asus) 212{ 213 int err; 214 215 asus->inputdev = input_allocate_device(); 216 if (!asus->inputdev) 217 return -ENOMEM; 218 219 asus->inputdev->name = asus->driver->input_name; 220 asus->inputdev->phys = asus->driver->input_phys; 221 asus->inputdev->id.bustype = BUS_HOST; 222 asus->inputdev->dev.parent = &asus->platform_device->dev; 223 set_bit(EV_REP, asus->inputdev->evbit); 224 225 err = sparse_keymap_setup(asus->inputdev, asus->driver->keymap, NULL); 226 if (err) 227 goto err_free_dev; 228 229 err = input_register_device(asus->inputdev); 230 if (err) 231 goto err_free_keymap; 232 233 return 0; 234 235err_free_keymap: 236 sparse_keymap_free(asus->inputdev); 237err_free_dev: 238 input_free_device(asus->inputdev); 239 return err; 240} 241 242static void asus_wmi_input_exit(struct asus_wmi *asus) 243{ 244 if (asus->inputdev) { 245 sparse_keymap_free(asus->inputdev); 246 input_unregister_device(asus->inputdev); 247 } 248 249 asus->inputdev = NULL; 250} 251 252static int asus_wmi_evaluate_method(u32 method_id, u32 arg0, u32 arg1, 253 u32 *retval) 254{ 255 struct bios_args args = { 256 .arg0 = arg0, 257 .arg1 = arg1, 258 }; 259 struct acpi_buffer input = { (acpi_size) sizeof(args), &args }; 260 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; 261 acpi_status status; 262 union acpi_object *obj; 263 u32 tmp; 264 265 status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID, 1, method_id, 266 &input, &output); 267 268 if (ACPI_FAILURE(status)) 269 goto exit; 270 271 obj = (union acpi_object *)output.pointer; 272 if (obj && obj->type == ACPI_TYPE_INTEGER) 273 tmp = (u32) obj->integer.value; 274 else 275 tmp = 0; 276 277 if (retval) 278 *retval = tmp; 279 280 kfree(obj); 281 282exit: 283 if (ACPI_FAILURE(status)) 284 return -EIO; 285 286 if (tmp == ASUS_WMI_UNSUPPORTED_METHOD) 287 return -ENODEV; 288 289 return 0; 290} 291 292static int asus_wmi_get_devstate(struct asus_wmi *asus, u32 dev_id, u32 *retval) 293{ 294 return asus_wmi_evaluate_method(asus->dsts_id, dev_id, 0, retval); 295} 296 297static int asus_wmi_set_devstate(u32 dev_id, u32 ctrl_param, 298 u32 *retval) 299{ 300 return asus_wmi_evaluate_method(ASUS_WMI_METHODID_DEVS, dev_id, 301 ctrl_param, retval); 302} 303 304/* Helper for special devices with magic return codes */ 305static int asus_wmi_get_devstate_bits(struct asus_wmi *asus, 306 u32 dev_id, u32 mask) 307{ 308 u32 retval = 0; 309 int err; 310 311 err = asus_wmi_get_devstate(asus, dev_id, &retval); 312 313 if (err < 0) 314 return err; 315 316 if (!(retval & ASUS_WMI_DSTS_PRESENCE_BIT)) 317 return -ENODEV; 318 319 if (mask == ASUS_WMI_DSTS_STATUS_BIT) { 320 if (retval & ASUS_WMI_DSTS_UNKNOWN_BIT) 321 return -ENODEV; 322 } 323 324 return retval & mask; 325} 326 327static int asus_wmi_get_devstate_simple(struct asus_wmi *asus, u32 dev_id) 328{ 329 return asus_wmi_get_devstate_bits(asus, dev_id, 330 ASUS_WMI_DSTS_STATUS_BIT); 331} 332 333/* 334 * LEDs 335 */ 336/* 337 * These functions actually update the LED's, and are called from a 338 * workqueue. By doing this as separate work rather than when the LED 339 * subsystem asks, we avoid messing with the Asus ACPI stuff during a 340 * potentially bad time, such as a timer interrupt. 341 */ 342static void tpd_led_update(struct work_struct *work) 343{ 344 int ctrl_param; 345 struct asus_wmi *asus; 346 347 asus = container_of(work, struct asus_wmi, tpd_led_work); 348 349 ctrl_param = asus->tpd_led_wk; 350 asus_wmi_set_devstate(ASUS_WMI_DEVID_TOUCHPAD_LED, ctrl_param, NULL); 351} 352 353static void tpd_led_set(struct led_classdev *led_cdev, 354 enum led_brightness value) 355{ 356 struct asus_wmi *asus; 357 358 asus = container_of(led_cdev, struct asus_wmi, tpd_led); 359 360 asus->tpd_led_wk = !!value; 361 queue_work(asus->led_workqueue, &asus->tpd_led_work); 362} 363 364static int read_tpd_led_state(struct asus_wmi *asus) 365{ 366 return asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_TOUCHPAD_LED); 367} 368 369static enum led_brightness tpd_led_get(struct led_classdev *led_cdev) 370{ 371 struct asus_wmi *asus; 372 373 asus = container_of(led_cdev, struct asus_wmi, tpd_led); 374 375 return read_tpd_led_state(asus); 376} 377 378static void kbd_led_update(struct work_struct *work) 379{ 380 int ctrl_param = 0; 381 struct asus_wmi *asus; 382 383 asus = container_of(work, struct asus_wmi, kbd_led_work); 384 385 /* 386 * bits 0-2: level 387 * bit 7: light on/off 388 */ 389 if (asus->kbd_led_wk > 0) 390 ctrl_param = 0x80 | (asus->kbd_led_wk & 0x7F); 391 392 asus_wmi_set_devstate(ASUS_WMI_DEVID_KBD_BACKLIGHT, ctrl_param, NULL); 393} 394 395static int kbd_led_read(struct asus_wmi *asus, int *level, int *env) 396{ 397 int retval; 398 399 /* 400 * bits 0-2: level 401 * bit 7: light on/off 402 * bit 8-10: environment (0: dark, 1: normal, 2: light) 403 * bit 17: status unknown 404 */ 405 retval = asus_wmi_get_devstate_bits(asus, ASUS_WMI_DEVID_KBD_BACKLIGHT, 406 0xFFFF); 407 408 /* Unknown status is considered as off */ 409 if (retval == 0x8000) 410 retval = 0; 411 412 if (retval >= 0) { 413 if (level) 414 *level = retval & 0x7F; 415 if (env) 416 *env = (retval >> 8) & 0x7F; 417 retval = 0; 418 } 419 420 return retval; 421} 422 423static void kbd_led_set(struct led_classdev *led_cdev, 424 enum led_brightness value) 425{ 426 struct asus_wmi *asus; 427 428 asus = container_of(led_cdev, struct asus_wmi, kbd_led); 429 430 if (value > asus->kbd_led.max_brightness) 431 value = asus->kbd_led.max_brightness; 432 else if (value < 0) 433 value = 0; 434 435 asus->kbd_led_wk = value; 436 queue_work(asus->led_workqueue, &asus->kbd_led_work); 437} 438 439static enum led_brightness kbd_led_get(struct led_classdev *led_cdev) 440{ 441 struct asus_wmi *asus; 442 int retval, value; 443 444 asus = container_of(led_cdev, struct asus_wmi, kbd_led); 445 446 retval = kbd_led_read(asus, &value, NULL); 447 448 if (retval < 0) 449 return retval; 450 451 return value; 452} 453 454static void asus_wmi_led_exit(struct asus_wmi *asus) 455{ 456 if (!IS_ERR_OR_NULL(asus->kbd_led.dev)) 457 led_classdev_unregister(&asus->kbd_led); 458 if (!IS_ERR_OR_NULL(asus->tpd_led.dev)) 459 led_classdev_unregister(&asus->tpd_led); 460 if (asus->led_workqueue) 461 destroy_workqueue(asus->led_workqueue); 462} 463 464static int asus_wmi_led_init(struct asus_wmi *asus) 465{ 466 int rv = 0; 467 468 asus->led_workqueue = create_singlethread_workqueue("led_workqueue"); 469 if (!asus->led_workqueue) 470 return -ENOMEM; 471 472 if (read_tpd_led_state(asus) >= 0) { 473 INIT_WORK(&asus->tpd_led_work, tpd_led_update); 474 475 asus->tpd_led.name = "asus::touchpad"; 476 asus->tpd_led.brightness_set = tpd_led_set; 477 asus->tpd_led.brightness_get = tpd_led_get; 478 asus->tpd_led.max_brightness = 1; 479 480 rv = led_classdev_register(&asus->platform_device->dev, 481 &asus->tpd_led); 482 if (rv) 483 goto error; 484 } 485 486 if (kbd_led_read(asus, NULL, NULL) >= 0) { 487 INIT_WORK(&asus->kbd_led_work, kbd_led_update); 488 489 asus->kbd_led.name = "asus::kbd_backlight"; 490 asus->kbd_led.brightness_set = kbd_led_set; 491 asus->kbd_led.brightness_get = kbd_led_get; 492 asus->kbd_led.max_brightness = 3; 493 494 rv = led_classdev_register(&asus->platform_device->dev, 495 &asus->kbd_led); 496 } 497 498error: 499 if (rv) 500 asus_wmi_led_exit(asus); 501 502 return rv; 503} 504 505 506/* 507 * PCI hotplug (for wlan rfkill) 508 */ 509static bool asus_wlan_rfkill_blocked(struct asus_wmi *asus) 510{ 511 int result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WLAN); 512 513 if (result < 0) 514 return false; 515 return !result; 516} 517 518static void asus_rfkill_hotplug(struct asus_wmi *asus) 519{ 520 struct pci_dev *dev; 521 struct pci_bus *bus; 522 bool blocked; 523 bool absent; 524 u32 l; 525 526 mutex_lock(&asus->wmi_lock); 527 blocked = asus_wlan_rfkill_blocked(asus); 528 mutex_unlock(&asus->wmi_lock); 529 530 mutex_lock(&asus->hotplug_lock); 531 532 if (asus->wlan.rfkill) 533 rfkill_set_sw_state(asus->wlan.rfkill, blocked); 534 535 if (asus->hotplug_slot) { 536 bus = pci_find_bus(0, 1); 537 if (!bus) { 538 pr_warn("Unable to find PCI bus 1?\n"); 539 goto out_unlock; 540 } 541 542 if (pci_bus_read_config_dword(bus, 0, PCI_VENDOR_ID, &l)) { 543 pr_err("Unable to read PCI config space?\n"); 544 goto out_unlock; 545 } 546 absent = (l == 0xffffffff); 547 548 if (blocked != absent) { 549 pr_warn("BIOS says wireless lan is %s, " 550 "but the pci device is %s\n", 551 blocked ? "blocked" : "unblocked", 552 absent ? "absent" : "present"); 553 pr_warn("skipped wireless hotplug as probably " 554 "inappropriate for this model\n"); 555 goto out_unlock; 556 } 557 558 if (!blocked) { 559 dev = pci_get_slot(bus, 0); 560 if (dev) { 561 /* Device already present */ 562 pci_dev_put(dev); 563 goto out_unlock; 564 } 565 dev = pci_scan_single_device(bus, 0); 566 if (dev) { 567 pci_bus_assign_resources(bus); 568 if (pci_bus_add_device(dev)) 569 pr_err("Unable to hotplug wifi\n"); 570 } 571 } else { 572 dev = pci_get_slot(bus, 0); 573 if (dev) { 574 pci_stop_and_remove_bus_device(dev); 575 pci_dev_put(dev); 576 } 577 } 578 } 579 580out_unlock: 581 mutex_unlock(&asus->hotplug_lock); 582} 583 584static void asus_rfkill_notify(acpi_handle handle, u32 event, void *data) 585{ 586 struct asus_wmi *asus = data; 587 588 if (event != ACPI_NOTIFY_BUS_CHECK) 589 return; 590 591 /* 592 * We can't call directly asus_rfkill_hotplug because most 593 * of the time WMBC is still being executed and not reetrant. 594 * There is currently no way to tell ACPICA that we want this 595 * method to be serialized, we schedule a asus_rfkill_hotplug 596 * call later, in a safer context. 597 */ 598 queue_work(asus->hotplug_workqueue, &asus->hotplug_work); 599} 600 601static int asus_register_rfkill_notifier(struct asus_wmi *asus, char *node) 602{ 603 acpi_status status; 604 acpi_handle handle; 605 606 status = acpi_get_handle(NULL, node, &handle); 607 608 if (ACPI_SUCCESS(status)) { 609 status = acpi_install_notify_handler(handle, 610 ACPI_SYSTEM_NOTIFY, 611 asus_rfkill_notify, asus); 612 if (ACPI_FAILURE(status)) 613 pr_warn("Failed to register notify on %s\n", node); 614 } else 615 return -ENODEV; 616 617 return 0; 618} 619 620static void asus_unregister_rfkill_notifier(struct asus_wmi *asus, char *node) 621{ 622 acpi_status status = AE_OK; 623 acpi_handle handle; 624 625 status = acpi_get_handle(NULL, node, &handle); 626 627 if (ACPI_SUCCESS(status)) { 628 status = acpi_remove_notify_handler(handle, 629 ACPI_SYSTEM_NOTIFY, 630 asus_rfkill_notify); 631 if (ACPI_FAILURE(status)) 632 pr_err("Error removing rfkill notify handler %s\n", 633 node); 634 } 635} 636 637static int asus_get_adapter_status(struct hotplug_slot *hotplug_slot, 638 u8 *value) 639{ 640 struct asus_wmi *asus = hotplug_slot->private; 641 int result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WLAN); 642 643 if (result < 0) 644 return result; 645 646 *value = !!result; 647 return 0; 648} 649 650static void asus_cleanup_pci_hotplug(struct hotplug_slot *hotplug_slot) 651{ 652 kfree(hotplug_slot->info); 653 kfree(hotplug_slot); 654} 655 656static struct hotplug_slot_ops asus_hotplug_slot_ops = { 657 .owner = THIS_MODULE, 658 .get_adapter_status = asus_get_adapter_status, 659 .get_power_status = asus_get_adapter_status, 660}; 661 662static void asus_hotplug_work(struct work_struct *work) 663{ 664 struct asus_wmi *asus; 665 666 asus = container_of(work, struct asus_wmi, hotplug_work); 667 asus_rfkill_hotplug(asus); 668} 669 670static int asus_setup_pci_hotplug(struct asus_wmi *asus) 671{ 672 int ret = -ENOMEM; 673 struct pci_bus *bus = pci_find_bus(0, 1); 674 675 if (!bus) { 676 pr_err("Unable to find wifi PCI bus\n"); 677 return -ENODEV; 678 } 679 680 asus->hotplug_workqueue = 681 create_singlethread_workqueue("hotplug_workqueue"); 682 if (!asus->hotplug_workqueue) 683 goto error_workqueue; 684 685 INIT_WORK(&asus->hotplug_work, asus_hotplug_work); 686 687 asus->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL); 688 if (!asus->hotplug_slot) 689 goto error_slot; 690 691 asus->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info), 692 GFP_KERNEL); 693 if (!asus->hotplug_slot->info) 694 goto error_info; 695 696 asus->hotplug_slot->private = asus; 697 asus->hotplug_slot->release = &asus_cleanup_pci_hotplug; 698 asus->hotplug_slot->ops = &asus_hotplug_slot_ops; 699 asus_get_adapter_status(asus->hotplug_slot, 700 &asus->hotplug_slot->info->adapter_status); 701 702 ret = pci_hp_register(asus->hotplug_slot, bus, 0, "asus-wifi"); 703 if (ret) { 704 pr_err("Unable to register hotplug slot - %d\n", ret); 705 goto error_register; 706 } 707 708 return 0; 709 710error_register: 711 kfree(asus->hotplug_slot->info); 712error_info: 713 kfree(asus->hotplug_slot); 714 asus->hotplug_slot = NULL; 715error_slot: 716 destroy_workqueue(asus->hotplug_workqueue); 717error_workqueue: 718 return ret; 719} 720 721/* 722 * Rfkill devices 723 */ 724static int asus_rfkill_set(void *data, bool blocked) 725{ 726 struct asus_rfkill *priv = data; 727 u32 ctrl_param = !blocked; 728 729 return asus_wmi_set_devstate(priv->dev_id, ctrl_param, NULL); 730} 731 732static void asus_rfkill_query(struct rfkill *rfkill, void *data) 733{ 734 struct asus_rfkill *priv = data; 735 int result; 736 737 result = asus_wmi_get_devstate_simple(priv->asus, priv->dev_id); 738 739 if (result < 0) 740 return; 741 742 rfkill_set_sw_state(priv->rfkill, !result); 743} 744 745static int asus_rfkill_wlan_set(void *data, bool blocked) 746{ 747 struct asus_rfkill *priv = data; 748 struct asus_wmi *asus = priv->asus; 749 int ret; 750 751 /* 752 * This handler is enabled only if hotplug is enabled. 753 * In this case, the asus_wmi_set_devstate() will 754 * trigger a wmi notification and we need to wait 755 * this call to finish before being able to call 756 * any wmi method 757 */ 758 mutex_lock(&asus->wmi_lock); 759 ret = asus_rfkill_set(data, blocked); 760 mutex_unlock(&asus->wmi_lock); 761 return ret; 762} 763 764static const struct rfkill_ops asus_rfkill_wlan_ops = { 765 .set_block = asus_rfkill_wlan_set, 766 .query = asus_rfkill_query, 767}; 768 769static const struct rfkill_ops asus_rfkill_ops = { 770 .set_block = asus_rfkill_set, 771 .query = asus_rfkill_query, 772}; 773 774static int asus_new_rfkill(struct asus_wmi *asus, 775 struct asus_rfkill *arfkill, 776 const char *name, enum rfkill_type type, int dev_id) 777{ 778 int result = asus_wmi_get_devstate_simple(asus, dev_id); 779 struct rfkill **rfkill = &arfkill->rfkill; 780 781 if (result < 0) 782 return result; 783 784 arfkill->dev_id = dev_id; 785 arfkill->asus = asus; 786 787 if (dev_id == ASUS_WMI_DEVID_WLAN && 788 asus->driver->quirks->hotplug_wireless) 789 *rfkill = rfkill_alloc(name, &asus->platform_device->dev, type, 790 &asus_rfkill_wlan_ops, arfkill); 791 else 792 *rfkill = rfkill_alloc(name, &asus->platform_device->dev, type, 793 &asus_rfkill_ops, arfkill); 794 795 if (!*rfkill) 796 return -EINVAL; 797 798 rfkill_init_sw_state(*rfkill, !result); 799 result = rfkill_register(*rfkill); 800 if (result) { 801 rfkill_destroy(*rfkill); 802 *rfkill = NULL; 803 return result; 804 } 805 return 0; 806} 807 808static void asus_wmi_rfkill_exit(struct asus_wmi *asus) 809{ 810 asus_unregister_rfkill_notifier(asus, "\\_SB.PCI0.P0P5"); 811 asus_unregister_rfkill_notifier(asus, "\\_SB.PCI0.P0P6"); 812 asus_unregister_rfkill_notifier(asus, "\\_SB.PCI0.P0P7"); 813 if (asus->wlan.rfkill) { 814 rfkill_unregister(asus->wlan.rfkill); 815 rfkill_destroy(asus->wlan.rfkill); 816 asus->wlan.rfkill = NULL; 817 } 818 /* 819 * Refresh pci hotplug in case the rfkill state was changed after 820 * asus_unregister_rfkill_notifier() 821 */ 822 asus_rfkill_hotplug(asus); 823 if (asus->hotplug_slot) 824 pci_hp_deregister(asus->hotplug_slot); 825 if (asus->hotplug_workqueue) 826 destroy_workqueue(asus->hotplug_workqueue); 827 828 if (asus->bluetooth.rfkill) { 829 rfkill_unregister(asus->bluetooth.rfkill); 830 rfkill_destroy(asus->bluetooth.rfkill); 831 asus->bluetooth.rfkill = NULL; 832 } 833 if (asus->wimax.rfkill) { 834 rfkill_unregister(asus->wimax.rfkill); 835 rfkill_destroy(asus->wimax.rfkill); 836 asus->wimax.rfkill = NULL; 837 } 838 if (asus->wwan3g.rfkill) { 839 rfkill_unregister(asus->wwan3g.rfkill); 840 rfkill_destroy(asus->wwan3g.rfkill); 841 asus->wwan3g.rfkill = NULL; 842 } 843 if (asus->gps.rfkill) { 844 rfkill_unregister(asus->gps.rfkill); 845 rfkill_destroy(asus->gps.rfkill); 846 asus->gps.rfkill = NULL; 847 } 848 if (asus->uwb.rfkill) { 849 rfkill_unregister(asus->uwb.rfkill); 850 rfkill_destroy(asus->uwb.rfkill); 851 asus->uwb.rfkill = NULL; 852 } 853} 854 855static int asus_wmi_rfkill_init(struct asus_wmi *asus) 856{ 857 int result = 0; 858 859 mutex_init(&asus->hotplug_lock); 860 mutex_init(&asus->wmi_lock); 861 862 result = asus_new_rfkill(asus, &asus->wlan, "asus-wlan", 863 RFKILL_TYPE_WLAN, ASUS_WMI_DEVID_WLAN); 864 865 if (result && result != -ENODEV) 866 goto exit; 867 868 result = asus_new_rfkill(asus, &asus->bluetooth, 869 "asus-bluetooth", RFKILL_TYPE_BLUETOOTH, 870 ASUS_WMI_DEVID_BLUETOOTH); 871 872 if (result && result != -ENODEV) 873 goto exit; 874 875 result = asus_new_rfkill(asus, &asus->wimax, "asus-wimax", 876 RFKILL_TYPE_WIMAX, ASUS_WMI_DEVID_WIMAX); 877 878 if (result && result != -ENODEV) 879 goto exit; 880 881 result = asus_new_rfkill(asus, &asus->wwan3g, "asus-wwan3g", 882 RFKILL_TYPE_WWAN, ASUS_WMI_DEVID_WWAN3G); 883 884 if (result && result != -ENODEV) 885 goto exit; 886 887 result = asus_new_rfkill(asus, &asus->gps, "asus-gps", 888 RFKILL_TYPE_GPS, ASUS_WMI_DEVID_GPS); 889 890 if (result && result != -ENODEV) 891 goto exit; 892 893 result = asus_new_rfkill(asus, &asus->uwb, "asus-uwb", 894 RFKILL_TYPE_UWB, ASUS_WMI_DEVID_UWB); 895 896 if (result && result != -ENODEV) 897 goto exit; 898 899 if (!asus->driver->quirks->hotplug_wireless) 900 goto exit; 901 902 result = asus_setup_pci_hotplug(asus); 903 /* 904 * If we get -EBUSY then something else is handling the PCI hotplug - 905 * don't fail in this case 906 */ 907 if (result == -EBUSY) 908 result = 0; 909 910 asus_register_rfkill_notifier(asus, "\\_SB.PCI0.P0P5"); 911 asus_register_rfkill_notifier(asus, "\\_SB.PCI0.P0P6"); 912 asus_register_rfkill_notifier(asus, "\\_SB.PCI0.P0P7"); 913 /* 914 * Refresh pci hotplug in case the rfkill state was changed during 915 * setup. 916 */ 917 asus_rfkill_hotplug(asus); 918 919exit: 920 if (result && result != -ENODEV) 921 asus_wmi_rfkill_exit(asus); 922 923 if (result == -ENODEV) 924 result = 0; 925 926 return result; 927} 928 929/* 930 * Hwmon device 931 */ 932static ssize_t asus_hwmon_pwm1(struct device *dev, 933 struct device_attribute *attr, 934 char *buf) 935{ 936 struct asus_wmi *asus = dev_get_drvdata(dev); 937 u32 value; 938 int err; 939 940 err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_FAN_CTRL, &value); 941 942 if (err < 0) 943 return err; 944 945 value &= 0xFF; 946 947 if (value == 1) /* Low Speed */ 948 value = 85; 949 else if (value == 2) 950 value = 170; 951 else if (value == 3) 952 value = 255; 953 else if (value != 0) { 954 pr_err("Unknown fan speed %#x", value); 955 value = -1; 956 } 957 958 return sprintf(buf, "%d\n", value); 959} 960 961static ssize_t asus_hwmon_temp1(struct device *dev, 962 struct device_attribute *attr, 963 char *buf) 964{ 965 struct asus_wmi *asus = dev_get_drvdata(dev); 966 u32 value; 967 int err; 968 969 err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_THERMAL_CTRL, &value); 970 971 if (err < 0) 972 return err; 973 974 value = KELVIN_TO_CELSIUS((value & 0xFFFF)) * 1000; 975 976 return sprintf(buf, "%d\n", value); 977} 978 979static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO, asus_hwmon_pwm1, NULL, 0); 980static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, asus_hwmon_temp1, NULL, 0); 981 982static ssize_t 983show_name(struct device *dev, struct device_attribute *attr, char *buf) 984{ 985 return sprintf(buf, "asus\n"); 986} 987static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0); 988 989static struct attribute *hwmon_attributes[] = { 990 &sensor_dev_attr_pwm1.dev_attr.attr, 991 &sensor_dev_attr_temp1_input.dev_attr.attr, 992 &sensor_dev_attr_name.dev_attr.attr, 993 NULL 994}; 995 996static umode_t asus_hwmon_sysfs_is_visible(struct kobject *kobj, 997 struct attribute *attr, int idx) 998{ 999 struct device *dev = container_of(kobj, struct device, kobj); 1000 struct platform_device *pdev = to_platform_device(dev->parent); 1001 struct asus_wmi *asus = platform_get_drvdata(pdev); 1002 bool ok = true; 1003 int dev_id = -1; 1004 u32 value = ASUS_WMI_UNSUPPORTED_METHOD; 1005 1006 if (attr == &sensor_dev_attr_pwm1.dev_attr.attr) 1007 dev_id = ASUS_WMI_DEVID_FAN_CTRL; 1008 else if (attr == &sensor_dev_attr_temp1_input.dev_attr.attr) 1009 dev_id = ASUS_WMI_DEVID_THERMAL_CTRL; 1010 1011 if (dev_id != -1) { 1012 int err = asus_wmi_get_devstate(asus, dev_id, &value); 1013 1014 if (err < 0) 1015 return 0; /* can't return negative here */ 1016 } 1017 1018 if (dev_id == ASUS_WMI_DEVID_FAN_CTRL) { 1019 /* 1020 * We need to find a better way, probably using sfun, 1021 * bits or spec ... 1022 * Currently we disable it if: 1023 * - ASUS_WMI_UNSUPPORTED_METHOD is returned 1024 * - reverved bits are non-zero 1025 * - sfun and presence bit are not set 1026 */ 1027 if (value == ASUS_WMI_UNSUPPORTED_METHOD || value & 0xFFF80000 1028 || (!asus->sfun && !(value & ASUS_WMI_DSTS_PRESENCE_BIT))) 1029 ok = false; 1030 } else if (dev_id == ASUS_WMI_DEVID_THERMAL_CTRL) { 1031 /* If value is zero, something is clearly wrong */ 1032 if (value == 0) 1033 ok = false; 1034 } 1035 1036 return ok ? attr->mode : 0; 1037} 1038 1039static struct attribute_group hwmon_attribute_group = { 1040 .is_visible = asus_hwmon_sysfs_is_visible, 1041 .attrs = hwmon_attributes 1042}; 1043 1044static void asus_wmi_hwmon_exit(struct asus_wmi *asus) 1045{ 1046 struct device *hwmon; 1047 1048 hwmon = asus->hwmon_device; 1049 if (!hwmon) 1050 return; 1051 sysfs_remove_group(&hwmon->kobj, &hwmon_attribute_group); 1052 hwmon_device_unregister(hwmon); 1053 asus->hwmon_device = NULL; 1054} 1055 1056static int asus_wmi_hwmon_init(struct asus_wmi *asus) 1057{ 1058 struct device *hwmon; 1059 int result; 1060 1061 hwmon = hwmon_device_register(&asus->platform_device->dev); 1062 if (IS_ERR(hwmon)) { 1063 pr_err("Could not register asus hwmon device\n"); 1064 return PTR_ERR(hwmon); 1065 } 1066 dev_set_drvdata(hwmon, asus); 1067 asus->hwmon_device = hwmon; 1068 result = sysfs_create_group(&hwmon->kobj, &hwmon_attribute_group); 1069 if (result) 1070 asus_wmi_hwmon_exit(asus); 1071 return result; 1072} 1073 1074/* 1075 * Backlight 1076 */ 1077static int read_backlight_power(struct asus_wmi *asus) 1078{ 1079 int ret; 1080 if (asus->driver->quirks->store_backlight_power) 1081 ret = !asus->driver->panel_power; 1082 else 1083 ret = asus_wmi_get_devstate_simple(asus, 1084 ASUS_WMI_DEVID_BACKLIGHT); 1085 1086 if (ret < 0) 1087 return ret; 1088 1089 return ret ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN; 1090} 1091 1092static int read_brightness_max(struct asus_wmi *asus) 1093{ 1094 u32 retval; 1095 int err; 1096 1097 err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_BRIGHTNESS, &retval); 1098 1099 if (err < 0) 1100 return err; 1101 1102 retval = retval & ASUS_WMI_DSTS_MAX_BRIGTH_MASK; 1103 retval >>= 8; 1104 1105 if (!retval) 1106 return -ENODEV; 1107 1108 return retval; 1109} 1110 1111static int read_brightness(struct backlight_device *bd) 1112{ 1113 struct asus_wmi *asus = bl_get_data(bd); 1114 u32 retval; 1115 int err; 1116 1117 err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_BRIGHTNESS, &retval); 1118 1119 if (err < 0) 1120 return err; 1121 1122 return retval & ASUS_WMI_DSTS_BRIGHTNESS_MASK; 1123} 1124 1125static u32 get_scalar_command(struct backlight_device *bd) 1126{ 1127 struct asus_wmi *asus = bl_get_data(bd); 1128 u32 ctrl_param = 0; 1129 1130 if ((asus->driver->brightness < bd->props.brightness) || 1131 bd->props.brightness == bd->props.max_brightness) 1132 ctrl_param = 0x00008001; 1133 else if ((asus->driver->brightness > bd->props.brightness) || 1134 bd->props.brightness == 0) 1135 ctrl_param = 0x00008000; 1136 1137 asus->driver->brightness = bd->props.brightness; 1138 1139 return ctrl_param; 1140} 1141 1142static int update_bl_status(struct backlight_device *bd) 1143{ 1144 struct asus_wmi *asus = bl_get_data(bd); 1145 u32 ctrl_param; 1146 int power, err = 0; 1147 1148 power = read_backlight_power(asus); 1149 if (power != -ENODEV && bd->props.power != power) { 1150 ctrl_param = !!(bd->props.power == FB_BLANK_UNBLANK); 1151 err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BACKLIGHT, 1152 ctrl_param, NULL); 1153 if (asus->driver->quirks->store_backlight_power) 1154 asus->driver->panel_power = bd->props.power; 1155 1156 /* When using scalar brightness, updating the brightness 1157 * will mess with the backlight power */ 1158 if (asus->driver->quirks->scalar_panel_brightness) 1159 return err; 1160 } 1161 1162 if (asus->driver->quirks->scalar_panel_brightness) 1163 ctrl_param = get_scalar_command(bd); 1164 else 1165 ctrl_param = bd->props.brightness; 1166 1167 err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BRIGHTNESS, 1168 ctrl_param, NULL); 1169 1170 return err; 1171} 1172 1173static const struct backlight_ops asus_wmi_bl_ops = { 1174 .get_brightness = read_brightness, 1175 .update_status = update_bl_status, 1176}; 1177 1178static int asus_wmi_backlight_notify(struct asus_wmi *asus, int code) 1179{ 1180 struct backlight_device *bd = asus->backlight_device; 1181 int old = bd->props.brightness; 1182 int new = old; 1183 1184 if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX) 1185 new = code - NOTIFY_BRNUP_MIN + 1; 1186 else if (code >= NOTIFY_BRNDOWN_MIN && code <= NOTIFY_BRNDOWN_MAX) 1187 new = code - NOTIFY_BRNDOWN_MIN; 1188 1189 bd->props.brightness = new; 1190 backlight_update_status(bd); 1191 backlight_force_update(bd, BACKLIGHT_UPDATE_HOTKEY); 1192 1193 return old; 1194} 1195 1196static int asus_wmi_backlight_init(struct asus_wmi *asus) 1197{ 1198 struct backlight_device *bd; 1199 struct backlight_properties props; 1200 int max; 1201 int power; 1202 1203 max = read_brightness_max(asus); 1204 1205 if (max == -ENODEV) 1206 max = 0; 1207 else if (max < 0) 1208 return max; 1209 1210 power = read_backlight_power(asus); 1211 1212 if (power == -ENODEV) 1213 power = FB_BLANK_UNBLANK; 1214 else if (power < 0) 1215 return power; 1216 1217 memset(&props, 0, sizeof(struct backlight_properties)); 1218 props.type = BACKLIGHT_PLATFORM; 1219 props.max_brightness = max; 1220 bd = backlight_device_register(asus->driver->name, 1221 &asus->platform_device->dev, asus, 1222 &asus_wmi_bl_ops, &props); 1223 if (IS_ERR(bd)) { 1224 pr_err("Could not register backlight device\n"); 1225 return PTR_ERR(bd); 1226 } 1227 1228 asus->backlight_device = bd; 1229 1230 if (asus->driver->quirks->store_backlight_power) 1231 asus->driver->panel_power = power; 1232 1233 bd->props.brightness = read_brightness(bd); 1234 bd->props.power = power; 1235 backlight_update_status(bd); 1236 1237 asus->driver->brightness = bd->props.brightness; 1238 1239 return 0; 1240} 1241 1242static void asus_wmi_backlight_exit(struct asus_wmi *asus) 1243{ 1244 if (asus->backlight_device) 1245 backlight_device_unregister(asus->backlight_device); 1246 1247 asus->backlight_device = NULL; 1248} 1249 1250static void asus_wmi_notify(u32 value, void *context) 1251{ 1252 struct asus_wmi *asus = context; 1253 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; 1254 union acpi_object *obj; 1255 acpi_status status; 1256 int code; 1257 int orig_code; 1258 unsigned int key_value = 1; 1259 bool autorelease = 1; 1260 1261 status = wmi_get_event_data(value, &response); 1262 if (status != AE_OK) { 1263 pr_err("bad event status 0x%x\n", status); 1264 return; 1265 } 1266 1267 obj = (union acpi_object *)response.pointer; 1268 1269 if (!obj || obj->type != ACPI_TYPE_INTEGER) 1270 goto exit; 1271 1272 code = obj->integer.value; 1273 orig_code = code; 1274 1275 if (asus->driver->key_filter) { 1276 asus->driver->key_filter(asus->driver, &code, &key_value, 1277 &autorelease); 1278 if (code == ASUS_WMI_KEY_IGNORE) 1279 goto exit; 1280 } 1281 1282 if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX) 1283 code = NOTIFY_BRNUP_MIN; 1284 else if (code >= NOTIFY_BRNDOWN_MIN && 1285 code <= NOTIFY_BRNDOWN_MAX) 1286 code = NOTIFY_BRNDOWN_MIN; 1287 1288 if (code == NOTIFY_BRNUP_MIN || code == NOTIFY_BRNDOWN_MIN) { 1289 if (!acpi_video_backlight_support()) 1290 asus_wmi_backlight_notify(asus, orig_code); 1291 } else if (!sparse_keymap_report_event(asus->inputdev, code, 1292 key_value, autorelease)) 1293 pr_info("Unknown key %x pressed\n", code); 1294 1295exit: 1296 kfree(obj); 1297} 1298 1299/* 1300 * Sys helpers 1301 */ 1302static int parse_arg(const char *buf, unsigned long count, int *val) 1303{ 1304 if (!count) 1305 return 0; 1306 if (sscanf(buf, "%i", val) != 1) 1307 return -EINVAL; 1308 return count; 1309} 1310 1311static ssize_t store_sys_wmi(struct asus_wmi *asus, int devid, 1312 const char *buf, size_t count) 1313{ 1314 u32 retval; 1315 int rv, err, value; 1316 1317 value = asus_wmi_get_devstate_simple(asus, devid); 1318 if (value == -ENODEV) /* Check device presence */ 1319 return value; 1320 1321 rv = parse_arg(buf, count, &value); 1322 err = asus_wmi_set_devstate(devid, value, &retval); 1323 1324 if (err < 0) 1325 return err; 1326 1327 return rv; 1328} 1329 1330static ssize_t show_sys_wmi(struct asus_wmi *asus, int devid, char *buf) 1331{ 1332 int value = asus_wmi_get_devstate_simple(asus, devid); 1333 1334 if (value < 0) 1335 return value; 1336 1337 return sprintf(buf, "%d\n", value); 1338} 1339 1340#define ASUS_WMI_CREATE_DEVICE_ATTR(_name, _mode, _cm) \ 1341 static ssize_t show_##_name(struct device *dev, \ 1342 struct device_attribute *attr, \ 1343 char *buf) \ 1344 { \ 1345 struct asus_wmi *asus = dev_get_drvdata(dev); \ 1346 \ 1347 return show_sys_wmi(asus, _cm, buf); \ 1348 } \ 1349 static ssize_t store_##_name(struct device *dev, \ 1350 struct device_attribute *attr, \ 1351 const char *buf, size_t count) \ 1352 { \ 1353 struct asus_wmi *asus = dev_get_drvdata(dev); \ 1354 \ 1355 return store_sys_wmi(asus, _cm, buf, count); \ 1356 } \ 1357 static struct device_attribute dev_attr_##_name = { \ 1358 .attr = { \ 1359 .name = __stringify(_name), \ 1360 .mode = _mode }, \ 1361 .show = show_##_name, \ 1362 .store = store_##_name, \ 1363 } 1364 1365ASUS_WMI_CREATE_DEVICE_ATTR(touchpad, 0644, ASUS_WMI_DEVID_TOUCHPAD); 1366ASUS_WMI_CREATE_DEVICE_ATTR(camera, 0644, ASUS_WMI_DEVID_CAMERA); 1367ASUS_WMI_CREATE_DEVICE_ATTR(cardr, 0644, ASUS_WMI_DEVID_CARDREADER); 1368 1369static ssize_t store_cpufv(struct device *dev, struct device_attribute *attr, 1370 const char *buf, size_t count) 1371{ 1372 int value, rv; 1373 1374 if (!count || sscanf(buf, "%i", &value) != 1) 1375 return -EINVAL; 1376 if (value < 0 || value > 2) 1377 return -EINVAL; 1378 1379 rv = asus_wmi_evaluate_method(ASUS_WMI_METHODID_CFVS, value, 0, NULL); 1380 if (rv < 0) 1381 return rv; 1382 1383 return count; 1384} 1385 1386static DEVICE_ATTR(cpufv, S_IRUGO | S_IWUSR, NULL, store_cpufv); 1387 1388static struct attribute *platform_attributes[] = { 1389 &dev_attr_cpufv.attr, 1390 &dev_attr_camera.attr, 1391 &dev_attr_cardr.attr, 1392 &dev_attr_touchpad.attr, 1393 NULL 1394}; 1395 1396static umode_t asus_sysfs_is_visible(struct kobject *kobj, 1397 struct attribute *attr, int idx) 1398{ 1399 struct device *dev = container_of(kobj, struct device, kobj); 1400 struct platform_device *pdev = to_platform_device(dev); 1401 struct asus_wmi *asus = platform_get_drvdata(pdev); 1402 bool ok = true; 1403 int devid = -1; 1404 1405 if (attr == &dev_attr_camera.attr) 1406 devid = ASUS_WMI_DEVID_CAMERA; 1407 else if (attr == &dev_attr_cardr.attr) 1408 devid = ASUS_WMI_DEVID_CARDREADER; 1409 else if (attr == &dev_attr_touchpad.attr) 1410 devid = ASUS_WMI_DEVID_TOUCHPAD; 1411 1412 if (devid != -1) 1413 ok = !(asus_wmi_get_devstate_simple(asus, devid) < 0); 1414 1415 return ok ? attr->mode : 0; 1416} 1417 1418static struct attribute_group platform_attribute_group = { 1419 .is_visible = asus_sysfs_is_visible, 1420 .attrs = platform_attributes 1421}; 1422 1423static void asus_wmi_sysfs_exit(struct platform_device *device) 1424{ 1425 sysfs_remove_group(&device->dev.kobj, &platform_attribute_group); 1426} 1427 1428static int asus_wmi_sysfs_init(struct platform_device *device) 1429{ 1430 return sysfs_create_group(&device->dev.kobj, &platform_attribute_group); 1431} 1432 1433/* 1434 * Platform device 1435 */ 1436static int asus_wmi_platform_init(struct asus_wmi *asus) 1437{ 1438 int rv; 1439 1440 /* INIT enable hotkeys on some models */ 1441 if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_INIT, 0, 0, &rv)) 1442 pr_info("Initialization: %#x", rv); 1443 1444 /* We don't know yet what to do with this version... */ 1445 if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_SPEC, 0, 0x9, &rv)) { 1446 pr_info("BIOS WMI version: %d.%d", rv >> 16, rv & 0xFF); 1447 asus->spec = rv; 1448 } 1449 1450 /* 1451 * The SFUN method probably allows the original driver to get the list 1452 * of features supported by a given model. For now, 0x0100 or 0x0800 1453 * bit signifies that the laptop is equipped with a Wi-Fi MiniPCI card. 1454 * The significance of others is yet to be found. 1455 */ 1456 if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_SFUN, 0, 0, &rv)) { 1457 pr_info("SFUN value: %#x", rv); 1458 asus->sfun = rv; 1459 } 1460 1461 /* 1462 * Eee PC and Notebooks seems to have different method_id for DSTS, 1463 * but it may also be related to the BIOS's SPEC. 1464 * Note, on most Eeepc, there is no way to check if a method exist 1465 * or note, while on notebooks, they returns 0xFFFFFFFE on failure, 1466 * but once again, SPEC may probably be used for that kind of things. 1467 */ 1468 if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS, 0, 0, NULL)) 1469 asus->dsts_id = ASUS_WMI_METHODID_DSTS; 1470 else if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS2, 0, 0, NULL)) 1471 asus->dsts_id = ASUS_WMI_METHODID_DSTS2; 1472 1473 if (!asus->dsts_id) { 1474 pr_err("Can't find DSTS"); 1475 return -ENODEV; 1476 } 1477 1478 /* CWAP allow to define the behavior of the Fn+F2 key, 1479 * this method doesn't seems to be present on Eee PCs */ 1480 if (asus->driver->quirks->wapf >= 0) 1481 asus_wmi_set_devstate(ASUS_WMI_DEVID_CWAP, 1482 asus->driver->quirks->wapf, NULL); 1483 1484 return asus_wmi_sysfs_init(asus->platform_device); 1485} 1486 1487static void asus_wmi_platform_exit(struct asus_wmi *asus) 1488{ 1489 asus_wmi_sysfs_exit(asus->platform_device); 1490} 1491 1492/* 1493 * debugfs 1494 */ 1495struct asus_wmi_debugfs_node { 1496 struct asus_wmi *asus; 1497 char *name; 1498 int (*show) (struct seq_file *m, void *data); 1499}; 1500 1501static int show_dsts(struct seq_file *m, void *data) 1502{ 1503 struct asus_wmi *asus = m->private; 1504 int err; 1505 u32 retval = -1; 1506 1507 err = asus_wmi_get_devstate(asus, asus->debug.dev_id, &retval); 1508 1509 if (err < 0) 1510 return err; 1511 1512 seq_printf(m, "DSTS(%#x) = %#x\n", asus->debug.dev_id, retval); 1513 1514 return 0; 1515} 1516 1517static int show_devs(struct seq_file *m, void *data) 1518{ 1519 struct asus_wmi *asus = m->private; 1520 int err; 1521 u32 retval = -1; 1522 1523 err = asus_wmi_set_devstate(asus->debug.dev_id, asus->debug.ctrl_param, 1524 &retval); 1525 1526 if (err < 0) 1527 return err; 1528 1529 seq_printf(m, "DEVS(%#x, %#x) = %#x\n", asus->debug.dev_id, 1530 asus->debug.ctrl_param, retval); 1531 1532 return 0; 1533} 1534 1535static int show_call(struct seq_file *m, void *data) 1536{ 1537 struct asus_wmi *asus = m->private; 1538 struct bios_args args = { 1539 .arg0 = asus->debug.dev_id, 1540 .arg1 = asus->debug.ctrl_param, 1541 }; 1542 struct acpi_buffer input = { (acpi_size) sizeof(args), &args }; 1543 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; 1544 union acpi_object *obj; 1545 acpi_status status; 1546 1547 status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID, 1548 1, asus->debug.method_id, 1549 &input, &output); 1550 1551 if (ACPI_FAILURE(status)) 1552 return -EIO; 1553 1554 obj = (union acpi_object *)output.pointer; 1555 if (obj && obj->type == ACPI_TYPE_INTEGER) 1556 seq_printf(m, "%#x(%#x, %#x) = %#x\n", asus->debug.method_id, 1557 asus->debug.dev_id, asus->debug.ctrl_param, 1558 (u32) obj->integer.value); 1559 else 1560 seq_printf(m, "%#x(%#x, %#x) = t:%d\n", asus->debug.method_id, 1561 asus->debug.dev_id, asus->debug.ctrl_param, 1562 obj ? obj->type : -1); 1563 1564 kfree(obj); 1565 1566 return 0; 1567} 1568 1569static struct asus_wmi_debugfs_node asus_wmi_debug_files[] = { 1570 {NULL, "devs", show_devs}, 1571 {NULL, "dsts", show_dsts}, 1572 {NULL, "call", show_call}, 1573}; 1574 1575static int asus_wmi_debugfs_open(struct inode *inode, struct file *file) 1576{ 1577 struct asus_wmi_debugfs_node *node = inode->i_private; 1578 1579 return single_open(file, node->show, node->asus); 1580} 1581 1582static const struct file_operations asus_wmi_debugfs_io_ops = { 1583 .owner = THIS_MODULE, 1584 .open = asus_wmi_debugfs_open, 1585 .read = seq_read, 1586 .llseek = seq_lseek, 1587 .release = single_release, 1588}; 1589 1590static void asus_wmi_debugfs_exit(struct asus_wmi *asus) 1591{ 1592 debugfs_remove_recursive(asus->debug.root); 1593} 1594 1595static int asus_wmi_debugfs_init(struct asus_wmi *asus) 1596{ 1597 struct dentry *dent; 1598 int i; 1599 1600 asus->debug.root = debugfs_create_dir(asus->driver->name, NULL); 1601 if (!asus->debug.root) { 1602 pr_err("failed to create debugfs directory"); 1603 goto error_debugfs; 1604 } 1605 1606 dent = debugfs_create_x32("method_id", S_IRUGO | S_IWUSR, 1607 asus->debug.root, &asus->debug.method_id); 1608 if (!dent) 1609 goto error_debugfs; 1610 1611 dent = debugfs_create_x32("dev_id", S_IRUGO | S_IWUSR, 1612 asus->debug.root, &asus->debug.dev_id); 1613 if (!dent) 1614 goto error_debugfs; 1615 1616 dent = debugfs_create_x32("ctrl_param", S_IRUGO | S_IWUSR, 1617 asus->debug.root, &asus->debug.ctrl_param); 1618 if (!dent) 1619 goto error_debugfs; 1620 1621 for (i = 0; i < ARRAY_SIZE(asus_wmi_debug_files); i++) { 1622 struct asus_wmi_debugfs_node *node = &asus_wmi_debug_files[i]; 1623 1624 node->asus = asus; 1625 dent = debugfs_create_file(node->name, S_IFREG | S_IRUGO, 1626 asus->debug.root, node, 1627 &asus_wmi_debugfs_io_ops); 1628 if (!dent) { 1629 pr_err("failed to create debug file: %s\n", node->name); 1630 goto error_debugfs; 1631 } 1632 } 1633 1634 return 0; 1635 1636error_debugfs: 1637 asus_wmi_debugfs_exit(asus); 1638 return -ENOMEM; 1639} 1640 1641/* 1642 * WMI Driver 1643 */ 1644static int asus_wmi_add(struct platform_device *pdev) 1645{ 1646 struct platform_driver *pdrv = to_platform_driver(pdev->dev.driver); 1647 struct asus_wmi_driver *wdrv = to_asus_wmi_driver(pdrv); 1648 struct asus_wmi *asus; 1649 acpi_status status; 1650 int err; 1651 1652 asus = kzalloc(sizeof(struct asus_wmi), GFP_KERNEL); 1653 if (!asus) 1654 return -ENOMEM; 1655 1656 asus->driver = wdrv; 1657 asus->platform_device = pdev; 1658 wdrv->platform_device = pdev; 1659 platform_set_drvdata(asus->platform_device, asus); 1660 1661 if (wdrv->detect_quirks) 1662 wdrv->detect_quirks(asus->driver); 1663 1664 err = asus_wmi_platform_init(asus); 1665 if (err) 1666 goto fail_platform; 1667 1668 err = asus_wmi_input_init(asus); 1669 if (err) 1670 goto fail_input; 1671 1672 err = asus_wmi_hwmon_init(asus); 1673 if (err) 1674 goto fail_hwmon; 1675 1676 err = asus_wmi_led_init(asus); 1677 if (err) 1678 goto fail_leds; 1679 1680 err = asus_wmi_rfkill_init(asus); 1681 if (err) 1682 goto fail_rfkill; 1683 1684 if (!acpi_video_backlight_support()) { 1685 err = asus_wmi_backlight_init(asus); 1686 if (err && err != -ENODEV) 1687 goto fail_backlight; 1688 } else 1689 pr_info("Backlight controlled by ACPI video driver\n"); 1690 1691 status = wmi_install_notify_handler(asus->driver->event_guid, 1692 asus_wmi_notify, asus); 1693 if (ACPI_FAILURE(status)) { 1694 pr_err("Unable to register notify handler - %d\n", status); 1695 err = -ENODEV; 1696 goto fail_wmi_handler; 1697 } 1698 1699 err = asus_wmi_debugfs_init(asus); 1700 if (err) 1701 goto fail_debugfs; 1702 1703 return 0; 1704 1705fail_debugfs: 1706 wmi_remove_notify_handler(asus->driver->event_guid); 1707fail_wmi_handler: 1708 asus_wmi_backlight_exit(asus); 1709fail_backlight: 1710 asus_wmi_rfkill_exit(asus); 1711fail_rfkill: 1712 asus_wmi_led_exit(asus); 1713fail_leds: 1714 asus_wmi_hwmon_exit(asus); 1715fail_hwmon: 1716 asus_wmi_input_exit(asus); 1717fail_input: 1718 asus_wmi_platform_exit(asus); 1719fail_platform: 1720 kfree(asus); 1721 return err; 1722} 1723 1724static int asus_wmi_remove(struct platform_device *device) 1725{ 1726 struct asus_wmi *asus; 1727 1728 asus = platform_get_drvdata(device); 1729 wmi_remove_notify_handler(asus->driver->event_guid); 1730 asus_wmi_backlight_exit(asus); 1731 asus_wmi_input_exit(asus); 1732 asus_wmi_hwmon_exit(asus); 1733 asus_wmi_led_exit(asus); 1734 asus_wmi_rfkill_exit(asus); 1735 asus_wmi_debugfs_exit(asus); 1736 asus_wmi_platform_exit(asus); 1737 1738 kfree(asus); 1739 return 0; 1740} 1741 1742/* 1743 * Platform driver - hibernate/resume callbacks 1744 */ 1745static int asus_hotk_thaw(struct device *device) 1746{ 1747 struct asus_wmi *asus = dev_get_drvdata(device); 1748 1749 if (asus->wlan.rfkill) { 1750 bool wlan; 1751 1752 /* 1753 * Work around bios bug - acpi _PTS turns off the wireless led 1754 * during suspend. Normally it restores it on resume, but 1755 * we should kick it ourselves in case hibernation is aborted. 1756 */ 1757 wlan = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WLAN); 1758 asus_wmi_set_devstate(ASUS_WMI_DEVID_WLAN, wlan, NULL); 1759 } 1760 1761 return 0; 1762} 1763 1764static int asus_hotk_restore(struct device *device) 1765{ 1766 struct asus_wmi *asus = dev_get_drvdata(device); 1767 int bl; 1768 1769 /* Refresh both wlan rfkill state and pci hotplug */ 1770 if (asus->wlan.rfkill) 1771 asus_rfkill_hotplug(asus); 1772 1773 if (asus->bluetooth.rfkill) { 1774 bl = !asus_wmi_get_devstate_simple(asus, 1775 ASUS_WMI_DEVID_BLUETOOTH); 1776 rfkill_set_sw_state(asus->bluetooth.rfkill, bl); 1777 } 1778 if (asus->wimax.rfkill) { 1779 bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WIMAX); 1780 rfkill_set_sw_state(asus->wimax.rfkill, bl); 1781 } 1782 if (asus->wwan3g.rfkill) { 1783 bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WWAN3G); 1784 rfkill_set_sw_state(asus->wwan3g.rfkill, bl); 1785 } 1786 if (asus->gps.rfkill) { 1787 bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_GPS); 1788 rfkill_set_sw_state(asus->gps.rfkill, bl); 1789 } 1790 if (asus->uwb.rfkill) { 1791 bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_UWB); 1792 rfkill_set_sw_state(asus->uwb.rfkill, bl); 1793 } 1794 1795 return 0; 1796} 1797 1798static const struct dev_pm_ops asus_pm_ops = { 1799 .thaw = asus_hotk_thaw, 1800 .restore = asus_hotk_restore, 1801}; 1802 1803static int asus_wmi_probe(struct platform_device *pdev) 1804{ 1805 struct platform_driver *pdrv = to_platform_driver(pdev->dev.driver); 1806 struct asus_wmi_driver *wdrv = to_asus_wmi_driver(pdrv); 1807 int ret; 1808 1809 if (!wmi_has_guid(ASUS_WMI_MGMT_GUID)) { 1810 pr_warn("Management GUID not found\n"); 1811 return -ENODEV; 1812 } 1813 1814 if (wdrv->event_guid && !wmi_has_guid(wdrv->event_guid)) { 1815 pr_warn("Event GUID not found\n"); 1816 return -ENODEV; 1817 } 1818 1819 if (wdrv->probe) { 1820 ret = wdrv->probe(pdev); 1821 if (ret) 1822 return ret; 1823 } 1824 1825 return asus_wmi_add(pdev); 1826} 1827 1828static bool used; 1829 1830int __init_or_module asus_wmi_register_driver(struct asus_wmi_driver *driver) 1831{ 1832 struct platform_driver *platform_driver; 1833 struct platform_device *platform_device; 1834 1835 if (used) 1836 return -EBUSY; 1837 1838 platform_driver = &driver->platform_driver; 1839 platform_driver->remove = asus_wmi_remove; 1840 platform_driver->driver.owner = driver->owner; 1841 platform_driver->driver.name = driver->name; 1842 platform_driver->driver.pm = &asus_pm_ops; 1843 1844 platform_device = platform_create_bundle(platform_driver, 1845 asus_wmi_probe, 1846 NULL, 0, NULL, 0); 1847 if (IS_ERR(platform_device)) 1848 return PTR_ERR(platform_device); 1849 1850 used = true; 1851 return 0; 1852} 1853EXPORT_SYMBOL_GPL(asus_wmi_register_driver); 1854 1855void asus_wmi_unregister_driver(struct asus_wmi_driver *driver) 1856{ 1857 platform_device_unregister(driver->platform_device); 1858 platform_driver_unregister(&driver->platform_driver); 1859 used = false; 1860} 1861EXPORT_SYMBOL_GPL(asus_wmi_unregister_driver); 1862 1863static int __init asus_wmi_init(void) 1864{ 1865 if (!wmi_has_guid(ASUS_WMI_MGMT_GUID)) { 1866 pr_info("Asus Management GUID not found"); 1867 return -ENODEV; 1868 } 1869 1870 pr_info("ASUS WMI generic driver loaded"); 1871 return 0; 1872} 1873 1874static void __exit asus_wmi_exit(void) 1875{ 1876 pr_info("ASUS WMI generic driver unloaded"); 1877} 1878 1879module_init(asus_wmi_init); 1880module_exit(asus_wmi_exit);