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