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