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