aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/misc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/misc')
-rw-r--r--drivers/input/misc/88pm80x_onkey.c1
-rw-r--r--drivers/input/misc/88pm860x_onkey.c4
-rw-r--r--drivers/input/misc/Kconfig6
-rw-r--r--drivers/input/misc/ab8500-ponkey.c8
-rw-r--r--drivers/input/misc/axp20x-pek.c25
-rw-r--r--drivers/input/misc/da9055_onkey.c5
-rw-r--r--drivers/input/misc/da9063_onkey.c7
-rw-r--r--drivers/input/misc/e3x0-button.c10
-rw-r--r--drivers/input/misc/hisi_powerkey.c8
-rw-r--r--drivers/input/misc/max8925_onkey.c8
-rw-r--r--drivers/input/misc/pm8941-pwrkey.c4
-rw-r--r--drivers/input/misc/rk805-pwrkey.c8
-rw-r--r--drivers/input/misc/soc_button_array.c127
-rw-r--r--drivers/input/misc/stpmic1_onkey.c10
-rw-r--r--drivers/input/misc/tps65218-pwrbutton.c4
-rw-r--r--drivers/input/misc/twl6040-vibra.c4
16 files changed, 128 insertions, 111 deletions
diff --git a/drivers/input/misc/88pm80x_onkey.c b/drivers/input/misc/88pm80x_onkey.c
index 45a09497f680..51c8a326fd06 100644
--- a/drivers/input/misc/88pm80x_onkey.c
+++ b/drivers/input/misc/88pm80x_onkey.c
@@ -77,7 +77,6 @@ static int pm80x_onkey_probe(struct platform_device *pdev)
info->irq = platform_get_irq(pdev, 0);
if (info->irq < 0) {
- dev_err(&pdev->dev, "No IRQ resource!\n");
err = -EINVAL;
goto out;
}
diff --git a/drivers/input/misc/88pm860x_onkey.c b/drivers/input/misc/88pm860x_onkey.c
index cc87443aa2ee..685995cad73f 100644
--- a/drivers/input/misc/88pm860x_onkey.c
+++ b/drivers/input/misc/88pm860x_onkey.c
@@ -64,10 +64,8 @@ static int pm860x_onkey_probe(struct platform_device *pdev)
int irq, ret;
irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(&pdev->dev, "No IRQ resource!\n");
+ if (irq < 0)
return -EINVAL;
- }
info = devm_kzalloc(&pdev->dev, sizeof(struct pm860x_onkey_info),
GFP_KERNEL);
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index d07c1eb15aa6..7d9ae394e597 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -813,10 +813,10 @@ config INPUT_IDEAPAD_SLIDEBAR
config INPUT_SOC_BUTTON_ARRAY
tristate "Windows-compatible SoC Button Array"
- depends on KEYBOARD_GPIO
+ depends on KEYBOARD_GPIO && ACPI
help
- Say Y here if you have a SoC-based tablet that originally
- runs Windows 8.
+ Say Y here if you have a SoC-based tablet that originally runs
+ Windows 8 or a Microsoft Surface Book 2, Pro 5, Laptop 1 or later.
To compile this driver as a module, choose M here: the
module will be called soc_button_array.
diff --git a/drivers/input/misc/ab8500-ponkey.c b/drivers/input/misc/ab8500-ponkey.c
index 12b18a8db315..ea3b8292acdd 100644
--- a/drivers/input/misc/ab8500-ponkey.c
+++ b/drivers/input/misc/ab8500-ponkey.c
@@ -55,16 +55,12 @@ static int ab8500_ponkey_probe(struct platform_device *pdev)
int error;
irq_dbf = platform_get_irq_byname(pdev, "ONKEY_DBF");
- if (irq_dbf < 0) {
- dev_err(&pdev->dev, "No IRQ for ONKEY_DBF, error=%d\n", irq_dbf);
+ if (irq_dbf < 0)
return irq_dbf;
- }
irq_dbr = platform_get_irq_byname(pdev, "ONKEY_DBR");
- if (irq_dbr < 0) {
- dev_err(&pdev->dev, "No IRQ for ONKEY_DBR, error=%d\n", irq_dbr);
+ if (irq_dbr < 0)
return irq_dbr;
- }
ponkey = devm_kzalloc(&pdev->dev, sizeof(struct ab8500_ponkey),
GFP_KERNEL);
diff --git a/drivers/input/misc/axp20x-pek.c b/drivers/input/misc/axp20x-pek.c
index debeeaeb8812..17c1cca74498 100644
--- a/drivers/input/misc/axp20x-pek.c
+++ b/drivers/input/misc/axp20x-pek.c
@@ -195,15 +195,12 @@ DEVICE_ATTR(startup, 0644, axp20x_show_attr_startup, axp20x_store_attr_startup);
DEVICE_ATTR(shutdown, 0644, axp20x_show_attr_shutdown,
axp20x_store_attr_shutdown);
-static struct attribute *axp20x_attributes[] = {
+static struct attribute *axp20x_attrs[] = {
&dev_attr_startup.attr,
&dev_attr_shutdown.attr,
NULL,
};
-
-static const struct attribute_group axp20x_attribute_group = {
- .attrs = axp20x_attributes,
-};
+ATTRIBUTE_GROUPS(axp20x);
static irqreturn_t axp20x_pek_irq(int irq, void *pwr)
{
@@ -232,20 +229,14 @@ static int axp20x_pek_probe_input_device(struct axp20x_pek *axp20x_pek,
int error;
axp20x_pek->irq_dbr = platform_get_irq_byname(pdev, "PEK_DBR");
- if (axp20x_pek->irq_dbr < 0) {
- dev_err(&pdev->dev, "No IRQ for PEK_DBR, error=%d\n",
- axp20x_pek->irq_dbr);
+ if (axp20x_pek->irq_dbr < 0)
return axp20x_pek->irq_dbr;
- }
axp20x_pek->irq_dbr = regmap_irq_get_virq(axp20x->regmap_irqc,
axp20x_pek->irq_dbr);
axp20x_pek->irq_dbf = platform_get_irq_byname(pdev, "PEK_DBF");
- if (axp20x_pek->irq_dbf < 0) {
- dev_err(&pdev->dev, "No IRQ for PEK_DBF, error=%d\n",
- axp20x_pek->irq_dbf);
+ if (axp20x_pek->irq_dbf < 0)
return axp20x_pek->irq_dbf;
- }
axp20x_pek->irq_dbf = regmap_irq_get_virq(axp20x->regmap_irqc,
axp20x_pek->irq_dbf);
@@ -356,13 +347,6 @@ static int axp20x_pek_probe(struct platform_device *pdev)
axp20x_pek->info = (struct axp20x_info *)match->driver_data;
- error = devm_device_add_group(&pdev->dev, &axp20x_attribute_group);
- if (error) {
- dev_err(&pdev->dev, "Failed to create sysfs attributes: %d\n",
- error);
- return error;
- }
-
platform_set_drvdata(pdev, axp20x_pek);
return 0;
@@ -411,6 +395,7 @@ static struct platform_driver axp20x_pek_driver = {
.driver = {
.name = "axp20x-pek",
.pm = &axp20x_pek_pm_ops,
+ .dev_groups = axp20x_groups,
},
};
module_platform_driver(axp20x_pek_driver);
diff --git a/drivers/input/misc/da9055_onkey.c b/drivers/input/misc/da9055_onkey.c
index a4ff4782e605..7a0d3a1d503c 100644
--- a/drivers/input/misc/da9055_onkey.c
+++ b/drivers/input/misc/da9055_onkey.c
@@ -76,11 +76,8 @@ static int da9055_onkey_probe(struct platform_device *pdev)
int irq, err;
irq = platform_get_irq_byname(pdev, "ONKEY");
- if (irq < 0) {
- dev_err(&pdev->dev,
- "Failed to get an IRQ for input device, %d\n", irq);
+ if (irq < 0)
return -EINVAL;
- }
onkey = devm_kzalloc(&pdev->dev, sizeof(*onkey), GFP_KERNEL);
if (!onkey) {
diff --git a/drivers/input/misc/da9063_onkey.c b/drivers/input/misc/da9063_onkey.c
index fd355cf59397..dace8577fa43 100644
--- a/drivers/input/misc/da9063_onkey.c
+++ b/drivers/input/misc/da9063_onkey.c
@@ -248,11 +248,8 @@ static int da9063_onkey_probe(struct platform_device *pdev)
}
irq = platform_get_irq_byname(pdev, "ONKEY");
- if (irq < 0) {
- error = irq;
- dev_err(&pdev->dev, "Failed to get platform IRQ: %d\n", error);
- return error;
- }
+ if (irq < 0)
+ return irq;
error = devm_request_threaded_irq(&pdev->dev, irq,
NULL, da9063_onkey_irq_handler,
diff --git a/drivers/input/misc/e3x0-button.c b/drivers/input/misc/e3x0-button.c
index 4d7217f43888..e2fde6e1553f 100644
--- a/drivers/input/misc/e3x0-button.c
+++ b/drivers/input/misc/e3x0-button.c
@@ -65,18 +65,12 @@ static int e3x0_button_probe(struct platform_device *pdev)
int error;
irq_press = platform_get_irq_byname(pdev, "press");
- if (irq_press < 0) {
- dev_err(&pdev->dev, "No IRQ for 'press', error=%d\n",
- irq_press);
+ if (irq_press < 0)
return irq_press;
- }
irq_release = platform_get_irq_byname(pdev, "release");
- if (irq_release < 0) {
- dev_err(&pdev->dev, "No IRQ for 'release', error=%d\n",
- irq_release);
+ if (irq_release < 0)
return irq_release;
- }
input = devm_input_allocate_device(&pdev->dev);
if (!input)
diff --git a/drivers/input/misc/hisi_powerkey.c b/drivers/input/misc/hisi_powerkey.c
index dee6245f38d7..d3c293a95d32 100644
--- a/drivers/input/misc/hisi_powerkey.c
+++ b/drivers/input/misc/hisi_powerkey.c
@@ -90,12 +90,8 @@ static int hi65xx_powerkey_probe(struct platform_device *pdev)
for (i = 0; i < ARRAY_SIZE(hi65xx_irq_info); i++) {
irq = platform_get_irq_byname(pdev, hi65xx_irq_info[i].name);
- if (irq < 0) {
- error = irq;
- dev_err(dev, "couldn't get irq %s: %d\n",
- hi65xx_irq_info[i].name, error);
- return error;
- }
+ if (irq < 0)
+ return irq;
error = devm_request_any_context_irq(dev, irq,
hi65xx_irq_info[i].handler,
diff --git a/drivers/input/misc/max8925_onkey.c b/drivers/input/misc/max8925_onkey.c
index 7c49b8d23894..ffab4a490c75 100644
--- a/drivers/input/misc/max8925_onkey.c
+++ b/drivers/input/misc/max8925_onkey.c
@@ -71,16 +71,12 @@ static int max8925_onkey_probe(struct platform_device *pdev)
int irq[2], error;
irq[0] = platform_get_irq(pdev, 0);
- if (irq[0] < 0) {
- dev_err(&pdev->dev, "No IRQ resource!\n");
+ if (irq[0] < 0)
return -EINVAL;
- }
irq[1] = platform_get_irq(pdev, 1);
- if (irq[1] < 0) {
- dev_err(&pdev->dev, "No IRQ resource!\n");
+ if (irq[1] < 0)
return -EINVAL;
- }
info = devm_kzalloc(&pdev->dev, sizeof(struct max8925_onkey_info),
GFP_KERNEL);
diff --git a/drivers/input/misc/pm8941-pwrkey.c b/drivers/input/misc/pm8941-pwrkey.c
index 017f81a66658..cf8104454e74 100644
--- a/drivers/input/misc/pm8941-pwrkey.c
+++ b/drivers/input/misc/pm8941-pwrkey.c
@@ -205,10 +205,8 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev)
return error;
pwrkey->irq = platform_get_irq(pdev, 0);
- if (pwrkey->irq < 0) {
- dev_err(&pdev->dev, "failed to get irq\n");
+ if (pwrkey->irq < 0)
return pwrkey->irq;
- }
error = regmap_read(pwrkey->regmap, pwrkey->baseaddr + PON_REV2,
&pwrkey->revision);
diff --git a/drivers/input/misc/rk805-pwrkey.c b/drivers/input/misc/rk805-pwrkey.c
index 4a6d4a5746e5..3fb64dbda1a2 100644
--- a/drivers/input/misc/rk805-pwrkey.c
+++ b/drivers/input/misc/rk805-pwrkey.c
@@ -53,16 +53,12 @@ static int rk805_pwrkey_probe(struct platform_device *pdev)
input_set_capability(pwr, EV_KEY, KEY_POWER);
fall_irq = platform_get_irq(pdev, 0);
- if (fall_irq < 0) {
- dev_err(&pdev->dev, "Can't get fall irq: %d\n", fall_irq);
+ if (fall_irq < 0)
return fall_irq;
- }
rise_irq = platform_get_irq(pdev, 1);
- if (rise_irq < 0) {
- dev_err(&pdev->dev, "Can't get rise irq: %d\n", rise_irq);
+ if (rise_irq < 0)
return rise_irq;
- }
err = devm_request_any_context_irq(&pwr->dev, fall_irq,
pwrkey_fall_irq,
diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c
index 5e59f8e57f8e..97e3639e99d0 100644
--- a/drivers/input/misc/soc_button_array.c
+++ b/drivers/input/misc/soc_button_array.c
@@ -25,6 +25,11 @@ struct soc_button_info {
bool wakeup;
};
+struct soc_device_data {
+ const struct soc_button_info *button_info;
+ int (*check)(struct device *dev);
+};
+
/*
* 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
@@ -87,8 +92,13 @@ soc_button_device_create(struct platform_device *pdev,
continue;
gpio = soc_button_lookup_gpio(&pdev->dev, info->acpi_index);
- if (!gpio_is_valid(gpio))
+ if (gpio < 0 && gpio != -ENOENT) {
+ error = gpio;
+ goto err_free_mem;
+ } else if (!gpio_is_valid(gpio)) {
+ /* Skip GPIO if not present */
continue;
+ }
gpio_keys[n_buttons].type = info->event_type;
gpio_keys[n_buttons].code = info->event_code;
@@ -110,25 +120,19 @@ soc_button_device_create(struct platform_device *pdev,
gpio_keys_pdata->nbuttons = n_buttons;
gpio_keys_pdata->rep = autorepeat;
- pd = platform_device_alloc("gpio-keys", PLATFORM_DEVID_AUTO);
- if (!pd) {
- error = -ENOMEM;
+ pd = platform_device_register_resndata(&pdev->dev, "gpio-keys",
+ PLATFORM_DEVID_AUTO, NULL, 0,
+ gpio_keys_pdata,
+ sizeof(*gpio_keys_pdata));
+ error = PTR_ERR_OR_ZERO(pd);
+ if (error) {
+ dev_err(&pdev->dev,
+ "failed registering gpio-keys: %d\n", error);
goto err_free_mem;
}
- error = platform_device_add_data(pd, gpio_keys_pdata,
- sizeof(*gpio_keys_pdata));
- if (error)
- goto err_free_pdev;
-
- error = platform_device_add(pd);
- if (error)
- goto err_free_pdev;
-
return pd;
-err_free_pdev:
- platform_device_put(pd);
err_free_mem:
devm_kfree(&pdev->dev, gpio_keys_pdata);
return ERR_PTR(error);
@@ -309,23 +313,26 @@ static int soc_button_remove(struct platform_device *pdev)
static int soc_button_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- const struct acpi_device_id *id;
- struct soc_button_info *button_info;
+ const struct soc_device_data *device_data;
+ const struct soc_button_info *button_info;
struct soc_button_data *priv;
struct platform_device *pd;
int i;
int error;
- id = acpi_match_device(dev->driver->acpi_match_table, dev);
- if (!id)
- return -ENODEV;
+ device_data = acpi_device_get_match_data(dev);
+ if (device_data && device_data->check) {
+ error = device_data->check(dev);
+ if (error)
+ return error;
+ }
- if (!id->driver_data) {
+ if (device_data && device_data->button_info) {
+ button_info = device_data->button_info;
+ } else {
button_info = soc_button_get_button_info(dev);
if (IS_ERR(button_info))
return PTR_ERR(button_info);
- } else {
- button_info = (struct soc_button_info *)id->driver_data;
}
error = gpiod_count(dev, NULL);
@@ -357,7 +364,7 @@ static int soc_button_probe(struct platform_device *pdev)
if (!priv->children[0] && !priv->children[1])
return -ENODEV;
- if (!id->driver_data)
+ if (!device_data || !device_data->button_info)
devm_kfree(dev, button_info);
return 0;
@@ -368,7 +375,7 @@ static int soc_button_probe(struct platform_device *pdev)
* is defined in section 2.8.7.2 of "Windows ACPI Design Guide for SoC
* Platforms"
*/
-static struct soc_button_info soc_button_PNP0C40[] = {
+static const struct soc_button_info soc_button_PNP0C40[] = {
{ "power", 0, EV_KEY, KEY_POWER, false, true },
{ "home", 1, EV_KEY, KEY_LEFTMETA, false, true },
{ "volume_up", 2, EV_KEY, KEY_VOLUMEUP, true, false },
@@ -377,9 +384,77 @@ static struct soc_button_info soc_button_PNP0C40[] = {
{ }
};
+static const struct soc_device_data soc_device_PNP0C40 = {
+ .button_info = soc_button_PNP0C40,
+};
+
+/*
+ * 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 0x01
+#define MSHW0040_DSM_GET_OMPR 0x02 // get OEM Platform Revision
+static const guid_t MSHW0040_DSM_UUID =
+ GUID_INIT(0x6fd05c69, 0xcde3, 0x49f4, 0x95, 0xed, 0xab, 0x16, 0x65,
+ 0x49, 0x80, 0x35);
+
+static int soc_device_check_MSHW0040(struct device *dev)
+{
+ acpi_handle handle = ACPI_HANDLE(dev);
+ union acpi_object *result;
+ u64 oem_platform_rev = 0; // valid revisions are nonzero
+
+ // get OEM platform revision
+ result = acpi_evaluate_dsm_typed(handle, &MSHW0040_DSM_UUID,
+ MSHW0040_DSM_REVISION,
+ MSHW0040_DSM_GET_OMPR, NULL,
+ ACPI_TYPE_INTEGER);
+
+ if (result) {
+ oem_platform_rev = result->integer.value;
+ ACPI_FREE(result);
+ }
+
+ /*
+ * If the revision is zero here, the _DSM evaluation has failed. This
+ * indicates that we have a Pro 4 or Book 1 and this driver should not
+ * be used.
+ */
+ if (oem_platform_rev == 0)
+ return -ENODEV;
+
+ dev_dbg(dev, "OEM Platform Revision %llu\n", oem_platform_rev);
+
+ return 0;
+}
+
+/*
+ * Button infos for Microsoft Surface Book 2 and Surface Pro (2017).
+ * Obtained from DSDT/testing.
+ */
+static const struct soc_button_info soc_button_MSHW0040[] = {
+ { "power", 0, EV_KEY, KEY_POWER, false, true },
+ { "volume_up", 2, EV_KEY, KEY_VOLUMEUP, true, false },
+ { "volume_down", 4, EV_KEY, KEY_VOLUMEDOWN, true, false },
+ { }
+};
+
+static const struct soc_device_data soc_device_MSHW0040 = {
+ .button_info = soc_button_MSHW0040,
+ .check = soc_device_check_MSHW0040,
+};
+
static const struct acpi_device_id soc_button_acpi_match[] = {
- { "PNP0C40", (unsigned long)soc_button_PNP0C40 },
+ { "PNP0C40", (unsigned long)&soc_device_PNP0C40 },
{ "ACPI0011", 0 },
+
+ /* Microsoft Surface Devices (5th and 6th generation) */
+ { "MSHW0040", (unsigned long)&soc_device_MSHW0040 },
+
{ }
};
diff --git a/drivers/input/misc/stpmic1_onkey.c b/drivers/input/misc/stpmic1_onkey.c
index 7b49c9997df7..d8dc2f2f8000 100644
--- a/drivers/input/misc/stpmic1_onkey.c
+++ b/drivers/input/misc/stpmic1_onkey.c
@@ -61,18 +61,12 @@ static int stpmic1_onkey_probe(struct platform_device *pdev)
return -ENOMEM;
onkey->irq_falling = platform_get_irq_byname(pdev, "onkey-falling");
- if (onkey->irq_falling < 0) {
- dev_err(dev, "failed: request IRQ onkey-falling %d\n",
- onkey->irq_falling);
+ if (onkey->irq_falling < 0)
return onkey->irq_falling;
- }
onkey->irq_rising = platform_get_irq_byname(pdev, "onkey-rising");
- if (onkey->irq_rising < 0) {
- dev_err(dev, "failed: request IRQ onkey-rising %d\n",
- onkey->irq_rising);
+ if (onkey->irq_rising < 0)
return onkey->irq_rising;
- }
if (!device_property_read_u32(dev, "power-off-time-sec", &val)) {
if (val > 0 && val <= 16) {
diff --git a/drivers/input/misc/tps65218-pwrbutton.c b/drivers/input/misc/tps65218-pwrbutton.c
index a4455bb12ae0..f011447c44fb 100644
--- a/drivers/input/misc/tps65218-pwrbutton.c
+++ b/drivers/input/misc/tps65218-pwrbutton.c
@@ -124,10 +124,8 @@ static int tps6521x_pb_probe(struct platform_device *pdev)
device_init_wakeup(dev, true);
irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(dev, "No IRQ resource!\n");
+ if (irq < 0)
return -EINVAL;
- }
error = devm_request_threaded_irq(dev, irq, NULL, tps6521x_pb_irq,
IRQF_TRIGGER_RISING |
diff --git a/drivers/input/misc/twl6040-vibra.c b/drivers/input/misc/twl6040-vibra.c
index 93235a007d07..bf6644927630 100644
--- a/drivers/input/misc/twl6040-vibra.c
+++ b/drivers/input/misc/twl6040-vibra.c
@@ -272,10 +272,8 @@ static int twl6040_vibra_probe(struct platform_device *pdev)
}
info->irq = platform_get_irq(pdev, 0);
- if (info->irq < 0) {
- dev_err(info->dev, "invalid irq\n");
+ if (info->irq < 0)
return -EINVAL;
- }
error = devm_request_threaded_irq(&pdev->dev, info->irq, NULL,
twl6040_vib_irq_handler,