acer-wmi.c revision 08a0799d5736f1494ef35d386570d177447acbfb
1/* 2 * Acer WMI Laptop Extras 3 * 4 * Copyright (C) 2007-2009 Carlos Corbacho <carlos@strangeworlds.co.uk> 5 * 6 * Based on acer_acpi: 7 * Copyright (C) 2005-2007 E.M. Smith 8 * Copyright (C) 2007-2008 Carlos Corbacho <cathectic@gmail.com> 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2 of the License, or 13 * (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 */ 24 25#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 26 27#include <linux/kernel.h> 28#include <linux/module.h> 29#include <linux/init.h> 30#include <linux/types.h> 31#include <linux/dmi.h> 32#include <linux/fb.h> 33#include <linux/backlight.h> 34#include <linux/leds.h> 35#include <linux/platform_device.h> 36#include <linux/acpi.h> 37#include <linux/i8042.h> 38#include <linux/rfkill.h> 39#include <linux/workqueue.h> 40#include <linux/debugfs.h> 41#include <linux/slab.h> 42#include <linux/input.h> 43#include <linux/input/sparse-keymap.h> 44 45#include <acpi/acpi_drivers.h> 46 47MODULE_AUTHOR("Carlos Corbacho"); 48MODULE_DESCRIPTION("Acer Laptop WMI Extras Driver"); 49MODULE_LICENSE("GPL"); 50 51/* 52 * Magic Number 53 * Meaning is unknown - this number is required for writing to ACPI for AMW0 54 * (it's also used in acerhk when directly accessing the BIOS) 55 */ 56#define ACER_AMW0_WRITE 0x9610 57 58/* 59 * Bit masks for the AMW0 interface 60 */ 61#define ACER_AMW0_WIRELESS_MASK 0x35 62#define ACER_AMW0_BLUETOOTH_MASK 0x34 63#define ACER_AMW0_MAILLED_MASK 0x31 64 65/* 66 * Method IDs for WMID interface 67 */ 68#define ACER_WMID_GET_WIRELESS_METHODID 1 69#define ACER_WMID_GET_BLUETOOTH_METHODID 2 70#define ACER_WMID_GET_BRIGHTNESS_METHODID 3 71#define ACER_WMID_SET_WIRELESS_METHODID 4 72#define ACER_WMID_SET_BLUETOOTH_METHODID 5 73#define ACER_WMID_SET_BRIGHTNESS_METHODID 6 74#define ACER_WMID_GET_THREEG_METHODID 10 75#define ACER_WMID_SET_THREEG_METHODID 11 76 77/* 78 * Acer ACPI method GUIDs 79 */ 80#define AMW0_GUID1 "67C3371D-95A3-4C37-BB61-DD47B491DAAB" 81#define AMW0_GUID2 "431F16ED-0C2B-444C-B267-27DEB140CF9C" 82#define WMID_GUID1 "6AF4F258-B401-42FD-BE91-3D4AC2D7C0D3" 83#define WMID_GUID2 "95764E09-FB56-4E83-B31A-37761F60994A" 84#define WMID_GUID3 "61EF69EA-865C-4BC3-A502-A0DEBA0CB531" 85 86/* 87 * Acer ACPI event GUIDs 88 */ 89#define ACERWMID_EVENT_GUID "676AA15E-6A47-4D9F-A2CC-1E6D18D14026" 90 91MODULE_ALIAS("wmi:67C3371D-95A3-4C37-BB61-DD47B491DAAB"); 92MODULE_ALIAS("wmi:6AF4F258-B401-42FD-BE91-3D4AC2D7C0D3"); 93MODULE_ALIAS("wmi:676AA15E-6A47-4D9F-A2CC-1E6D18D14026"); 94 95enum acer_wmi_event_ids { 96 WMID_HOTKEY_EVENT = 0x1, 97}; 98 99static const struct key_entry acer_wmi_keymap[] = { 100 {KE_KEY, 0x01, {KEY_WLAN} }, /* WiFi */ 101 {KE_KEY, 0x12, {KEY_BLUETOOTH} }, /* BT */ 102 {KE_KEY, 0x21, {KEY_PROG1} }, /* Backup */ 103 {KE_KEY, 0x22, {KEY_PROG2} }, /* Arcade */ 104 {KE_KEY, 0x23, {KEY_PROG3} }, /* P_Key */ 105 {KE_KEY, 0x24, {KEY_PROG4} }, /* Social networking_Key */ 106 {KE_KEY, 0x64, {KEY_SWITCHVIDEOMODE} }, /* Display Switch */ 107 {KE_KEY, 0x82, {KEY_TOUCHPAD_TOGGLE} }, /* Touch Pad On/Off */ 108 {KE_END, 0} 109}; 110 111static struct input_dev *acer_wmi_input_dev; 112 113struct event_return_value { 114 u8 function; 115 u8 key_num; 116 u16 device_state; 117 u32 reserved; 118} __attribute__((packed)); 119 120/* 121 * GUID3 Get Device Status device flags 122 */ 123#define ACER_WMID3_GDS_WIRELESS (1<<0) /* WiFi */ 124#define ACER_WMID3_GDS_THREEG (1<<6) /* 3G */ 125#define ACER_WMID3_GDS_BLUETOOTH (1<<11) /* BT */ 126 127struct lm_input_params { 128 u8 function_num; /* Function Number */ 129 u16 commun_devices; /* Communication type devices default status */ 130 u16 devices; /* Other type devices default status */ 131 u8 lm_status; /* Launch Manager Status */ 132 u16 reserved; 133} __attribute__((packed)); 134 135struct lm_return_value { 136 u8 error_code; /* Error Code */ 137 u8 ec_return_value; /* EC Return Value */ 138 u16 reserved; 139} __attribute__((packed)); 140 141struct wmid3_gds_input_param { /* Get Device Status input parameter */ 142 u8 function_num; /* Function Number */ 143 u8 hotkey_number; /* Hotkey Number */ 144 u16 devices; /* Get Device */ 145} __attribute__((packed)); 146 147struct wmid3_gds_return_value { /* Get Device Status return value*/ 148 u8 error_code; /* Error Code */ 149 u8 ec_return_value; /* EC Return Value */ 150 u16 devices; /* Current Device Status */ 151 u32 reserved; 152} __attribute__((packed)); 153 154struct hotkey_function_type_aa { 155 u8 type; 156 u8 length; 157 u16 handle; 158 u16 commun_func_bitmap; 159} __attribute__((packed)); 160 161/* 162 * Interface capability flags 163 */ 164#define ACER_CAP_MAILLED (1<<0) 165#define ACER_CAP_WIRELESS (1<<1) 166#define ACER_CAP_BLUETOOTH (1<<2) 167#define ACER_CAP_BRIGHTNESS (1<<3) 168#define ACER_CAP_THREEG (1<<4) 169#define ACER_CAP_ANY (0xFFFFFFFF) 170 171/* 172 * Interface type flags 173 */ 174enum interface_flags { 175 ACER_AMW0, 176 ACER_AMW0_V2, 177 ACER_WMID, 178}; 179 180#define ACER_DEFAULT_WIRELESS 0 181#define ACER_DEFAULT_BLUETOOTH 0 182#define ACER_DEFAULT_MAILLED 0 183#define ACER_DEFAULT_THREEG 0 184 185static int max_brightness = 0xF; 186 187static int mailled = -1; 188static int brightness = -1; 189static int threeg = -1; 190static int force_series; 191static bool ec_raw_mode; 192static bool has_type_aa; 193 194module_param(mailled, int, 0444); 195module_param(brightness, int, 0444); 196module_param(threeg, int, 0444); 197module_param(force_series, int, 0444); 198module_param(ec_raw_mode, bool, 0444); 199MODULE_PARM_DESC(mailled, "Set initial state of Mail LED"); 200MODULE_PARM_DESC(brightness, "Set initial LCD backlight brightness"); 201MODULE_PARM_DESC(threeg, "Set initial state of 3G hardware"); 202MODULE_PARM_DESC(force_series, "Force a different laptop series"); 203MODULE_PARM_DESC(ec_raw_mode, "Enable EC raw mode"); 204 205struct acer_data { 206 int mailled; 207 int threeg; 208 int brightness; 209}; 210 211struct acer_debug { 212 struct dentry *root; 213 struct dentry *devices; 214 u32 wmid_devices; 215}; 216 217static struct rfkill *wireless_rfkill; 218static struct rfkill *bluetooth_rfkill; 219static struct rfkill *threeg_rfkill; 220static bool rfkill_inited; 221 222/* Each low-level interface must define at least some of the following */ 223struct wmi_interface { 224 /* The WMI device type */ 225 u32 type; 226 227 /* The capabilities this interface provides */ 228 u32 capability; 229 230 /* Private data for the current interface */ 231 struct acer_data data; 232 233 /* debugfs entries associated with this interface */ 234 struct acer_debug debug; 235}; 236 237/* The static interface pointer, points to the currently detected interface */ 238static struct wmi_interface *interface; 239 240/* 241 * Embedded Controller quirks 242 * Some laptops require us to directly access the EC to either enable or query 243 * features that are not available through WMI. 244 */ 245 246struct quirk_entry { 247 u8 wireless; 248 u8 mailled; 249 s8 brightness; 250 u8 bluetooth; 251}; 252 253static struct quirk_entry *quirks; 254 255static void set_quirks(void) 256{ 257 if (!interface) 258 return; 259 260 if (quirks->mailled) 261 interface->capability |= ACER_CAP_MAILLED; 262 263 if (quirks->brightness) 264 interface->capability |= ACER_CAP_BRIGHTNESS; 265} 266 267static int dmi_matched(const struct dmi_system_id *dmi) 268{ 269 quirks = dmi->driver_data; 270 return 1; 271} 272 273static struct quirk_entry quirk_unknown = { 274}; 275 276static struct quirk_entry quirk_acer_aspire_1520 = { 277 .brightness = -1, 278}; 279 280static struct quirk_entry quirk_acer_travelmate_2490 = { 281 .mailled = 1, 282}; 283 284/* This AMW0 laptop has no bluetooth */ 285static struct quirk_entry quirk_medion_md_98300 = { 286 .wireless = 1, 287}; 288 289static struct quirk_entry quirk_fujitsu_amilo_li_1718 = { 290 .wireless = 2, 291}; 292 293/* The Aspire One has a dummy ACPI-WMI interface - disable it */ 294static struct dmi_system_id __devinitdata acer_blacklist[] = { 295 { 296 .ident = "Acer Aspire One (SSD)", 297 .matches = { 298 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 299 DMI_MATCH(DMI_PRODUCT_NAME, "AOA110"), 300 }, 301 }, 302 { 303 .ident = "Acer Aspire One (HDD)", 304 .matches = { 305 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 306 DMI_MATCH(DMI_PRODUCT_NAME, "AOA150"), 307 }, 308 }, 309 {} 310}; 311 312static struct dmi_system_id acer_quirks[] = { 313 { 314 .callback = dmi_matched, 315 .ident = "Acer Aspire 1360", 316 .matches = { 317 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 318 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1360"), 319 }, 320 .driver_data = &quirk_acer_aspire_1520, 321 }, 322 { 323 .callback = dmi_matched, 324 .ident = "Acer Aspire 1520", 325 .matches = { 326 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 327 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1520"), 328 }, 329 .driver_data = &quirk_acer_aspire_1520, 330 }, 331 { 332 .callback = dmi_matched, 333 .ident = "Acer Aspire 3100", 334 .matches = { 335 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 336 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3100"), 337 }, 338 .driver_data = &quirk_acer_travelmate_2490, 339 }, 340 { 341 .callback = dmi_matched, 342 .ident = "Acer Aspire 3610", 343 .matches = { 344 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 345 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3610"), 346 }, 347 .driver_data = &quirk_acer_travelmate_2490, 348 }, 349 { 350 .callback = dmi_matched, 351 .ident = "Acer Aspire 5100", 352 .matches = { 353 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 354 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5100"), 355 }, 356 .driver_data = &quirk_acer_travelmate_2490, 357 }, 358 { 359 .callback = dmi_matched, 360 .ident = "Acer Aspire 5610", 361 .matches = { 362 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 363 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5610"), 364 }, 365 .driver_data = &quirk_acer_travelmate_2490, 366 }, 367 { 368 .callback = dmi_matched, 369 .ident = "Acer Aspire 5630", 370 .matches = { 371 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 372 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5630"), 373 }, 374 .driver_data = &quirk_acer_travelmate_2490, 375 }, 376 { 377 .callback = dmi_matched, 378 .ident = "Acer Aspire 5650", 379 .matches = { 380 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 381 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5650"), 382 }, 383 .driver_data = &quirk_acer_travelmate_2490, 384 }, 385 { 386 .callback = dmi_matched, 387 .ident = "Acer Aspire 5680", 388 .matches = { 389 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 390 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5680"), 391 }, 392 .driver_data = &quirk_acer_travelmate_2490, 393 }, 394 { 395 .callback = dmi_matched, 396 .ident = "Acer Aspire 9110", 397 .matches = { 398 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 399 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 9110"), 400 }, 401 .driver_data = &quirk_acer_travelmate_2490, 402 }, 403 { 404 .callback = dmi_matched, 405 .ident = "Acer TravelMate 2490", 406 .matches = { 407 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 408 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2490"), 409 }, 410 .driver_data = &quirk_acer_travelmate_2490, 411 }, 412 { 413 .callback = dmi_matched, 414 .ident = "Acer TravelMate 4200", 415 .matches = { 416 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 417 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 4200"), 418 }, 419 .driver_data = &quirk_acer_travelmate_2490, 420 }, 421 { 422 .callback = dmi_matched, 423 .ident = "Fujitsu Siemens Amilo Li 1718", 424 .matches = { 425 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), 426 DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Li 1718"), 427 }, 428 .driver_data = &quirk_fujitsu_amilo_li_1718, 429 }, 430 { 431 .callback = dmi_matched, 432 .ident = "Medion MD 98300", 433 .matches = { 434 DMI_MATCH(DMI_SYS_VENDOR, "MEDION"), 435 DMI_MATCH(DMI_PRODUCT_NAME, "WAM2030"), 436 }, 437 .driver_data = &quirk_medion_md_98300, 438 }, 439 {} 440}; 441 442/* Find which quirks are needed for a particular vendor/ model pair */ 443static void find_quirks(void) 444{ 445 if (!force_series) { 446 dmi_check_system(acer_quirks); 447 } else if (force_series == 2490) { 448 quirks = &quirk_acer_travelmate_2490; 449 } 450 451 if (quirks == NULL) 452 quirks = &quirk_unknown; 453 454 set_quirks(); 455} 456 457/* 458 * General interface convenience methods 459 */ 460 461static bool has_cap(u32 cap) 462{ 463 if ((interface->capability & cap) != 0) 464 return 1; 465 466 return 0; 467} 468 469/* 470 * AMW0 (V1) interface 471 */ 472struct wmab_args { 473 u32 eax; 474 u32 ebx; 475 u32 ecx; 476 u32 edx; 477}; 478 479struct wmab_ret { 480 u32 eax; 481 u32 ebx; 482 u32 ecx; 483 u32 edx; 484 u32 eex; 485}; 486 487static acpi_status wmab_execute(struct wmab_args *regbuf, 488struct acpi_buffer *result) 489{ 490 struct acpi_buffer input; 491 acpi_status status; 492 input.length = sizeof(struct wmab_args); 493 input.pointer = (u8 *)regbuf; 494 495 status = wmi_evaluate_method(AMW0_GUID1, 1, 1, &input, result); 496 497 return status; 498} 499 500static acpi_status AMW0_get_u32(u32 *value, u32 cap, 501struct wmi_interface *iface) 502{ 503 int err; 504 u8 result; 505 506 switch (cap) { 507 case ACER_CAP_MAILLED: 508 switch (quirks->mailled) { 509 default: 510 err = ec_read(0xA, &result); 511 if (err) 512 return AE_ERROR; 513 *value = (result >> 7) & 0x1; 514 return AE_OK; 515 } 516 break; 517 case ACER_CAP_WIRELESS: 518 switch (quirks->wireless) { 519 case 1: 520 err = ec_read(0x7B, &result); 521 if (err) 522 return AE_ERROR; 523 *value = result & 0x1; 524 return AE_OK; 525 case 2: 526 err = ec_read(0x71, &result); 527 if (err) 528 return AE_ERROR; 529 *value = result & 0x1; 530 return AE_OK; 531 default: 532 err = ec_read(0xA, &result); 533 if (err) 534 return AE_ERROR; 535 *value = (result >> 2) & 0x1; 536 return AE_OK; 537 } 538 break; 539 case ACER_CAP_BLUETOOTH: 540 switch (quirks->bluetooth) { 541 default: 542 err = ec_read(0xA, &result); 543 if (err) 544 return AE_ERROR; 545 *value = (result >> 4) & 0x1; 546 return AE_OK; 547 } 548 break; 549 case ACER_CAP_BRIGHTNESS: 550 switch (quirks->brightness) { 551 default: 552 err = ec_read(0x83, &result); 553 if (err) 554 return AE_ERROR; 555 *value = result; 556 return AE_OK; 557 } 558 break; 559 default: 560 return AE_ERROR; 561 } 562 return AE_OK; 563} 564 565static acpi_status AMW0_set_u32(u32 value, u32 cap, struct wmi_interface *iface) 566{ 567 struct wmab_args args; 568 569 args.eax = ACER_AMW0_WRITE; 570 args.ebx = value ? (1<<8) : 0; 571 args.ecx = args.edx = 0; 572 573 switch (cap) { 574 case ACER_CAP_MAILLED: 575 if (value > 1) 576 return AE_BAD_PARAMETER; 577 args.ebx |= ACER_AMW0_MAILLED_MASK; 578 break; 579 case ACER_CAP_WIRELESS: 580 if (value > 1) 581 return AE_BAD_PARAMETER; 582 args.ebx |= ACER_AMW0_WIRELESS_MASK; 583 break; 584 case ACER_CAP_BLUETOOTH: 585 if (value > 1) 586 return AE_BAD_PARAMETER; 587 args.ebx |= ACER_AMW0_BLUETOOTH_MASK; 588 break; 589 case ACER_CAP_BRIGHTNESS: 590 if (value > max_brightness) 591 return AE_BAD_PARAMETER; 592 switch (quirks->brightness) { 593 default: 594 return ec_write(0x83, value); 595 break; 596 } 597 default: 598 return AE_ERROR; 599 } 600 601 /* Actually do the set */ 602 return wmab_execute(&args, NULL); 603} 604 605static acpi_status AMW0_find_mailled(void) 606{ 607 struct wmab_args args; 608 struct wmab_ret ret; 609 acpi_status status = AE_OK; 610 struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL }; 611 union acpi_object *obj; 612 613 args.eax = 0x86; 614 args.ebx = args.ecx = args.edx = 0; 615 616 status = wmab_execute(&args, &out); 617 if (ACPI_FAILURE(status)) 618 return status; 619 620 obj = (union acpi_object *) out.pointer; 621 if (obj && obj->type == ACPI_TYPE_BUFFER && 622 obj->buffer.length == sizeof(struct wmab_ret)) { 623 ret = *((struct wmab_ret *) obj->buffer.pointer); 624 } else { 625 kfree(out.pointer); 626 return AE_ERROR; 627 } 628 629 if (ret.eex & 0x1) 630 interface->capability |= ACER_CAP_MAILLED; 631 632 kfree(out.pointer); 633 634 return AE_OK; 635} 636 637static acpi_status AMW0_set_capabilities(void) 638{ 639 struct wmab_args args; 640 struct wmab_ret ret; 641 acpi_status status; 642 struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL }; 643 union acpi_object *obj; 644 645 /* 646 * On laptops with this strange GUID (non Acer), normal probing doesn't 647 * work. 648 */ 649 if (wmi_has_guid(AMW0_GUID2)) { 650 interface->capability |= ACER_CAP_WIRELESS; 651 return AE_OK; 652 } 653 654 args.eax = ACER_AMW0_WRITE; 655 args.ecx = args.edx = 0; 656 657 args.ebx = 0xa2 << 8; 658 args.ebx |= ACER_AMW0_WIRELESS_MASK; 659 660 status = wmab_execute(&args, &out); 661 if (ACPI_FAILURE(status)) 662 return status; 663 664 obj = out.pointer; 665 if (obj && obj->type == ACPI_TYPE_BUFFER && 666 obj->buffer.length == sizeof(struct wmab_ret)) { 667 ret = *((struct wmab_ret *) obj->buffer.pointer); 668 } else { 669 status = AE_ERROR; 670 goto out; 671 } 672 673 if (ret.eax & 0x1) 674 interface->capability |= ACER_CAP_WIRELESS; 675 676 args.ebx = 2 << 8; 677 args.ebx |= ACER_AMW0_BLUETOOTH_MASK; 678 679 /* 680 * It's ok to use existing buffer for next wmab_execute call. 681 * But we need to kfree(out.pointer) if next wmab_execute fail. 682 */ 683 status = wmab_execute(&args, &out); 684 if (ACPI_FAILURE(status)) 685 goto out; 686 687 obj = (union acpi_object *) out.pointer; 688 if (obj && obj->type == ACPI_TYPE_BUFFER 689 && obj->buffer.length == sizeof(struct wmab_ret)) { 690 ret = *((struct wmab_ret *) obj->buffer.pointer); 691 } else { 692 status = AE_ERROR; 693 goto out; 694 } 695 696 if (ret.eax & 0x1) 697 interface->capability |= ACER_CAP_BLUETOOTH; 698 699 /* 700 * This appears to be safe to enable, since all Wistron based laptops 701 * appear to use the same EC register for brightness, even if they 702 * differ for wireless, etc 703 */ 704 if (quirks->brightness >= 0) 705 interface->capability |= ACER_CAP_BRIGHTNESS; 706 707 status = AE_OK; 708out: 709 kfree(out.pointer); 710 return status; 711} 712 713static struct wmi_interface AMW0_interface = { 714 .type = ACER_AMW0, 715}; 716 717static struct wmi_interface AMW0_V2_interface = { 718 .type = ACER_AMW0_V2, 719}; 720 721/* 722 * New interface (The WMID interface) 723 */ 724static acpi_status 725WMI_execute_u32(u32 method_id, u32 in, u32 *out) 726{ 727 struct acpi_buffer input = { (acpi_size) sizeof(u32), (void *)(&in) }; 728 struct acpi_buffer result = { ACPI_ALLOCATE_BUFFER, NULL }; 729 union acpi_object *obj; 730 u32 tmp; 731 acpi_status status; 732 733 status = wmi_evaluate_method(WMID_GUID1, 1, method_id, &input, &result); 734 735 if (ACPI_FAILURE(status)) 736 return status; 737 738 obj = (union acpi_object *) result.pointer; 739 if (obj && obj->type == ACPI_TYPE_BUFFER && 740 obj->buffer.length == sizeof(u32)) { 741 tmp = *((u32 *) obj->buffer.pointer); 742 } else { 743 tmp = 0; 744 } 745 746 if (out) 747 *out = tmp; 748 749 kfree(result.pointer); 750 751 return status; 752} 753 754static acpi_status WMID_get_u32(u32 *value, u32 cap, 755struct wmi_interface *iface) 756{ 757 acpi_status status; 758 u8 tmp; 759 u32 result, method_id = 0; 760 761 switch (cap) { 762 case ACER_CAP_WIRELESS: 763 method_id = ACER_WMID_GET_WIRELESS_METHODID; 764 break; 765 case ACER_CAP_BLUETOOTH: 766 method_id = ACER_WMID_GET_BLUETOOTH_METHODID; 767 break; 768 case ACER_CAP_BRIGHTNESS: 769 method_id = ACER_WMID_GET_BRIGHTNESS_METHODID; 770 break; 771 case ACER_CAP_THREEG: 772 method_id = ACER_WMID_GET_THREEG_METHODID; 773 break; 774 case ACER_CAP_MAILLED: 775 if (quirks->mailled == 1) { 776 ec_read(0x9f, &tmp); 777 *value = tmp & 0x1; 778 return 0; 779 } 780 default: 781 return AE_ERROR; 782 } 783 status = WMI_execute_u32(method_id, 0, &result); 784 785 if (ACPI_SUCCESS(status)) 786 *value = (u8)result; 787 788 return status; 789} 790 791static acpi_status WMID_set_u32(u32 value, u32 cap, struct wmi_interface *iface) 792{ 793 u32 method_id = 0; 794 char param; 795 796 switch (cap) { 797 case ACER_CAP_BRIGHTNESS: 798 if (value > max_brightness) 799 return AE_BAD_PARAMETER; 800 method_id = ACER_WMID_SET_BRIGHTNESS_METHODID; 801 break; 802 case ACER_CAP_WIRELESS: 803 if (value > 1) 804 return AE_BAD_PARAMETER; 805 method_id = ACER_WMID_SET_WIRELESS_METHODID; 806 break; 807 case ACER_CAP_BLUETOOTH: 808 if (value > 1) 809 return AE_BAD_PARAMETER; 810 method_id = ACER_WMID_SET_BLUETOOTH_METHODID; 811 break; 812 case ACER_CAP_THREEG: 813 if (value > 1) 814 return AE_BAD_PARAMETER; 815 method_id = ACER_WMID_SET_THREEG_METHODID; 816 break; 817 case ACER_CAP_MAILLED: 818 if (value > 1) 819 return AE_BAD_PARAMETER; 820 if (quirks->mailled == 1) { 821 param = value ? 0x92 : 0x93; 822 i8042_lock_chip(); 823 i8042_command(¶m, 0x1059); 824 i8042_unlock_chip(); 825 return 0; 826 } 827 break; 828 default: 829 return AE_ERROR; 830 } 831 return WMI_execute_u32(method_id, (u32)value, NULL); 832} 833 834static void type_aa_dmi_decode(const struct dmi_header *header, void *dummy) 835{ 836 struct hotkey_function_type_aa *type_aa; 837 838 /* We are looking for OEM-specific Type AAh */ 839 if (header->type != 0xAA) 840 return; 841 842 has_type_aa = true; 843 type_aa = (struct hotkey_function_type_aa *) header; 844 845 pr_info("Function bitmap for Communication Button: 0x%x\n", 846 type_aa->commun_func_bitmap); 847 848 if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_WIRELESS) 849 interface->capability |= ACER_CAP_WIRELESS; 850 if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_THREEG) 851 interface->capability |= ACER_CAP_THREEG; 852 if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_BLUETOOTH) 853 interface->capability |= ACER_CAP_BLUETOOTH; 854} 855 856static acpi_status WMID_set_capabilities(void) 857{ 858 struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL}; 859 union acpi_object *obj; 860 acpi_status status; 861 u32 devices; 862 863 status = wmi_query_block(WMID_GUID2, 1, &out); 864 if (ACPI_FAILURE(status)) 865 return status; 866 867 obj = (union acpi_object *) out.pointer; 868 if (obj && obj->type == ACPI_TYPE_BUFFER && 869 obj->buffer.length == sizeof(u32)) { 870 devices = *((u32 *) obj->buffer.pointer); 871 } else { 872 kfree(out.pointer); 873 return AE_ERROR; 874 } 875 876 dmi_walk(type_aa_dmi_decode, NULL); 877 if (!has_type_aa) { 878 interface->capability |= ACER_CAP_WIRELESS; 879 interface->capability |= ACER_CAP_THREEG; 880 if (devices & 0x10) 881 interface->capability |= ACER_CAP_BLUETOOTH; 882 } 883 884 /* WMID always provides brightness methods */ 885 interface->capability |= ACER_CAP_BRIGHTNESS; 886 887 if (!(devices & 0x20)) 888 max_brightness = 0x9; 889 890 kfree(out.pointer); 891 return status; 892} 893 894static struct wmi_interface wmid_interface = { 895 .type = ACER_WMID, 896}; 897 898/* 899 * Generic Device (interface-independent) 900 */ 901 902static acpi_status get_u32(u32 *value, u32 cap) 903{ 904 acpi_status status = AE_ERROR; 905 906 switch (interface->type) { 907 case ACER_AMW0: 908 status = AMW0_get_u32(value, cap, interface); 909 break; 910 case ACER_AMW0_V2: 911 if (cap == ACER_CAP_MAILLED) { 912 status = AMW0_get_u32(value, cap, interface); 913 break; 914 } 915 case ACER_WMID: 916 status = WMID_get_u32(value, cap, interface); 917 break; 918 } 919 920 return status; 921} 922 923static acpi_status set_u32(u32 value, u32 cap) 924{ 925 acpi_status status; 926 927 if (interface->capability & cap) { 928 switch (interface->type) { 929 case ACER_AMW0: 930 return AMW0_set_u32(value, cap, interface); 931 case ACER_AMW0_V2: 932 if (cap == ACER_CAP_MAILLED) 933 return AMW0_set_u32(value, cap, interface); 934 935 /* 936 * On some models, some WMID methods don't toggle 937 * properly. For those cases, we want to run the AMW0 938 * method afterwards to be certain we've really toggled 939 * the device state. 940 */ 941 if (cap == ACER_CAP_WIRELESS || 942 cap == ACER_CAP_BLUETOOTH) { 943 status = WMID_set_u32(value, cap, interface); 944 if (ACPI_FAILURE(status)) 945 return status; 946 947 return AMW0_set_u32(value, cap, interface); 948 } 949 case ACER_WMID: 950 return WMID_set_u32(value, cap, interface); 951 default: 952 return AE_BAD_PARAMETER; 953 } 954 } 955 return AE_BAD_PARAMETER; 956} 957 958static void __init acer_commandline_init(void) 959{ 960 /* 961 * These will all fail silently if the value given is invalid, or the 962 * capability isn't available on the given interface 963 */ 964 set_u32(mailled, ACER_CAP_MAILLED); 965 if (!has_type_aa) 966 set_u32(threeg, ACER_CAP_THREEG); 967 set_u32(brightness, ACER_CAP_BRIGHTNESS); 968} 969 970/* 971 * LED device (Mail LED only, no other LEDs known yet) 972 */ 973static void mail_led_set(struct led_classdev *led_cdev, 974enum led_brightness value) 975{ 976 set_u32(value, ACER_CAP_MAILLED); 977} 978 979static struct led_classdev mail_led = { 980 .name = "acer-wmi::mail", 981 .brightness_set = mail_led_set, 982}; 983 984static int __devinit acer_led_init(struct device *dev) 985{ 986 return led_classdev_register(dev, &mail_led); 987} 988 989static void acer_led_exit(void) 990{ 991 set_u32(LED_OFF, ACER_CAP_MAILLED); 992 led_classdev_unregister(&mail_led); 993} 994 995/* 996 * Backlight device 997 */ 998static struct backlight_device *acer_backlight_device; 999 1000static int read_brightness(struct backlight_device *bd) 1001{ 1002 u32 value; 1003 get_u32(&value, ACER_CAP_BRIGHTNESS); 1004 return value; 1005} 1006 1007static int update_bl_status(struct backlight_device *bd) 1008{ 1009 int intensity = bd->props.brightness; 1010 1011 if (bd->props.power != FB_BLANK_UNBLANK) 1012 intensity = 0; 1013 if (bd->props.fb_blank != FB_BLANK_UNBLANK) 1014 intensity = 0; 1015 1016 set_u32(intensity, ACER_CAP_BRIGHTNESS); 1017 1018 return 0; 1019} 1020 1021static const struct backlight_ops acer_bl_ops = { 1022 .get_brightness = read_brightness, 1023 .update_status = update_bl_status, 1024}; 1025 1026static int __devinit acer_backlight_init(struct device *dev) 1027{ 1028 struct backlight_properties props; 1029 struct backlight_device *bd; 1030 1031 memset(&props, 0, sizeof(struct backlight_properties)); 1032 props.type = BACKLIGHT_PLATFORM; 1033 props.max_brightness = max_brightness; 1034 bd = backlight_device_register("acer-wmi", dev, NULL, &acer_bl_ops, 1035 &props); 1036 if (IS_ERR(bd)) { 1037 pr_err("Could not register Acer backlight device\n"); 1038 acer_backlight_device = NULL; 1039 return PTR_ERR(bd); 1040 } 1041 1042 acer_backlight_device = bd; 1043 1044 bd->props.power = FB_BLANK_UNBLANK; 1045 bd->props.brightness = read_brightness(bd); 1046 backlight_update_status(bd); 1047 return 0; 1048} 1049 1050static void acer_backlight_exit(void) 1051{ 1052 backlight_device_unregister(acer_backlight_device); 1053} 1054 1055static acpi_status wmid3_get_device_status(u32 *value, u16 device) 1056{ 1057 struct wmid3_gds_return_value return_value; 1058 acpi_status status; 1059 union acpi_object *obj; 1060 struct wmid3_gds_input_param params = { 1061 .function_num = 0x1, 1062 .hotkey_number = 0x01, 1063 .devices = device, 1064 }; 1065 struct acpi_buffer input = { 1066 sizeof(struct wmid3_gds_input_param), 1067 ¶ms 1068 }; 1069 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; 1070 1071 status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output); 1072 if (ACPI_FAILURE(status)) 1073 return status; 1074 1075 obj = output.pointer; 1076 1077 if (!obj) 1078 return AE_ERROR; 1079 else if (obj->type != ACPI_TYPE_BUFFER) { 1080 kfree(obj); 1081 return AE_ERROR; 1082 } 1083 if (obj->buffer.length != 8) { 1084 pr_warning("Unknown buffer length %d\n", obj->buffer.length); 1085 kfree(obj); 1086 return AE_ERROR; 1087 } 1088 1089 return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer); 1090 kfree(obj); 1091 1092 if (return_value.error_code || return_value.ec_return_value) 1093 pr_warning("Get Device Status failed: " 1094 "0x%x - 0x%x\n", return_value.error_code, 1095 return_value.ec_return_value); 1096 else 1097 *value = !!(return_value.devices & device); 1098 1099 return status; 1100} 1101 1102static acpi_status get_device_status(u32 *value, u32 cap) 1103{ 1104 if (wmi_has_guid(WMID_GUID3)) { 1105 u16 device; 1106 1107 switch (cap) { 1108 case ACER_CAP_WIRELESS: 1109 device = ACER_WMID3_GDS_WIRELESS; 1110 break; 1111 case ACER_CAP_BLUETOOTH: 1112 device = ACER_WMID3_GDS_BLUETOOTH; 1113 break; 1114 case ACER_CAP_THREEG: 1115 device = ACER_WMID3_GDS_THREEG; 1116 break; 1117 default: 1118 return AE_ERROR; 1119 } 1120 return wmid3_get_device_status(value, device); 1121 1122 } else { 1123 return get_u32(value, cap); 1124 } 1125} 1126 1127/* 1128 * Rfkill devices 1129 */ 1130static void acer_rfkill_update(struct work_struct *ignored); 1131static DECLARE_DELAYED_WORK(acer_rfkill_work, acer_rfkill_update); 1132static void acer_rfkill_update(struct work_struct *ignored) 1133{ 1134 u32 state; 1135 acpi_status status; 1136 1137 status = get_u32(&state, ACER_CAP_WIRELESS); 1138 if (ACPI_SUCCESS(status)) 1139 rfkill_set_sw_state(wireless_rfkill, !state); 1140 1141 if (has_cap(ACER_CAP_BLUETOOTH)) { 1142 status = get_u32(&state, ACER_CAP_BLUETOOTH); 1143 if (ACPI_SUCCESS(status)) 1144 rfkill_set_sw_state(bluetooth_rfkill, !state); 1145 } 1146 1147 if (has_cap(ACER_CAP_THREEG) && wmi_has_guid(WMID_GUID3)) { 1148 status = wmid3_get_device_status(&state, 1149 ACER_WMID3_GDS_THREEG); 1150 if (ACPI_SUCCESS(status)) 1151 rfkill_set_sw_state(threeg_rfkill, !state); 1152 } 1153 1154 schedule_delayed_work(&acer_rfkill_work, round_jiffies_relative(HZ)); 1155} 1156 1157static int acer_rfkill_set(void *data, bool blocked) 1158{ 1159 acpi_status status; 1160 u32 cap = (unsigned long)data; 1161 1162 if (rfkill_inited) { 1163 status = set_u32(!blocked, cap); 1164 if (ACPI_FAILURE(status)) 1165 return -ENODEV; 1166 } 1167 1168 return 0; 1169} 1170 1171static const struct rfkill_ops acer_rfkill_ops = { 1172 .set_block = acer_rfkill_set, 1173}; 1174 1175static struct rfkill *acer_rfkill_register(struct device *dev, 1176 enum rfkill_type type, 1177 char *name, u32 cap) 1178{ 1179 int err; 1180 struct rfkill *rfkill_dev; 1181 u32 state; 1182 acpi_status status; 1183 1184 rfkill_dev = rfkill_alloc(name, dev, type, 1185 &acer_rfkill_ops, 1186 (void *)(unsigned long)cap); 1187 if (!rfkill_dev) 1188 return ERR_PTR(-ENOMEM); 1189 1190 status = get_device_status(&state, cap); 1191 1192 err = rfkill_register(rfkill_dev); 1193 if (err) { 1194 rfkill_destroy(rfkill_dev); 1195 return ERR_PTR(err); 1196 } 1197 1198 if (ACPI_SUCCESS(status)) 1199 rfkill_set_sw_state(rfkill_dev, !state); 1200 1201 return rfkill_dev; 1202} 1203 1204static int acer_rfkill_init(struct device *dev) 1205{ 1206 wireless_rfkill = acer_rfkill_register(dev, RFKILL_TYPE_WLAN, 1207 "acer-wireless", ACER_CAP_WIRELESS); 1208 if (IS_ERR(wireless_rfkill)) 1209 return PTR_ERR(wireless_rfkill); 1210 1211 if (has_cap(ACER_CAP_BLUETOOTH)) { 1212 bluetooth_rfkill = acer_rfkill_register(dev, 1213 RFKILL_TYPE_BLUETOOTH, "acer-bluetooth", 1214 ACER_CAP_BLUETOOTH); 1215 if (IS_ERR(bluetooth_rfkill)) { 1216 rfkill_unregister(wireless_rfkill); 1217 rfkill_destroy(wireless_rfkill); 1218 return PTR_ERR(bluetooth_rfkill); 1219 } 1220 } 1221 1222 if (has_cap(ACER_CAP_THREEG)) { 1223 threeg_rfkill = acer_rfkill_register(dev, 1224 RFKILL_TYPE_WWAN, "acer-threeg", 1225 ACER_CAP_THREEG); 1226 if (IS_ERR(threeg_rfkill)) { 1227 rfkill_unregister(wireless_rfkill); 1228 rfkill_destroy(wireless_rfkill); 1229 rfkill_unregister(bluetooth_rfkill); 1230 rfkill_destroy(bluetooth_rfkill); 1231 return PTR_ERR(threeg_rfkill); 1232 } 1233 } 1234 1235 rfkill_inited = true; 1236 1237 if (ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID)) 1238 schedule_delayed_work(&acer_rfkill_work, 1239 round_jiffies_relative(HZ)); 1240 1241 return 0; 1242} 1243 1244static void acer_rfkill_exit(void) 1245{ 1246 if (ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID)) 1247 cancel_delayed_work_sync(&acer_rfkill_work); 1248 1249 rfkill_unregister(wireless_rfkill); 1250 rfkill_destroy(wireless_rfkill); 1251 1252 if (has_cap(ACER_CAP_BLUETOOTH)) { 1253 rfkill_unregister(bluetooth_rfkill); 1254 rfkill_destroy(bluetooth_rfkill); 1255 } 1256 1257 if (has_cap(ACER_CAP_THREEG)) { 1258 rfkill_unregister(threeg_rfkill); 1259 rfkill_destroy(threeg_rfkill); 1260 } 1261 return; 1262} 1263 1264/* 1265 * sysfs interface 1266 */ 1267static ssize_t show_bool_threeg(struct device *dev, 1268 struct device_attribute *attr, char *buf) 1269{ 1270 u32 result; \ 1271 acpi_status status; 1272 if (wmi_has_guid(WMID_GUID3)) 1273 status = wmid3_get_device_status(&result, 1274 ACER_WMID3_GDS_THREEG); 1275 else 1276 status = get_u32(&result, ACER_CAP_THREEG); 1277 if (ACPI_SUCCESS(status)) 1278 return sprintf(buf, "%u\n", result); 1279 return sprintf(buf, "Read error\n"); 1280} 1281 1282static ssize_t set_bool_threeg(struct device *dev, 1283 struct device_attribute *attr, const char *buf, size_t count) 1284{ 1285 u32 tmp = simple_strtoul(buf, NULL, 10); 1286 acpi_status status = set_u32(tmp, ACER_CAP_THREEG); 1287 if (ACPI_FAILURE(status)) 1288 return -EINVAL; 1289 return count; 1290} 1291static DEVICE_ATTR(threeg, S_IRUGO | S_IWUSR, show_bool_threeg, 1292 set_bool_threeg); 1293 1294static ssize_t show_interface(struct device *dev, struct device_attribute *attr, 1295 char *buf) 1296{ 1297 switch (interface->type) { 1298 case ACER_AMW0: 1299 return sprintf(buf, "AMW0\n"); 1300 case ACER_AMW0_V2: 1301 return sprintf(buf, "AMW0 v2\n"); 1302 case ACER_WMID: 1303 return sprintf(buf, "WMID\n"); 1304 default: 1305 return sprintf(buf, "Error!\n"); 1306 } 1307} 1308 1309static DEVICE_ATTR(interface, S_IRUGO, show_interface, NULL); 1310 1311static void acer_wmi_notify(u32 value, void *context) 1312{ 1313 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; 1314 union acpi_object *obj; 1315 struct event_return_value return_value; 1316 acpi_status status; 1317 1318 status = wmi_get_event_data(value, &response); 1319 if (status != AE_OK) { 1320 pr_warning("bad event status 0x%x\n", status); 1321 return; 1322 } 1323 1324 obj = (union acpi_object *)response.pointer; 1325 1326 if (!obj) 1327 return; 1328 if (obj->type != ACPI_TYPE_BUFFER) { 1329 pr_warning("Unknown response received %d\n", obj->type); 1330 kfree(obj); 1331 return; 1332 } 1333 if (obj->buffer.length != 8) { 1334 pr_warning("Unknown buffer length %d\n", obj->buffer.length); 1335 kfree(obj); 1336 return; 1337 } 1338 1339 return_value = *((struct event_return_value *)obj->buffer.pointer); 1340 kfree(obj); 1341 1342 switch (return_value.function) { 1343 case WMID_HOTKEY_EVENT: 1344 if (return_value.device_state) { 1345 u16 device_state = return_value.device_state; 1346 pr_debug("deivces states: 0x%x\n", device_state); 1347 if (has_cap(ACER_CAP_WIRELESS)) 1348 rfkill_set_sw_state(wireless_rfkill, 1349 !(device_state & ACER_WMID3_GDS_WIRELESS)); 1350 if (has_cap(ACER_CAP_BLUETOOTH)) 1351 rfkill_set_sw_state(bluetooth_rfkill, 1352 !(device_state & ACER_WMID3_GDS_BLUETOOTH)); 1353 if (has_cap(ACER_CAP_THREEG)) 1354 rfkill_set_sw_state(threeg_rfkill, 1355 !(device_state & ACER_WMID3_GDS_THREEG)); 1356 } 1357 if (!sparse_keymap_report_event(acer_wmi_input_dev, 1358 return_value.key_num, 1, true)) 1359 pr_warning("Unknown key number - 0x%x\n", 1360 return_value.key_num); 1361 break; 1362 default: 1363 pr_warning("Unknown function number - %d - %d\n", 1364 return_value.function, return_value.key_num); 1365 break; 1366 } 1367} 1368 1369static acpi_status 1370wmid3_set_lm_mode(struct lm_input_params *params, 1371 struct lm_return_value *return_value) 1372{ 1373 acpi_status status; 1374 union acpi_object *obj; 1375 1376 struct acpi_buffer input = { sizeof(struct lm_input_params), params }; 1377 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; 1378 1379 status = wmi_evaluate_method(WMID_GUID3, 0, 0x1, &input, &output); 1380 if (ACPI_FAILURE(status)) 1381 return status; 1382 1383 obj = output.pointer; 1384 1385 if (!obj) 1386 return AE_ERROR; 1387 else if (obj->type != ACPI_TYPE_BUFFER) { 1388 kfree(obj); 1389 return AE_ERROR; 1390 } 1391 if (obj->buffer.length != 4) { 1392 pr_warning("Unknown buffer length %d\n", obj->buffer.length); 1393 kfree(obj); 1394 return AE_ERROR; 1395 } 1396 1397 *return_value = *((struct lm_return_value *)obj->buffer.pointer); 1398 kfree(obj); 1399 1400 return status; 1401} 1402 1403static int acer_wmi_enable_ec_raw(void) 1404{ 1405 struct lm_return_value return_value; 1406 acpi_status status; 1407 struct lm_input_params params = { 1408 .function_num = 0x1, 1409 .commun_devices = 0xFFFF, 1410 .devices = 0xFFFF, 1411 .lm_status = 0x00, /* Launch Manager Deactive */ 1412 }; 1413 1414 status = wmid3_set_lm_mode(¶ms, &return_value); 1415 1416 if (return_value.error_code || return_value.ec_return_value) 1417 pr_warning("Enabling EC raw mode failed: " 1418 "0x%x - 0x%x\n", return_value.error_code, 1419 return_value.ec_return_value); 1420 else 1421 pr_info("Enabled EC raw mode"); 1422 1423 return status; 1424} 1425 1426static int acer_wmi_enable_lm(void) 1427{ 1428 struct lm_return_value return_value; 1429 acpi_status status; 1430 struct lm_input_params params = { 1431 .function_num = 0x1, 1432 .commun_devices = 0xFFFF, 1433 .devices = 0xFFFF, 1434 .lm_status = 0x01, /* Launch Manager Active */ 1435 }; 1436 1437 status = wmid3_set_lm_mode(¶ms, &return_value); 1438 1439 if (return_value.error_code || return_value.ec_return_value) 1440 pr_warning("Enabling Launch Manager failed: " 1441 "0x%x - 0x%x\n", return_value.error_code, 1442 return_value.ec_return_value); 1443 1444 return status; 1445} 1446 1447static int __init acer_wmi_input_setup(void) 1448{ 1449 acpi_status status; 1450 int err; 1451 1452 acer_wmi_input_dev = input_allocate_device(); 1453 if (!acer_wmi_input_dev) 1454 return -ENOMEM; 1455 1456 acer_wmi_input_dev->name = "Acer WMI hotkeys"; 1457 acer_wmi_input_dev->phys = "wmi/input0"; 1458 acer_wmi_input_dev->id.bustype = BUS_HOST; 1459 1460 err = sparse_keymap_setup(acer_wmi_input_dev, acer_wmi_keymap, NULL); 1461 if (err) 1462 goto err_free_dev; 1463 1464 status = wmi_install_notify_handler(ACERWMID_EVENT_GUID, 1465 acer_wmi_notify, NULL); 1466 if (ACPI_FAILURE(status)) { 1467 err = -EIO; 1468 goto err_free_keymap; 1469 } 1470 1471 err = input_register_device(acer_wmi_input_dev); 1472 if (err) 1473 goto err_uninstall_notifier; 1474 1475 return 0; 1476 1477err_uninstall_notifier: 1478 wmi_remove_notify_handler(ACERWMID_EVENT_GUID); 1479err_free_keymap: 1480 sparse_keymap_free(acer_wmi_input_dev); 1481err_free_dev: 1482 input_free_device(acer_wmi_input_dev); 1483 return err; 1484} 1485 1486static void acer_wmi_input_destroy(void) 1487{ 1488 wmi_remove_notify_handler(ACERWMID_EVENT_GUID); 1489 sparse_keymap_free(acer_wmi_input_dev); 1490 input_unregister_device(acer_wmi_input_dev); 1491} 1492 1493/* 1494 * debugfs functions 1495 */ 1496static u32 get_wmid_devices(void) 1497{ 1498 struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL}; 1499 union acpi_object *obj; 1500 acpi_status status; 1501 u32 devices = 0; 1502 1503 status = wmi_query_block(WMID_GUID2, 1, &out); 1504 if (ACPI_FAILURE(status)) 1505 return 0; 1506 1507 obj = (union acpi_object *) out.pointer; 1508 if (obj && obj->type == ACPI_TYPE_BUFFER && 1509 obj->buffer.length == sizeof(u32)) { 1510 devices = *((u32 *) obj->buffer.pointer); 1511 } 1512 1513 kfree(out.pointer); 1514 return devices; 1515} 1516 1517/* 1518 * Platform device 1519 */ 1520static int __devinit acer_platform_probe(struct platform_device *device) 1521{ 1522 int err; 1523 1524 if (has_cap(ACER_CAP_MAILLED)) { 1525 err = acer_led_init(&device->dev); 1526 if (err) 1527 goto error_mailled; 1528 } 1529 1530 if (has_cap(ACER_CAP_BRIGHTNESS)) { 1531 err = acer_backlight_init(&device->dev); 1532 if (err) 1533 goto error_brightness; 1534 } 1535 1536 err = acer_rfkill_init(&device->dev); 1537 if (err) 1538 goto error_rfkill; 1539 1540 return err; 1541 1542error_rfkill: 1543 if (has_cap(ACER_CAP_BRIGHTNESS)) 1544 acer_backlight_exit(); 1545error_brightness: 1546 if (has_cap(ACER_CAP_MAILLED)) 1547 acer_led_exit(); 1548error_mailled: 1549 return err; 1550} 1551 1552static int acer_platform_remove(struct platform_device *device) 1553{ 1554 if (has_cap(ACER_CAP_MAILLED)) 1555 acer_led_exit(); 1556 if (has_cap(ACER_CAP_BRIGHTNESS)) 1557 acer_backlight_exit(); 1558 1559 acer_rfkill_exit(); 1560 return 0; 1561} 1562 1563static int acer_platform_suspend(struct platform_device *dev, 1564pm_message_t state) 1565{ 1566 u32 value; 1567 struct acer_data *data = &interface->data; 1568 1569 if (!data) 1570 return -ENOMEM; 1571 1572 if (has_cap(ACER_CAP_MAILLED)) { 1573 get_u32(&value, ACER_CAP_MAILLED); 1574 set_u32(LED_OFF, ACER_CAP_MAILLED); 1575 data->mailled = value; 1576 } 1577 1578 if (has_cap(ACER_CAP_BRIGHTNESS)) { 1579 get_u32(&value, ACER_CAP_BRIGHTNESS); 1580 data->brightness = value; 1581 } 1582 1583 return 0; 1584} 1585 1586static int acer_platform_resume(struct platform_device *device) 1587{ 1588 struct acer_data *data = &interface->data; 1589 1590 if (!data) 1591 return -ENOMEM; 1592 1593 if (has_cap(ACER_CAP_MAILLED)) 1594 set_u32(data->mailled, ACER_CAP_MAILLED); 1595 1596 if (has_cap(ACER_CAP_BRIGHTNESS)) 1597 set_u32(data->brightness, ACER_CAP_BRIGHTNESS); 1598 1599 return 0; 1600} 1601 1602static void acer_platform_shutdown(struct platform_device *device) 1603{ 1604 struct acer_data *data = &interface->data; 1605 1606 if (!data) 1607 return; 1608 1609 if (has_cap(ACER_CAP_MAILLED)) 1610 set_u32(LED_OFF, ACER_CAP_MAILLED); 1611} 1612 1613static struct platform_driver acer_platform_driver = { 1614 .driver = { 1615 .name = "acer-wmi", 1616 .owner = THIS_MODULE, 1617 }, 1618 .probe = acer_platform_probe, 1619 .remove = acer_platform_remove, 1620 .suspend = acer_platform_suspend, 1621 .resume = acer_platform_resume, 1622 .shutdown = acer_platform_shutdown, 1623}; 1624 1625static struct platform_device *acer_platform_device; 1626 1627static int remove_sysfs(struct platform_device *device) 1628{ 1629 if (has_cap(ACER_CAP_THREEG)) 1630 device_remove_file(&device->dev, &dev_attr_threeg); 1631 1632 device_remove_file(&device->dev, &dev_attr_interface); 1633 1634 return 0; 1635} 1636 1637static int create_sysfs(void) 1638{ 1639 int retval = -ENOMEM; 1640 1641 if (has_cap(ACER_CAP_THREEG)) { 1642 retval = device_create_file(&acer_platform_device->dev, 1643 &dev_attr_threeg); 1644 if (retval) 1645 goto error_sysfs; 1646 } 1647 1648 retval = device_create_file(&acer_platform_device->dev, 1649 &dev_attr_interface); 1650 if (retval) 1651 goto error_sysfs; 1652 1653 return 0; 1654 1655error_sysfs: 1656 remove_sysfs(acer_platform_device); 1657 return retval; 1658} 1659 1660static void remove_debugfs(void) 1661{ 1662 debugfs_remove(interface->debug.devices); 1663 debugfs_remove(interface->debug.root); 1664} 1665 1666static int create_debugfs(void) 1667{ 1668 interface->debug.root = debugfs_create_dir("acer-wmi", NULL); 1669 if (!interface->debug.root) { 1670 pr_err("Failed to create debugfs directory"); 1671 return -ENOMEM; 1672 } 1673 1674 interface->debug.devices = debugfs_create_u32("devices", S_IRUGO, 1675 interface->debug.root, 1676 &interface->debug.wmid_devices); 1677 if (!interface->debug.devices) 1678 goto error_debugfs; 1679 1680 return 0; 1681 1682error_debugfs: 1683 remove_debugfs(); 1684 return -ENOMEM; 1685} 1686 1687static int __init acer_wmi_init(void) 1688{ 1689 int err; 1690 1691 pr_info("Acer Laptop ACPI-WMI Extras\n"); 1692 1693 if (dmi_check_system(acer_blacklist)) { 1694 pr_info("Blacklisted hardware detected - not loading\n"); 1695 return -ENODEV; 1696 } 1697 1698 find_quirks(); 1699 1700 /* 1701 * Detect which ACPI-WMI interface we're using. 1702 */ 1703 if (wmi_has_guid(AMW0_GUID1) && wmi_has_guid(WMID_GUID1)) 1704 interface = &AMW0_V2_interface; 1705 1706 if (!wmi_has_guid(AMW0_GUID1) && wmi_has_guid(WMID_GUID1)) 1707 interface = &wmid_interface; 1708 1709 if (wmi_has_guid(WMID_GUID2) && interface) { 1710 if (ACPI_FAILURE(WMID_set_capabilities())) { 1711 pr_err("Unable to detect available WMID devices\n"); 1712 return -ENODEV; 1713 } 1714 } else if (!wmi_has_guid(WMID_GUID2) && interface) { 1715 pr_err("No WMID device detection method found\n"); 1716 return -ENODEV; 1717 } 1718 1719 if (wmi_has_guid(AMW0_GUID1) && !wmi_has_guid(WMID_GUID1)) { 1720 interface = &AMW0_interface; 1721 1722 if (ACPI_FAILURE(AMW0_set_capabilities())) { 1723 pr_err("Unable to detect available AMW0 devices\n"); 1724 return -ENODEV; 1725 } 1726 } 1727 1728 if (wmi_has_guid(AMW0_GUID1)) 1729 AMW0_find_mailled(); 1730 1731 if (!interface) { 1732 pr_err("No or unsupported WMI interface, unable to load\n"); 1733 return -ENODEV; 1734 } 1735 1736 set_quirks(); 1737 1738 if (acpi_video_backlight_support() && has_cap(ACER_CAP_BRIGHTNESS)) { 1739 interface->capability &= ~ACER_CAP_BRIGHTNESS; 1740 pr_info("Brightness must be controlled by " 1741 "generic video driver\n"); 1742 } 1743 1744 if (wmi_has_guid(WMID_GUID3)) { 1745 if (ec_raw_mode) { 1746 if (ACPI_FAILURE(acer_wmi_enable_ec_raw())) { 1747 pr_err("Cannot enable EC raw mode\n"); 1748 return -ENODEV; 1749 } 1750 } else if (ACPI_FAILURE(acer_wmi_enable_lm())) { 1751 pr_err("Cannot enable Launch Manager mode\n"); 1752 return -ENODEV; 1753 } 1754 } else if (ec_raw_mode) { 1755 pr_info("No WMID EC raw mode enable method\n"); 1756 } 1757 1758 if (wmi_has_guid(ACERWMID_EVENT_GUID)) { 1759 err = acer_wmi_input_setup(); 1760 if (err) 1761 return err; 1762 } 1763 1764 err = platform_driver_register(&acer_platform_driver); 1765 if (err) { 1766 pr_err("Unable to register platform driver.\n"); 1767 goto error_platform_register; 1768 } 1769 1770 acer_platform_device = platform_device_alloc("acer-wmi", -1); 1771 if (!acer_platform_device) { 1772 err = -ENOMEM; 1773 goto error_device_alloc; 1774 } 1775 1776 err = platform_device_add(acer_platform_device); 1777 if (err) 1778 goto error_device_add; 1779 1780 err = create_sysfs(); 1781 if (err) 1782 goto error_create_sys; 1783 1784 if (wmi_has_guid(WMID_GUID2)) { 1785 interface->debug.wmid_devices = get_wmid_devices(); 1786 err = create_debugfs(); 1787 if (err) 1788 goto error_create_debugfs; 1789 } 1790 1791 /* Override any initial settings with values from the commandline */ 1792 acer_commandline_init(); 1793 1794 return 0; 1795 1796error_create_debugfs: 1797 remove_sysfs(acer_platform_device); 1798error_create_sys: 1799 platform_device_del(acer_platform_device); 1800error_device_add: 1801 platform_device_put(acer_platform_device); 1802error_device_alloc: 1803 platform_driver_unregister(&acer_platform_driver); 1804error_platform_register: 1805 if (wmi_has_guid(ACERWMID_EVENT_GUID)) 1806 acer_wmi_input_destroy(); 1807 1808 return err; 1809} 1810 1811static void __exit acer_wmi_exit(void) 1812{ 1813 if (wmi_has_guid(ACERWMID_EVENT_GUID)) 1814 acer_wmi_input_destroy(); 1815 1816 remove_sysfs(acer_platform_device); 1817 remove_debugfs(); 1818 platform_device_unregister(acer_platform_device); 1819 platform_driver_unregister(&acer_platform_driver); 1820 1821 pr_info("Acer Laptop WMI Extras unloaded\n"); 1822 return; 1823} 1824 1825module_init(acer_wmi_init); 1826module_exit(acer_wmi_exit); 1827