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