summaryrefslogtreecommitdiff
path: root/drivers/input
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/keyboard/cros_ec_keyb.c6
-rw-r--r--drivers/input/keyboard/imx_sc_key.c2
-rw-r--r--drivers/input/misc/Kconfig11
-rw-r--r--drivers/input/misc/Makefile1
-rw-r--r--drivers/input/misc/arizona-haptics.c14
-rw-r--r--drivers/input/misc/pf1550-onkey.c197
-rw-r--r--drivers/input/tablet/pegasus_notetaker.c9
-rw-r--r--drivers/input/touchscreen/goodix.c28
-rw-r--r--drivers/input/touchscreen/goodix.h1
9 files changed, 232 insertions, 37 deletions
diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c
index f7209c8ebbcc..1c6b0461dc35 100644
--- a/drivers/input/keyboard/cros_ec_keyb.c
+++ b/drivers/input/keyboard/cros_ec_keyb.c
@@ -261,6 +261,12 @@ static int cros_ec_keyb_work(struct notifier_block *nb,
case EC_MKBP_EVENT_KEY_MATRIX:
pm_wakeup_event(ckdev->dev, 0);
+ if (!ckdev->idev) {
+ dev_warn_once(ckdev->dev,
+ "Unexpected key matrix event\n");
+ return NOTIFY_OK;
+ }
+
if (ckdev->ec->event_size != ckdev->cols) {
dev_err(ckdev->dev,
"Discarded incomplete key matrix event.\n");
diff --git a/drivers/input/keyboard/imx_sc_key.c b/drivers/input/keyboard/imx_sc_key.c
index d18839f1f4f6..b620cd310cdb 100644
--- a/drivers/input/keyboard/imx_sc_key.c
+++ b/drivers/input/keyboard/imx_sc_key.c
@@ -158,7 +158,7 @@ static int imx_sc_key_probe(struct platform_device *pdev)
return error;
}
- error = devm_add_action_or_reset(&pdev->dev, imx_sc_key_action, &priv);
+ error = devm_add_action_or_reset(&pdev->dev, imx_sc_key_action, priv);
if (error)
return error;
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index cc2558630797..94a753fcb64f 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -190,6 +190,17 @@ config INPUT_PCSPKR
To compile this driver as a module, choose M here: the
module will be called pcspkr.
+config INPUT_PF1550_ONKEY
+ tristate "NXP PF1550 Onkey support"
+ depends on MFD_PF1550
+ help
+ Say Y here if you want support for PF1550 PMIC. Onkey can trigger
+ release and 1s(push hold), 2s, 3s, 4s, 8s interrupt for long press
+ detect.
+
+ To compile this driver as a module, choose M here. The module will be
+ called pf1550-onkey.
+
config INPUT_PM8941_PWRKEY
tristate "Qualcomm PM8941 power key support"
depends on MFD_SPMI_PMIC
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index f5ebfa9d9983..415fc4e2918b 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -63,6 +63,7 @@ obj-$(CONFIG_INPUT_PALMAS_PWRBUTTON) += palmas-pwrbutton.o
obj-$(CONFIG_INPUT_PCAP) += pcap_keys.o
obj-$(CONFIG_INPUT_PCF8574) += pcf8574_keypad.o
obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o
+obj-$(CONFIG_INPUT_PF1550_ONKEY) += pf1550-onkey.o
obj-$(CONFIG_INPUT_PM8941_PWRKEY) += pm8941-pwrkey.o
obj-$(CONFIG_INPUT_PM8XXX_VIBRATOR) += pm8xxx-vibrator.o
obj-$(CONFIG_INPUT_PMIC8XXX_PWRKEY) += pmic8xxx-pwrkey.o
diff --git a/drivers/input/misc/arizona-haptics.c b/drivers/input/misc/arizona-haptics.c
index 5fa1c9438a85..bb1544d63c51 100644
--- a/drivers/input/misc/arizona-haptics.c
+++ b/drivers/input/misc/arizona-haptics.c
@@ -34,8 +34,6 @@ static void arizona_haptics_work(struct work_struct *work)
struct arizona_haptics,
work);
struct arizona *arizona = haptics->arizona;
- struct snd_soc_component *component =
- snd_soc_dapm_to_component(arizona->dapm);
int ret;
if (!haptics->arizona->dapm) {
@@ -65,7 +63,7 @@ static void arizona_haptics_work(struct work_struct *work)
return;
}
- ret = snd_soc_component_enable_pin(component, "HAPTICS");
+ ret = snd_soc_dapm_enable_pin(arizona->dapm, "HAPTICS");
if (ret != 0) {
dev_err(arizona->dev, "Failed to start HAPTICS: %d\n",
ret);
@@ -80,7 +78,7 @@ static void arizona_haptics_work(struct work_struct *work)
}
} else {
/* This disable sequence will be a noop if already enabled */
- ret = snd_soc_component_disable_pin(component, "HAPTICS");
+ ret = snd_soc_dapm_disable_pin(arizona->dapm, "HAPTICS");
if (ret != 0) {
dev_err(arizona->dev, "Failed to disable HAPTICS: %d\n",
ret);
@@ -139,14 +137,12 @@ static int arizona_haptics_play(struct input_dev *input, void *data,
static void arizona_haptics_close(struct input_dev *input)
{
struct arizona_haptics *haptics = input_get_drvdata(input);
- struct snd_soc_component *component;
+ struct snd_soc_dapm_context *dapm = haptics->arizona->dapm;
cancel_work_sync(&haptics->work);
- if (haptics->arizona->dapm) {
- component = snd_soc_dapm_to_component(haptics->arizona->dapm);
- snd_soc_component_disable_pin(component, "HAPTICS");
- }
+ if (dapm)
+ snd_soc_dapm_disable_pin(dapm, "HAPTICS");
}
static int arizona_haptics_probe(struct platform_device *pdev)
diff --git a/drivers/input/misc/pf1550-onkey.c b/drivers/input/misc/pf1550-onkey.c
new file mode 100644
index 000000000000..9be6377151cb
--- /dev/null
+++ b/drivers/input/misc/pf1550-onkey.c
@@ -0,0 +1,197 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for the PF1550 ONKEY
+ * Copyright (C) 2016 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * Portions Copyright (c) 2025 Savoir-faire Linux Inc.
+ * Samuel Kayode <samuel.kayode@savoirfairelinux.com>
+ */
+
+#include <linux/err.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mfd/pf1550.h>
+#include <linux/platform_device.h>
+
+#define PF1550_ONKEY_IRQ_NR 6
+
+struct onkey_drv_data {
+ struct device *dev;
+ const struct pf1550_ddata *pf1550;
+ bool wakeup;
+ struct input_dev *input;
+};
+
+static irqreturn_t pf1550_onkey_irq_handler(int irq, void *data)
+{
+ struct onkey_drv_data *onkey = data;
+ struct platform_device *pdev = to_platform_device(onkey->dev);
+ int i, state, irq_type = -1;
+
+ for (i = 0; i < PF1550_ONKEY_IRQ_NR; i++)
+ if (irq == platform_get_irq(pdev, i))
+ irq_type = i;
+
+ switch (irq_type) {
+ case PF1550_ONKEY_IRQ_PUSHI:
+ state = 0;
+ break;
+ case PF1550_ONKEY_IRQ_1SI:
+ case PF1550_ONKEY_IRQ_2SI:
+ case PF1550_ONKEY_IRQ_3SI:
+ case PF1550_ONKEY_IRQ_4SI:
+ case PF1550_ONKEY_IRQ_8SI:
+ state = 1;
+ break;
+ default:
+ dev_err(onkey->dev, "onkey interrupt: irq %d occurred\n",
+ irq_type);
+ return IRQ_HANDLED;
+ }
+
+ input_event(onkey->input, EV_KEY, KEY_POWER, state);
+ input_sync(onkey->input);
+
+ return IRQ_HANDLED;
+}
+
+static int pf1550_onkey_probe(struct platform_device *pdev)
+{
+ struct onkey_drv_data *onkey;
+ struct input_dev *input;
+ bool key_power = false;
+ int i, irq, error;
+
+ onkey = devm_kzalloc(&pdev->dev, sizeof(*onkey), GFP_KERNEL);
+ if (!onkey)
+ return -ENOMEM;
+
+ onkey->dev = &pdev->dev;
+
+ onkey->pf1550 = dev_get_drvdata(pdev->dev.parent);
+ if (!onkey->pf1550->regmap)
+ return dev_err_probe(&pdev->dev, -ENODEV,
+ "failed to get regmap\n");
+
+ onkey->wakeup = device_property_read_bool(pdev->dev.parent,
+ "wakeup-source");
+
+ if (device_property_read_bool(pdev->dev.parent,
+ "nxp,disable-key-power")) {
+ error = regmap_clear_bits(onkey->pf1550->regmap,
+ PF1550_PMIC_REG_PWRCTRL1,
+ PF1550_ONKEY_RST_EN);
+ if (error)
+ return dev_err_probe(&pdev->dev, error,
+ "failed: disable turn system off");
+ } else {
+ key_power = true;
+ }
+
+ input = devm_input_allocate_device(&pdev->dev);
+ if (!input)
+ return dev_err_probe(&pdev->dev, -ENOMEM,
+ "failed to allocate the input device\n");
+
+ input->name = pdev->name;
+ input->phys = "pf1550-onkey/input0";
+ input->id.bustype = BUS_HOST;
+
+ if (key_power)
+ input_set_capability(input, EV_KEY, KEY_POWER);
+
+ onkey->input = input;
+ platform_set_drvdata(pdev, onkey);
+
+ for (i = 0; i < PF1550_ONKEY_IRQ_NR; i++) {
+ irq = platform_get_irq(pdev, i);
+ if (irq < 0)
+ return irq;
+
+ error = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+ pf1550_onkey_irq_handler,
+ IRQF_NO_SUSPEND,
+ "pf1550-onkey", onkey);
+ if (error)
+ return dev_err_probe(&pdev->dev, error,
+ "failed: irq request (IRQ: %d)\n",
+ i);
+ }
+
+ error = input_register_device(input);
+ if (error)
+ return dev_err_probe(&pdev->dev, error,
+ "failed to register input device\n");
+
+ device_init_wakeup(&pdev->dev, onkey->wakeup);
+
+ return 0;
+}
+
+static int pf1550_onkey_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct onkey_drv_data *onkey = platform_get_drvdata(pdev);
+ int i, irq;
+
+ if (!device_may_wakeup(&pdev->dev))
+ regmap_write(onkey->pf1550->regmap,
+ PF1550_PMIC_REG_ONKEY_INT_MASK0,
+ ONKEY_IRQ_PUSHI | ONKEY_IRQ_1SI | ONKEY_IRQ_2SI |
+ ONKEY_IRQ_3SI | ONKEY_IRQ_4SI | ONKEY_IRQ_8SI);
+ else
+ for (i = 0; i < PF1550_ONKEY_IRQ_NR; i++) {
+ irq = platform_get_irq(pdev, i);
+ if (irq > 0)
+ enable_irq_wake(irq);
+ }
+
+ return 0;
+}
+
+static int pf1550_onkey_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct onkey_drv_data *onkey = platform_get_drvdata(pdev);
+ int i, irq;
+
+ if (!device_may_wakeup(&pdev->dev))
+ regmap_write(onkey->pf1550->regmap,
+ PF1550_PMIC_REG_ONKEY_INT_MASK0,
+ ~((u8)(ONKEY_IRQ_PUSHI | ONKEY_IRQ_1SI |
+ ONKEY_IRQ_2SI | ONKEY_IRQ_3SI | ONKEY_IRQ_4SI |
+ ONKEY_IRQ_8SI)));
+ else
+ for (i = 0; i < PF1550_ONKEY_IRQ_NR; i++) {
+ irq = platform_get_irq(pdev, i);
+ if (irq > 0)
+ disable_irq_wake(irq);
+ }
+
+ return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(pf1550_onkey_pm_ops, pf1550_onkey_suspend,
+ pf1550_onkey_resume);
+
+static const struct platform_device_id pf1550_onkey_id[] = {
+ { "pf1550-onkey", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, pf1550_onkey_id);
+
+static struct platform_driver pf1550_onkey_driver = {
+ .driver = {
+ .name = "pf1550-onkey",
+ .pm = pm_sleep_ptr(&pf1550_onkey_pm_ops),
+ },
+ .probe = pf1550_onkey_probe,
+ .id_table = pf1550_onkey_id,
+};
+module_platform_driver(pf1550_onkey_driver);
+
+MODULE_AUTHOR("Freescale Semiconductor");
+MODULE_DESCRIPTION("PF1550 onkey Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/tablet/pegasus_notetaker.c b/drivers/input/tablet/pegasus_notetaker.c
index 8d6b71d59793..eabb4a0b8a0d 100644
--- a/drivers/input/tablet/pegasus_notetaker.c
+++ b/drivers/input/tablet/pegasus_notetaker.c
@@ -63,6 +63,9 @@
#define BUTTON_PRESSED 0xb5
#define COMMAND_VERSION 0xa9
+/* 1 Status + 1 Color + 2 X + 2 Y = 6 bytes */
+#define NOTETAKER_PACKET_SIZE 6
+
/* in xy data packet */
#define BATTERY_NO_REPORT 0x40
#define BATTERY_LOW 0x41
@@ -311,6 +314,12 @@ static int pegasus_probe(struct usb_interface *intf,
}
pegasus->data_len = usb_maxpacket(dev, pipe);
+ if (pegasus->data_len < NOTETAKER_PACKET_SIZE) {
+ dev_err(&intf->dev, "packet size is too small (%d)\n",
+ pegasus->data_len);
+ error = -EINVAL;
+ goto err_free_mem;
+ }
pegasus->data = usb_alloc_coherent(dev, pegasus->data_len, GFP_KERNEL,
&pegasus->data_dma);
diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c
index 252dcae039f8..f8798d11ec03 100644
--- a/drivers/input/touchscreen/goodix.c
+++ b/drivers/input/touchscreen/goodix.c
@@ -796,17 +796,6 @@ int goodix_reset_no_int_sync(struct goodix_ts_data *ts)
usleep_range(6000, 10000); /* T4: > 5ms */
- /*
- * Put the reset pin back in to input / high-impedance mode to save
- * power. Only do this in the non ACPI case since some ACPI boards
- * don't have a pull-up, so there the reset pin must stay active-high.
- */
- if (ts->irq_pin_access_method == IRQ_PIN_ACCESS_GPIO) {
- error = gpiod_direction_input(ts->gpiod_rst);
- if (error)
- goto error;
- }
-
return 0;
error:
@@ -957,14 +946,6 @@ static int goodix_add_acpi_gpio_mappings(struct goodix_ts_data *ts)
return -EINVAL;
}
- /*
- * Normally we put the reset pin in input / high-impedance mode to save
- * power. But some x86/ACPI boards don't have a pull-up, so for the ACPI
- * case, leave the pin as is. This results in the pin not being touched
- * at all on x86/ACPI boards, except when needed for error-recover.
- */
- ts->gpiod_rst_flags = GPIOD_ASIS;
-
return devm_acpi_dev_add_driver_gpios(dev, gpio_mapping);
}
#else
@@ -989,12 +970,6 @@ static int goodix_get_gpio_config(struct goodix_ts_data *ts)
return -EINVAL;
dev = &ts->client->dev;
- /*
- * By default we request the reset pin as input, leaving it in
- * high-impedance when not resetting the controller to save power.
- */
- ts->gpiod_rst_flags = GPIOD_IN;
-
ts->avdd28 = devm_regulator_get(dev, "AVDD28");
if (IS_ERR(ts->avdd28))
return dev_err_probe(dev, PTR_ERR(ts->avdd28), "Failed to get AVDD28 regulator\n");
@@ -1019,7 +994,7 @@ retry_get_irq_gpio:
ts->gpiod_int = gpiod;
/* Get the reset line GPIO pin number */
- gpiod = devm_gpiod_get_optional(dev, GOODIX_GPIO_RST_NAME, ts->gpiod_rst_flags);
+ gpiod = devm_gpiod_get_optional(dev, GOODIX_GPIO_RST_NAME, GPIOD_ASIS);
if (IS_ERR(gpiod))
return dev_err_probe(dev, PTR_ERR(gpiod), "Failed to get %s GPIO\n",
GOODIX_GPIO_RST_NAME);
@@ -1557,6 +1532,7 @@ MODULE_DEVICE_TABLE(i2c, goodix_ts_id);
static const struct acpi_device_id goodix_acpi_match[] = {
{ "GDIX1001", 0 },
{ "GDIX1002", 0 },
+ { "GDIX1003", 0 },
{ "GDX9110", 0 },
{ }
};
diff --git a/drivers/input/touchscreen/goodix.h b/drivers/input/touchscreen/goodix.h
index 87797cc88b32..0d1e8a8d2cba 100644
--- a/drivers/input/touchscreen/goodix.h
+++ b/drivers/input/touchscreen/goodix.h
@@ -88,7 +88,6 @@ struct goodix_ts_data {
struct gpio_desc *gpiod_rst;
int gpio_count;
int gpio_int_idx;
- enum gpiod_flags gpiod_rst_flags;
char id[GOODIX_ID_MAX_LEN + 1];
char cfg_name[64];
u16 version;