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