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