// SPDX-License-Identifier: GPL-2.0-only /* * Supports for the button array on SoC tablets originally running * Windows 8. * * (C) Copyright 2014 Intel Corporation */ #include <linux/module.h> #include <linux/input.h> #include <linux/init.h> #include <linux/irq.h> #include <linux/kernel.h> #include <linux/acpi.h> #include <linux/dmi.h> #include <linux/gpio/consumer.h> #include <linux/gpio_keys.h> #include <linux/gpio.h> #include <linux/platform_device.h> static bool use_low_level_irq; module_param(use_low_level_irq, bool, 0444); MODULE_PARM_DESC(…) …; struct soc_button_info { … }; struct soc_device_data { … }; /* * Some of the buttons like volume up/down are auto repeat, while others * are not. To support both, we register two platform devices, and put * buttons into them based on whether the key should be auto repeat. */ #define BUTTON_TYPES … struct soc_button_data { … }; /* * Some 2-in-1s which use the soc_button_array driver have this ugly issue in * their DSDT where the _LID method modifies the irq-type settings of the GPIOs * used for the power and home buttons. The intend of this AML code is to * disable these buttons when the lid is closed. * The AML does this by directly poking the GPIO controllers registers. This is * problematic because when re-enabling the irq, which happens whenever _LID * gets called with the lid open (e.g. on boot and on resume), it sets the * irq-type to IRQ_TYPE_LEVEL_LOW. Where as the gpio-keys driver programs the * type to, and expects it to be, IRQ_TYPE_EDGE_BOTH. * To work around this we don't set gpio_keys_button.gpio on these 2-in-1s, * instead we get the irq for the GPIO ourselves, configure it as * IRQ_TYPE_LEVEL_LOW (to match how the _LID AML code configures it) and pass * the irq in gpio_keys_button.irq. Below is a list of affected devices. */ static const struct dmi_system_id dmi_use_low_level_irq[] = …; /* * Some devices have a wrong entry which points to a GPIO which is * required in another driver, so this driver must not claim it. */ static const struct dmi_system_id dmi_invalid_acpi_index[] = …; /* * Get the Nth GPIO number from the ACPI object. */ static int soc_button_lookup_gpio(struct device *dev, int acpi_index, int *gpio_ret, int *irq_ret) { … } static struct platform_device * soc_button_device_create(struct platform_device *pdev, const struct soc_button_info *button_info, bool autorepeat) { … } static int soc_button_get_acpi_object_int(const union acpi_object *obj) { … } /* Parse a single ACPI0011 _DSD button descriptor */ static int soc_button_parse_btn_desc(struct device *dev, const union acpi_object *desc, int collection_uid, struct soc_button_info *info) { … } /* ACPI0011 _DSD btns descriptors UUID: fa6bd625-9ce8-470d-a2c7-b3ca36c4282e */ static const u8 btns_desc_uuid[16] = …; /* Parse ACPI0011 _DSD button descriptors */ static struct soc_button_info *soc_button_get_button_info(struct device *dev) { … } static void soc_button_remove(struct platform_device *pdev) { … } static int soc_button_probe(struct platform_device *pdev) { … } /* * Definition of buttons on the tablet. The ACPI index of each button * is defined in section 2.8.7.2 of "Windows ACPI Design Guide for SoC * Platforms" */ static const struct soc_button_info soc_button_PNP0C40[] = …; static const struct soc_device_data soc_device_PNP0C40 = …; static const struct soc_button_info soc_button_INT33D3[] = …; static const struct soc_device_data soc_device_INT33D3 = …; /* * Button info for Microsoft Surface 3 (non pro), this is indentical to * the PNP0C40 info except that the home button is active-high. * * The Surface 3 Pro also has a MSHW0028 ACPI device, but that uses a custom * version of the drivers/platform/x86/intel/hid.c 5 button array ACPI API * instead. A check() callback is not necessary though as the Surface 3 Pro * MSHW0028 ACPI device's resource table does not contain any GPIOs. */ static const struct soc_button_info soc_button_MSHW0028[] = …; static const struct soc_device_data soc_device_MSHW0028 = …; /* * Special device check for Surface Book 2 and Surface Pro (2017). * Both, the Surface Pro 4 (surfacepro3_button.c) and the above mentioned * devices use MSHW0040 for power and volume buttons, however the way they * have to be addressed differs. Make sure that we only load this drivers * for the correct devices by checking the OEM Platform Revision provided by * the _DSM method. */ #define MSHW0040_DSM_REVISION … #define MSHW0040_DSM_GET_OMPR … static const guid_t MSHW0040_DSM_UUID = …; static int soc_device_check_MSHW0040(struct device *dev) { … } /* * Button infos for Microsoft Surface Book 2 and Surface Pro (2017). * Obtained from DSDT/testing. */ static const struct soc_button_info soc_button_MSHW0040[] = …; static const struct soc_device_data soc_device_MSHW0040 = …; static const struct acpi_device_id soc_button_acpi_match[] = …; MODULE_DEVICE_TABLE(acpi, soc_button_acpi_match); static struct platform_driver soc_button_driver = …; module_platform_driver(…) …; MODULE_DESCRIPTION(…) …; MODULE_LICENSE(…) …;