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