linux/drivers/input/misc/soc_button_array.c

// 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();