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