From 463fa44eec2fef50d111ed0199cf593235065c04 Mon Sep 17 00:00:00 2001 From: Evan Green Date: Wed, 2 Oct 2019 14:00:21 -0700 Subject: [PATCH 01/70] Input: atmel_mxt_ts - disable IRQ across suspend Across suspend and resume, we are seeing error messages like the following: atmel_mxt_ts i2c-PRP0001:00: __mxt_read_reg: i2c transfer failed (-121) atmel_mxt_ts i2c-PRP0001:00: Failed to read T44 and T5 (-121) This occurs because the driver leaves its IRQ enabled. Upon resume, there is an IRQ pending, but the interrupt is serviced before both the driver and the underlying I2C bus have been resumed. This causes EREMOTEIO errors. Disable the IRQ in suspend, and re-enable it on resume. If there are cases where the driver enters suspend with interrupts disabled, that's a bug we should fix separately. Signed-off-by: Evan Green Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/atmel_mxt_ts.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 24c4b691b1c9..ae60442efda0 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -3156,6 +3156,8 @@ static int __maybe_unused mxt_suspend(struct device *dev) mutex_unlock(&input_dev->mutex); + disable_irq(data->irq); + return 0; } @@ -3168,6 +3170,8 @@ static int __maybe_unused mxt_resume(struct device *dev) if (!input_dev) return 0; + enable_irq(data->irq); + mutex_lock(&input_dev->mutex); if (input_dev->users) From 894616f79200f74af6a0426fa20d986b1f45cd9b Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 2 Oct 2019 10:20:19 -0700 Subject: [PATCH 02/70] Input: add input_get_poll_interval() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some drivers need to be able to know the current polling interval for devices working in polling mode, let's allow them fetching it. Acked-By: Benjamin Tissoires Tested-by: Michal Vokáč Signed-off-by: Dmitry Torokhov --- drivers/input/input-poller.c | 9 +++++++++ include/linux/input.h | 1 + 2 files changed, 10 insertions(+) diff --git a/drivers/input/input-poller.c b/drivers/input/input-poller.c index 1b3d28964bb2..7d6b4e8879f1 100644 --- a/drivers/input/input-poller.c +++ b/drivers/input/input-poller.c @@ -123,6 +123,15 @@ void input_set_max_poll_interval(struct input_dev *dev, unsigned int interval) } EXPORT_SYMBOL(input_set_max_poll_interval); +int input_get_poll_interval(struct input_dev *dev) +{ + if (!dev->poller) + return -EINVAL; + + return dev->poller->poll_interval; +} +EXPORT_SYMBOL(input_get_poll_interval); + /* SYSFS interface */ static ssize_t input_dev_get_poll_interval(struct device *dev, diff --git a/include/linux/input.h b/include/linux/input.h index 94f277cd806a..56f2fd32e609 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -383,6 +383,7 @@ int input_setup_polling(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 input_get_poll_interval(struct input_dev *dev); int __must_check input_register_handler(struct input_handler *); void input_unregister_handler(struct input_handler *); From 3df955f870c214368d73236733b8a9e5a994b2c3 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 17 Sep 2019 08:56:50 -0700 Subject: [PATCH 03/70] Input: gpio_mouse - switch to using input device polling mode Now that instances of input_dev support polling mode natively, we no longer need to create input_polled_dev instance. Acked-by: Hans-Christian Noren Egtvedt Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/Kconfig | 1 - drivers/input/mouse/gpio_mouse.c | 45 ++++++++++++++------------------ 2 files changed, 20 insertions(+), 26 deletions(-) diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index 652c38e3c0b5..bf738d3b7fe4 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig @@ -381,7 +381,6 @@ config MOUSE_VSXXXAA config MOUSE_GPIO tristate "GPIO mouse" depends on GPIOLIB || COMPILE_TEST - select INPUT_POLLDEV help This driver simulates a mouse on GPIO lines of various CPUs (and some other chips). diff --git a/drivers/input/mouse/gpio_mouse.c b/drivers/input/mouse/gpio_mouse.c index 461436f6f087..23507fce3a2b 100644 --- a/drivers/input/mouse/gpio_mouse.c +++ b/drivers/input/mouse/gpio_mouse.c @@ -8,7 +8,7 @@ #include #include -#include +#include #include #include #include @@ -43,10 +43,9 @@ struct gpio_mouse { * Timer function which is run every scan_ms ms when the device is opened. * The dev input variable is set to the the input_dev pointer. */ -static void gpio_mouse_scan(struct input_polled_dev *dev) +static void gpio_mouse_scan(struct input_dev *input) { - struct gpio_mouse *gpio = dev->private; - struct input_dev *input = dev->input; + struct gpio_mouse *gpio = input_get_drvdata(input); int x, y; if (gpio->bleft) @@ -71,18 +70,17 @@ static int gpio_mouse_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct gpio_mouse *gmouse; - struct input_polled_dev *input_poll; struct input_dev *input; - int ret; + int error; gmouse = devm_kzalloc(dev, sizeof(*gmouse), GFP_KERNEL); if (!gmouse) return -ENOMEM; /* Assign some default scanning time */ - ret = device_property_read_u32(dev, "scan-interval-ms", - &gmouse->scan_ms); - if (ret || gmouse->scan_ms == 0) { + error = device_property_read_u32(dev, "scan-interval-ms", + &gmouse->scan_ms); + if (error || gmouse->scan_ms == 0) { dev_warn(dev, "invalid scan time, set to 50 ms\n"); gmouse->scan_ms = 50; } @@ -112,23 +110,14 @@ static int gpio_mouse_probe(struct platform_device *pdev) if (IS_ERR(gmouse->bright)) return PTR_ERR(gmouse->bright); - input_poll = devm_input_allocate_polled_device(dev); - if (!input_poll) { - dev_err(dev, "not enough memory for input device\n"); + input = devm_input_allocate_device(dev); + if (!input) return -ENOMEM; - } - platform_set_drvdata(pdev, input_poll); - - /* set input-polldev handlers */ - input_poll->private = gmouse; - input_poll->poll = gpio_mouse_scan; - input_poll->poll_interval = gmouse->scan_ms; - - input = input_poll->input; input->name = pdev->name; input->id.bustype = BUS_HOST; - input->dev.parent = &pdev->dev; + + input_set_drvdata(input, gmouse); input_set_capability(input, EV_REL, REL_X); input_set_capability(input, EV_REL, REL_Y); @@ -139,10 +128,16 @@ static int gpio_mouse_probe(struct platform_device *pdev) if (gmouse->bright) input_set_capability(input, EV_KEY, BTN_RIGHT); - ret = input_register_polled_device(input_poll); - if (ret) { + error = input_setup_polling(input, gpio_mouse_scan); + if (error) + return error; + + input_set_poll_interval(input, gmouse->scan_ms); + + error = input_register_device(input); + if (error) { dev_err(dev, "could not register input device\n"); - return ret; + return error; } dev_dbg(dev, "%d ms scan time, buttons: %s%s%s\n", From bdafbb15d13b8819d75e026c0b4b61a701583a91 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 8 Oct 2019 10:13:38 -0700 Subject: [PATCH 04/70] Input: pixcir_i2c_ts - remove unneeded gpio.h header file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The touchscreen device is a GPIO consumer, not a GPIO controller, so there is no need to include . Remove the unneeded header file. Signed-off-by: Fabio Estevam Reviewed-by: Roger Quadros Tested-by: Michal Vokáč Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/pixcir_i2c_ts.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c index e146dfa257b1..4561d65e7a1e 100644 --- a/drivers/input/touchscreen/pixcir_i2c_ts.c +++ b/drivers/input/touchscreen/pixcir_i2c_ts.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include From 0d3c8501e32e19c9bdfc65e5d4e17e7772729332 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 8 Oct 2019 10:13:55 -0700 Subject: [PATCH 05/70] Input: pixcir_i2c_ts - move definitions into a single file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All the defined symbols from linux/platform_data/pixcir_i2c_ts.h are only used by the pixcir_i2c_ts driver, so move all the definitions locally and get rid of the pixcir_i2c_ts.h file. Signed-off-by: Fabio Estevam Reviewed-by: Roger Quadros Tested-by: Michal Vokáč Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/pixcir_i2c_ts.c | 60 ++++++++++++++++++- include/linux/platform_data/pixcir_i2c_ts.h | 64 --------------------- 2 files changed, 59 insertions(+), 65 deletions(-) delete mode 100644 include/linux/platform_data/pixcir_i2c_ts.h diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c index 4561d65e7a1e..acc9504aa35b 100644 --- a/drivers/input/touchscreen/pixcir_i2c_ts.c +++ b/drivers/input/touchscreen/pixcir_i2c_ts.c @@ -15,11 +15,69 @@ #include #include #include -#include #include #define PIXCIR_MAX_SLOTS 5 /* Max fingers supported by driver */ +/* + * Register map + */ +#define PIXCIR_REG_POWER_MODE 51 +#define PIXCIR_REG_INT_MODE 52 + +/* + * Power modes: + * active: max scan speed + * idle: lower scan speed with automatic transition to active on touch + * halt: datasheet says sleep but this is more like halt as the chip + * clocks are cut and it can only be brought out of this mode + * using the RESET pin. + */ +enum pixcir_power_mode { + PIXCIR_POWER_ACTIVE, + PIXCIR_POWER_IDLE, + PIXCIR_POWER_HALT, +}; + +#define PIXCIR_POWER_MODE_MASK 0x03 +#define PIXCIR_POWER_ALLOW_IDLE (1UL << 2) + +/* + * Interrupt modes: + * periodical: interrupt is asserted periodicaly + * diff coordinates: interrupt is asserted when coordinates change + * level on touch: interrupt level asserted during touch + * pulse on touch: interrupt pulse asserted during touch + * + */ +enum pixcir_int_mode { + PIXCIR_INT_PERIODICAL, + PIXCIR_INT_DIFF_COORD, + PIXCIR_INT_LEVEL_TOUCH, + PIXCIR_INT_PULSE_TOUCH, +}; + +#define PIXCIR_INT_MODE_MASK 0x03 +#define PIXCIR_INT_ENABLE (1UL << 3) +#define PIXCIR_INT_POL_HIGH (1UL << 2) + +/** + * struct pixcir_irc_chip_data - chip related data + * @max_fingers: Max number of fingers reported simultaneously by h/w + * @has_hw_ids: Hardware supports finger tracking IDs + * + */ +struct pixcir_i2c_chip_data { + u8 max_fingers; + bool has_hw_ids; +}; + +struct pixcir_ts_platform_data { + int x_max; + int y_max; + struct pixcir_i2c_chip_data chip; +}; + struct pixcir_i2c_ts_data { struct i2c_client *client; struct input_dev *input; diff --git a/include/linux/platform_data/pixcir_i2c_ts.h b/include/linux/platform_data/pixcir_i2c_ts.h deleted file mode 100644 index 4ab3cd6f1cc2..000000000000 --- a/include/linux/platform_data/pixcir_i2c_ts.h +++ /dev/null @@ -1,64 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _PIXCIR_I2C_TS_H -#define _PIXCIR_I2C_TS_H - -/* - * Register map - */ -#define PIXCIR_REG_POWER_MODE 51 -#define PIXCIR_REG_INT_MODE 52 - -/* - * Power modes: - * active: max scan speed - * idle: lower scan speed with automatic transition to active on touch - * halt: datasheet says sleep but this is more like halt as the chip - * clocks are cut and it can only be brought out of this mode - * using the RESET pin. - */ -enum pixcir_power_mode { - PIXCIR_POWER_ACTIVE, - PIXCIR_POWER_IDLE, - PIXCIR_POWER_HALT, -}; - -#define PIXCIR_POWER_MODE_MASK 0x03 -#define PIXCIR_POWER_ALLOW_IDLE (1UL << 2) - -/* - * Interrupt modes: - * periodical: interrupt is asserted periodicaly - * diff coordinates: interrupt is asserted when coordinates change - * level on touch: interrupt level asserted during touch - * pulse on touch: interrupt pulse asserted druing touch - * - */ -enum pixcir_int_mode { - PIXCIR_INT_PERIODICAL, - PIXCIR_INT_DIFF_COORD, - PIXCIR_INT_LEVEL_TOUCH, - PIXCIR_INT_PULSE_TOUCH, -}; - -#define PIXCIR_INT_MODE_MASK 0x03 -#define PIXCIR_INT_ENABLE (1UL << 3) -#define PIXCIR_INT_POL_HIGH (1UL << 2) - -/** - * struct pixcir_irc_chip_data - chip related data - * @max_fingers: Max number of fingers reported simultaneously by h/w - * @has_hw_ids: Hardware supports finger tracking IDs - * - */ -struct pixcir_i2c_chip_data { - u8 max_fingers; - bool has_hw_ids; -}; - -struct pixcir_ts_platform_data { - int x_max; - int y_max; - struct pixcir_i2c_chip_data chip; -}; - -#endif From 12e7425a69fd97785f6d6835c2de0e72a9a48918 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 8 Oct 2019 10:14:41 -0700 Subject: [PATCH 06/70] Input: pixcir_i2c_ts - keep header files sorted MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Keep the header files in alphabetical order to keep it more organized. Signed-off-by: Fabio Estevam Reviewed-by: Roger Quadros Tested-by: Michal Vokáč Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/pixcir_i2c_ts.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c index acc9504aa35b..f22b2e7be2be 100644 --- a/drivers/input/touchscreen/pixcir_i2c_ts.c +++ b/drivers/input/touchscreen/pixcir_i2c_ts.c @@ -5,17 +5,17 @@ * Copyright (C) 2010-2011 Pixcir, Inc. */ +#include #include -#include -#include -#include +#include #include #include #include #include -#include +#include #include -#include +#include +#include #define PIXCIR_MAX_SLOTS 5 /* Max fingers supported by driver */ From 13fb9cf593c35073d707c1dabbef9f0cff772695 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 8 Oct 2019 10:15:01 -0700 Subject: [PATCH 07/70] Input: pixcir_i2c_ts - print register address in decimal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The pixcir datasheet lists the registers addresses in decimal and so are PIXCIR_REG_POWER_MODE and PIXCIR_REG_INT_MODE defined in decimal. Change the error messages to print the register addresses in decimal instead of hexadecimal for better readability. Signed-off-by: Fabio Estevam Reviewed-by: Roger Quadros Tested-by: Michal Vokáč Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/pixcir_i2c_ts.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c index f22b2e7be2be..5f2a3dc353c8 100644 --- a/drivers/input/touchscreen/pixcir_i2c_ts.c +++ b/drivers/input/touchscreen/pixcir_i2c_ts.c @@ -249,7 +249,7 @@ static int pixcir_set_power_mode(struct pixcir_i2c_ts_data *ts, ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_POWER_MODE); if (ret < 0) { - dev_err(dev, "%s: can't read reg 0x%x : %d\n", + dev_err(dev, "%s: can't read reg %d : %d\n", __func__, PIXCIR_REG_POWER_MODE, ret); return ret; } @@ -262,7 +262,7 @@ static int pixcir_set_power_mode(struct pixcir_i2c_ts_data *ts, ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_POWER_MODE, ret); if (ret < 0) { - dev_err(dev, "%s: can't write reg 0x%x : %d\n", + dev_err(dev, "%s: can't write reg %d : %d\n", __func__, PIXCIR_REG_POWER_MODE, ret); return ret; } @@ -288,7 +288,7 @@ static int pixcir_set_int_mode(struct pixcir_i2c_ts_data *ts, ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_INT_MODE); if (ret < 0) { - dev_err(dev, "%s: can't read reg 0x%x : %d\n", + dev_err(dev, "%s: can't read reg %d : %d\n", __func__, PIXCIR_REG_INT_MODE, ret); return ret; } @@ -303,7 +303,7 @@ static int pixcir_set_int_mode(struct pixcir_i2c_ts_data *ts, ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_INT_MODE, ret); if (ret < 0) { - dev_err(dev, "%s: can't write reg 0x%x : %d\n", + dev_err(dev, "%s: can't write reg %d : %d\n", __func__, PIXCIR_REG_INT_MODE, ret); return ret; } @@ -321,7 +321,7 @@ static int pixcir_int_enable(struct pixcir_i2c_ts_data *ts, bool enable) ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_INT_MODE); if (ret < 0) { - dev_err(dev, "%s: can't read reg 0x%x : %d\n", + dev_err(dev, "%s: can't read reg %d : %d\n", __func__, PIXCIR_REG_INT_MODE, ret); return ret; } @@ -333,7 +333,7 @@ static int pixcir_int_enable(struct pixcir_i2c_ts_data *ts, bool enable) ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_INT_MODE, ret); if (ret < 0) { - dev_err(dev, "%s: can't write reg 0x%x : %d\n", + dev_err(dev, "%s: can't write reg %d : %d\n", __func__, PIXCIR_REG_INT_MODE, ret); return ret; } From 71a8f3455cbf50f96d521c5a4c972c4709affd80 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 8 Oct 2019 10:15:12 -0700 Subject: [PATCH 08/70] Input: pixcir_i2c_ts - do not print error on defer probe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the case of defer probe we should not print an error message. This also aligns with how defer probe is handled in the other GPIOs used by this driver. Signed-off-by: Fabio Estevam Reviewed-by: Roger Quadros Tested-by: Michal Vokáč Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/pixcir_i2c_ts.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c index 5f2a3dc353c8..ec768ab6148e 100644 --- a/drivers/input/touchscreen/pixcir_i2c_ts.c +++ b/drivers/input/touchscreen/pixcir_i2c_ts.c @@ -567,7 +567,9 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client, tsdata->gpio_attb = devm_gpiod_get(dev, "attb", GPIOD_IN); if (IS_ERR(tsdata->gpio_attb)) { error = PTR_ERR(tsdata->gpio_attb); - dev_err(dev, "Failed to request ATTB gpio: %d\n", error); + if (error != -EPROBE_DEFER) + dev_err(dev, "Failed to request ATTB gpio: %d\n", + error); return error; } @@ -575,7 +577,9 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client, GPIOD_OUT_LOW); if (IS_ERR(tsdata->gpio_reset)) { error = PTR_ERR(tsdata->gpio_reset); - dev_err(dev, "Failed to request RESET gpio: %d\n", error); + if (error != -EPROBE_DEFER) + dev_err(dev, "Failed to request RESET gpio: %d\n", + error); return error; } From 792e154c4814abb1ec2b18c418b44a303cf6ead9 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 8 Oct 2019 11:38:04 -0700 Subject: [PATCH 09/70] Input: pixcir_i2c_ts - remove platform data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previous change moved platform data definition into the driver, making it unusable for users. Given that we want to move away from custom platform data structures, and always use device properties (DT, ACPI or static) to configure devices, let's complete the removal. Tested-by: Fabio Estevam Tested-by: Michal Vokáč Reviewed-by: Roger Quadros Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/pixcir_i2c_ts.c | 100 ++++++---------------- 1 file changed, 25 insertions(+), 75 deletions(-) diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c index ec768ab6148e..9aa098577350 100644 --- a/drivers/input/touchscreen/pixcir_i2c_ts.c +++ b/drivers/input/touchscreen/pixcir_i2c_ts.c @@ -62,7 +62,7 @@ enum pixcir_int_mode { #define PIXCIR_INT_POL_HIGH (1UL << 2) /** - * struct pixcir_irc_chip_data - chip related data + * struct pixcir_i2c_chip_data - chip related data * @max_fingers: Max number of fingers reported simultaneously by h/w * @has_hw_ids: Hardware supports finger tracking IDs * @@ -72,12 +72,6 @@ struct pixcir_i2c_chip_data { bool has_hw_ids; }; -struct pixcir_ts_platform_data { - int x_max; - int y_max; - struct pixcir_i2c_chip_data chip; -}; - struct pixcir_i2c_ts_data { struct i2c_client *client; struct input_dev *input; @@ -87,7 +81,6 @@ struct pixcir_i2c_ts_data { struct gpio_desc *gpio_wake; const struct pixcir_i2c_chip_data *chip; struct touchscreen_properties prop; - int max_fingers; /* Max fingers supported in this instance */ bool running; }; @@ -111,7 +104,7 @@ static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata, memset(report, 0, sizeof(struct pixcir_report_data)); i = chip->has_hw_ids ? 1 : 0; - readsize = 2 + tsdata->max_fingers * (4 + i); + readsize = 2 + tsdata->chip->max_fingers * (4 + i); if (readsize > sizeof(rdbuf)) readsize = sizeof(rdbuf); @@ -132,8 +125,8 @@ static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata, } touch = rdbuf[0] & 0x7; - if (touch > tsdata->max_fingers) - touch = tsdata->max_fingers; + if (touch > tsdata->chip->max_fingers) + touch = tsdata->chip->max_fingers; report->num_touches = touch; bufptr = &rdbuf[2]; @@ -469,31 +462,9 @@ unlock: static SIMPLE_DEV_PM_OPS(pixcir_dev_pm_ops, pixcir_i2c_ts_suspend, pixcir_i2c_ts_resume); -#ifdef CONFIG_OF -static const struct of_device_id pixcir_of_match[]; - -static int pixcir_parse_dt(struct device *dev, - struct pixcir_i2c_ts_data *tsdata) -{ - tsdata->chip = of_device_get_match_data(dev); - if (!tsdata->chip) - return -EINVAL; - - return 0; -} -#else -static int pixcir_parse_dt(struct device *dev, - struct pixcir_i2c_ts_data *tsdata) -{ - return -EINVAL; -} -#endif - static int pixcir_i2c_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) { - const struct pixcir_ts_platform_data *pdata = - dev_get_platdata(&client->dev); struct device *dev = &client->dev; struct pixcir_i2c_ts_data *tsdata; struct input_dev *input; @@ -503,19 +474,11 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client, if (!tsdata) return -ENOMEM; - if (pdata) { - tsdata->chip = &pdata->chip; - } else if (dev->of_node) { - error = pixcir_parse_dt(dev, tsdata); - if (error) - return error; - } else { - dev_err(dev, "platform data not defined\n"); - return -EINVAL; - } - - if (!tsdata->chip->max_fingers) { - dev_err(dev, "Invalid max_fingers in chip data\n"); + tsdata->chip = device_get_match_data(dev); + if (!tsdata->chip && id) + tsdata->chip = (const void *)id->driver_data; + if (!tsdata->chip) { + dev_err(dev, "can't locate chip data\n"); return -EINVAL; } @@ -532,30 +495,17 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client, input->id.bustype = BUS_I2C; input->open = pixcir_input_open; input->close = pixcir_input_close; - input->dev.parent = dev; - if (pdata) { - input_set_abs_params(input, ABS_MT_POSITION_X, 0, pdata->x_max, 0, 0); - input_set_abs_params(input, ABS_MT_POSITION_Y, 0, pdata->y_max, 0, 0); - } else { - input_set_capability(input, EV_ABS, ABS_MT_POSITION_X); - input_set_capability(input, EV_ABS, ABS_MT_POSITION_Y); - touchscreen_parse_properties(input, true, &tsdata->prop); - if (!input_abs_get_max(input, ABS_MT_POSITION_X) || - !input_abs_get_max(input, ABS_MT_POSITION_Y)) { - dev_err(dev, "Touchscreen size is not specified\n"); - return -EINVAL; - } + input_set_capability(input, EV_ABS, ABS_MT_POSITION_X); + input_set_capability(input, EV_ABS, ABS_MT_POSITION_Y); + touchscreen_parse_properties(input, true, &tsdata->prop); + if (!input_abs_get_max(input, ABS_MT_POSITION_X) || + !input_abs_get_max(input, ABS_MT_POSITION_Y)) { + dev_err(dev, "Touchscreen size is not specified\n"); + return -EINVAL; } - tsdata->max_fingers = tsdata->chip->max_fingers; - if (tsdata->max_fingers > PIXCIR_MAX_SLOTS) { - tsdata->max_fingers = PIXCIR_MAX_SLOTS; - dev_info(dev, "Limiting maximum fingers to %d\n", - tsdata->max_fingers); - } - - error = input_mt_init_slots(input, tsdata->max_fingers, + error = input_mt_init_slots(input, tsdata->chip->max_fingers, INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); if (error) { dev_err(dev, "Error initializing Multi-Touch slots\n"); @@ -635,14 +585,6 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client, return 0; } -static const struct i2c_device_id pixcir_i2c_ts_id[] = { - { "pixcir_ts", 0 }, - { "pixcir_tangoc", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, pixcir_i2c_ts_id); - -#ifdef CONFIG_OF static const struct pixcir_i2c_chip_data pixcir_ts_data = { .max_fingers = 2, /* no hw id support */ @@ -653,6 +595,14 @@ static const struct pixcir_i2c_chip_data pixcir_tangoc_data = { .has_hw_ids = true, }; +static const struct i2c_device_id pixcir_i2c_ts_id[] = { + { "pixcir_ts", (unsigned long) &pixcir_ts_data }, + { "pixcir_tangoc", (unsigned long) &pixcir_tangoc_data }, + { } +}; +MODULE_DEVICE_TABLE(i2c, pixcir_i2c_ts_id); + +#ifdef CONFIG_OF static const struct of_device_id pixcir_of_match[] = { { .compatible = "pixcir,pixcir_ts", .data = &pixcir_ts_data }, { .compatible = "pixcir,pixcir_tangoc", .data = &pixcir_tangoc_data }, From 7cef1079e3ad0403bf9a2bb67228044efdded6c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Vok=C3=A1=C4=8D?= Date: Tue, 15 Oct 2019 17:16:38 -0700 Subject: [PATCH 10/70] dt-bindings: input: Add common input binding in json-schema MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Create schema for the common input properties and merge all properties from the Documentation/devicetree/bindings/input/keys.txt binding into this common schema. Signed-off-by: Michal Vokáč Reviewed-by: Rob Herring Signed-off-by: Dmitry Torokhov --- .../devicetree/bindings/input/input.yaml | 32 +++++++++++++++++++ .../devicetree/bindings/input/keys.txt | 8 ----- .../bindings/input/mtk-pmic-keys.txt | 4 +-- .../bindings/input/st,stpmic1-onkey.txt | 2 +- 4 files changed, 35 insertions(+), 11 deletions(-) create mode 100644 Documentation/devicetree/bindings/input/input.yaml delete mode 100644 Documentation/devicetree/bindings/input/keys.txt diff --git a/Documentation/devicetree/bindings/input/input.yaml b/Documentation/devicetree/bindings/input/input.yaml new file mode 100644 index 000000000000..ca8fe84a2e62 --- /dev/null +++ b/Documentation/devicetree/bindings/input/input.yaml @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/input/input.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Common input schema binding + +maintainers: + - Dmitry Torokhov + +properties: + autorepeat: + description: Enable autorepeat when key is pressed and held down. + type: boolean + + linux,keycodes: + description: + Specifies an array of numeric keycode values to be used for reporting + button presses. + allOf: + - $ref: /schemas/types.yaml#/definitions/uint32-array + - items: + minimum: 0 + maximum: 0xff + + power-off-time-sec: + description: + Duration in seconds which the key should be kept pressed for device to + power off automatically. Device with key pressed shutdown feature can + specify this property. + $ref: /schemas/types.yaml#/definitions/uint32 diff --git a/Documentation/devicetree/bindings/input/keys.txt b/Documentation/devicetree/bindings/input/keys.txt deleted file mode 100644 index f5a5ddde53f1..000000000000 --- a/Documentation/devicetree/bindings/input/keys.txt +++ /dev/null @@ -1,8 +0,0 @@ -General Keys Properties: - -Optional properties for Keys: -- power-off-time-sec: Duration in seconds which the key should be kept - pressed for device to power off automatically. Device with key pressed - shutdown feature can specify this property. -- linux,keycodes: Specifies the numeric keycode values to be used for - reporting key presses. diff --git a/Documentation/devicetree/bindings/input/mtk-pmic-keys.txt b/Documentation/devicetree/bindings/input/mtk-pmic-keys.txt index 2888d07c2ef0..535d92885372 100644 --- a/Documentation/devicetree/bindings/input/mtk-pmic-keys.txt +++ b/Documentation/devicetree/bindings/input/mtk-pmic-keys.txt @@ -10,13 +10,13 @@ Documentation/devicetree/bindings/mfd/mt6397.txt Required properties: - compatible: "mediatek,mt6397-keys" or "mediatek,mt6323-keys" -- linux,keycodes: See Documentation/devicetree/bindings/input/keys.txt +- linux,keycodes: See Documentation/devicetree/bindings/input/input.yaml Optional Properties: - wakeup-source: See Documentation/devicetree/bindings/power/wakeup-source.txt - mediatek,long-press-mode: Long press key shutdown setting, 1 for pwrkey only, 2 for pwrkey/homekey together, others for disabled. -- power-off-time-sec: See Documentation/devicetree/bindings/input/keys.txt +- power-off-time-sec: See Documentation/devicetree/bindings/input/input.yaml Example: diff --git a/Documentation/devicetree/bindings/input/st,stpmic1-onkey.txt b/Documentation/devicetree/bindings/input/st,stpmic1-onkey.txt index 4494613ae7ad..eb8e83736c02 100644 --- a/Documentation/devicetree/bindings/input/st,stpmic1-onkey.txt +++ b/Documentation/devicetree/bindings/input/st,stpmic1-onkey.txt @@ -15,7 +15,7 @@ Optional properties: - st,onkey-pu-inactive: onkey pull up is not active - power-off-time-sec: Duration in seconds which the key should be kept pressed for device to power off automatically (from 1 to 16 seconds). - see See Documentation/devicetree/bindings/input/keys.txt + see See Documentation/devicetree/bindings/input/input.yaml Example: From def10ec7992f037140f3bd9542d1242cfd2027d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Vok=C3=A1=C4=8D?= Date: Tue, 15 Oct 2019 17:16:52 -0700 Subject: [PATCH 11/70] dt-bindings: input: Convert mpr121 binding to json-schema MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert the mpr121 binding to DT schema format using json-schema. Signed-off-by: Michal Vokáč Reviewed-by: Rob Herring Signed-off-by: Dmitry Torokhov --- .../bindings/input/fsl,mpr121-touchkey.yaml | 66 +++++++++++++++++++ .../bindings/input/mpr121-touchkey.txt | 30 --------- 2 files changed, 66 insertions(+), 30 deletions(-) create mode 100644 Documentation/devicetree/bindings/input/fsl,mpr121-touchkey.yaml delete mode 100644 Documentation/devicetree/bindings/input/mpr121-touchkey.txt diff --git a/Documentation/devicetree/bindings/input/fsl,mpr121-touchkey.yaml b/Documentation/devicetree/bindings/input/fsl,mpr121-touchkey.yaml new file mode 100644 index 000000000000..c6fbcdf78556 --- /dev/null +++ b/Documentation/devicetree/bindings/input/fsl,mpr121-touchkey.yaml @@ -0,0 +1,66 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/input/fsl,mpr121-touchkey.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale MPR121 capacitive touch sensor controller + +maintainers: + - Dmitry Torokhov + +description: | + The MPR121 supports up to 12 completely independent electrodes/capacitance + sensing inputs in which 8 are multifunctional for LED driving and GPIO. + https://www.nxp.com/docs/en/data-sheet/MPR121.pdf + +allOf: + - $ref: input.yaml# + +properties: + compatible: + const: fsl,mpr121-touchkey + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + vdd-supply: + maxItems: 1 + + linux,keycodes: + minItems: 1 + maxItems: 12 + + wakeup-source: + description: Use any event on keypad as wakeup event. + type: boolean + +required: + - compatible + - reg + - interrupts + - vdd-supply + - linux,keycodes + +examples: + - | + #include "dt-bindings/input/input.h" + i2c { + #address-cells = <1>; + #size-cells = <0>; + + mpr121@5a { + compatible = "fsl,mpr121-touchkey"; + reg = <0x5a>; + interrupt-parent = <&gpio1>; + interrupts = <28 2>; + autorepeat; + vdd-supply = <&ldo4_reg>; + linux,keycodes = , , , , + , , , , + , , , ; + }; + }; diff --git a/Documentation/devicetree/bindings/input/mpr121-touchkey.txt b/Documentation/devicetree/bindings/input/mpr121-touchkey.txt deleted file mode 100644 index b7c61ee5841b..000000000000 --- a/Documentation/devicetree/bindings/input/mpr121-touchkey.txt +++ /dev/null @@ -1,30 +0,0 @@ -* Freescale MPR121 Controllor - -Required Properties: -- compatible: Should be "fsl,mpr121-touchkey" -- reg: The I2C slave address of the device. -- interrupts: The interrupt number to the cpu. -- vdd-supply: Phandle to the Vdd power supply. -- linux,keycodes: Specifies an array of numeric keycode values to - be used for reporting button presses. The array can - contain up to 12 entries. - -Optional Properties: -- wakeup-source: Use any event on keypad as wakeup event. -- autorepeat: Enable autorepeat feature. - -Example: - -#include "dt-bindings/input/input.h" - - touchkey: mpr121@5a { - compatible = "fsl,mpr121-touchkey"; - reg = <0x5a>; - interrupt-parent = <&gpio1>; - interrupts = <28 2>; - autorepeat; - vdd-supply = <&ldo4_reg>; - linux,keycodes = , , , , - , , , - , , , ; - }; From ee358cb45984f4569098d3a97edfd0067576ad2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Vok=C3=A1=C4=8D?= Date: Tue, 15 Oct 2019 17:17:29 -0700 Subject: [PATCH 12/70] Input: mpr121 - add polling mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In case the interrupt line is not available, polling can be used to read out the state of the keys. Period of the polling needs to be configured by the poll-interval DT property. Signed-off-by: Michal Vokáč Reviewed-by: Rob Herring Signed-off-by: Dmitry Torokhov --- .../bindings/input/fsl,mpr121-touchkey.yaml | 25 ++++++- .../devicetree/bindings/input/input.yaml | 4 ++ drivers/input/keyboard/mpr121_touchkey.c | 69 ++++++++++++++----- 3 files changed, 79 insertions(+), 19 deletions(-) diff --git a/Documentation/devicetree/bindings/input/fsl,mpr121-touchkey.yaml b/Documentation/devicetree/bindings/input/fsl,mpr121-touchkey.yaml index c6fbcdf78556..5b37be0be4e9 100644 --- a/Documentation/devicetree/bindings/input/fsl,mpr121-touchkey.yaml +++ b/Documentation/devicetree/bindings/input/fsl,mpr121-touchkey.yaml @@ -17,6 +17,10 @@ description: | allOf: - $ref: input.yaml# +anyOf: + - required: [ interrupts ] + - required: [ poll-interval ] + properties: compatible: const: fsl,mpr121-touchkey @@ -41,12 +45,12 @@ properties: required: - compatible - reg - - interrupts - vdd-supply - linux,keycodes examples: - | + // Example with interrupts #include "dt-bindings/input/input.h" i2c { #address-cells = <1>; @@ -64,3 +68,22 @@ examples: , , , ; }; }; + + - | + // Example with polling + #include "dt-bindings/input/input.h" + i2c { + #address-cells = <1>; + #size-cells = <0>; + + mpr121@5a { + compatible = "fsl,mpr121-touchkey"; + reg = <0x5a>; + poll-interval = <20>; + autorepeat; + vdd-supply = <&ldo4_reg>; + linux,keycodes = , , , , + , , , , + , , , ; + }; + }; diff --git a/Documentation/devicetree/bindings/input/input.yaml b/Documentation/devicetree/bindings/input/input.yaml index ca8fe84a2e62..6d519046b3af 100644 --- a/Documentation/devicetree/bindings/input/input.yaml +++ b/Documentation/devicetree/bindings/input/input.yaml @@ -24,6 +24,10 @@ properties: minimum: 0 maximum: 0xff + poll-interval: + description: Poll interval time in milliseconds. + $ref: /schemas/types.yaml#/definitions/uint32 + power-off-time-sec: description: Duration in seconds which the key should be kept pressed for device to diff --git a/drivers/input/keyboard/mpr121_touchkey.c b/drivers/input/keyboard/mpr121_touchkey.c index ee80de44ce3f..40d6e5087cde 100644 --- a/drivers/input/keyboard/mpr121_touchkey.c +++ b/drivers/input/keyboard/mpr121_touchkey.c @@ -54,6 +54,9 @@ /* MPR121 has 12 keys */ #define MPR121_MAX_KEY_COUNT 12 +#define MPR121_MIN_POLL_INTERVAL 10 +#define MPR121_MAX_POLL_INTERVAL 200 + struct mpr121_touchkey { struct i2c_client *client; struct input_dev *input_dev; @@ -115,11 +118,11 @@ static struct regulator *mpr121_vdd_supply_init(struct device *dev) return vdd_supply; } -static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id) +static void mpr_touchkey_report(struct input_dev *dev) { - struct mpr121_touchkey *mpr121 = dev_id; - struct i2c_client *client = mpr121->client; + struct mpr121_touchkey *mpr121 = input_get_drvdata(dev); struct input_dev *input = mpr121->input_dev; + struct i2c_client *client = mpr121->client; unsigned long bit_changed; unsigned int key_num; int reg; @@ -127,14 +130,14 @@ static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id) reg = i2c_smbus_read_byte_data(client, ELE_TOUCH_STATUS_1_ADDR); if (reg < 0) { dev_err(&client->dev, "i2c read error [%d]\n", reg); - goto out; + return; } reg <<= 8; reg |= i2c_smbus_read_byte_data(client, ELE_TOUCH_STATUS_0_ADDR); if (reg < 0) { dev_err(&client->dev, "i2c read error [%d]\n", reg); - goto out; + return; } reg &= TOUCH_STATUS_MASK; @@ -155,8 +158,14 @@ static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id) } input_sync(input); +} + +static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id) +{ + struct mpr121_touchkey *mpr121 = dev_id; + + mpr_touchkey_report(mpr121->input_dev); -out: return IRQ_HANDLED; } @@ -229,14 +238,10 @@ static int mpr_touchkey_probe(struct i2c_client *client, int vdd_uv; struct mpr121_touchkey *mpr121; struct input_dev *input_dev; + u32 poll_interval = 0; int error; int i; - if (!client->irq) { - dev_err(dev, "irq number should not be zero\n"); - return -EINVAL; - } - vdd_supply = mpr121_vdd_supply_init(dev); if (IS_ERR(vdd_supply)) return PTR_ERR(vdd_supply); @@ -274,6 +279,7 @@ static int mpr_touchkey_probe(struct i2c_client *client, if (device_property_read_bool(dev, "autorepeat")) __set_bit(EV_REP, input_dev->evbit); input_set_capability(input_dev, EV_MSC, MSC_SCAN); + input_set_drvdata(input_dev, mpr121); input_dev->keycode = mpr121->keycodes; input_dev->keycodesize = sizeof(mpr121->keycodes[0]); @@ -288,13 +294,40 @@ static int mpr_touchkey_probe(struct i2c_client *client, return error; } - error = devm_request_threaded_irq(dev, client->irq, NULL, - mpr_touchkey_interrupt, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - dev->driver->name, mpr121); - if (error) { - dev_err(dev, "Failed to register interrupt\n"); - return error; + device_property_read_u32(dev, "poll-interval", &poll_interval); + + if (client->irq) { + error = devm_request_threaded_irq(dev, client->irq, NULL, + mpr_touchkey_interrupt, + IRQF_TRIGGER_FALLING | + IRQF_ONESHOT, + dev->driver->name, mpr121); + if (error) { + dev_err(dev, "Failed to register interrupt\n"); + return error; + } + } else if (poll_interval) { + if (poll_interval < MPR121_MIN_POLL_INTERVAL) + return -EINVAL; + + if (poll_interval > MPR121_MAX_POLL_INTERVAL) + return -EINVAL; + + error = input_setup_polling(input_dev, mpr_touchkey_report); + if (error) { + dev_err(dev, "Failed to setup polling\n"); + return error; + } + + input_set_poll_interval(input_dev, poll_interval); + input_set_min_poll_interval(input_dev, + MPR121_MIN_POLL_INTERVAL); + input_set_max_poll_interval(input_dev, + MPR121_MAX_POLL_INTERVAL); + } else { + dev_err(dev, + "invalid IRQ number and polling not configured\n"); + return -EINVAL; } error = input_register_device(input_dev); From 688f1dfb69b4efd111121d0b185c7eec1b184a00 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Tue, 15 Oct 2019 17:27:21 -0700 Subject: [PATCH 13/70] Input: keyboard - imx_sc: Add i.MX system controller key support i.MX8QXP is an ARMv8 SoC which has a Cortex-M4 system controller inside, the system controller is in charge of controlling power, clock and scu key etc.. Adds i.MX system controller key driver support, Linux kernel has to communicate with system controller via MU (message unit) IPC to get scu key's status. Signed-off-by: Anson Huang Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/1570412509-7893-2-git-send-email-Anson.Huang@nxp.com Signed-off-by: Dmitry Torokhov --- .../bindings/arm/freescale/fsl,scu.txt | 14 ++ drivers/input/keyboard/Kconfig | 10 + drivers/input/keyboard/Makefile | 1 + drivers/input/keyboard/imx_sc_key.c | 187 ++++++++++++++++++ 4 files changed, 212 insertions(+) create mode 100644 drivers/input/keyboard/imx_sc_key.c diff --git a/Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt b/Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt index a575e42f7fec..e57eaff07738 100644 --- a/Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt +++ b/Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt @@ -155,6 +155,15 @@ Required properties: Optional properties: - timeout-sec: contains the watchdog timeout in seconds. +SCU key bindings based on SCU Message Protocol +------------------------------------------------------------ + +Required properties: +- compatible: should be: + "fsl,imx8qxp-sc-key" + followed by "fsl,imx-sc-key"; +- linux,keycodes: See Documentation/devicetree/bindings/input/keys.txt + Example (imx8qxp): ------------- aliases { @@ -218,6 +227,11 @@ firmware { compatible = "fsl,imx8qxp-sc-rtc"; }; + scu_key: scu-key { + compatible = "fsl,imx8qxp-sc-key", "fsl,imx-sc-key"; + linux,keycodes = ; + }; + watchdog { compatible = "fsl,imx8qxp-sc-wdt", "fsl,imx-sc-wdt"; timeout-sec = <60>; diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 2e6d2887eec1..a716a90de683 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -469,6 +469,16 @@ config KEYBOARD_IMX To compile this driver as a module, choose M here: the module will be called imx_keypad. +config KEYBOARD_IMX_SC_KEY + tristate "IMX SCU Key Driver" + depends on IMX_SCU + help + This is the system controller key driver for NXP i.MX SoCs with + system controller inside. + + To compile this driver as a module, choose M here: the + module will be called imx_sc_key. + config KEYBOARD_NEWTON tristate "Newton keyboard" select SERIO diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 9510325c0c5d..f5b17524adf2 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -29,6 +29,7 @@ obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o obj-$(CONFIG_KEYBOARD_IPAQ_MICRO) += ipaq-micro-keys.o obj-$(CONFIG_KEYBOARD_IMX) += imx_keypad.o +obj-$(CONFIG_KEYBOARD_IMX_SC_KEY) += imx_sc_key.o obj-$(CONFIG_KEYBOARD_HP6XX) += jornada680_kbd.o obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o obj-$(CONFIG_KEYBOARD_LKKBD) += lkkbd.o diff --git a/drivers/input/keyboard/imx_sc_key.c b/drivers/input/keyboard/imx_sc_key.c new file mode 100644 index 000000000000..dd57daa67e5f --- /dev/null +++ b/drivers/input/keyboard/imx_sc_key.c @@ -0,0 +1,187 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2019 NXP. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEBOUNCE_TIME 30 +#define REPEAT_INTERVAL 60 + +#define SC_IRQ_BUTTON 1 +#define SC_IRQ_GROUP_WAKE 3 + +#define IMX_SC_MISC_FUNC_GET_BUTTON_STATUS 18 + +struct imx_key_drv_data { + u32 keycode; + bool keystate; /* true: pressed, false: released */ + struct delayed_work check_work; + struct input_dev *input; + struct imx_sc_ipc *key_ipc_handle; + struct notifier_block key_notifier; +}; + +struct imx_sc_msg_key { + struct imx_sc_rpc_msg hdr; + u8 state; +}; + +static int imx_sc_key_notify(struct notifier_block *nb, + unsigned long event, void *group) +{ + struct imx_key_drv_data *priv = + container_of(nb, + struct imx_key_drv_data, + key_notifier); + + if ((event & SC_IRQ_BUTTON) && (*(u8 *)group == SC_IRQ_GROUP_WAKE)) { + schedule_delayed_work(&priv->check_work, + msecs_to_jiffies(DEBOUNCE_TIME)); + pm_wakeup_event(priv->input->dev.parent, 0); + } + + return 0; +} + +static void imx_sc_check_for_events(struct work_struct *work) +{ + struct imx_key_drv_data *priv = + container_of(work, + struct imx_key_drv_data, + check_work.work); + struct input_dev *input = priv->input; + struct imx_sc_msg_key msg; + struct imx_sc_rpc_msg *hdr = &msg.hdr; + bool state; + int error; + + hdr->ver = IMX_SC_RPC_VERSION; + hdr->svc = IMX_SC_RPC_SVC_MISC; + hdr->func = IMX_SC_MISC_FUNC_GET_BUTTON_STATUS; + hdr->size = 1; + + error = imx_scu_call_rpc(priv->key_ipc_handle, &msg, true); + if (error) { + dev_err(&input->dev, "read imx sc key failed, error %d\n", error); + return; + } + + state = (bool)msg.state; + + if (state ^ priv->keystate) { + priv->keystate = state; + input_event(input, EV_KEY, priv->keycode, state); + input_sync(input); + if (!priv->keystate) + pm_relax(priv->input->dev.parent); + } + + if (state) + schedule_delayed_work(&priv->check_work, + msecs_to_jiffies(REPEAT_INTERVAL)); +} + +static int imx_sc_key_probe(struct platform_device *pdev) +{ + struct imx_key_drv_data *priv; + struct input_dev *input; + int error; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + error = imx_scu_get_handle(&priv->key_ipc_handle); + if (error) + return error; + + if (device_property_read_u32(&pdev->dev, "linux,keycodes", + &priv->keycode)) { + dev_err(&pdev->dev, "missing linux,keycodes property\n"); + return -EINVAL; + } + + INIT_DELAYED_WORK(&priv->check_work, imx_sc_check_for_events); + + input = devm_input_allocate_device(&pdev->dev); + if (!input) { + dev_err(&pdev->dev, "failed to allocate the input device\n"); + return -ENOMEM; + } + + input->name = pdev->name; + input->phys = "imx-sc-key/input0"; + input->id.bustype = BUS_HOST; + + input_set_capability(input, EV_KEY, priv->keycode); + + error = input_register_device(input); + if (error) { + dev_err(&pdev->dev, "failed to register input device\n"); + return error; + } + + priv->input = input; + platform_set_drvdata(pdev, priv); + + error = imx_scu_irq_group_enable(SC_IRQ_GROUP_WAKE, SC_IRQ_BUTTON, + true); + if (error) { + dev_err(&pdev->dev, "failed to enable scu group irq\n"); + return error; + } + + priv->key_notifier.notifier_call = imx_sc_key_notify; + error = imx_scu_irq_register_notifier(&priv->key_notifier); + if (error) { + imx_scu_irq_group_enable(SC_IRQ_GROUP_WAKE, SC_IRQ_BUTTON, + false); + dev_err(&pdev->dev, "failed to register scu notifier\n"); + return error; + } + + return 0; +} + +static int imx_sc_key_remove(struct platform_device *pdev) +{ + struct imx_key_drv_data *priv = platform_get_drvdata(pdev); + + imx_scu_irq_group_enable(SC_IRQ_GROUP_WAKE, SC_IRQ_BUTTON, false); + imx_scu_irq_unregister_notifier(&priv->key_notifier); + cancel_delayed_work_sync(&priv->check_work); + + return 0; +} + +static const struct of_device_id imx_sc_key_ids[] = { + { .compatible = "fsl,imx-sc-key" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, imx_sc_key_ids); + +static struct platform_driver imx_sc_key_driver = { + .driver = { + .name = "imx-sc-key", + .of_match_table = imx_sc_key_ids, + }, + .probe = imx_sc_key_probe, + .remove = imx_sc_key_remove, +}; +module_platform_driver(imx_sc_key_driver); + +MODULE_AUTHOR("Anson Huang "); +MODULE_DESCRIPTION("i.MX System Controller Key Driver"); +MODULE_LICENSE("GPL v2"); From ee1b4b2e7c92f892855175e564e091130a59d707 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 23 Oct 2019 13:37:21 -0700 Subject: [PATCH 14/70] Input: hp_sdc_rtc - remove dead chardev code The driver contains half of the implementation of /dev/rtc, but this was never completed, and it is now incompatible with the drivers/rtc framework. Remove the chardev completely. If anyone wants to add the functionality later, that shoudl be done through rtc_register_device(). The remaining portions of the driver basically implement a single procfs file that may or may not be used anywhere. Not sure why this is in drivers/input/ though. Signed-off-by: Arnd Bergmann Acked-by: Alexandre Belloni Acked-by: Helge Deller Link: https://lore.kernel.org/r/20191023142521.3643152-1-arnd@arndb.de Signed-off-by: Dmitry Torokhov --- drivers/input/misc/hp_sdc_rtc.c | 342 -------------------------------- 1 file changed, 342 deletions(-) diff --git a/drivers/input/misc/hp_sdc_rtc.c b/drivers/input/misc/hp_sdc_rtc.c index abca895a6156..199bc17ddb1d 100644 --- a/drivers/input/misc/hp_sdc_rtc.c +++ b/drivers/input/misc/hp_sdc_rtc.c @@ -53,28 +53,10 @@ MODULE_LICENSE("Dual BSD/GPL"); #define RTC_VERSION "1.10d" -static DEFINE_MUTEX(hp_sdc_rtc_mutex); static unsigned long epoch = 2000; static struct semaphore i8042tregs; -static hp_sdc_irqhook hp_sdc_rtc_isr; - -static struct fasync_struct *hp_sdc_rtc_async_queue; - -static DECLARE_WAIT_QUEUE_HEAD(hp_sdc_rtc_wait); - -static ssize_t hp_sdc_rtc_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos); - -static long hp_sdc_rtc_unlocked_ioctl(struct file *file, - unsigned int cmd, unsigned long arg); - -static unsigned int hp_sdc_rtc_poll(struct file *file, poll_table *wait); - -static int hp_sdc_rtc_open(struct inode *inode, struct file *file); -static int hp_sdc_rtc_fasync (int fd, struct file *filp, int on); - static void hp_sdc_rtc_isr (int irq, void *dev_id, uint8_t status, uint8_t data) { @@ -283,151 +265,6 @@ static inline int hp_sdc_rtc_read_ct(struct timespec64 *res) { return 0; } - -#if 0 /* not used yet */ -/* Set the i8042 real-time clock */ -static int hp_sdc_rtc_set_rt (struct timeval *setto) -{ - uint32_t tenms; - unsigned int days; - hp_sdc_transaction t; - uint8_t tseq[11] = { - HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT, - HP_SDC_CMD_SET_RTMS, 3, 0, 0, 0, - HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT, - HP_SDC_CMD_SET_RTD, 2, 0, 0 - }; - - t.endidx = 10; - - if (0xffff < setto->tv_sec / 86400) return -1; - days = setto->tv_sec / 86400; - if (0xffff < setto->tv_usec / 1000000 / 86400) return -1; - days += ((setto->tv_sec % 86400) + setto->tv_usec / 1000000) / 86400; - if (days > 0xffff) return -1; - - if (0xffffff < setto->tv_sec) return -1; - tenms = setto->tv_sec * 100; - if (0xffffff < setto->tv_usec / 10000) return -1; - tenms += setto->tv_usec / 10000; - if (tenms > 0xffffff) return -1; - - tseq[3] = (uint8_t)(tenms & 0xff); - tseq[4] = (uint8_t)((tenms >> 8) & 0xff); - tseq[5] = (uint8_t)((tenms >> 16) & 0xff); - - tseq[9] = (uint8_t)(days & 0xff); - tseq[10] = (uint8_t)((days >> 8) & 0xff); - - t.seq = tseq; - - if (hp_sdc_enqueue_transaction(&t)) return -1; - return 0; -} - -/* Set the i8042 fast handshake timer */ -static int hp_sdc_rtc_set_fhs (struct timeval *setto) -{ - uint32_t tenms; - hp_sdc_transaction t; - uint8_t tseq[5] = { - HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT, - HP_SDC_CMD_SET_FHS, 2, 0, 0 - }; - - t.endidx = 4; - - if (0xffff < setto->tv_sec) return -1; - tenms = setto->tv_sec * 100; - if (0xffff < setto->tv_usec / 10000) return -1; - tenms += setto->tv_usec / 10000; - if (tenms > 0xffff) return -1; - - tseq[3] = (uint8_t)(tenms & 0xff); - tseq[4] = (uint8_t)((tenms >> 8) & 0xff); - - t.seq = tseq; - - if (hp_sdc_enqueue_transaction(&t)) return -1; - return 0; -} - - -/* Set the i8042 match timer (a.k.a. alarm) */ -#define hp_sdc_rtc_set_mt (setto) \ - hp_sdc_rtc_set_i8042timer(setto, HP_SDC_CMD_SET_MT) - -/* Set the i8042 delay timer */ -#define hp_sdc_rtc_set_dt (setto) \ - hp_sdc_rtc_set_i8042timer(setto, HP_SDC_CMD_SET_DT) - -/* Set the i8042 cycle timer (a.k.a. periodic) */ -#define hp_sdc_rtc_set_ct (setto) \ - hp_sdc_rtc_set_i8042timer(setto, HP_SDC_CMD_SET_CT) - -/* Set one of the i8042 3-byte wide timers */ -static int hp_sdc_rtc_set_i8042timer (struct timeval *setto, uint8_t setcmd) -{ - uint32_t tenms; - hp_sdc_transaction t; - uint8_t tseq[6] = { - HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT, - 0, 3, 0, 0, 0 - }; - - t.endidx = 6; - - if (0xffffff < setto->tv_sec) return -1; - tenms = setto->tv_sec * 100; - if (0xffffff < setto->tv_usec / 10000) return -1; - tenms += setto->tv_usec / 10000; - if (tenms > 0xffffff) return -1; - - tseq[1] = setcmd; - tseq[3] = (uint8_t)(tenms & 0xff); - tseq[4] = (uint8_t)((tenms >> 8) & 0xff); - tseq[5] = (uint8_t)((tenms >> 16) & 0xff); - - t.seq = tseq; - - if (hp_sdc_enqueue_transaction(&t)) { - return -1; - } - return 0; -} -#endif - -static ssize_t hp_sdc_rtc_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) { - ssize_t retval; - - if (count < sizeof(unsigned long)) - return -EINVAL; - - retval = put_user(68, (unsigned long __user *)buf); - return retval; -} - -static __poll_t hp_sdc_rtc_poll(struct file *file, poll_table *wait) -{ - unsigned long l; - - l = 0; - if (l != 0) - return EPOLLIN | EPOLLRDNORM; - return 0; -} - -static int hp_sdc_rtc_open(struct inode *inode, struct file *file) -{ - return 0; -} - -static int hp_sdc_rtc_fasync (int fd, struct file *filp, int on) -{ - return fasync_helper (fd, filp, on, &hp_sdc_rtc_async_queue); -} - static int hp_sdc_rtc_proc_show(struct seq_file *m, void *v) { #define YN(bit) ("no") @@ -507,182 +344,6 @@ static int hp_sdc_rtc_proc_show(struct seq_file *m, void *v) #undef NY } -static int hp_sdc_rtc_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) -{ -#if 1 - return -EINVAL; -#else - - struct rtc_time wtime; - struct timeval ttime; - int use_wtime = 0; - - /* This needs major work. */ - - switch (cmd) { - - case RTC_AIE_OFF: /* Mask alarm int. enab. bit */ - case RTC_AIE_ON: /* Allow alarm interrupts. */ - case RTC_PIE_OFF: /* Mask periodic int. enab. bit */ - case RTC_PIE_ON: /* Allow periodic ints */ - case RTC_UIE_ON: /* Allow ints for RTC updates. */ - case RTC_UIE_OFF: /* Allow ints for RTC updates. */ - { - /* We cannot mask individual user timers and we - cannot tell them apart when they occur, so it - would be disingenuous to succeed these IOCTLs */ - return -EINVAL; - } - case RTC_ALM_READ: /* Read the present alarm time */ - { - if (hp_sdc_rtc_read_mt(&ttime)) return -EFAULT; - if (hp_sdc_rtc_read_bbrtc(&wtime)) return -EFAULT; - - wtime.tm_hour = ttime.tv_sec / 3600; ttime.tv_sec %= 3600; - wtime.tm_min = ttime.tv_sec / 60; ttime.tv_sec %= 60; - wtime.tm_sec = ttime.tv_sec; - - break; - } - case RTC_IRQP_READ: /* Read the periodic IRQ rate. */ - { - return put_user(hp_sdc_rtc_freq, (unsigned long *)arg); - } - case RTC_IRQP_SET: /* Set periodic IRQ rate. */ - { - /* - * The max we can do is 100Hz. - */ - - if ((arg < 1) || (arg > 100)) return -EINVAL; - ttime.tv_sec = 0; - ttime.tv_usec = 1000000 / arg; - if (hp_sdc_rtc_set_ct(&ttime)) return -EFAULT; - hp_sdc_rtc_freq = arg; - return 0; - } - case RTC_ALM_SET: /* Store a time into the alarm */ - { - /* - * This expects a struct hp_sdc_rtc_time. Writing 0xff means - * "don't care" or "match all" for PC timers. The HP SDC - * does not support that perk, but it could be emulated fairly - * easily. Only the tm_hour, tm_min and tm_sec are used. - * We could do it with 10ms accuracy with the HP SDC, if the - * rtc interface left us a way to do that. - */ - struct hp_sdc_rtc_time alm_tm; - - if (copy_from_user(&alm_tm, (struct hp_sdc_rtc_time*)arg, - sizeof(struct hp_sdc_rtc_time))) - return -EFAULT; - - if (alm_tm.tm_hour > 23) return -EINVAL; - if (alm_tm.tm_min > 59) return -EINVAL; - if (alm_tm.tm_sec > 59) return -EINVAL; - - ttime.sec = alm_tm.tm_hour * 3600 + - alm_tm.tm_min * 60 + alm_tm.tm_sec; - ttime.usec = 0; - if (hp_sdc_rtc_set_mt(&ttime)) return -EFAULT; - return 0; - } - case RTC_RD_TIME: /* Read the time/date from RTC */ - { - if (hp_sdc_rtc_read_bbrtc(&wtime)) return -EFAULT; - break; - } - case RTC_SET_TIME: /* Set the RTC */ - { - struct rtc_time hp_sdc_rtc_tm; - unsigned char mon, day, hrs, min, sec, leap_yr; - unsigned int yrs; - - if (!capable(CAP_SYS_TIME)) - return -EACCES; - if (copy_from_user(&hp_sdc_rtc_tm, (struct rtc_time *)arg, - sizeof(struct rtc_time))) - return -EFAULT; - - yrs = hp_sdc_rtc_tm.tm_year + 1900; - mon = hp_sdc_rtc_tm.tm_mon + 1; /* tm_mon starts at zero */ - day = hp_sdc_rtc_tm.tm_mday; - hrs = hp_sdc_rtc_tm.tm_hour; - min = hp_sdc_rtc_tm.tm_min; - sec = hp_sdc_rtc_tm.tm_sec; - - if (yrs < 1970) - return -EINVAL; - - leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400)); - - if ((mon > 12) || (day == 0)) - return -EINVAL; - if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr))) - return -EINVAL; - if ((hrs >= 24) || (min >= 60) || (sec >= 60)) - return -EINVAL; - - if ((yrs -= eH) > 255) /* They are unsigned */ - return -EINVAL; - - - return 0; - } - case RTC_EPOCH_READ: /* Read the epoch. */ - { - return put_user (epoch, (unsigned long *)arg); - } - case RTC_EPOCH_SET: /* Set the epoch. */ - { - /* - * There were no RTC clocks before 1900. - */ - if (arg < 1900) - return -EINVAL; - if (!capable(CAP_SYS_TIME)) - return -EACCES; - - epoch = arg; - return 0; - } - default: - return -EINVAL; - } - return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0; -#endif -} - -static long hp_sdc_rtc_unlocked_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) -{ - int ret; - - mutex_lock(&hp_sdc_rtc_mutex); - ret = hp_sdc_rtc_ioctl(file, cmd, arg); - mutex_unlock(&hp_sdc_rtc_mutex); - - return ret; -} - - -static const struct file_operations hp_sdc_rtc_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .read = hp_sdc_rtc_read, - .poll = hp_sdc_rtc_poll, - .unlocked_ioctl = hp_sdc_rtc_unlocked_ioctl, - .open = hp_sdc_rtc_open, - .fasync = hp_sdc_rtc_fasync, -}; - -static struct miscdevice hp_sdc_rtc_dev = { - .minor = RTC_MINOR, - .name = "rtc_HIL", - .fops = &hp_sdc_rtc_fops -}; - static int __init hp_sdc_rtc_init(void) { int ret; @@ -696,8 +357,6 @@ static int __init hp_sdc_rtc_init(void) if ((ret = hp_sdc_request_timer_irq(&hp_sdc_rtc_isr))) return ret; - if (misc_register(&hp_sdc_rtc_dev) != 0) - printk(KERN_INFO "Could not register misc. dev for i8042 rtc\n"); proc_create_single("driver/rtc", 0, NULL, hp_sdc_rtc_proc_show); @@ -710,7 +369,6 @@ static int __init hp_sdc_rtc_init(void) static void __exit hp_sdc_rtc_exit(void) { remove_proc_entry ("driver/rtc", NULL); - misc_deregister(&hp_sdc_rtc_dev); hp_sdc_release_timer_irq(hp_sdc_rtc_isr); printk(KERN_INFO "HP i8042 SDC + MSM-58321 RTC support unloaded\n"); } From cb3efd5a38855eabd26c2b631dd027169678d60f Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 23 Oct 2019 13:52:23 -0700 Subject: [PATCH 15/70] Input: adp5589 - make keypad support optional On some platforms the adp5589 is used in GPIO only mode. On these platforms we do not want to register a input device, so make that optional and only create the input device if a keymap is supplied. Signed-off-by: Lars-Peter Clausen Signed-off-by: Alexandru Ardelean Link: https://lore.kernel.org/r/20191023070541.13940-1-alexandru.ardelean@analog.com [dtor: dropped unnecessary changes related to passing pdata to various functions] Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/adp5589-keys.c | 171 +++++++++++++++----------- 1 file changed, 98 insertions(+), 73 deletions(-) diff --git a/drivers/input/keyboard/adp5589-keys.c b/drivers/input/keyboard/adp5589-keys.c index 4f96a4a99e5b..e7d58e7f0257 100644 --- a/drivers/input/keyboard/adp5589-keys.c +++ b/drivers/input/keyboard/adp5589-keys.c @@ -857,70 +857,35 @@ static void adp5589_report_switch_state(struct adp5589_kpad *kpad) input_sync(kpad->input); } -static int adp5589_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int adp5589_keypad_add(struct adp5589_kpad *kpad, unsigned int revid) { - struct adp5589_kpad *kpad; + struct i2c_client *client = kpad->client; const struct adp5589_kpad_platform_data *pdata = dev_get_platdata(&client->dev); struct input_dev *input; - unsigned int revid; - int ret, i; + unsigned int i; int error; - if (!i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_BYTE_DATA)) { - dev_err(&client->dev, "SMBUS Byte Data not Supported\n"); - return -EIO; - } - - if (!pdata) { - dev_err(&client->dev, "no platform data?\n"); - return -EINVAL; - } - - kpad = kzalloc(sizeof(*kpad), GFP_KERNEL); - if (!kpad) - return -ENOMEM; - - switch (id->driver_data) { - case ADP5585_02: - kpad->support_row5 = true; - /* fall through */ - case ADP5585_01: - kpad->is_adp5585 = true; - kpad->var = &const_adp5585; - break; - case ADP5589: - kpad->support_row5 = true; - kpad->var = &const_adp5589; - break; - } - if (!((pdata->keypad_en_mask & kpad->var->row_mask) && (pdata->keypad_en_mask >> kpad->var->col_shift)) || !pdata->keymap) { dev_err(&client->dev, "no rows, cols or keymap from pdata\n"); - error = -EINVAL; - goto err_free_mem; + return -EINVAL; } if (pdata->keymapsize != kpad->var->keymapsize) { dev_err(&client->dev, "invalid keymapsize\n"); - error = -EINVAL; - goto err_free_mem; + return -EINVAL; } if (!pdata->gpimap && pdata->gpimapsize) { dev_err(&client->dev, "invalid gpimap from pdata\n"); - error = -EINVAL; - goto err_free_mem; + return -EINVAL; } if (pdata->gpimapsize > kpad->var->gpimapsize_max) { dev_err(&client->dev, "invalid gpimapsize\n"); - error = -EINVAL; - goto err_free_mem; + return -EINVAL; } for (i = 0; i < pdata->gpimapsize; i++) { @@ -929,41 +894,27 @@ static int adp5589_probe(struct i2c_client *client, if (pin < kpad->var->gpi_pin_base || pin > kpad->var->gpi_pin_end) { dev_err(&client->dev, "invalid gpi pin data\n"); - error = -EINVAL; - goto err_free_mem; + return -EINVAL; } if ((1 << (pin - kpad->var->gpi_pin_row_base)) & pdata->keypad_en_mask) { dev_err(&client->dev, "invalid gpi row/col data\n"); - error = -EINVAL; - goto err_free_mem; + return -EINVAL; } } if (!client->irq) { dev_err(&client->dev, "no IRQ?\n"); - error = -EINVAL; - goto err_free_mem; + return -EINVAL; } input = input_allocate_device(); - if (!input) { - error = -ENOMEM; - goto err_free_mem; - } + if (!input) + return -ENOMEM; - kpad->client = client; kpad->input = input; - ret = adp5589_read(client, ADP5589_5_ID); - if (ret < 0) { - error = ret; - goto err_free_input; - } - - revid = (u8) ret & ADP5589_5_DEVICE_ID_MASK; - input->name = client->name; input->phys = "adp5589-keys/input0"; input->dev.parent = &client->dev; @@ -1015,30 +966,99 @@ static int adp5589_probe(struct i2c_client *client, goto err_unreg_dev; } + device_init_wakeup(&client->dev, 1); + + return 0; + +err_unreg_dev: + input_unregister_device(input); + input = NULL; +err_free_input: + input_free_device(input); + + return error; +} + +static void adp5589_keypad_remove(struct adp5589_kpad *kpad) +{ + if (kpad->input) { + free_irq(kpad->client->irq, kpad); + input_unregister_device(kpad->input); + } +} + +static int adp5589_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct adp5589_kpad *kpad; + const struct adp5589_kpad_platform_data *pdata = + dev_get_platdata(&client->dev); + unsigned int revid; + int error, ret; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_err(&client->dev, "SMBUS Byte Data not Supported\n"); + return -EIO; + } + + if (!pdata) { + dev_err(&client->dev, "no platform data?\n"); + return -EINVAL; + } + + kpad = kzalloc(sizeof(*kpad), GFP_KERNEL); + if (!kpad) + return -ENOMEM; + + kpad->client = client; + + switch (id->driver_data) { + case ADP5585_02: + kpad->support_row5 = true; + /* fall through */ + case ADP5585_01: + kpad->is_adp5585 = true; + kpad->var = &const_adp5585; + break; + case ADP5589: + kpad->support_row5 = true; + kpad->var = &const_adp5589; + break; + } + + ret = adp5589_read(client, ADP5589_5_ID); + if (ret < 0) { + error = ret; + goto err_free_mem; + } + + revid = (u8) ret & ADP5589_5_DEVICE_ID_MASK; + + if (pdata->keymapsize) { + error = adp5589_keypad_add(kpad, revid); + if (error) + goto err_free_mem; + } + error = adp5589_setup(kpad); if (error) - goto err_free_irq; + goto err_keypad_remove; if (kpad->gpimapsize) adp5589_report_switch_state(kpad); error = adp5589_gpio_add(kpad); if (error) - goto err_free_irq; + goto err_keypad_remove; - device_init_wakeup(&client->dev, 1); i2c_set_clientdata(client, kpad); dev_info(&client->dev, "Rev.%d keypad, irq %d\n", revid, client->irq); return 0; -err_free_irq: - free_irq(client->irq, kpad); -err_unreg_dev: - input_unregister_device(input); - input = NULL; -err_free_input: - input_free_device(input); +err_keypad_remove: + adp5589_keypad_remove(kpad); err_free_mem: kfree(kpad); @@ -1050,8 +1070,7 @@ static int adp5589_remove(struct i2c_client *client) struct adp5589_kpad *kpad = i2c_get_clientdata(client); adp5589_write(client, kpad->var->reg(ADP5589_GENERAL_CFG), 0); - free_irq(client->irq, kpad); - input_unregister_device(kpad->input); + adp5589_keypad_remove(kpad); adp5589_gpio_remove(kpad); kfree(kpad); @@ -1064,6 +1083,9 @@ static int adp5589_suspend(struct device *dev) struct adp5589_kpad *kpad = dev_get_drvdata(dev); struct i2c_client *client = kpad->client; + if (!kpad->input) + return 0; + disable_irq(client->irq); if (device_may_wakeup(&client->dev)) @@ -1077,6 +1099,9 @@ static int adp5589_resume(struct device *dev) struct adp5589_kpad *kpad = dev_get_drvdata(dev); struct i2c_client *client = kpad->client; + if (!kpad->input) + return 0; + if (device_may_wakeup(&client->dev)) disable_irq_wake(client->irq); From 2a60f598777d8b819383698c3dd4fd35dff21182 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 13 Sep 2019 17:43:34 -0700 Subject: [PATCH 16/70] Input: gpio_keys - switch to using devm_fwnode_gpiod_get() devm_fwnode_get_gpiod_from_child() is going away as the name is too unwieldy, let's switch to using the new devm_fwnode_gpiod_get(). Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/gpio_keys.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index 1373dc5b0765..1f56d53454b2 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -494,10 +494,8 @@ static int gpio_keys_setup_key(struct platform_device *pdev, spin_lock_init(&bdata->lock); if (child) { - bdata->gpiod = devm_fwnode_get_gpiod_from_child(dev, NULL, - child, - GPIOD_IN, - desc); + bdata->gpiod = devm_fwnode_gpiod_get(dev, child, + NULL, GPIOD_IN, desc); if (IS_ERR(bdata->gpiod)) { error = PTR_ERR(bdata->gpiod); if (error == -ENOENT) { From 5f92dcee81f4fb7375ec3cedc48dfb042cf492b2 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 13 Sep 2019 17:43:34 -0700 Subject: [PATCH 17/70] Input: gpio_keys_polled - switch to using devm_fwnode_gpiod_get() devm_fwnode_get_gpiod_from_child() is going away as the name is too unwieldy, let's switch to using the new devm_fwnode_gpiod_get(). Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/gpio_keys_polled.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c index 465eecfa6b3f..51bbd010089a 100644 --- a/drivers/input/keyboard/gpio_keys_polled.c +++ b/drivers/input/keyboard/gpio_keys_polled.c @@ -300,10 +300,9 @@ static int gpio_keys_polled_probe(struct platform_device *pdev) return -EINVAL; } - bdata->gpiod = devm_fwnode_get_gpiod_from_child(dev, - NULL, child, - GPIOD_IN, - button->desc); + bdata->gpiod = devm_fwnode_gpiod_get(dev, child, + NULL, GPIOD_IN, + button->desc); if (IS_ERR(bdata->gpiod)) { error = PTR_ERR(bdata->gpiod); if (error != -EPROBE_DEFER) From d34a069e1c63ddc20e2c3c8bfdec2510682b15f3 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Sun, 27 Oct 2019 10:35:21 -0700 Subject: [PATCH 18/70] Input: colibri-vf50-ts - remove unneeded gpio.h header file The touchscreen device is a GPIO consumer, not a GPIO controller, so there is no need to include . Remove the unneeded header file. Signed-off-by: Fabio Estevam Link: https://lore.kernel.org/r/20191026185958.24158-1-festevam@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/colibri-vf50-ts.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/input/touchscreen/colibri-vf50-ts.c b/drivers/input/touchscreen/colibri-vf50-ts.c index 0e40897949bb..aa829725ded7 100644 --- a/drivers/input/touchscreen/colibri-vf50-ts.c +++ b/drivers/input/touchscreen/colibri-vf50-ts.c @@ -9,7 +9,6 @@ #include #include -#include #include #include #include From 2fd61f796875b78469f35101cc2124ffed6343e5 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Sun, 27 Oct 2019 10:35:31 -0700 Subject: [PATCH 19/70] Input: s3c2410_ts - remove unneeded gpio.h header file There is no gpio functions used in the driver that is exported by the gpio.h header, so remove this unneeded header. Signed-off-by: Fabio Estevam Link: https://lore.kernel.org/r/20191026185958.24158-2-festevam@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/s3c2410_ts.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c index b346e7cafd62..82920ff46f72 100644 --- a/drivers/input/touchscreen/s3c2410_ts.c +++ b/drivers/input/touchscreen/s3c2410_ts.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include From 78e45917bf7a066fffbeb3d87f4031109df6da55 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Sun, 27 Oct 2019 10:35:41 -0700 Subject: [PATCH 20/70] Input: wacom_i2c - remove unneeded gpio.h header file There is no gpio functions used in the driver that is exported by the gpio.h header, so remove this unneeded header. Signed-off-by: Fabio Estevam Link: https://lore.kernel.org/r/20191026185958.24158-3-festevam@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/wacom_i2c.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/input/touchscreen/wacom_i2c.c b/drivers/input/touchscreen/wacom_i2c.c index f017af8c2aa3..1afc6bde2891 100644 --- a/drivers/input/touchscreen/wacom_i2c.c +++ b/drivers/input/touchscreen/wacom_i2c.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #define WACOM_CMD_QUERY0 0x04 From 95c9ea96adb3c7be6295d017c7e2f594f0871c16 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 21 Oct 2019 10:11:23 -0700 Subject: [PATCH 21/70] Input: st1232 - simplify parsing of read buffer Avoid complex 2-variable loop when parsing touchscreen data to make the code clearer. Acked-by: Martin Kepplinger Tested-by: Matthias Fend Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/st1232.c | 50 +++++++++++++++--------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c index 1139714e72e2..47033ef3749a 100644 --- a/drivers/input/touchscreen/st1232.c +++ b/drivers/input/touchscreen/st1232.c @@ -57,38 +57,38 @@ static int st1232_ts_read_data(struct st1232_ts_data *ts) { struct st1232_ts_finger *finger = ts->finger; struct i2c_client *client = ts->client; - struct i2c_msg msg[2]; - int error; - int i, y; u8 start_reg = ts->chip_info->start_reg; - u8 *buf = ts->read_buf; + struct i2c_msg msg[] = { + { + .addr = client->addr, + .len = sizeof(start_reg), + .buf = &start_reg, + }, + { + .addr = client->addr, + .flags = I2C_M_RD, + .len = ts->read_buf_len, + .buf = ts->read_buf, + } + }; + int ret; + int i; + u8 *buf; - /* read touchscreen data */ - msg[0].addr = client->addr; - msg[0].flags = 0; - msg[0].len = 1; - msg[0].buf = &start_reg; + ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)); + if (ret != ARRAY_SIZE(msg)) + return ret < 0 ? ret : -EIO; - msg[1].addr = ts->client->addr; - msg[1].flags = I2C_M_RD; - msg[1].len = ts->read_buf_len; - msg[1].buf = buf; - - error = i2c_transfer(client->adapter, msg, 2); - if (error < 0) - return error; - - for (i = 0, y = 0; i < ts->chip_info->max_fingers; i++, y += 3) { - finger[i].is_valid = buf[i + y] >> 7; + for (i = 0; i < ts->chip_info->max_fingers; i++) { + buf = &ts->read_buf[i * 4]; + finger[i].is_valid = buf[0] >> 7; if (finger[i].is_valid) { - finger[i].x = ((buf[i + y] & 0x0070) << 4) | - buf[i + y + 1]; - finger[i].y = ((buf[i + y] & 0x0007) << 8) | - buf[i + y + 2]; + finger[i].x = ((buf[0] & 0x70) << 4) | buf[1]; + finger[i].y = ((buf[0] & 0x07) << 8) | buf[2]; /* st1232 includes a z-axis / touch strength */ if (ts->chip_info->have_z) - finger[i].t = buf[i + 6]; + finger[i].t = ts->read_buf[i + 6]; } } From 16dc7c5c13f1482ac32b8ac7cbc1ad8ab13b0f5d Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 21 Oct 2019 10:55:56 -0700 Subject: [PATCH 22/70] Input: st1232 - do not unconditionally configure as wakeup source Do not unconditionally configure the touchscreen as wakeup source but rather rely on I2C core to do that when requested (either via "wakeup-source" device property, or when creating a client with I2C_CLIENT_WAKE flag). Tested-by: Matthias Fend Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/st1232.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c index 47033ef3749a..f1b97075aa9b 100644 --- a/drivers/input/touchscreen/st1232.c +++ b/drivers/input/touchscreen/st1232.c @@ -266,7 +266,6 @@ static int st1232_ts_probe(struct i2c_client *client, } i2c_set_clientdata(client, ts); - device_init_wakeup(&client->dev, 1); return 0; } From 95dc58a9a02f9267cc08199e059329463cfe938c Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 21 Oct 2019 11:00:21 -0700 Subject: [PATCH 23/70] Input: st1232 - rely on I2C core to configure wakeup interrupt When I2C client is created with I2C_CLIENT_WAKE flag (which happens either because we have "wakeup-source" device property or the flag was passed in when creating an I2C client manually), I2C core will take care of configuring interrupt as wakeup source on suspend. Tested-by: Matthias Fend Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/st1232.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c index f1b97075aa9b..bb116f41f1c0 100644 --- a/drivers/input/touchscreen/st1232.c +++ b/drivers/input/touchscreen/st1232.c @@ -284,12 +284,10 @@ static int __maybe_unused st1232_ts_suspend(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct st1232_ts_data *ts = i2c_get_clientdata(client); - if (device_may_wakeup(&client->dev)) { - enable_irq_wake(client->irq); - } else { - disable_irq(client->irq); + disable_irq(client->irq); + + if (!device_may_wakeup(&client->dev)) st1232_ts_power(ts, false); - } return 0; } @@ -299,12 +297,10 @@ static int __maybe_unused st1232_ts_resume(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct st1232_ts_data *ts = i2c_get_clientdata(client); - if (device_may_wakeup(&client->dev)) { - disable_irq_wake(client->irq); - } else { + if (!device_may_wakeup(&client->dev)) st1232_ts_power(ts, true); - enable_irq(client->irq); - } + + enable_irq(client->irq); return 0; } From efd7bb08a762d4f6322054c6824bd942971ac563 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 21 Oct 2019 11:02:33 -0700 Subject: [PATCH 24/70] Input: st1232 - do not reset the chip too early We should not be putting the chip into reset while interrupts are enabled and ISR may be running. Fix this by installing a custom devm action and powering off the device/resetting GPIO line from there. This ensures proper ordering. Tested-by: Matthias Fend Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/st1232.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c index bb116f41f1c0..bfea02202ded 100644 --- a/drivers/input/touchscreen/st1232.c +++ b/drivers/input/touchscreen/st1232.c @@ -149,6 +149,11 @@ static void st1232_ts_power(struct st1232_ts_data *ts, bool poweron) gpiod_set_value_cansleep(ts->reset_gpio, !poweron); } +static void st1232_ts_power_off(void *data) +{ + st1232_ts_power(data, false); +} + static const struct st_chip_info st1232_chip_info = { .have_z = true, .max_x = 0x31f, /* 800 - 1 */ @@ -229,6 +234,13 @@ static int st1232_ts_probe(struct i2c_client *client, st1232_ts_power(ts, true); + error = devm_add_action_or_reset(&client->dev, st1232_ts_power_off, ts); + if (error) { + dev_err(&client->dev, + "Failed to install power off action: %d\n", error); + return error; + } + input_dev->name = "st1232-touchscreen"; input_dev->id.bustype = BUS_I2C; input_dev->dev.parent = &client->dev; @@ -270,15 +282,6 @@ static int st1232_ts_probe(struct i2c_client *client, return 0; } -static int st1232_ts_remove(struct i2c_client *client) -{ - struct st1232_ts_data *ts = i2c_get_clientdata(client); - - st1232_ts_power(ts, false); - - return 0; -} - static int __maybe_unused st1232_ts_suspend(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); @@ -324,7 +327,6 @@ MODULE_DEVICE_TABLE(of, st1232_ts_dt_ids); static struct i2c_driver st1232_ts_driver = { .probe = st1232_ts_probe, - .remove = st1232_ts_remove, .id_table = st1232_ts_id, .driver = { .name = ST1232_TS_NAME, From ac6b31797925b6f89885987c81d908bad90dea60 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 21 Oct 2019 20:49:19 -0700 Subject: [PATCH 25/70] Input: st1232 - do not allocate fingers data separately The finger structure size is quite small and allocating it together with the main driver structure will not increase likelyhood of allocation failing, but reduces number of objects needing to be tracked by the allocator and devm. Tested-by: Matthias Fend Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/st1232.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c index bfea02202ded..dfc0c6cb0213 100644 --- a/drivers/input/touchscreen/st1232.c +++ b/drivers/input/touchscreen/st1232.c @@ -50,12 +50,12 @@ struct st1232_ts_data { const struct st_chip_info *chip_info; int read_buf_len; u8 *read_buf; - struct st1232_ts_finger *finger; + struct st1232_ts_finger fingers[]; }; static int st1232_ts_read_data(struct st1232_ts_data *ts) { - struct st1232_ts_finger *finger = ts->finger; + struct st1232_ts_finger *finger = ts->fingers; struct i2c_client *client = ts->client; u8 start_reg = ts->chip_info->start_reg; struct i2c_msg msg[] = { @@ -98,7 +98,7 @@ static int st1232_ts_read_data(struct st1232_ts_data *ts) static irqreturn_t st1232_ts_irq_handler(int irq, void *dev_id) { struct st1232_ts_data *ts = dev_id; - struct st1232_ts_finger *finger = ts->finger; + struct st1232_ts_finger *finger = ts->fingers; struct input_dev *input_dev = ts->input_dev; int count = 0; int i, ret; @@ -177,7 +177,6 @@ static int st1232_ts_probe(struct i2c_client *client, { const struct st_chip_info *match; struct st1232_ts_data *ts; - struct st1232_ts_finger *finger; struct input_dev *input_dev; int error; @@ -199,16 +198,13 @@ static int st1232_ts_probe(struct i2c_client *client, return -EINVAL; } - ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL); + ts = devm_kzalloc(&client->dev, + struct_size(ts, fingers, match->max_fingers), + GFP_KERNEL); if (!ts) return -ENOMEM; ts->chip_info = match; - ts->finger = devm_kcalloc(&client->dev, - ts->chip_info->max_fingers, sizeof(*finger), - GFP_KERNEL); - if (!ts->finger) - return -ENOMEM; /* allocate a buffer according to the number of registers to read */ ts->read_buf_len = ts->chip_info->max_fingers * 4; From b67b6f598c5d6efe58f202b1f95cd0503583b728 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 21 Oct 2019 20:50:37 -0700 Subject: [PATCH 26/70] Input: st1232 - do not set parent device explicitly devm_input_allocate_device() already sets parent device for us. Tested-by: Matthias Fend Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/st1232.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c index dfc0c6cb0213..0aee330731c9 100644 --- a/drivers/input/touchscreen/st1232.c +++ b/drivers/input/touchscreen/st1232.c @@ -239,7 +239,6 @@ static int st1232_ts_probe(struct i2c_client *client, input_dev->name = "st1232-touchscreen"; input_dev->id.bustype = BUS_I2C; - input_dev->dev.parent = &client->dev; __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); __set_bit(EV_SYN, input_dev->evbit); From 833c2c083856ef3077b51c908ec401fa0a130d57 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 22 Oct 2019 09:34:59 -0700 Subject: [PATCH 27/70] Input: st1232 - note that the receive buffer is DMA-safe The receiving buffer is allocated separately from the main driver data structure, and is naturally DMA-safe, so mark it as such when building I2C transfer message. Tested-by: Matthias Fend Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/st1232.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c index 0aee330731c9..a4a3b82ee69d 100644 --- a/drivers/input/touchscreen/st1232.c +++ b/drivers/input/touchscreen/st1232.c @@ -66,7 +66,7 @@ static int st1232_ts_read_data(struct st1232_ts_data *ts) }, { .addr = client->addr, - .flags = I2C_M_RD, + .flags = I2C_M_RD | I2C_M_DMA_SAFE, .len = ts->read_buf_len, .buf = ts->read_buf, } From a1b92973fba47ceaeb0e337132876aba078fa8b7 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 22 Oct 2019 10:31:16 -0700 Subject: [PATCH 28/70] Input: st1232 - switch to using MT-B protocol Switch the driver to the slotted variant of multitouch protocol (MT-B) with in-kernel tracking of the contacts. Tested-by: Matthias Fend Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/st1232.c | 110 +++++++++++++++-------------- 1 file changed, 56 insertions(+), 54 deletions(-) diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c index a4a3b82ee69d..63b29c7279e2 100644 --- a/drivers/input/touchscreen/st1232.c +++ b/drivers/input/touchscreen/st1232.c @@ -14,23 +14,19 @@ #include #include #include +#include +#include #include #include #include #include #include #include -#include #define ST1232_TS_NAME "st1232-ts" #define ST1633_TS_NAME "st1633-ts" -struct st1232_ts_finger { - u16 x; - u16 y; - u8 t; - bool is_valid; -}; +#define ST_TS_MAX_FINGERS 10 struct st_chip_info { bool have_z; @@ -50,12 +46,10 @@ struct st1232_ts_data { const struct st_chip_info *chip_info; int read_buf_len; u8 *read_buf; - struct st1232_ts_finger fingers[]; }; static int st1232_ts_read_data(struct st1232_ts_data *ts) { - struct st1232_ts_finger *finger = ts->fingers; struct i2c_client *client = ts->client; u8 start_reg = ts->chip_info->start_reg; struct i2c_msg msg[] = { @@ -72,59 +66,69 @@ static int st1232_ts_read_data(struct st1232_ts_data *ts) } }; int ret; - int i; - u8 *buf; ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)); if (ret != ARRAY_SIZE(msg)) return ret < 0 ? ret : -EIO; + return 0; +} + +static int st1232_ts_parse_and_report(struct st1232_ts_data *ts) +{ + struct input_dev *input = ts->input_dev; + struct input_mt_pos pos[ST_TS_MAX_FINGERS]; + u8 z[ST_TS_MAX_FINGERS]; + int slots[ST_TS_MAX_FINGERS]; + int n_contacts = 0; + int i; + for (i = 0; i < ts->chip_info->max_fingers; i++) { - buf = &ts->read_buf[i * 4]; - finger[i].is_valid = buf[0] >> 7; - if (finger[i].is_valid) { - finger[i].x = ((buf[0] & 0x70) << 4) | buf[1]; - finger[i].y = ((buf[0] & 0x07) << 8) | buf[2]; + u8 *buf = &ts->read_buf[i * 4]; + + if (buf[0] & BIT(7)) { + unsigned int x = ((buf[0] & 0x70) << 4) | buf[1]; + unsigned int y = ((buf[0] & 0x07) << 8) | buf[2]; + + touchscreen_set_mt_pos(&pos[n_contacts], + &ts->prop, x, y); /* st1232 includes a z-axis / touch strength */ if (ts->chip_info->have_z) - finger[i].t = ts->read_buf[i + 6]; + z[n_contacts] = ts->read_buf[i + 6]; + + n_contacts++; } } - return 0; + input_mt_assign_slots(input, slots, pos, n_contacts, 0); + for (i = 0; i < n_contacts; 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); + if (ts->chip_info->have_z) + input_report_abs(input, ABS_MT_TOUCH_MAJOR, z[i]); + } + + input_mt_sync_frame(input); + input_sync(input); + + return n_contacts; } static irqreturn_t st1232_ts_irq_handler(int irq, void *dev_id) { struct st1232_ts_data *ts = dev_id; - struct st1232_ts_finger *finger = ts->fingers; - struct input_dev *input_dev = ts->input_dev; - int count = 0; - int i, ret; + int count; + int error; - ret = st1232_ts_read_data(ts); - if (ret < 0) - goto end; + error = st1232_ts_read_data(ts); + if (error) + goto out; - /* multi touch protocol */ - for (i = 0; i < ts->chip_info->max_fingers; i++) { - if (!finger[i].is_valid) - continue; - - if (ts->chip_info->have_z) - input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, - finger[i].t); - - touchscreen_report_pos(input_dev, &ts->prop, - finger[i].x, finger[i].y, true); - input_mt_sync(input_dev); - count++; - } - - /* SYN_MT_REPORT only if no contact */ + count = st1232_ts_parse_and_report(ts); if (!count) { - input_mt_sync(input_dev); if (ts->low_latency_req.dev) { dev_pm_qos_remove_request(&ts->low_latency_req); ts->low_latency_req.dev = NULL; @@ -136,10 +140,7 @@ static irqreturn_t st1232_ts_irq_handler(int irq, void *dev_id) DEV_PM_QOS_RESUME_LATENCY, 100); } - /* SYN_REPORT */ - input_sync(input_dev); - -end: +out: return IRQ_HANDLED; } @@ -198,9 +199,7 @@ static int st1232_ts_probe(struct i2c_client *client, return -EINVAL; } - ts = devm_kzalloc(&client->dev, - struct_size(ts, fingers, match->max_fingers), - GFP_KERNEL); + ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL); if (!ts) return -ENOMEM; @@ -240,11 +239,6 @@ static int st1232_ts_probe(struct i2c_client *client, input_dev->name = "st1232-touchscreen"; input_dev->id.bustype = BUS_I2C; - __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); - __set_bit(EV_SYN, input_dev->evbit); - __set_bit(EV_KEY, input_dev->evbit); - __set_bit(EV_ABS, input_dev->evbit); - if (ts->chip_info->have_z) input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, ts->chip_info->max_area, 0, 0); @@ -256,6 +250,14 @@ static int st1232_ts_probe(struct i2c_client *client, touchscreen_parse_properties(input_dev, true, &ts->prop); + error = input_mt_init_slots(input_dev, ts->chip_info->max_fingers, + INPUT_MT_DIRECT | INPUT_MT_TRACK | + INPUT_MT_DROP_UNUSED); + if (error) { + dev_err(&client->dev, "failed to initialize MT slots\n"); + return error; + } + error = devm_request_threaded_irq(&client->dev, client->irq, NULL, st1232_ts_irq_handler, IRQF_ONESHOT, From 7448bfec6bf5e3e4a5abdd21b125a95c29a5952f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Myl=C3=A8ne=20Josserand?= Date: Mon, 28 Oct 2019 20:56:23 -0700 Subject: [PATCH 29/70] Input: edt-ft5x06 - add support for regulator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the support for enabling optional regulator that may be used as VCC source. Signed-off-by: Mylène Josserand Signed-off-by: Ondrej Jirman Reviewed-by: Rob Herring # bindings Link: https://lore.kernel.org/r/20191029005806.3577376-2-megous@megous.com Signed-off-by: Dmitry Torokhov --- .../bindings/input/touchscreen/edt-ft5x06.txt | 1 + drivers/input/touchscreen/edt-ft5x06.c | 30 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.txt b/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.txt index 870b8c5cce9b..0f6950073d6f 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.txt +++ b/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.txt @@ -30,6 +30,7 @@ Required properties: Optional properties: - reset-gpios: GPIO specification for the RESET input - wake-gpios: GPIO specification for the WAKE input + - vcc-supply: Regulator that supplies the touchscreen - pinctrl-names: should be "default" - pinctrl-0: a phandle pointing to the pin settings for the diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index 5525f1fb1526..d61731c0037d 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -28,6 +28,7 @@ #include #include #include +#include #define WORK_REGISTER_THRESHOLD 0x00 #define WORK_REGISTER_REPORT_RATE 0x08 @@ -88,6 +89,7 @@ struct edt_ft5x06_ts_data { struct touchscreen_properties prop; u16 num_x; u16 num_y; + struct regulator *vcc; struct gpio_desc *reset_gpio; struct gpio_desc *wake_gpio; @@ -1036,6 +1038,13 @@ edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata) } } +static void edt_ft5x06_disable_regulator(void *arg) +{ + struct edt_ft5x06_ts_data *data = arg; + + regulator_disable(data->vcc); +} + static int edt_ft5x06_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -1064,6 +1073,27 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, tsdata->max_support_points = chip_data->max_support_points; + tsdata->vcc = devm_regulator_get(&client->dev, "vcc"); + if (IS_ERR(tsdata->vcc)) { + error = PTR_ERR(tsdata->vcc); + if (error != -EPROBE_DEFER) + dev_err(&client->dev, + "failed to request regulator: %d\n", error); + return error; + } + + error = regulator_enable(tsdata->vcc); + if (error < 0) { + dev_err(&client->dev, "failed to enable vcc: %d\n", error); + return error; + } + + error = devm_add_action_or_reset(&client->dev, + edt_ft5x06_disable_regulator, + tsdata); + if (error) + return error; + tsdata->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(tsdata->reset_gpio)) { From 055070a7d0d35d0a85697f21788a2c82534ed53b Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 28 Oct 2019 21:27:49 -0700 Subject: [PATCH 30/70] Input: psxpad-spi - switch to using polled mode of input devices We have added polled mode to the normal input devices with the intent of retiring input_polled_dev. This converts psxpad-spi driver to use the polling mode of standard input devices and removes dependency on INPUT_POLLDEV. Link: https://lore.kernel.org/r/20191001220421.GA66693@dtor-ws Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/Kconfig | 1 - drivers/input/joystick/psxpad-spi.c | 64 +++++++++++++++-------------- 2 files changed, 34 insertions(+), 31 deletions(-) diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig index 312b854b5506..940b744639c7 100644 --- a/drivers/input/joystick/Kconfig +++ b/drivers/input/joystick/Kconfig @@ -334,7 +334,6 @@ config JOYSTICK_MAPLE config JOYSTICK_PSXPAD_SPI tristate "PlayStation 1/2 joypads via SPI interface" depends on SPI - select INPUT_POLLDEV help Say Y here if you wish to connect PlayStation 1/2 joypads via SPI interface. diff --git a/drivers/input/joystick/psxpad-spi.c b/drivers/input/joystick/psxpad-spi.c index 7eee1b0e360f..a32656064f39 100644 --- a/drivers/input/joystick/psxpad-spi.c +++ b/drivers/input/joystick/psxpad-spi.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -60,7 +59,7 @@ static const u8 PSX_CMD_ENABLE_MOTOR[] = { struct psxpad { struct spi_device *spi; - struct input_polled_dev *pdev; + struct input_dev *idev; char phys[0x20]; bool motor1enable; bool motor2enable; @@ -140,8 +139,7 @@ static void psxpad_set_motor_level(struct psxpad *pad, static int psxpad_spi_play_effect(struct input_dev *idev, void *data, struct ff_effect *effect) { - struct input_polled_dev *pdev = input_get_drvdata(idev); - struct psxpad *pad = pdev->private; + struct psxpad *pad = input_get_drvdata(idev); switch (effect->type) { case FF_RUMBLE: @@ -158,10 +156,9 @@ static int psxpad_spi_init_ff(struct psxpad *pad) { int err; - input_set_capability(pad->pdev->input, EV_FF, FF_RUMBLE); + input_set_capability(pad->idev, EV_FF, FF_RUMBLE); - err = input_ff_create_memless(pad->pdev->input, NULL, - psxpad_spi_play_effect); + err = input_ff_create_memless(pad->idev, NULL, psxpad_spi_play_effect); if (err) { dev_err(&pad->spi->dev, "input_ff_create_memless() failed: %d\n", err); @@ -189,24 +186,25 @@ static inline int psxpad_spi_init_ff(struct psxpad *pad) } #endif /* CONFIG_JOYSTICK_PSXPAD_SPI_FF */ -static void psxpad_spi_poll_open(struct input_polled_dev *pdev) +static int psxpad_spi_poll_open(struct input_dev *input) { - struct psxpad *pad = pdev->private; + struct psxpad *pad = input_get_drvdata(input); pm_runtime_get_sync(&pad->spi->dev); + + return 0; } -static void psxpad_spi_poll_close(struct input_polled_dev *pdev) +static void psxpad_spi_poll_close(struct input_dev *input) { - struct psxpad *pad = pdev->private; + struct psxpad *pad = input_get_drvdata(input); pm_runtime_put_sync(&pad->spi->dev); } -static void psxpad_spi_poll(struct input_polled_dev *pdev) +static void psxpad_spi_poll(struct input_dev *input) { - struct psxpad *pad = pdev->private; - struct input_dev *input = pdev->input; + struct psxpad *pad = input_get_drvdata(input); u8 b_rsp3, b_rsp4; int err; @@ -284,7 +282,6 @@ static void psxpad_spi_poll(struct input_polled_dev *pdev) static int psxpad_spi_probe(struct spi_device *spi) { struct psxpad *pad; - struct input_polled_dev *pdev; struct input_dev *idev; int err; @@ -292,31 +289,26 @@ static int psxpad_spi_probe(struct spi_device *spi) if (!pad) return -ENOMEM; - pdev = input_allocate_polled_device(); - if (!pdev) { + idev = devm_input_allocate_device(&spi->dev); + if (!idev) { dev_err(&spi->dev, "failed to allocate input device\n"); return -ENOMEM; } /* input poll device settings */ - pad->pdev = pdev; + pad->idev = idev; pad->spi = spi; - pdev->private = pad; - pdev->open = psxpad_spi_poll_open; - pdev->close = psxpad_spi_poll_close; - pdev->poll = psxpad_spi_poll; - /* poll interval is about 60fps */ - pdev->poll_interval = 16; - pdev->poll_interval_min = 8; - pdev->poll_interval_max = 32; - /* input device settings */ - idev = pdev->input; + input_set_drvdata(idev, pad); + idev->name = "PlayStation 1/2 joypad"; snprintf(pad->phys, sizeof(pad->phys), "%s/input", dev_name(&spi->dev)); idev->id.bustype = BUS_SPI; + idev->open = psxpad_spi_poll_open; + idev->close = psxpad_spi_poll_close; + /* key/value map settings */ input_set_abs_params(idev, ABS_X, 0, 255, 0, 0); input_set_abs_params(idev, ABS_Y, 0, 255, 0, 0); @@ -354,11 +346,23 @@ static int psxpad_spi_probe(struct spi_device *spi) /* pad settings */ psxpad_set_motor_level(pad, 0, 0); + + err = input_setup_polling(idev, psxpad_spi_poll); + if (err) { + dev_err(&spi->dev, "failed to set up polling: %d\n", err); + return err; + } + + /* poll interval is about 60fps */ + input_set_poll_interval(idev, 16); + input_set_min_poll_interval(idev, 8); + input_set_max_poll_interval(idev, 32); + /* register input poll device */ - err = input_register_polled_device(pdev); + err = input_register_device(idev); if (err) { dev_err(&spi->dev, - "failed to register input poll device: %d\n", err); + "failed to register input device: %d\n", err); return err; } From bd88ce25335d23a9967e6d3d1efdc320dbd0a3a4 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 29 Oct 2019 16:41:57 -0700 Subject: [PATCH 31/70] Input: raspberrypi-ts - switch to using polled mode of input devices We have added polled mode to the normal input devices with the intent of retiring input_polled_dev. This converts raspberrypi-ts driver to use the polling mode of standard input devices and removes dependency on INPUT_POLLDEV. Link: https://lore.kernel.org/r/20191017204217.106453-2-dmitry.torokhov@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/Kconfig | 1 - drivers/input/touchscreen/raspberrypi-ts.c | 38 ++++++++++++---------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 46ad9090493b..00e7a9f218bc 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -700,7 +700,6 @@ config TOUCHSCREEN_EDT_FT5X06 config TOUCHSCREEN_RASPBERRYPI_FW tristate "Raspberry Pi's firmware base touch screen support" depends on RASPBERRYPI_FIRMWARE || (RASPBERRYPI_FIRMWARE=n && COMPILE_TEST) - select INPUT_POLLDEV help Say Y here if you have the official Raspberry Pi 7 inch screen on your system. diff --git a/drivers/input/touchscreen/raspberrypi-ts.c b/drivers/input/touchscreen/raspberrypi-ts.c index 69881265d121..0e2e08f3f433 100644 --- a/drivers/input/touchscreen/raspberrypi-ts.c +++ b/drivers/input/touchscreen/raspberrypi-ts.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include @@ -34,7 +33,7 @@ struct rpi_ts { struct platform_device *pdev; - struct input_polled_dev *poll_dev; + struct input_dev *input; struct touchscreen_properties prop; void __iomem *fw_regs_va; @@ -57,10 +56,9 @@ struct rpi_ts_regs { } point[RPI_TS_MAX_SUPPORTED_POINTS]; }; -static void rpi_ts_poll(struct input_polled_dev *dev) +static void rpi_ts_poll(struct input_dev *input) { - struct input_dev *input = dev->input; - struct rpi_ts *ts = dev->private; + struct rpi_ts *ts = input_get_drvdata(input); struct rpi_ts_regs regs; int modified_ids = 0; long released_ids; @@ -123,10 +121,9 @@ static int rpi_ts_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; - struct input_polled_dev *poll_dev; + struct input_dev *input; struct device_node *fw_node; struct rpi_firmware *fw; - struct input_dev *input; struct rpi_ts *ts; u32 touchbuf; int error; @@ -160,7 +157,6 @@ static int rpi_ts_probe(struct platform_device *pdev) return error; } - touchbuf = (u32)ts->fw_regs_phys; error = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_SET_TOUCHBUF, &touchbuf, sizeof(touchbuf)); @@ -170,19 +166,17 @@ static int rpi_ts_probe(struct platform_device *pdev) return error; } - poll_dev = devm_input_allocate_polled_device(dev); - if (!poll_dev) { + input = devm_input_allocate_device(dev); + if (!input) { dev_err(dev, "Failed to allocate input device\n"); return -ENOMEM; } - ts->poll_dev = poll_dev; - input = poll_dev->input; + + ts->input = input; + input_set_drvdata(input, ts); input->name = "raspberrypi-ts"; input->id.bustype = BUS_HOST; - poll_dev->poll_interval = RPI_TS_POLL_INTERVAL; - poll_dev->poll = rpi_ts_poll; - poll_dev->private = ts; input_set_abs_params(input, ABS_MT_POSITION_X, 0, RPI_TS_DEFAULT_WIDTH, 0, 0); @@ -197,7 +191,15 @@ static int rpi_ts_probe(struct platform_device *pdev) return error; } - error = input_register_polled_device(poll_dev); + error = input_setup_polling(input, rpi_ts_poll); + if (error) { + dev_err(dev, "could not set up polling mode, %d\n", error); + return error; + } + + input_set_poll_interval(input, RPI_TS_POLL_INTERVAL); + + error = input_register_device(input); if (error) { dev_err(dev, "could not register input device, %d\n", error); return error; @@ -214,10 +216,10 @@ MODULE_DEVICE_TABLE(of, rpi_ts_match); static struct platform_driver rpi_ts_driver = { .driver = { - .name = "raspberrypi-ts", + .name = "raspberrypi-ts", .of_match_table = rpi_ts_match, }, - .probe = rpi_ts_probe, + .probe = rpi_ts_probe, }; module_platform_driver(rpi_ts_driver); From 08b936012964dd9261c600e998e47321c92ca83f Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 29 Oct 2019 16:42:30 -0700 Subject: [PATCH 32/70] Input: sur40 - switch to using polled mode of input devices We have added polled mode to the normal input devices with the intent of retiring input_polled_dev. This converts sur40 driver to use the polling mode of standard input devices and removes dependency on INPUT_POLLDEV. Link: https://lore.kernel.org/r/20191017204217.106453-3-dmitry.torokhov@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/Kconfig | 1 - drivers/input/touchscreen/sur40.c | 92 ++++++++++++++++++------------- 2 files changed, 53 insertions(+), 40 deletions(-) diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 00e7a9f218bc..df9cb92166c3 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -1209,7 +1209,6 @@ config TOUCHSCREEN_SUR40 tristate "Samsung SUR40 (Surface 2.0/PixelSense) touchscreen" depends on USB && MEDIA_USB_SUPPORT && HAS_DMA depends on VIDEO_V4L2 - select INPUT_POLLDEV select VIDEOBUF2_DMA_SG help Say Y here if you want support for the Samsung SUR40 touchscreen diff --git a/drivers/input/touchscreen/sur40.c b/drivers/input/touchscreen/sur40.c index 3fd3e862269b..1dd47dda71cd 100644 --- a/drivers/input/touchscreen/sur40.c +++ b/drivers/input/touchscreen/sur40.c @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include @@ -206,7 +206,7 @@ struct sur40_state { struct usb_device *usbdev; struct device *dev; - struct input_polled_dev *input; + struct input_dev *input; struct v4l2_device v4l2; struct video_device vdev; @@ -370,6 +370,10 @@ static int sur40_init(struct sur40_state *dev) goto error; result = sur40_command(dev, SUR40_GET_VERSION, 0x03, buffer, 12); + if (result < 0) + goto error; + + result = 0; /* * Discard the result buffer - no known data inside except @@ -381,22 +385,22 @@ error: } /* - * Callback routines from input_polled_dev + * Callback routines from input_dev */ /* Enable the device, polling will now start. */ -static void sur40_open(struct input_polled_dev *polldev) +static int sur40_open(struct input_dev *input) { - struct sur40_state *sur40 = polldev->private; + struct sur40_state *sur40 = input_get_drvdata(input); dev_dbg(sur40->dev, "open\n"); - sur40_init(sur40); + return sur40_init(sur40); } /* Disable device, polling has stopped. */ -static void sur40_close(struct input_polled_dev *polldev) +static void sur40_close(struct input_dev *input) { - struct sur40_state *sur40 = polldev->private; + struct sur40_state *sur40 = input_get_drvdata(input); dev_dbg(sur40->dev, "close\n"); /* @@ -448,10 +452,9 @@ static void sur40_report_blob(struct sur40_blob *blob, struct input_dev *input) } /* core function: poll for new input data */ -static void sur40_poll(struct input_polled_dev *polldev) +static void sur40_poll(struct input_dev *input) { - struct sur40_state *sur40 = polldev->private; - struct input_dev *input = polldev->input; + struct sur40_state *sur40 = input_get_drvdata(input); int result, bulk_read, need_blobs, packet_blobs, i; u32 uninitialized_var(packet_id); @@ -613,10 +616,9 @@ err_poll: } /* Initialize input device parameters. */ -static void sur40_input_setup(struct input_dev *input_dev) +static int sur40_input_setup_events(struct input_dev *input_dev) { - __set_bit(EV_KEY, input_dev->evbit); - __set_bit(EV_ABS, input_dev->evbit); + int error; input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, SENSOR_RES_X, 0, 0); @@ -637,8 +639,14 @@ static void sur40_input_setup(struct input_dev *input_dev) input_set_abs_params(input_dev, ABS_MT_ORIENTATION, 0, 1, 0, 0); - input_mt_init_slots(input_dev, MAX_CONTACTS, - INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); + error = input_mt_init_slots(input_dev, MAX_CONTACTS, + INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); + if (error) { + dev_err(input_dev->dev.parent, "failed to set up slots\n"); + return error; + } + + return 0; } /* Check candidate USB interface. */ @@ -649,7 +657,7 @@ static int sur40_probe(struct usb_interface *interface, struct sur40_state *sur40; struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; - struct input_polled_dev *poll_dev; + struct input_dev *input; int error; /* Check if we really have the right interface. */ @@ -670,8 +678,8 @@ static int sur40_probe(struct usb_interface *interface, if (!sur40) return -ENOMEM; - poll_dev = input_allocate_polled_device(); - if (!poll_dev) { + input = input_allocate_device(); + if (!input) { error = -ENOMEM; goto err_free_dev; } @@ -681,26 +689,33 @@ static int sur40_probe(struct usb_interface *interface, spin_lock_init(&sur40->qlock); mutex_init(&sur40->lock); - /* Set up polled input device control structure */ - poll_dev->private = sur40; - poll_dev->poll_interval = POLL_INTERVAL; - poll_dev->open = sur40_open; - poll_dev->poll = sur40_poll; - poll_dev->close = sur40_close; - /* Set up regular input device structure */ - sur40_input_setup(poll_dev->input); - - poll_dev->input->name = DRIVER_LONG; - usb_to_input_id(usbdev, &poll_dev->input->id); + input->name = DRIVER_LONG; + usb_to_input_id(usbdev, &input->id); usb_make_path(usbdev, sur40->phys, sizeof(sur40->phys)); strlcat(sur40->phys, "/input0", sizeof(sur40->phys)); - poll_dev->input->phys = sur40->phys; - poll_dev->input->dev.parent = &interface->dev; + input->phys = sur40->phys; + input->dev.parent = &interface->dev; + + input->open = sur40_open; + input->close = sur40_close; + + error = sur40_input_setup_events(input); + if (error) + goto err_free_input; + + input_set_drvdata(input, sur40); + error = input_setup_polling(input, sur40_poll); + if (error) { + dev_err(&interface->dev, "failed to set up polling"); + goto err_free_input; + } + + input_set_poll_interval(input, POLL_INTERVAL); sur40->usbdev = usbdev; sur40->dev = &interface->dev; - sur40->input = poll_dev; + sur40->input = input; /* use the bulk-in endpoint tested above */ sur40->bulk_in_size = usb_endpoint_maxp(endpoint); @@ -709,11 +724,11 @@ static int sur40_probe(struct usb_interface *interface, if (!sur40->bulk_in_buffer) { dev_err(&interface->dev, "Unable to allocate input buffer."); error = -ENOMEM; - goto err_free_polldev; + goto err_free_input; } /* register the polled input device */ - error = input_register_polled_device(poll_dev); + error = input_register_device(input); if (error) { dev_err(&interface->dev, "Unable to register polled input device."); @@ -796,8 +811,8 @@ err_unreg_v4l2: v4l2_device_unregister(&sur40->v4l2); err_free_buffer: kfree(sur40->bulk_in_buffer); -err_free_polldev: - input_free_polled_device(sur40->input); +err_free_input: + input_free_device(input); err_free_dev: kfree(sur40); @@ -813,8 +828,7 @@ static void sur40_disconnect(struct usb_interface *interface) video_unregister_device(&sur40->vdev); v4l2_device_unregister(&sur40->v4l2); - input_unregister_polled_device(sur40->input); - input_free_polled_device(sur40->input); + input_unregister_device(sur40->input); kfree(sur40->bulk_in_buffer); kfree(sur40); From 9b587815ddd8f092c5a87f764e30b39fe8748c4d Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 29 Oct 2019 16:50:20 -0700 Subject: [PATCH 33/70] Input: ts4800-ts - switch to using polled mode of input devices We have added polled mode to the normal input devices with the intent of retiring input_polled_dev. This converts ts4800-ts driver to use the polling mode of standard input devices and removes dependency on INPUT_POLLDEV. Link: https://lore.kernel.org/r/20191017204217.106453-4-dmitry.torokhov@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/Kconfig | 1 - drivers/input/touchscreen/ts4800-ts.c | 68 +++++++++++++++------------ 2 files changed, 38 insertions(+), 31 deletions(-) diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index df9cb92166c3..2c00232b2506 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -1037,7 +1037,6 @@ config TOUCHSCREEN_TS4800 depends on HAS_IOMEM && OF depends on SOC_IMX51 || COMPILE_TEST select MFD_SYSCON - select INPUT_POLLDEV help Say Y here if you have a touchscreen on a TS-4800 board. diff --git a/drivers/input/touchscreen/ts4800-ts.c b/drivers/input/touchscreen/ts4800-ts.c index 5b4f5362c67b..6cf66aadc10e 100644 --- a/drivers/input/touchscreen/ts4800-ts.c +++ b/drivers/input/touchscreen/ts4800-ts.c @@ -10,7 +10,6 @@ #include #include -#include #include #include #include @@ -33,7 +32,7 @@ #define Y_OFFSET 0x2 struct ts4800_ts { - struct input_polled_dev *poll_dev; + struct input_dev *input; struct device *dev; char phys[32]; @@ -46,22 +45,26 @@ struct ts4800_ts { int debounce; }; -static void ts4800_ts_open(struct input_polled_dev *dev) +static int ts4800_ts_open(struct input_dev *input_dev) { - struct ts4800_ts *ts = dev->private; - int ret; + struct ts4800_ts *ts = input_get_drvdata(input_dev); + int error; ts->pendown = false; ts->debounce = DEBOUNCE_COUNT; - ret = regmap_update_bits(ts->regmap, ts->reg, ts->bit, ts->bit); - if (ret) - dev_warn(ts->dev, "Failed to enable touchscreen\n"); + error = regmap_update_bits(ts->regmap, ts->reg, ts->bit, ts->bit); + if (error) { + dev_warn(ts->dev, "Failed to enable touchscreen: %d\n", error); + return error; + } + + return 0; } -static void ts4800_ts_close(struct input_polled_dev *dev) +static void ts4800_ts_close(struct input_dev *input_dev) { - struct ts4800_ts *ts = dev->private; + struct ts4800_ts *ts = input_get_drvdata(input_dev); int ret; ret = regmap_update_bits(ts->regmap, ts->reg, ts->bit, 0); @@ -70,10 +73,9 @@ static void ts4800_ts_close(struct input_polled_dev *dev) } -static void ts4800_ts_poll(struct input_polled_dev *dev) +static void ts4800_ts_poll(struct input_dev *input_dev) { - struct input_dev *input_dev = dev->input; - struct ts4800_ts *ts = dev->private; + struct ts4800_ts *ts = input_get_drvdata(input_dev); u16 last_x = readw(ts->base + X_OFFSET); u16 last_y = readw(ts->base + Y_OFFSET); bool pendown = last_x & PENDOWN_MASK; @@ -146,7 +148,7 @@ static int ts4800_parse_dt(struct platform_device *pdev, static int ts4800_ts_probe(struct platform_device *pdev) { - struct input_polled_dev *poll_dev; + struct input_dev *input_dev; struct ts4800_ts *ts; int error; @@ -162,32 +164,38 @@ static int ts4800_ts_probe(struct platform_device *pdev) if (IS_ERR(ts->base)) return PTR_ERR(ts->base); - poll_dev = devm_input_allocate_polled_device(&pdev->dev); - if (!poll_dev) + input_dev = devm_input_allocate_device(&pdev->dev); + if (!input_dev) return -ENOMEM; snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&pdev->dev)); - ts->poll_dev = poll_dev; + ts->input = input_dev; ts->dev = &pdev->dev; - poll_dev->private = ts; - poll_dev->poll_interval = POLL_INTERVAL; - poll_dev->open = ts4800_ts_open; - poll_dev->close = ts4800_ts_close; - poll_dev->poll = ts4800_ts_poll; + input_set_drvdata(input_dev, ts); - poll_dev->input->name = "TS-4800 Touchscreen"; - poll_dev->input->phys = ts->phys; + input_dev->name = "TS-4800 Touchscreen"; + input_dev->phys = ts->phys; - input_set_capability(poll_dev->input, EV_KEY, BTN_TOUCH); - input_set_abs_params(poll_dev->input, ABS_X, 0, MAX_12BIT, 0, 0); - input_set_abs_params(poll_dev->input, ABS_Y, 0, MAX_12BIT, 0, 0); + input_dev->open = ts4800_ts_open; + input_dev->close = ts4800_ts_close; - error = input_register_polled_device(poll_dev); + input_set_capability(input_dev, EV_KEY, BTN_TOUCH); + input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0); + input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0); + + error = input_setup_polling(input_dev, ts4800_ts_poll); + if (error) { + dev_err(&pdev->dev, "Unable to set up polling: %d\n", error); + return error; + } + + input_set_poll_interval(input_dev, POLL_INTERVAL); + + error = input_register_device(input_dev); if (error) { dev_err(&pdev->dev, - "Unabled to register polled input device (%d)\n", - error); + "Unable to register input device: %d\n", error); return error; } From 7cca5a342ecd78ee163eaf352dc3995291b55406 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 29 Oct 2019 16:50:47 -0700 Subject: [PATCH 34/70] Input: tsc6507x-ts - switch to using polled mode of input devices We have added polled mode to the normal input devices with the intent of retiring input_polled_dev. This converts tsc6507x-ts driver to use the polling mode of standard input devices and removes dependency on INPUT_POLLDEV. Link: https://lore.kernel.org/r/20191017204217.106453-5-dmitry.torokhov@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/Kconfig | 1 - drivers/input/touchscreen/tps6507x-ts.c | 36 ++++++++++++------------- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 2c00232b2506..40bfc551ce30 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -1243,7 +1243,6 @@ config TOUCHSCREEN_SX8654 config TOUCHSCREEN_TPS6507X tristate "TPS6507x based touchscreens" depends on I2C - select INPUT_POLLDEV help Say Y here if you have a TPS6507x based touchscreen controller. diff --git a/drivers/input/touchscreen/tps6507x-ts.c b/drivers/input/touchscreen/tps6507x-ts.c index 75170a7439b1..357a3108f2e5 100644 --- a/drivers/input/touchscreen/tps6507x-ts.c +++ b/drivers/input/touchscreen/tps6507x-ts.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -40,7 +39,7 @@ struct ts_event { struct tps6507x_ts { struct device *dev; - struct input_polled_dev *poll_dev; + struct input_dev *input; struct tps6507x_dev *mfd; char phys[32]; struct ts_event tc; @@ -148,10 +147,9 @@ static s32 tps6507x_adc_standby(struct tps6507x_ts *tsc) return ret; } -static void tps6507x_ts_poll(struct input_polled_dev *poll_dev) +static void tps6507x_ts_poll(struct input_dev *input_dev) { - struct tps6507x_ts *tsc = poll_dev->private; - struct input_dev *input_dev = poll_dev->input; + struct tps6507x_ts *tsc = input_get_drvdata(input_dev); bool pendown; s32 ret; @@ -205,7 +203,6 @@ static int tps6507x_ts_probe(struct platform_device *pdev) const struct tps6507x_board *tps_board; const struct touchscreen_init_data *init_data; struct tps6507x_ts *tsc; - struct input_polled_dev *poll_dev; struct input_dev *input_dev; int error; @@ -240,23 +237,16 @@ static int tps6507x_ts_probe(struct platform_device *pdev) snprintf(tsc->phys, sizeof(tsc->phys), "%s/input0", dev_name(tsc->dev)); - poll_dev = devm_input_allocate_polled_device(&pdev->dev); - if (!poll_dev) { + input_dev = devm_input_allocate_device(&pdev->dev); + if (!input_dev) { dev_err(tsc->dev, "Failed to allocate polled input device.\n"); return -ENOMEM; } - tsc->poll_dev = poll_dev; - - poll_dev->private = tsc; - poll_dev->poll = tps6507x_ts_poll; - poll_dev->poll_interval = init_data ? - init_data->poll_period : TSC_DEFAULT_POLL_PERIOD; - - input_dev = poll_dev->input; - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); + tsc->input = input_dev; + input_set_drvdata(input_dev, tsc); + input_set_capability(input_dev, EV_KEY, BTN_TOUCH); input_set_abs_params(input_dev, ABS_X, 0, MAX_10BIT, 0, 0); input_set_abs_params(input_dev, ABS_Y, 0, MAX_10BIT, 0, 0); input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_10BIT, 0, 0); @@ -275,7 +265,15 @@ static int tps6507x_ts_probe(struct platform_device *pdev) if (error) return error; - error = input_register_polled_device(poll_dev); + error = input_setup_polling(input_dev, tps6507x_ts_poll); + if (error) + return error; + + input_set_poll_interval(input_dev, + init_data ? init_data->poll_period : + TSC_DEFAULT_POLL_PERIOD); + + error = input_register_device(input_dev); if (error) return error; From d0fe37b923e1ebe8d62b315a45b49ab321dc6319 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 29 Oct 2019 16:54:04 -0700 Subject: [PATCH 35/70] Input: adc-keys - switch to using polled mode of input devices We have added polled mode to the normal input devices with the intent of retiring input_polled_dev. This converts adc-keys driver to use the polling mode of standard input devices and removes dependency on INPUT_POLLDEV. Acked-by: Marco Felsch Link: https://lore.kernel.org/r/20191017204217.106453-6-dmitry.torokhov@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/Kconfig | 1 - drivers/input/keyboard/adc-keys.c | 36 ++++++++++++++++--------------- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 04ad3715c0d0..ffb7f7ba1861 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -16,7 +16,6 @@ if INPUT_KEYBOARD config KEYBOARD_ADC tristate "ADC Ladder Buttons" depends on IIO - select INPUT_POLLDEV help This driver implements support for buttons connected to an ADC using a resistor ladder. diff --git a/drivers/input/keyboard/adc-keys.c b/drivers/input/keyboard/adc-keys.c index 9885fd56f5f9..6d5be48d1b3d 100644 --- a/drivers/input/keyboard/adc-keys.c +++ b/drivers/input/keyboard/adc-keys.c @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include @@ -30,9 +29,9 @@ struct adc_keys_state { const struct adc_keys_button *map; }; -static void adc_keys_poll(struct input_polled_dev *dev) +static void adc_keys_poll(struct input_dev *input) { - struct adc_keys_state *st = dev->private; + struct adc_keys_state *st = input_get_drvdata(input); int i, value, ret; u32 diff, closest = 0xffffffff; int keycode = 0; @@ -55,12 +54,12 @@ static void adc_keys_poll(struct input_polled_dev *dev) keycode = 0; if (st->last_key && st->last_key != keycode) - input_report_key(dev->input, st->last_key, 0); + input_report_key(input, st->last_key, 0); if (keycode) - input_report_key(dev->input, keycode, 1); + input_report_key(input, keycode, 1); - input_sync(dev->input); + input_sync(input); st->last_key = keycode; } @@ -108,7 +107,6 @@ static int adc_keys_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct adc_keys_state *st; - struct input_polled_dev *poll_dev; struct input_dev *input; enum iio_chan_type type; int i, value; @@ -145,19 +143,13 @@ static int adc_keys_probe(struct platform_device *pdev) if (error) return error; - poll_dev = devm_input_allocate_polled_device(dev); - if (!poll_dev) { + input = devm_input_allocate_device(dev); + if (!input) { dev_err(dev, "failed to allocate input device\n"); return -ENOMEM; } - if (!device_property_read_u32(dev, "poll-interval", &value)) - poll_dev->poll_interval = value; - - poll_dev->poll = adc_keys_poll; - poll_dev->private = st; - - input = poll_dev->input; + input_set_drvdata(input, st); input->name = pdev->name; input->phys = "adc-keys/input0"; @@ -174,7 +166,17 @@ static int adc_keys_probe(struct platform_device *pdev) if (device_property_read_bool(dev, "autorepeat")) __set_bit(EV_REP, input->evbit); - error = input_register_polled_device(poll_dev); + + error = input_setup_polling(input, adc_keys_poll); + if (error) { + dev_err(dev, "Unable to set up polling: %d\n", error); + return error; + } + + if (!device_property_read_u32(dev, "poll-interval", &value)) + input_set_poll_interval(input, value); + + error = input_register_device(input); if (error) { dev_err(dev, "Unable to register input device: %d\n", error); return error; From ea6c52ae259a4b6663d299d5e3509f0c21ac9d5a Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 29 Oct 2019 16:54:37 -0700 Subject: [PATCH 36/70] Input: clps711x-keypad - switch to using polled mode of input devices We have added polled mode to the normal input devices with the intent of retiring input_polled_dev. This converts clps711x-keypad driver to use the polling mode of standard input devices and removes dependency on INPUT_POLLDEV. Also use managed API when allocating input device, this allows us to remove clps711x_keypad_remove() method. Acked-by: Andy Shevchenko Acked-by: Marco Felsch Link: https://lore.kernel.org/r/20191017204217.106453-7-dmitry.torokhov@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/Kconfig | 1 - drivers/input/keyboard/clps711x-keypad.c | 70 ++++++++++-------------- 2 files changed, 29 insertions(+), 42 deletions(-) diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index ffb7f7ba1861..1024e3fcc0d6 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -190,7 +190,6 @@ config KEYBOARD_CLPS711X tristate "CLPS711X Keypad support" depends on OF_GPIO && (ARCH_CLPS711X || COMPILE_TEST) select INPUT_MATRIXKMAP - select INPUT_POLLDEV help Say Y here to enable the matrix keypad on the Cirrus Logic CLPS711X CPUs. diff --git a/drivers/input/keyboard/clps711x-keypad.c b/drivers/input/keyboard/clps711x-keypad.c index c4a5c07a4b98..019dd6ed2c29 100644 --- a/drivers/input/keyboard/clps711x-keypad.c +++ b/drivers/input/keyboard/clps711x-keypad.c @@ -6,7 +6,6 @@ */ #include -#include #include #include #include @@ -30,10 +29,10 @@ struct clps711x_keypad_data { struct clps711x_gpio_data *gpio_data; }; -static void clps711x_keypad_poll(struct input_polled_dev *dev) +static void clps711x_keypad_poll(struct input_dev *input) { - const unsigned short *keycodes = dev->input->keycode; - struct clps711x_keypad_data *priv = dev->private; + const unsigned short *keycodes = input->keycode; + struct clps711x_keypad_data *priv = input_get_drvdata(input); bool sync = false; int col, row; @@ -61,14 +60,14 @@ static void clps711x_keypad_poll(struct input_polled_dev *dev) if (state) { set_bit(col, data->last_state); - input_event(dev->input, EV_MSC, - MSC_SCAN, code); + input_event(input, + EV_MSC, MSC_SCAN, code); } else { clear_bit(col, data->last_state); } if (keycodes[code]) - input_report_key(dev->input, + input_report_key(input, keycodes[code], state); sync = true; } @@ -80,7 +79,7 @@ static void clps711x_keypad_poll(struct input_polled_dev *dev) } if (sync) - input_sync(dev->input); + input_sync(input); } static int clps711x_keypad_probe(struct platform_device *pdev) @@ -88,7 +87,7 @@ static int clps711x_keypad_probe(struct platform_device *pdev) struct clps711x_keypad_data *priv; struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; - struct input_polled_dev *poll_dev; + struct input_dev *input; u32 poll_interval; int i, err; @@ -125,53 +124,43 @@ static int clps711x_keypad_probe(struct platform_device *pdev) if (err) return err; - poll_dev = input_allocate_polled_device(); - if (!poll_dev) + input = devm_input_allocate_device(dev); + if (!input) return -ENOMEM; - poll_dev->private = priv; - poll_dev->poll = clps711x_keypad_poll; - poll_dev->poll_interval = poll_interval; - poll_dev->input->name = pdev->name; - poll_dev->input->dev.parent = dev; - poll_dev->input->id.bustype = BUS_HOST; - poll_dev->input->id.vendor = 0x0001; - poll_dev->input->id.product = 0x0001; - poll_dev->input->id.version = 0x0100; + input_set_drvdata(input, priv); + + input->name = pdev->name; + input->dev.parent = dev; + input->id.bustype = BUS_HOST; + input->id.vendor = 0x0001; + input->id.product = 0x0001; + input->id.version = 0x0100; err = matrix_keypad_build_keymap(NULL, NULL, priv->row_count, CLPS711X_KEYPAD_COL_COUNT, - NULL, poll_dev->input); + NULL, input); if (err) - goto out_err; + return err; - input_set_capability(poll_dev->input, EV_MSC, MSC_SCAN); + input_set_capability(input, EV_MSC, MSC_SCAN); if (of_property_read_bool(np, "autorepeat")) - __set_bit(EV_REP, poll_dev->input->evbit); - - platform_set_drvdata(pdev, poll_dev); + __set_bit(EV_REP, input->evbit); /* Set all columns to low */ regmap_update_bits(priv->syscon, SYSCON_OFFSET, SYSCON1_KBDSCAN_MASK, SYSCON1_KBDSCAN(1)); - err = input_register_polled_device(poll_dev); + + err = input_setup_polling(input, clps711x_keypad_poll); if (err) - goto out_err; + return err; - return 0; + input_set_poll_interval(input, poll_interval); -out_err: - input_free_polled_device(poll_dev); - return err; -} - -static int clps711x_keypad_remove(struct platform_device *pdev) -{ - struct input_polled_dev *poll_dev = platform_get_drvdata(pdev); - - input_unregister_polled_device(poll_dev); - input_free_polled_device(poll_dev); + err = input_register_device(input); + if (err) + return err; return 0; } @@ -188,7 +177,6 @@ static struct platform_driver clps711x_keypad_driver = { .of_match_table = clps711x_keypad_of_match, }, .probe = clps711x_keypad_probe, - .remove = clps711x_keypad_remove, }; module_platform_driver(clps711x_keypad_driver); From c028c44f42838c502a8f4cc9f9e783cf4b65950b Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 29 Oct 2019 16:54:53 -0700 Subject: [PATCH 37/70] Input: jornada680_kbd - switch to using polled mode of input devices We have added polled mode to the normal input devices with the intent of retiring input_polled_dev. This converts jornada680_kbd driver to use the polling mode of standard input devices and removes dependency on INPUT_POLLDEV. Acked-by: Marco Felsch Link: https://lore.kernel.org/r/20191017204217.106453-8-dmitry.torokhov@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/Kconfig | 1 - drivers/input/keyboard/jornada680_kbd.c | 37 +++++++++++++------------ 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 1024e3fcc0d6..84daf99c475b 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -340,7 +340,6 @@ config KEYBOARD_HIL config KEYBOARD_HP6XX tristate "HP Jornada 6xx keyboard" depends on SH_HP6XX - select INPUT_POLLDEV help Say Y here if you have a HP Jornada 620/660/680/690 and want to support the built-in keyboard. diff --git a/drivers/input/keyboard/jornada680_kbd.c b/drivers/input/keyboard/jornada680_kbd.c index 4232aa876d2e..7e35081393be 100644 --- a/drivers/input/keyboard/jornada680_kbd.c +++ b/drivers/input/keyboard/jornada680_kbd.c @@ -15,7 +15,6 @@ #include #include -#include #include #include #include @@ -64,7 +63,7 @@ static const unsigned short jornada_scancodes[] = { #define JORNADA_SCAN_SIZE 18 struct jornadakbd { - struct input_polled_dev *poll_dev; + struct input_dev *input; unsigned short keymap[ARRAY_SIZE(jornada_scancodes)]; unsigned char length; unsigned char old_scan[JORNADA_SCAN_SIZE]; @@ -73,7 +72,7 @@ struct jornadakbd { static void jornada_parse_kbd(struct jornadakbd *jornadakbd) { - struct input_dev *input_dev = jornadakbd->poll_dev->input; + struct input_dev *input_dev = jornadakbd->input; unsigned short *keymap = jornadakbd->keymap; unsigned int sync_me = 0; unsigned int i, j; @@ -167,9 +166,9 @@ static void jornada_scan_keyb(unsigned char *s) *s++ = __raw_readb(PHDR); } -static void jornadakbd680_poll(struct input_polled_dev *dev) +static void jornadakbd680_poll(struct input_dev *input) { - struct jornadakbd *jornadakbd = dev->private; + struct jornadakbd *jornadakbd = input_get_drvdata(input); jornada_scan_keyb(jornadakbd->new_scan); jornada_parse_kbd(jornadakbd); @@ -179,7 +178,6 @@ static void jornadakbd680_poll(struct input_polled_dev *dev) static int jornada680kbd_probe(struct platform_device *pdev) { struct jornadakbd *jornadakbd; - struct input_polled_dev *poll_dev; struct input_dev *input_dev; int i, error; @@ -188,29 +186,24 @@ static int jornada680kbd_probe(struct platform_device *pdev) if (!jornadakbd) return -ENOMEM; - poll_dev = devm_input_allocate_polled_device(&pdev->dev); - if (!poll_dev) { - dev_err(&pdev->dev, "failed to allocate polled input device\n"); + input_dev = devm_input_allocate_device(&pdev->dev); + if (!input_dev) { + dev_err(&pdev->dev, "failed to allocate input device\n"); return -ENOMEM; } - jornadakbd->poll_dev = poll_dev; + jornadakbd->input = input_dev; memcpy(jornadakbd->keymap, jornada_scancodes, sizeof(jornadakbd->keymap)); - poll_dev->private = jornadakbd; - poll_dev->poll = jornadakbd680_poll; - poll_dev->poll_interval = 50; /* msec */ - - input_dev = poll_dev->input; + input_set_drvdata(input_dev, jornadakbd); input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); input_dev->name = "HP Jornada 680 keyboard"; input_dev->phys = "jornadakbd/input0"; input_dev->keycode = jornadakbd->keymap; input_dev->keycodesize = sizeof(unsigned short); input_dev->keycodemax = ARRAY_SIZE(jornada_scancodes); - input_dev->dev.parent = &pdev->dev; input_dev->id.bustype = BUS_HOST; for (i = 0; i < 128; i++) @@ -220,9 +213,17 @@ static int jornada680kbd_probe(struct platform_device *pdev) input_set_capability(input_dev, EV_MSC, MSC_SCAN); - error = input_register_polled_device(jornadakbd->poll_dev); + error = input_setup_polling(input_dev, jornadakbd680_poll); if (error) { - dev_err(&pdev->dev, "failed to register polled input device\n"); + dev_err(&pdev->dev, "failed to set up polling\n"); + return error; + } + + input_set_poll_interval(input_dev, 50 /* msec */); + + error = input_register_device(input_dev); + if (error) { + dev_err(&pdev->dev, "failed to register input device\n"); return error; } From 9584bded0ba886b13a41eb25e0ed1431c2191979 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 29 Oct 2019 16:55:10 -0700 Subject: [PATCH 38/70] Input: gpio_keys_polled - switch to using polled mode of input devices We have added polled mode to the normal input devices with the intent of retiring input_polled_dev. This converts gpio_keys_polled driver to use the polling mode of standard input devices and removes dependency on INPUT_POLLDEV. Note that we still keep polled and non-polled gpio-keys drivers separate, as they are different enough and mixing them up would make the code pretty confusing. Acked-by: Andy Shevchenko Acked-by: Marco Felsch Link: https://lore.kernel.org/r/20191017204217.106453-9-dmitry.torokhov@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/Kconfig | 1 - drivers/input/keyboard/gpio_keys_polled.c | 65 ++++++++++++----------- 2 files changed, 34 insertions(+), 32 deletions(-) diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 84daf99c475b..1ddfc2413035 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -248,7 +248,6 @@ config KEYBOARD_GPIO config KEYBOARD_GPIO_POLLED tristate "Polled GPIO buttons" depends on GPIOLIB - select INPUT_POLLDEV help This driver implements support for buttons connected to GPIO pins that are not capable of generating interrupts. diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c index 51bbd010089a..6eb0a2f3f9de 100644 --- a/drivers/input/keyboard/gpio_keys_polled.c +++ b/drivers/input/keyboard/gpio_keys_polled.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include @@ -34,7 +33,7 @@ struct gpio_keys_button_data { }; struct gpio_keys_polled_dev { - struct input_polled_dev *poll_dev; + struct input_dev *input; struct device *dev; const struct gpio_keys_platform_data *pdata; unsigned long rel_axis_seen[BITS_TO_LONGS(REL_CNT)]; @@ -42,12 +41,11 @@ struct gpio_keys_polled_dev { struct gpio_keys_button_data data[0]; }; -static void gpio_keys_button_event(struct input_polled_dev *dev, +static void gpio_keys_button_event(struct input_dev *input, const struct gpio_keys_button *button, int state) { - struct gpio_keys_polled_dev *bdev = dev->private; - struct input_dev *input = dev->input; + struct gpio_keys_polled_dev *bdev = input_get_drvdata(input); unsigned int type = button->type ?: EV_KEY; if (type == EV_REL) { @@ -66,7 +64,7 @@ static void gpio_keys_button_event(struct input_polled_dev *dev, } } -static void gpio_keys_polled_check_state(struct input_polled_dev *dev, +static void gpio_keys_polled_check_state(struct input_dev *input, const struct gpio_keys_button *button, struct gpio_keys_button_data *bdata) { @@ -74,10 +72,10 @@ static void gpio_keys_polled_check_state(struct input_polled_dev *dev, state = gpiod_get_value_cansleep(bdata->gpiod); if (state < 0) { - dev_err(dev->input->dev.parent, + dev_err(input->dev.parent, "failed to get gpio state: %d\n", state); } else { - gpio_keys_button_event(dev, button, state); + gpio_keys_button_event(input, button, state); if (state != bdata->last_state) { bdata->count = 0; @@ -86,11 +84,10 @@ static void gpio_keys_polled_check_state(struct input_polled_dev *dev, } } -static void gpio_keys_polled_poll(struct input_polled_dev *dev) +static void gpio_keys_polled_poll(struct input_dev *input) { - struct gpio_keys_polled_dev *bdev = dev->private; + struct gpio_keys_polled_dev *bdev = input_get_drvdata(input); const struct gpio_keys_platform_data *pdata = bdev->pdata; - struct input_dev *input = dev->input; int i; memset(bdev->rel_axis_seen, 0, sizeof(bdev->rel_axis_seen)); @@ -101,10 +98,10 @@ static void gpio_keys_polled_poll(struct input_polled_dev *dev) if (bdata->count < bdata->threshold) { bdata->count++; - gpio_keys_button_event(dev, &pdata->buttons[i], + gpio_keys_button_event(input, &pdata->buttons[i], bdata->last_state); } else { - gpio_keys_polled_check_state(dev, &pdata->buttons[i], + gpio_keys_polled_check_state(input, &pdata->buttons[i], bdata); } } @@ -122,18 +119,20 @@ static void gpio_keys_polled_poll(struct input_polled_dev *dev) input_sync(input); } -static void gpio_keys_polled_open(struct input_polled_dev *dev) +static int gpio_keys_polled_open(struct input_dev *input) { - struct gpio_keys_polled_dev *bdev = dev->private; + struct gpio_keys_polled_dev *bdev = input_get_drvdata(input); const struct gpio_keys_platform_data *pdata = bdev->pdata; if (pdata->enable) pdata->enable(bdev->dev); + + return 0; } -static void gpio_keys_polled_close(struct input_polled_dev *dev) +static void gpio_keys_polled_close(struct input_dev *input) { - struct gpio_keys_polled_dev *bdev = dev->private; + struct gpio_keys_polled_dev *bdev = input_get_drvdata(input); const struct gpio_keys_platform_data *pdata = bdev->pdata; if (pdata->disable) @@ -232,7 +231,6 @@ static int gpio_keys_polled_probe(struct platform_device *pdev) struct fwnode_handle *child = NULL; const struct gpio_keys_platform_data *pdata = dev_get_platdata(dev); struct gpio_keys_polled_dev *bdev; - struct input_polled_dev *poll_dev; struct input_dev *input; int error; int i; @@ -255,19 +253,13 @@ static int gpio_keys_polled_probe(struct platform_device *pdev) return -ENOMEM; } - poll_dev = devm_input_allocate_polled_device(dev); - if (!poll_dev) { - dev_err(dev, "no memory for polled device\n"); + input = devm_input_allocate_device(dev); + if (!input) { + dev_err(dev, "no memory for input device\n"); return -ENOMEM; } - poll_dev->private = bdev; - poll_dev->poll = gpio_keys_polled_poll; - poll_dev->poll_interval = pdata->poll_interval; - poll_dev->open = gpio_keys_polled_open; - poll_dev->close = gpio_keys_polled_close; - - input = poll_dev->input; + input_set_drvdata(input, bdev); input->name = pdata->name ?: pdev->name; input->phys = DRV_NAME"/input0"; @@ -277,6 +269,9 @@ static int gpio_keys_polled_probe(struct platform_device *pdev) input->id.product = 0x0001; input->id.version = 0x0100; + input->open = gpio_keys_polled_open; + input->close = gpio_keys_polled_close; + __set_bit(EV_KEY, input->evbit); if (pdata->rep) __set_bit(EV_REP, input->evbit); @@ -352,11 +347,19 @@ static int gpio_keys_polled_probe(struct platform_device *pdev) fwnode_handle_put(child); - bdev->poll_dev = poll_dev; + bdev->input = input; bdev->dev = dev; bdev->pdata = pdata; - error = input_register_polled_device(poll_dev); + error = input_setup_polling(input, gpio_keys_polled_poll); + if (error) { + dev_err(dev, "unable to set up polling, err=%d\n", error); + return error; + } + + input_set_poll_interval(input, pdata->poll_interval); + + error = input_register_device(input); if (error) { dev_err(dev, "unable to register polled device, err=%d\n", error); @@ -365,7 +368,7 @@ static int gpio_keys_polled_probe(struct platform_device *pdev) /* report initial state of the buttons */ for (i = 0; i < pdata->nbuttons; i++) - gpio_keys_polled_check_state(poll_dev, &pdata->buttons[i], + gpio_keys_polled_check_state(input, &pdata->buttons[i], &bdev->data[i]); input_sync(input); From 071ec845c8c65a992b7760172e84a456382315d7 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 29 Oct 2019 17:02:19 -0700 Subject: [PATCH 39/70] Input: apanel - switch to using polled mode of input devices We have added polled mode to the normal input devices with the intent of retiring input_polled_dev. This converts apanel driver to use the polling mode of standard input devices and removes dependency on INPUT_POLLDEV. While at it, let's convert the driver to use devm. Link: https://lore.kernel.org/r/20191017204217.106453-10-dmitry.torokhov@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/misc/Kconfig | 1 - drivers/input/misc/apanel.c | 183 ++++++++++++++++-------------------- 2 files changed, 79 insertions(+), 105 deletions(-) diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 7d9ae394e597..a6b8af69915d 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -257,7 +257,6 @@ config INPUT_MMA8450 config INPUT_APANEL tristate "Fujitsu Lifebook Application Panel buttons" depends on X86 && I2C && LEDS_CLASS - select INPUT_POLLDEV select CHECK_SIGNATURE help Say Y here for support of the Application Panel buttons, used on diff --git a/drivers/input/misc/apanel.c b/drivers/input/misc/apanel.c index 53ec40d1b90d..7276657ad7ca 100644 --- a/drivers/input/misc/apanel.c +++ b/drivers/input/misc/apanel.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include @@ -51,19 +51,28 @@ static enum apanel_chip device_chip[APANEL_DEV_MAX]; #define MAX_PANEL_KEYS 12 struct apanel { - struct input_polled_dev *ipdev; + struct input_dev *idev; struct i2c_client *client; unsigned short keymap[MAX_PANEL_KEYS]; - u16 nkeys; + u16 nkeys; struct led_classdev mail_led; }; +static const unsigned short apanel_keymap[MAX_PANEL_KEYS] = { + [0] = KEY_MAIL, + [1] = KEY_WWW, + [2] = KEY_PROG2, + [3] = KEY_PROG1, -static int apanel_probe(struct i2c_client *, const struct i2c_device_id *); + [8] = KEY_FORWARD, + [9] = KEY_REWIND, + [10] = KEY_STOPCD, + [11] = KEY_PLAYPAUSE, +}; static void report_key(struct input_dev *input, unsigned keycode) { - pr_debug(APANEL ": report key %#x\n", keycode); + dev_dbg(input->dev.parent, "report key %#x\n", keycode); input_report_key(input, keycode, 1); input_sync(input); @@ -79,10 +88,9 @@ static void report_key(struct input_dev *input, unsigned keycode) * CD keys: * Forward (0x100), Rewind (0x200), Stop (0x400), Pause (0x800) */ -static void apanel_poll(struct input_polled_dev *ipdev) +static void apanel_poll(struct input_dev *idev) { - struct apanel *ap = ipdev->private; - struct input_dev *idev = ipdev->input; + struct apanel *ap = input_get_drvdata(idev); u8 cmd = device_chip[APANEL_DEV_APPBTN] == CHIP_OZ992C ? 0 : 8; s32 data; int i; @@ -112,22 +120,76 @@ static int mail_led_set(struct led_classdev *led, return i2c_smbus_write_word_data(ap->client, 0x10, led_bits); } -static int apanel_remove(struct i2c_client *client) +static int apanel_probe(struct i2c_client *client, + const struct i2c_device_id *id) { - struct apanel *ap = i2c_get_clientdata(client); + struct apanel *ap; + struct input_dev *idev; + u8 cmd = device_chip[APANEL_DEV_APPBTN] == CHIP_OZ992C ? 0 : 8; + int i, err; - if (device_chip[APANEL_DEV_LED] != CHIP_NONE) - led_classdev_unregister(&ap->mail_led); + ap = devm_kzalloc(&client->dev, sizeof(*ap), GFP_KERNEL); + if (!ap) + return -ENOMEM; - input_unregister_polled_device(ap->ipdev); - input_free_polled_device(ap->ipdev); + idev = devm_input_allocate_device(&client->dev); + if (!idev) + return -ENOMEM; + + ap->idev = idev; + ap->client = client; + + i2c_set_clientdata(client, ap); + + err = i2c_smbus_write_word_data(client, cmd, 0); + if (err) { + dev_warn(&client->dev, "smbus write error %d\n", err); + return err; + } + + input_set_drvdata(idev, ap); + + idev->name = APANEL_NAME " buttons"; + idev->phys = "apanel/input0"; + idev->id.bustype = BUS_HOST; + + memcpy(ap->keymap, apanel_keymap, sizeof(apanel_keymap)); + idev->keycode = ap->keymap; + idev->keycodesize = sizeof(ap->keymap[0]); + idev->keycodemax = (device_chip[APANEL_DEV_CDBTN] != CHIP_NONE) ? 12 : 4; + + set_bit(EV_KEY, idev->evbit); + for (i = 0; i < idev->keycodemax; i++) + if (ap->keymap[i]) + set_bit(ap->keymap[i], idev->keybit); + + err = input_setup_polling(idev, apanel_poll); + if (err) + return err; + + input_set_poll_interval(idev, POLL_INTERVAL_DEFAULT); + + err = input_register_device(idev); + if (err) + return err; + + if (device_chip[APANEL_DEV_LED] != CHIP_NONE) { + ap->mail_led.name = "mail:blue"; + ap->mail_led.brightness_set_blocking = mail_led_set; + err = devm_led_classdev_register(&client->dev, &ap->mail_led); + if (err) + return err; + } return 0; } static void apanel_shutdown(struct i2c_client *client) { - apanel_remove(client); + struct apanel *ap = i2c_get_clientdata(client); + + if (device_chip[APANEL_DEV_LED] != CHIP_NONE) + led_set_brightness(&ap->mail_led, LED_OFF); } static const struct i2c_device_id apanel_id[] = { @@ -140,98 +202,11 @@ static struct i2c_driver apanel_driver = { .driver = { .name = APANEL, }, - .probe = &apanel_probe, - .remove = &apanel_remove, - .shutdown = &apanel_shutdown, + .probe = apanel_probe, + .shutdown = apanel_shutdown, .id_table = apanel_id, }; -static struct apanel apanel = { - .keymap = { - [0] = KEY_MAIL, - [1] = KEY_WWW, - [2] = KEY_PROG2, - [3] = KEY_PROG1, - - [8] = KEY_FORWARD, - [9] = KEY_REWIND, - [10] = KEY_STOPCD, - [11] = KEY_PLAYPAUSE, - - }, - .mail_led = { - .name = "mail:blue", - .brightness_set_blocking = mail_led_set, - }, -}; - -/* NB: Only one panel on the i2c. */ -static int apanel_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct apanel *ap; - struct input_polled_dev *ipdev; - struct input_dev *idev; - u8 cmd = device_chip[APANEL_DEV_APPBTN] == CHIP_OZ992C ? 0 : 8; - int i, err = -ENOMEM; - - ap = &apanel; - - ipdev = input_allocate_polled_device(); - if (!ipdev) - goto out1; - - ap->ipdev = ipdev; - ap->client = client; - - i2c_set_clientdata(client, ap); - - err = i2c_smbus_write_word_data(client, cmd, 0); - if (err) { - dev_warn(&client->dev, APANEL ": smbus write error %d\n", - err); - goto out3; - } - - ipdev->poll = apanel_poll; - ipdev->poll_interval = POLL_INTERVAL_DEFAULT; - ipdev->private = ap; - - idev = ipdev->input; - idev->name = APANEL_NAME " buttons"; - idev->phys = "apanel/input0"; - idev->id.bustype = BUS_HOST; - idev->dev.parent = &client->dev; - - set_bit(EV_KEY, idev->evbit); - - idev->keycode = ap->keymap; - idev->keycodesize = sizeof(ap->keymap[0]); - idev->keycodemax = (device_chip[APANEL_DEV_CDBTN] != CHIP_NONE) ? 12 : 4; - - for (i = 0; i < idev->keycodemax; i++) - if (ap->keymap[i]) - set_bit(ap->keymap[i], idev->keybit); - - err = input_register_polled_device(ipdev); - if (err) - goto out3; - - if (device_chip[APANEL_DEV_LED] != CHIP_NONE) { - err = led_classdev_register(&client->dev, &ap->mail_led); - if (err) - goto out4; - } - - return 0; -out4: - input_unregister_polled_device(ipdev); -out3: - input_free_polled_device(ipdev); -out1: - return err; -} - /* Scan the system ROM for the signature "FJKEYINF" */ static __init const void __iomem *bios_signature(const void __iomem *bios) { From 4a767ec368bf4b743ce466394096c528eb4abecb Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 29 Oct 2019 17:03:45 -0700 Subject: [PATCH 40/70] Input: wistron_btns - switch to using polled mode of input devices We have added polled mode to the normal input devices with the intent of retiring input_polled_dev. This converts wistron_btns driver to use the polling mode of standard input devices and removes dependency on INPUT_POLLDEV. Link: https://lore.kernel.org/r/20191017204217.106453-11-dmitry.torokhov@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/misc/Kconfig | 1 - drivers/input/misc/wistron_btns.c | 53 ++++++++++++++++--------------- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index a6b8af69915d..248e3b40bd24 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -346,7 +346,6 @@ config INPUT_CPCAP_PWRBUTTON config INPUT_WISTRON_BTNS tristate "x86 Wistron laptop button interface" depends on X86_32 - select INPUT_POLLDEV select INPUT_SPARSEKMAP select NEW_LEDS select LEDS_CLASS diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c index 7ce6cc60d4d2..80dfd72a02d3 100644 --- a/drivers/input/misc/wistron_btns.c +++ b/drivers/input/misc/wistron_btns.c @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include #include @@ -1030,7 +1030,7 @@ static int __init select_keymap(void) /* Input layer interface */ -static struct input_polled_dev *wistron_idev; +static struct input_dev *wistron_idev; static unsigned long jiffies_last_press; static bool wifi_enabled; static bool bluetooth_enabled; @@ -1114,7 +1114,7 @@ static inline void wistron_led_resume(void) static void handle_key(u8 code) { const struct key_entry *key = - sparse_keymap_entry_from_scancode(wistron_idev->input, code); + sparse_keymap_entry_from_scancode(wistron_idev, code); if (key) { switch (key->type) { @@ -1133,14 +1133,14 @@ static void handle_key(u8 code) break; default: - sparse_keymap_report_entry(wistron_idev->input, - key, 1, true); + sparse_keymap_report_entry(wistron_idev, key, 1, true); break; } jiffies_last_press = jiffies; - } else + } else { printk(KERN_NOTICE "wistron_btns: Unknown key code %02X\n", code); + } } static void poll_bios(bool discard) @@ -1158,21 +1158,23 @@ static void poll_bios(bool discard) } } -static void wistron_flush(struct input_polled_dev *dev) +static int wistron_flush(struct input_dev *dev) { /* Flush stale event queue */ poll_bios(true); + + return 0; } -static void wistron_poll(struct input_polled_dev *dev) +static void wistron_poll(struct input_dev *dev) { poll_bios(false); /* Increase poll frequency if user is currently pressing keys (< 2s ago) */ if (time_before(jiffies, jiffies_last_press + 2 * HZ)) - dev->poll_interval = POLL_INTERVAL_BURST; + input_set_poll_interval(dev, POLL_INTERVAL_BURST); else - dev->poll_interval = POLL_INTERVAL_DEFAULT; + input_set_poll_interval(dev, POLL_INTERVAL_DEFAULT); } static int wistron_setup_keymap(struct input_dev *dev, @@ -1208,35 +1210,37 @@ static int wistron_setup_keymap(struct input_dev *dev, static int setup_input_dev(void) { - struct input_dev *input_dev; int error; - wistron_idev = input_allocate_polled_device(); + wistron_idev = input_allocate_device(); if (!wistron_idev) return -ENOMEM; + wistron_idev->name = "Wistron laptop buttons"; + wistron_idev->phys = "wistron/input0"; + wistron_idev->id.bustype = BUS_HOST; + wistron_idev->dev.parent = &wistron_device->dev; + wistron_idev->open = wistron_flush; - wistron_idev->poll = wistron_poll; - wistron_idev->poll_interval = POLL_INTERVAL_DEFAULT; - input_dev = wistron_idev->input; - input_dev->name = "Wistron laptop buttons"; - input_dev->phys = "wistron/input0"; - input_dev->id.bustype = BUS_HOST; - input_dev->dev.parent = &wistron_device->dev; - - error = sparse_keymap_setup(input_dev, keymap, wistron_setup_keymap); + error = sparse_keymap_setup(wistron_idev, keymap, wistron_setup_keymap); if (error) goto err_free_dev; - error = input_register_polled_device(wistron_idev); + error = input_setup_polling(wistron_idev, wistron_poll); + if (error) + goto err_free_dev; + + input_set_poll_interval(wistron_idev, POLL_INTERVAL_DEFAULT); + + error = input_register_device(wistron_idev); if (error) goto err_free_dev; return 0; err_free_dev: - input_free_polled_device(wistron_idev); + input_free_device(wistron_idev); return error; } @@ -1285,8 +1289,7 @@ static int wistron_probe(struct platform_device *dev) static int wistron_remove(struct platform_device *dev) { wistron_led_remove(); - input_unregister_polled_device(wistron_idev); - input_free_polled_device(wistron_idev); + input_unregister_device(wistron_idev); bios_detach(); return 0; From 4d69ca90de6ad611d74571ebd18d6bf86a9e1218 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 29 Oct 2019 17:03:54 -0700 Subject: [PATCH 41/70] Input: cobalt_btns - convert to use managed resources This simplifies error handling and allows to remove cobalt_buttons_remove() method. Link: https://lore.kernel.org/r/20191017204217.106453-12-dmitry.torokhov@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/misc/cobalt_btns.c | 57 ++++++++++---------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/drivers/input/misc/cobalt_btns.c b/drivers/input/misc/cobalt_btns.c index bcf6174bbd5d..f7c1693fc6bb 100644 --- a/drivers/input/misc/cobalt_btns.c +++ b/drivers/input/misc/cobalt_btns.c @@ -5,6 +5,7 @@ * Copyright (C) 2007-2008 Yoichi Yuasa */ #include +#include #include #include #include @@ -26,7 +27,6 @@ static const unsigned short cobalt_map[] = { }; struct buttons_dev { - struct input_polled_dev *poll_dev; unsigned short keymap[ARRAY_SIZE(cobalt_map)]; int count[ARRAY_SIZE(cobalt_map)]; void __iomem *reg; @@ -67,15 +67,24 @@ static int cobalt_buttons_probe(struct platform_device *pdev) struct resource *res; int error, i; - bdev = kzalloc(sizeof(struct buttons_dev), GFP_KERNEL); - poll_dev = input_allocate_polled_device(); - if (!bdev || !poll_dev) { - error = -ENOMEM; - goto err_free_mem; - } + bdev = devm_kzalloc(&pdev->dev, sizeof(*bdev), GFP_KERNEL); + if (!bdev) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -EBUSY; + + bdev->reg = devm_ioremap(&pdev->dev, res->start, resource_size(res)); + if (!bdev->reg) + return -ENOMEM; memcpy(bdev->keymap, cobalt_map, sizeof(bdev->keymap)); + poll_dev = devm_input_allocate_polled_device(&pdev->dev); + if (!poll_dev) + return -ENOMEM; + poll_dev->private = bdev; poll_dev->poll = handle_buttons; poll_dev->poll_interval = BUTTONS_POLL_INTERVAL; @@ -84,7 +93,6 @@ static int cobalt_buttons_probe(struct platform_device *pdev) input->name = "Cobalt buttons"; input->phys = "cobalt/input0"; input->id.bustype = BUS_HOST; - input->dev.parent = &pdev->dev; input->keycode = bdev->keymap; input->keycodemax = ARRAY_SIZE(bdev->keymap); @@ -96,39 +104,9 @@ static int cobalt_buttons_probe(struct platform_device *pdev) __set_bit(bdev->keymap[i], input->keybit); __clear_bit(KEY_RESERVED, input->keybit); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - error = -EBUSY; - goto err_free_mem; - } - - bdev->poll_dev = poll_dev; - bdev->reg = ioremap(res->start, resource_size(res)); - dev_set_drvdata(&pdev->dev, bdev); - error = input_register_polled_device(poll_dev); if (error) - goto err_iounmap; - - return 0; - - err_iounmap: - iounmap(bdev->reg); - err_free_mem: - input_free_polled_device(poll_dev); - kfree(bdev); - return error; -} - -static int cobalt_buttons_remove(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct buttons_dev *bdev = dev_get_drvdata(dev); - - input_unregister_polled_device(bdev->poll_dev); - input_free_polled_device(bdev->poll_dev); - iounmap(bdev->reg); - kfree(bdev); + return error; return 0; } @@ -141,7 +119,6 @@ MODULE_ALIAS("platform:Cobalt buttons"); static struct platform_driver cobalt_buttons_driver = { .probe = cobalt_buttons_probe, - .remove = cobalt_buttons_remove, .driver = { .name = "Cobalt buttons", }, From 5d96738d9a74ec774bc7408288b44a7db6321c47 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 29 Oct 2019 17:04:02 -0700 Subject: [PATCH 42/70] Input: cobalt_btns - switch to using polled mode of input devices We have added polled mode to the normal input devices with the intent of retiring input_polled_dev. This converts cobalt_btns driver to use the polling mode of standard input devices and removes dependency on INPUT_POLLDEV. Link: https://lore.kernel.org/r/20191017204217.106453-13-dmitry.torokhov@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/misc/Kconfig | 1 - drivers/input/misc/cobalt_btns.c | 26 ++++++++++++++------------ 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 248e3b40bd24..05520bf4e31d 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -326,7 +326,6 @@ config INPUT_IXP4XX_BEEPER config INPUT_COBALT_BTNS tristate "Cobalt button interface" depends on MIPS_COBALT - select INPUT_POLLDEV help Say Y here if you want to support MIPS Cobalt button interface. diff --git a/drivers/input/misc/cobalt_btns.c b/drivers/input/misc/cobalt_btns.c index f7c1693fc6bb..b1624f5414ee 100644 --- a/drivers/input/misc/cobalt_btns.c +++ b/drivers/input/misc/cobalt_btns.c @@ -4,7 +4,7 @@ * * Copyright (C) 2007-2008 Yoichi Yuasa */ -#include +#include #include #include #include @@ -32,10 +32,9 @@ struct buttons_dev { void __iomem *reg; }; -static void handle_buttons(struct input_polled_dev *dev) +static void handle_buttons(struct input_dev *input) { - struct buttons_dev *bdev = dev->private; - struct input_dev *input = dev->input; + struct buttons_dev *bdev = input_get_drvdata(input); uint32_t status; int i; @@ -62,7 +61,6 @@ static void handle_buttons(struct input_polled_dev *dev) static int cobalt_buttons_probe(struct platform_device *pdev) { struct buttons_dev *bdev; - struct input_polled_dev *poll_dev; struct input_dev *input; struct resource *res; int error, i; @@ -81,15 +79,12 @@ static int cobalt_buttons_probe(struct platform_device *pdev) memcpy(bdev->keymap, cobalt_map, sizeof(bdev->keymap)); - poll_dev = devm_input_allocate_polled_device(&pdev->dev); - if (!poll_dev) + input = devm_input_allocate_device(&pdev->dev); + if (!input) return -ENOMEM; - poll_dev->private = bdev; - poll_dev->poll = handle_buttons; - poll_dev->poll_interval = BUTTONS_POLL_INTERVAL; + input_set_drvdata(input, bdev); - input = poll_dev->input; input->name = "Cobalt buttons"; input->phys = "cobalt/input0"; input->id.bustype = BUS_HOST; @@ -104,7 +99,14 @@ static int cobalt_buttons_probe(struct platform_device *pdev) __set_bit(bdev->keymap[i], input->keybit); __clear_bit(KEY_RESERVED, input->keybit); - error = input_register_polled_device(poll_dev); + + error = input_setup_polling(input, handle_buttons); + if (error) + return error; + + input_set_poll_interval(input, BUTTONS_POLL_INTERVAL); + + error = input_register_device(input); if (error) return error; From 9e085dd069d5d868cca7ae92b610c678c170ac92 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 29 Oct 2019 17:04:10 -0700 Subject: [PATCH 43/70] Input: sgi_btns - switch to using managed resources Switching to devm API allows to clean up error handling paths and drop the remove() method. Link: https://lore.kernel.org/r/20191017204217.106453-14-dmitry.torokhov@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/misc/sgi_btns.c | 37 ++++++++--------------------------- 1 file changed, 8 insertions(+), 29 deletions(-) diff --git a/drivers/input/misc/sgi_btns.c b/drivers/input/misc/sgi_btns.c index 0fee6ddf3602..829277b4271f 100644 --- a/drivers/input/misc/sgi_btns.c +++ b/drivers/input/misc/sgi_btns.c @@ -45,7 +45,6 @@ static const unsigned short sgi_map[] = { }; struct buttons_dev { - struct input_polled_dev *poll_dev; unsigned short keymap[ARRAY_SIZE(sgi_map)]; int count[ARRAY_SIZE(sgi_map)]; }; @@ -84,12 +83,13 @@ static int sgi_buttons_probe(struct platform_device *pdev) struct input_dev *input; int error, i; - bdev = kzalloc(sizeof(struct buttons_dev), GFP_KERNEL); - poll_dev = input_allocate_polled_device(); - if (!bdev || !poll_dev) { - error = -ENOMEM; - goto err_free_mem; - } + bdev = devm_kzalloc(&pdev->dev, sizeof(*bdev), GFP_KERNEL); + if (!bdev) + return -ENOMEM; + + poll_dev = devm_input_allocate_polled_device(&pdev->dev); + if (!poll_dev) + return -ENOMEM; memcpy(bdev->keymap, sgi_map, sizeof(bdev->keymap)); @@ -101,7 +101,6 @@ static int sgi_buttons_probe(struct platform_device *pdev) input->name = "SGI buttons"; input->phys = "sgi/input0"; input->id.bustype = BUS_HOST; - input->dev.parent = &pdev->dev; input->keycode = bdev->keymap; input->keycodemax = ARRAY_SIZE(bdev->keymap); @@ -113,35 +112,15 @@ static int sgi_buttons_probe(struct platform_device *pdev) __set_bit(bdev->keymap[i], input->keybit); __clear_bit(KEY_RESERVED, input->keybit); - bdev->poll_dev = poll_dev; - platform_set_drvdata(pdev, bdev); - error = input_register_polled_device(poll_dev); if (error) - goto err_free_mem; - - return 0; - - err_free_mem: - input_free_polled_device(poll_dev); - kfree(bdev); - return error; -} - -static int sgi_buttons_remove(struct platform_device *pdev) -{ - struct buttons_dev *bdev = platform_get_drvdata(pdev); - - input_unregister_polled_device(bdev->poll_dev); - input_free_polled_device(bdev->poll_dev); - kfree(bdev); + return error; return 0; } static struct platform_driver sgi_buttons_driver = { .probe = sgi_buttons_probe, - .remove = sgi_buttons_remove, .driver = { .name = "sgibtns", }, From aede7a1e0cc3e5712f8cb2953198c295b487faed Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 29 Oct 2019 17:04:18 -0700 Subject: [PATCH 44/70] Input: sgi_btns - switch to using polled mode of input devices We have added polled mode to the normal input devices with the intent of retiring input_polled_dev. This converts sgi_btns driver to use the polling mode of standard input devices and removes dependency on INPUT_POLLDEV. Link: https://lore.kernel.org/r/20191017204217.106453-15-dmitry.torokhov@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/misc/Kconfig | 1 - drivers/input/misc/sgi_btns.c | 25 +++++++++++++------------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 05520bf4e31d..c27a9ee4ef9a 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -543,7 +543,6 @@ config INPUT_UINPUT config INPUT_SGI_BTNS tristate "SGI Indy/O2 volume button interface" depends on SGI_IP22 || SGI_IP32 - select INPUT_POLLDEV help Say Y here if you want to support SGI Indy/O2 volume button interface. diff --git a/drivers/input/misc/sgi_btns.c b/drivers/input/misc/sgi_btns.c index 829277b4271f..0657d785b3cc 100644 --- a/drivers/input/misc/sgi_btns.c +++ b/drivers/input/misc/sgi_btns.c @@ -4,7 +4,7 @@ * * Copyright (C) 2008 Thomas Bogendoerfer */ -#include +#include #include #include #include @@ -49,10 +49,9 @@ struct buttons_dev { int count[ARRAY_SIZE(sgi_map)]; }; -static void handle_buttons(struct input_polled_dev *dev) +static void handle_buttons(struct input_dev *input) { - struct buttons_dev *bdev = dev->private; - struct input_dev *input = dev->input; + struct buttons_dev *bdev = input_get_drvdata(input); u8 status; int i; @@ -79,7 +78,6 @@ static void handle_buttons(struct input_polled_dev *dev) static int sgi_buttons_probe(struct platform_device *pdev) { struct buttons_dev *bdev; - struct input_polled_dev *poll_dev; struct input_dev *input; int error, i; @@ -87,17 +85,14 @@ static int sgi_buttons_probe(struct platform_device *pdev) if (!bdev) return -ENOMEM; - poll_dev = devm_input_allocate_polled_device(&pdev->dev); - if (!poll_dev) + input = devm_input_allocate_device(&pdev->dev); + if (!input) return -ENOMEM; memcpy(bdev->keymap, sgi_map, sizeof(bdev->keymap)); - poll_dev->private = bdev; - poll_dev->poll = handle_buttons; - poll_dev->poll_interval = BUTTONS_POLL_INTERVAL; + input_set_drvdata(input, bdev); - input = poll_dev->input; input->name = "SGI buttons"; input->phys = "sgi/input0"; input->id.bustype = BUS_HOST; @@ -112,7 +107,13 @@ static int sgi_buttons_probe(struct platform_device *pdev) __set_bit(bdev->keymap[i], input->keybit); __clear_bit(KEY_RESERVED, input->keybit); - error = input_register_polled_device(poll_dev); + error = input_setup_polling(input, handle_buttons); + if (error) + return error; + + input_set_poll_interval(input, BUTTONS_POLL_INTERVAL); + + error = input_register_device(input); if (error) return error; From 528c7d02c78bc78aab40ed843129418dc2d44250 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 29 Oct 2019 17:04:25 -0700 Subject: [PATCH 45/70] Input: rb532_button - switch to using managed resources Using devm API allows us to clean up error handling paths and drop the remove() method. Link: https://lore.kernel.org/r/20191017204217.106453-16-dmitry.torokhov@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/misc/rb532_button.c | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/drivers/input/misc/rb532_button.c b/drivers/input/misc/rb532_button.c index 4412055f8761..3c43024f4527 100644 --- a/drivers/input/misc/rb532_button.c +++ b/drivers/input/misc/rb532_button.c @@ -58,7 +58,7 @@ static int rb532_button_probe(struct platform_device *pdev) struct input_polled_dev *poll_dev; int error; - poll_dev = input_allocate_polled_device(); + poll_dev = devm_input_allocate_polled_device(&pdev->dev); if (!poll_dev) return -ENOMEM; @@ -68,34 +68,18 @@ static int rb532_button_probe(struct platform_device *pdev) poll_dev->input->name = "rb532 button"; poll_dev->input->phys = "rb532/button0"; poll_dev->input->id.bustype = BUS_HOST; - poll_dev->input->dev.parent = &pdev->dev; - - dev_set_drvdata(&pdev->dev, poll_dev); input_set_capability(poll_dev->input, EV_KEY, RB532_BTN_KSYM); error = input_register_polled_device(poll_dev); - if (error) { - input_free_polled_device(poll_dev); + if (error) return error; - } - - return 0; -} - -static int rb532_button_remove(struct platform_device *pdev) -{ - struct input_polled_dev *poll_dev = dev_get_drvdata(&pdev->dev); - - input_unregister_polled_device(poll_dev); - input_free_polled_device(poll_dev); return 0; } static struct platform_driver rb532_button_driver = { .probe = rb532_button_probe, - .remove = rb532_button_remove, .driver = { .name = DRV_NAME, }, From 36bc3684c212d467ddae0dda3d18d64c5212bae6 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 29 Oct 2019 17:04:33 -0700 Subject: [PATCH 46/70] Input: rb532_button - switch to using polled mode of input devices We have added polled mode to the normal input devices with the intent of retiring input_polled_dev. This converts rb532_button driver to use the polling mode of standard input devices and removes dependency on INPUT_POLLDEV. Link: https://lore.kernel.org/r/20191017204217.106453-17-dmitry.torokhov@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/misc/Kconfig | 1 - drivers/input/misc/rb532_button.c | 32 ++++++++++++++++--------------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index c27a9ee4ef9a..102e993bbd6b 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -633,7 +633,6 @@ config INPUT_RB532_BUTTON tristate "Mikrotik Routerboard 532 button interface" depends on MIKROTIK_RB532 depends on GPIOLIB - select INPUT_POLLDEV help Say Y here if you want support for the S1 button built into Mikrotik's Routerboard 532. diff --git a/drivers/input/misc/rb532_button.c b/drivers/input/misc/rb532_button.c index 3c43024f4527..190a80e1e2c1 100644 --- a/drivers/input/misc/rb532_button.c +++ b/drivers/input/misc/rb532_button.c @@ -5,7 +5,7 @@ * Copyright (C) 2009 Phil Sutter */ -#include +#include #include #include #include @@ -46,32 +46,34 @@ static bool rb532_button_pressed(void) return !val; } -static void rb532_button_poll(struct input_polled_dev *poll_dev) +static void rb532_button_poll(struct input_dev *input) { - input_report_key(poll_dev->input, RB532_BTN_KSYM, - rb532_button_pressed()); - input_sync(poll_dev->input); + input_report_key(input, RB532_BTN_KSYM, rb532_button_pressed()); + input_sync(input); } static int rb532_button_probe(struct platform_device *pdev) { - struct input_polled_dev *poll_dev; + struct input_dev *input; int error; - poll_dev = devm_input_allocate_polled_device(&pdev->dev); - if (!poll_dev) + input = devm_input_allocate_device(&pdev->dev); + if (!input) return -ENOMEM; - poll_dev->poll = rb532_button_poll; - poll_dev->poll_interval = RB532_BTN_RATE; + input->name = "rb532 button"; + input->phys = "rb532/button0"; + input->id.bustype = BUS_HOST; - poll_dev->input->name = "rb532 button"; - poll_dev->input->phys = "rb532/button0"; - poll_dev->input->id.bustype = BUS_HOST; + input_set_capability(input, EV_KEY, RB532_BTN_KSYM); - input_set_capability(poll_dev->input, EV_KEY, RB532_BTN_KSYM); + error = input_setup_polling(input, rb532_button_poll); + if (error) + return error; - error = input_register_polled_device(poll_dev); + input_set_poll_interval(input, RB532_BTN_RATE); + + error = input_register_device(input); if (error) return error; From ff68cf0b166efd626e653d9ca55f1a1ec74f3667 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 29 Oct 2019 17:04:51 -0700 Subject: [PATCH 47/70] Input: gpio_decoder - switch to using polled mode of input devices We have added polled mode to the normal input devices with the intent of retiring input_polled_dev. This converts gpio_decoder driver to use the polling mode of standard input devices and removes dependency on INPUT_POLLDEV. Link: https://lore.kernel.org/r/20191017204217.106453-18-dmitry.torokhov@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/misc/Kconfig | 1 - drivers/input/misc/gpio_decoder.c | 42 +++++++++++++++++-------------- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 102e993bbd6b..b108c992bb7a 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -290,7 +290,6 @@ config INPUT_GPIO_BEEPER config INPUT_GPIO_DECODER tristate "Polled GPIO Decoder Input driver" depends on GPIOLIB || COMPILE_TEST - select INPUT_POLLDEV help Say Y here if you want driver to read status of multiple GPIO lines and report the encoded value as an absolute integer to diff --git a/drivers/input/misc/gpio_decoder.c b/drivers/input/misc/gpio_decoder.c index 1dca526e6f1a..145826a1a9a1 100644 --- a/drivers/input/misc/gpio_decoder.c +++ b/drivers/input/misc/gpio_decoder.c @@ -17,14 +17,12 @@ #include #include #include -#include #include #include #include #include struct gpio_decoder { - struct input_polled_dev *poll_dev; struct gpio_descs *input_gpios; struct device *dev; u32 axis; @@ -53,15 +51,15 @@ static int gpio_decoder_get_gpios_state(struct gpio_decoder *decoder) return ret; } -static void gpio_decoder_poll_gpios(struct input_polled_dev *poll_dev) +static void gpio_decoder_poll_gpios(struct input_dev *input) { - struct gpio_decoder *decoder = poll_dev->private; + struct gpio_decoder *decoder = input_get_drvdata(input); int state; state = gpio_decoder_get_gpios_state(decoder); if (state >= 0 && state != decoder->last_stable) { - input_report_abs(poll_dev->input, decoder->axis, state); - input_sync(poll_dev->input); + input_report_abs(input, decoder->axis, state); + input_sync(input); decoder->last_stable = state; } } @@ -70,20 +68,23 @@ static int gpio_decoder_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct gpio_decoder *decoder; - struct input_polled_dev *poll_dev; + struct input_dev *input; u32 max; int err; - decoder = devm_kzalloc(dev, sizeof(struct gpio_decoder), GFP_KERNEL); + decoder = devm_kzalloc(dev, sizeof(*decoder), GFP_KERNEL); if (!decoder) return -ENOMEM; + decoder->dev = dev; device_property_read_u32(dev, "linux,axis", &decoder->axis); + decoder->input_gpios = devm_gpiod_get_array(dev, NULL, GPIOD_IN); if (IS_ERR(decoder->input_gpios)) { dev_err(dev, "unable to acquire input gpios\n"); return PTR_ERR(decoder->input_gpios); } + if (decoder->input_gpios->ndescs < 2) { dev_err(dev, "not enough gpios found\n"); return -EINVAL; @@ -92,22 +93,25 @@ static int gpio_decoder_probe(struct platform_device *pdev) if (device_property_read_u32(dev, "decoder-max-value", &max)) max = (1U << decoder->input_gpios->ndescs) - 1; - decoder->dev = dev; - poll_dev = devm_input_allocate_polled_device(decoder->dev); - if (!poll_dev) + input = devm_input_allocate_device(dev); + if (!input) return -ENOMEM; - poll_dev->private = decoder; - poll_dev->poll = gpio_decoder_poll_gpios; - decoder->poll_dev = poll_dev; + input_set_drvdata(input, decoder); - poll_dev->input->name = pdev->name; - poll_dev->input->id.bustype = BUS_HOST; - input_set_abs_params(poll_dev->input, decoder->axis, 0, max, 0, 0); + input->name = pdev->name; + input->id.bustype = BUS_HOST; + input_set_abs_params(input, decoder->axis, 0, max, 0, 0); - err = input_register_polled_device(poll_dev); + err = input_setup_polling(input, gpio_decoder_poll_gpios); if (err) { - dev_err(dev, "failed to register polled device\n"); + dev_err(dev, "failed to set up polling\n"); + return err; + } + + err = input_register_device(input); + if (err) { + dev_err(dev, "failed to register input device\n"); return err; } From 867e8820e037c45f57ad39869ecfb3e58a23d908 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 29 Oct 2019 17:04:58 -0700 Subject: [PATCH 48/70] Input: mma8450 - switch to using polled mode of input devices We have added polled mode to the normal input devices with the intent of retiring input_polled_dev. This converts mma8450 driver to use the polling mode of standard input devices and removes dependency on INPUT_POLLDEV. Link: https://lore.kernel.org/r/20191017204217.106453-19-dmitry.torokhov@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/misc/Kconfig | 1 - drivers/input/misc/mma8450.c | 101 ++++++++++++++++------------------- 2 files changed, 46 insertions(+), 56 deletions(-) diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index b108c992bb7a..e1309cb190e1 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -246,7 +246,6 @@ config INPUT_MC13783_PWRBUTTON config INPUT_MMA8450 tristate "MMA8450 - Freescale's 3-Axis, 8/12-bit Digital Accelerometer" depends on I2C - select INPUT_POLLDEV help Say Y here if you want to support Freescale's MMA8450 Accelerometer through I2C interface. diff --git a/drivers/input/misc/mma8450.c b/drivers/input/misc/mma8450.c index 49f5242bc54c..1b5a5e19230a 100644 --- a/drivers/input/misc/mma8450.c +++ b/drivers/input/misc/mma8450.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #define MMA8450_DRV_NAME "mma8450" @@ -39,15 +39,8 @@ #define MMA8450_CTRL_REG1 0x38 #define MMA8450_CTRL_REG2 0x39 -/* mma8450 status */ -struct mma8450 { - struct i2c_client *client; - struct input_polled_dev *idev; -}; - -static int mma8450_read(struct mma8450 *m, unsigned off) +static int mma8450_read(struct i2c_client *c, unsigned int off) { - struct i2c_client *c = m->client; int ret; ret = i2c_smbus_read_byte_data(c, off); @@ -59,9 +52,8 @@ static int mma8450_read(struct mma8450 *m, unsigned off) return ret; } -static int mma8450_write(struct mma8450 *m, unsigned off, u8 v) +static int mma8450_write(struct i2c_client *c, unsigned int off, u8 v) { - struct i2c_client *c = m->client; int error; error = i2c_smbus_write_byte_data(c, off, v); @@ -75,10 +67,9 @@ static int mma8450_write(struct mma8450 *m, unsigned off, u8 v) return 0; } -static int mma8450_read_block(struct mma8450 *m, unsigned off, +static int mma8450_read_block(struct i2c_client *c, unsigned int off, u8 *buf, size_t size) { - struct i2c_client *c = m->client; int err; err = i2c_smbus_read_i2c_block_data(c, off, size, buf); @@ -92,21 +83,21 @@ static int mma8450_read_block(struct mma8450 *m, unsigned off, return 0; } -static void mma8450_poll(struct input_polled_dev *dev) +static void mma8450_poll(struct input_dev *input) { - struct mma8450 *m = dev->private; + struct i2c_client *c = input_get_drvdata(input); int x, y, z; int ret; u8 buf[6]; - ret = mma8450_read(m, MMA8450_STATUS); + ret = mma8450_read(c, MMA8450_STATUS); if (ret < 0) return; if (!(ret & MMA8450_STATUS_ZXYDR)) return; - ret = mma8450_read_block(m, MMA8450_OUT_X_LSB, buf, sizeof(buf)); + ret = mma8450_read_block(c, MMA8450_OUT_X_LSB, buf, sizeof(buf)); if (ret < 0) return; @@ -114,41 +105,42 @@ static void mma8450_poll(struct input_polled_dev *dev) y = ((int)(s8)buf[3] << 4) | (buf[2] & 0xf); z = ((int)(s8)buf[5] << 4) | (buf[4] & 0xf); - input_report_abs(dev->input, ABS_X, x); - input_report_abs(dev->input, ABS_Y, y); - input_report_abs(dev->input, ABS_Z, z); - input_sync(dev->input); + input_report_abs(input, ABS_X, x); + input_report_abs(input, ABS_Y, y); + input_report_abs(input, ABS_Z, z); + input_sync(input); } /* Initialize the MMA8450 chip */ -static void mma8450_open(struct input_polled_dev *dev) +static int mma8450_open(struct input_dev *input) { - struct mma8450 *m = dev->private; + struct i2c_client *c = input_get_drvdata(input); int err; /* enable all events from X/Y/Z, no FIFO */ - err = mma8450_write(m, MMA8450_XYZ_DATA_CFG, 0x07); + err = mma8450_write(c, MMA8450_XYZ_DATA_CFG, 0x07); if (err) - return; + return err; /* * Sleep mode poll rate - 50Hz * System output data rate - 400Hz * Full scale selection - Active, +/- 2G */ - err = mma8450_write(m, MMA8450_CTRL_REG1, 0x01); - if (err < 0) - return; + err = mma8450_write(c, MMA8450_CTRL_REG1, 0x01); + if (err) + return err; msleep(MODE_CHANGE_DELAY_MS); + return 0; } -static void mma8450_close(struct input_polled_dev *dev) +static void mma8450_close(struct input_dev *input) { - struct mma8450 *m = dev->private; + struct i2c_client *c = input_get_drvdata(input); - mma8450_write(m, MMA8450_CTRL_REG1, 0x00); - mma8450_write(m, MMA8450_CTRL_REG2, 0x01); + mma8450_write(c, MMA8450_CTRL_REG1, 0x00); + mma8450_write(c, MMA8450_CTRL_REG2, 0x01); } /* @@ -157,38 +149,37 @@ static void mma8450_close(struct input_polled_dev *dev) static int mma8450_probe(struct i2c_client *c, const struct i2c_device_id *id) { - struct input_polled_dev *idev; - struct mma8450 *m; + struct input_dev *input; int err; - m = devm_kzalloc(&c->dev, sizeof(*m), GFP_KERNEL); - if (!m) + input = devm_input_allocate_device(&c->dev); + if (!input) return -ENOMEM; - idev = devm_input_allocate_polled_device(&c->dev); - if (!idev) - return -ENOMEM; + input_set_drvdata(input, c); - m->client = c; - m->idev = idev; + input->name = MMA8450_DRV_NAME; + input->id.bustype = BUS_I2C; - idev->private = m; - idev->input->name = MMA8450_DRV_NAME; - idev->input->id.bustype = BUS_I2C; - idev->poll = mma8450_poll; - idev->poll_interval = POLL_INTERVAL; - idev->poll_interval_max = POLL_INTERVAL_MAX; - idev->open = mma8450_open; - idev->close = mma8450_close; + input->open = mma8450_open; + input->close = mma8450_close; - __set_bit(EV_ABS, idev->input->evbit); - input_set_abs_params(idev->input, ABS_X, -2048, 2047, 32, 32); - input_set_abs_params(idev->input, ABS_Y, -2048, 2047, 32, 32); - input_set_abs_params(idev->input, ABS_Z, -2048, 2047, 32, 32); + input_set_abs_params(input, ABS_X, -2048, 2047, 32, 32); + input_set_abs_params(input, ABS_Y, -2048, 2047, 32, 32); + input_set_abs_params(input, ABS_Z, -2048, 2047, 32, 32); - err = input_register_polled_device(idev); + err = input_setup_polling(input, mma8450_poll); if (err) { - dev_err(&c->dev, "failed to register polled input device\n"); + dev_err(&c->dev, "failed to set up polling\n"); + return err; + } + + input_set_poll_interval(input, POLL_INTERVAL); + input_set_max_poll_interval(input, POLL_INTERVAL_MAX); + + err = input_register_device(input); + if (err) { + dev_err(&c->dev, "failed to register input device\n"); return err; } From 493a6ebd59dcecb09d8e97293e1b254ad0003a7b Mon Sep 17 00:00:00 2001 From: Jonathan Bakker Date: Tue, 29 Oct 2019 17:05:06 -0700 Subject: [PATCH 49/70] Input: bma150 - use managed resources helpers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver can be cleaned up by using managed resource helpers. Signed-off-by: Jonathan Bakker Signed-off-by: Paweł Chmiel [dtor: do not explicitly set parent of input device since we are using devm] Link: https://lore.kernel.org/r/20191017204217.106453-20-dmitry.torokhov@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/misc/bma150.c | 51 ++++++++++--------------------------- 1 file changed, 14 insertions(+), 37 deletions(-) diff --git a/drivers/input/misc/bma150.c b/drivers/input/misc/bma150.c index 735d3a46f44b..d65b008a3c7a 100644 --- a/drivers/input/misc/bma150.c +++ b/drivers/input/misc/bma150.c @@ -439,13 +439,11 @@ static int bma150_initialize(struct bma150_data *bma150, return bma150_set_mode(bma150, BMA150_MODE_SLEEP); } -static void bma150_init_input_device(struct bma150_data *bma150, - struct input_dev *idev) +static void bma150_init_input_device(struct input_dev *idev) { idev->name = BMA150_DRIVER; idev->phys = BMA150_DRIVER "/input0"; idev->id.bustype = BUS_I2C; - idev->dev.parent = &bma150->client->dev; idev->evbit[0] = BIT_MASK(EV_ABS); input_set_abs_params(idev, ABS_X, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0); @@ -458,11 +456,11 @@ static int bma150_register_input_device(struct bma150_data *bma150) struct input_dev *idev; int error; - idev = input_allocate_device(); + idev = devm_input_allocate_device(&bma150->client->dev); if (!idev) return -ENOMEM; - bma150_init_input_device(bma150, idev); + bma150_init_input_device(idev); idev->open = bma150_irq_open; idev->close = bma150_irq_close; @@ -471,10 +469,8 @@ static int bma150_register_input_device(struct bma150_data *bma150) bma150->input = idev; error = input_register_device(idev); - if (error) { - input_free_device(idev); + if (error) return error; - } return 0; } @@ -484,7 +480,7 @@ static int bma150_register_polled_device(struct bma150_data *bma150) struct input_polled_dev *ipoll_dev; int error; - ipoll_dev = input_allocate_polled_device(); + ipoll_dev = devm_input_allocate_polled_device(&bma150->client->dev); if (!ipoll_dev) return -ENOMEM; @@ -496,16 +492,14 @@ static int bma150_register_polled_device(struct bma150_data *bma150) ipoll_dev->poll_interval_min = BMA150_POLL_MIN; ipoll_dev->poll_interval_max = BMA150_POLL_MAX; - bma150_init_input_device(bma150, ipoll_dev->input); + bma150_init_input_device(ipoll_dev->input); bma150->input_polled = ipoll_dev; bma150->input = ipoll_dev->input; error = input_register_polled_device(ipoll_dev); - if (error) { - input_free_polled_device(ipoll_dev); + if (error) return error; - } return 0; } @@ -531,7 +525,7 @@ static int bma150_probe(struct i2c_client *client, return -EINVAL; } - bma150 = kzalloc(sizeof(struct bma150_data), GFP_KERNEL); + bma150 = devm_kzalloc(&client->dev, sizeof(*bma150), GFP_KERNEL); if (!bma150) return -ENOMEM; @@ -544,7 +538,7 @@ static int bma150_probe(struct i2c_client *client, dev_err(&client->dev, "IRQ GPIO conf. error %d, error %d\n", client->irq, error); - goto err_free_mem; + return error; } } cfg = &pdata->cfg; @@ -554,14 +548,14 @@ static int bma150_probe(struct i2c_client *client, error = bma150_initialize(bma150, cfg); if (error) - goto err_free_mem; + return error; if (client->irq > 0) { error = bma150_register_input_device(bma150); if (error) - goto err_free_mem; + return error; - error = request_threaded_irq(client->irq, + error = devm_request_threaded_irq(&client->dev, client->irq, NULL, bma150_irq_thread, IRQF_TRIGGER_RISING | IRQF_ONESHOT, BMA150_DRIVER, bma150); @@ -569,13 +563,12 @@ static int bma150_probe(struct i2c_client *client, dev_err(&client->dev, "irq request failed %d, error %d\n", client->irq, error); - input_unregister_device(bma150->input); - goto err_free_mem; + return error; } } else { error = bma150_register_polled_device(bma150); if (error) - goto err_free_mem; + return error; } i2c_set_clientdata(client, bma150); @@ -583,28 +576,12 @@ static int bma150_probe(struct i2c_client *client, pm_runtime_enable(&client->dev); return 0; - -err_free_mem: - kfree(bma150); - return error; } static int bma150_remove(struct i2c_client *client) { - struct bma150_data *bma150 = i2c_get_clientdata(client); - pm_runtime_disable(&client->dev); - if (client->irq > 0) { - free_irq(client->irq, bma150); - input_unregister_device(bma150->input); - } else { - input_unregister_polled_device(bma150->input_polled); - input_free_polled_device(bma150->input_polled); - } - - kfree(bma150); - return 0; } From b873f73cf66ffd19c6eba47ade6844ac01e9ccb0 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 29 Oct 2019 17:05:13 -0700 Subject: [PATCH 50/70] Input: bma150 - switch to using polled mode of input devices We have added polled mode to the normal input devices with the intent of retiring input_polled_dev. This converts bma150 driver to use the polling mode of standard input devices and removes dependency on INPUT_POLLDEV. Link: https://lore.kernel.org/r/20191017204217.106453-21-dmitry.torokhov@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/misc/Kconfig | 1 - drivers/input/misc/bma150.c | 155 ++++++++++-------------------------- 2 files changed, 44 insertions(+), 112 deletions(-) diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index e1309cb190e1..438ec07e3b62 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -100,7 +100,6 @@ config INPUT_ATMEL_CAPTOUCH config INPUT_BMA150 tristate "BMA150/SMB380 acceleration sensor support" depends on I2C - select INPUT_POLLDEV help Say Y here if you have Bosch Sensortec's BMA150 or SMB380 acceleration sensor hooked to an I2C bus. diff --git a/drivers/input/misc/bma150.c b/drivers/input/misc/bma150.c index d65b008a3c7a..a9d984da95f3 100644 --- a/drivers/input/misc/bma150.c +++ b/drivers/input/misc/bma150.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -123,7 +122,6 @@ struct bma150_data { struct i2c_client *client; - struct input_polled_dev *input_polled; struct input_dev *input; u8 mode; }; @@ -336,13 +334,16 @@ static irqreturn_t bma150_irq_thread(int irq, void *dev) return IRQ_HANDLED; } -static void bma150_poll(struct input_polled_dev *dev) +static void bma150_poll(struct input_dev *input) { - bma150_report_xyz(dev->private); + struct bma150_data *bma150 = input_get_drvdata(input); + + bma150_report_xyz(bma150); } -static int bma150_open(struct bma150_data *bma150) +static int bma150_open(struct input_dev *input) { + struct bma150_data *bma150 = input_get_drvdata(input); int error; error = pm_runtime_get_sync(&bma150->client->dev); @@ -362,44 +363,18 @@ static int bma150_open(struct bma150_data *bma150) return 0; } -static void bma150_close(struct bma150_data *bma150) +static void bma150_close(struct input_dev *input) { + struct bma150_data *bma150 = input_get_drvdata(input); + pm_runtime_put_sync(&bma150->client->dev); if (bma150->mode != BMA150_MODE_SLEEP) bma150_set_mode(bma150, BMA150_MODE_SLEEP); } -static int bma150_irq_open(struct input_dev *input) -{ - struct bma150_data *bma150 = input_get_drvdata(input); - - return bma150_open(bma150); -} - -static void bma150_irq_close(struct input_dev *input) -{ - struct bma150_data *bma150 = input_get_drvdata(input); - - bma150_close(bma150); -} - -static void bma150_poll_open(struct input_polled_dev *ipoll_dev) -{ - struct bma150_data *bma150 = ipoll_dev->private; - - bma150_open(bma150); -} - -static void bma150_poll_close(struct input_polled_dev *ipoll_dev) -{ - struct bma150_data *bma150 = ipoll_dev->private; - - bma150_close(bma150); -} - static int bma150_initialize(struct bma150_data *bma150, - const struct bma150_cfg *cfg) + const struct bma150_cfg *cfg) { int error; @@ -439,78 +414,14 @@ static int bma150_initialize(struct bma150_data *bma150, return bma150_set_mode(bma150, BMA150_MODE_SLEEP); } -static void bma150_init_input_device(struct input_dev *idev) -{ - idev->name = BMA150_DRIVER; - idev->phys = BMA150_DRIVER "/input0"; - idev->id.bustype = BUS_I2C; - - idev->evbit[0] = BIT_MASK(EV_ABS); - input_set_abs_params(idev, ABS_X, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0); - input_set_abs_params(idev, ABS_Y, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0); - input_set_abs_params(idev, ABS_Z, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0); -} - -static int bma150_register_input_device(struct bma150_data *bma150) -{ - struct input_dev *idev; - int error; - - idev = devm_input_allocate_device(&bma150->client->dev); - if (!idev) - return -ENOMEM; - - bma150_init_input_device(idev); - - idev->open = bma150_irq_open; - idev->close = bma150_irq_close; - input_set_drvdata(idev, bma150); - - bma150->input = idev; - - error = input_register_device(idev); - if (error) - return error; - - return 0; -} - -static int bma150_register_polled_device(struct bma150_data *bma150) -{ - struct input_polled_dev *ipoll_dev; - int error; - - ipoll_dev = devm_input_allocate_polled_device(&bma150->client->dev); - if (!ipoll_dev) - return -ENOMEM; - - ipoll_dev->private = bma150; - ipoll_dev->open = bma150_poll_open; - ipoll_dev->close = bma150_poll_close; - ipoll_dev->poll = bma150_poll; - ipoll_dev->poll_interval = BMA150_POLL_INTERVAL; - ipoll_dev->poll_interval_min = BMA150_POLL_MIN; - ipoll_dev->poll_interval_max = BMA150_POLL_MAX; - - bma150_init_input_device(ipoll_dev->input); - - bma150->input_polled = ipoll_dev; - bma150->input = ipoll_dev->input; - - error = input_register_polled_device(ipoll_dev); - if (error) - return error; - - return 0; -} - static int bma150_probe(struct i2c_client *client, - const struct i2c_device_id *id) + const struct i2c_device_id *id) { const struct bma150_platform_data *pdata = dev_get_platdata(&client->dev); const struct bma150_cfg *cfg; struct bma150_data *bma150; + struct input_dev *idev; int chip_id; int error; @@ -550,11 +461,39 @@ static int bma150_probe(struct i2c_client *client, if (error) return error; - if (client->irq > 0) { - error = bma150_register_input_device(bma150); + idev = devm_input_allocate_device(&bma150->client->dev); + if (!idev) + return -ENOMEM; + + input_set_drvdata(idev, bma150); + bma150->input = idev; + + idev->name = BMA150_DRIVER; + idev->phys = BMA150_DRIVER "/input0"; + idev->id.bustype = BUS_I2C; + + idev->open = bma150_open; + idev->close = bma150_close; + + input_set_abs_params(idev, ABS_X, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0); + input_set_abs_params(idev, ABS_Y, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0); + input_set_abs_params(idev, ABS_Z, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0); + + if (client->irq <= 0) { + error = input_setup_polling(idev, bma150_poll); if (error) return error; + input_set_poll_interval(idev, BMA150_POLL_INTERVAL); + input_set_min_poll_interval(idev, BMA150_POLL_MIN); + input_set_max_poll_interval(idev, BMA150_POLL_MAX); + } + + error = input_register_device(idev); + if (error) + return error; + + if (client->irq > 0) { error = devm_request_threaded_irq(&client->dev, client->irq, NULL, bma150_irq_thread, IRQF_TRIGGER_RISING | IRQF_ONESHOT, @@ -565,10 +504,6 @@ static int bma150_probe(struct i2c_client *client, client->irq, error); return error; } - } else { - error = bma150_register_polled_device(bma150); - if (error) - return error; } i2c_set_clientdata(client, bma150); @@ -585,8 +520,7 @@ static int bma150_remove(struct i2c_client *client) return 0; } -#ifdef CONFIG_PM -static int bma150_suspend(struct device *dev) +static int __maybe_unused bma150_suspend(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); struct bma150_data *bma150 = i2c_get_clientdata(client); @@ -594,14 +528,13 @@ static int bma150_suspend(struct device *dev) return bma150_set_mode(bma150, BMA150_MODE_SLEEP); } -static int bma150_resume(struct device *dev) +static int __maybe_unused bma150_resume(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); struct bma150_data *bma150 = i2c_get_clientdata(client); return bma150_set_mode(bma150, BMA150_MODE_NORMAL); } -#endif static UNIVERSAL_DEV_PM_OPS(bma150_pm, bma150_suspend, bma150_resume, NULL); From e73391180ae937f6947fc252a27c0e203365a9f1 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 29 Oct 2019 17:05:27 -0700 Subject: [PATCH 51/70] Input: kxtj9 - switch to using managed resources Using devm API allows to clean up error handling and drop the remove() method. Link: https://lore.kernel.org/r/20191017204217.106453-22-dmitry.torokhov@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/misc/kxtj9.c | 88 +++++++++++++------------------------- 1 file changed, 29 insertions(+), 59 deletions(-) diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c index db01c4a33914..a86544d575f8 100644 --- a/drivers/input/misc/kxtj9.c +++ b/drivers/input/misc/kxtj9.c @@ -292,7 +292,6 @@ static void kxtj9_init_input_device(struct kxtj9_data *tj9, input_dev->name = "kxtj9_accel"; input_dev->id.bustype = BUS_I2C; - input_dev->dev.parent = &tj9->client->dev; } static int kxtj9_setup_input_device(struct kxtj9_data *tj9) @@ -300,7 +299,7 @@ static int kxtj9_setup_input_device(struct kxtj9_data *tj9) struct input_dev *input_dev; int err; - input_dev = input_allocate_device(); + input_dev = devm_input_allocate_device(&tj9->client->dev); if (!input_dev) { dev_err(&tj9->client->dev, "input device allocate failed\n"); return -ENOMEM; @@ -319,7 +318,6 @@ static int kxtj9_setup_input_device(struct kxtj9_data *tj9) dev_err(&tj9->client->dev, "unable to register input polled device %s: %d\n", tj9->input_dev->name, err); - input_free_device(tj9->input_dev); return err; } @@ -424,8 +422,8 @@ static int kxtj9_setup_polled_device(struct kxtj9_data *tj9) { int err; struct input_polled_dev *poll_dev; - poll_dev = input_allocate_polled_device(); + poll_dev = devm_input_allocate_polled_device(&tj9->client->dev); if (!poll_dev) { dev_err(&tj9->client->dev, "Failed to allocate polled device\n"); @@ -446,19 +444,12 @@ static int kxtj9_setup_polled_device(struct kxtj9_data *tj9) if (err) { dev_err(&tj9->client->dev, "Unable to register polled device, err=%d\n", err); - input_free_polled_device(poll_dev); return err; } return 0; } -static void kxtj9_teardown_polled_device(struct kxtj9_data *tj9) -{ - input_unregister_polled_device(tj9->poll_dev); - input_free_polled_device(tj9->poll_dev); -} - #else static inline int kxtj9_setup_polled_device(struct kxtj9_data *tj9) @@ -466,12 +457,16 @@ static inline int kxtj9_setup_polled_device(struct kxtj9_data *tj9) return -ENOSYS; } -static inline void kxtj9_teardown_polled_device(struct kxtj9_data *tj9) -{ -} - #endif +static void kxtj9_platform_exit(void *data) +{ + struct kxtj9_data *tj9 = data; + + if (tj9->pdata.exit) + tj9->pdata.exit(); +} + static int kxtj9_verify(struct kxtj9_data *tj9) { int retval; @@ -494,7 +489,7 @@ out: } static int kxtj9_probe(struct i2c_client *client, - const struct i2c_device_id *id) + const struct i2c_device_id *id) { const struct kxtj9_platform_data *pdata = dev_get_platdata(&client->dev); @@ -512,7 +507,7 @@ static int kxtj9_probe(struct i2c_client *client, return -EINVAL; } - tj9 = kzalloc(sizeof(*tj9), GFP_KERNEL); + tj9 = devm_kzalloc(&client->dev, sizeof(*tj9), GFP_KERNEL); if (!tj9) { dev_err(&client->dev, "failed to allocate memory for module data\n"); @@ -525,13 +520,17 @@ static int kxtj9_probe(struct i2c_client *client, if (pdata->init) { err = pdata->init(); if (err < 0) - goto err_free_mem; + return err; } + err = devm_add_action_or_reset(&client->dev, kxtj9_platform_exit, tj9); + if (err) + return err; + err = kxtj9_verify(tj9); if (err < 0) { dev_err(&client->dev, "device not recognized\n"); - goto err_pdata_exit; + return err; } i2c_set_clientdata(client, tj9); @@ -546,59 +545,31 @@ static int kxtj9_probe(struct i2c_client *client, err = kxtj9_setup_input_device(tj9); if (err) - goto err_pdata_exit; + return err; - err = request_threaded_irq(client->irq, NULL, kxtj9_isr, - IRQF_TRIGGER_RISING | IRQF_ONESHOT, - "kxtj9-irq", tj9); + err = devm_request_threaded_irq(&client->dev, client->irq, + NULL, kxtj9_isr, + IRQF_TRIGGER_RISING | + IRQF_ONESHOT, + "kxtj9-irq", tj9); if (err) { dev_err(&client->dev, "request irq failed: %d\n", err); - goto err_destroy_input; + return err; } - err = sysfs_create_group(&client->dev.kobj, &kxtj9_attribute_group); + err = devm_device_add_group(&client->dev, + &kxtj9_attribute_group); if (err) { dev_err(&client->dev, "sysfs create failed: %d\n", err); - goto err_free_irq; + return err; } } else { err = kxtj9_setup_polled_device(tj9); if (err) - goto err_pdata_exit; + return err; } - return 0; - -err_free_irq: - free_irq(client->irq, tj9); -err_destroy_input: - input_unregister_device(tj9->input_dev); -err_pdata_exit: - if (tj9->pdata.exit) - tj9->pdata.exit(); -err_free_mem: - kfree(tj9); - return err; -} - -static int kxtj9_remove(struct i2c_client *client) -{ - struct kxtj9_data *tj9 = i2c_get_clientdata(client); - - if (client->irq) { - sysfs_remove_group(&client->dev.kobj, &kxtj9_attribute_group); - free_irq(client->irq, tj9); - input_unregister_device(tj9->input_dev); - } else { - kxtj9_teardown_polled_device(tj9); - } - - if (tj9->pdata.exit) - tj9->pdata.exit(); - - kfree(tj9); - return 0; } @@ -647,7 +618,6 @@ static struct i2c_driver kxtj9_driver = { .pm = &kxtj9_pm_ops, }, .probe = kxtj9_probe, - .remove = kxtj9_remove, .id_table = kxtj9_id, }; From 78713dfade756210a88630d0c3eb7ed04774d499 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 29 Oct 2019 17:05:34 -0700 Subject: [PATCH 52/70] Input: kxtj9 - switch to using polled mode of input devices We have added polled mode to the normal input devices with the intent of retiring input_polled_dev. This converts kxtj9 driver to use the polling mode of standard input devices and removes dependency on INPUT_POLLDEV. note that with regular input devices handling polling, there is no longer a benefit in having separate INPUT_KXTJ9_POLLED_MODE config option. Link: https://lore.kernel.org/r/20191017204217.106453-23-dmitry.torokhov@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/misc/Kconfig | 7 -- drivers/input/misc/kxtj9.c | 152 +++++++++---------------------------- 2 files changed, 37 insertions(+), 122 deletions(-) diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 438ec07e3b62..7e2e658d551c 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -404,13 +404,6 @@ config INPUT_KXTJ9 To compile this driver as a module, choose M here: the module will be called kxtj9. -config INPUT_KXTJ9_POLLED_MODE - bool "Enable polling mode support" - depends on INPUT_KXTJ9 - select INPUT_POLLDEV - help - Say Y here if you need accelerometer to work in polling mode. - config INPUT_POWERMATE tristate "Griffin PowerMate and Contour Jog support" depends on USB_ARCH_HAS_HCD diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c index a86544d575f8..52313c6e3fb3 100644 --- a/drivers/input/misc/kxtj9.c +++ b/drivers/input/misc/kxtj9.c @@ -11,7 +11,6 @@ #include #include #include -#include #define NAME "kxtj9" #define G_MAX 8000 @@ -71,9 +70,6 @@ struct kxtj9_data { struct i2c_client *client; struct kxtj9_platform_data pdata; struct input_dev *input_dev; -#ifdef CONFIG_INPUT_KXTJ9_POLLED_MODE - struct input_polled_dev *poll_dev; -#endif unsigned int last_poll_interval; u8 shift; u8 ctrl_reg1; @@ -282,48 +278,6 @@ static void kxtj9_input_close(struct input_dev *dev) kxtj9_disable(tj9); } -static void kxtj9_init_input_device(struct kxtj9_data *tj9, - struct input_dev *input_dev) -{ - __set_bit(EV_ABS, input_dev->evbit); - input_set_abs_params(input_dev, ABS_X, -G_MAX, G_MAX, FUZZ, FLAT); - input_set_abs_params(input_dev, ABS_Y, -G_MAX, G_MAX, FUZZ, FLAT); - input_set_abs_params(input_dev, ABS_Z, -G_MAX, G_MAX, FUZZ, FLAT); - - input_dev->name = "kxtj9_accel"; - input_dev->id.bustype = BUS_I2C; -} - -static int kxtj9_setup_input_device(struct kxtj9_data *tj9) -{ - struct input_dev *input_dev; - int err; - - input_dev = devm_input_allocate_device(&tj9->client->dev); - if (!input_dev) { - dev_err(&tj9->client->dev, "input device allocate failed\n"); - return -ENOMEM; - } - - tj9->input_dev = input_dev; - - input_dev->open = kxtj9_input_open; - input_dev->close = kxtj9_input_close; - input_set_drvdata(input_dev, tj9); - - kxtj9_init_input_device(tj9, input_dev); - - err = input_register_device(tj9->input_dev); - if (err) { - dev_err(&tj9->client->dev, - "unable to register input polled device %s: %d\n", - tj9->input_dev->name, err); - return err; - } - - return 0; -} - /* * When IRQ mode is selected, we need to provide an interface to allow the user * to change the output data rate of the part. For consistency, we are using @@ -389,12 +343,10 @@ static struct attribute_group kxtj9_attribute_group = { .attrs = kxtj9_attributes }; - -#ifdef CONFIG_INPUT_KXTJ9_POLLED_MODE -static void kxtj9_poll(struct input_polled_dev *dev) +static void kxtj9_poll(struct input_dev *input) { - struct kxtj9_data *tj9 = dev->private; - unsigned int poll_interval = dev->poll_interval; + struct kxtj9_data *tj9 = input_get_drvdata(input); + unsigned int poll_interval = input_get_poll_interval(input); kxtj9_report_acceleration_data(tj9); @@ -404,61 +356,6 @@ static void kxtj9_poll(struct input_polled_dev *dev) } } -static void kxtj9_polled_input_open(struct input_polled_dev *dev) -{ - struct kxtj9_data *tj9 = dev->private; - - kxtj9_enable(tj9); -} - -static void kxtj9_polled_input_close(struct input_polled_dev *dev) -{ - struct kxtj9_data *tj9 = dev->private; - - kxtj9_disable(tj9); -} - -static int kxtj9_setup_polled_device(struct kxtj9_data *tj9) -{ - int err; - struct input_polled_dev *poll_dev; - - poll_dev = devm_input_allocate_polled_device(&tj9->client->dev); - if (!poll_dev) { - dev_err(&tj9->client->dev, - "Failed to allocate polled device\n"); - return -ENOMEM; - } - - tj9->poll_dev = poll_dev; - tj9->input_dev = poll_dev->input; - - poll_dev->private = tj9; - poll_dev->poll = kxtj9_poll; - poll_dev->open = kxtj9_polled_input_open; - poll_dev->close = kxtj9_polled_input_close; - - kxtj9_init_input_device(tj9, poll_dev->input); - - err = input_register_polled_device(poll_dev); - if (err) { - dev_err(&tj9->client->dev, - "Unable to register polled device, err=%d\n", err); - return err; - } - - return 0; -} - -#else - -static inline int kxtj9_setup_polled_device(struct kxtj9_data *tj9) -{ - return -ENOSYS; -} - -#endif - static void kxtj9_platform_exit(void *data) { struct kxtj9_data *tj9 = data; @@ -494,6 +391,7 @@ static int kxtj9_probe(struct i2c_client *client, const struct kxtj9_platform_data *pdata = dev_get_platdata(&client->dev); struct kxtj9_data *tj9; + struct input_dev *input_dev; int err; if (!i2c_check_functionality(client->adapter, @@ -538,15 +436,44 @@ static int kxtj9_probe(struct i2c_client *client, tj9->ctrl_reg1 = tj9->pdata.res_12bit | tj9->pdata.g_range; tj9->last_poll_interval = tj9->pdata.init_interval; + input_dev = devm_input_allocate_device(&client->dev); + if (!input_dev) { + dev_err(&client->dev, "input device allocate failed\n"); + return -ENOMEM; + } + + input_set_drvdata(input_dev, tj9); + tj9->input_dev = input_dev; + + input_dev->name = "kxtj9_accel"; + input_dev->id.bustype = BUS_I2C; + + input_dev->open = kxtj9_input_open; + input_dev->close = kxtj9_input_close; + + input_set_abs_params(input_dev, ABS_X, -G_MAX, G_MAX, FUZZ, FLAT); + input_set_abs_params(input_dev, ABS_Y, -G_MAX, G_MAX, FUZZ, FLAT); + input_set_abs_params(input_dev, ABS_Z, -G_MAX, G_MAX, FUZZ, FLAT); + + if (client->irq <= 0) { + err = input_setup_polling(input_dev, kxtj9_poll); + if (err) + return err; + } + + err = input_register_device(input_dev); + if (err) { + dev_err(&client->dev, + "unable to register input polled device %s: %d\n", + input_dev->name, err); + return err; + } + if (client->irq) { /* If in irq mode, populate INT_CTRL_REG1 and enable DRDY. */ tj9->int_ctrl |= KXTJ9_IEN | KXTJ9_IEA | KXTJ9_IEL; tj9->ctrl_reg1 |= DRDYE; - err = kxtj9_setup_input_device(tj9); - if (err) - return err; - err = devm_request_threaded_irq(&client->dev, client->irq, NULL, kxtj9_isr, IRQF_TRIGGER_RISING | @@ -563,11 +490,6 @@ static int kxtj9_probe(struct i2c_client *client, dev_err(&client->dev, "sysfs create failed: %d\n", err); return err; } - - } else { - err = kxtj9_setup_polled_device(tj9); - if (err) - return err; } return 0; From d843304b22e84b41dd00663a13cb960d2f4d064d Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Mon, 4 Nov 2019 15:59:38 -0800 Subject: [PATCH 53/70] Input: synaptics-rmi4 - simplify data read in rmi_f54_work The body of the for loop is only ever run once as the second standard_report element is never changed from its initial zero init, so the loop condition is never satisfies after the first run. Equally the start member of the first element is never changed from 0, so the index offset is always a constant 0. Remove this needless obfuscation of the code and write it in a straight forward manner. Signed-off-by: Lucas Stach Link: https://lore.kernel.org/r/20191104114454.10500-3-l.stach@pengutronix.de Signed-off-by: Dmitry Torokhov --- drivers/input/rmi4/rmi_f54.c | 48 ++++++++++++------------------------ 1 file changed, 16 insertions(+), 32 deletions(-) diff --git a/drivers/input/rmi4/rmi_f54.c b/drivers/input/rmi4/rmi_f54.c index 710b02595486..514f5568b74d 100644 --- a/drivers/input/rmi4/rmi_f54.c +++ b/drivers/input/rmi4/rmi_f54.c @@ -81,11 +81,6 @@ static const char * const rmi_f54_report_type_names[] = { = "Full Raw Capacitance RX Offset Removed", }; -struct rmi_f54_reports { - int start; - int size; -}; - struct f54_data { struct rmi_function *fn; @@ -98,7 +93,6 @@ struct f54_data { enum rmi_f54_report_type report_type; u8 *report_data; int report_size; - struct rmi_f54_reports standard_report[2]; bool is_busy; struct mutex status_mutex; @@ -516,13 +510,10 @@ static void rmi_f54_work(struct work_struct *work) struct f54_data *f54 = container_of(work, struct f54_data, work.work); struct rmi_function *fn = f54->fn; u8 fifo[2]; - struct rmi_f54_reports *report; int report_size; u8 command; - u8 *data; int error; - data = f54->report_data; report_size = rmi_f54_get_report_size(f54); if (report_size == 0) { dev_err(&fn->dev, "Bad report size, report type=%d\n", @@ -530,8 +521,6 @@ static void rmi_f54_work(struct work_struct *work) error = -EINVAL; goto error; /* retry won't help */ } - f54->standard_report[0].size = report_size; - report = f54->standard_report; mutex_lock(&f54->data_mutex); @@ -556,28 +545,23 @@ static void rmi_f54_work(struct work_struct *work) rmi_dbg(RMI_DEBUG_FN, &fn->dev, "Get report command completed, reading data\n"); - report_size = 0; - for (; report->size; report++) { - fifo[0] = report->start & 0xff; - fifo[1] = (report->start >> 8) & 0xff; - error = rmi_write_block(fn->rmi_dev, - fn->fd.data_base_addr + F54_FIFO_OFFSET, - fifo, sizeof(fifo)); - if (error) { - dev_err(&fn->dev, "Failed to set fifo start offset\n"); - goto abort; - } + fifo[0] = 0; + fifo[1] = 0; + error = rmi_write_block(fn->rmi_dev, + fn->fd.data_base_addr + F54_FIFO_OFFSET, + fifo, sizeof(fifo)); + if (error) { + dev_err(&fn->dev, "Failed to set fifo start offset\n"); + goto abort; + } - error = rmi_read_block(fn->rmi_dev, fn->fd.data_base_addr + - F54_REPORT_DATA_OFFSET, data, - report->size); - if (error) { - dev_err(&fn->dev, "%s: read [%d bytes] returned %d\n", - __func__, report->size, error); - goto abort; - } - data += report->size; - report_size += report->size; + error = rmi_read_block(fn->rmi_dev, fn->fd.data_base_addr + + F54_REPORT_DATA_OFFSET, f54->report_data, + report_size); + if (error) { + dev_err(&fn->dev, "%s: read [%d bytes] returned %d\n", + __func__, report_size, error); + goto abort; } abort: From ee85fbe14fd62a30df76f0a8dcee590d9c759703 Mon Sep 17 00:00:00 2001 From: Flavio Suligoi Date: Mon, 11 Nov 2019 10:20:03 -0800 Subject: [PATCH 54/70] Input: ar1021 - fix typo in preprocessor macro name Fix spelling mistake. Signed-off-by: Flavio Suligoi Link: https://lore.kernel.org/r/1573211947-660-1-git-send-email-f.suligoi@asem.it Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/ar1021_i2c.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/input/touchscreen/ar1021_i2c.c b/drivers/input/touchscreen/ar1021_i2c.c index 28644f372bd8..c0d5c2413356 100644 --- a/drivers/input/touchscreen/ar1021_i2c.c +++ b/drivers/input/touchscreen/ar1021_i2c.c @@ -13,7 +13,7 @@ #include #include -#define AR1021_TOCUH_PKG_SIZE 5 +#define AR1021_TOUCH_PKG_SIZE 5 #define AR1021_MAX_X 4095 #define AR1021_MAX_Y 4095 @@ -25,7 +25,7 @@ struct ar1021_i2c { struct i2c_client *client; struct input_dev *input; - u8 data[AR1021_TOCUH_PKG_SIZE]; + u8 data[AR1021_TOUCH_PKG_SIZE]; }; static irqreturn_t ar1021_i2c_irq(int irq, void *dev_id) From 92d6d0a19246921264147a5edf6a72dea8dc4b40 Mon Sep 17 00:00:00 2001 From: Marcel Ziswiler Date: Wed, 30 Oct 2019 16:10:39 -0700 Subject: [PATCH 55/70] dt-bindings: input: touchscreen: ad7879: generic node names in example Update example in ad7879 device tree documentation to use generic touch controller node names. Signed-off-by: Marcel Ziswiler Acked-by: Rob Herring Link: https://lore.kernel.org/r/20191026090403.3057-3-marcel@ziswiler.com Signed-off-by: Dmitry Torokhov --- .../devicetree/bindings/input/touchscreen/ad7879.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/input/touchscreen/ad7879.txt b/Documentation/devicetree/bindings/input/touchscreen/ad7879.txt index cdd743a1f2d5..afa38dc069f0 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/ad7879.txt +++ b/Documentation/devicetree/bindings/input/touchscreen/ad7879.txt @@ -38,7 +38,7 @@ Optional properties: Example: - ad7879@2c { + touchscreen0@2c { compatible = "adi,ad7879-1"; reg = <0x2c>; interrupt-parent = <&gpio1>; @@ -52,7 +52,7 @@ Example: adi,conversion-interval = /bits/ 8 <255>; }; - ad7879@1 { + touchscreen1@1 { compatible = "adi,ad7879"; spi-max-frequency = <5000000>; reg = <1>; From eb91ecc9fc43fbefdfdfe1ea8b3f136ccbc02f66 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 11 Aug 2019 09:16:37 -0700 Subject: [PATCH 56/70] Input: ili210x - add ILI2117 support Add support for ILI2117 touch controller. This controller is similar to the ILI210x and ILI251x, except for the following differences: - Reading out of touch data must happen at most 300 mS after the interrupt line was asserted. No command must be sent, the data are returned upon pure I2C read of 43 bytes long. - Supports 10 simultaneous touch inputs. - Touch data format is slightly different. Signed-off-by: Marek Vasut Reviewed-by: Rob Herring # for DT binding Tested-by: Adam Ford #imx6q-logicpd Tested-by: Sven Van Asbroeck # ILI2118A variant Signed-off-by: Dmitry Torokhov --- .../bindings/input/ilitek,ili2xxx.txt | 3 +- drivers/input/touchscreen/ili210x.c | 46 ++++++++++++++++++- 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/input/ilitek,ili2xxx.txt b/Documentation/devicetree/bindings/input/ilitek,ili2xxx.txt index b2a76301e632..dc194b2c151a 100644 --- a/Documentation/devicetree/bindings/input/ilitek,ili2xxx.txt +++ b/Documentation/devicetree/bindings/input/ilitek,ili2xxx.txt @@ -1,8 +1,9 @@ -Ilitek ILI210x/ILI251x touchscreen controller +Ilitek ILI210x/ILI2117/ILI251x touchscreen controller Required properties: - compatible: ilitek,ili210x for ILI210x + ilitek,ili2117 for ILI2117 ilitek,ili251x for ILI251x - reg: The I2C address of the device diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c index e9006407c9bc..36491d8ff990 100644 --- a/drivers/input/touchscreen/ili210x.c +++ b/drivers/input/touchscreen/ili210x.c @@ -13,6 +13,7 @@ #include #define ILI210X_TOUCHES 2 +#define ILI211X_TOUCHES 10 #define ILI251X_TOUCHES 10 #define DEFAULT_POLL_PERIOD 20 @@ -30,6 +31,7 @@ struct firmware_version { enum ili2xxx_model { MODEL_ILI210X, + MODEL_ILI211X, MODEL_ILI251X, }; @@ -118,6 +120,27 @@ static bool ili210x_touchdata_to_coords(struct ili210x *priv, u8 *touchdata, return true; } +static bool ili211x_touchdata_to_coords(struct ili210x *priv, u8 *touchdata, + unsigned int finger, + unsigned int *x, unsigned int *y) +{ + u32 data; + + if (finger >= ILI211X_TOUCHES) + return false; + + data = get_unaligned_be32(touchdata + 1 + (finger * 4) + 0); + if (data == 0xffffffff) /* Finger up */ + return false; + + *x = ((touchdata[1 + (finger * 4) + 0] & 0xf0) << 4) | + touchdata[1 + (finger * 4) + 1]; + *y = ((touchdata[1 + (finger * 4) + 0] & 0x0f) << 8) | + touchdata[1 + (finger * 4) + 2]; + + return true; +} + static bool ili251x_touchdata_to_coords(struct ili210x *priv, u8 *touchdata, unsigned int finger, unsigned int *x, unsigned int *y) @@ -146,6 +169,9 @@ static bool ili210x_report_events(struct ili210x *priv, u8 *touchdata) if (priv->model == MODEL_ILI210X) { touch = ili210x_touchdata_to_coords(priv, touchdata, i, &x, &y); + } else if (priv->model == MODEL_ILI211X) { + touch = ili211x_touchdata_to_coords(priv, touchdata, + i, &x, &y); } else if (priv->model == MODEL_ILI251X) { touch = ili251x_touchdata_to_coords(priv, touchdata, i, &x, &y); @@ -176,12 +202,26 @@ static void ili210x_work(struct work_struct *work) dwork.work); struct i2c_client *client = priv->client; u8 touchdata[64] = { 0 }; + s16 sum = 0; bool touch; - int error = -EINVAL; + int i, error = -EINVAL; if (priv->model == MODEL_ILI210X) { error = ili210x_read_reg(client, REG_TOUCHDATA, touchdata, sizeof(touchdata)); + } else if (priv->model == MODEL_ILI211X) { + error = ili210x_read(client, touchdata, 43); + if (!error) { + /* This chip uses custom checksum at the end of data */ + for (i = 0; i <= 41; i++) + sum = (sum + touchdata[i]) & 0xff; + if ((-sum & 0xff) != touchdata[42]) { + dev_err(&client->dev, + "CRC error (crc=0x%02x expected=0x%02x)\n", + sum, touchdata[42]); + return; + } + } } else if (priv->model == MODEL_ILI251X) { error = ili210x_read_reg(client, REG_TOUCHDATA, touchdata, 31); @@ -311,6 +351,8 @@ static int ili210x_i2c_probe(struct i2c_client *client, priv->model = model; if (model == MODEL_ILI210X) priv->max_touches = ILI210X_TOUCHES; + if (model == MODEL_ILI211X) + priv->max_touches = ILI211X_TOUCHES; if (model == MODEL_ILI251X) priv->max_touches = ILI251X_TOUCHES; @@ -395,6 +437,7 @@ static SIMPLE_DEV_PM_OPS(ili210x_i2c_pm, static const struct i2c_device_id ili210x_i2c_id[] = { { "ili210x", MODEL_ILI210X }, + { "ili2117", MODEL_ILI211X }, { "ili251x", MODEL_ILI251X }, { } }; @@ -402,6 +445,7 @@ MODULE_DEVICE_TABLE(i2c, ili210x_i2c_id); static const struct of_device_id ili210x_dt_ids[] = { { .compatible = "ilitek,ili210x", .data = (void *)MODEL_ILI210X }, + { .compatible = "ilitek,ili2117", .data = (void *)MODEL_ILI211X }, { .compatible = "ilitek,ili251x", .data = (void *)MODEL_ILI251X }, { }, }; From 71f8e38ae635d92e553eec8d7359cb88b539b306 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sat, 10 Aug 2019 23:19:24 -0700 Subject: [PATCH 57/70] Input: ili210x - switch to using threaded IRQ Let's switch the driver to using threaded IRQ so that we do not need to manage the interrupt and work separately, and we do not acknowledge interrupt until we finished handling it completely. Tested-by: Adam Ford #imx6q-logicpd Tested-by: Sven Van Asbroeck # ILI2118A variant Tested-by: Marek Vasut # ILI2117 Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/ili210x.c | 115 +++++++++++++--------------- 1 file changed, 55 insertions(+), 60 deletions(-) diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c index 36491d8ff990..6985ca8b6565 100644 --- a/drivers/input/touchscreen/ili210x.c +++ b/drivers/input/touchscreen/ili210x.c @@ -1,21 +1,21 @@ // SPDX-License-Identifier: GPL-2.0-only -#include +#include +#include #include -#include -#include #include #include #include -#include -#include -#include +#include +#include #include +#include #include #define ILI210X_TOUCHES 2 #define ILI211X_TOUCHES 10 #define ILI251X_TOUCHES 10 -#define DEFAULT_POLL_PERIOD 20 + +#define ILI2XXX_POLL_PERIOD 20 /* Touchscreen commands */ #define REG_TOUCHDATA 0x10 @@ -38,12 +38,11 @@ enum ili2xxx_model { struct ili210x { struct i2c_client *client; struct input_dev *input; - unsigned int poll_period; - struct delayed_work dwork; struct gpio_desc *reset_gpio; struct touchscreen_properties prop; enum ili2xxx_model model; unsigned int max_touches; + bool stop; }; static int ili210x_read_reg(struct i2c_client *client, u8 reg, void *buf, @@ -196,57 +195,54 @@ static bool ili210x_report_events(struct ili210x *priv, u8 *touchdata) return contact; } -static void ili210x_work(struct work_struct *work) +static irqreturn_t ili210x_irq(int irq, void *irq_data) { - struct ili210x *priv = container_of(work, struct ili210x, - dwork.work); + struct ili210x *priv = irq_data; struct i2c_client *client = priv->client; u8 touchdata[64] = { 0 }; s16 sum = 0; bool touch; - int i, error = -EINVAL; + int i; + int error; - if (priv->model == MODEL_ILI210X) { - error = ili210x_read_reg(client, REG_TOUCHDATA, - touchdata, sizeof(touchdata)); - } else if (priv->model == MODEL_ILI211X) { - error = ili210x_read(client, touchdata, 43); - if (!error) { - /* This chip uses custom checksum at the end of data */ - for (i = 0; i <= 41; i++) - sum = (sum + touchdata[i]) & 0xff; - if ((-sum & 0xff) != touchdata[42]) { - dev_err(&client->dev, - "CRC error (crc=0x%02x expected=0x%02x)\n", - sum, touchdata[42]); - return; + do { + if (priv->model == MODEL_ILI210X) { + error = ili210x_read_reg(client, REG_TOUCHDATA, + touchdata, sizeof(touchdata)); + } else if (priv->model == MODEL_ILI211X) { + error = ili210x_read(client, touchdata, 43); + if (!error) { + /* + * This chip uses custom checksum at the end + * of data. + */ + for (i = 0; i <= 41; i++) + sum = (sum + touchdata[i]) & 0xff; + if ((-sum & 0xff) != touchdata[42]) { + dev_err(&client->dev, + "CRC error (crc=0x%02x expected=0x%02x)\n", + sum, touchdata[42]); + break; + } } + } else if (priv->model == MODEL_ILI251X) { + error = ili210x_read_reg(client, REG_TOUCHDATA, + touchdata, 31); + if (!error && touchdata[0] == 2) + error = ili210x_read(client, + &touchdata[31], 20); } - } else if (priv->model == MODEL_ILI251X) { - error = ili210x_read_reg(client, REG_TOUCHDATA, - touchdata, 31); - if (!error && touchdata[0] == 2) - error = ili210x_read(client, &touchdata[31], 20); - } - if (error) { - dev_err(&client->dev, - "Unable to get touchdata, err = %d\n", error); - return; - } + if (error) { + dev_err(&client->dev, + "Unable to get touchdata, err = %d\n", error); + break; + } - touch = ili210x_report_events(priv, touchdata); - - if (touch) - schedule_delayed_work(&priv->dwork, - msecs_to_jiffies(priv->poll_period)); -} - -static irqreturn_t ili210x_irq(int irq, void *irq_data) -{ - struct ili210x *priv = irq_data; - - schedule_delayed_work(&priv->dwork, 0); + touch = ili210x_report_events(priv, touchdata); + if (touch) + msleep(ILI2XXX_POLL_PERIOD); + } while (!priv->stop && touch); return IRQ_HANDLED; } @@ -293,11 +289,12 @@ static void ili210x_power_down(void *data) gpiod_set_value_cansleep(reset_gpio, 1); } -static void ili210x_cancel_work(void *data) +static void ili210x_stop(void *data) { struct ili210x *priv = data; - cancel_delayed_work_sync(&priv->dwork); + /* Tell ISR to quit even if there is a contact. */ + priv->stop = true; } static int ili210x_i2c_probe(struct i2c_client *client, @@ -345,8 +342,6 @@ static int ili210x_i2c_probe(struct i2c_client *client, priv->client = client; priv->input = input; - priv->poll_period = DEFAULT_POLL_PERIOD; - INIT_DELAYED_WORK(&priv->dwork, ili210x_work); priv->reset_gpio = reset_gpio; priv->model = model; if (model == MODEL_ILI210X) @@ -378,18 +373,18 @@ static int ili210x_i2c_probe(struct i2c_client *client, touchscreen_parse_properties(input, true, &priv->prop); input_mt_init_slots(input, priv->max_touches, INPUT_MT_DIRECT); - error = devm_add_action(dev, ili210x_cancel_work, priv); - if (error) - return error; - - error = devm_request_irq(dev, client->irq, ili210x_irq, 0, - client->name, priv); + error = devm_request_threaded_irq(dev, client->irq, NULL, ili210x_irq, + IRQF_ONESHOT, client->name, priv); if (error) { dev_err(dev, "Unable to request touchscreen IRQ, err: %d\n", error); return error; } + error = devm_add_action_or_reset(dev, ili210x_stop, priv); + if (error) + return error; + error = devm_device_add_group(dev, &ili210x_attr_group); if (error) { dev_err(dev, "Unable to create sysfs attributes, err: %d\n", From 43f06a4c639de8ee89fc348a9a3ecd70320a04dd Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 4 Nov 2019 10:39:41 -0800 Subject: [PATCH 58/70] Input: ili210x - handle errors from input_mt_init_slots() input_mt_init_slots() may fail and we need to handle such failures. Tested-by: Adam Ford #imx6q-logicpd Tested-by: Sven Van Asbroeck # ILI2118A variant Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/ili210x.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c index 6985ca8b6565..7dee37901b7b 100644 --- a/drivers/input/touchscreen/ili210x.c +++ b/drivers/input/touchscreen/ili210x.c @@ -371,7 +371,12 @@ static int ili210x_i2c_probe(struct i2c_client *client, input_set_abs_params(input, ABS_MT_POSITION_X, 0, 0xffff, 0, 0); input_set_abs_params(input, ABS_MT_POSITION_Y, 0, 0xffff, 0, 0); touchscreen_parse_properties(input, true, &priv->prop); - input_mt_init_slots(input, priv->max_touches, INPUT_MT_DIRECT); + + error = input_mt_init_slots(input, priv->max_touches, INPUT_MT_DIRECT); + if (error) { + dev_err(dev, "Unable to set up slots, err: %d\n", error); + return error; + } error = devm_request_threaded_irq(dev, client->irq, NULL, ili210x_irq, IRQF_ONESHOT, client->name, priv); From efda86a49553bc7e44b3f7254208577bff2da932 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 4 Nov 2019 15:20:47 -0800 Subject: [PATCH 59/70] Input: ili210x - do not set parent device explicitly We are using devm_input_allocate_device() that set's up the parent for us, no need to do it ourselves. Tested-by: Adam Ford #imx6q-logicpd Tested-by: Sven Van Asbroeck # ILI2118A variant Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/ili210x.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c index 7dee37901b7b..28e2dd748c5a 100644 --- a/drivers/input/touchscreen/ili210x.c +++ b/drivers/input/touchscreen/ili210x.c @@ -365,7 +365,6 @@ static int ili210x_i2c_probe(struct i2c_client *client, /* Setup input device */ input->name = "ILI210x Touchscreen"; input->id.bustype = BUS_I2C; - input->dev.parent = dev; /* Multi touch */ input_set_abs_params(input, ABS_MT_POSITION_X, 0, 0xffff, 0, 0); From ef536abd3afd1e3cbddf04c724db793f12ab9c44 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 6 Feb 2019 22:33:05 -0800 Subject: [PATCH 60/70] Input: ili210x - define and use chip operations structure Instead of doing if/else if/else on the chip's model number let's define chip operations structure and use it to perform indirect calls. With number of protocols supported by the driver growing, this makes it better maintainable. This change includes fixes to checks whether the driver should continue polling the controller by Sven Van Asbroeck . Tested-by: Adam Ford #imx6q-logicpd Tested-by: Sven Van Asbroeck # ILI2118A variant Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/ili210x.c | 311 ++++++++++++++++------------ 1 file changed, 174 insertions(+), 137 deletions(-) diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c index 28e2dd748c5a..22811df82044 100644 --- a/drivers/input/touchscreen/ili210x.c +++ b/drivers/input/touchscreen/ili210x.c @@ -11,12 +11,13 @@ #include #include -#define ILI210X_TOUCHES 2 -#define ILI211X_TOUCHES 10 -#define ILI251X_TOUCHES 10 - #define ILI2XXX_POLL_PERIOD 20 +#define ILI210X_DATA_SIZE 64 +#define ILI211X_DATA_SIZE 43 +#define ILI251X_DATA_SIZE1 31 +#define ILI251X_DATA_SIZE2 20 + /* Touchscreen commands */ #define REG_TOUCHDATA 0x10 #define REG_PANEL_INFO 0x20 @@ -29,10 +30,14 @@ struct firmware_version { u8 minor; } __packed; -enum ili2xxx_model { - MODEL_ILI210X, - MODEL_ILI211X, - MODEL_ILI251X, +struct ili2xxx_chip { + int (*read_reg)(struct i2c_client *client, u8 reg, + void *buf, size_t len); + int (*get_touch_data)(struct i2c_client *client, u8 *data); + bool (*parse_touch_data)(const u8 *data, unsigned int finger, + unsigned int *x, unsigned int *y); + bool (*continue_polling)(const u8 *data, bool touch); + unsigned int max_touches; }; struct ili210x { @@ -40,16 +45,14 @@ struct ili210x { struct input_dev *input; struct gpio_desc *reset_gpio; struct touchscreen_properties prop; - enum ili2xxx_model model; - unsigned int max_touches; + const struct ili2xxx_chip *chip; bool stop; }; -static int ili210x_read_reg(struct i2c_client *client, u8 reg, void *buf, - size_t len) +static int ili210x_read_reg(struct i2c_client *client, + u8 reg, void *buf, size_t len) { - struct ili210x *priv = i2c_get_clientdata(client); - struct i2c_msg msg[2] = { + struct i2c_msg msg[] = { { .addr = client->addr, .flags = 0, @@ -63,53 +66,28 @@ static int ili210x_read_reg(struct i2c_client *client, u8 reg, void *buf, .buf = buf, } }; + int error, ret; - if (priv->model == MODEL_ILI251X) { - if (i2c_transfer(client->adapter, msg, 1) != 1) { - dev_err(&client->dev, "i2c transfer failed\n"); - return -EIO; - } - - usleep_range(5000, 5500); - - if (i2c_transfer(client->adapter, msg + 1, 1) != 1) { - dev_err(&client->dev, "i2c transfer failed\n"); - return -EIO; - } - } else { - if (i2c_transfer(client->adapter, msg, 2) != 2) { - dev_err(&client->dev, "i2c transfer failed\n"); - return -EIO; - } + ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)); + if (ret != ARRAY_SIZE(msg)) { + error = ret < 0 ? ret : -EIO; + dev_err(&client->dev, "%s failed: %d\n", __func__, error); + return error; } return 0; } -static int ili210x_read(struct i2c_client *client, void *buf, size_t len) +static int ili210x_read_touch_data(struct i2c_client *client, u8 *data) { - struct i2c_msg msg = { - .addr = client->addr, - .flags = I2C_M_RD, - .len = len, - .buf = buf, - }; - - if (i2c_transfer(client->adapter, &msg, 1) != 1) { - dev_err(&client->dev, "i2c transfer failed\n"); - return -EIO; - } - - return 0; + return ili210x_read_reg(client, REG_TOUCHDATA, + data, ILI210X_DATA_SIZE); } -static bool ili210x_touchdata_to_coords(struct ili210x *priv, u8 *touchdata, +static bool ili210x_touchdata_to_coords(const u8 *touchdata, unsigned int finger, unsigned int *x, unsigned int *y) { - if (finger >= ILI210X_TOUCHES) - return false; - if (touchdata[0] & BIT(finger)) return false; @@ -119,15 +97,53 @@ static bool ili210x_touchdata_to_coords(struct ili210x *priv, u8 *touchdata, return true; } -static bool ili211x_touchdata_to_coords(struct ili210x *priv, u8 *touchdata, +static bool ili210x_check_continue_polling(const u8 *data, bool touch) +{ + return data[0] & 0xf3; +} + +static const struct ili2xxx_chip ili210x_chip = { + .read_reg = ili210x_read_reg, + .get_touch_data = ili210x_read_touch_data, + .parse_touch_data = ili210x_touchdata_to_coords, + .continue_polling = ili210x_check_continue_polling, + .max_touches = 2, +}; + +static int ili211x_read_touch_data(struct i2c_client *client, u8 *data) +{ + s16 sum = 0; + int error; + int ret; + int i; + + ret = i2c_master_recv(client, data, ILI211X_DATA_SIZE); + if (ret != ILI211X_DATA_SIZE) { + error = ret < 0 ? ret : -EIO; + dev_err(&client->dev, "%s failed: %d\n", __func__, error); + return error; + } + + /* This chip uses custom checksum at the end of data */ + for (i = 0; i < ILI211X_DATA_SIZE - 1; i++) + sum = (sum + data[i]) & 0xff; + + if ((-sum & 0xff) != data[ILI211X_DATA_SIZE - 1]) { + dev_err(&client->dev, + "CRC error (crc=0x%02x expected=0x%02x)\n", + sum, data[ILI211X_DATA_SIZE - 1]); + return -EIO; + } + + return 0; +} + +static bool ili211x_touchdata_to_coords(const u8 *touchdata, unsigned int finger, unsigned int *x, unsigned int *y) { u32 data; - if (finger >= ILI211X_TOUCHES) - return false; - data = get_unaligned_be32(touchdata + 1 + (finger * 4) + 0); if (data == 0xffffffff) /* Finger up */ return false; @@ -140,58 +156,104 @@ static bool ili211x_touchdata_to_coords(struct ili210x *priv, u8 *touchdata, return true; } -static bool ili251x_touchdata_to_coords(struct ili210x *priv, u8 *touchdata, +static bool ili211x_decline_polling(const u8 *data, bool touch) +{ + return false; +} + +static const struct ili2xxx_chip ili211x_chip = { + .read_reg = ili210x_read_reg, + .get_touch_data = ili211x_read_touch_data, + .parse_touch_data = ili211x_touchdata_to_coords, + .continue_polling = ili211x_decline_polling, + .max_touches = 10, +}; + +static int ili251x_read_reg(struct i2c_client *client, + u8 reg, void *buf, size_t len) +{ + int error; + int ret; + + ret = i2c_master_send(client, ®, 1); + if (ret == 1) { + usleep_range(5000, 5500); + + ret = i2c_master_recv(client, buf, len); + if (ret == len) + return 0; + } + + error = ret < 0 ? ret : -EIO; + dev_err(&client->dev, "%s failed: %d\n", __func__, error); + return ret; +} + +static int ili251x_read_touch_data(struct i2c_client *client, u8 *data) +{ + int error; + + error = ili251x_read_reg(client, REG_TOUCHDATA, + data, ILI251X_DATA_SIZE1); + if (!error && data[0] == 2) { + error = i2c_master_recv(client, data + ILI251X_DATA_SIZE1, + ILI251X_DATA_SIZE2); + if (error >= 0 && error != ILI251X_DATA_SIZE2) + error = -EIO; + } + + return error; +} + +static bool ili251x_touchdata_to_coords(const u8 *touchdata, unsigned int finger, unsigned int *x, unsigned int *y) { - if (finger >= ILI251X_TOUCHES) + u16 val; + + val = get_unaligned_be16(touchdata + 1 + (finger * 5) + 0); + if (!(val & BIT(15))) /* Touch indication */ return false; - *x = get_unaligned_be16(touchdata + 1 + (finger * 5) + 0); - if (!(*x & BIT(15))) /* Touch indication */ - return false; - - *x &= 0x3fff; + *x = val & 0x3fff; *y = get_unaligned_be16(touchdata + 1 + (finger * 5) + 2); return true; } +static bool ili251x_check_continue_polling(const u8 *data, bool touch) +{ + return touch; +} + +static const struct ili2xxx_chip ili251x_chip = { + .read_reg = ili251x_read_reg, + .get_touch_data = ili251x_read_touch_data, + .parse_touch_data = ili251x_touchdata_to_coords, + .continue_polling = ili251x_check_continue_polling, + .max_touches = 10, +}; + static bool ili210x_report_events(struct ili210x *priv, u8 *touchdata) { struct input_dev *input = priv->input; int i; - bool contact = false, touch = false; + bool contact = false, touch; unsigned int x = 0, y = 0; - for (i = 0; i < priv->max_touches; i++) { - if (priv->model == MODEL_ILI210X) { - touch = ili210x_touchdata_to_coords(priv, touchdata, - i, &x, &y); - } else if (priv->model == MODEL_ILI211X) { - touch = ili211x_touchdata_to_coords(priv, touchdata, - i, &x, &y); - } else if (priv->model == MODEL_ILI251X) { - touch = ili251x_touchdata_to_coords(priv, touchdata, - i, &x, &y); - if (touch) - contact = true; - } + for (i = 0; i < priv->chip->max_touches; i++) { + touch = priv->chip->parse_touch_data(touchdata, i, &x, &y); input_mt_slot(input, i); - input_mt_report_slot_state(input, MT_TOOL_FINGER, touch); - if (!touch) - continue; - touchscreen_report_pos(input, &priv->prop, x, y, - true); + if (input_mt_report_slot_state(input, MT_TOOL_FINGER, touch)) { + touchscreen_report_pos(input, &priv->prop, x, y, true); + contact = true; + } } input_mt_report_pointer_emulation(input, false); input_sync(input); - if (priv->model == MODEL_ILI210X) - contact = touchdata[0] & 0xf3; - return contact; } @@ -199,50 +261,25 @@ static irqreturn_t ili210x_irq(int irq, void *irq_data) { struct ili210x *priv = irq_data; struct i2c_client *client = priv->client; - u8 touchdata[64] = { 0 }; - s16 sum = 0; + const struct ili2xxx_chip *chip = priv->chip; + u8 touchdata[ILI210X_DATA_SIZE] = { 0 }; + bool keep_polling; bool touch; - int i; int error; do { - if (priv->model == MODEL_ILI210X) { - error = ili210x_read_reg(client, REG_TOUCHDATA, - touchdata, sizeof(touchdata)); - } else if (priv->model == MODEL_ILI211X) { - error = ili210x_read(client, touchdata, 43); - if (!error) { - /* - * This chip uses custom checksum at the end - * of data. - */ - for (i = 0; i <= 41; i++) - sum = (sum + touchdata[i]) & 0xff; - if ((-sum & 0xff) != touchdata[42]) { - dev_err(&client->dev, - "CRC error (crc=0x%02x expected=0x%02x)\n", - sum, touchdata[42]); - break; - } - } - } else if (priv->model == MODEL_ILI251X) { - error = ili210x_read_reg(client, REG_TOUCHDATA, - touchdata, 31); - if (!error && touchdata[0] == 2) - error = ili210x_read(client, - &touchdata[31], 20); - } - + error = chip->get_touch_data(client, touchdata); if (error) { dev_err(&client->dev, - "Unable to get touchdata, err = %d\n", error); + "Unable to get touch data: %d\n", error); break; } touch = ili210x_report_events(priv, touchdata); - if (touch) + keep_polling = chip->continue_polling(touchdata, touch); + if (keep_polling) msleep(ILI2XXX_POLL_PERIOD); - } while (!priv->stop && touch); + } while (!priv->stop && keep_polling); return IRQ_HANDLED; } @@ -298,20 +335,26 @@ static void ili210x_stop(void *data) } static int ili210x_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) + const struct i2c_device_id *id) { struct device *dev = &client->dev; + const struct ili2xxx_chip *chip; struct ili210x *priv; struct gpio_desc *reset_gpio; struct input_dev *input; struct firmware_version firmware; - enum ili2xxx_model model; int error; - model = (enum ili2xxx_model)id->driver_data; - dev_dbg(dev, "Probing for ILI210X I2C Touschreen driver"); + chip = device_get_match_data(dev); + if (!chip && id) + chip = (const struct ili2xxx_chip *)id->driver_data; + if (!chip) { + dev_err(&client->dev, "unknown device model\n"); + return -ENODEV; + } + if (client->irq <= 0) { dev_err(dev, "No IRQ!\n"); return -EINVAL; @@ -343,19 +386,12 @@ static int ili210x_i2c_probe(struct i2c_client *client, priv->client = client; priv->input = input; priv->reset_gpio = reset_gpio; - priv->model = model; - if (model == MODEL_ILI210X) - priv->max_touches = ILI210X_TOUCHES; - if (model == MODEL_ILI211X) - priv->max_touches = ILI211X_TOUCHES; - if (model == MODEL_ILI251X) - priv->max_touches = ILI251X_TOUCHES; - + priv->chip = chip; i2c_set_clientdata(client, priv); /* Get firmware version */ - error = ili210x_read_reg(client, REG_FIRMWARE_VERSION, - &firmware, sizeof(firmware)); + error = chip->read_reg(client, REG_FIRMWARE_VERSION, + &firmware, sizeof(firmware)); if (error) { dev_err(dev, "Failed to get firmware version, err: %d\n", error); @@ -371,7 +407,8 @@ static int ili210x_i2c_probe(struct i2c_client *client, input_set_abs_params(input, ABS_MT_POSITION_Y, 0, 0xffff, 0, 0); touchscreen_parse_properties(input, true, &priv->prop); - error = input_mt_init_slots(input, priv->max_touches, INPUT_MT_DIRECT); + error = input_mt_init_slots(input, priv->chip->max_touches, + INPUT_MT_DIRECT); if (error) { dev_err(dev, "Unable to set up slots, err: %d\n", error); return error; @@ -435,18 +472,18 @@ static SIMPLE_DEV_PM_OPS(ili210x_i2c_pm, ili210x_i2c_suspend, ili210x_i2c_resume); static const struct i2c_device_id ili210x_i2c_id[] = { - { "ili210x", MODEL_ILI210X }, - { "ili2117", MODEL_ILI211X }, - { "ili251x", MODEL_ILI251X }, + { "ili210x", (long)&ili210x_chip }, + { "ili2117", (long)&ili211x_chip }, + { "ili251x", (long)&ili251x_chip }, { } }; MODULE_DEVICE_TABLE(i2c, ili210x_i2c_id); static const struct of_device_id ili210x_dt_ids[] = { - { .compatible = "ilitek,ili210x", .data = (void *)MODEL_ILI210X }, - { .compatible = "ilitek,ili2117", .data = (void *)MODEL_ILI211X }, - { .compatible = "ilitek,ili251x", .data = (void *)MODEL_ILI251X }, - { }, + { .compatible = "ilitek,ili210x", .data = &ili210x_chip }, + { .compatible = "ilitek,ili2117", .data = &ili211x_chip }, + { .compatible = "ilitek,ili251x", .data = &ili251x_chip }, + { } }; MODULE_DEVICE_TABLE(of, ili210x_dt_ids); From 172bb5f34c0dd5e94eb877edb3e8721d1ebd5c75 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 4 Nov 2019 15:27:41 -0800 Subject: [PATCH 61/70] Input: ili210x - do not unconditionally mark touchscreen as wakeup source I2C devices that are supposed to be wakeup sources should be instantiated with I2C_CLIENT_WAKE flag (which can be either set by in board info, or retrieved from "wakeup-source" property); individual drivers should not be marking devices as wakeup sources unconditionally. Tested-by: Adam Ford #imx6q-logicpd Tested-by: Sven Van Asbroeck # ILI2118A variant Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/ili210x.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c index 22811df82044..ef0da2fc8bd3 100644 --- a/drivers/input/touchscreen/ili210x.c +++ b/drivers/input/touchscreen/ili210x.c @@ -439,8 +439,6 @@ static int ili210x_i2c_probe(struct i2c_client *client, return error; } - device_init_wakeup(dev, 1); - dev_dbg(dev, "ILI210x initialized (IRQ: %d), firmware version %d.%d.%d", client->irq, firmware.id, firmware.major, firmware.minor); From a5fdf7d02656e71071d1a13ab887f94e58651baf Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 4 Nov 2019 15:30:22 -0800 Subject: [PATCH 62/70] Input: ili210x - remove unneeded suspend and resume handlers When I2C client is instantiated with I2C_CLIENT_WAKE flag (either via "wakeup-source" device property, or via board info flag), it will mark the main IRQ line as wakeup IRQ, which will ensure that it will be enabled for wakeup when system transitions to suspend state. Since our suspend/resume handlers were only managing IRQ wakeup state, they are no longer needed, and can be removed. Tested-by: Adam Ford #imx6q-logicpd Tested-by: Sven Van Asbroeck # ILI2118A variant Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/ili210x.c | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c index ef0da2fc8bd3..0ed6014af6d7 100644 --- a/drivers/input/touchscreen/ili210x.c +++ b/drivers/input/touchscreen/ili210x.c @@ -446,29 +446,6 @@ static int ili210x_i2c_probe(struct i2c_client *client, return 0; } -static int __maybe_unused ili210x_i2c_suspend(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - - if (device_may_wakeup(&client->dev)) - enable_irq_wake(client->irq); - - return 0; -} - -static int __maybe_unused ili210x_i2c_resume(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - - if (device_may_wakeup(&client->dev)) - disable_irq_wake(client->irq); - - return 0; -} - -static SIMPLE_DEV_PM_OPS(ili210x_i2c_pm, - ili210x_i2c_suspend, ili210x_i2c_resume); - static const struct i2c_device_id ili210x_i2c_id[] = { { "ili210x", (long)&ili210x_chip }, { "ili2117", (long)&ili211x_chip }, @@ -488,7 +465,6 @@ MODULE_DEVICE_TABLE(of, ili210x_dt_ids); static struct i2c_driver ili210x_ts_driver = { .driver = { .name = "ili210x_i2c", - .pm = &ili210x_i2c_pm, .of_match_table = ili210x_dt_ids, }, .id_table = ili210x_i2c_id, From 8d13c7642fabb0f9fb044041ebcce23fb002d86b Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Tue, 8 Oct 2019 16:48:02 -0700 Subject: [PATCH 63/70] Input: mms114 - use device_get_match_data device_get_match_data is available now, so we can replace the call to of_device_get_match_data and remove the FIXME comment. Signed-off-by: Stephan Gerhold Reviewed-by: Andi Shyti Link: https://lore.kernel.org/r/20191007203343.101466-2-stephan@gerhold.net Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/mms114.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c index a5ab774da4cc..69c6d559eeb0 100644 --- a/drivers/input/touchscreen/mms114.c +++ b/drivers/input/touchscreen/mms114.c @@ -446,8 +446,7 @@ static int mms114_probe(struct i2c_client *client, data->client = client; data->input_dev = input_dev; - /* FIXME: switch to device_get_match_data() when available */ - match_data = of_device_get_match_data(&client->dev); + match_data = device_get_match_data(&client->dev); if (!match_data) return -EINVAL; From c7dded5b2980de9811f47a1a576e0596a5a775ce Mon Sep 17 00:00:00 2001 From: Sven Van Asbroeck Date: Tue, 12 Nov 2019 15:40:03 -0800 Subject: [PATCH 64/70] Input: ili210x - do not retrieve/print chip firmware version The driver's method to retrieve the firmware version on ili2117/ ili2118 chip flavours is incorrect. The firmware version register address and layout are wrong. The firmware version is not actually used anywhere inside or outside this driver. There is a dev_dbg() print, but that is only visible when the developer explicitly compiles in debug support. Don't make the code more complicated to preserve a feature that no-one is using. Remove all code associated with chip firmware version. Signed-off-by: Sven Van Asbroeck Link: https://lore.kernel.org/r/20191112164429.11225-1-TheSven73@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/ili210x.c | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c index 0ed6014af6d7..a6feae5ce887 100644 --- a/drivers/input/touchscreen/ili210x.c +++ b/drivers/input/touchscreen/ili210x.c @@ -21,15 +21,8 @@ /* Touchscreen commands */ #define REG_TOUCHDATA 0x10 #define REG_PANEL_INFO 0x20 -#define REG_FIRMWARE_VERSION 0x40 #define REG_CALIBRATE 0xcc -struct firmware_version { - u8 id; - u8 major; - u8 minor; -} __packed; - struct ili2xxx_chip { int (*read_reg)(struct i2c_client *client, u8 reg, void *buf, size_t len); @@ -342,7 +335,6 @@ static int ili210x_i2c_probe(struct i2c_client *client, struct ili210x *priv; struct gpio_desc *reset_gpio; struct input_dev *input; - struct firmware_version firmware; int error; dev_dbg(dev, "Probing for ILI210X I2C Touschreen driver"); @@ -389,15 +381,6 @@ static int ili210x_i2c_probe(struct i2c_client *client, priv->chip = chip; i2c_set_clientdata(client, priv); - /* Get firmware version */ - error = chip->read_reg(client, REG_FIRMWARE_VERSION, - &firmware, sizeof(firmware)); - if (error) { - dev_err(dev, "Failed to get firmware version, err: %d\n", - error); - return error; - } - /* Setup input device */ input->name = "ILI210x Touchscreen"; input->id.bustype = BUS_I2C; @@ -439,10 +422,6 @@ static int ili210x_i2c_probe(struct i2c_client *client, return error; } - dev_dbg(dev, - "ILI210x initialized (IRQ: %d), firmware version %d.%d.%d", - client->irq, firmware.id, firmware.major, firmware.minor); - return 0; } From b32fbeaec52d387004dd7fa15877b8adf7b396c3 Mon Sep 17 00:00:00 2001 From: Sven Van Asbroeck Date: Tue, 12 Nov 2019 15:40:48 -0800 Subject: [PATCH 65/70] Input: ili210x - add resolution to chip operations structure Optionally allow the touch screen resolution to be set by adding it to the chip operations structure. If it is omitted (left zero), the resolution defaults to 64K. Which is the previously hard-coded value. Set the ili2117 resolution to 2048, as indicated in its datasheet. Signed-off-by: Sven Van Asbroeck Link: https://lore.kernel.org/r/20191112210148.3535-1-TheSven73@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/ili210x.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c index a6feae5ce887..6861ac4355b2 100644 --- a/drivers/input/touchscreen/ili210x.c +++ b/drivers/input/touchscreen/ili210x.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -31,6 +32,7 @@ struct ili2xxx_chip { unsigned int *x, unsigned int *y); bool (*continue_polling)(const u8 *data, bool touch); unsigned int max_touches; + unsigned int resolution; }; struct ili210x { @@ -160,6 +162,7 @@ static const struct ili2xxx_chip ili211x_chip = { .parse_touch_data = ili211x_touchdata_to_coords, .continue_polling = ili211x_decline_polling, .max_touches = 10, + .resolution = 2048, }; static int ili251x_read_reg(struct i2c_client *client, @@ -336,6 +339,7 @@ static int ili210x_i2c_probe(struct i2c_client *client, struct gpio_desc *reset_gpio; struct input_dev *input; int error; + unsigned int max_xy; dev_dbg(dev, "Probing for ILI210X I2C Touschreen driver"); @@ -386,8 +390,9 @@ static int ili210x_i2c_probe(struct i2c_client *client, input->id.bustype = BUS_I2C; /* Multi touch */ - input_set_abs_params(input, ABS_MT_POSITION_X, 0, 0xffff, 0, 0); - input_set_abs_params(input, ABS_MT_POSITION_Y, 0, 0xffff, 0, 0); + max_xy = (chip->resolution ?: SZ_64K) - 1; + input_set_abs_params(input, ABS_MT_POSITION_X, 0, max_xy, 0, 0); + input_set_abs_params(input, ABS_MT_POSITION_Y, 0, max_xy, 0, 0); touchscreen_parse_properties(input, true, &priv->prop); error = input_mt_init_slots(input, priv->chip->max_touches, From cc12ba1872c6bf05b5f177fae5082bcbea335f2b Mon Sep 17 00:00:00 2001 From: Sven Van Asbroeck Date: Tue, 12 Nov 2019 15:44:10 -0800 Subject: [PATCH 66/70] Input: ili210x - optionally show calibrate sysfs attribute Only show the 'calibrate' sysfs attribute on chip flavours which support calibration by writing to a calibration register. Do this by adding a flag to the chip operations structure. Signed-off-by: Sven Van Asbroeck Link: https://lore.kernel.org/r/20191112210148.3535-2-TheSven73@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/ili210x.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c index 6861ac4355b2..4a17096e83e1 100644 --- a/drivers/input/touchscreen/ili210x.c +++ b/drivers/input/touchscreen/ili210x.c @@ -33,6 +33,7 @@ struct ili2xxx_chip { bool (*continue_polling)(const u8 *data, bool touch); unsigned int max_touches; unsigned int resolution; + bool has_calibrate_reg; }; struct ili210x { @@ -103,6 +104,7 @@ static const struct ili2xxx_chip ili210x_chip = { .parse_touch_data = ili210x_touchdata_to_coords, .continue_polling = ili210x_check_continue_polling, .max_touches = 2, + .has_calibrate_reg = true, }; static int ili211x_read_touch_data(struct i2c_client *client, u8 *data) @@ -228,6 +230,7 @@ static const struct ili2xxx_chip ili251x_chip = { .parse_touch_data = ili251x_touchdata_to_coords, .continue_polling = ili251x_check_continue_polling, .max_touches = 10, + .has_calibrate_reg = true, }; static bool ili210x_report_events(struct ili210x *priv, u8 *touchdata) @@ -311,8 +314,19 @@ static struct attribute *ili210x_attributes[] = { NULL, }; +static umode_t ili210x_calibrate_visible(struct kobject *kobj, + struct attribute *attr, int index) +{ + struct device *dev = kobj_to_dev(kobj); + struct i2c_client *client = to_i2c_client(dev); + struct ili210x *priv = i2c_get_clientdata(client); + + return priv->chip->has_calibrate_reg; +} + static const struct attribute_group ili210x_attr_group = { .attrs = ili210x_attributes, + .is_visible = ili210x_calibrate_visible, }; static void ili210x_power_down(void *data) From dffe969aa7abfd866bc86780762a6aafa196d286 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Fri, 15 Nov 2019 11:30:14 -0800 Subject: [PATCH 67/70] Input: imx_sc_key - correct SCU message structure to avoid stack corruption The SCU message's data field used for receiving response data from SCU should be 32-bit width, as SCU will send back 32-bit width data. This solves kernel panic when CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG is enabled. [ 1.950768] Kernel panic - not syncing: stack-protector: Kernel stack is corrupted [ 1.980607] Workqueue: events imx_sc_check_for_events [ 1.985657] Call trace: [ 1.988104] dump_backtrace+0x0/0x140 [ 1.991768] show_stack+0x14/0x20 [ 1.995090] dump_stack+0xb4/0xf8 [ 1.998407] panic+0x158/0x324 [ 2.001463] print_tainted+0x0/0xa8 [ 2.004950] imx_sc_check_for_events+0x18c/0x190 [ 2.009569] process_one_work+0x198/0x320 [ 2.013579] worker_thread+0x48/0x420 [ 2.017252] kthread+0xf0/0x120 [ 2.020394] ret_from_fork+0x10/0x18 [ 2.023977] SMP: stopping secondary CPUs [ 2.027901] Kernel Offset: disabled [ 2.031391] CPU features: 0x0002,2100600c [ 2.035401] Memory Limit: none Signed-off-by: Anson Huang Fixes: 688f1dfb69b4 ("Input: keyboard - imx_sc: Add i.MX system controller key support") Link: https://lore.kernel.org/r/1573730499-2224-1-git-send-email-Anson.Huang@nxp.com Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/imx_sc_key.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/keyboard/imx_sc_key.c b/drivers/input/keyboard/imx_sc_key.c index dd57daa67e5f..53799527dc75 100644 --- a/drivers/input/keyboard/imx_sc_key.c +++ b/drivers/input/keyboard/imx_sc_key.c @@ -35,7 +35,7 @@ struct imx_key_drv_data { struct imx_sc_msg_key { struct imx_sc_rpc_msg hdr; - u8 state; + u32 state; }; static int imx_sc_key_notify(struct notifier_block *nb, From bcf1e034d3aae39d27371b51916359ea7501db01 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 22 Nov 2019 14:49:30 -0800 Subject: [PATCH 68/70] Input: fix Kconfig indentation Adjust indentation from spaces to tab (+optional two spaces) as in coding style with command like: $ sed -e 's/^ /\t/' -i */Kconfig Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/1574306373-29581-1-git-send-email-krzk@kernel.org Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/Kconfig | 14 +++++++------- drivers/input/mouse/Kconfig | 14 +++++++------- drivers/input/tablet/Kconfig | 18 +++++++++--------- drivers/input/touchscreen/Kconfig | 2 +- 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 1ddfc2413035..61f4eb63eec1 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -167,14 +167,14 @@ config KEYBOARD_QT1050 the module will be called qt1050 config KEYBOARD_QT1070 - tristate "Atmel AT42QT1070 Touch Sensor Chip" - depends on I2C - help - Say Y here if you want to use Atmel AT42QT1070 QTouch - Sensor chip as input device. + tristate "Atmel AT42QT1070 Touch Sensor Chip" + depends on I2C + help + Say Y here if you want to use Atmel AT42QT1070 QTouch + Sensor chip as input device. - To compile this driver as a module, choose M here: - the module will be called qt1070 + To compile this driver as a module, choose M here: + the module will be called qt1070 config KEYBOARD_QT2160 tristate "Atmel AT42QT2160 Touch Sensor Chip" diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index bf738d3b7fe4..d8b6a5dab190 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig @@ -92,14 +92,14 @@ config MOUSE_PS2_SYNAPTICS_SMBUS If unsure, say Y. config MOUSE_PS2_CYPRESS - bool "Cypress PS/2 mouse protocol extension" if EXPERT - default y - depends on MOUSE_PS2 - help - Say Y here if you have a Cypress PS/2 Trackpad connected to - your system. + bool "Cypress PS/2 mouse protocol extension" if EXPERT + default y + depends on MOUSE_PS2 + help + Say Y here if you have a Cypress PS/2 Trackpad connected to + your system. - If unsure, say Y. + If unsure, say Y. config MOUSE_PS2_LIFEBOOK bool "Fujitsu Lifebook PS/2 mouse protocol extension" if EXPERT diff --git a/drivers/input/tablet/Kconfig b/drivers/input/tablet/Kconfig index e4c0d9a055b9..51c339182017 100644 --- a/drivers/input/tablet/Kconfig +++ b/drivers/input/tablet/Kconfig @@ -39,16 +39,16 @@ config TABLET_USB_AIPTEK module will be called aiptek. config TABLET_USB_GTCO - tristate "GTCO CalComp/InterWrite USB Support" - depends on USB && INPUT - help - Say Y here if you want to use the USB version of the GTCO - CalComp/InterWrite Tablet. Make sure to say Y to "Mouse support" - (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support" - (CONFIG_INPUT_EVDEV) as well. + tristate "GTCO CalComp/InterWrite USB Support" + depends on USB && INPUT + help + Say Y here if you want to use the USB version of the GTCO + CalComp/InterWrite Tablet. Make sure to say Y to "Mouse support" + (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support" + (CONFIG_INPUT_EVDEV) as well. - To compile this driver as a module, choose M here: the - module will be called gtco. + To compile this driver as a module, choose M here: the + module will be called gtco. config TABLET_USB_HANWANG tristate "Hanwang Art Master III tablet support (USB)" diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 40bfc551ce30..c071f7c407b6 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -633,7 +633,7 @@ config TOUCHSCREEN_HP600 depends on SH_HP6XX && SH_ADC help Say Y here if you have a HP Jornada 620/660/680/690 and want to - support the built-in touchscreen. + support the built-in touchscreen. To compile this driver as a module, choose M here: the module will be called hp680_ts_input. From fc1156f373e3927e0dcf06678906c367588bfdd6 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 22 Nov 2019 16:17:08 -0800 Subject: [PATCH 69/70] Input: synaptics - switch another X1 Carbon 6 to RMI/SMbus Some Lenovo X1 Carbon Gen 6 laptops report LEN0091. Add this to the smbus_pnp_ids list. Signed-off-by: Hans Verkuil Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20191119105118.54285-2-hverkuil-cisco@xs4all.nl Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/synaptics.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 56fae3472114..1ae6f8bba9ae 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -172,6 +172,7 @@ static const char * const smbus_pnp_ids[] = { "LEN0071", /* T480 */ "LEN0072", /* X1 Carbon Gen 5 (2017) - Elan/ALPS trackpoint */ "LEN0073", /* X1 Carbon G5 (Elantech) */ + "LEN0091", /* X1 Carbon 6 */ "LEN0092", /* X1 Carbon 6 */ "LEN0093", /* T480 */ "LEN0096", /* X280 */ From 71c296f6d5b33faf9867d04c6c5d75c7e56b886b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 22 Nov 2019 16:17:47 -0800 Subject: [PATCH 70/70] Input: synaptics-rmi4 - fix various V4L2 compliance problems in F54 The v4l2-compliance utility reported several V4L2 API compliance issues: - the sequence counter wasn't filled in - the sequence counter wasn't reset to 0 at the start of streaming - the returned field value wasn't set to V4L2_FIELD_NONE - the timestamp wasn't set - the payload size was undefined if an error was returned - min_buffers_needed doesn't need to be initialized Fix these issues. Signed-off-by: Hans Verkuil Reviewed-by: Lucas Stach --- drivers/input/rmi4/rmi_f54.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/input/rmi4/rmi_f54.c b/drivers/input/rmi4/rmi_f54.c index 514f5568b74d..5a3bf07e98f4 100644 --- a/drivers/input/rmi4/rmi_f54.c +++ b/drivers/input/rmi4/rmi_f54.c @@ -110,6 +110,7 @@ struct f54_data { struct video_device vdev; struct vb2_queue queue; struct mutex lock; + u32 sequence; int input; enum rmi_f54_report_type inputs[F54_MAX_REPORT_TYPE]; }; @@ -284,6 +285,7 @@ static int rmi_f54_queue_setup(struct vb2_queue *q, unsigned int *nbuffers, static void rmi_f54_buffer_queue(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct f54_data *f54 = vb2_get_drv_priv(vb->vb2_queue); u16 *ptr; enum vb2_buffer_state state; @@ -292,6 +294,7 @@ static void rmi_f54_buffer_queue(struct vb2_buffer *vb) mutex_lock(&f54->status_mutex); + vb2_set_plane_payload(vb, 0, 0); reptype = rmi_f54_get_reptype(f54, f54->input); if (reptype == F54_REPORT_NONE) { state = VB2_BUF_STATE_ERROR; @@ -338,14 +341,25 @@ static void rmi_f54_buffer_queue(struct vb2_buffer *vb) data_done: mutex_unlock(&f54->data_mutex); done: + vb->timestamp = ktime_get_ns(); + vbuf->field = V4L2_FIELD_NONE; + vbuf->sequence = f54->sequence++; vb2_buffer_done(vb, state); mutex_unlock(&f54->status_mutex); } +static void rmi_f54_stop_streaming(struct vb2_queue *q) +{ + struct f54_data *f54 = vb2_get_drv_priv(q); + + f54->sequence = 0; +} + /* V4L2 structures */ static const struct vb2_ops rmi_f54_queue_ops = { .queue_setup = rmi_f54_queue_setup, .buf_queue = rmi_f54_buffer_queue, + .stop_streaming = rmi_f54_stop_streaming, .wait_prepare = vb2_ops_wait_prepare, .wait_finish = vb2_ops_wait_finish, }; @@ -357,7 +371,6 @@ static const struct vb2_queue rmi_f54_queue = { .ops = &rmi_f54_queue_ops, .mem_ops = &vb2_vmalloc_memops, .timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC, - .min_buffers_needed = 1, }; static int rmi_f54_vidioc_querycap(struct file *file, void *priv,