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