From 5d4b45a1dd7b00feab57624035dcdbc1bab2e0f8 Mon Sep 17 00:00:00 2001 From: Markus Koch Date: Sun, 21 Jul 2019 20:20:28 +0300 Subject: Input: add support for the FlySky FS-iA6B RC receiver This patch adds support for the FlySky FS-iA6B RC receiver (serial IBUS). It allows the usage of the FlySky FS-i6 and other AFHDS compliant remote controls as a joystick input device. To use it, a patch to inputattach which adds the FS-iA6B as a 115200 baud serial device is required. I will upstream it after this patch is merged. More information about the hardware can be found here: https://notsyncing.net/?p=blog&b=2018.linux-fsia6b Signed-off-by: Markus Koch Signed-off-by: Dmitry Torokhov --- MAINTAINERS | 6 ++ drivers/input/joystick/Kconfig | 10 ++ drivers/input/joystick/Makefile | 5 +- drivers/input/joystick/fsia6b.c | 231 ++++++++++++++++++++++++++++++++++++++++ include/uapi/linux/serio.h | 1 + 5 files changed, 251 insertions(+), 2 deletions(-) create mode 100644 drivers/input/joystick/fsia6b.c diff --git a/MAINTAINERS b/MAINTAINERS index 677ef41cb012..cdd25b0a1218 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -12394,6 +12394,12 @@ S: Maintained F: Documentation/input/devices/pxrc.rst F: drivers/input/joystick/pxrc.c +FLYSKY FSIA6B RC RECEIVER +M: Markus Koch +L: linux-input@vger.kernel.org +S: Maintained +F: drivers/input/joystick/fsia6b.c + PHONET PROTOCOL M: Remi Denis-Courmont S: Supported diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig index 72b932901d00..312b854b5506 100644 --- a/drivers/input/joystick/Kconfig +++ b/drivers/input/joystick/Kconfig @@ -362,4 +362,14 @@ config JOYSTICK_PXRC To compile this driver as a module, choose M here: the module will be called pxrc. +config JOYSTICK_FSIA6B + tristate "FlySky FS-iA6B RC Receiver" + select SERIO + help + Say Y here if you use a FlySky FS-i6 RC remote control along with the + FS-iA6B RC receiver as a joystick input device. + + To compile this driver as a module, choose M here: the + module will be called fsia6b. + endif diff --git a/drivers/input/joystick/Makefile b/drivers/input/joystick/Makefile index dd0492ebbed7..8656023f6ef5 100644 --- a/drivers/input/joystick/Makefile +++ b/drivers/input/joystick/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_JOYSTICK_AS5011) += as5011.o obj-$(CONFIG_JOYSTICK_ANALOG) += analog.o obj-$(CONFIG_JOYSTICK_COBRA) += cobra.o obj-$(CONFIG_JOYSTICK_DB9) += db9.o +obj-$(CONFIG_JOYSTICK_FSIA6B) += fsia6b.o obj-$(CONFIG_JOYSTICK_GAMECON) += gamecon.o obj-$(CONFIG_JOYSTICK_GF2K) += gf2k.o obj-$(CONFIG_JOYSTICK_GRIP) += grip.o @@ -23,7 +24,7 @@ obj-$(CONFIG_JOYSTICK_JOYDUMP) += joydump.o obj-$(CONFIG_JOYSTICK_MAGELLAN) += magellan.o obj-$(CONFIG_JOYSTICK_MAPLE) += maplecontrol.o obj-$(CONFIG_JOYSTICK_PSXPAD_SPI) += psxpad-spi.o -obj-$(CONFIG_JOYSTICK_PXRC) += pxrc.o +obj-$(CONFIG_JOYSTICK_PXRC) += pxrc.o obj-$(CONFIG_JOYSTICK_SIDEWINDER) += sidewinder.o obj-$(CONFIG_JOYSTICK_SPACEBALL) += spaceball.o obj-$(CONFIG_JOYSTICK_SPACEORB) += spaceorb.o @@ -32,7 +33,7 @@ obj-$(CONFIG_JOYSTICK_TMDC) += tmdc.o obj-$(CONFIG_JOYSTICK_TURBOGRAFX) += turbografx.o obj-$(CONFIG_JOYSTICK_TWIDJOY) += twidjoy.o obj-$(CONFIG_JOYSTICK_WARRIOR) += warrior.o +obj-$(CONFIG_JOYSTICK_WALKERA0701) += walkera0701.o obj-$(CONFIG_JOYSTICK_XPAD) += xpad.o obj-$(CONFIG_JOYSTICK_ZHENHUA) += zhenhua.o -obj-$(CONFIG_JOYSTICK_WALKERA0701) += walkera0701.o diff --git a/drivers/input/joystick/fsia6b.c b/drivers/input/joystick/fsia6b.c new file mode 100644 index 000000000000..e78c4c768990 --- /dev/null +++ b/drivers/input/joystick/fsia6b.c @@ -0,0 +1,231 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * FS-iA6B iBus RC receiver driver + * + * This driver provides all 14 channels of the FlySky FS-ia6B RC receiver + * as analog values. + * + * Additionally, the channels can be converted to discrete switch values. + * By default, it is configured for the offical FS-i6 remote control. + * If you use a different hardware configuration, you can configure it + * using the `switch_config` parameter. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_DESC "FS-iA6B iBus RC receiver" + +MODULE_AUTHOR("Markus Koch "); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); + +#define IBUS_SERVO_COUNT 14 + +static char *switch_config = "00000022320000"; +module_param(switch_config, charp, 0444); +MODULE_PARM_DESC(switch_config, + "Amount of switch positions per channel (14 characters, 0-3)"); + +static int fsia6b_axes[IBUS_SERVO_COUNT] = { + ABS_X, ABS_Y, + ABS_Z, ABS_RX, + ABS_RY, ABS_RZ, + ABS_HAT0X, ABS_HAT0Y, + ABS_HAT1X, ABS_HAT1Y, + ABS_HAT2X, ABS_HAT2Y, + ABS_HAT3X, ABS_HAT3Y +}; + +enum ibus_state { SYNC, COLLECT, PROCESS }; + +struct ibus_packet { + enum ibus_state state; + + int offset; + u16 ibuf; + u16 channel[IBUS_SERVO_COUNT]; +}; + +struct fsia6b { + struct input_dev *dev; + struct ibus_packet packet; + + char phys[32]; +}; + +static irqreturn_t fsia6b_serio_irq(struct serio *serio, + unsigned char data, unsigned int flags) +{ + struct fsia6b *fsia6b = serio_get_drvdata(serio); + int i; + int sw_state; + int sw_id = BTN_0; + + fsia6b->packet.ibuf = (data << 8) | ((fsia6b->packet.ibuf >> 8) & 0xFF); + + switch (fsia6b->packet.state) { + case SYNC: + if (fsia6b->packet.ibuf == 0x4020) + fsia6b->packet.state = COLLECT; + break; + + case COLLECT: + fsia6b->packet.state = PROCESS; + break; + + case PROCESS: + fsia6b->packet.channel[fsia6b->packet.offset] = + fsia6b->packet.ibuf; + fsia6b->packet.offset++; + + if (fsia6b->packet.offset == IBUS_SERVO_COUNT) { + fsia6b->packet.offset = 0; + fsia6b->packet.state = SYNC; + for (i = 0; i < IBUS_SERVO_COUNT; ++i) { + input_report_abs(fsia6b->dev, fsia6b_axes[i], + fsia6b->packet.channel[i]); + + sw_state = 0; + if (fsia6b->packet.channel[i] > 1900) + sw_state = 1; + else if (fsia6b->packet.channel[i] < 1100) + sw_state = 2; + + switch (switch_config[i]) { + case '3': + input_report_key(fsia6b->dev, + sw_id++, + sw_state == 0); + /* fall-through */ + case '2': + input_report_key(fsia6b->dev, + sw_id++, + sw_state == 1); + /* fall-through */ + case '1': + input_report_key(fsia6b->dev, + sw_id++, + sw_state == 2); + } + } + input_sync(fsia6b->dev); + } else { + fsia6b->packet.state = COLLECT; + } + break; + } + + return IRQ_HANDLED; +} + +static int fsia6b_serio_connect(struct serio *serio, struct serio_driver *drv) +{ + struct fsia6b *fsia6b; + struct input_dev *input_dev; + int err; + int i, j; + int sw_id = 0; + + fsia6b = kzalloc(sizeof(*fsia6b), GFP_KERNEL); + if (!fsia6b) + return -ENOMEM; + + fsia6b->packet.ibuf = 0; + fsia6b->packet.offset = 0; + fsia6b->packet.state = SYNC; + + serio_set_drvdata(serio, fsia6b); + + input_dev = input_allocate_device(); + if (!input_dev) { + err = -ENOMEM; + goto fail1; + } + fsia6b->dev = input_dev; + + snprintf(fsia6b->phys, sizeof(fsia6b->phys), "%s/input0", serio->phys); + + input_dev->name = DRIVER_DESC; + input_dev->phys = fsia6b->phys; + input_dev->id.bustype = BUS_RS232; + input_dev->id.vendor = SERIO_FSIA6B; + input_dev->id.product = serio->id.id; + input_dev->id.version = 0x0100; + input_dev->dev.parent = &serio->dev; + + for (i = 0; i < IBUS_SERVO_COUNT; i++) + input_set_abs_params(input_dev, fsia6b_axes[i], + 1000, 2000, 2, 2); + + /* Register switch configuration */ + for (i = 0; i < IBUS_SERVO_COUNT; i++) { + if (switch_config[i] < '0' || switch_config[i] > '3') { + dev_err(&fsia6b->dev->dev, + "Invalid switch configuration supplied for fsia6b.\n"); + err = -EINVAL; + goto fail2; + } + + for (j = '1'; j <= switch_config[i]; j++) { + input_set_capability(input_dev, EV_KEY, BTN_0 + sw_id); + sw_id++; + } + } + + err = serio_open(serio, drv); + if (err) + goto fail2; + + err = input_register_device(fsia6b->dev); + if (err) + goto fail3; + + return 0; + +fail3: serio_close(serio); +fail2: input_free_device(input_dev); +fail1: serio_set_drvdata(serio, NULL); + kfree(fsia6b); + return err; +} + +static void fsia6b_serio_disconnect(struct serio *serio) +{ + struct fsia6b *fsia6b = serio_get_drvdata(serio); + + serio_close(serio); + serio_set_drvdata(serio, NULL); + input_unregister_device(fsia6b->dev); + kfree(fsia6b); +} + +static const struct serio_device_id fsia6b_serio_ids[] = { + { + .type = SERIO_RS232, + .proto = SERIO_FSIA6B, + .id = SERIO_ANY, + .extra = SERIO_ANY, + }, + { 0 } +}; + +MODULE_DEVICE_TABLE(serio, fsia6b_serio_ids); + +static struct serio_driver fsia6b_serio_drv = { + .driver = { + .name = "fsia6b" + }, + .description = DRIVER_DESC, + .id_table = fsia6b_serio_ids, + .interrupt = fsia6b_serio_irq, + .connect = fsia6b_serio_connect, + .disconnect = fsia6b_serio_disconnect +}; + +module_serio_driver(fsia6b_serio_drv) diff --git a/include/uapi/linux/serio.h b/include/uapi/linux/serio.h index a0cac1d8670d..50e991952c97 100644 --- a/include/uapi/linux/serio.h +++ b/include/uapi/linux/serio.h @@ -82,5 +82,6 @@ #define SERIO_EGALAX 0x3f #define SERIO_PULSE8_CEC 0x40 #define SERIO_RAINSHADOW_CEC 0x41 +#define SERIO_FSIA6B 0x42 #endif /* _UAPI_SERIO_H */ -- cgit v1.2.3 From 9d41cbe23db0a3c51c0b28db987a6898f5d1255c Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Tue, 16 Jul 2019 09:26:56 +0200 Subject: Input: fsl-imx25-tcq - use devm_platform_ioremap_resource() devm_platform_ioremap_resource() internally have platform_get_resource() and devm_ioremap_resource() in it. So instead of calling them separately use devm_platform_ioremap_resource() directly. Signed-off-by: Mukesh Ojha Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/fsl-imx25-tcq.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/input/touchscreen/fsl-imx25-tcq.c b/drivers/input/touchscreen/fsl-imx25-tcq.c index 1d6c8f490b40..b66df8ab89f2 100644 --- a/drivers/input/touchscreen/fsl-imx25-tcq.c +++ b/drivers/input/touchscreen/fsl-imx25-tcq.c @@ -503,7 +503,6 @@ static int mx25_tcq_probe(struct platform_device *pdev) struct input_dev *idev; struct mx25_tcq_priv *priv; struct mx25_tsadc *tsadc = dev_get_drvdata(dev->parent); - struct resource *res; void __iomem *mem; int error; @@ -512,8 +511,7 @@ static int mx25_tcq_probe(struct platform_device *pdev) return -ENOMEM; priv->dev = dev; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - mem = devm_ioremap_resource(dev, res); + mem = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(mem)) return PTR_ERR(mem); -- cgit v1.2.3 From 46bec7a918715d3b0e8d22e5e99d3245c1097c65 Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Tue, 16 Jul 2019 09:27:22 +0200 Subject: Input: mxs-lradc-ts - use devm_platform_ioremap_resource() devm_platform_ioremap_resource() internally have platform_get_resource() and devm_ioremap_resource() in it. So instead of calling them separately use devm_platform_ioremap_resource() directly. Signed-off-by: Mukesh Ojha Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/mxs-lradc-ts.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/input/touchscreen/mxs-lradc-ts.c b/drivers/input/touchscreen/mxs-lradc-ts.c index 593b8d3e90b5..9e36fee38d61 100644 --- a/drivers/input/touchscreen/mxs-lradc-ts.c +++ b/drivers/input/touchscreen/mxs-lradc-ts.c @@ -606,7 +606,6 @@ static int mxs_lradc_ts_probe(struct platform_device *pdev) struct device_node *node = dev->parent->of_node; struct mxs_lradc *lradc = dev_get_drvdata(dev->parent); struct mxs_lradc_ts *ts; - struct resource *iores; int ret, irq, virq, i; u32 ts_wires = 0, adapt; @@ -620,12 +619,9 @@ static int mxs_lradc_ts_probe(struct platform_device *pdev) ts->dev = dev; spin_lock_init(&ts->lock); - iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!iores) - return -EINVAL; - ts->base = devm_ioremap(dev, iores->start, resource_size(iores)); - if (!ts->base) - return -ENOMEM; + ts->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(ts->base)) + return PTR_ERR(ts->base); ret = of_property_read_u32(node, "fsl,lradc-touchscreen-wires", &ts_wires); -- cgit v1.2.3 From 9601fa8fa9feb90afdddab345d942e33aa505835 Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Tue, 16 Jul 2019 09:34:13 +0200 Subject: Input: sun4i-ts - use devm_platform_ioremap_resource() devm_platform_ioremap_resource() internally have platform_get_resource() and devm_ioremap_resource() in it. So instead of calling them separately use devm_platform_ioremap_resource() directly. Signed-off-by: Mukesh Ojha Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/sun4i-ts.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/input/touchscreen/sun4i-ts.c b/drivers/input/touchscreen/sun4i-ts.c index 92f6e1ae23a2..4e83e96bb73f 100644 --- a/drivers/input/touchscreen/sun4i-ts.c +++ b/drivers/input/touchscreen/sun4i-ts.c @@ -300,8 +300,7 @@ static int sun4i_ts_probe(struct platform_device *pdev) input_set_drvdata(ts->input, ts); } - ts->base = devm_ioremap_resource(dev, - platform_get_resource(pdev, IORESOURCE_MEM, 0)); + ts->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(ts->base)) return PTR_ERR(ts->base); -- cgit v1.2.3 From f8890bd2875bf9d6aca4cd7fbf246364dbeb8a0f Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Tue, 16 Jul 2019 09:34:39 +0200 Subject: Input: ts4800-ts - use devm_platform_ioremap_resource() devm_platform_ioremap_resource() internally have platform_get_resource() and devm_ioremap_resource() in it. So instead of calling them separately use devm_platform_ioremap_resource() directly. Signed-off-by: Mukesh Ojha Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/ts4800-ts.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/input/touchscreen/ts4800-ts.c b/drivers/input/touchscreen/ts4800-ts.c index fed73eeb47b3..5b4f5362c67b 100644 --- a/drivers/input/touchscreen/ts4800-ts.c +++ b/drivers/input/touchscreen/ts4800-ts.c @@ -148,7 +148,6 @@ static int ts4800_ts_probe(struct platform_device *pdev) { struct input_polled_dev *poll_dev; struct ts4800_ts *ts; - struct resource *res; int error; ts = devm_kzalloc(&pdev->dev, sizeof(*ts), GFP_KERNEL); @@ -159,8 +158,7 @@ static int ts4800_ts_probe(struct platform_device *pdev) if (error) return error; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - ts->base = devm_ioremap_resource(&pdev->dev, res); + ts->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(ts->base)) return PTR_ERR(ts->base); -- cgit v1.2.3 From 3ccd63d369c80d7e73e19ca996d29b6e5d7225bb Mon Sep 17 00:00:00 2001 From: Denis Efremov Date: Sun, 14 Jul 2019 11:26:34 -0700 Subject: Input: synaptics-rmi4 - remove the exporting of rmi_2d_sensor_set_input_params The function rmi_2d_sensor_set_input_params is declared static and marked EXPORT_SYMBOL_GPL, which is at best an odd combination. Because the function is not used outside of the drivers/input/rmi4/rmi_2d_sensor.c file it is defined in, this commit removes the EXPORT_SYMBOL_GPL() marking. Signed-off-by: Denis Efremov Signed-off-by: Dmitry Torokhov --- drivers/input/rmi4/rmi_2d_sensor.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/input/rmi4/rmi_2d_sensor.c b/drivers/input/rmi4/rmi_2d_sensor.c index ea549efe4bc4..b7fe6eb35a4e 100644 --- a/drivers/input/rmi4/rmi_2d_sensor.c +++ b/drivers/input/rmi4/rmi_2d_sensor.c @@ -204,7 +204,6 @@ static void rmi_2d_sensor_set_input_params(struct rmi_2d_sensor *sensor) if (sensor->topbuttonpad) set_bit(INPUT_PROP_TOPBUTTONPAD, input->propbit); } -EXPORT_SYMBOL_GPL(rmi_2d_sensor_set_input_params); int rmi_2d_sensor_configure_input(struct rmi_function *fn, struct rmi_2d_sensor *sensor) -- cgit v1.2.3 From 9609b904c7eb411020d367d1f0904d0691819592 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sat, 13 Jul 2019 01:13:16 -0700 Subject: Input: elan_i2c - switch to using devm_device_add_groups() Instead of installing custom devm cleanup action to remove attribute groups on failure, let's use the dedicated devm API. Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/elan_i2c_core.c | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index d9b103a81a79..b549d032da93 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -1138,13 +1138,6 @@ static void elan_disable_regulator(void *_data) regulator_disable(data->vcc); } -static void elan_remove_sysfs_groups(void *_data) -{ - struct elan_tp_data *data = _data; - - sysfs_remove_groups(&data->client->dev.kobj, elan_sysfs_groups); -} - static int elan_probe(struct i2c_client *client, const struct i2c_device_id *dev_id) { @@ -1269,20 +1262,12 @@ static int elan_probe(struct i2c_client *client, return error; } - error = sysfs_create_groups(&dev->kobj, elan_sysfs_groups); + error = devm_device_add_groups(dev, elan_sysfs_groups); if (error) { dev_err(dev, "failed to create sysfs attributes: %d\n", error); return error; } - error = devm_add_action(dev, elan_remove_sysfs_groups, data); - if (error) { - elan_remove_sysfs_groups(data); - dev_err(dev, "Failed to add sysfs cleanup action: %d\n", - error); - return error; - } - error = input_register_device(data->input); if (error) { dev_err(dev, "failed to register input device: %d\n", error); -- cgit v1.2.3 From 2e75cfaa32c113568994eda716a0bdddc92b376e Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sat, 13 Jul 2019 01:18:14 -0700 Subject: Input: elan_i2c - switch to using devm_add_action_or_reset() Instead of manually disabling regulators when devm_add_action() fails we can use devm_add_action_or_reset() which does it for us. Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/elan_i2c_core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index b549d032da93..8719da540383 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -1187,9 +1187,8 @@ static int elan_probe(struct i2c_client *client, return error; } - error = devm_add_action(dev, elan_disable_regulator, data); + error = devm_add_action_or_reset(dev, elan_disable_regulator, data); if (error) { - regulator_disable(data->vcc); dev_err(dev, "Failed to add disable regulator action: %d\n", error); return error; -- cgit v1.2.3 From c2433827c1a149b72f1413f0151155f6fa4b3214 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sat, 13 Jul 2019 01:23:18 -0700 Subject: Input: cyapa - switch to using devm_device_add_group() Instead of installing custom devm cleanup action to remove attribute groups on failure, let's use the dedicated devm API. Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/cyapa.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index dfd3873513e4..c675f156948b 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -1238,13 +1238,6 @@ static const struct attribute_group cyapa_sysfs_group = { .attrs = cyapa_sysfs_entries, }; -static void cyapa_remove_sysfs_group(void *data) -{ - struct cyapa *cyapa = data; - - sysfs_remove_group(&cyapa->client->dev.kobj, &cyapa_sysfs_group); -} - static void cyapa_disable_regulator(void *data) { struct cyapa *cyapa = data; @@ -1312,19 +1305,12 @@ static int cyapa_probe(struct i2c_client *client, return error; } - error = sysfs_create_group(&dev->kobj, &cyapa_sysfs_group); + error = devm_device_add_group(dev, &cyapa_sysfs_group); if (error) { dev_err(dev, "failed to create sysfs entries: %d\n", error); return error; } - error = devm_add_action(dev, cyapa_remove_sysfs_group, cyapa); - if (error) { - cyapa_remove_sysfs_group(cyapa); - dev_err(dev, "failed to add sysfs cleanup action: %d\n", error); - return error; - } - error = cyapa_prepare_wakeup_controls(cyapa); if (error) { dev_err(dev, "failed to prepare wakeup controls: %d\n", error); -- cgit v1.2.3 From 3b51c44bd6936e86a7180abd9aebc4387a479253 Mon Sep 17 00:00:00 2001 From: Atif Niyaz Date: Wed, 24 Jul 2019 22:26:31 +0300 Subject: Input: allow drivers specify timestamp for input events Currently, evdev stamps events with timestamps acquired in evdev_events() However, this timestamping may not be accurate in terms of measuring when the actual event happened. Let's allow individual drivers specify timestamp in order to provide a more accurate sense of time for the event. It is expected that drivers will set the timestamp in their hard interrupt routine. Signed-off-by: Atif Niyaz Signed-off-by: Dmitry Torokhov --- drivers/input/evdev.c | 35 ++++++++--------------------------- drivers/input/input.c | 40 ++++++++++++++++++++++++++++++++++++++++ include/linux/input.h | 14 ++++++++++++++ 3 files changed, 62 insertions(+), 27 deletions(-) diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 867c2cfd0038..d7dd6fcf2db0 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -25,13 +25,6 @@ #include #include "input-compat.h" -enum evdev_clock_type { - EV_CLK_REAL = 0, - EV_CLK_MONO, - EV_CLK_BOOT, - EV_CLK_MAX -}; - struct evdev { int open; struct input_handle handle; @@ -53,7 +46,7 @@ struct evdev_client { struct fasync_struct *fasync; struct evdev *evdev; struct list_head node; - unsigned int clk_type; + enum input_clock_type clk_type; bool revoked; unsigned long *evmasks[EV_CNT]; unsigned int bufsize; @@ -149,17 +142,10 @@ static void __evdev_flush_queue(struct evdev_client *client, unsigned int type) static void __evdev_queue_syn_dropped(struct evdev_client *client) { + ktime_t *ev_time = input_get_timestamp(client->evdev->handle.dev); + struct timespec64 ts = ktime_to_timespec64(ev_time[client->clk_type]); struct input_event ev; - ktime_t time; - struct timespec64 ts; - time = client->clk_type == EV_CLK_REAL ? - ktime_get_real() : - client->clk_type == EV_CLK_MONO ? - ktime_get() : - ktime_get_boottime(); - - ts = ktime_to_timespec64(time); ev.input_event_sec = ts.tv_sec; ev.input_event_usec = ts.tv_nsec / NSEC_PER_USEC; ev.type = EV_SYN; @@ -188,18 +174,18 @@ static void evdev_queue_syn_dropped(struct evdev_client *client) static int evdev_set_clk_type(struct evdev_client *client, unsigned int clkid) { unsigned long flags; - unsigned int clk_type; + enum input_clock_type clk_type; switch (clkid) { case CLOCK_REALTIME: - clk_type = EV_CLK_REAL; + clk_type = INPUT_CLK_REAL; break; case CLOCK_MONOTONIC: - clk_type = EV_CLK_MONO; + clk_type = INPUT_CLK_MONO; break; case CLOCK_BOOTTIME: - clk_type = EV_CLK_BOOT; + clk_type = INPUT_CLK_BOOT; break; default: return -EINVAL; @@ -307,12 +293,7 @@ static void evdev_events(struct input_handle *handle, { struct evdev *evdev = handle->private; struct evdev_client *client; - ktime_t ev_time[EV_CLK_MAX]; - - ev_time[EV_CLK_MONO] = ktime_get(); - ev_time[EV_CLK_REAL] = ktime_mono_to_real(ev_time[EV_CLK_MONO]); - ev_time[EV_CLK_BOOT] = ktime_mono_to_any(ev_time[EV_CLK_MONO], - TK_OFFS_BOOT); + ktime_t *ev_time = input_get_timestamp(handle->dev); rcu_read_lock(); diff --git a/drivers/input/input.c b/drivers/input/input.c index 7f3c5fcb9ed6..7494a0dede79 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -1894,6 +1894,46 @@ void input_free_device(struct input_dev *dev) } EXPORT_SYMBOL(input_free_device); +/** + * input_set_timestamp - set timestamp for input events + * @dev: input device to set timestamp for + * @timestamp: the time at which the event has occurred + * in CLOCK_MONOTONIC + * + * This function is intended to provide to the input system a more + * accurate time of when an event actually occurred. The driver should + * call this function as soon as a timestamp is acquired ensuring + * clock conversions in input_set_timestamp are done correctly. + * + * The system entering suspend state between timestamp acquisition and + * calling input_set_timestamp can result in inaccurate conversions. + */ +void input_set_timestamp(struct input_dev *dev, ktime_t timestamp) +{ + dev->timestamp[INPUT_CLK_MONO] = timestamp; + dev->timestamp[INPUT_CLK_REAL] = ktime_mono_to_real(timestamp); + dev->timestamp[INPUT_CLK_BOOT] = ktime_mono_to_any(timestamp, + TK_OFFS_BOOT); +} +EXPORT_SYMBOL(input_set_timestamp); + +/** + * input_get_timestamp - get timestamp for input events + * @dev: input device to get timestamp from + * + * A valid timestamp is a timestamp of non-zero value. + */ +ktime_t *input_get_timestamp(struct input_dev *dev) +{ + const ktime_t invalid_timestamp = ktime_set(0, 0); + + if (!ktime_compare(dev->timestamp[INPUT_CLK_MONO], invalid_timestamp)) + input_set_timestamp(dev, ktime_get()); + + return dev->timestamp; +} +EXPORT_SYMBOL(input_get_timestamp); + /** * input_set_capability - mark device as capable of a certain event * @dev: device that is capable of emitting or accepting event diff --git a/include/linux/input.h b/include/linux/input.h index 510e78558c10..e95a439d8bd5 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -33,6 +33,13 @@ struct input_value { __s32 value; }; +enum input_clock_type { + INPUT_CLK_REAL = 0, + INPUT_CLK_MONO, + INPUT_CLK_BOOT, + INPUT_CLK_MAX +}; + /** * struct input_dev - represents an input device * @name: name of the device @@ -114,6 +121,8 @@ struct input_value { * @vals: array of values queued in the current frame * @devres_managed: indicates that devices is managed with devres framework * and needs not be explicitly unregistered or freed. + * @timestamp: storage for a timestamp set by input_set_timestamp called + * by a driver */ struct input_dev { const char *name; @@ -184,6 +193,8 @@ struct input_dev { struct input_value *vals; bool devres_managed; + + ktime_t timestamp[INPUT_CLK_MAX]; }; #define to_input_dev(d) container_of(d, struct input_dev, dev) @@ -382,6 +393,9 @@ void input_close_device(struct input_handle *); int input_flush_device(struct input_handle *handle, struct file *file); +void input_set_timestamp(struct input_dev *dev, ktime_t timestamp); +ktime_t *input_get_timestamp(struct input_dev *dev); + void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value); void input_inject_event(struct input_handle *handle, unsigned int type, unsigned int code, int value); -- cgit v1.2.3 From 64dd243d735655d1ff6bc7450dd5203cf57c9dfb Mon Sep 17 00:00:00 2001 From: Maximilian Luz Date: Sun, 28 Jul 2019 12:55:48 +0300 Subject: platform/x86: surfacepro3_button: Fix device check Do not use the surfacepro3_button driver on newer Microsoft Surface models, only use it on the Surface Pro 3 and 4. Newer models (5th, 6th and possibly future generations) use the same device as the Surface Pro 4 to represent their volume and power buttons (MSHW0040), but their actual implementation is significantly different. This patch ensures that the surfacepro3_button driver is only used on the Pro 3 and 4 models, allowing a different driver to bind on other models. Signed-off-by: Maximilian Luz Acked-by: Andy Shevchenko Acked-by: Chen Yu Signed-off-by: Dmitry Torokhov --- drivers/platform/x86/surfacepro3_button.c | 47 +++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/drivers/platform/x86/surfacepro3_button.c b/drivers/platform/x86/surfacepro3_button.c index 47c6d000465a..ec515223f654 100644 --- a/drivers/platform/x86/surfacepro3_button.c +++ b/drivers/platform/x86/surfacepro3_button.c @@ -20,6 +20,12 @@ #define SURFACE_BUTTON_OBJ_NAME "VGBI" #define SURFACE_BUTTON_DEVICE_NAME "Surface Pro 3/4 Buttons" +#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); + #define SURFACE_BUTTON_NOTIFY_TABLET_MODE 0xc8 #define SURFACE_BUTTON_NOTIFY_PRESS_POWER 0xc6 @@ -142,6 +148,44 @@ static int surface_button_resume(struct device *dev) } #endif +/* + * Surface Pro 4 and Surface Book 2 / Surface Pro 2017 use the same device + * ID (MSHW0040) for the power/volume buttons. Make sure this is the right + * device by checking for the _DSM method and OEM Platform Revision. + * + * Returns true if the driver should bind to this device, i.e. the device is + * either MSWH0028 (Pro 3) or MSHW0040 on a Pro 4 or Book 1. + */ +static bool surface_button_check_MSHW0040(struct acpi_device *dev) +{ + acpi_handle handle = dev->handle; + 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 evaluating the _DSM fails, the method is not present. This means + * that we have either MSHW0028 or MSHW0040 on Pro 4 or Book 1, so we + * should use this driver. We use revision 0 indicating it is + * unavailable. + */ + + if (result) { + oem_platform_rev = result->integer.value; + ACPI_FREE(result); + } + + dev_dbg(&dev->dev, "OEM Platform Revision %llu\n", oem_platform_rev); + + return oem_platform_rev == 0; +} + + static int surface_button_add(struct acpi_device *device) { struct surface_button *button; @@ -154,6 +198,9 @@ static int surface_button_add(struct acpi_device *device) strlen(SURFACE_BUTTON_OBJ_NAME))) return -ENODEV; + if (!surface_button_check_MSHW0040(device)) + return -ENODEV; + button = kzalloc(sizeof(struct surface_button), GFP_KERNEL); if (!button) return -ENOMEM; -- cgit v1.2.3 From c394159310d02defcfe63c617f13b0c2974725c5 Mon Sep 17 00:00:00 2001 From: Maximilian Luz Date: Sat, 27 Jul 2019 11:25:38 +0300 Subject: Input: soc_button_array - add support for newer surface devices Power and volume button support for 5th and 6th generation Microsoft Surface devices via soc_button_array. Note that these devices use the same MSHW0040 device as on the Surface Pro 4, however the implementation is different (GPIOs vs. ACPI notifications). Thus some checking is required to ensure we only load this driver on the correct devices. Signed-off-by: Maximilian Luz Signed-off-by: Dmitry Torokhov --- drivers/input/misc/Kconfig | 6 +- drivers/input/misc/soc_button_array.c | 105 ++++++++++++++++++++++++++++++---- 2 files changed, 96 insertions(+), 15 deletions(-) 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/soc_button_array.c b/drivers/input/misc/soc_button_array.c index 5e59f8e57f8e..6f0133fe1546 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; @@ -309,23 +319,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 +370,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 +381,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 +390,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 }, + { } }; -- cgit v1.2.3 From f0fbeaa82028eaa4e2481ab49534c2e1465c99ce Mon Sep 17 00:00:00 2001 From: Marco Felsch Date: Fri, 9 Aug 2019 07:37:32 -0700 Subject: dt-bindings: input: ads7846: fix property description The ti,y-max is used for the maximum value of the Y axis. Signed-off-by: Marco Felsch Reviewed-by: Rob Herring Signed-off-by: Dmitry Torokhov --- Documentation/devicetree/bindings/input/touchscreen/ads7846.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/input/touchscreen/ads7846.txt b/Documentation/devicetree/bindings/input/touchscreen/ads7846.txt index 04413da51391..ce540ddac902 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/ads7846.txt +++ b/Documentation/devicetree/bindings/input/touchscreen/ads7846.txt @@ -52,7 +52,7 @@ Optional properties: ti,x-min Minimum value on the X axis (u16). ti,y-min Minimum value on the Y axis (u16). ti,x-max Maximum value on the X axis (u16). - ti,y-max Minimum value on the Y axis (u16). + ti,y-max Maximum value on the Y axis (u16). ti,pressure-min Minimum reported pressure value (threshold) - u16. ti,pressure-max Maximum reported pressure value (u16). -- cgit v1.2.3 From a2f99330c50bb89fe2625d374fdf22f021163b55 Mon Sep 17 00:00:00 2001 From: Marco Felsch Date: Fri, 9 Aug 2019 07:40:00 -0700 Subject: Input: ads7846 - add support for general touchscreen bindings A few vendor specific bindings are now covered by common bindings. Let the driver parse the common bindings to make use of common inverting and swapping mechnism. Aslo make use of touchscreen_report_pos() to ensure the correct inverting-swapping order. The vendor specific properties are used as default (backward compatibility) and gets overwritten by common bindings. Signed-off-by: Marco Felsch Reviewed-by: Rob Herring Signed-off-by: Dmitry Torokhov --- .../bindings/input/touchscreen/ads7846.txt | 29 ++++++++++++----- drivers/input/touchscreen/ads7846.c | 38 +++++++++++++++++----- 2 files changed, 51 insertions(+), 16 deletions(-) diff --git a/Documentation/devicetree/bindings/input/touchscreen/ads7846.txt b/Documentation/devicetree/bindings/input/touchscreen/ads7846.txt index ce540ddac902..81f6bda97d3c 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/ads7846.txt +++ b/Documentation/devicetree/bindings/input/touchscreen/ads7846.txt @@ -32,7 +32,6 @@ Optional properties: (ADS7846). ti,keep-vref-on set to keep vref on for differential measurements as well - ti,swap-xy swap x and y axis ti,settle-delay-usec Settling time of the analog signals; a function of Vcc and the capacitance on the X/Y drivers. If set to non-zero, @@ -51,13 +50,6 @@ Optional properties: in Ohms (u16). ti,x-min Minimum value on the X axis (u16). ti,y-min Minimum value on the Y axis (u16). - ti,x-max Maximum value on the X axis (u16). - ti,y-max Maximum value on the Y axis (u16). - ti,pressure-min Minimum reported pressure value - (threshold) - u16. - ti,pressure-max Maximum reported pressure value (u16). - ti,debounce-max Max number of additional readings per - sample (u16). ti,debounce-tol Tolerance used for filtering (u16). ti,debounce-rep Additional consecutive good readings required after the first two (u16). @@ -67,7 +59,28 @@ Optional properties: line is connected to. wakeup-source use any event on touchscreen as wakeup event. (Legacy property support: "linux,wakeup") + touchscreen-size-x General touchscreen binding, see [1]. + touchscreen-size-y General touchscreen binding, see [1]. + touchscreen-max-pressure General touchscreen binding, see [1]. + touchscreen-min-pressure General touchscreen binding, see [1]. + touchscreen-average-samples General touchscreen binding, see [1]. + touchscreen-inverted-x General touchscreen binding, see [1]. + touchscreen-inverted-y General touchscreen binding, see [1]. + touchscreen-swapped-x-y General touchscreen binding, see [1]. + +[1] All general touchscreen properties are described in + Documentation/devicetree/bindings/input/touchscreen/touchscreen.txt. +Deprecated properties: + + ti,swap-xy swap x and y axis + ti,x-max Maximum value on the X axis (u16). + ti,y-max Maximum value on the Y axis (u16). + ti,pressure-min Minimum reported pressure value + (threshold) - u16. + ti,pressure-max Maximum reported pressure value (u16). + ti,debounce-max Max number of additional readings per + sample (u16). Example for a TSC2046 chip connected to an McSPI controller of an OMAP SoC:: diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index accbbe8d2966..51ddb204ca1b 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -129,6 +130,8 @@ struct ads7846 { u16 penirq_recheck_delay_usecs; + struct touchscreen_properties core_prop; + struct mutex lock; bool stopped; /* P: lock */ bool disabled; /* P: lock */ @@ -823,17 +826,13 @@ static void ads7846_report_state(struct ads7846 *ts) if (Rt) { struct input_dev *input = ts->input; - if (ts->swap_xy) - swap(x, y); - if (!ts->pendown) { input_report_key(input, BTN_TOUCH, 1); ts->pendown = true; dev_vdbg(&ts->spi->dev, "DOWN\n"); } - input_report_abs(input, ABS_X, x); - input_report_abs(input, ABS_Y, y); + touchscreen_report_pos(input, &ts->core_prop, x, y, false); input_report_abs(input, ABS_PRESSURE, ts->pressure_max - Rt); input_sync(input); @@ -1185,6 +1184,7 @@ static const struct ads7846_platform_data *ads7846_probe_dt(struct device *dev) struct ads7846_platform_data *pdata; struct device_node *node = dev->of_node; const struct of_device_id *match; + u32 value; if (!node) { dev_err(dev, "Device does not have associated DT data\n"); @@ -1223,10 +1223,18 @@ static const struct ads7846_platform_data *ads7846_probe_dt(struct device *dev) of_property_read_u16(node, "ti,x-max", &pdata->x_max); of_property_read_u16(node, "ti,y-max", &pdata->y_max); + /* + * touchscreen-max-pressure gets parsed during + * touchscreen_parse_properties() + */ of_property_read_u16(node, "ti,pressure-min", &pdata->pressure_min); + if (!of_property_read_u32(node, "touchscreen-min-pressure", &value)) + pdata->pressure_min = (u16) value; of_property_read_u16(node, "ti,pressure-max", &pdata->pressure_max); of_property_read_u16(node, "ti,debounce-max", &pdata->debounce_max); + if (!of_property_read_u32(node, "touchscreen-average-samples", &value)) + pdata->debounce_max = (u16) value; of_property_read_u16(node, "ti,debounce-tol", &pdata->debounce_tol); of_property_read_u16(node, "ti,debounce-rep", &pdata->debounce_rep); @@ -1309,10 +1317,7 @@ static int ads7846_probe(struct spi_device *spi) ts->model = pdata->model ? : 7846; ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100; ts->x_plate_ohms = pdata->x_plate_ohms ? : 400; - ts->pressure_max = pdata->pressure_max ? : ~0; - ts->vref_mv = pdata->vref_mv; - ts->swap_xy = pdata->swap_xy; if (pdata->filter != NULL) { if (pdata->filter_init != NULL) { @@ -1364,6 +1369,23 @@ static int ads7846_probe(struct spi_device *spi) input_set_abs_params(input_dev, ABS_PRESSURE, pdata->pressure_min, pdata->pressure_max, 0, 0); + /* + * Parse common framework properties. Must be done here to ensure the + * correct behaviour in case of using the legacy vendor bindings. The + * general binding value overrides the vendor specific one. + */ + touchscreen_parse_properties(ts->input, false, &ts->core_prop); + ts->pressure_max = input_abs_get_max(input_dev, ABS_PRESSURE) ? : ~0; + + /* + * Check if legacy ti,swap-xy binding is used instead of + * touchscreen-swapped-x-y + */ + if (!ts->core_prop.swap_x_y && pdata->swap_xy) { + swap(input_dev->absinfo[ABS_X], input_dev->absinfo[ABS_Y]); + ts->core_prop.swap_x_y = true; + } + ads7846_setup_spi_msg(ts, pdata); ts->reg = regulator_get(&spi->dev, "vcc"); -- cgit v1.2.3 From 26332247fb3fe919a3e51589601ba3de566cc355 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Fri, 9 Aug 2019 09:45:27 -0700 Subject: Input: synaptics - fix a typo This should be 'synaptics', not 'synpatics' Signed-off-by: Christophe JAILLET Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/synaptics.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index b77b18c9ad02..a0e53b34156c 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -191,7 +191,7 @@ static const char * const forcepad_pnp_ids[] = { }; /* - * Send a command to the synpatics touchpad by special commands + * Send a command to the synaptics touchpad by special commands */ static int synaptics_send_cmd(struct psmouse *psmouse, u8 cmd, u8 *param) { -- cgit v1.2.3 From 060157e1dbc133075a2e20786d6ff6d4b41909f9 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 9 Aug 2019 14:55:43 -0700 Subject: Input: remove w90x900 keyboard driver The ARM w90x900 platform is getting removed, so this driver is obsolete. Signed-off-by: Arnd Bergmann Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/Kconfig | 11 -- drivers/input/keyboard/Makefile | 1 - drivers/input/keyboard/w90p910_keypad.c | 264 --------------------------- include/linux/platform_data/keypad-w90p910.h | 16 -- 4 files changed, 292 deletions(-) delete mode 100644 drivers/input/keyboard/w90p910_keypad.c delete mode 100644 include/linux/platform_data/keypad-w90p910.h diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 8e9c3ea9d5e7..c1da129a4eb5 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -731,17 +731,6 @@ config KEYBOARD_XTKBD To compile this driver as a module, choose M here: the module will be called xtkbd. -config KEYBOARD_W90P910 - tristate "W90P910 Matrix Keypad support" - depends on ARCH_W90X900 - select INPUT_MATRIXKMAP - help - Say Y here to enable the matrix keypad on evaluation board - based on W90P910. - - To compile this driver as a module, choose M here: the - module will be called w90p910_keypad. - config KEYBOARD_CROS_EC tristate "ChromeOS EC keyboard" select INPUT_MATRIXKMAP diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 06a0af6efeae..9510325c0c5d 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -68,4 +68,3 @@ obj-$(CONFIG_KEYBOARD_TEGRA) += tegra-kbc.o obj-$(CONFIG_KEYBOARD_TM2_TOUCHKEY) += tm2-touchkey.o obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o -obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o diff --git a/drivers/input/keyboard/w90p910_keypad.c b/drivers/input/keyboard/w90p910_keypad.c deleted file mode 100644 index c88d05d6108a..000000000000 --- a/drivers/input/keyboard/w90p910_keypad.c +++ /dev/null @@ -1,264 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2008-2009 Nuvoton technology corporation. - * - * Wan ZongShun - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -/* Keypad Interface Control Registers */ -#define KPI_CONF 0x00 -#define KPI_3KCONF 0x04 -#define KPI_LPCONF 0x08 -#define KPI_STATUS 0x0C - -#define IS1KEY (0x01 << 16) -#define INTTR (0x01 << 21) -#define KEY0R (0x0f << 3) -#define KEY0C 0x07 -#define DEBOUNCE_BIT 0x08 -#define KSIZE0 (0x01 << 16) -#define KSIZE1 (0x01 << 17) -#define KPSEL (0x01 << 19) -#define ENKP (0x01 << 18) - -#define KGET_RAW(n) (((n) & KEY0R) >> 3) -#define KGET_COLUMN(n) ((n) & KEY0C) - -#define W90P910_NUM_ROWS 8 -#define W90P910_NUM_COLS 8 -#define W90P910_ROW_SHIFT 3 - -struct w90p910_keypad { - const struct w90p910_keypad_platform_data *pdata; - struct clk *clk; - struct input_dev *input_dev; - void __iomem *mmio_base; - int irq; - unsigned short keymap[W90P910_NUM_ROWS * W90P910_NUM_COLS]; -}; - -static void w90p910_keypad_scan_matrix(struct w90p910_keypad *keypad, - unsigned int status) -{ - struct input_dev *input_dev = keypad->input_dev; - unsigned int row = KGET_RAW(status); - unsigned int col = KGET_COLUMN(status); - unsigned int code = MATRIX_SCAN_CODE(row, col, W90P910_ROW_SHIFT); - unsigned int key = keypad->keymap[code]; - - input_event(input_dev, EV_MSC, MSC_SCAN, code); - input_report_key(input_dev, key, 1); - input_sync(input_dev); - - input_event(input_dev, EV_MSC, MSC_SCAN, code); - input_report_key(input_dev, key, 0); - input_sync(input_dev); -} - -static irqreturn_t w90p910_keypad_irq_handler(int irq, void *dev_id) -{ - struct w90p910_keypad *keypad = dev_id; - unsigned int kstatus, val; - - kstatus = __raw_readl(keypad->mmio_base + KPI_STATUS); - - val = INTTR | IS1KEY; - - if (kstatus & val) - w90p910_keypad_scan_matrix(keypad, kstatus); - - return IRQ_HANDLED; -} - -static int w90p910_keypad_open(struct input_dev *dev) -{ - struct w90p910_keypad *keypad = input_get_drvdata(dev); - const struct w90p910_keypad_platform_data *pdata = keypad->pdata; - unsigned int val, config; - - /* Enable unit clock */ - clk_enable(keypad->clk); - - val = __raw_readl(keypad->mmio_base + KPI_CONF); - val |= (KPSEL | ENKP); - val &= ~(KSIZE0 | KSIZE1); - - config = pdata->prescale | (pdata->debounce << DEBOUNCE_BIT); - - val |= config; - - __raw_writel(val, keypad->mmio_base + KPI_CONF); - - return 0; -} - -static void w90p910_keypad_close(struct input_dev *dev) -{ - struct w90p910_keypad *keypad = input_get_drvdata(dev); - - /* Disable clock unit */ - clk_disable(keypad->clk); -} - -static int w90p910_keypad_probe(struct platform_device *pdev) -{ - const struct w90p910_keypad_platform_data *pdata = - dev_get_platdata(&pdev->dev); - const struct matrix_keymap_data *keymap_data; - struct w90p910_keypad *keypad; - struct input_dev *input_dev; - struct resource *res; - int irq; - int error; - - if (!pdata) { - dev_err(&pdev->dev, "no platform data defined\n"); - return -EINVAL; - } - - keymap_data = pdata->keymap_data; - - irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "failed to get keypad irq\n"); - return -ENXIO; - } - - keypad = kzalloc(sizeof(struct w90p910_keypad), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!keypad || !input_dev) { - dev_err(&pdev->dev, "failed to allocate driver data\n"); - error = -ENOMEM; - goto failed_free; - } - - keypad->pdata = pdata; - keypad->input_dev = input_dev; - keypad->irq = irq; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res == NULL) { - dev_err(&pdev->dev, "failed to get I/O memory\n"); - error = -ENXIO; - goto failed_free; - } - - res = request_mem_region(res->start, resource_size(res), pdev->name); - if (res == NULL) { - dev_err(&pdev->dev, "failed to request I/O memory\n"); - error = -EBUSY; - goto failed_free; - } - - keypad->mmio_base = ioremap(res->start, resource_size(res)); - if (keypad->mmio_base == NULL) { - dev_err(&pdev->dev, "failed to remap I/O memory\n"); - error = -ENXIO; - goto failed_free_res; - } - - keypad->clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(keypad->clk)) { - dev_err(&pdev->dev, "failed to get keypad clock\n"); - error = PTR_ERR(keypad->clk); - goto failed_free_io; - } - - /* set multi-function pin for w90p910 kpi. */ - mfp_set_groupi(&pdev->dev); - - input_dev->name = pdev->name; - input_dev->id.bustype = BUS_HOST; - input_dev->open = w90p910_keypad_open; - input_dev->close = w90p910_keypad_close; - input_dev->dev.parent = &pdev->dev; - - error = matrix_keypad_build_keymap(keymap_data, NULL, - W90P910_NUM_ROWS, W90P910_NUM_COLS, - keypad->keymap, input_dev); - if (error) { - dev_err(&pdev->dev, "failed to build keymap\n"); - goto failed_put_clk; - } - - error = request_irq(keypad->irq, w90p910_keypad_irq_handler, - 0, pdev->name, keypad); - if (error) { - dev_err(&pdev->dev, "failed to request IRQ\n"); - goto failed_put_clk; - } - - __set_bit(EV_REP, input_dev->evbit); - input_set_capability(input_dev, EV_MSC, MSC_SCAN); - input_set_drvdata(input_dev, keypad); - - /* Register the input device */ - error = input_register_device(input_dev); - if (error) { - dev_err(&pdev->dev, "failed to register input device\n"); - goto failed_free_irq; - } - - platform_set_drvdata(pdev, keypad); - return 0; - -failed_free_irq: - free_irq(irq, keypad); -failed_put_clk: - clk_put(keypad->clk); -failed_free_io: - iounmap(keypad->mmio_base); -failed_free_res: - release_mem_region(res->start, resource_size(res)); -failed_free: - input_free_device(input_dev); - kfree(keypad); - return error; -} - -static int w90p910_keypad_remove(struct platform_device *pdev) -{ - struct w90p910_keypad *keypad = platform_get_drvdata(pdev); - struct resource *res; - - free_irq(keypad->irq, keypad); - - clk_put(keypad->clk); - - input_unregister_device(keypad->input_dev); - - iounmap(keypad->mmio_base); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(res->start, resource_size(res)); - - kfree(keypad); - - return 0; -} - -static struct platform_driver w90p910_keypad_driver = { - .probe = w90p910_keypad_probe, - .remove = w90p910_keypad_remove, - .driver = { - .name = "nuc900-kpi", - }, -}; -module_platform_driver(w90p910_keypad_driver); - -MODULE_AUTHOR("Wan ZongShun "); -MODULE_DESCRIPTION("w90p910 keypad driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:nuc900-keypad"); diff --git a/include/linux/platform_data/keypad-w90p910.h b/include/linux/platform_data/keypad-w90p910.h deleted file mode 100644 index 206ca4ecd93f..000000000000 --- a/include/linux/platform_data/keypad-w90p910.h +++ /dev/null @@ -1,16 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __ASM_ARCH_W90P910_KEYPAD_H -#define __ASM_ARCH_W90P910_KEYPAD_H - -#include - -extern void mfp_set_groupi(struct device *dev); - -struct w90p910_keypad_platform_data { - const struct matrix_keymap_data *keymap_data; - - unsigned int prescale; - unsigned int debounce; -}; - -#endif /* __ASM_ARCH_W90P910_KEYPAD_H */ -- cgit v1.2.3 From 6bd744b723d229ac38eeea2cf0717d8cd2858032 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 9 Aug 2019 14:56:02 -0700 Subject: Input: remove w90x900 touchscreen driver The ARM w90x900 platform is getting removed, so this driver is obsolete. Signed-off-by: Arnd Bergmann Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/Kconfig | 9 - drivers/input/touchscreen/Makefile | 1 - drivers/input/touchscreen/w90p910_ts.c | 331 --------------------------------- 3 files changed, 341 deletions(-) delete mode 100644 drivers/input/touchscreen/w90p910_ts.c diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index fb91f2d4049e..46ad9090493b 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -1112,15 +1112,6 @@ config TOUCHSCREEN_TSC2007_IIO or ambient light monitoring), temperature and raw input values. -config TOUCHSCREEN_W90X900 - tristate "W90P910 touchscreen driver" - depends on ARCH_W90X900 - help - Say Y here if you have a W90P910 based touchscreen. - - To compile this driver as a module, choose M here: the - module will be called w90p910_ts. - config TOUCHSCREEN_PCAP tristate "Motorola PCAP touchscreen" depends on EZX_PCAP diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 084a596a0c8b..94c6162409b3 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -102,7 +102,6 @@ wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712) += wm9712.o wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9713) += wm9713.o obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o -obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o obj-$(CONFIG_TOUCHSCREEN_SX8654) += sx8654.o obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o obj-$(CONFIG_TOUCHSCREEN_ZET6223) += zet6223.o diff --git a/drivers/input/touchscreen/w90p910_ts.c b/drivers/input/touchscreen/w90p910_ts.c deleted file mode 100644 index 7893d7fa398c..000000000000 --- a/drivers/input/touchscreen/w90p910_ts.c +++ /dev/null @@ -1,331 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2008 Nuvoton technology corporation. - * - * Wan ZongShun - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -/* ADC controller bit defines */ -#define ADC_DELAY 0xf00 -#define ADC_DOWN 0x01 -#define ADC_TSC_Y (0x01 << 8) -#define ADC_TSC_X (0x00 << 8) -#define TSC_FOURWIRE (~(0x03 << 1)) -#define ADC_CLK_EN (0x01 << 28) /* ADC clock enable */ -#define ADC_READ_CON (0x01 << 12) -#define ADC_CONV (0x01 << 13) -#define ADC_SEMIAUTO (0x01 << 14) -#define ADC_WAITTRIG (0x03 << 14) -#define ADC_RST1 (0x01 << 16) -#define ADC_RST0 (0x00 << 16) -#define ADC_EN (0x01 << 17) -#define ADC_INT (0x01 << 18) -#define WT_INT (0x01 << 20) -#define ADC_INT_EN (0x01 << 21) -#define LVD_INT_EN (0x01 << 22) -#define WT_INT_EN (0x01 << 23) -#define ADC_DIV (0x04 << 1) /* div = 6 */ - -enum ts_state { - TS_WAIT_NEW_PACKET, /* We are waiting next touch report */ - TS_WAIT_X_COORD, /* We are waiting for ADC to report X coord */ - TS_WAIT_Y_COORD, /* We are waiting for ADC to report Y coord */ - TS_IDLE, /* Input device is closed, don't do anything */ -}; - -struct w90p910_ts { - struct input_dev *input; - struct timer_list timer; - struct clk *clk; - int irq_num; - void __iomem *ts_reg; - spinlock_t lock; - enum ts_state state; -}; - -static void w90p910_report_event(struct w90p910_ts *w90p910_ts, bool down) -{ - struct input_dev *dev = w90p910_ts->input; - - if (down) { - input_report_abs(dev, ABS_X, - __raw_readl(w90p910_ts->ts_reg + 0x0c)); - input_report_abs(dev, ABS_Y, - __raw_readl(w90p910_ts->ts_reg + 0x10)); - } - - input_report_key(dev, BTN_TOUCH, down); - input_sync(dev); -} - -static void w90p910_prepare_x_reading(struct w90p910_ts *w90p910_ts) -{ - unsigned long ctlreg; - - __raw_writel(ADC_TSC_X, w90p910_ts->ts_reg + 0x04); - ctlreg = __raw_readl(w90p910_ts->ts_reg); - ctlreg &= ~(ADC_WAITTRIG | WT_INT | WT_INT_EN); - ctlreg |= ADC_SEMIAUTO | ADC_INT_EN | ADC_CONV; - __raw_writel(ctlreg, w90p910_ts->ts_reg); - - w90p910_ts->state = TS_WAIT_X_COORD; -} - -static void w90p910_prepare_y_reading(struct w90p910_ts *w90p910_ts) -{ - unsigned long ctlreg; - - __raw_writel(ADC_TSC_Y, w90p910_ts->ts_reg + 0x04); - ctlreg = __raw_readl(w90p910_ts->ts_reg); - ctlreg &= ~(ADC_WAITTRIG | ADC_INT | WT_INT_EN); - ctlreg |= ADC_SEMIAUTO | ADC_INT_EN | ADC_CONV; - __raw_writel(ctlreg, w90p910_ts->ts_reg); - - w90p910_ts->state = TS_WAIT_Y_COORD; -} - -static void w90p910_prepare_next_packet(struct w90p910_ts *w90p910_ts) -{ - unsigned long ctlreg; - - ctlreg = __raw_readl(w90p910_ts->ts_reg); - ctlreg &= ~(ADC_INT | ADC_INT_EN | ADC_SEMIAUTO | ADC_CONV); - ctlreg |= ADC_WAITTRIG | WT_INT_EN; - __raw_writel(ctlreg, w90p910_ts->ts_reg); - - w90p910_ts->state = TS_WAIT_NEW_PACKET; -} - -static irqreturn_t w90p910_ts_interrupt(int irq, void *dev_id) -{ - struct w90p910_ts *w90p910_ts = dev_id; - unsigned long flags; - - spin_lock_irqsave(&w90p910_ts->lock, flags); - - switch (w90p910_ts->state) { - case TS_WAIT_NEW_PACKET: - /* - * The controller only generates interrupts when pen - * is down. - */ - del_timer(&w90p910_ts->timer); - w90p910_prepare_x_reading(w90p910_ts); - break; - - - case TS_WAIT_X_COORD: - w90p910_prepare_y_reading(w90p910_ts); - break; - - case TS_WAIT_Y_COORD: - w90p910_report_event(w90p910_ts, true); - w90p910_prepare_next_packet(w90p910_ts); - mod_timer(&w90p910_ts->timer, jiffies + msecs_to_jiffies(100)); - break; - - case TS_IDLE: - break; - } - - spin_unlock_irqrestore(&w90p910_ts->lock, flags); - - return IRQ_HANDLED; -} - -static void w90p910_check_pen_up(struct timer_list *t) -{ - struct w90p910_ts *w90p910_ts = from_timer(w90p910_ts, t, timer); - unsigned long flags; - - spin_lock_irqsave(&w90p910_ts->lock, flags); - - if (w90p910_ts->state == TS_WAIT_NEW_PACKET && - !(__raw_readl(w90p910_ts->ts_reg + 0x04) & ADC_DOWN)) { - - w90p910_report_event(w90p910_ts, false); - } - - spin_unlock_irqrestore(&w90p910_ts->lock, flags); -} - -static int w90p910_open(struct input_dev *dev) -{ - struct w90p910_ts *w90p910_ts = input_get_drvdata(dev); - unsigned long val; - - /* enable the ADC clock */ - clk_enable(w90p910_ts->clk); - - __raw_writel(ADC_RST1, w90p910_ts->ts_reg); - msleep(1); - __raw_writel(ADC_RST0, w90p910_ts->ts_reg); - msleep(1); - - /* set delay and screen type */ - val = __raw_readl(w90p910_ts->ts_reg + 0x04); - __raw_writel(val & TSC_FOURWIRE, w90p910_ts->ts_reg + 0x04); - __raw_writel(ADC_DELAY, w90p910_ts->ts_reg + 0x08); - - w90p910_ts->state = TS_WAIT_NEW_PACKET; - wmb(); - - /* set trigger mode */ - val = __raw_readl(w90p910_ts->ts_reg); - val |= ADC_WAITTRIG | ADC_DIV | ADC_EN | WT_INT_EN; - __raw_writel(val, w90p910_ts->ts_reg); - - return 0; -} - -static void w90p910_close(struct input_dev *dev) -{ - struct w90p910_ts *w90p910_ts = input_get_drvdata(dev); - unsigned long val; - - /* disable trigger mode */ - - spin_lock_irq(&w90p910_ts->lock); - - w90p910_ts->state = TS_IDLE; - - val = __raw_readl(w90p910_ts->ts_reg); - val &= ~(ADC_WAITTRIG | ADC_DIV | ADC_EN | WT_INT_EN | ADC_INT_EN); - __raw_writel(val, w90p910_ts->ts_reg); - - spin_unlock_irq(&w90p910_ts->lock); - - /* Now that interrupts are shut off we can safely delete timer */ - del_timer_sync(&w90p910_ts->timer); - - /* stop the ADC clock */ - clk_disable(w90p910_ts->clk); -} - -static int w90x900ts_probe(struct platform_device *pdev) -{ - struct w90p910_ts *w90p910_ts; - struct input_dev *input_dev; - struct resource *res; - int err; - - w90p910_ts = kzalloc(sizeof(struct w90p910_ts), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!w90p910_ts || !input_dev) { - err = -ENOMEM; - goto fail1; - } - - w90p910_ts->input = input_dev; - w90p910_ts->state = TS_IDLE; - spin_lock_init(&w90p910_ts->lock); - timer_setup(&w90p910_ts->timer, w90p910_check_pen_up, 0); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - err = -ENXIO; - goto fail1; - } - - if (!request_mem_region(res->start, resource_size(res), - pdev->name)) { - err = -EBUSY; - goto fail1; - } - - w90p910_ts->ts_reg = ioremap(res->start, resource_size(res)); - if (!w90p910_ts->ts_reg) { - err = -ENOMEM; - goto fail2; - } - - w90p910_ts->clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(w90p910_ts->clk)) { - err = PTR_ERR(w90p910_ts->clk); - goto fail3; - } - - input_dev->name = "W90P910 TouchScreen"; - input_dev->phys = "w90p910ts/event0"; - input_dev->id.bustype = BUS_HOST; - input_dev->id.vendor = 0x0005; - input_dev->id.product = 0x0001; - input_dev->id.version = 0x0100; - input_dev->dev.parent = &pdev->dev; - input_dev->open = w90p910_open; - input_dev->close = w90p910_close; - - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); - - input_set_abs_params(input_dev, ABS_X, 0, 0x400, 0, 0); - input_set_abs_params(input_dev, ABS_Y, 0, 0x400, 0, 0); - - input_set_drvdata(input_dev, w90p910_ts); - - w90p910_ts->irq_num = platform_get_irq(pdev, 0); - if (request_irq(w90p910_ts->irq_num, w90p910_ts_interrupt, - 0, "w90p910ts", w90p910_ts)) { - err = -EBUSY; - goto fail4; - } - - err = input_register_device(w90p910_ts->input); - if (err) - goto fail5; - - platform_set_drvdata(pdev, w90p910_ts); - - return 0; - -fail5: free_irq(w90p910_ts->irq_num, w90p910_ts); -fail4: clk_put(w90p910_ts->clk); -fail3: iounmap(w90p910_ts->ts_reg); -fail2: release_mem_region(res->start, resource_size(res)); -fail1: input_free_device(input_dev); - kfree(w90p910_ts); - return err; -} - -static int w90x900ts_remove(struct platform_device *pdev) -{ - struct w90p910_ts *w90p910_ts = platform_get_drvdata(pdev); - struct resource *res; - - free_irq(w90p910_ts->irq_num, w90p910_ts); - del_timer_sync(&w90p910_ts->timer); - iounmap(w90p910_ts->ts_reg); - - clk_put(w90p910_ts->clk); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(res->start, resource_size(res)); - - input_unregister_device(w90p910_ts->input); - kfree(w90p910_ts); - - return 0; -} - -static struct platform_driver w90x900ts_driver = { - .probe = w90x900ts_probe, - .remove = w90x900ts_remove, - .driver = { - .name = "nuc900-ts", - }, -}; -module_platform_driver(w90x900ts_driver); - -MODULE_AUTHOR("Wan ZongShun "); -MODULE_DESCRIPTION("w90p910 touch screen driver!"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:nuc900-ts"); -- cgit v1.2.3 From cf1b2a208d2e1b4c436a56672d09d12c34c06384 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 11 Aug 2019 23:41:23 -0700 Subject: Input: gpio_keys - convert driver to use dev_groups Drivers now have the option to have the driver core create and remove any needed sysfs attribute files. So take advantage of that and do not register "by hand" a bunch of sysfs files. Signed-off-by: Greg Kroah-Hartman Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/gpio_keys.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index 03f4d152f6b7..1373dc5b0765 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -351,10 +351,7 @@ static struct attribute *gpio_keys_attrs[] = { &dev_attr_disabled_switches.attr, NULL, }; - -static const struct attribute_group gpio_keys_attr_group = { - .attrs = gpio_keys_attrs, -}; +ATTRIBUTE_GROUPS(gpio_keys); static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata) { @@ -851,13 +848,6 @@ static int gpio_keys_probe(struct platform_device *pdev) fwnode_handle_put(child); - error = devm_device_add_group(dev, &gpio_keys_attr_group); - if (error) { - dev_err(dev, "Unable to export keys/switches, error: %d\n", - error); - return error; - } - error = input_register_device(input); if (error) { dev_err(dev, "Unable to register input device, error: %d\n", @@ -1026,6 +1016,7 @@ static struct platform_driver gpio_keys_device_driver = { .name = "gpio-keys", .pm = &gpio_keys_pm_ops, .of_match_table = gpio_keys_of_match, + .dev_groups = gpio_keys_groups, } }; -- cgit v1.2.3 From d99995a4f0f189731695efad4135daf04df53075 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 11 Aug 2019 23:42:31 -0700 Subject: Input: axp20x-pek - convert driver to use dev_groups Drivers now have the option to have the driver core create and remove any needed sysfs attribute files. So take advantage of that and do not register "by hand" a sysfs group of attributes. Signed-off-by: Greg Kroah-Hartman Signed-off-by: Dmitry Torokhov --- drivers/input/misc/axp20x-pek.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/drivers/input/misc/axp20x-pek.c b/drivers/input/misc/axp20x-pek.c index debeeaeb8812..235925b28772 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) { @@ -356,13 +353,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 +401,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); -- cgit v1.2.3 From 6e57ce76d0622aa4d790edd8e49f3704c48707c9 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Sun, 11 Aug 2019 23:59:51 -0700 Subject: Input: mpr121 - switch to use device_property_count_u32() Use use device_property_count_u32() directly, that makes code neater. Signed-off-by: Andy Shevchenko Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/mpr121_touchkey.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/input/keyboard/mpr121_touchkey.c b/drivers/input/keyboard/mpr121_touchkey.c index e9ceaa16b46a..ee80de44ce3f 100644 --- a/drivers/input/keyboard/mpr121_touchkey.c +++ b/drivers/input/keyboard/mpr121_touchkey.c @@ -253,8 +253,7 @@ static int mpr_touchkey_probe(struct i2c_client *client, mpr121->client = client; mpr121->input_dev = input_dev; - mpr121->keycount = device_property_read_u32_array(dev, "linux,keycodes", - NULL, 0); + mpr121->keycount = device_property_count_u32(dev, "linux,keycodes"); if (mpr121->keycount > MPR121_MAX_KEY_COUNT) { dev_err(dev, "too many keys defined (%d)\n", mpr121->keycount); return -EINVAL; -- cgit v1.2.3 From 104c995fd6ab7c2bdb275a54334123184fd2efb2 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 12 Aug 2019 00:00:16 -0700 Subject: Input: hideep - switch to use device_property_count_u32() Use use device_property_count_u32() directly, that makes code neater. Signed-off-by: Andy Shevchenko Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/hideep.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/input/touchscreen/hideep.c b/drivers/input/touchscreen/hideep.c index 84fbbf415c43..ddad4a82a5e5 100644 --- a/drivers/input/touchscreen/hideep.c +++ b/drivers/input/touchscreen/hideep.c @@ -811,8 +811,7 @@ static int hideep_init_input(struct hideep_ts *ts) if (error) return error; - ts->key_num = device_property_read_u32_array(dev, "linux,keycodes", - NULL, 0); + ts->key_num = device_property_count_u32(dev, "linux,keycodes"); if (ts->key_num > HIDEEP_KEY_MAX) { dev_err(dev, "too many keys defined: %d\n", ts->key_num); -- cgit v1.2.3 From 9ed05c94f20d504b6f0653ae981d171a801ae707 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 12 Aug 2019 00:00:35 -0700 Subject: Input: atmel_mxt_ts - switch to use device_property_count_u32() Use use device_property_count_u32() directly, that makes code neater. Signed-off-by: Andy Shevchenko Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/atmel_mxt_ts.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 4a5f482cf1af..24c4b691b1c9 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -2990,8 +2990,7 @@ static int mxt_parse_device_properties(struct mxt_data *data) int error; if (device_property_present(dev, keymap_property)) { - n_keys = device_property_read_u32_array(dev, keymap_property, - NULL, 0); + n_keys = device_property_count_u32(dev, keymap_property); if (n_keys <= 0) { error = n_keys < 0 ? n_keys : -EINVAL; dev_err(dev, "invalid/malformed '%s' property: %d\n", -- cgit v1.2.3 From 656d29ce0f44163dbb12ff30b5a1a50644040500 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 12 Aug 2019 00:00:55 -0700 Subject: Input: matrix-keymap - switch to use device_property_count_u32() Use use device_property_count_u32() directly, that makes code neater. Signed-off-by: Andy Shevchenko Signed-off-by: Dmitry Torokhov --- drivers/input/matrix-keymap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/matrix-keymap.c b/drivers/input/matrix-keymap.c index da312be94c3a..4fa53423f56c 100644 --- a/drivers/input/matrix-keymap.c +++ b/drivers/input/matrix-keymap.c @@ -81,7 +81,7 @@ static int matrix_keypad_parse_keymap(const char *propname, if (!propname) propname = "linux,keymap"; - size = device_property_read_u32_array(dev, propname, NULL, 0); + size = device_property_count_u32(dev, propname); if (size <= 0) { dev_err(dev, "missing or malformed property %s: %d\n", propname, size); -- cgit v1.2.3 From 042cc4c778e1aa56f83ebe44b6f959c204861f08 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 12 Aug 2019 00:05:21 -0700 Subject: Input: edt-ft5x06 - no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Signed-off-by: Greg Kroah-Hartman Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/edt-ft5x06.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index 3cc4341bbdff..5525f1fb1526 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -764,8 +764,6 @@ edt_ft5x06_ts_prepare_debugfs(struct edt_ft5x06_ts_data *tsdata, const char *debugfs_name) { tsdata->debug_dir = debugfs_create_dir(debugfs_name, NULL); - if (!tsdata->debug_dir) - return; debugfs_create_u16("num_x", S_IRUSR, tsdata->debug_dir, &tsdata->num_x); debugfs_create_u16("num_y", S_IRUSR, tsdata->debug_dir, &tsdata->num_y); -- cgit v1.2.3 From f5d4c647d0ddcf4ffcb9ff584fba87a976addcbd Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 12 Aug 2019 00:06:38 -0700 Subject: Input: applespi - no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Signed-off-by: Greg Kroah-Hartman Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/applespi.c | 30 ++++++------------------------ 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/drivers/input/keyboard/applespi.c b/drivers/input/keyboard/applespi.c index 584289b67fb3..d38398526965 100644 --- a/drivers/input/keyboard/applespi.c +++ b/drivers/input/keyboard/applespi.c @@ -1797,30 +1797,12 @@ static int applespi_probe(struct spi_device *spi) /* set up debugfs entries for touchpad dimensions logging */ applespi->debugfs_root = debugfs_create_dir("applespi", NULL); - if (IS_ERR(applespi->debugfs_root)) { - if (PTR_ERR(applespi->debugfs_root) != -ENODEV) - dev_warn(&applespi->spi->dev, - "Error creating debugfs root entry (%ld)\n", - PTR_ERR(applespi->debugfs_root)); - } else { - struct dentry *ret; - - ret = debugfs_create_bool("enable_tp_dim", 0600, - applespi->debugfs_root, - &applespi->debug_tp_dim); - if (IS_ERR(ret)) - dev_dbg(&applespi->spi->dev, - "Error creating debugfs entry enable_tp_dim (%ld)\n", - PTR_ERR(ret)); - - ret = debugfs_create_file("tp_dim", 0400, - applespi->debugfs_root, applespi, - &applespi_tp_dim_fops); - if (IS_ERR(ret)) - dev_dbg(&applespi->spi->dev, - "Error creating debugfs entry tp_dim (%ld)\n", - PTR_ERR(ret)); - } + + debugfs_create_bool("enable_tp_dim", 0600, applespi->debugfs_root, + &applespi->debug_tp_dim); + + debugfs_create_file("tp_dim", 0400, applespi->debugfs_root, applespi, + &applespi_tp_dim_fops); return 0; } -- cgit v1.2.3 From 0bec8b7e5ca1a629f26173691526432f9d7cf8c1 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 14 Aug 2019 10:46:38 -0700 Subject: Input: remove dev_err() usage after platform_get_irq() We don't need dev_err() messages when platform_get_irq() fails now that platform_get_irq() prints an error message itself when something goes wrong. Let's remove these prints with a simple semantic patch. // @@ expression ret; struct platform_device *E; @@ ret = ( platform_get_irq(E, ...) | platform_get_irq_byname(E, ...) ); if ( \( ret < 0 \| ret <= 0 \) ) { ( -if (ret != -EPROBE_DEFER) -{ ... -dev_err(...); -... } | ... -dev_err(...); ) ... } // While we're here, remove braces on if statements that only have one statement (manually). Signed-off-by: Stephen Boyd Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/bcm-keypad.c | 4 +--- drivers/input/keyboard/davinci_keyscan.c | 1 - drivers/input/keyboard/imx_keypad.c | 4 +--- drivers/input/keyboard/lpc32xx-keys.c | 4 +--- drivers/input/keyboard/nomadik-ske-keypad.c | 4 +--- drivers/input/keyboard/nspire-keypad.c | 4 +--- drivers/input/keyboard/opencores-kbd.c | 4 +--- drivers/input/keyboard/pmic8xxx-keypad.c | 8 ++------ drivers/input/keyboard/pxa27x_keypad.c | 4 +--- drivers/input/keyboard/pxa930_rotary.c | 4 +--- drivers/input/keyboard/sh_keysc.c | 4 +--- drivers/input/keyboard/snvs_pwrkey.c | 4 +--- drivers/input/keyboard/spear-keyboard.c | 4 +--- drivers/input/keyboard/st-keyscan.c | 4 +--- drivers/input/keyboard/tegra-kbc.c | 4 +--- drivers/input/misc/88pm80x_onkey.c | 1 - drivers/input/misc/88pm860x_onkey.c | 4 +--- drivers/input/misc/ab8500-ponkey.c | 8 ++------ drivers/input/misc/axp20x-pek.c | 10 ++-------- drivers/input/misc/da9055_onkey.c | 5 +---- drivers/input/misc/da9063_onkey.c | 7 ++----- drivers/input/misc/e3x0-button.c | 10 ++-------- drivers/input/misc/hisi_powerkey.c | 8 ++------ drivers/input/misc/max8925_onkey.c | 8 ++------ drivers/input/misc/pm8941-pwrkey.c | 4 +--- drivers/input/misc/rk805-pwrkey.c | 8 ++------ drivers/input/misc/stpmic1_onkey.c | 10 ++-------- drivers/input/misc/tps65218-pwrbutton.c | 4 +--- drivers/input/misc/twl6040-vibra.c | 4 +--- drivers/input/mouse/pxa930_trkball.c | 4 +--- drivers/input/serio/arc_ps2.c | 4 +--- drivers/input/serio/ps2-gpio.c | 2 -- drivers/input/touchscreen/88pm860x-ts.c | 4 +--- drivers/input/touchscreen/bcm_iproc_tsc.c | 4 +--- drivers/input/touchscreen/fsl-imx25-tcq.c | 4 +--- drivers/input/touchscreen/imx6ul_tsc.c | 8 ++------ drivers/input/touchscreen/lpc32xx_ts.c | 4 +--- 37 files changed, 44 insertions(+), 142 deletions(-) diff --git a/drivers/input/keyboard/bcm-keypad.c b/drivers/input/keyboard/bcm-keypad.c index e1cf63ee148f..2b771c3a5578 100644 --- a/drivers/input/keyboard/bcm-keypad.c +++ b/drivers/input/keyboard/bcm-keypad.c @@ -413,10 +413,8 @@ static int bcm_kp_probe(struct platform_device *pdev) bcm_kp_stop(kp); kp->irq = platform_get_irq(pdev, 0); - if (kp->irq < 0) { - dev_err(&pdev->dev, "no IRQ specified\n"); + if (kp->irq < 0) return -EINVAL; - } error = devm_request_threaded_irq(&pdev->dev, kp->irq, NULL, bcm_kp_isr_thread, diff --git a/drivers/input/keyboard/davinci_keyscan.c b/drivers/input/keyboard/davinci_keyscan.c index 1d94928db922..f489cd585b33 100644 --- a/drivers/input/keyboard/davinci_keyscan.c +++ b/drivers/input/keyboard/davinci_keyscan.c @@ -192,7 +192,6 @@ static int __init davinci_ks_probe(struct platform_device *pdev) davinci_ks->irq = platform_get_irq(pdev, 0); if (davinci_ks->irq < 0) { - dev_err(dev, "no key scan irq\n"); error = davinci_ks->irq; goto fail2; } diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c index 97500a2de2d5..5a46d113e909 100644 --- a/drivers/input/keyboard/imx_keypad.c +++ b/drivers/input/keyboard/imx_keypad.c @@ -430,10 +430,8 @@ static int imx_keypad_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "no irq defined in platform data\n"); + if (irq < 0) return irq; - } input_dev = devm_input_allocate_device(&pdev->dev); if (!input_dev) { diff --git a/drivers/input/keyboard/lpc32xx-keys.c b/drivers/input/keyboard/lpc32xx-keys.c index a34e3271b0c9..348af2aeb5de 100644 --- a/drivers/input/keyboard/lpc32xx-keys.c +++ b/drivers/input/keyboard/lpc32xx-keys.c @@ -172,10 +172,8 @@ static int lpc32xx_kscan_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "failed to get platform irq\n"); + if (irq < 0) return -EINVAL; - } kscandat = devm_kzalloc(&pdev->dev, sizeof(*kscandat), GFP_KERNEL); diff --git a/drivers/input/keyboard/nomadik-ske-keypad.c b/drivers/input/keyboard/nomadik-ske-keypad.c index fa265fdce2c4..608446e14614 100644 --- a/drivers/input/keyboard/nomadik-ske-keypad.c +++ b/drivers/input/keyboard/nomadik-ske-keypad.c @@ -235,10 +235,8 @@ static int __init ske_keypad_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "failed to get keypad irq\n"); + if (irq < 0) return -EINVAL; - } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { diff --git a/drivers/input/keyboard/nspire-keypad.c b/drivers/input/keyboard/nspire-keypad.c index 57eac91ecd76..63d5e488137d 100644 --- a/drivers/input/keyboard/nspire-keypad.c +++ b/drivers/input/keyboard/nspire-keypad.c @@ -165,10 +165,8 @@ static int nspire_keypad_probe(struct platform_device *pdev) int error; irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "failed to get keypad irq\n"); + if (irq < 0) return -EINVAL; - } keypad = devm_kzalloc(&pdev->dev, sizeof(struct nspire_keypad), GFP_KERNEL); diff --git a/drivers/input/keyboard/opencores-kbd.c b/drivers/input/keyboard/opencores-kbd.c index 159346cb4060..b0ea387414c1 100644 --- a/drivers/input/keyboard/opencores-kbd.c +++ b/drivers/input/keyboard/opencores-kbd.c @@ -49,10 +49,8 @@ static int opencores_kbd_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "missing board IRQ resource\n"); + if (irq < 0) return -EINVAL; - } opencores_kbd = devm_kzalloc(&pdev->dev, sizeof(*opencores_kbd), GFP_KERNEL); diff --git a/drivers/input/keyboard/pmic8xxx-keypad.c b/drivers/input/keyboard/pmic8xxx-keypad.c index d529768a1d06..91d5811d6f0e 100644 --- a/drivers/input/keyboard/pmic8xxx-keypad.c +++ b/drivers/input/keyboard/pmic8xxx-keypad.c @@ -544,16 +544,12 @@ static int pmic8xxx_kp_probe(struct platform_device *pdev) } kp->key_sense_irq = platform_get_irq(pdev, 0); - if (kp->key_sense_irq < 0) { - dev_err(&pdev->dev, "unable to get keypad sense irq\n"); + if (kp->key_sense_irq < 0) return kp->key_sense_irq; - } kp->key_stuck_irq = platform_get_irq(pdev, 1); - if (kp->key_stuck_irq < 0) { - dev_err(&pdev->dev, "unable to get keypad stuck irq\n"); + if (kp->key_stuck_irq < 0) return kp->key_stuck_irq; - } kp->input->name = "PMIC8XXX keypad"; kp->input->phys = "pmic8xxx_keypad/input0"; diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c index 39023664d2f2..7e65708b25a4 100644 --- a/drivers/input/keyboard/pxa27x_keypad.c +++ b/drivers/input/keyboard/pxa27x_keypad.c @@ -727,10 +727,8 @@ static int pxa27x_keypad_probe(struct platform_device *pdev) return -EINVAL; irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "failed to get keypad irq\n"); + if (irq < 0) return -ENXIO; - } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res == NULL) { diff --git a/drivers/input/keyboard/pxa930_rotary.c b/drivers/input/keyboard/pxa930_rotary.c index 585e7765cbf0..f7414091d94e 100644 --- a/drivers/input/keyboard/pxa930_rotary.c +++ b/drivers/input/keyboard/pxa930_rotary.c @@ -89,10 +89,8 @@ static int pxa930_rotary_probe(struct platform_device *pdev) int err; irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "no irq for rotary controller\n"); + if (irq < 0) return -ENXIO; - } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c index 08ba41a81f14..27ad73f43451 100644 --- a/drivers/input/keyboard/sh_keysc.c +++ b/drivers/input/keyboard/sh_keysc.c @@ -181,10 +181,8 @@ static int sh_keysc_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "failed to get irq\n"); + if (irq < 0) goto err0; - } priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (priv == NULL) { diff --git a/drivers/input/keyboard/snvs_pwrkey.c b/drivers/input/keyboard/snvs_pwrkey.c index 5342d8d45f81..e76b7a400a1c 100644 --- a/drivers/input/keyboard/snvs_pwrkey.c +++ b/drivers/input/keyboard/snvs_pwrkey.c @@ -118,10 +118,8 @@ static int imx_snvs_pwrkey_probe(struct platform_device *pdev) pdata->wakeup = of_property_read_bool(np, "wakeup-source"); pdata->irq = platform_get_irq(pdev, 0); - if (pdata->irq < 0) { - dev_err(&pdev->dev, "no irq defined in platform data\n"); + if (pdata->irq < 0) return -EINVAL; - } regmap_update_bits(pdata->snvs, SNVS_LPCR_REG, SNVS_LPCR_DEP_EN, SNVS_LPCR_DEP_EN); diff --git a/drivers/input/keyboard/spear-keyboard.c b/drivers/input/keyboard/spear-keyboard.c index 7d25fa338ab4..9b8d78f87253 100644 --- a/drivers/input/keyboard/spear-keyboard.c +++ b/drivers/input/keyboard/spear-keyboard.c @@ -191,10 +191,8 @@ static int spear_kbd_probe(struct platform_device *pdev) int error; irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "not able to get irq for the device\n"); + if (irq < 0) return irq; - } kbd = devm_kzalloc(&pdev->dev, sizeof(*kbd), GFP_KERNEL); if (!kbd) { diff --git a/drivers/input/keyboard/st-keyscan.c b/drivers/input/keyboard/st-keyscan.c index f097128b93fe..27562cd67fb6 100644 --- a/drivers/input/keyboard/st-keyscan.c +++ b/drivers/input/keyboard/st-keyscan.c @@ -187,10 +187,8 @@ static int keyscan_probe(struct platform_device *pdev) keyscan_stop(keypad_data); keypad_data->irq = platform_get_irq(pdev, 0); - if (keypad_data->irq < 0) { - dev_err(&pdev->dev, "no IRQ specified\n"); + if (keypad_data->irq < 0) return -EINVAL; - } error = devm_request_irq(&pdev->dev, keypad_data->irq, keyscan_isr, 0, pdev->name, keypad_data); diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c index a37a7a9e9171..d34d6947960f 100644 --- a/drivers/input/keyboard/tegra-kbc.c +++ b/drivers/input/keyboard/tegra-kbc.c @@ -631,10 +631,8 @@ static int tegra_kbc_probe(struct platform_device *pdev) return -EINVAL; kbc->irq = platform_get_irq(pdev, 0); - if (kbc->irq < 0) { - dev_err(&pdev->dev, "failed to get keyboard IRQ\n"); + if (kbc->irq < 0) return -ENXIO; - } kbc->idev = devm_input_allocate_device(&pdev->dev); if (!kbc->idev) { 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/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 235925b28772..17c1cca74498 100644 --- a/drivers/input/misc/axp20x-pek.c +++ b/drivers/input/misc/axp20x-pek.c @@ -229,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); 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/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, diff --git a/drivers/input/mouse/pxa930_trkball.c b/drivers/input/mouse/pxa930_trkball.c index 87bac8cff6f7..41acde60b60f 100644 --- a/drivers/input/mouse/pxa930_trkball.c +++ b/drivers/input/mouse/pxa930_trkball.c @@ -147,10 +147,8 @@ static int pxa930_trkball_probe(struct platform_device *pdev) int irq, error; irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "failed to get trkball irq\n"); + if (irq < 0) return -ENXIO; - } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { diff --git a/drivers/input/serio/arc_ps2.c b/drivers/input/serio/arc_ps2.c index 443194a2b9e3..0af9fba5d16d 100644 --- a/drivers/input/serio/arc_ps2.c +++ b/drivers/input/serio/arc_ps2.c @@ -187,10 +187,8 @@ static int arc_ps2_probe(struct platform_device *pdev) int error, id, i; irq = platform_get_irq_byname(pdev, "arc_ps2_irq"); - if (irq < 0) { - dev_err(&pdev->dev, "no IRQ defined\n"); + if (irq < 0) return -EINVAL; - } arc_ps2 = devm_kzalloc(&pdev->dev, sizeof(struct arc_ps2_data), GFP_KERNEL); diff --git a/drivers/input/serio/ps2-gpio.c b/drivers/input/serio/ps2-gpio.c index e0f18469d01b..8970b49ea09a 100644 --- a/drivers/input/serio/ps2-gpio.c +++ b/drivers/input/serio/ps2-gpio.c @@ -369,8 +369,6 @@ static int ps2_gpio_probe(struct platform_device *pdev) drvdata->irq = platform_get_irq(pdev, 0); if (drvdata->irq < 0) { - dev_err(dev, "failed to get irq from platform resource: %d\n", - drvdata->irq); error = drvdata->irq; goto err_free_serio; } diff --git a/drivers/input/touchscreen/88pm860x-ts.c b/drivers/input/touchscreen/88pm860x-ts.c index 1d1bbc8da949..81a3ea4b9a3d 100644 --- a/drivers/input/touchscreen/88pm860x-ts.c +++ b/drivers/input/touchscreen/88pm860x-ts.c @@ -185,10 +185,8 @@ static int pm860x_touch_probe(struct platform_device *pdev) int irq, ret, res_x = 0, data = 0; irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "No IRQ resource!\n"); + if (irq < 0) return -EINVAL; - } if (pm860x_touch_dt_init(pdev, chip, &res_x)) { if (pdata) { diff --git a/drivers/input/touchscreen/bcm_iproc_tsc.c b/drivers/input/touchscreen/bcm_iproc_tsc.c index 4d11b27c7c43..7de1fd24ce36 100644 --- a/drivers/input/touchscreen/bcm_iproc_tsc.c +++ b/drivers/input/touchscreen/bcm_iproc_tsc.c @@ -489,10 +489,8 @@ static int iproc_ts_probe(struct platform_device *pdev) /* get interrupt */ irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "platform_get_irq failed: %d\n", irq); + if (irq < 0) return irq; - } error = devm_request_irq(&pdev->dev, irq, iproc_touchscreen_interrupt, diff --git a/drivers/input/touchscreen/fsl-imx25-tcq.c b/drivers/input/touchscreen/fsl-imx25-tcq.c index b66df8ab89f2..60a7246c5157 100644 --- a/drivers/input/touchscreen/fsl-imx25-tcq.c +++ b/drivers/input/touchscreen/fsl-imx25-tcq.c @@ -526,10 +526,8 @@ static int mx25_tcq_probe(struct platform_device *pdev) } priv->irq = platform_get_irq(pdev, 0); - if (priv->irq <= 0) { - dev_err(dev, "Failed to get IRQ\n"); + if (priv->irq <= 0) return priv->irq; - } idev = devm_input_allocate_device(dev); if (!idev) { diff --git a/drivers/input/touchscreen/imx6ul_tsc.c b/drivers/input/touchscreen/imx6ul_tsc.c index e04eecd65bbb..9ed258854349 100644 --- a/drivers/input/touchscreen/imx6ul_tsc.c +++ b/drivers/input/touchscreen/imx6ul_tsc.c @@ -430,16 +430,12 @@ static int imx6ul_tsc_probe(struct platform_device *pdev) } tsc_irq = platform_get_irq(pdev, 0); - if (tsc_irq < 0) { - dev_err(&pdev->dev, "no tsc irq resource?\n"); + if (tsc_irq < 0) return tsc_irq; - } adc_irq = platform_get_irq(pdev, 1); - if (adc_irq < 0) { - dev_err(&pdev->dev, "no adc irq resource?\n"); + if (adc_irq < 0) return adc_irq; - } err = devm_request_threaded_irq(tsc->dev, tsc_irq, NULL, tsc_irq_fn, IRQF_ONESHOT, diff --git a/drivers/input/touchscreen/lpc32xx_ts.c b/drivers/input/touchscreen/lpc32xx_ts.c index 567ed64b5392..b2cd9472e2d1 100644 --- a/drivers/input/touchscreen/lpc32xx_ts.c +++ b/drivers/input/touchscreen/lpc32xx_ts.c @@ -212,10 +212,8 @@ static int lpc32xx_ts_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "Can't get interrupt resource\n"); + if (irq < 0) return irq; - } tsc = kzalloc(sizeof(*tsc), GFP_KERNEL); input = input_allocate_device(); -- cgit v1.2.3 From 62c3801619e16b68a37ea899b76572145dfe41c9 Mon Sep 17 00:00:00 2001 From: Fei Shao Date: Wed, 14 Aug 2019 15:06:00 -0700 Subject: Input: cros_ec_keyb - add back missing mask for event_type In the previous patch we didn't mask out event_type in case statement, so switches are always picked instead of buttons, which results in ChromeOS devices misbehaving when power button is pressed. This patch adds back the missing mask. Fixes: d096aa3eb604 ("Input: cros_ec_keyb: mask out extra flags in event_type") Signed-off-by: Fei Shao Reviewed-by: Nicolas Boichat Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/cros_ec_keyb.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c index 38cb6d82d8fe..bef7bee6f05e 100644 --- a/drivers/input/keyboard/cros_ec_keyb.c +++ b/drivers/input/keyboard/cros_ec_keyb.c @@ -226,6 +226,8 @@ static int cros_ec_keyb_work(struct notifier_block *nb, { struct cros_ec_keyb *ckdev = container_of(nb, struct cros_ec_keyb, notifier); + uint8_t mkbp_event_type = ckdev->ec->event_data.event_type & + EC_MKBP_EVENT_TYPE_MASK; u32 val; unsigned int ev_type; @@ -237,7 +239,7 @@ static int cros_ec_keyb_work(struct notifier_block *nb, if (queued_during_suspend && !device_may_wakeup(ckdev->dev)) return NOTIFY_OK; - switch (ckdev->ec->event_data.event_type & EC_MKBP_EVENT_TYPE_MASK) { + switch (mkbp_event_type) { case EC_MKBP_EVENT_KEY_MATRIX: pm_wakeup_event(ckdev->dev, 0); @@ -264,7 +266,7 @@ static int cros_ec_keyb_work(struct notifier_block *nb, case EC_MKBP_EVENT_SWITCH: pm_wakeup_event(ckdev->dev, 0); - if (ckdev->ec->event_data.event_type == EC_MKBP_EVENT_BUTTON) { + if (mkbp_event_type == EC_MKBP_EVENT_BUTTON) { val = get_unaligned_le32( &ckdev->ec->event_data.data.buttons); ev_type = EV_KEY; -- cgit v1.2.3 From 2da9d2b5b9d64cf5228dd3fb4d1220ff3fec8440 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Fri, 16 Aug 2019 15:07:15 -0700 Subject: Input: wacom_w8001 - allocate additional space for 'phys' GCC warns that the output of our call to 'snprintf' in 'w8001_connect' may be truncated since both 'serio->phys' and 'w8001->phys' are 32 bytes in length. Increase the amount of space allocated for the latter to compensate. Signed-off-by: Jason Gerecke Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/wacom_w8001.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c index 3715d1eace92..691285ace228 100644 --- a/drivers/input/touchscreen/wacom_w8001.c +++ b/drivers/input/touchscreen/wacom_w8001.c @@ -27,6 +27,8 @@ MODULE_AUTHOR("Jaya Kumar "); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); +#define W8001_MAX_PHYS 42 + #define W8001_MAX_LENGTH 13 #define W8001_LEAD_MASK 0x80 #define W8001_LEAD_BYTE 0x80 @@ -89,7 +91,7 @@ struct w8001 { unsigned char response_type; unsigned char response[W8001_MAX_LENGTH]; unsigned char data[W8001_MAX_LENGTH]; - char phys[32]; + char phys[W8001_MAX_PHYS]; int type; unsigned int pktlen; u16 max_touch_x; -- cgit v1.2.3 From e95656ea15e54d4e6a192d560d84008b53fc1eb5 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 18 Apr 2017 17:28:30 -0700 Subject: Input: add support for polling to input devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Separating "normal" and "polled" input devices was a mistake, as often we want to allow the very same device work on both interrupt-driven and polled mode, depending on the board on which the device is used. This introduces new APIs: - input_setup_polling - input_set_poll_interval - input_set_min_poll_interval - input_set_max_poll_interval These new APIs allow switching an input device into polled mode with sysfs attributes matching drivers using input_polled_dev APIs that will be eventually removed. Tested-by: Michal Vokáč Acked-by: Benjamin Tissoires Signed-off-by: Dmitry Torokhov --- drivers/input/Makefile | 2 +- drivers/input/input-poller.c | 213 +++++++++++++++++++++++++++++++++++++++++++ drivers/input/input-poller.h | 18 ++++ drivers/input/input.c | 36 ++++++-- include/linux/input.h | 12 +++ 5 files changed, 273 insertions(+), 8 deletions(-) create mode 100644 drivers/input/input-poller.c create mode 100644 drivers/input/input-poller.h diff --git a/drivers/input/Makefile b/drivers/input/Makefile index 40de6a7be641..e35650930371 100644 --- a/drivers/input/Makefile +++ b/drivers/input/Makefile @@ -6,7 +6,7 @@ # Each configuration option enables a list of files. obj-$(CONFIG_INPUT) += input-core.o -input-core-y := input.o input-compat.o input-mt.o ff-core.o +input-core-y := input.o input-compat.o input-mt.o input-poller.o ff-core.o obj-$(CONFIG_INPUT_FF_MEMLESS) += ff-memless.o obj-$(CONFIG_INPUT_POLLDEV) += input-polldev.o diff --git a/drivers/input/input-poller.c b/drivers/input/input-poller.c new file mode 100644 index 000000000000..1b3d28964bb2 --- /dev/null +++ b/drivers/input/input-poller.c @@ -0,0 +1,213 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Support for polling mode for input devices. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "input-poller.h" + +struct input_dev_poller { + void (*poll)(struct input_dev *dev); + + unsigned int poll_interval; /* msec */ + unsigned int poll_interval_max; /* msec */ + unsigned int poll_interval_min; /* msec */ + + struct input_dev *input; + struct delayed_work work; +}; + +static void input_dev_poller_queue_work(struct input_dev_poller *poller) +{ + unsigned long delay; + + delay = msecs_to_jiffies(poller->poll_interval); + if (delay >= HZ) + delay = round_jiffies_relative(delay); + + queue_delayed_work(system_freezable_wq, &poller->work, delay); +} + +static void input_dev_poller_work(struct work_struct *work) +{ + struct input_dev_poller *poller = + container_of(work, struct input_dev_poller, work.work); + + poller->poll(poller->input); + input_dev_poller_queue_work(poller); +} + +void input_dev_poller_finalize(struct input_dev_poller *poller) +{ + if (!poller->poll_interval) + poller->poll_interval = 500; + if (!poller->poll_interval_max) + poller->poll_interval_max = poller->poll_interval; +} + +void input_dev_poller_start(struct input_dev_poller *poller) +{ + /* Only start polling if polling is enabled */ + if (poller->poll_interval > 0) { + poller->poll(poller->input); + input_dev_poller_queue_work(poller); + } +} + +void input_dev_poller_stop(struct input_dev_poller *poller) +{ + cancel_delayed_work_sync(&poller->work); +} + +int input_setup_polling(struct input_dev *dev, + void (*poll_fn)(struct input_dev *dev)) +{ + struct input_dev_poller *poller; + + poller = kzalloc(sizeof(*poller), GFP_KERNEL); + if (!poller) { + /* + * We want to show message even though kzalloc() may have + * printed backtrace as knowing what instance of input + * device we were dealing with is helpful. + */ + dev_err(dev->dev.parent ?: &dev->dev, + "%s: unable to allocate poller structure\n", __func__); + return -ENOMEM; + } + + INIT_DELAYED_WORK(&poller->work, input_dev_poller_work); + poller->input = dev; + poller->poll = poll_fn; + + dev->poller = poller; + return 0; +} +EXPORT_SYMBOL(input_setup_polling); + +static bool input_dev_ensure_poller(struct input_dev *dev) +{ + if (!dev->poller) { + dev_err(dev->dev.parent ?: &dev->dev, + "poller structure has not been set up\n"); + return false; + } + + return true; +} + +void input_set_poll_interval(struct input_dev *dev, unsigned int interval) +{ + if (input_dev_ensure_poller(dev)) + dev->poller->poll_interval = interval; +} +EXPORT_SYMBOL(input_set_poll_interval); + +void input_set_min_poll_interval(struct input_dev *dev, unsigned int interval) +{ + if (input_dev_ensure_poller(dev)) + dev->poller->poll_interval_min = interval; +} +EXPORT_SYMBOL(input_set_min_poll_interval); + +void input_set_max_poll_interval(struct input_dev *dev, unsigned int interval) +{ + if (input_dev_ensure_poller(dev)) + dev->poller->poll_interval_max = interval; +} +EXPORT_SYMBOL(input_set_max_poll_interval); + +/* SYSFS interface */ + +static ssize_t input_dev_get_poll_interval(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct input_dev *input = to_input_dev(dev); + + return sprintf(buf, "%d\n", input->poller->poll_interval); +} + +static ssize_t input_dev_set_poll_interval(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct input_dev *input = to_input_dev(dev); + struct input_dev_poller *poller = input->poller; + unsigned int interval; + int err; + + err = kstrtouint(buf, 0, &interval); + if (err) + return err; + + if (interval < poller->poll_interval_min) + return -EINVAL; + + if (interval > poller->poll_interval_max) + return -EINVAL; + + mutex_lock(&input->mutex); + + poller->poll_interval = interval; + + if (input->users) { + cancel_delayed_work_sync(&poller->work); + if (poller->poll_interval > 0) + input_dev_poller_queue_work(poller); + } + + mutex_unlock(&input->mutex); + + return count; +} + +static DEVICE_ATTR(poll, 0644, + input_dev_get_poll_interval, input_dev_set_poll_interval); + +static ssize_t input_dev_get_poll_max(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct input_dev *input = to_input_dev(dev); + + return sprintf(buf, "%d\n", input->poller->poll_interval_max); +} + +static DEVICE_ATTR(max, 0444, input_dev_get_poll_max, NULL); + +static ssize_t input_dev_get_poll_min(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct input_dev *input = to_input_dev(dev); + + return sprintf(buf, "%d\n", input->poller->poll_interval_min); +} + +static DEVICE_ATTR(min, 0444, input_dev_get_poll_min, NULL); + +static umode_t input_poller_attrs_visible(struct kobject *kobj, + struct attribute *attr, int n) +{ + struct device *dev = kobj_to_dev(kobj); + struct input_dev *input = to_input_dev(dev); + + return input->poller ? attr->mode : 0; +} + +static struct attribute *input_poller_attrs[] = { + &dev_attr_poll.attr, + &dev_attr_max.attr, + &dev_attr_min.attr, + NULL +}; + +struct attribute_group input_poller_attribute_group = { + .is_visible = input_poller_attrs_visible, + .attrs = input_poller_attrs, +}; diff --git a/drivers/input/input-poller.h b/drivers/input/input-poller.h new file mode 100644 index 000000000000..e3fca0be1d32 --- /dev/null +++ b/drivers/input/input-poller.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef _INPUT_POLLER_H +#define _INPUT_POLLER_H + +/* + * Support for polling mode for input devices. + */ +#include + +struct input_dev_poller; + +void input_dev_poller_finalize(struct input_dev_poller *poller); +void input_dev_poller_start(struct input_dev_poller *poller); +void input_dev_poller_stop(struct input_dev_poller *poller); + +extern struct attribute_group input_poller_attribute_group; + +#endif /* _INPUT_POLLER_H */ diff --git a/drivers/input/input.c b/drivers/input/input.c index 7494a0dede79..c08aa3596144 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -24,6 +24,7 @@ #include #include #include "input-compat.h" +#include "input-poller.h" MODULE_AUTHOR("Vojtech Pavlik "); MODULE_DESCRIPTION("Input core"); @@ -603,20 +604,31 @@ int input_open_device(struct input_handle *handle) handle->open++; - if (!dev->users++ && dev->open) - retval = dev->open(dev); + if (dev->users++) { + /* + * Device is already opened, so we can exit immediately and + * report success. + */ + goto out; + } - if (retval) { - dev->users--; - if (!--handle->open) { + if (dev->open) { + retval = dev->open(dev); + if (retval) { + dev->users--; + handle->open--; /* * Make sure we are not delivering any more events * through this handle */ synchronize_rcu(); + goto out; } } + if (dev->poller) + input_dev_poller_start(dev->poller); + out: mutex_unlock(&dev->mutex); return retval; @@ -655,8 +667,13 @@ void input_close_device(struct input_handle *handle) __input_release_device(handle); - if (!--dev->users && dev->close) - dev->close(dev); + if (!--dev->users) { + if (dev->poller) + input_dev_poller_stop(dev->poller); + + if (dev->close) + dev->close(dev); + } if (!--handle->open) { /* @@ -1502,6 +1519,7 @@ static const struct attribute_group *input_dev_attr_groups[] = { &input_dev_attr_group, &input_dev_id_attr_group, &input_dev_caps_attr_group, + &input_poller_attribute_group, NULL }; @@ -1511,6 +1529,7 @@ static void input_dev_release(struct device *device) input_ff_destroy(dev); input_mt_destroy_slots(dev); + kfree(dev->poller); kfree(dev->absinfo); kfree(dev->vals); kfree(dev); @@ -2175,6 +2194,9 @@ int input_register_device(struct input_dev *dev) if (!dev->setkeycode) dev->setkeycode = input_default_setkeycode; + if (dev->poller) + input_dev_poller_finalize(dev->poller); + error = device_add(&dev->dev); if (error) goto err_free_vals; diff --git a/include/linux/input.h b/include/linux/input.h index e95a439d8bd5..94f277cd806a 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -21,6 +21,8 @@ #include #include +struct input_dev_poller; + /** * struct input_value - input value representation * @type: type of value (EV_KEY, EV_ABS, etc) @@ -71,6 +73,8 @@ enum input_clock_type { * not sleep * @ff: force feedback structure associated with the device if device * supports force feedback effects + * @poller: poller structure associated with the device if device is + * set up to use polling mode * @repeat_key: stores key code of the last key pressed; used to implement * software autorepeat * @timer: timer for software autorepeat @@ -156,6 +160,8 @@ struct input_dev { struct ff_device *ff; + struct input_dev_poller *poller; + unsigned int repeat_key; struct timer_list timer; @@ -372,6 +378,12 @@ void input_unregister_device(struct input_dev *); void input_reset_device(struct input_dev *); +int input_setup_polling(struct input_dev *dev, + void (*poll_fn)(struct input_dev *dev)); +void input_set_poll_interval(struct input_dev *dev, unsigned int interval); +void input_set_min_poll_interval(struct input_dev *dev, unsigned int interval); +void input_set_max_poll_interval(struct input_dev *dev, unsigned int interval); + int __must_check input_register_handler(struct input_handler *); void input_unregister_handler(struct input_handler *); -- cgit v1.2.3 From cfd8579ddc02d8c5024bae7106ba37079653b3d2 Mon Sep 17 00:00:00 2001 From: Hui Wang Date: Tue, 20 Aug 2019 12:07:01 -0700 Subject: Input: psmouse - drop all unneeded functions from mouse headers Recently we had a building error if we enable the MOUSE_PS2_ALPS while disable the MOUSE_PS2_TRACKPOINT, and was fixed by 49e6979e7e92 ("Input: psmouse - fix build error of multiple definition"). We could improve that fix by dropping all unneeded functions and CONFIG_MOUSE_ guards from the header, it is safe to do that since those functions are not directly called by psmouse-base.c anymore. Signed-off-by: Hui Wang Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/alps.h | 11 ----------- drivers/input/mouse/byd.h | 11 ----------- drivers/input/mouse/cypress_ps2.h | 11 ----------- drivers/input/mouse/elantech.h | 18 ++---------------- drivers/input/mouse/hgpk.h | 13 +++---------- drivers/input/mouse/lifebook.h | 13 +++---------- drivers/input/mouse/logips2pp.h | 7 ------- drivers/input/mouse/sentelic.h | 11 ----------- drivers/input/mouse/touchkit_ps2.h | 8 -------- drivers/input/mouse/trackpoint.h | 8 -------- drivers/input/mouse/vmmouse.h | 11 ----------- 11 files changed, 8 insertions(+), 114 deletions(-) diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h index f4bab629739c..0a1048cf23f6 100644 --- a/drivers/input/mouse/alps.h +++ b/drivers/input/mouse/alps.h @@ -323,18 +323,7 @@ struct alps_data { #define ALPS_QUIRK_TRACKSTICK_BUTTONS 1 /* trakcstick buttons in trackstick packet */ -#ifdef CONFIG_MOUSE_PS2_ALPS int alps_detect(struct psmouse *psmouse, bool set_properties); int alps_init(struct psmouse *psmouse); -#else -inline int alps_detect(struct psmouse *psmouse, bool set_properties) -{ - return -ENOSYS; -} -inline int alps_init(struct psmouse *psmouse) -{ - return -ENOSYS; -} -#endif /* CONFIG_MOUSE_PS2_ALPS */ #endif diff --git a/drivers/input/mouse/byd.h b/drivers/input/mouse/byd.h index 8cb90d904186..ff2771e2dd2e 100644 --- a/drivers/input/mouse/byd.h +++ b/drivers/input/mouse/byd.h @@ -2,18 +2,7 @@ #ifndef _BYD_H #define _BYD_H -#ifdef CONFIG_MOUSE_PS2_BYD int byd_detect(struct psmouse *psmouse, bool set_properties); int byd_init(struct psmouse *psmouse); -#else -static inline int byd_detect(struct psmouse *psmouse, bool set_properties) -{ - return -ENOSYS; -} -static inline int byd_init(struct psmouse *psmouse) -{ - return -ENOSYS; -} -#endif /* CONFIG_MOUSE_PS2_BYD */ #endif /* _BYD_H */ diff --git a/drivers/input/mouse/cypress_ps2.h b/drivers/input/mouse/cypress_ps2.h index 1eaddd818004..bb4979d06bf9 100644 --- a/drivers/input/mouse/cypress_ps2.h +++ b/drivers/input/mouse/cypress_ps2.h @@ -170,18 +170,7 @@ struct cytp_data { }; -#ifdef CONFIG_MOUSE_PS2_CYPRESS int cypress_detect(struct psmouse *psmouse, bool set_properties); int cypress_init(struct psmouse *psmouse); -#else -inline int cypress_detect(struct psmouse *psmouse, bool set_properties) -{ - return -ENOSYS; -} -inline int cypress_init(struct psmouse *psmouse) -{ - return -ENOSYS; -} -#endif /* CONFIG_MOUSE_PS2_CYPRESS */ #endif /* _CYPRESS_PS2_H */ diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h index 46343998522b..e0a3e59d4f1b 100644 --- a/drivers/input/mouse/elantech.h +++ b/drivers/input/mouse/elantech.h @@ -184,32 +184,18 @@ struct elantech_data { void (*original_set_rate)(struct psmouse *psmouse, unsigned int rate); }; -#ifdef CONFIG_MOUSE_PS2_ELANTECH int elantech_detect(struct psmouse *psmouse, bool set_properties); int elantech_init_ps2(struct psmouse *psmouse); + +#ifdef CONFIG_MOUSE_PS2_ELANTECH int elantech_init(struct psmouse *psmouse); #else -static inline int elantech_detect(struct psmouse *psmouse, bool set_properties) -{ - return -ENOSYS; -} static inline int elantech_init(struct psmouse *psmouse) { return -ENOSYS; } -static inline int elantech_init_ps2(struct psmouse *psmouse) -{ - return -ENOSYS; -} #endif /* CONFIG_MOUSE_PS2_ELANTECH */ -#if defined(CONFIG_MOUSE_PS2_ELANTECH_SMBUS) int elantech_init_smbus(struct psmouse *psmouse); -#else -static inline int elantech_init_smbus(struct psmouse *psmouse) -{ - return -ENOSYS; -} -#endif /* CONFIG_MOUSE_PS2_ELANTECH_SMBUS */ #endif diff --git a/drivers/input/mouse/hgpk.h b/drivers/input/mouse/hgpk.h index 98b7b384229b..ce041591f1a8 100644 --- a/drivers/input/mouse/hgpk.h +++ b/drivers/input/mouse/hgpk.h @@ -47,22 +47,15 @@ struct hgpk_data { int xsaw_secondary, ysaw_secondary; /* jumpiness detection */ }; -#ifdef CONFIG_MOUSE_PS2_OLPC -void hgpk_module_init(void); int hgpk_detect(struct psmouse *psmouse, bool set_properties); int hgpk_init(struct psmouse *psmouse); + +#ifdef CONFIG_MOUSE_PS2_OLPC +void hgpk_module_init(void); #else static inline void hgpk_module_init(void) { } -static inline int hgpk_detect(struct psmouse *psmouse, bool set_properties) -{ - return -ENODEV; -} -static inline int hgpk_init(struct psmouse *psmouse) -{ - return -ENODEV; -} #endif #endif diff --git a/drivers/input/mouse/lifebook.h b/drivers/input/mouse/lifebook.h index 573f2ca1983d..d989cca62dd6 100644 --- a/drivers/input/mouse/lifebook.h +++ b/drivers/input/mouse/lifebook.h @@ -8,22 +8,15 @@ #ifndef _LIFEBOOK_H #define _LIFEBOOK_H -#ifdef CONFIG_MOUSE_PS2_LIFEBOOK -void lifebook_module_init(void); int lifebook_detect(struct psmouse *psmouse, bool set_properties); int lifebook_init(struct psmouse *psmouse); + +#ifdef CONFIG_MOUSE_PS2_LIFEBOOK +void lifebook_module_init(void); #else static inline void lifebook_module_init(void) { } -static inline int lifebook_detect(struct psmouse *psmouse, bool set_properties) -{ - return -ENOSYS; -} -static inline int lifebook_init(struct psmouse *psmouse) -{ - return -ENOSYS; -} #endif #endif diff --git a/drivers/input/mouse/logips2pp.h b/drivers/input/mouse/logips2pp.h index 5f9344135f70..df885c4874df 100644 --- a/drivers/input/mouse/logips2pp.h +++ b/drivers/input/mouse/logips2pp.h @@ -8,13 +8,6 @@ #ifndef _LOGIPS2PP_H #define _LOGIPS2PP_H -#ifdef CONFIG_MOUSE_PS2_LOGIPS2PP int ps2pp_detect(struct psmouse *psmouse, bool set_properties); -#else -static inline int ps2pp_detect(struct psmouse *psmouse, bool set_properties) -{ - return -ENOSYS; -} -#endif /* CONFIG_MOUSE_PS2_LOGIPS2PP */ #endif diff --git a/drivers/input/mouse/sentelic.h b/drivers/input/mouse/sentelic.h index dc88a93adf85..02cac0e7ad63 100644 --- a/drivers/input/mouse/sentelic.h +++ b/drivers/input/mouse/sentelic.h @@ -106,19 +106,8 @@ struct fsp_data { unsigned int last_mt_fgr; /* Last seen finger(multitouch) */ }; -#ifdef CONFIG_MOUSE_PS2_SENTELIC extern int fsp_detect(struct psmouse *psmouse, bool set_properties); extern int fsp_init(struct psmouse *psmouse); -#else -static inline int fsp_detect(struct psmouse *psmouse, bool set_properties) -{ - return -ENOSYS; -} -static inline int fsp_init(struct psmouse *psmouse) -{ - return -ENOSYS; -} -#endif #endif /* __KERNEL__ */ diff --git a/drivers/input/mouse/touchkit_ps2.h b/drivers/input/mouse/touchkit_ps2.h index 5acb76464a5b..c808fe6c782f 100644 --- a/drivers/input/mouse/touchkit_ps2.h +++ b/drivers/input/mouse/touchkit_ps2.h @@ -9,14 +9,6 @@ #ifndef _TOUCHKIT_PS2_H #define _TOUCHKIT_PS2_H -#ifdef CONFIG_MOUSE_PS2_TOUCHKIT int touchkit_ps2_detect(struct psmouse *psmouse, bool set_properties); -#else -static inline int touchkit_ps2_detect(struct psmouse *psmouse, - bool set_properties) -{ - return -ENOSYS; -} -#endif /* CONFIG_MOUSE_PS2_TOUCHKIT */ #endif diff --git a/drivers/input/mouse/trackpoint.h b/drivers/input/mouse/trackpoint.h index 77110f3ec21d..5cb93ed26085 100644 --- a/drivers/input/mouse/trackpoint.h +++ b/drivers/input/mouse/trackpoint.h @@ -155,14 +155,6 @@ struct trackpoint_data { bool ext_dev; }; -#ifdef CONFIG_MOUSE_PS2_TRACKPOINT int trackpoint_detect(struct psmouse *psmouse, bool set_properties); -#else -static inline int trackpoint_detect(struct psmouse *psmouse, - bool set_properties) -{ - return -ENOSYS; -} -#endif /* CONFIG_MOUSE_PS2_TRACKPOINT */ #endif /* _TRACKPOINT_H */ diff --git a/drivers/input/mouse/vmmouse.h b/drivers/input/mouse/vmmouse.h index 774549a12930..90157aecade7 100644 --- a/drivers/input/mouse/vmmouse.h +++ b/drivers/input/mouse/vmmouse.h @@ -8,20 +8,9 @@ #ifndef _VMMOUSE_H #define _VMMOUSE_H -#ifdef CONFIG_MOUSE_PS2_VMMOUSE #define VMMOUSE_PSNAME "VirtualPS/2" int vmmouse_detect(struct psmouse *psmouse, bool set_properties); int vmmouse_init(struct psmouse *psmouse); -#else -static inline int vmmouse_detect(struct psmouse *psmouse, bool set_properties) -{ - return -ENOSYS; -} -static inline int vmmouse_init(struct psmouse *psmouse) -{ - return -ENOSYS; -} -#endif #endif -- cgit v1.2.3 From 53119e513478b3b5c2b81a9a049f52cf17fcfff3 Mon Sep 17 00:00:00 2001 From: Enrico Weigelt Date: Tue, 20 Aug 2019 12:08:43 -0700 Subject: Input: soc_button_array - use platform_device_register_resndata() The registration of gpio-keys device can be written much shorter by using the platform_device_register_resndata() helper. Signed-off-by: Enrico Weigelt Signed-off-by: Dmitry Torokhov --- drivers/input/misc/soc_button_array.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c index 6f0133fe1546..97e3639e99d0 100644 --- a/drivers/input/misc/soc_button_array.c +++ b/drivers/input/misc/soc_button_array.c @@ -120,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); -- cgit v1.2.3 From c8a144b250dcd5fe6df95b8d101e9e2fe4c16201 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Thu, 29 Aug 2019 14:31:05 -0700 Subject: Input: i8042 - enable wakeup on a stable struct device We don't know when the device will be added with device_add() in serio_add_port() because serio_add_port() is called from a workqueue that this driver schedules by calling serio_register_port(). The best we can know is that the device will definitely not have been added yet when the start callback is called on the serio device. While it hasn't been shown to be a problem, proactively move the wakeup enabling calls to the start hook so that we don't race with the workqueue calling device_add(). This will avoid racy situations where code tries to add wakeup sysfs attributes for this device from dpm_sysfs_add() but the path in device_set_wakeup_capable() has already done so. Signed-off-by: Stephen Boyd Signed-off-by: Dmitry Torokhov --- drivers/input/serio/i8042.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index b695094290ab..20ff2bed3917 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -432,6 +432,20 @@ static int i8042_start(struct serio *serio) { struct i8042_port *port = serio->port_data; + device_set_wakeup_capable(&serio->dev, true); + + /* + * On platforms using suspend-to-idle, allow the keyboard to + * wake up the system from sleep by enabling keyboard wakeups + * by default. This is consistent with keyboard wakeup + * behavior on many platforms using suspend-to-RAM (ACPI S3) + * by default. + */ + if (pm_suspend_default_s2idle() && + serio == i8042_ports[I8042_KBD_PORT_NO].serio) { + device_set_wakeup_enable(&serio->dev, true); + } + spin_lock_irq(&i8042_lock); port->exists = true; spin_unlock_irq(&i8042_lock); @@ -1397,17 +1411,6 @@ static void __init i8042_register_ports(void) (unsigned long) I8042_COMMAND_REG, i8042_ports[i].irq); serio_register_port(serio); - device_set_wakeup_capable(&serio->dev, true); - - /* - * On platforms using suspend-to-idle, allow the keyboard to - * wake up the system from sleep by enabling keyboard wakeups - * by default. This is consistent with keyboard wakeup - * behavior on many platforms using suspend-to-RAM (ACPI S3) - * by default. - */ - if (pm_suspend_default_s2idle() && i == I8042_KBD_PORT_NO) - device_set_wakeup_enable(&serio->dev, true); } } -- cgit v1.2.3 From 5dc15dcf39c40fcc420e41b43e31ab260c3feec3 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 9 Aug 2019 09:48:51 -0700 Subject: ARM: ux500: improve BU21013 touchpad bindings In preparation to update to bu21013_tp driver properly annotate GPIOs property (the INT GPIOs are active low, not open drain), and also define interrupt lines so we do not have to have special conversion in the driver. Tested-by: Linus Walleij Signed-off-by: Dmitry Torokhov --- arch/arm/boot/dts/ste-hrefprev60-stuib.dts | 14 ++++++++++---- arch/arm/boot/dts/ste-hrefv60plus-stuib.dts | 14 ++++++++++---- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/arch/arm/boot/dts/ste-hrefprev60-stuib.dts b/arch/arm/boot/dts/ste-hrefprev60-stuib.dts index aed940bd65a8..b78be5f4c212 100644 --- a/arch/arm/boot/dts/ste-hrefprev60-stuib.dts +++ b/arch/arm/boot/dts/ste-hrefprev60-stuib.dts @@ -4,6 +4,8 @@ */ /dts-v1/; +#include +#include #include "ste-hrefprev60.dtsi" #include "ste-href-stuib.dtsi" @@ -23,12 +25,16 @@ i2c@80110000 { /* Only one of these will be used */ bu21013_tp@5c { - touch-gpio = <&gpio2 12 0x4>; - reset-gpio = <&tc3589x_gpio 13 0x4>; + interrupt-parent = <&gpio2>; + interrupts = <12 IRQ_TYPE_LEVEL_LOW>; + touch-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>; + reset-gpios = <&tc3589x_gpio 13 GPIO_LINE_OPEN_DRAIN>; }; bu21013_tp@5d { - touch-gpio = <&gpio2 12 0x4>; - reset-gpio = <&tc3589x_gpio 13 0x4>; + interrupt-parent = <&gpio2>; + interrupts = <12 IRQ_TYPE_LEVEL_LOW>; + touch-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>; + reset-gpios = <&tc3589x_gpio 13 GPIO_LINE_OPEN_DRAIN>; }; }; }; diff --git a/arch/arm/boot/dts/ste-hrefv60plus-stuib.dts b/arch/arm/boot/dts/ste-hrefv60plus-stuib.dts index 0f3c3b86bb20..9be513aad549 100644 --- a/arch/arm/boot/dts/ste-hrefv60plus-stuib.dts +++ b/arch/arm/boot/dts/ste-hrefv60plus-stuib.dts @@ -6,6 +6,8 @@ */ /dts-v1/; +#include +#include #include "ste-hrefv60plus.dtsi" #include "ste-href-stuib.dtsi" @@ -25,12 +27,16 @@ i2c@80110000 { /* Only one of these will be used */ bu21013_tp@5c { - touch-gpio = <&gpio2 20 0x4>; - reset-gpio = <&gpio4 17 0x4>; + interrupt-parent = <&gpio2>; + interrupts = <20 IRQ_TYPE_LEVEL_LOW>; + touch-gpios = <&gpio2 20 GPIO_ACTIVE_LOW>; + reset-gpios = <&gpio4 17 GPIO_LINE_OPEN_DRAIN>; }; bu21013_tp@5d { - touch-gpio = <&gpio2 20 0x4>; - reset-gpio = <&gpio4 17 0x4>; + interrupt-parent = <&gpio2>; + interrupts = <20 IRQ_TYPE_LEVEL_LOW>; + touch-gpios = <&gpio2 20 GPIO_ACTIVE_LOW>; + reset-gpios = <&gpio4 17 GPIO_LINE_OPEN_DRAIN>; }; }; }; -- cgit v1.2.3 From a1b70a44b80af641a441937803cb8251e8e6d8e3 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 8 Aug 2019 11:03:59 -0700 Subject: Input: bu21013_ts - convert to use GPIO descriptors This driver can use GPIO descriptors rather than GPIO numbers without any problems, convert it. Name the field variables after the actual pins on the chip rather than the "reset" and "touch" names from the devicetree bindings that are vaguely inaccurate. No in-tree users pass GPIO numbers in platform data so drop this. Descriptor tables can be used to get these GPIOs from a board file if need be. Signed-off-by: Linus Walleij Signed-off-by: Dmitry Torokhov --- .../bindings/input/touchscreen/bu21013.txt | 5 +- drivers/input/touchscreen/bu21013_ts.c | 86 ++++++++++------------ include/linux/input/bu21013.h | 4 - 3 files changed, 41 insertions(+), 54 deletions(-) diff --git a/Documentation/devicetree/bindings/input/touchscreen/bu21013.txt b/Documentation/devicetree/bindings/input/touchscreen/bu21013.txt index 56d835242af2..43899fc36ecf 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/bu21013.txt +++ b/Documentation/devicetree/bindings/input/touchscreen/bu21013.txt @@ -2,10 +2,11 @@ Required properties: - compatible : "rohm,bu21013_tp" - - reg : I2C device address + - reg : I2C device address + - reset-gpios : GPIO pin enabling (selecting) chip (CS) Optional properties: - - touch-gpio : GPIO pin registering a touch event + - touch-gpios : GPIO pin registering a touch event - -supply : Phandle to a regulator supply - rohm,touch-max-x : Maximum outward permitted limit in the X axis - rohm,touch-max-y : Maximum outward permitted limit in the Y axis diff --git a/drivers/input/touchscreen/bu21013_ts.c b/drivers/input/touchscreen/bu21013_ts.c index 1d703e230ac3..c20f86f98ffc 100644 --- a/drivers/input/touchscreen/bu21013_ts.c +++ b/drivers/input/touchscreen/bu21013_ts.c @@ -14,11 +14,9 @@ #include #include #include -#include +#include #include -#include -#define PEN_DOWN_INTR 0 #define MAX_FINGERS 2 #define RESET_DELAY 30 #define PENUP_TIMEOUT (10) @@ -143,8 +141,9 @@ * @touch_stopped: touch stop flag * @chip: pointer to the touch panel controller * @in_dev: pointer to the input device structure - * @intr_pin: interrupt pin value * @regulator: pointer to the Regulator used for touch screen + * @cs_gpiod: chip select GPIO line + * @int_gpiod: touch interrupt GPIO line * * Touch panel device data structure */ @@ -154,8 +153,9 @@ struct bu21013_ts_data { const struct bu21013_platform_device *chip; struct input_dev *in_dev; struct regulator *regulator; + struct gpio_desc *cs_gpiod; + struct gpio_desc *int_gpiod; unsigned int irq; - unsigned int intr_pin; bool touch_stopped; }; @@ -257,20 +257,21 @@ static irqreturn_t bu21013_gpio_irq(int irq, void *device_data) { struct bu21013_ts_data *data = device_data; struct i2c_client *i2c = data->client; + int keep_polling; int retval; do { retval = bu21013_do_touch_report(data); if (retval < 0) { dev_err(&i2c->dev, "bu21013_do_touch_report failed\n"); - return IRQ_NONE; + break; } - data->intr_pin = gpio_get_value(data->chip->touch_pin); - if (data->intr_pin == PEN_DOWN_INTR) + keep_polling = gpiod_get_value(data->int_gpiod); + if (keep_polling) wait_event_timeout(data->wait, data->touch_stopped, msecs_to_jiffies(2)); - } while (!data->intr_pin && !data->touch_stopped); + } while (keep_polling && !data->touch_stopped); return IRQ_HANDLED; } @@ -425,28 +426,6 @@ static void bu21013_free_irq(struct bu21013_ts_data *bu21013_data) free_irq(bu21013_data->irq, bu21013_data); } -/** - * bu21013_cs_disable() - deconfigures the touch panel controller - * @bu21013_data: device structure pointer - * - * This function is used to deconfigure the chip selection - * for touch panel controller. - */ -static void bu21013_cs_disable(struct bu21013_ts_data *bu21013_data) -{ - int error; - - error = gpio_direction_output(bu21013_data->chip->cs_pin, 0); - if (error < 0) - dev_warn(&bu21013_data->client->dev, - "%s: gpio direction failed, error: %d\n", - __func__, error); - else - gpio_set_value(bu21013_data->chip->cs_pin, 0); - - gpio_free(bu21013_data->chip->cs_pin); -} - #ifdef CONFIG_OF static const struct bu21013_platform_device * bu21013_parse_dt(struct device *dev) @@ -471,9 +450,6 @@ bu21013_parse_dt(struct device *dev) of_property_read_u32(np, "rohm,touch-max-x", &pdata->touch_x_max); of_property_read_u32(np, "rohm,touch-max-y", &pdata->touch_y_max); - pdata->touch_pin = of_get_named_gpio(np, "touch-gpio", 0); - pdata->cs_pin = of_get_named_gpio(np, "reset-gpio", 0); - pdata->ext_clk = false; return pdata; @@ -516,11 +492,6 @@ static int bu21013_probe(struct i2c_client *client, return PTR_ERR(pdata); } - if (!gpio_is_valid(pdata->touch_pin)) { - dev_err(&client->dev, "invalid touch_pin supplied\n"); - return -EINVAL; - } - bu21013_data = kzalloc(sizeof(struct bu21013_ts_data), GFP_KERNEL); in_dev = input_allocate_device(); if (!bu21013_data || !in_dev) { @@ -529,16 +500,26 @@ static int bu21013_probe(struct i2c_client *client, goto err_free_mem; } + /* Named "INT" on the chip, DT binding is "touch" */ + bu21013_data->int_gpiod = gpiod_get(&client->dev, "touch", GPIOD_IN); + error = PTR_ERR_OR_ZERO(bu21013_data->int_gpiod); + if (error) { + if (error != -EPROBE_DEFER) + dev_err(&client->dev, "failed to get INT GPIO\n"); + goto err_free_mem; + } + gpiod_set_consumer_name(bu21013_data->int_gpiod, "BU21013 INT"); + bu21013_data->in_dev = in_dev; bu21013_data->chip = pdata; bu21013_data->client = client; - bu21013_data->irq = gpio_to_irq(pdata->touch_pin); + bu21013_data->irq = gpiod_to_irq(bu21013_data->int_gpiod); bu21013_data->regulator = regulator_get(&client->dev, "avdd"); if (IS_ERR(bu21013_data->regulator)) { dev_err(&client->dev, "regulator_get failed\n"); error = PTR_ERR(bu21013_data->regulator); - goto err_free_mem; + goto err_put_int_gpio; } error = regulator_enable(bu21013_data->regulator); @@ -550,13 +531,16 @@ static int bu21013_probe(struct i2c_client *client, bu21013_data->touch_stopped = false; init_waitqueue_head(&bu21013_data->wait); - /* configure the gpio pins */ - error = gpio_request_one(pdata->cs_pin, GPIOF_OUT_INIT_HIGH, - "touchp_reset"); - if (error < 0) { - dev_err(&client->dev, "Unable to request gpio reset_pin\n"); + /* Named "CS" on the chip, DT binding is "reset" */ + bu21013_data->cs_gpiod = gpiod_get(&client->dev, "reset", + GPIOD_OUT_HIGH); + error = PTR_ERR_OR_ZERO(bu21013_data->cs_gpiod); + if (error) { + if (error != -EPROBE_DEFER) + dev_err(&client->dev, "failed to get CS GPIO\n"); goto err_disable_regulator; } + gpiod_set_consumer_name(bu21013_data->cs_gpiod, "BU21013 CS"); /* configure the touch panel controller */ error = bu21013_init_chip(bu21013_data); @@ -604,11 +588,14 @@ static int bu21013_probe(struct i2c_client *client, err_free_irq: bu21013_free_irq(bu21013_data); err_cs_disable: - bu21013_cs_disable(bu21013_data); + gpiod_set_value(bu21013_data->cs_gpiod, 0); + gpiod_put(bu21013_data->cs_gpiod); err_disable_regulator: regulator_disable(bu21013_data->regulator); err_put_regulator: regulator_put(bu21013_data->regulator); +err_put_int_gpio: + gpiod_put(bu21013_data->int_gpiod); err_free_mem: input_free_device(in_dev); kfree(bu21013_data); @@ -628,13 +615,16 @@ static int bu21013_remove(struct i2c_client *client) bu21013_free_irq(bu21013_data); - bu21013_cs_disable(bu21013_data); + gpiod_set_value(bu21013_data->cs_gpiod, 0); + gpiod_put(bu21013_data->cs_gpiod); input_unregister_device(bu21013_data->in_dev); regulator_disable(bu21013_data->regulator); regulator_put(bu21013_data->regulator); + gpiod_put(bu21013_data->int_gpiod); + kfree(bu21013_data); return 0; diff --git a/include/linux/input/bu21013.h b/include/linux/input/bu21013.h index 7e5b7e978e8a..58b1a9d44443 100644 --- a/include/linux/input/bu21013.h +++ b/include/linux/input/bu21013.h @@ -11,8 +11,6 @@ * struct bu21013_platform_device - Handle the platform data * @touch_x_max: touch x max * @touch_y_max: touch y max - * @cs_pin: chip select pin - * @touch_pin: touch gpio pin * @ext_clk: external clock flag * @x_flip: x flip flag * @y_flip: y flip flag @@ -23,8 +21,6 @@ struct bu21013_platform_device { int touch_x_max; int touch_y_max; - unsigned int cs_pin; - unsigned int touch_pin; bool ext_clk; bool x_flip; bool y_flip; -- cgit v1.2.3 From a866781e84dd022dde5d307093555e65c31277de Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 8 Aug 2019 14:19:36 -0700 Subject: Input: bu21013_ts - rename some variables "bu21013_data" and "struct bu21013_ts_data" are a tad long, let's call them "ts" and "struct bu21013_ts". Also rename retval to error in bu21013_init_chip() and adjust formatting; i2c_smbus_write_byte_data() returns negative on error and 0 on success, so we simply test if whether erro is 0 or not. Tested-by: Linus Walleij Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/bu21013_ts.c | 376 +++++++++++++++++---------------- 1 file changed, 190 insertions(+), 186 deletions(-) diff --git a/drivers/input/touchscreen/bu21013_ts.c b/drivers/input/touchscreen/bu21013_ts.c index c20f86f98ffc..e9cb020ed725 100644 --- a/drivers/input/touchscreen/bu21013_ts.c +++ b/drivers/input/touchscreen/bu21013_ts.c @@ -135,7 +135,7 @@ #define DRIVER_TP "bu21013_tp" /** - * struct bu21013_ts_data - touch panel data structure + * struct bu21013_ts - touch panel data structure * @client: pointer to the i2c client * @wait: variable to wait_queue_head_t structure * @touch_stopped: touch stop flag @@ -147,7 +147,7 @@ * * Touch panel device data structure */ -struct bu21013_ts_data { +struct bu21013_ts { struct i2c_client *client; wait_queue_head_t wait; const struct bu21013_platform_device *chip; @@ -161,34 +161,35 @@ struct bu21013_ts_data { /** * bu21013_read_block_data(): read the touch co-ordinates - * @data: bu21013_ts_data structure pointer + * @data: bu21013_ts structure pointer * @buf: byte pointer * * Read the touch co-ordinates using i2c read block into buffer * and returns integer. */ -static int bu21013_read_block_data(struct bu21013_ts_data *data, u8 *buf) +static int bu21013_read_block_data(struct bu21013_ts *ts, u8 *buf) { int ret, i; for (i = 0; i < I2C_RETRY_COUNT; i++) { - ret = i2c_smbus_read_i2c_block_data - (data->client, BU21013_SENSORS_BTN_0_7_REG, - LENGTH_OF_BUFFER, buf); + ret = i2c_smbus_read_i2c_block_data(ts->client, + BU21013_SENSORS_BTN_0_7_REG, + LENGTH_OF_BUFFER, buf); if (ret == LENGTH_OF_BUFFER) return 0; } + return -EINVAL; } /** * bu21013_do_touch_report(): Get the touch co-ordinates - * @data: bu21013_ts_data structure pointer + * @data: bu21013_ts structure pointer * * Get the touch co-ordinates from touch sensor registers and writes * into device structure and returns integer. */ -static int bu21013_do_touch_report(struct bu21013_ts_data *data) +static int bu21013_do_touch_report(struct bu21013_ts *ts) { u8 buf[LENGTH_OF_BUFFER]; unsigned int pos_x[2], pos_y[2]; @@ -196,10 +197,7 @@ static int bu21013_do_touch_report(struct bu21013_ts_data *data) int finger_down_count = 0; int i; - if (data == NULL) - return -EINVAL; - - if (bu21013_read_block_data(data, buf) < 0) + if (bu21013_read_block_data(ts, buf) < 0) return -EINVAL; has_x_sensors = hweight32(buf[0] & BU21013_SENSORS_EN_0_7); @@ -227,21 +225,21 @@ static int bu21013_do_touch_report(struct bu21013_ts_data *data) } for (i = 0; i < finger_down_count; i++) { - if (data->chip->x_flip) - pos_x[i] = data->chip->touch_x_max - pos_x[i]; - if (data->chip->y_flip) - pos_y[i] = data->chip->touch_y_max - pos_y[i]; + if (ts->chip->x_flip) + pos_x[i] = ts->chip->touch_x_max - pos_x[i]; + if (ts->chip->y_flip) + pos_y[i] = ts->chip->touch_y_max - pos_y[i]; - input_report_abs(data->in_dev, + input_report_abs(ts->in_dev, ABS_MT_POSITION_X, pos_x[i]); - input_report_abs(data->in_dev, + input_report_abs(ts->in_dev, ABS_MT_POSITION_Y, pos_y[i]); - input_mt_sync(data->in_dev); + input_mt_sync(ts->in_dev); } } else - input_mt_sync(data->in_dev); + input_mt_sync(ts->in_dev); - input_sync(data->in_dev); + input_sync(ts->in_dev); return 0; } @@ -255,23 +253,22 @@ static int bu21013_do_touch_report(struct bu21013_ts_data *data) */ static irqreturn_t bu21013_gpio_irq(int irq, void *device_data) { - struct bu21013_ts_data *data = device_data; - struct i2c_client *i2c = data->client; + struct bu21013_ts *ts = device_data; int keep_polling; - int retval; + int error; do { - retval = bu21013_do_touch_report(data); - if (retval < 0) { - dev_err(&i2c->dev, "bu21013_do_touch_report failed\n"); + error = bu21013_do_touch_report(ts); + if (error) { + dev_err(&ts->client->dev, "%s failed\n", __func__); break; } - keep_polling = gpiod_get_value(data->int_gpiod); + keep_polling = gpiod_get_value(ts->int_gpiod); if (keep_polling) - wait_event_timeout(data->wait, data->touch_stopped, + wait_event_timeout(ts->wait, ts->touch_stopped, msecs_to_jiffies(2)); - } while (keep_polling && !data->touch_stopped); + } while (keep_polling && !ts->touch_stopped); return IRQ_HANDLED; } @@ -283,130 +280,138 @@ static irqreturn_t bu21013_gpio_irq(int irq, void *device_data) * This function is used to power on * the bu21013 controller and returns integer. */ -static int bu21013_init_chip(struct bu21013_ts_data *data) +static int bu21013_init_chip(struct bu21013_ts *ts) { - int retval; - struct i2c_client *i2c = data->client; + struct i2c_client *client = ts->client; + int error; - retval = i2c_smbus_write_byte_data(i2c, BU21013_RESET_REG, - BU21013_RESET_ENABLE); - if (retval < 0) { - dev_err(&i2c->dev, "BU21013_RESET reg write failed\n"); - return retval; + error = i2c_smbus_write_byte_data(client, BU21013_RESET_REG, + BU21013_RESET_ENABLE); + if (error) { + dev_err(&client->dev, "BU21013_RESET reg write failed\n"); + return error; } msleep(RESET_DELAY); - retval = i2c_smbus_write_byte_data(i2c, BU21013_SENSOR_0_7_REG, - BU21013_SENSORS_EN_0_7); - if (retval < 0) { - dev_err(&i2c->dev, "BU21013_SENSOR_0_7 reg write failed\n"); - return retval; + error = i2c_smbus_write_byte_data(client, BU21013_SENSOR_0_7_REG, + BU21013_SENSORS_EN_0_7); + if (error) { + dev_err(&client->dev, "BU21013_SENSOR_0_7 reg write failed\n"); + return error; } - retval = i2c_smbus_write_byte_data(i2c, BU21013_SENSOR_8_15_REG, - BU21013_SENSORS_EN_8_15); - if (retval < 0) { - dev_err(&i2c->dev, "BU21013_SENSOR_8_15 reg write failed\n"); - return retval; + error = i2c_smbus_write_byte_data(client, BU21013_SENSOR_8_15_REG, + BU21013_SENSORS_EN_8_15); + if (error) { + dev_err(&client->dev, "BU21013_SENSOR_8_15 reg write failed\n"); + return error; } - retval = i2c_smbus_write_byte_data(i2c, BU21013_SENSOR_16_23_REG, - BU21013_SENSORS_EN_16_23); - if (retval < 0) { - dev_err(&i2c->dev, "BU21013_SENSOR_16_23 reg write failed\n"); - return retval; + error = i2c_smbus_write_byte_data(client, BU21013_SENSOR_16_23_REG, + BU21013_SENSORS_EN_16_23); + if (error) { + dev_err(&client->dev, "BU21013_SENSOR_16_23 reg write failed\n"); + return error; } - retval = i2c_smbus_write_byte_data(i2c, BU21013_POS_MODE1_REG, - (BU21013_POS_MODE1_0 | BU21013_POS_MODE1_1)); - if (retval < 0) { - dev_err(&i2c->dev, "BU21013_POS_MODE1 reg write failed\n"); - return retval; + error = i2c_smbus_write_byte_data(client, BU21013_POS_MODE1_REG, + BU21013_POS_MODE1_0 | + BU21013_POS_MODE1_1); + if (error) { + dev_err(&client->dev, "BU21013_POS_MODE1 reg write failed\n"); + return error; } - retval = i2c_smbus_write_byte_data(i2c, BU21013_POS_MODE2_REG, - (BU21013_POS_MODE2_ZERO | BU21013_POS_MODE2_AVG1 | - BU21013_POS_MODE2_AVG2 | BU21013_POS_MODE2_EN_RAW | - BU21013_POS_MODE2_MULTI)); - if (retval < 0) { - dev_err(&i2c->dev, "BU21013_POS_MODE2 reg write failed\n"); - return retval; + error = i2c_smbus_write_byte_data(client, BU21013_POS_MODE2_REG, + BU21013_POS_MODE2_ZERO | + BU21013_POS_MODE2_AVG1 | + BU21013_POS_MODE2_AVG2 | + BU21013_POS_MODE2_EN_RAW | + BU21013_POS_MODE2_MULTI); + if (error) { + dev_err(&client->dev, "BU21013_POS_MODE2 reg write failed\n"); + return error; } - if (data->chip->ext_clk) - retval = i2c_smbus_write_byte_data(i2c, BU21013_CLK_MODE_REG, - (BU21013_CLK_MODE_EXT | BU21013_CLK_MODE_CALIB)); + if (ts->chip->ext_clk) + error = i2c_smbus_write_byte_data(client, BU21013_CLK_MODE_REG, + BU21013_CLK_MODE_EXT | + BU21013_CLK_MODE_CALIB); else - retval = i2c_smbus_write_byte_data(i2c, BU21013_CLK_MODE_REG, - (BU21013_CLK_MODE_DIV | BU21013_CLK_MODE_CALIB)); - if (retval < 0) { - dev_err(&i2c->dev, "BU21013_CLK_MODE reg write failed\n"); - return retval; + error = i2c_smbus_write_byte_data(client, BU21013_CLK_MODE_REG, + BU21013_CLK_MODE_DIV | + BU21013_CLK_MODE_CALIB); + if (error) { + dev_err(&client->dev, "BU21013_CLK_MODE reg write failed\n"); + return error; } - retval = i2c_smbus_write_byte_data(i2c, BU21013_IDLE_REG, - (BU21013_IDLET_0 | BU21013_IDLE_INTERMIT_EN)); - if (retval < 0) { - dev_err(&i2c->dev, "BU21013_IDLE reg write failed\n"); - return retval; + error = i2c_smbus_write_byte_data(client, BU21013_IDLE_REG, + BU21013_IDLET_0 | + BU21013_IDLE_INTERMIT_EN); + if (error) { + dev_err(&client->dev, "BU21013_IDLE reg write failed\n"); + return error; } - retval = i2c_smbus_write_byte_data(i2c, BU21013_INT_MODE_REG, - BU21013_INT_MODE_LEVEL); - if (retval < 0) { - dev_err(&i2c->dev, "BU21013_INT_MODE reg write failed\n"); - return retval; + error = i2c_smbus_write_byte_data(client, BU21013_INT_MODE_REG, + BU21013_INT_MODE_LEVEL); + if (error) { + dev_err(&client->dev, "BU21013_INT_MODE reg write failed\n"); + return error; } - retval = i2c_smbus_write_byte_data(i2c, BU21013_FILTER_REG, - (BU21013_DELTA_0_6 | - BU21013_FILTER_EN)); - if (retval < 0) { - dev_err(&i2c->dev, "BU21013_FILTER reg write failed\n"); - return retval; + error = i2c_smbus_write_byte_data(client, BU21013_FILTER_REG, + BU21013_DELTA_0_6 | + BU21013_FILTER_EN); + if (error) { + dev_err(&client->dev, "BU21013_FILTER reg write failed\n"); + return error; } - retval = i2c_smbus_write_byte_data(i2c, BU21013_TH_ON_REG, - BU21013_TH_ON_5); - if (retval < 0) { - dev_err(&i2c->dev, "BU21013_TH_ON reg write failed\n"); - return retval; + error = i2c_smbus_write_byte_data(client, BU21013_TH_ON_REG, + BU21013_TH_ON_5); + if (error) { + dev_err(&client->dev, "BU21013_TH_ON reg write failed\n"); + return error; } - retval = i2c_smbus_write_byte_data(i2c, BU21013_TH_OFF_REG, - BU21013_TH_OFF_4 | BU21013_TH_OFF_3); - if (retval < 0) { - dev_err(&i2c->dev, "BU21013_TH_OFF reg write failed\n"); - return retval; + error = i2c_smbus_write_byte_data(client, BU21013_TH_OFF_REG, + BU21013_TH_OFF_4 | BU21013_TH_OFF_3); + if (error) { + dev_err(&client->dev, "BU21013_TH_OFF reg write failed\n"); + return error; } - retval = i2c_smbus_write_byte_data(i2c, BU21013_GAIN_REG, - (BU21013_GAIN_0 | BU21013_GAIN_1)); - if (retval < 0) { - dev_err(&i2c->dev, "BU21013_GAIN reg write failed\n"); - return retval; + error = i2c_smbus_write_byte_data(client, BU21013_GAIN_REG, + BU21013_GAIN_0 | BU21013_GAIN_1); + if (error) { + dev_err(&client->dev, "BU21013_GAIN reg write failed\n"); + return error; } - retval = i2c_smbus_write_byte_data(i2c, BU21013_OFFSET_MODE_REG, - BU21013_OFFSET_MODE_DEFAULT); - if (retval < 0) { - dev_err(&i2c->dev, "BU21013_OFFSET_MODE reg write failed\n"); - return retval; + error = i2c_smbus_write_byte_data(client, BU21013_OFFSET_MODE_REG, + BU21013_OFFSET_MODE_DEFAULT); + if (error) { + dev_err(&client->dev, "BU21013_OFFSET_MODE reg write failed\n"); + return error; } - retval = i2c_smbus_write_byte_data(i2c, BU21013_XY_EDGE_REG, - (BU21013_X_EDGE_0 | BU21013_X_EDGE_2 | - BU21013_Y_EDGE_1 | BU21013_Y_EDGE_3)); - if (retval < 0) { - dev_err(&i2c->dev, "BU21013_XY_EDGE reg write failed\n"); - return retval; + error = i2c_smbus_write_byte_data(client, BU21013_XY_EDGE_REG, + BU21013_X_EDGE_0 | + BU21013_X_EDGE_2 | + BU21013_Y_EDGE_1 | + BU21013_Y_EDGE_3); + if (error) { + dev_err(&client->dev, "BU21013_XY_EDGE reg write failed\n"); + return error; } - retval = i2c_smbus_write_byte_data(i2c, BU21013_DONE_REG, - BU21013_DONE); - if (retval < 0) { - dev_err(&i2c->dev, "BU21013_REG_DONE reg write failed\n"); - return retval; + error = i2c_smbus_write_byte_data(client, BU21013_DONE_REG, + BU21013_DONE); + if (error) { + dev_err(&client->dev, "BU21013_REG_DONE reg write failed\n"); + return error; } return 0; @@ -414,16 +419,16 @@ static int bu21013_init_chip(struct bu21013_ts_data *data) /** * bu21013_free_irq() - frees IRQ registered for touchscreen - * @bu21013_data: device structure pointer + * @ts: device structure pointer * * This function signals interrupt thread to stop processing and * frees interrupt. */ -static void bu21013_free_irq(struct bu21013_ts_data *bu21013_data) +static void bu21013_free_irq(struct bu21013_ts *ts) { - bu21013_data->touch_stopped = true; - wake_up(&bu21013_data->wait); - free_irq(bu21013_data->irq, bu21013_data); + ts->touch_stopped = true; + wake_up(&ts->wait); + free_irq(ts->irq, ts); } #ifdef CONFIG_OF @@ -476,12 +481,12 @@ static int bu21013_probe(struct i2c_client *client, { const struct bu21013_platform_device *pdata = dev_get_platdata(&client->dev); - struct bu21013_ts_data *bu21013_data; + struct bu21013_ts *ts; struct input_dev *in_dev; int error; if (!i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_BYTE_DATA)) { + I2C_FUNC_SMBUS_BYTE_DATA)) { dev_err(&client->dev, "i2c smbus byte data not supported\n"); return -EIO; } @@ -492,58 +497,57 @@ static int bu21013_probe(struct i2c_client *client, return PTR_ERR(pdata); } - bu21013_data = kzalloc(sizeof(struct bu21013_ts_data), GFP_KERNEL); + ts = kzalloc(sizeof(*ts), GFP_KERNEL); in_dev = input_allocate_device(); - if (!bu21013_data || !in_dev) { + if (!ts || !in_dev) { dev_err(&client->dev, "device memory alloc failed\n"); error = -ENOMEM; goto err_free_mem; } /* Named "INT" on the chip, DT binding is "touch" */ - bu21013_data->int_gpiod = gpiod_get(&client->dev, "touch", GPIOD_IN); - error = PTR_ERR_OR_ZERO(bu21013_data->int_gpiod); + ts->int_gpiod = gpiod_get(&client->dev, "touch", GPIOD_IN); + error = PTR_ERR_OR_ZERO(ts->int_gpiod); if (error) { if (error != -EPROBE_DEFER) dev_err(&client->dev, "failed to get INT GPIO\n"); goto err_free_mem; } - gpiod_set_consumer_name(bu21013_data->int_gpiod, "BU21013 INT"); + gpiod_set_consumer_name(ts->int_gpiod, "BU21013 INT"); - bu21013_data->in_dev = in_dev; - bu21013_data->chip = pdata; - bu21013_data->client = client; - bu21013_data->irq = gpiod_to_irq(bu21013_data->int_gpiod); + ts->in_dev = in_dev; + ts->chip = pdata; + ts->client = client; + ts->irq = gpiod_to_irq(ts->int_gpiod); - bu21013_data->regulator = regulator_get(&client->dev, "avdd"); - if (IS_ERR(bu21013_data->regulator)) { + ts->regulator = regulator_get(&client->dev, "avdd"); + if (IS_ERR(ts->regulator)) { dev_err(&client->dev, "regulator_get failed\n"); - error = PTR_ERR(bu21013_data->regulator); + error = PTR_ERR(ts->regulator); goto err_put_int_gpio; } - error = regulator_enable(bu21013_data->regulator); + error = regulator_enable(ts->regulator); if (error < 0) { dev_err(&client->dev, "regulator enable failed\n"); goto err_put_regulator; } - bu21013_data->touch_stopped = false; - init_waitqueue_head(&bu21013_data->wait); + ts->touch_stopped = false; + init_waitqueue_head(&ts->wait); /* Named "CS" on the chip, DT binding is "reset" */ - bu21013_data->cs_gpiod = gpiod_get(&client->dev, "reset", - GPIOD_OUT_HIGH); - error = PTR_ERR_OR_ZERO(bu21013_data->cs_gpiod); + ts->cs_gpiod = gpiod_get(&client->dev, "reset", GPIOD_OUT_HIGH); + error = PTR_ERR_OR_ZERO(ts->cs_gpiod); if (error) { if (error != -EPROBE_DEFER) dev_err(&client->dev, "failed to get CS GPIO\n"); goto err_disable_regulator; } - gpiod_set_consumer_name(bu21013_data->cs_gpiod, "BU21013 CS"); + gpiod_set_consumer_name(ts->cs_gpiod, "BU21013 CS"); /* configure the touch panel controller */ - error = bu21013_init_chip(bu21013_data); + error = bu21013_init_chip(ts); if (error) { dev_err(&client->dev, "error in bu21013 config\n"); goto err_cs_disable; @@ -558,19 +562,19 @@ static int bu21013_probe(struct i2c_client *client, __set_bit(EV_KEY, in_dev->evbit); __set_bit(EV_ABS, in_dev->evbit); - input_set_abs_params(in_dev, ABS_MT_POSITION_X, 0, - pdata->touch_x_max, 0, 0); - input_set_abs_params(in_dev, ABS_MT_POSITION_Y, 0, - pdata->touch_y_max, 0, 0); - input_set_drvdata(in_dev, bu21013_data); + input_set_abs_params(in_dev, ABS_MT_POSITION_X, + 0, pdata->touch_x_max, 0, 0); + input_set_abs_params(in_dev, ABS_MT_POSITION_Y, + 0, pdata->touch_y_max, 0, 0); + input_set_drvdata(in_dev, ts); - error = request_threaded_irq(bu21013_data->irq, NULL, bu21013_gpio_irq, + error = request_threaded_irq(ts->irq, NULL, bu21013_gpio_irq, IRQF_TRIGGER_FALLING | IRQF_SHARED | IRQF_ONESHOT, - DRIVER_TP, bu21013_data); + DRIVER_TP, ts); if (error) { dev_err(&client->dev, "request irq %d failed\n", - bu21013_data->irq); + ts->irq); goto err_cs_disable; } @@ -581,24 +585,24 @@ static int bu21013_probe(struct i2c_client *client, } device_init_wakeup(&client->dev, pdata->wakeup); - i2c_set_clientdata(client, bu21013_data); + i2c_set_clientdata(client, ts); return 0; err_free_irq: - bu21013_free_irq(bu21013_data); + bu21013_free_irq(ts); err_cs_disable: - gpiod_set_value(bu21013_data->cs_gpiod, 0); - gpiod_put(bu21013_data->cs_gpiod); + gpiod_set_value(ts->cs_gpiod, 0); + gpiod_put(ts->cs_gpiod); err_disable_regulator: - regulator_disable(bu21013_data->regulator); + regulator_disable(ts->regulator); err_put_regulator: - regulator_put(bu21013_data->regulator); + regulator_put(ts->regulator); err_put_int_gpio: - gpiod_put(bu21013_data->int_gpiod); + gpiod_put(ts->int_gpiod); err_free_mem: input_free_device(in_dev); - kfree(bu21013_data); + kfree(ts); return error; } @@ -611,21 +615,21 @@ err_free_mem: */ static int bu21013_remove(struct i2c_client *client) { - struct bu21013_ts_data *bu21013_data = i2c_get_clientdata(client); + struct bu21013_ts *ts = i2c_get_clientdata(client); - bu21013_free_irq(bu21013_data); + bu21013_free_irq(ts); - gpiod_set_value(bu21013_data->cs_gpiod, 0); - gpiod_put(bu21013_data->cs_gpiod); + gpiod_set_value(ts->cs_gpiod, 0); + gpiod_put(ts->cs_gpiod); - input_unregister_device(bu21013_data->in_dev); + input_unregister_device(ts->in_dev); - regulator_disable(bu21013_data->regulator); - regulator_put(bu21013_data->regulator); + regulator_disable(ts->regulator); + regulator_put(ts->regulator); - gpiod_put(bu21013_data->int_gpiod); + gpiod_put(ts->int_gpiod); - kfree(bu21013_data); + kfree(ts); return 0; } @@ -640,16 +644,16 @@ static int bu21013_remove(struct i2c_client *client) */ static int bu21013_suspend(struct device *dev) { - struct bu21013_ts_data *bu21013_data = dev_get_drvdata(dev); - struct i2c_client *client = bu21013_data->client; + struct bu21013_ts *ts = dev_get_drvdata(dev); + struct i2c_client *client = ts->client; - bu21013_data->touch_stopped = true; + ts->touch_stopped = true; if (device_may_wakeup(&client->dev)) - enable_irq_wake(bu21013_data->irq); + enable_irq_wake(ts->irq); else - disable_irq(bu21013_data->irq); + disable_irq(ts->irq); - regulator_disable(bu21013_data->regulator); + regulator_disable(ts->regulator); return 0; } @@ -663,28 +667,28 @@ static int bu21013_suspend(struct device *dev) */ static int bu21013_resume(struct device *dev) { - struct bu21013_ts_data *bu21013_data = dev_get_drvdata(dev); - struct i2c_client *client = bu21013_data->client; + struct bu21013_ts *ts = dev_get_drvdata(dev); + struct i2c_client *client = ts->client; int retval; - retval = regulator_enable(bu21013_data->regulator); + retval = regulator_enable(ts->regulator); if (retval < 0) { dev_err(&client->dev, "bu21013 regulator enable failed\n"); return retval; } - retval = bu21013_init_chip(bu21013_data); + retval = bu21013_init_chip(ts); if (retval < 0) { dev_err(&client->dev, "bu21013 controller config failed\n"); return retval; } - bu21013_data->touch_stopped = false; + ts->touch_stopped = false; if (device_may_wakeup(&client->dev)) - disable_irq_wake(bu21013_data->irq); + disable_irq_wake(ts->irq); else - enable_irq(bu21013_data->irq); + enable_irq(ts->irq); return 0; } -- cgit v1.2.3 From 0570bab054106f68533dcb0de2e64c48b15d7b9f Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 8 Aug 2019 15:53:43 -0700 Subject: Input: bu21013_ts - annotate supend/resume methods as __maybe_unused Instead if #ifdef-ing out suspend and resume methods, let's mark them as __maybe_unused to get better compile time coverage. Tested-by: Linus Walleij Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/bu21013_ts.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/drivers/input/touchscreen/bu21013_ts.c b/drivers/input/touchscreen/bu21013_ts.c index e9cb020ed725..0bdadd24296f 100644 --- a/drivers/input/touchscreen/bu21013_ts.c +++ b/drivers/input/touchscreen/bu21013_ts.c @@ -634,7 +634,6 @@ static int bu21013_remove(struct i2c_client *client) return 0; } -#ifdef CONFIG_PM /** * bu21013_suspend() - suspend the touch screen controller * @dev: pointer to device structure @@ -642,7 +641,7 @@ static int bu21013_remove(struct i2c_client *client) * This function is used to suspend the * touch panel controller and returns integer */ -static int bu21013_suspend(struct device *dev) +static int __maybe_unused bu21013_suspend(struct device *dev) { struct bu21013_ts *ts = dev_get_drvdata(dev); struct i2c_client *client = ts->client; @@ -665,7 +664,7 @@ static int bu21013_suspend(struct device *dev) * This function is used to resume the touch panel * controller and returns integer. */ -static int bu21013_resume(struct device *dev) +static int __maybe_unused bu21013_resume(struct device *dev) { struct bu21013_ts *ts = dev_get_drvdata(dev); struct i2c_client *client = ts->client; @@ -693,11 +692,7 @@ static int bu21013_resume(struct device *dev) return 0; } -static const struct dev_pm_ops bu21013_dev_pm_ops = { - .suspend = bu21013_suspend, - .resume = bu21013_resume, -}; -#endif +static SIMPLE_DEV_PM_OPS(bu21013_dev_pm_ops, bu21013_suspend, bu21013_resume); static const struct i2c_device_id bu21013_id[] = { { DRIVER_TP, 0 }, @@ -708,9 +703,7 @@ MODULE_DEVICE_TABLE(i2c, bu21013_id); static struct i2c_driver bu21013_driver = { .driver = { .name = DRIVER_TP, -#ifdef CONFIG_PM .pm = &bu21013_dev_pm_ops, -#endif }, .probe = bu21013_probe, .remove = bu21013_remove, -- cgit v1.2.3 From a5ee351d5bc7c9e0abdbc3d345a503cc07d0623f Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 8 Aug 2019 16:02:43 -0700 Subject: Input: bu21013_ts - remove useless comments The comments for individual functions in the driver do not provide any additional information beyond what function names indicate. Tested-by: Linus Walleij Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/bu21013_ts.c | 61 ++-------------------------------- 1 file changed, 2 insertions(+), 59 deletions(-) diff --git a/drivers/input/touchscreen/bu21013_ts.c b/drivers/input/touchscreen/bu21013_ts.c index 0bdadd24296f..a5230f6ea5f0 100644 --- a/drivers/input/touchscreen/bu21013_ts.c +++ b/drivers/input/touchscreen/bu21013_ts.c @@ -159,14 +159,6 @@ struct bu21013_ts { bool touch_stopped; }; -/** - * bu21013_read_block_data(): read the touch co-ordinates - * @data: bu21013_ts structure pointer - * @buf: byte pointer - * - * Read the touch co-ordinates using i2c read block into buffer - * and returns integer. - */ static int bu21013_read_block_data(struct bu21013_ts *ts, u8 *buf) { int ret, i; @@ -182,13 +174,6 @@ static int bu21013_read_block_data(struct bu21013_ts *ts, u8 *buf) return -EINVAL; } -/** - * bu21013_do_touch_report(): Get the touch co-ordinates - * @data: bu21013_ts structure pointer - * - * Get the touch co-ordinates from touch sensor registers and writes - * into device structure and returns integer. - */ static int bu21013_do_touch_report(struct bu21013_ts *ts) { u8 buf[LENGTH_OF_BUFFER]; @@ -243,14 +228,7 @@ static int bu21013_do_touch_report(struct bu21013_ts *ts) return 0; } -/** - * bu21013_gpio_irq() - gpio thread function for touch interrupt - * @irq: irq value - * @device_data: void pointer - * - * This gpio thread function for touch interrupt - * and returns irqreturn_t. - */ + static irqreturn_t bu21013_gpio_irq(int irq, void *device_data) { struct bu21013_ts *ts = device_data; @@ -273,13 +251,6 @@ static irqreturn_t bu21013_gpio_irq(int irq, void *device_data) return IRQ_HANDLED; } -/** - * bu21013_init_chip() - power on sequence for the bu21013 controller - * @data: device structure pointer - * - * This function is used to power on - * the bu21013 controller and returns integer. - */ static int bu21013_init_chip(struct bu21013_ts *ts) { struct i2c_client *client = ts->client; @@ -468,14 +439,6 @@ bu21013_parse_dt(struct device *dev) } #endif -/** - * bu21013_probe() - initializes the i2c-client touchscreen driver - * @client: i2c client structure pointer - * @id: i2c device id pointer - * - * This function used to initializes the i2c-client touchscreen - * driver and returns integer. - */ static int bu21013_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -606,13 +569,7 @@ err_free_mem: return error; } -/** - * bu21013_remove() - removes the i2c-client touchscreen driver - * @client: i2c client structure pointer - * - * This function uses to remove the i2c-client - * touchscreen driver and returns integer. - */ + static int bu21013_remove(struct i2c_client *client) { struct bu21013_ts *ts = i2c_get_clientdata(client); @@ -634,13 +591,6 @@ static int bu21013_remove(struct i2c_client *client) return 0; } -/** - * bu21013_suspend() - suspend the touch screen controller - * @dev: pointer to device structure - * - * This function is used to suspend the - * touch panel controller and returns integer - */ static int __maybe_unused bu21013_suspend(struct device *dev) { struct bu21013_ts *ts = dev_get_drvdata(dev); @@ -657,13 +607,6 @@ static int __maybe_unused bu21013_suspend(struct device *dev) return 0; } -/** - * bu21013_resume() - resume the touch screen controller - * @dev: pointer to device structure - * - * This function is used to resume the touch panel - * controller and returns integer. - */ static int __maybe_unused bu21013_resume(struct device *dev) { struct bu21013_ts *ts = dev_get_drvdata(dev); -- cgit v1.2.3 From caeb1aae283f9b93d92400b1cb0395bdfd0d586c Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 8 Aug 2019 14:28:48 -0700 Subject: Input: bu21013_ts - convert to using managed resources This allows trimming error unwinding and device removal handling. Tested-by: Linus Walleij Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/bu21013_ts.c | 182 +++++++++++++++------------------ 1 file changed, 84 insertions(+), 98 deletions(-) diff --git a/drivers/input/touchscreen/bu21013_ts.c b/drivers/input/touchscreen/bu21013_ts.c index a5230f6ea5f0..2b8538a63945 100644 --- a/drivers/input/touchscreen/bu21013_ts.c +++ b/drivers/input/touchscreen/bu21013_ts.c @@ -137,7 +137,6 @@ /** * struct bu21013_ts - touch panel data structure * @client: pointer to the i2c client - * @wait: variable to wait_queue_head_t structure * @touch_stopped: touch stop flag * @chip: pointer to the touch panel controller * @in_dev: pointer to the input device structure @@ -149,7 +148,6 @@ */ struct bu21013_ts { struct i2c_client *client; - wait_queue_head_t wait; const struct bu21013_platform_device *chip; struct input_dev *in_dev; struct regulator *regulator; @@ -242,11 +240,13 @@ static irqreturn_t bu21013_gpio_irq(int irq, void *device_data) break; } + if (unlikely(ts->touch_stopped)) + break; + keep_polling = gpiod_get_value(ts->int_gpiod); if (keep_polling) - wait_event_timeout(ts->wait, ts->touch_stopped, - msecs_to_jiffies(2)); - } while (keep_polling && !ts->touch_stopped); + usleep_range(2000, 2500); + } while (keep_polling); return IRQ_HANDLED; } @@ -388,20 +388,6 @@ static int bu21013_init_chip(struct bu21013_ts *ts) return 0; } -/** - * bu21013_free_irq() - frees IRQ registered for touchscreen - * @ts: device structure pointer - * - * This function signals interrupt thread to stop processing and - * frees interrupt. - */ -static void bu21013_free_irq(struct bu21013_ts *ts) -{ - ts->touch_stopped = true; - wake_up(&ts->wait); - free_irq(ts->irq, ts); -} - #ifdef CONFIG_OF static const struct bu21013_platform_device * bu21013_parse_dt(struct device *dev) @@ -439,6 +425,20 @@ bu21013_parse_dt(struct device *dev) } #endif +static void bu21013_power_off(void *_ts) +{ + struct bu21013_ts *ts = _ts; + + regulator_disable(ts->regulator); +} + +static void bu21013_disable_chip(void *_ts) +{ + struct bu21013_ts *ts = _ts; + + gpiod_set_value(ts->cs_gpiod, 0); +} + static int bu21013_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -460,133 +460,119 @@ static int bu21013_probe(struct i2c_client *client, return PTR_ERR(pdata); } - ts = kzalloc(sizeof(*ts), GFP_KERNEL); - in_dev = input_allocate_device(); - if (!ts || !in_dev) { + ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL); + if (!ts) + return -ENOMEM; + + ts->chip = pdata; + ts->client = client; + + in_dev = devm_input_allocate_device(&client->dev); + if (!in_dev) { dev_err(&client->dev, "device memory alloc failed\n"); - error = -ENOMEM; - goto err_free_mem; + return -ENOMEM; } + ts->in_dev = in_dev; - /* Named "INT" on the chip, DT binding is "touch" */ - ts->int_gpiod = gpiod_get(&client->dev, "touch", GPIOD_IN); - error = PTR_ERR_OR_ZERO(ts->int_gpiod); - if (error) { - if (error != -EPROBE_DEFER) - dev_err(&client->dev, "failed to get INT GPIO\n"); - goto err_free_mem; - } - gpiod_set_consumer_name(ts->int_gpiod, "BU21013 INT"); + /* register the device to input subsystem */ + in_dev->name = DRIVER_TP; + in_dev->id.bustype = BUS_I2C; - ts->in_dev = in_dev; - ts->chip = pdata; - ts->client = client; - ts->irq = gpiod_to_irq(ts->int_gpiod); + __set_bit(EV_SYN, in_dev->evbit); + __set_bit(EV_KEY, in_dev->evbit); + __set_bit(EV_ABS, in_dev->evbit); + + input_set_abs_params(in_dev, ABS_MT_POSITION_X, + 0, pdata->touch_x_max, 0, 0); + input_set_abs_params(in_dev, ABS_MT_POSITION_Y, + 0, pdata->touch_y_max, 0, 0); + input_set_drvdata(in_dev, ts); - ts->regulator = regulator_get(&client->dev, "avdd"); + ts->regulator = devm_regulator_get(&client->dev, "avdd"); if (IS_ERR(ts->regulator)) { dev_err(&client->dev, "regulator_get failed\n"); - error = PTR_ERR(ts->regulator); - goto err_put_int_gpio; + return PTR_ERR(ts->regulator); } error = regulator_enable(ts->regulator); - if (error < 0) { + if (error) { dev_err(&client->dev, "regulator enable failed\n"); - goto err_put_regulator; + return error; } - ts->touch_stopped = false; - init_waitqueue_head(&ts->wait); + error = devm_add_action_or_reset(&client->dev, bu21013_power_off, ts); + if (error) { + dev_err(&client->dev, "failed to install power off handler\n"); + return error; + } /* Named "CS" on the chip, DT binding is "reset" */ - ts->cs_gpiod = gpiod_get(&client->dev, "reset", GPIOD_OUT_HIGH); + ts->cs_gpiod = devm_gpiod_get(&client->dev, "reset", GPIOD_OUT_HIGH); error = PTR_ERR_OR_ZERO(ts->cs_gpiod); if (error) { if (error != -EPROBE_DEFER) dev_err(&client->dev, "failed to get CS GPIO\n"); - goto err_disable_regulator; + return error; } gpiod_set_consumer_name(ts->cs_gpiod, "BU21013 CS"); + error = devm_add_action_or_reset(&client->dev, + bu21013_disable_chip, ts); + if (error) { + dev_err(&client->dev, + "failed to install chip disable handler\n"); + return error; + } + + /* Named "INT" on the chip, DT binding is "touch" */ + ts->int_gpiod = devm_gpiod_get(&client->dev, "touch", GPIOD_IN); + error = PTR_ERR_OR_ZERO(ts->int_gpiod); + if (error) { + if (error != -EPROBE_DEFER) + dev_err(&client->dev, "failed to get INT GPIO\n"); + return error; + } + gpiod_set_consumer_name(ts->int_gpiod, "BU21013 INT"); + /* configure the touch panel controller */ error = bu21013_init_chip(ts); if (error) { dev_err(&client->dev, "error in bu21013 config\n"); - goto err_cs_disable; + return error; } - /* register the device to input subsystem */ - in_dev->name = DRIVER_TP; - in_dev->id.bustype = BUS_I2C; - in_dev->dev.parent = &client->dev; - - __set_bit(EV_SYN, in_dev->evbit); - __set_bit(EV_KEY, in_dev->evbit); - __set_bit(EV_ABS, in_dev->evbit); - - input_set_abs_params(in_dev, ABS_MT_POSITION_X, - 0, pdata->touch_x_max, 0, 0); - input_set_abs_params(in_dev, ABS_MT_POSITION_Y, - 0, pdata->touch_y_max, 0, 0); - input_set_drvdata(in_dev, ts); - - error = request_threaded_irq(ts->irq, NULL, bu21013_gpio_irq, - IRQF_TRIGGER_FALLING | IRQF_SHARED | - IRQF_ONESHOT, - DRIVER_TP, ts); + ts->irq = gpiod_to_irq(ts->int_gpiod); + error = devm_request_threaded_irq(&client->dev, ts->irq, + NULL, bu21013_gpio_irq, + IRQF_TRIGGER_FALLING | + IRQF_SHARED | + IRQF_ONESHOT, + DRIVER_TP, ts); if (error) { dev_err(&client->dev, "request irq %d failed\n", ts->irq); - goto err_cs_disable; + return error; } error = input_register_device(in_dev); if (error) { dev_err(&client->dev, "failed to register input device\n"); - goto err_free_irq; + return error; } device_init_wakeup(&client->dev, pdata->wakeup); i2c_set_clientdata(client, ts); return 0; - -err_free_irq: - bu21013_free_irq(ts); -err_cs_disable: - gpiod_set_value(ts->cs_gpiod, 0); - gpiod_put(ts->cs_gpiod); -err_disable_regulator: - regulator_disable(ts->regulator); -err_put_regulator: - regulator_put(ts->regulator); -err_put_int_gpio: - gpiod_put(ts->int_gpiod); -err_free_mem: - input_free_device(in_dev); - kfree(ts); - - return error; } static int bu21013_remove(struct i2c_client *client) { struct bu21013_ts *ts = i2c_get_clientdata(client); - bu21013_free_irq(ts); - - gpiod_set_value(ts->cs_gpiod, 0); - gpiod_put(ts->cs_gpiod); - - input_unregister_device(ts->in_dev); - - regulator_disable(ts->regulator); - regulator_put(ts->regulator); - - gpiod_put(ts->int_gpiod); - - kfree(ts); + /* Make sure IRQ will exit quickly even if there is contact */ + ts->touch_stopped = true; + /* The resources will be freed by devm */ return 0; } -- cgit v1.2.3 From 1eb7b4cacc01771ae42fcbc5ae9a4bc1d13c1dbc Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 8 Aug 2019 12:09:43 -0700 Subject: Input: bu21013_ts - remove support for platform data There are no current users of the platform data in the tree, and any new users should either use device tree, or static device properties to describe the device. This change drop the platform data definition and handling and moves the driver over to generic device properties API. We also drop support for the external clock. If it is needed we will have to extend the bindings to supply the clock reference and handle it properly in the driver. Also, wakeup setting should be coming from I2C client. Tested-by: Linus Walleij Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/bu21013_ts.c | 109 +++++++++++---------------------- include/linux/input/bu21013.h | 30 --------- 2 files changed, 37 insertions(+), 102 deletions(-) delete mode 100644 include/linux/input/bu21013.h diff --git a/drivers/input/touchscreen/bu21013_ts.c b/drivers/input/touchscreen/bu21013_ts.c index 2b8538a63945..f3b3e4c72c84 100644 --- a/drivers/input/touchscreen/bu21013_ts.c +++ b/drivers/input/touchscreen/bu21013_ts.c @@ -4,18 +4,18 @@ * Author: Naveen Kumar G for ST-Ericsson */ -#include +#include #include -#include +#include #include -#include #include -#include -#include -#include +#include +#include #include -#include -#include +#include +#include +#include +#include #define MAX_FINGERS 2 #define RESET_DELAY 30 @@ -137,23 +137,32 @@ /** * struct bu21013_ts - touch panel data structure * @client: pointer to the i2c client - * @touch_stopped: touch stop flag - * @chip: pointer to the touch panel controller * @in_dev: pointer to the input device structure * @regulator: pointer to the Regulator used for touch screen * @cs_gpiod: chip select GPIO line * @int_gpiod: touch interrupt GPIO line + * @irq: interrupt number the device is using + * @touch_x_max: maximum X coordinate reported by the device + * @touch_y_max: maximum Y coordinate reported by the device + * @x_flip: indicates that the driver should invert X coordinate before + * reporting + * @y_flip: indicates that the driver should invert Y coordinate before + * reporting + * @touch_stopped: touch stop flag * * Touch panel device data structure */ struct bu21013_ts { struct i2c_client *client; - const struct bu21013_platform_device *chip; struct input_dev *in_dev; struct regulator *regulator; struct gpio_desc *cs_gpiod; struct gpio_desc *int_gpiod; unsigned int irq; + u32 touch_x_max; + u32 touch_y_max; + bool x_flip; + bool y_flip; bool touch_stopped; }; @@ -208,10 +217,10 @@ static int bu21013_do_touch_report(struct bu21013_ts *ts) } for (i = 0; i < finger_down_count; i++) { - if (ts->chip->x_flip) - pos_x[i] = ts->chip->touch_x_max - pos_x[i]; - if (ts->chip->y_flip) - pos_y[i] = ts->chip->touch_y_max - pos_y[i]; + if (ts->x_flip) + pos_x[i] = ts->touch_x_max - pos_x[i]; + if (ts->y_flip) + pos_y[i] = ts->touch_y_max - pos_y[i]; input_report_abs(ts->in_dev, ABS_MT_POSITION_X, pos_x[i]); @@ -304,14 +313,9 @@ static int bu21013_init_chip(struct bu21013_ts *ts) return error; } - if (ts->chip->ext_clk) - error = i2c_smbus_write_byte_data(client, BU21013_CLK_MODE_REG, - BU21013_CLK_MODE_EXT | - BU21013_CLK_MODE_CALIB); - else - error = i2c_smbus_write_byte_data(client, BU21013_CLK_MODE_REG, - BU21013_CLK_MODE_DIV | - BU21013_CLK_MODE_CALIB); + error = i2c_smbus_write_byte_data(client, BU21013_CLK_MODE_REG, + BU21013_CLK_MODE_DIV | + BU21013_CLK_MODE_CALIB); if (error) { dev_err(&client->dev, "BU21013_CLK_MODE reg write failed\n"); return error; @@ -388,43 +392,6 @@ static int bu21013_init_chip(struct bu21013_ts *ts) return 0; } -#ifdef CONFIG_OF -static const struct bu21013_platform_device * -bu21013_parse_dt(struct device *dev) -{ - struct device_node *np = dev->of_node; - struct bu21013_platform_device *pdata; - - if (!np) { - dev_err(dev, "no device tree or platform data\n"); - return ERR_PTR(-EINVAL); - } - - pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) - return ERR_PTR(-ENOMEM); - - pdata->y_flip = pdata->x_flip = false; - - pdata->x_flip = of_property_read_bool(np, "rohm,flip-x"); - pdata->y_flip = of_property_read_bool(np, "rohm,flip-y"); - - of_property_read_u32(np, "rohm,touch-max-x", &pdata->touch_x_max); - of_property_read_u32(np, "rohm,touch-max-y", &pdata->touch_y_max); - - pdata->ext_clk = false; - - return pdata; -} -#else -static inline const struct bu21013_platform_device * -bu21013_parse_dt(struct device *dev) -{ - dev_err(dev, "no platform data available\n"); - return ERR_PTR(-EINVAL); -} -#endif - static void bu21013_power_off(void *_ts) { struct bu21013_ts *ts = _ts; @@ -442,8 +409,6 @@ static void bu21013_disable_chip(void *_ts) static int bu21013_probe(struct i2c_client *client, const struct i2c_device_id *id) { - const struct bu21013_platform_device *pdata = - dev_get_platdata(&client->dev); struct bu21013_ts *ts; struct input_dev *in_dev; int error; @@ -454,19 +419,20 @@ static int bu21013_probe(struct i2c_client *client, return -EIO; } - if (!pdata) { - pdata = bu21013_parse_dt(&client->dev); - if (IS_ERR(pdata)) - return PTR_ERR(pdata); - } - ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL); if (!ts) return -ENOMEM; - ts->chip = pdata; ts->client = client; + ts->x_flip = device_property_read_bool(&client->dev, "rohm,flip-x"); + ts->y_flip = device_property_read_bool(&client->dev, "rohm,flip-y"); + + device_property_read_u32(&client->dev, "rohm,touch-max-x", + &ts->touch_x_max); + device_property_read_u32(&client->dev, "rohm,touch-max-y", + &ts->touch_y_max); + in_dev = devm_input_allocate_device(&client->dev); if (!in_dev) { dev_err(&client->dev, "device memory alloc failed\n"); @@ -483,9 +449,9 @@ static int bu21013_probe(struct i2c_client *client, __set_bit(EV_ABS, in_dev->evbit); input_set_abs_params(in_dev, ABS_MT_POSITION_X, - 0, pdata->touch_x_max, 0, 0); + 0, ts->touch_x_max, 0, 0); input_set_abs_params(in_dev, ABS_MT_POSITION_Y, - 0, pdata->touch_y_max, 0, 0); + 0, ts->touch_y_max, 0, 0); input_set_drvdata(in_dev, ts); ts->regulator = devm_regulator_get(&client->dev, "avdd"); @@ -560,7 +526,6 @@ static int bu21013_probe(struct i2c_client *client, return error; } - device_init_wakeup(&client->dev, pdata->wakeup); i2c_set_clientdata(client, ts); return 0; diff --git a/include/linux/input/bu21013.h b/include/linux/input/bu21013.h deleted file mode 100644 index 58b1a9d44443..000000000000 --- a/include/linux/input/bu21013.h +++ /dev/null @@ -1,30 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (C) ST-Ericsson SA 2010 - * Author: Naveen Kumar G for ST-Ericsson - */ - -#ifndef _BU21013_H -#define _BU21013_H - -/** - * struct bu21013_platform_device - Handle the platform data - * @touch_x_max: touch x max - * @touch_y_max: touch y max - * @ext_clk: external clock flag - * @x_flip: x flip flag - * @y_flip: y flip flag - * @wakeup: wakeup flag - * - * This is used to handle the platform data - */ -struct bu21013_platform_device { - int touch_x_max; - int touch_y_max; - bool ext_clk; - bool x_flip; - bool y_flip; - bool wakeup; -}; - -#endif -- cgit v1.2.3 From db3e34d4036db59cbacc1bff1c622b23d85b766b Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 9 Aug 2019 10:07:06 -0700 Subject: Input: bu21013_ts - use interrupt from I2C client Instead of trying to map INT GPIO to interrupt, let's use one supplied by I2C client. If there is none - bail. This will also allow us to treat INT GPIO as optional, as per the binding. Tested-by: Linus Walleij Signed-off-by: Dmitry Torokhov --- .../bindings/input/touchscreen/bu21013.txt | 6 +++- drivers/input/touchscreen/bu21013_ts.c | 35 ++++++++++++---------- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/Documentation/devicetree/bindings/input/touchscreen/bu21013.txt b/Documentation/devicetree/bindings/input/touchscreen/bu21013.txt index 43899fc36ecf..7ddb5de8343d 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/bu21013.txt +++ b/Documentation/devicetree/bindings/input/touchscreen/bu21013.txt @@ -4,6 +4,8 @@ Required properties: - compatible : "rohm,bu21013_tp" - reg : I2C device address - reset-gpios : GPIO pin enabling (selecting) chip (CS) + - interrupt-parent : the phandle for the gpio controller + - interrupts : (gpio) interrupt to which the chip is connected Optional properties: - touch-gpios : GPIO pin registering a touch event @@ -19,7 +21,9 @@ Example: bu21013_tp@5c { compatible = "rohm,bu21013_tp"; reg = <0x5c>; - touch-gpio = <&gpio2 20 0x4>; + interrupt-parent = <&gpio2>; + interrupts <&20 IRQ_TYPE_LEVEL_LOW>; + touch-gpio = <&gpio2 20 GPIO_ACTIVE_LOW>; avdd-supply = <&ab8500_ldo_aux1_reg>; rohm,touch-max-x = <384>; diff --git a/drivers/input/touchscreen/bu21013_ts.c b/drivers/input/touchscreen/bu21013_ts.c index f3b3e4c72c84..77ef0275c447 100644 --- a/drivers/input/touchscreen/bu21013_ts.c +++ b/drivers/input/touchscreen/bu21013_ts.c @@ -141,7 +141,6 @@ * @regulator: pointer to the Regulator used for touch screen * @cs_gpiod: chip select GPIO line * @int_gpiod: touch interrupt GPIO line - * @irq: interrupt number the device is using * @touch_x_max: maximum X coordinate reported by the device * @touch_y_max: maximum Y coordinate reported by the device * @x_flip: indicates that the driver should invert X coordinate before @@ -158,7 +157,6 @@ struct bu21013_ts { struct regulator *regulator; struct gpio_desc *cs_gpiod; struct gpio_desc *int_gpiod; - unsigned int irq; u32 touch_x_max; u32 touch_y_max; bool x_flip; @@ -252,7 +250,8 @@ static irqreturn_t bu21013_gpio_irq(int irq, void *device_data) if (unlikely(ts->touch_stopped)) break; - keep_polling = gpiod_get_value(ts->int_gpiod); + keep_polling = ts->int_gpiod ? + gpiod_get_value(ts->int_gpiod) : false; if (keep_polling) usleep_range(2000, 2500); } while (keep_polling); @@ -419,6 +418,11 @@ static int bu21013_probe(struct i2c_client *client, return -EIO; } + if (!client->irq) { + dev_err(&client->dev, "No IRQ set up\n"); + return -EINVAL; + } + ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL); if (!ts) return -ENOMEM; @@ -491,14 +495,17 @@ static int bu21013_probe(struct i2c_client *client, } /* Named "INT" on the chip, DT binding is "touch" */ - ts->int_gpiod = devm_gpiod_get(&client->dev, "touch", GPIOD_IN); + ts->int_gpiod = devm_gpiod_get_optional(&client->dev, + "touch", GPIOD_IN); error = PTR_ERR_OR_ZERO(ts->int_gpiod); if (error) { if (error != -EPROBE_DEFER) dev_err(&client->dev, "failed to get INT GPIO\n"); return error; } - gpiod_set_consumer_name(ts->int_gpiod, "BU21013 INT"); + + if (ts->int_gpiod) + gpiod_set_consumer_name(ts->int_gpiod, "BU21013 INT"); /* configure the touch panel controller */ error = bu21013_init_chip(ts); @@ -507,16 +514,12 @@ static int bu21013_probe(struct i2c_client *client, return error; } - ts->irq = gpiod_to_irq(ts->int_gpiod); - error = devm_request_threaded_irq(&client->dev, ts->irq, + error = devm_request_threaded_irq(&client->dev, client->irq, NULL, bu21013_gpio_irq, - IRQF_TRIGGER_FALLING | - IRQF_SHARED | - IRQF_ONESHOT, - DRIVER_TP, ts); + IRQF_ONESHOT, DRIVER_TP, ts); if (error) { dev_err(&client->dev, "request irq %d failed\n", - ts->irq); + client->irq); return error; } @@ -549,9 +552,9 @@ static int __maybe_unused bu21013_suspend(struct device *dev) ts->touch_stopped = true; if (device_may_wakeup(&client->dev)) - enable_irq_wake(ts->irq); + enable_irq_wake(client->irq); else - disable_irq(ts->irq); + disable_irq(client->irq); regulator_disable(ts->regulator); @@ -579,9 +582,9 @@ static int __maybe_unused bu21013_resume(struct device *dev) ts->touch_stopped = false; if (device_may_wakeup(&client->dev)) - disable_irq_wake(ts->irq); + disable_irq_wake(client->irq); else - enable_irq(ts->irq); + enable_irq(client->irq); return 0; } -- cgit v1.2.3 From 18aa4d6b67483b4dac08a537f6c4fc943eea5386 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 8 Aug 2019 17:41:12 -0700 Subject: Input: bu21013_ts - fix suspend when wake source If the touchscreen is configured as wakeup source we should not be cutting off power to it. Also, now that the driver relies on I2C client to supply IRQ, we do not need to explicitly enable and disable IRQ for wakeup: if device is created as wakeup source, I2C core will mark interrupt as wakeup one. Tested-by: Linus Walleij Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/bu21013_ts.c | 48 +++++++++++++++++----------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/drivers/input/touchscreen/bu21013_ts.c b/drivers/input/touchscreen/bu21013_ts.c index 77ef0275c447..e617847ece65 100644 --- a/drivers/input/touchscreen/bu21013_ts.c +++ b/drivers/input/touchscreen/bu21013_ts.c @@ -547,44 +547,44 @@ static int bu21013_remove(struct i2c_client *client) static int __maybe_unused bu21013_suspend(struct device *dev) { - struct bu21013_ts *ts = dev_get_drvdata(dev); - struct i2c_client *client = ts->client; + struct i2c_client *client = to_i2c_client(dev); + struct bu21013_ts *ts = i2c_get_clientdata(client); ts->touch_stopped = true; - if (device_may_wakeup(&client->dev)) - enable_irq_wake(client->irq); - else - disable_irq(client->irq); + mb(); + disable_irq(client->irq); - regulator_disable(ts->regulator); + if (!device_may_wakeup(&client->dev)) + regulator_disable(ts->regulator); return 0; } static int __maybe_unused bu21013_resume(struct device *dev) { - struct bu21013_ts *ts = dev_get_drvdata(dev); - struct i2c_client *client = ts->client; - int retval; + struct i2c_client *client = to_i2c_client(dev); + struct bu21013_ts *ts = i2c_get_clientdata(client); + int error; - retval = regulator_enable(ts->regulator); - if (retval < 0) { - dev_err(&client->dev, "bu21013 regulator enable failed\n"); - return retval; - } + if (!device_may_wakeup(&client->dev)) { + error = regulator_enable(ts->regulator); + if (error) { + dev_err(&client->dev, + "failed to re-enable regulator when resuming\n"); + return error; + } - retval = bu21013_init_chip(ts); - if (retval < 0) { - dev_err(&client->dev, "bu21013 controller config failed\n"); - return retval; + error = bu21013_init_chip(ts); + if (error) { + dev_err(&client->dev, + "failed to reinitialize chip when resuming\n"); + return error; + } } ts->touch_stopped = false; - - if (device_may_wakeup(&client->dev)) - disable_irq_wake(client->irq); - else - enable_irq(client->irq); + mb(); + enable_irq(client->irq); return 0; } -- cgit v1.2.3 From 307ec663f6c3e9a0a80c7092a1dea6e09debc127 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 9 Aug 2019 12:08:14 -0700 Subject: Input: bu21013_ts - switch to using MT-B (slotted) protocol MT-B protocol is more efficient and everyone expects it. We use in-kernel tracking to identify contacts. Tested-by: Linus Walleij Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/bu21013_ts.c | 80 ++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 37 deletions(-) diff --git a/drivers/input/touchscreen/bu21013_ts.c b/drivers/input/touchscreen/bu21013_ts.c index e617847ece65..2bff3f3f4464 100644 --- a/drivers/input/touchscreen/bu21013_ts.c +++ b/drivers/input/touchscreen/bu21013_ts.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -181,11 +182,13 @@ static int bu21013_read_block_data(struct bu21013_ts *ts, u8 *buf) static int bu21013_do_touch_report(struct bu21013_ts *ts) { - u8 buf[LENGTH_OF_BUFFER]; - unsigned int pos_x[2], pos_y[2]; - bool has_x_sensors, has_y_sensors; - int finger_down_count = 0; - int i; + struct input_dev *input = ts->in_dev; + struct input_mt_pos pos[MAX_FINGERS]; + int slots[MAX_FINGERS]; + u8 buf[LENGTH_OF_BUFFER]; + bool has_x_sensors, has_y_sensors; + int finger_down_count = 0; + int i; if (bu21013_read_block_data(ts, buf) < 0) return -EINVAL; @@ -197,39 +200,38 @@ static int bu21013_do_touch_report(struct bu21013_ts *ts) return 0; for (i = 0; i < MAX_FINGERS; i++) { - const u8 *p = &buf[4 * i + 3]; - unsigned int x = p[0] << SHIFT_2 | (p[1] & MASK_BITS); - unsigned int y = p[2] << SHIFT_2 | (p[3] & MASK_BITS); - if (x == 0 || y == 0) + const u8 *data = &buf[4 * i + 3]; + struct input_mt_pos *p = &pos[finger_down_count]; + + p->x = data[0] << SHIFT_2 | (data[1] & MASK_BITS); + p->y = data[2] << SHIFT_2 | (data[3] & MASK_BITS); + if (p->x == 0 || p->y == 0) continue; - pos_x[finger_down_count] = x; - pos_y[finger_down_count] = y; + finger_down_count++; + + if (ts->x_flip) + p->x = ts->touch_x_max - p->x; + if (ts->y_flip) + p->y = ts->touch_y_max - p->y; } - if (finger_down_count) { - if (finger_down_count == 2 && - (abs(pos_x[0] - pos_x[1]) < DELTA_MIN || - abs(pos_y[0] - pos_y[1]) < DELTA_MIN)) { - return 0; - } + if (finger_down_count == 2 && + (abs(pos[0].x - pos[1].x) < DELTA_MIN || + abs(pos[0].y - pos[1].y) < DELTA_MIN)) { + return 0; + } - for (i = 0; i < finger_down_count; i++) { - if (ts->x_flip) - pos_x[i] = ts->touch_x_max - pos_x[i]; - if (ts->y_flip) - pos_y[i] = ts->touch_y_max - pos_y[i]; - - input_report_abs(ts->in_dev, - ABS_MT_POSITION_X, pos_x[i]); - input_report_abs(ts->in_dev, - ABS_MT_POSITION_Y, pos_y[i]); - input_mt_sync(ts->in_dev); - } - } else - input_mt_sync(ts->in_dev); + input_mt_assign_slots(input, slots, pos, finger_down_count, DELTA_MIN); + for (i = 0; i < finger_down_count; i++) { + input_mt_slot(input, slots[i]); + input_mt_report_slot_state(input, MT_TOOL_FINGER, true); + input_report_abs(input, ABS_MT_POSITION_X, pos[i].x); + input_report_abs(input, ABS_MT_POSITION_Y, pos[i].y); + } - input_sync(ts->in_dev); + input_mt_sync_frame(input); + input_sync(input); return 0; } @@ -443,20 +445,24 @@ static int bu21013_probe(struct i2c_client *client, return -ENOMEM; } ts->in_dev = in_dev; + input_set_drvdata(in_dev, ts); /* register the device to input subsystem */ in_dev->name = DRIVER_TP; in_dev->id.bustype = BUS_I2C; - __set_bit(EV_SYN, in_dev->evbit); - __set_bit(EV_KEY, in_dev->evbit); - __set_bit(EV_ABS, in_dev->evbit); - input_set_abs_params(in_dev, ABS_MT_POSITION_X, 0, ts->touch_x_max, 0, 0); input_set_abs_params(in_dev, ABS_MT_POSITION_Y, 0, ts->touch_y_max, 0, 0); - input_set_drvdata(in_dev, ts); + + error = input_mt_init_slots(in_dev, MAX_FINGERS, + INPUT_MT_DIRECT | INPUT_MT_TRACK | + INPUT_MT_DROP_UNUSED); + if (error) { + dev_err(&client->dev, "failed to initialize MT slots"); + return error; + } ts->regulator = devm_regulator_get(&client->dev, "avdd"); if (IS_ERR(ts->regulator)) { -- cgit v1.2.3 From 4b6253fa736494346bab381114611e358afae545 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 9 Aug 2019 12:50:15 -0700 Subject: Input: bu21013_ts - switch to using standard touchscreen properties This switches the driver over to the standard touchscreen properties for coordinate transformation, while keeping old bindings working as well. Tested-by: Linus Walleij Signed-off-by: Dmitry Torokhov --- .../bindings/input/touchscreen/bu21013.txt | 16 +++++-- drivers/input/touchscreen/bu21013_ts.c | 54 +++++++++++++--------- 2 files changed, 46 insertions(+), 24 deletions(-) diff --git a/Documentation/devicetree/bindings/input/touchscreen/bu21013.txt b/Documentation/devicetree/bindings/input/touchscreen/bu21013.txt index 7ddb5de8343d..da4c9d8b99b1 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/bu21013.txt +++ b/Documentation/devicetree/bindings/input/touchscreen/bu21013.txt @@ -10,6 +10,16 @@ Required properties: Optional properties: - touch-gpios : GPIO pin registering a touch event - -supply : Phandle to a regulator supply + - touchscreen-size-x : General touchscreen binding, see [1]. + - touchscreen-size-y : General touchscreen binding, see [1]. + - touchscreen-inverted-x : General touchscreen binding, see [1]. + - touchscreen-inverted-y : General touchscreen binding, see [1]. + - touchscreen-swapped-x-y : General touchscreen binding, see [1]. + +[1] All general touchscreen properties are described in + Documentation/devicetree/bindings/input/touchscreen/touchscreen.txt. + +Deprecated properties: - rohm,touch-max-x : Maximum outward permitted limit in the X axis - rohm,touch-max-y : Maximum outward permitted limit in the Y axis - rohm,flip-x : Flip touch coordinates on the X axis @@ -26,8 +36,8 @@ Example: touch-gpio = <&gpio2 20 GPIO_ACTIVE_LOW>; avdd-supply = <&ab8500_ldo_aux1_reg>; - rohm,touch-max-x = <384>; - rohm,touch-max-y = <704>; - rohm,flip-y; + touchscreen-size-x = <384>; + touchscreen-size-y = <704>; + touchscreen-inverted-y; }; }; diff --git a/drivers/input/touchscreen/bu21013_ts.c b/drivers/input/touchscreen/bu21013_ts.c index 2bff3f3f4464..2f1f0d7607f8 100644 --- a/drivers/input/touchscreen/bu21013_ts.c +++ b/drivers/input/touchscreen/bu21013_ts.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -139,6 +140,7 @@ * struct bu21013_ts - touch panel data structure * @client: pointer to the i2c client * @in_dev: pointer to the input device structure + * @props: the device coordinate transformation properties * @regulator: pointer to the Regulator used for touch screen * @cs_gpiod: chip select GPIO line * @int_gpiod: touch interrupt GPIO line @@ -155,6 +157,7 @@ struct bu21013_ts { struct i2c_client *client; struct input_dev *in_dev; + struct touchscreen_properties props; struct regulator *regulator; struct gpio_desc *cs_gpiod; struct gpio_desc *int_gpiod; @@ -201,19 +204,13 @@ static int bu21013_do_touch_report(struct bu21013_ts *ts) for (i = 0; i < MAX_FINGERS; i++) { const u8 *data = &buf[4 * i + 3]; - struct input_mt_pos *p = &pos[finger_down_count]; + unsigned int x, y; - p->x = data[0] << SHIFT_2 | (data[1] & MASK_BITS); - p->y = data[2] << SHIFT_2 | (data[3] & MASK_BITS); - if (p->x == 0 || p->y == 0) - continue; - - finger_down_count++; - - if (ts->x_flip) - p->x = ts->touch_x_max - p->x; - if (ts->y_flip) - p->y = ts->touch_y_max - p->y; + x = data[0] << SHIFT_2 | (data[1] & MASK_BITS); + y = data[2] << SHIFT_2 | (data[3] & MASK_BITS); + if (x != 0 && y != 0) + touchscreen_set_mt_pos(&pos[finger_down_count++], + &ts->props, x, y); } if (finger_down_count == 2 && @@ -412,6 +409,8 @@ static int bu21013_probe(struct i2c_client *client, { struct bu21013_ts *ts; struct input_dev *in_dev; + struct input_absinfo *info; + u32 max_x = 0, max_y = 0; int error; if (!i2c_check_functionality(client->adapter, @@ -434,11 +433,6 @@ static int bu21013_probe(struct i2c_client *client, ts->x_flip = device_property_read_bool(&client->dev, "rohm,flip-x"); ts->y_flip = device_property_read_bool(&client->dev, "rohm,flip-y"); - device_property_read_u32(&client->dev, "rohm,touch-max-x", - &ts->touch_x_max); - device_property_read_u32(&client->dev, "rohm,touch-max-y", - &ts->touch_y_max); - in_dev = devm_input_allocate_device(&client->dev); if (!in_dev) { dev_err(&client->dev, "device memory alloc failed\n"); @@ -451,10 +445,28 @@ static int bu21013_probe(struct i2c_client *client, in_dev->name = DRIVER_TP; in_dev->id.bustype = BUS_I2C; - input_set_abs_params(in_dev, ABS_MT_POSITION_X, - 0, ts->touch_x_max, 0, 0); - input_set_abs_params(in_dev, ABS_MT_POSITION_Y, - 0, ts->touch_y_max, 0, 0); + device_property_read_u32(&client->dev, "rohm,touch-max-x", &max_x); + device_property_read_u32(&client->dev, "rohm,touch-max-y", &max_y); + + input_set_abs_params(in_dev, ABS_MT_POSITION_X, 0, max_x, 0, 0); + input_set_abs_params(in_dev, ABS_MT_POSITION_Y, 0, max_y, 0, 0); + + touchscreen_parse_properties(in_dev, true, &ts->props); + + /* Adjust for the legacy "flip" properties, if present */ + if (!ts->props.invert_x && + device_property_read_bool(&client->dev, "rohm,flip-x")) { + info = &in_dev->absinfo[ABS_MT_POSITION_X]; + info->maximum -= info->minimum; + info->minimum = 0; + } + + if (!ts->props.invert_y && + device_property_read_bool(&client->dev, "rohm,flip-y")) { + info = &in_dev->absinfo[ABS_MT_POSITION_Y]; + info->maximum -= info->minimum; + info->minimum = 0; + } error = input_mt_init_slots(in_dev, MAX_FINGERS, INPUT_MT_DIRECT | INPUT_MT_TRACK | -- cgit v1.2.3 From 4370b231d1001e0b560f82fd93616c7e54bd5fda Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 29 Aug 2019 16:55:26 -0700 Subject: Input: reset device timestamp on sync We need to reset input device's timestamp on input_sync(), otherwise drivers not using input_set_timestamp() will end up with a stale timestamp after their clients consume first input event. Fixes: 3b51c44bd693 ("Input: allow drivers specify timestamp for input events") Reported-by: John Stultz Signed-off-by: Dmitry Torokhov --- drivers/input/input.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/input/input.c b/drivers/input/input.c index c08aa3596144..55086279d044 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -397,6 +397,13 @@ static void input_handle_event(struct input_dev *dev, if (dev->num_vals >= 2) input_pass_values(dev, dev->vals, dev->num_vals); dev->num_vals = 0; + /* + * Reset the timestamp on flush so we won't end up + * with a stale one. Note we only need to reset the + * monolithic one as we use its presence when deciding + * whether to generate a synthetic timestamp. + */ + dev->timestamp[INPUT_CLK_MONO] = ktime_set(0, 0); } else if (dev->num_vals >= dev->max_vals - 2) { dev->vals[dev->num_vals++] = input_value_sync; input_pass_values(dev, dev->vals, dev->num_vals); -- cgit v1.2.3 From 410f25de467ee94c1a577c6ee7370c37b376c17c Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 5 Sep 2019 12:01:30 -0700 Subject: Input: sidewinder - make array seq static const, makes object smaller Don't populate the array seq on the stack but instead make it static const. Makes the object code smaller by 30 bytes. Before: text data bss dec hex filename 22284 3184 0 25468 637c drivers/input/joystick/sidewinder.o After: text data bss dec hex filename 22158 3280 0 25438 635e drivers/input/joystick/sidewinder.o (gcc version 9.2.1, amd64) Signed-off-by: Colin Ian King Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/sidewinder.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/joystick/sidewinder.c b/drivers/input/joystick/sidewinder.c index 0284da874a2b..1777e68c9f02 100644 --- a/drivers/input/joystick/sidewinder.c +++ b/drivers/input/joystick/sidewinder.c @@ -223,7 +223,7 @@ static __u64 sw_get_bits(unsigned char *buf, int pos, int num, char bits) static void sw_init_digital(struct gameport *gameport) { - int seq[] = { 140, 140+725, 140+300, 0 }; + static const int seq[] = { 140, 140+725, 140+300, 0 }; unsigned long flags; int i, t; -- cgit v1.2.3