linux/drivers/input/misc/soc_button_array.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Supports for the button array on SoC tablets originally running
   4 * Windows 8.
   5 *
   6 * (C) Copyright 2014 Intel Corporation
   7 */
   8
   9#include <linux/module.h>
  10#include <linux/input.h>
  11#include <linux/init.h>
  12#include <linux/irq.h>
  13#include <linux/kernel.h>
  14#include <linux/acpi.h>
  15#include <linux/dmi.h>
  16#include <linux/gpio/consumer.h>
  17#include <linux/gpio_keys.h>
  18#include <linux/gpio.h>
  19#include <linux/platform_device.h>
  20
  21struct soc_button_info {
  22        const char *name;
  23        int acpi_index;
  24        unsigned int event_type;
  25        unsigned int event_code;
  26        bool autorepeat;
  27        bool wakeup;
  28        bool active_low;
  29};
  30
  31struct soc_device_data {
  32        const struct soc_button_info *button_info;
  33        int (*check)(struct device *dev);
  34};
  35
  36/*
  37 * Some of the buttons like volume up/down are auto repeat, while others
  38 * are not. To support both, we register two platform devices, and put
  39 * buttons into them based on whether the key should be auto repeat.
  40 */
  41#define BUTTON_TYPES    2
  42
  43struct soc_button_data {
  44        struct platform_device *children[BUTTON_TYPES];
  45};
  46
  47/*
  48 * Some 2-in-1s which use the soc_button_array driver have this ugly issue in
  49 * their DSDT where the _LID method modifies the irq-type settings of the GPIOs
  50 * used for the power and home buttons. The intend of this AML code is to
  51 * disable these buttons when the lid is closed.
  52 * The AML does this by directly poking the GPIO controllers registers. This is
  53 * problematic because when re-enabling the irq, which happens whenever _LID
  54 * gets called with the lid open (e.g. on boot and on resume), it sets the
  55 * irq-type to IRQ_TYPE_LEVEL_LOW. Where as the gpio-keys driver programs the
  56 * type to, and expects it to be, IRQ_TYPE_EDGE_BOTH.
  57 * To work around this we don't set gpio_keys_button.gpio on these 2-in-1s,
  58 * instead we get the irq for the GPIO ourselves, configure it as
  59 * IRQ_TYPE_LEVEL_LOW (to match how the _LID AML code configures it) and pass
  60 * the irq in gpio_keys_button.irq. Below is a list of affected devices.
  61 */
  62static const struct dmi_system_id dmi_use_low_level_irq[] = {
  63        {
  64                /*
  65                 * Acer Switch 10 SW5-012. _LID method messes with home- and
  66                 * power-button GPIO IRQ settings. When (re-)enabling the irq
  67                 * it ors in its own flags without clearing the previous set
  68                 * ones, leading to an irq-type of IRQ_TYPE_LEVEL_LOW |
  69                 * IRQ_TYPE_LEVEL_HIGH causing a continuous interrupt storm.
  70                 */
  71                .matches = {
  72                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
  73                        DMI_MATCH(DMI_PRODUCT_NAME, "Aspire SW5-012"),
  74                },
  75        },
  76        {
  77                /*
  78                 * Acer One S1003. _LID method messes with power-button GPIO
  79                 * IRQ settings, leading to a non working power-button.
  80                 */
  81                .matches = {
  82                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
  83                        DMI_MATCH(DMI_PRODUCT_NAME, "One S1003"),
  84                },
  85        },
  86        {
  87                /*
  88                 * Lenovo Yoga Tab2 1051L, something messes with the home-button
  89                 * IRQ settings, leading to a non working home-button.
  90                 */
  91                .matches = {
  92                        DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
  93                        DMI_MATCH(DMI_PRODUCT_NAME, "60073"),
  94                        DMI_MATCH(DMI_PRODUCT_VERSION, "1051L"),
  95                },
  96        },
  97        {} /* Terminating entry */
  98};
  99
 100/*
 101 * Get the Nth GPIO number from the ACPI object.
 102 */
 103static int soc_button_lookup_gpio(struct device *dev, int acpi_index,
 104                                  int *gpio_ret, int *irq_ret)
 105{
 106        struct gpio_desc *desc;
 107
 108        desc = gpiod_get_index(dev, NULL, acpi_index, GPIOD_ASIS);
 109        if (IS_ERR(desc))
 110                return PTR_ERR(desc);
 111
 112        *gpio_ret = desc_to_gpio(desc);
 113        *irq_ret = gpiod_to_irq(desc);
 114
 115        gpiod_put(desc);
 116
 117        return 0;
 118}
 119
 120static struct platform_device *
 121soc_button_device_create(struct platform_device *pdev,
 122                         const struct soc_button_info *button_info,
 123                         bool autorepeat)
 124{
 125        const struct soc_button_info *info;
 126        struct platform_device *pd;
 127        struct gpio_keys_button *gpio_keys;
 128        struct gpio_keys_platform_data *gpio_keys_pdata;
 129        int error, gpio, irq;
 130        int n_buttons = 0;
 131
 132        for (info = button_info; info->name; info++)
 133                if (info->autorepeat == autorepeat)
 134                        n_buttons++;
 135
 136        gpio_keys_pdata = devm_kzalloc(&pdev->dev,
 137                                       sizeof(*gpio_keys_pdata) +
 138                                        sizeof(*gpio_keys) * n_buttons,
 139                                       GFP_KERNEL);
 140        if (!gpio_keys_pdata)
 141                return ERR_PTR(-ENOMEM);
 142
 143        gpio_keys = (void *)(gpio_keys_pdata + 1);
 144        n_buttons = 0;
 145
 146        for (info = button_info; info->name; info++) {
 147                if (info->autorepeat != autorepeat)
 148                        continue;
 149
 150                error = soc_button_lookup_gpio(&pdev->dev, info->acpi_index, &gpio, &irq);
 151                if (error || irq < 0) {
 152                        /*
 153                         * Skip GPIO if not present. Note we deliberately
 154                         * ignore -EPROBE_DEFER errors here. On some devices
 155                         * Intel is using so called virtual GPIOs which are not
 156                         * GPIOs at all but some way for AML code to check some
 157                         * random status bits without need a custom opregion.
 158                         * In some cases the resources table we parse points to
 159                         * such a virtual GPIO, since these are not real GPIOs
 160                         * we do not have a driver for these so they will never
 161                         * show up, therefore we ignore -EPROBE_DEFER.
 162                         */
 163                        continue;
 164                }
 165
 166                /* See dmi_use_low_level_irq[] comment */
 167                if (!autorepeat && dmi_check_system(dmi_use_low_level_irq)) {
 168                        irq_set_irq_type(irq, IRQ_TYPE_LEVEL_LOW);
 169                        gpio_keys[n_buttons].irq = irq;
 170                        gpio_keys[n_buttons].gpio = -ENOENT;
 171                } else {
 172                        gpio_keys[n_buttons].gpio = gpio;
 173                }
 174
 175                gpio_keys[n_buttons].type = info->event_type;
 176                gpio_keys[n_buttons].code = info->event_code;
 177                gpio_keys[n_buttons].active_low = info->active_low;
 178                gpio_keys[n_buttons].desc = info->name;
 179                gpio_keys[n_buttons].wakeup = info->wakeup;
 180                /* These devices often use cheap buttons, use 50 ms debounce */
 181                gpio_keys[n_buttons].debounce_interval = 50;
 182                n_buttons++;
 183        }
 184
 185        if (n_buttons == 0) {
 186                error = -ENODEV;
 187                goto err_free_mem;
 188        }
 189
 190        gpio_keys_pdata->buttons = gpio_keys;
 191        gpio_keys_pdata->nbuttons = n_buttons;
 192        gpio_keys_pdata->rep = autorepeat;
 193
 194        pd = platform_device_register_resndata(&pdev->dev, "gpio-keys",
 195                                               PLATFORM_DEVID_AUTO, NULL, 0,
 196                                               gpio_keys_pdata,
 197                                               sizeof(*gpio_keys_pdata));
 198        error = PTR_ERR_OR_ZERO(pd);
 199        if (error) {
 200                dev_err(&pdev->dev,
 201                        "failed registering gpio-keys: %d\n", error);
 202                goto err_free_mem;
 203        }
 204
 205        return pd;
 206
 207err_free_mem:
 208        devm_kfree(&pdev->dev, gpio_keys_pdata);
 209        return ERR_PTR(error);
 210}
 211
 212static int soc_button_get_acpi_object_int(const union acpi_object *obj)
 213{
 214        if (obj->type != ACPI_TYPE_INTEGER)
 215                return -1;
 216
 217        return obj->integer.value;
 218}
 219
 220/* Parse a single ACPI0011 _DSD button descriptor */
 221static int soc_button_parse_btn_desc(struct device *dev,
 222                                     const union acpi_object *desc,
 223                                     int collection_uid,
 224                                     struct soc_button_info *info)
 225{
 226        int upage, usage;
 227
 228        if (desc->type != ACPI_TYPE_PACKAGE ||
 229            desc->package.count != 5 ||
 230            /* First byte should be 1 (control) */
 231            soc_button_get_acpi_object_int(&desc->package.elements[0]) != 1 ||
 232            /* Third byte should be collection uid */
 233            soc_button_get_acpi_object_int(&desc->package.elements[2]) !=
 234                                                            collection_uid) {
 235                dev_err(dev, "Invalid ACPI Button Descriptor\n");
 236                return -ENODEV;
 237        }
 238
 239        info->event_type = EV_KEY;
 240        info->active_low = true;
 241        info->acpi_index =
 242                soc_button_get_acpi_object_int(&desc->package.elements[1]);
 243        upage = soc_button_get_acpi_object_int(&desc->package.elements[3]);
 244        usage = soc_button_get_acpi_object_int(&desc->package.elements[4]);
 245
 246        /*
 247         * The UUID: fa6bd625-9ce8-470d-a2c7-b3ca36c4282e descriptors use HID
 248         * usage page and usage codes, but otherwise the device is not HID
 249         * compliant: it uses one irq per button instead of generating HID
 250         * input reports and some buttons should generate wakeups where as
 251         * others should not, so we cannot use the HID subsystem.
 252         *
 253         * Luckily all devices only use a few usage page + usage combinations,
 254         * so we can simply check for the known combinations here.
 255         */
 256        if (upage == 0x01 && usage == 0x81) {
 257                info->name = "power";
 258                info->event_code = KEY_POWER;
 259                info->wakeup = true;
 260        } else if (upage == 0x01 && usage == 0xca) {
 261                info->name = "rotation lock switch";
 262                info->event_type = EV_SW;
 263                info->event_code = SW_ROTATE_LOCK;
 264        } else if (upage == 0x07 && usage == 0xe3) {
 265                info->name = "home";
 266                info->event_code = KEY_LEFTMETA;
 267                info->wakeup = true;
 268        } else if (upage == 0x0c && usage == 0xe9) {
 269                info->name = "volume_up";
 270                info->event_code = KEY_VOLUMEUP;
 271                info->autorepeat = true;
 272        } else if (upage == 0x0c && usage == 0xea) {
 273                info->name = "volume_down";
 274                info->event_code = KEY_VOLUMEDOWN;
 275                info->autorepeat = true;
 276        } else {
 277                dev_warn(dev, "Unknown button index %d upage %02x usage %02x, ignoring\n",
 278                         info->acpi_index, upage, usage);
 279                info->name = "unknown";
 280                info->event_code = KEY_RESERVED;
 281        }
 282
 283        return 0;
 284}
 285
 286/* ACPI0011 _DSD btns descriptors UUID: fa6bd625-9ce8-470d-a2c7-b3ca36c4282e */
 287static const u8 btns_desc_uuid[16] = {
 288        0x25, 0xd6, 0x6b, 0xfa, 0xe8, 0x9c, 0x0d, 0x47,
 289        0xa2, 0xc7, 0xb3, 0xca, 0x36, 0xc4, 0x28, 0x2e
 290};
 291
 292/* Parse ACPI0011 _DSD button descriptors */
 293static struct soc_button_info *soc_button_get_button_info(struct device *dev)
 294{
 295        struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
 296        const union acpi_object *desc, *el0, *uuid, *btns_desc = NULL;
 297        struct soc_button_info *button_info;
 298        acpi_status status;
 299        int i, btn, collection_uid = -1;
 300
 301        status = acpi_evaluate_object_typed(ACPI_HANDLE(dev), "_DSD", NULL,
 302                                            &buf, ACPI_TYPE_PACKAGE);
 303        if (ACPI_FAILURE(status)) {
 304                dev_err(dev, "ACPI _DSD object not found\n");
 305                return ERR_PTR(-ENODEV);
 306        }
 307
 308        /* Look for the Button Descriptors UUID */
 309        desc = buf.pointer;
 310        for (i = 0; (i + 1) < desc->package.count; i += 2) {
 311                uuid = &desc->package.elements[i];
 312
 313                if (uuid->type != ACPI_TYPE_BUFFER ||
 314                    uuid->buffer.length != 16 ||
 315                    desc->package.elements[i + 1].type != ACPI_TYPE_PACKAGE) {
 316                        break;
 317                }
 318
 319                if (memcmp(uuid->buffer.pointer, btns_desc_uuid, 16) == 0) {
 320                        btns_desc = &desc->package.elements[i + 1];
 321                        break;
 322                }
 323        }
 324
 325        if (!btns_desc) {
 326                dev_err(dev, "ACPI Button Descriptors not found\n");
 327                button_info = ERR_PTR(-ENODEV);
 328                goto out;
 329        }
 330
 331        /* The first package describes the collection */
 332        el0 = &btns_desc->package.elements[0];
 333        if (el0->type == ACPI_TYPE_PACKAGE &&
 334            el0->package.count == 5 &&
 335            /* First byte should be 0 (collection) */
 336            soc_button_get_acpi_object_int(&el0->package.elements[0]) == 0 &&
 337            /* Third byte should be 0 (top level collection) */
 338            soc_button_get_acpi_object_int(&el0->package.elements[2]) == 0) {
 339                collection_uid = soc_button_get_acpi_object_int(
 340                                                &el0->package.elements[1]);
 341        }
 342        if (collection_uid == -1) {
 343                dev_err(dev, "Invalid Button Collection Descriptor\n");
 344                button_info = ERR_PTR(-ENODEV);
 345                goto out;
 346        }
 347
 348        /* There are package.count - 1 buttons + 1 terminating empty entry */
 349        button_info = devm_kcalloc(dev, btns_desc->package.count,
 350                                   sizeof(*button_info), GFP_KERNEL);
 351        if (!button_info) {
 352                button_info = ERR_PTR(-ENOMEM);
 353                goto out;
 354        }
 355
 356        /* Parse the button descriptors */
 357        for (i = 1, btn = 0; i < btns_desc->package.count; i++, btn++) {
 358                if (soc_button_parse_btn_desc(dev,
 359                                              &btns_desc->package.elements[i],
 360                                              collection_uid,
 361                                              &button_info[btn])) {
 362                        button_info = ERR_PTR(-ENODEV);
 363                        goto out;
 364                }
 365        }
 366
 367out:
 368        kfree(buf.pointer);
 369        return button_info;
 370}
 371
 372static int soc_button_remove(struct platform_device *pdev)
 373{
 374        struct soc_button_data *priv = platform_get_drvdata(pdev);
 375
 376        int i;
 377
 378        for (i = 0; i < BUTTON_TYPES; i++)
 379                if (priv->children[i])
 380                        platform_device_unregister(priv->children[i]);
 381
 382        return 0;
 383}
 384
 385static int soc_button_probe(struct platform_device *pdev)
 386{
 387        struct device *dev = &pdev->dev;
 388        const struct soc_device_data *device_data;
 389        const struct soc_button_info *button_info;
 390        struct soc_button_data *priv;
 391        struct platform_device *pd;
 392        int i;
 393        int error;
 394
 395        device_data = acpi_device_get_match_data(dev);
 396        if (device_data && device_data->check) {
 397                error = device_data->check(dev);
 398                if (error)
 399                        return error;
 400        }
 401
 402        if (device_data && device_data->button_info) {
 403                button_info = device_data->button_info;
 404        } else {
 405                button_info = soc_button_get_button_info(dev);
 406                if (IS_ERR(button_info))
 407                        return PTR_ERR(button_info);
 408        }
 409
 410        error = gpiod_count(dev, NULL);
 411        if (error < 0) {
 412                dev_dbg(dev, "no GPIO attached, ignoring...\n");
 413                return -ENODEV;
 414        }
 415
 416        priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 417        if (!priv)
 418                return -ENOMEM;
 419
 420        platform_set_drvdata(pdev, priv);
 421
 422        for (i = 0; i < BUTTON_TYPES; i++) {
 423                pd = soc_button_device_create(pdev, button_info, i == 0);
 424                if (IS_ERR(pd)) {
 425                        error = PTR_ERR(pd);
 426                        if (error != -ENODEV) {
 427                                soc_button_remove(pdev);
 428                                return error;
 429                        }
 430                        continue;
 431                }
 432
 433                priv->children[i] = pd;
 434        }
 435
 436        if (!priv->children[0] && !priv->children[1])
 437                return -ENODEV;
 438
 439        if (!device_data || !device_data->button_info)
 440                devm_kfree(dev, button_info);
 441
 442        return 0;
 443}
 444
 445/*
 446 * Definition of buttons on the tablet. The ACPI index of each button
 447 * is defined in section 2.8.7.2 of "Windows ACPI Design Guide for SoC
 448 * Platforms"
 449 */
 450static const struct soc_button_info soc_button_PNP0C40[] = {
 451        { "power", 0, EV_KEY, KEY_POWER, false, true, true },
 452        { "home", 1, EV_KEY, KEY_LEFTMETA, false, true, true },
 453        { "volume_up", 2, EV_KEY, KEY_VOLUMEUP, true, false, true },
 454        { "volume_down", 3, EV_KEY, KEY_VOLUMEDOWN, true, false, true },
 455        { "rotation_lock", 4, EV_KEY, KEY_ROTATE_LOCK_TOGGLE, false, false, true },
 456        { }
 457};
 458
 459static const struct soc_device_data soc_device_PNP0C40 = {
 460        .button_info = soc_button_PNP0C40,
 461};
 462
 463static const struct soc_button_info soc_button_INT33D3[] = {
 464        { "tablet_mode", 0, EV_SW, SW_TABLET_MODE, false, false, false },
 465        { }
 466};
 467
 468static const struct soc_device_data soc_device_INT33D3 = {
 469        .button_info = soc_button_INT33D3,
 470};
 471
 472/*
 473 * Special device check for Surface Book 2 and Surface Pro (2017).
 474 * Both, the Surface Pro 4 (surfacepro3_button.c) and the above mentioned
 475 * devices use MSHW0040 for power and volume buttons, however the way they
 476 * have to be addressed differs. Make sure that we only load this drivers
 477 * for the correct devices by checking the OEM Platform Revision provided by
 478 * the _DSM method.
 479 */
 480#define MSHW0040_DSM_REVISION           0x01
 481#define MSHW0040_DSM_GET_OMPR           0x02    // get OEM Platform Revision
 482static const guid_t MSHW0040_DSM_UUID =
 483        GUID_INIT(0x6fd05c69, 0xcde3, 0x49f4, 0x95, 0xed, 0xab, 0x16, 0x65,
 484                  0x49, 0x80, 0x35);
 485
 486static int soc_device_check_MSHW0040(struct device *dev)
 487{
 488        acpi_handle handle = ACPI_HANDLE(dev);
 489        union acpi_object *result;
 490        u64 oem_platform_rev = 0;       // valid revisions are nonzero
 491
 492        // get OEM platform revision
 493        result = acpi_evaluate_dsm_typed(handle, &MSHW0040_DSM_UUID,
 494                                         MSHW0040_DSM_REVISION,
 495                                         MSHW0040_DSM_GET_OMPR, NULL,
 496                                         ACPI_TYPE_INTEGER);
 497
 498        if (result) {
 499                oem_platform_rev = result->integer.value;
 500                ACPI_FREE(result);
 501        }
 502
 503        /*
 504         * If the revision is zero here, the _DSM evaluation has failed. This
 505         * indicates that we have a Pro 4 or Book 1 and this driver should not
 506         * be used.
 507         */
 508        if (oem_platform_rev == 0)
 509                return -ENODEV;
 510
 511        dev_dbg(dev, "OEM Platform Revision %llu\n", oem_platform_rev);
 512
 513        return 0;
 514}
 515
 516/*
 517 * Button infos for Microsoft Surface Book 2 and Surface Pro (2017).
 518 * Obtained from DSDT/testing.
 519 */
 520static const struct soc_button_info soc_button_MSHW0040[] = {
 521        { "power", 0, EV_KEY, KEY_POWER, false, true, true },
 522        { "volume_up", 2, EV_KEY, KEY_VOLUMEUP, true, false, true },
 523        { "volume_down", 4, EV_KEY, KEY_VOLUMEDOWN, true, false, true },
 524        { }
 525};
 526
 527static const struct soc_device_data soc_device_MSHW0040 = {
 528        .button_info = soc_button_MSHW0040,
 529        .check = soc_device_check_MSHW0040,
 530};
 531
 532static const struct acpi_device_id soc_button_acpi_match[] = {
 533        { "PNP0C40", (unsigned long)&soc_device_PNP0C40 },
 534        { "INT33D3", (unsigned long)&soc_device_INT33D3 },
 535        { "ID9001", (unsigned long)&soc_device_INT33D3 },
 536        { "ACPI0011", 0 },
 537
 538        /* Microsoft Surface Devices (5th and 6th generation) */
 539        { "MSHW0040", (unsigned long)&soc_device_MSHW0040 },
 540
 541        { }
 542};
 543
 544MODULE_DEVICE_TABLE(acpi, soc_button_acpi_match);
 545
 546static struct platform_driver soc_button_driver = {
 547        .probe          = soc_button_probe,
 548        .remove         = soc_button_remove,
 549        .driver         = {
 550                .name = KBUILD_MODNAME,
 551                .acpi_match_table = ACPI_PTR(soc_button_acpi_match),
 552        },
 553};
 554module_platform_driver(soc_button_driver);
 555
 556MODULE_LICENSE("GPL");
 557