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