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