summaryrefslogtreecommitdiff
path: root/drivers/input/touchscreen
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/touchscreen')
-rw-r--r--drivers/input/touchscreen/Kconfig46
-rw-r--r--drivers/input/touchscreen/Makefile4
-rw-r--r--drivers/input/touchscreen/ad7877.c42
-rw-r--r--drivers/input/touchscreen/ad7879.c52
-rw-r--r--drivers/input/touchscreen/ads7846.c44
-rw-r--r--drivers/input/touchscreen/apple_z2.c481
-rw-r--r--drivers/input/touchscreen/atmel_mxt_ts.c318
-rw-r--r--drivers/input/touchscreen/auo-pixcir-ts.c43
-rw-r--r--drivers/input/touchscreen/bu21029_ts.c13
-rw-r--r--drivers/input/touchscreen/chipone_icn8318.c8
-rw-r--r--drivers/input/touchscreen/cyttsp5.c11
-rw-r--r--drivers/input/touchscreen/cyttsp_core.c21
-rw-r--r--drivers/input/touchscreen/da9052_tsi.c2
-rw-r--r--drivers/input/touchscreen/dynapro.c6
-rw-r--r--drivers/input/touchscreen/edt-ft5x06.c122
-rw-r--r--drivers/input/touchscreen/eeti_ts.c27
-rw-r--r--drivers/input/touchscreen/egalax_ts_serial.c5
-rw-r--r--drivers/input/touchscreen/ektf2127.c8
-rw-r--r--drivers/input/touchscreen/elants_i2c.c91
-rw-r--r--drivers/input/touchscreen/elo.c36
-rw-r--r--drivers/input/touchscreen/exc3000.c35
-rw-r--r--drivers/input/touchscreen/fsl-imx25-tcq.c1
-rw-r--r--drivers/input/touchscreen/fujitsu_ts.c5
-rw-r--r--drivers/input/touchscreen/goodix.c78
-rw-r--r--drivers/input/touchscreen/goodix.h1
-rw-r--r--drivers/input/touchscreen/goodix_berlin.h16
-rw-r--r--drivers/input/touchscreen/goodix_berlin_core.c38
-rw-r--r--drivers/input/touchscreen/goodix_berlin_i2c.c14
-rw-r--r--drivers/input/touchscreen/goodix_berlin_spi.c48
-rw-r--r--drivers/input/touchscreen/goodix_fwupload.c29
-rw-r--r--drivers/input/touchscreen/gunze.c4
-rw-r--r--drivers/input/touchscreen/hampshire.c6
-rw-r--r--drivers/input/touchscreen/hideep.c54
-rw-r--r--drivers/input/touchscreen/himax_hx852x.c503
-rw-r--r--drivers/input/touchscreen/hycon-hy46xx.c31
-rw-r--r--drivers/input/touchscreen/hynitron-cst816x.c253
-rw-r--r--drivers/input/touchscreen/ili210x.c96
-rw-r--r--drivers/input/touchscreen/ilitek_ts_i2c.c10
-rw-r--r--drivers/input/touchscreen/imagis.c30
-rw-r--r--drivers/input/touchscreen/imx6ul_tsc.c140
-rw-r--r--drivers/input/touchscreen/inexio.c4
-rw-r--r--drivers/input/touchscreen/ipaq-micro-ts.c8
-rw-r--r--drivers/input/touchscreen/iqs5xx.c191
-rw-r--r--drivers/input/touchscreen/iqs7211.c24
-rw-r--r--drivers/input/touchscreen/lpc32xx_ts.c8
-rw-r--r--drivers/input/touchscreen/mc13783_ts.c6
-rw-r--r--drivers/input/touchscreen/melfas_mip4.c123
-rw-r--r--drivers/input/touchscreen/migor_ts.c2
-rw-r--r--drivers/input/touchscreen/mk712.c215
-rw-r--r--drivers/input/touchscreen/mms114.c20
-rw-r--r--drivers/input/touchscreen/msg2638.c19
-rw-r--r--drivers/input/touchscreen/mtouch.c4
-rw-r--r--drivers/input/touchscreen/mxs-lradc-ts.c7
-rw-r--r--drivers/input/touchscreen/novatek-nvt-ts.c13
-rw-r--r--drivers/input/touchscreen/pcap_ts.c2
-rw-r--r--drivers/input/touchscreen/penmount.c4
-rw-r--r--drivers/input/touchscreen/pixcir_i2c_ts.c38
-rw-r--r--drivers/input/touchscreen/raydium_i2c_ts.c56
-rw-r--r--drivers/input/touchscreen/st1232.c90
-rw-r--r--drivers/input/touchscreen/stmfts.c84
-rw-r--r--drivers/input/touchscreen/stmpe-ts.c7
-rw-r--r--drivers/input/touchscreen/sur40.c27
-rw-r--r--drivers/input/touchscreen/sx8654.c24
-rw-r--r--drivers/input/touchscreen/ti_am335x_tsc.c8
-rw-r--r--drivers/input/touchscreen/touchit213.c6
-rw-r--r--drivers/input/touchscreen/touchright.c4
-rw-r--r--drivers/input/touchscreen/touchwin.c4
-rw-r--r--drivers/input/touchscreen/tsc2007.h2
-rw-r--r--drivers/input/touchscreen/tsc2007_core.c51
-rw-r--r--drivers/input/touchscreen/tsc2007_iio.c9
-rw-r--r--drivers/input/touchscreen/tsc200x-core.c7
-rw-r--r--drivers/input/touchscreen/tsc40.c4
-rw-r--r--drivers/input/touchscreen/usbtouchscreen.c54
-rw-r--r--drivers/input/touchscreen/wacom_w8001.c2
-rw-r--r--drivers/input/touchscreen/wdt87xx_i2c.c58
-rw-r--r--drivers/input/touchscreen/wm9705.c1
-rw-r--r--drivers/input/touchscreen/wm9712.c1
-rw-r--r--drivers/input/touchscreen/wm9713.c1
-rw-r--r--drivers/input/touchscreen/wm97xx-core.c58
-rw-r--r--drivers/input/touchscreen/zforce_ts.c3
-rw-r--r--drivers/input/touchscreen/zinitix.c19
81 files changed, 2531 insertions, 1509 deletions
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 1a03de7fcfa6..aeaf9a9cbb41 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -103,6 +103,18 @@ config TOUCHSCREEN_ADC
To compile this driver as a module, choose M here: the
module will be called resistive-adc-touch.ko.
+config TOUCHSCREEN_APPLE_Z2
+ tristate "Apple Z2 touchscreens"
+ depends on SPI && (ARCH_APPLE || COMPILE_TEST)
+ help
+ Say Y here if you have an ARM Apple device with
+ a touchscreen or a touchbar.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called apple_z2.
+
config TOUCHSCREEN_AR1021_I2C
tristate "Microchip AR1020/1021 i2c touchscreen"
depends on I2C && OF
@@ -429,6 +441,16 @@ config TOUCHSCREEN_HIDEEP
To compile this driver as a module, choose M here : the
module will be called hideep_ts.
+config TOUCHSCREEN_HIMAX_HX852X
+ tristate "Himax HX852x(ES) touchscreen"
+ depends on I2C
+ help
+ Say Y here if you have a Himax HX852x(ES) touchscreen.
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the module
+ will be called himax_hx852x.
+
config TOUCHSCREEN_HYCON_HY46XX
tristate "Hycon hy46xx touchscreen support"
depends on I2C
@@ -453,6 +475,18 @@ config TOUCHSCREEN_HYNITRON_CSTXXX
To compile this driver as a module, choose M here: the
module will be called hynitron-cstxxx.
+config TOUCHSCREEN_HYNITRON_CST816X
+ tristate "Hynitron CST816x touchscreen"
+ depends on I2C
+ help
+ Say Y here if you have a touchscreen using a Hynitron
+ CST816x series touchscreen controller.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called hynitron-cst816x.
+
config TOUCHSCREEN_ILI210X
tristate "Ilitek ILI210X based touchscreen"
depends on I2C
@@ -689,18 +723,6 @@ config TOUCHSCREEN_INEXIO
To compile this driver as a module, choose M here: the
module will be called inexio.
-config TOUCHSCREEN_MK712
- tristate "ICS MicroClock MK712 touchscreen"
- depends on ISA
- help
- Say Y here if you have the ICS MicroClock MK712 touchscreen
- controller chip in your system.
-
- If unsure, say N.
-
- To compile this driver as a module, choose M here: the
- module will be called mk712.
-
config TOUCHSCREEN_HP600
tristate "HP Jornada 6xx touchscreen"
depends on SH_HP6XX && SH_ADC
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 82bc837ca01e..f2b002abebe8 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_TOUCHSCREEN_AD7879_I2C) += ad7879-i2c.o
obj-$(CONFIG_TOUCHSCREEN_AD7879_SPI) += ad7879-spi.o
obj-$(CONFIG_TOUCHSCREEN_ADC) += resistive-adc-touch.o
obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o
+obj-$(CONFIG_TOUCHSCREEN_APPLE_Z2) += apple_z2.o
obj-$(CONFIG_TOUCHSCREEN_AR1021_I2C) += ar1021_i2c.o
obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT) += atmel_mxt_ts.o
obj-$(CONFIG_TOUCHSCREEN_AUO_PIXCIR) += auo-pixcir-ts.o
@@ -48,7 +49,9 @@ obj-$(CONFIG_TOUCHSCREEN_GOODIX_BERLIN_CORE) += goodix_berlin_core.o
obj-$(CONFIG_TOUCHSCREEN_GOODIX_BERLIN_I2C) += goodix_berlin_i2c.o
obj-$(CONFIG_TOUCHSCREEN_GOODIX_BERLIN_SPI) += goodix_berlin_spi.o
obj-$(CONFIG_TOUCHSCREEN_HIDEEP) += hideep.o
+obj-$(CONFIG_TOUCHSCREEN_HIMAX_HX852X) += himax_hx852x.o
obj-$(CONFIG_TOUCHSCREEN_HYNITRON_CSTXXX) += hynitron_cstxxx.o
+obj-$(CONFIG_TOUCHSCREEN_HYNITRON_CST816X) += hynitron-cst816x.o
obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o
obj-$(CONFIG_TOUCHSCREEN_ILITEK) += ilitek_ts_i2c.o
obj-$(CONFIG_TOUCHSCREEN_IMAGIS) += imagis.o
@@ -65,7 +68,6 @@ obj-$(CONFIG_TOUCHSCREEN_MIGOR) += migor_ts.o
obj-$(CONFIG_TOUCHSCREEN_MMS114) += mms114.o
obj-$(CONFIG_TOUCHSCREEN_MSG2638) += msg2638.o
obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o
-obj-$(CONFIG_TOUCHSCREEN_MK712) += mk712.o
obj-$(CONFIG_TOUCHSCREEN_NOVATEK_NVT_TS) += novatek-nvt-ts.o
obj-$(CONFIG_TOUCHSCREEN_HP600) += hp680_ts_input.o
obj-$(CONFIG_TOUCHSCREEN_HP7XX) += jornada720_ts.o
diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c
index a0598e9c7aff..cc39057d0117 100644
--- a/drivers/input/touchscreen/ad7877.c
+++ b/drivers/input/touchscreen/ad7877.c
@@ -201,7 +201,7 @@ static int ad7877_read(struct spi_device *spi, u16 reg)
struct ser_req *req;
int status, ret;
- req = kzalloc(sizeof *req, GFP_KERNEL);
+ req = kzalloc_obj(*req);
if (!req)
return -ENOMEM;
@@ -232,7 +232,7 @@ static int ad7877_write(struct spi_device *spi, u16 reg, u16 val)
struct ser_req *req;
int status;
- req = kzalloc(sizeof *req, GFP_KERNEL);
+ req = kzalloc_obj(*req);
if (!req)
return -ENOMEM;
@@ -259,7 +259,7 @@ static int ad7877_read_adc(struct spi_device *spi, unsigned command)
int sample;
int i;
- req = kzalloc(sizeof *req, GFP_KERNEL);
+ req = kzalloc_obj(*req);
if (!req)
return -ENOMEM;
@@ -375,18 +375,15 @@ static inline void ad7877_ts_event_release(struct ad7877 *ts)
static void ad7877_timer(struct timer_list *t)
{
- struct ad7877 *ts = from_timer(ts, t, timer);
- unsigned long flags;
+ struct ad7877 *ts = timer_container_of(ts, t, timer);
- spin_lock_irqsave(&ts->lock, flags);
+ guard(spinlock_irqsave)(&ts->lock);
ad7877_ts_event_release(ts);
- spin_unlock_irqrestore(&ts->lock, flags);
}
static irqreturn_t ad7877_irq(int irq, void *handle)
{
struct ad7877 *ts = handle;
- unsigned long flags;
int error;
error = spi_sync(ts->spi, &ts->msg);
@@ -395,11 +392,13 @@ static irqreturn_t ad7877_irq(int irq, void *handle)
goto out;
}
- spin_lock_irqsave(&ts->lock, flags);
- error = ad7877_process_data(ts);
- if (!error)
+ scoped_guard(spinlock_irqsave, &ts->lock) {
+ error = ad7877_process_data(ts);
+ if (error)
+ goto out;
+
mod_timer(&ts->timer, jiffies + TS_PEN_UP_TIMEOUT);
- spin_unlock_irqrestore(&ts->lock, flags);
+ }
out:
return IRQ_HANDLED;
@@ -409,13 +408,13 @@ static void ad7877_disable(void *data)
{
struct ad7877 *ts = data;
- mutex_lock(&ts->mutex);
+ guard(mutex)(&ts->mutex);
if (!ts->disabled) {
ts->disabled = true;
disable_irq(ts->spi->irq);
- if (del_timer_sync(&ts->timer))
+ if (timer_delete_sync(&ts->timer))
ad7877_ts_event_release(ts);
}
@@ -423,20 +422,16 @@ static void ad7877_disable(void *data)
* We know the chip's in lowpower mode since we always
* leave it that way after every request
*/
-
- mutex_unlock(&ts->mutex);
}
static void ad7877_enable(struct ad7877 *ts)
{
- mutex_lock(&ts->mutex);
+ guard(mutex)(&ts->mutex);
if (ts->disabled) {
ts->disabled = false;
enable_irq(ts->spi->irq);
}
-
- mutex_unlock(&ts->mutex);
}
#define SHOW(name) static ssize_t \
@@ -509,10 +504,9 @@ static ssize_t ad7877_dac_store(struct device *dev,
if (error)
return error;
- mutex_lock(&ts->mutex);
+ guard(mutex)(&ts->mutex);
ts->dac = val & 0xFF;
ad7877_write(ts->spi, AD7877_REG_DAC, (ts->dac << 4) | AD7877_DAC_CONF);
- mutex_unlock(&ts->mutex);
return count;
}
@@ -539,11 +533,10 @@ static ssize_t ad7877_gpio3_store(struct device *dev,
if (error)
return error;
- mutex_lock(&ts->mutex);
+ guard(mutex)(&ts->mutex);
ts->gpio3 = !!val;
ad7877_write(ts->spi, AD7877_REG_EXTWRITE, AD7877_EXTW_GPIO_DATA |
(ts->gpio4 << 4) | (ts->gpio3 << 5));
- mutex_unlock(&ts->mutex);
return count;
}
@@ -570,11 +563,10 @@ static ssize_t ad7877_gpio4_store(struct device *dev,
if (error)
return error;
- mutex_lock(&ts->mutex);
+ guard(mutex)(&ts->mutex);
ts->gpio4 = !!val;
ad7877_write(ts->spi, AD7877_REG_EXTWRITE, AD7877_EXTW_GPIO_DATA |
(ts->gpio4 << 4) | (ts->gpio3 << 5));
- mutex_unlock(&ts->mutex);
return count;
}
diff --git a/drivers/input/touchscreen/ad7879.c b/drivers/input/touchscreen/ad7879.c
index e5d69bf2276e..31d2a3029d5f 100644
--- a/drivers/input/touchscreen/ad7879.c
+++ b/drivers/input/touchscreen/ad7879.c
@@ -22,6 +22,7 @@
#include <linux/device.h>
#include <linux/delay.h>
+#include <linux/export.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
@@ -237,7 +238,7 @@ static void ad7879_ts_event_release(struct ad7879 *ts)
static void ad7879_timer(struct timer_list *t)
{
- struct ad7879 *ts = from_timer(ts, t, timer);
+ struct ad7879 *ts = timer_container_of(ts, t, timer);
ad7879_ts_event_release(ts);
}
@@ -273,7 +274,7 @@ static void __ad7879_disable(struct ad7879 *ts)
AD7879_PM(AD7879_PM_SHUTDOWN);
disable_irq(ts->irq);
- if (del_timer_sync(&ts->timer))
+ if (timer_delete_sync(&ts->timer))
ad7879_ts_event_release(ts);
ad7879_write(ts, AD7879_REG_CTRL2, reg);
@@ -304,15 +305,13 @@ static int __maybe_unused ad7879_suspend(struct device *dev)
{
struct ad7879 *ts = dev_get_drvdata(dev);
- mutex_lock(&ts->input->mutex);
+ guard(mutex)(&ts->input->mutex);
if (!ts->suspended && !ts->disabled && input_device_enabled(ts->input))
__ad7879_disable(ts);
ts->suspended = true;
- mutex_unlock(&ts->input->mutex);
-
return 0;
}
@@ -320,15 +319,13 @@ static int __maybe_unused ad7879_resume(struct device *dev)
{
struct ad7879 *ts = dev_get_drvdata(dev);
- mutex_lock(&ts->input->mutex);
+ guard(mutex)(&ts->input->mutex);
if (ts->suspended && !ts->disabled && input_device_enabled(ts->input))
__ad7879_enable(ts);
ts->suspended = false;
- mutex_unlock(&ts->input->mutex);
-
return 0;
}
@@ -337,7 +334,7 @@ EXPORT_SYMBOL(ad7879_pm_ops);
static void ad7879_toggle(struct ad7879 *ts, bool disable)
{
- mutex_lock(&ts->input->mutex);
+ guard(mutex)(&ts->input->mutex);
if (!ts->suspended && input_device_enabled(ts->input)) {
@@ -351,8 +348,6 @@ static void ad7879_toggle(struct ad7879 *ts, bool disable)
}
ts->disabled = disable;
-
- mutex_unlock(&ts->input->mutex);
}
static ssize_t ad7879_disable_show(struct device *dev,
@@ -402,23 +397,20 @@ static int ad7879_gpio_direction_input(struct gpio_chip *chip,
unsigned gpio)
{
struct ad7879 *ts = gpiochip_get_data(chip);
- int err;
- mutex_lock(&ts->mutex);
- ts->cmd_crtl2 |= AD7879_GPIO_EN | AD7879_GPIODIR | AD7879_GPIOPOL;
- err = ad7879_write(ts, AD7879_REG_CTRL2, ts->cmd_crtl2);
- mutex_unlock(&ts->mutex);
+ guard(mutex)(&ts->mutex);
- return err;
+ ts->cmd_crtl2 |= AD7879_GPIO_EN | AD7879_GPIODIR | AD7879_GPIOPOL;
+ return ad7879_write(ts, AD7879_REG_CTRL2, ts->cmd_crtl2);
}
static int ad7879_gpio_direction_output(struct gpio_chip *chip,
unsigned gpio, int level)
{
struct ad7879 *ts = gpiochip_get_data(chip);
- int err;
- mutex_lock(&ts->mutex);
+ guard(mutex)(&ts->mutex);
+
ts->cmd_crtl2 &= ~AD7879_GPIODIR;
ts->cmd_crtl2 |= AD7879_GPIO_EN | AD7879_GPIOPOL;
if (level)
@@ -426,37 +418,33 @@ static int ad7879_gpio_direction_output(struct gpio_chip *chip,
else
ts->cmd_crtl2 &= ~AD7879_GPIO_DATA;
- err = ad7879_write(ts, AD7879_REG_CTRL2, ts->cmd_crtl2);
- mutex_unlock(&ts->mutex);
-
- return err;
+ return ad7879_write(ts, AD7879_REG_CTRL2, ts->cmd_crtl2);
}
-static int ad7879_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
+static int ad7879_gpio_get_value(struct gpio_chip *chip, unsigned int gpio)
{
struct ad7879 *ts = gpiochip_get_data(chip);
u16 val;
- mutex_lock(&ts->mutex);
- val = ad7879_read(ts, AD7879_REG_CTRL2);
- mutex_unlock(&ts->mutex);
+ guard(mutex)(&ts->mutex);
+ val = ad7879_read(ts, AD7879_REG_CTRL2);
return !!(val & AD7879_GPIO_DATA);
}
-static void ad7879_gpio_set_value(struct gpio_chip *chip,
- unsigned gpio, int value)
+static int ad7879_gpio_set_value(struct gpio_chip *chip, unsigned int gpio,
+ int value)
{
struct ad7879 *ts = gpiochip_get_data(chip);
- mutex_lock(&ts->mutex);
+ guard(mutex)(&ts->mutex);
+
if (value)
ts->cmd_crtl2 |= AD7879_GPIO_DATA;
else
ts->cmd_crtl2 &= ~AD7879_GPIO_DATA;
- ad7879_write(ts, AD7879_REG_CTRL2, ts->cmd_crtl2);
- mutex_unlock(&ts->mutex);
+ return ad7879_write(ts, AD7879_REG_CTRL2, ts->cmd_crtl2);
}
static int ad7879_gpio_add(struct ad7879 *ts)
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index 67264c5b49cb..4b39f7212d35 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -289,7 +289,7 @@ static void __ads7846_enable(struct ads7846 *ts)
static void ads7846_disable(struct ads7846 *ts)
{
- mutex_lock(&ts->lock);
+ guard(mutex)(&ts->lock);
if (!ts->disabled) {
@@ -298,13 +298,11 @@ static void ads7846_disable(struct ads7846 *ts)
ts->disabled = true;
}
-
- mutex_unlock(&ts->lock);
}
static void ads7846_enable(struct ads7846 *ts)
{
- mutex_lock(&ts->lock);
+ guard(mutex)(&ts->lock);
if (ts->disabled) {
@@ -313,8 +311,6 @@ static void ads7846_enable(struct ads7846 *ts)
if (!ts->suspended)
__ads7846_enable(ts);
}
-
- mutex_unlock(&ts->lock);
}
/*--------------------------------------------------------------------------*/
@@ -354,10 +350,9 @@ static int ads7846_read12_ser(struct device *dev, unsigned command)
{
struct spi_device *spi = to_spi_device(dev);
struct ads7846 *ts = dev_get_drvdata(dev);
- struct ser_req *req;
int status;
- req = kzalloc(sizeof *req, GFP_KERNEL);
+ struct ser_req *req __free(kfree) = kzalloc_obj(*req);
if (!req)
return -ENOMEM;
@@ -418,11 +413,11 @@ static int ads7846_read12_ser(struct device *dev, unsigned command)
CS_CHANGE(req->xfer[7]);
spi_message_add_tail(&req->xfer[7], &req->msg);
- mutex_lock(&ts->lock);
- ads7846_stop(ts);
- status = spi_sync(spi, &req->msg);
- ads7846_restart(ts);
- mutex_unlock(&ts->lock);
+ scoped_guard(mutex, &ts->lock) {
+ ads7846_stop(ts);
+ status = spi_sync(spi, &req->msg);
+ ads7846_restart(ts);
+ }
if (status == 0) {
/* on-wire is a must-ignore bit, a BE12 value, then padding */
@@ -431,7 +426,6 @@ static int ads7846_read12_ser(struct device *dev, unsigned command)
status &= 0x0fff;
}
- kfree(req);
return status;
}
@@ -439,10 +433,9 @@ static int ads7845_read12_ser(struct device *dev, unsigned command)
{
struct spi_device *spi = to_spi_device(dev);
struct ads7846 *ts = dev_get_drvdata(dev);
- struct ads7845_ser_req *req;
int status;
- req = kzalloc(sizeof *req, GFP_KERNEL);
+ struct ads7845_ser_req *req __free(kfree) = kzalloc_obj(*req);
if (!req)
return -ENOMEM;
@@ -454,11 +447,11 @@ static int ads7845_read12_ser(struct device *dev, unsigned command)
req->xfer[0].len = 3;
spi_message_add_tail(&req->xfer[0], &req->msg);
- mutex_lock(&ts->lock);
- ads7846_stop(ts);
- status = spi_sync(spi, &req->msg);
- ads7846_restart(ts);
- mutex_unlock(&ts->lock);
+ scoped_guard(mutex, &ts->lock) {
+ ads7846_stop(ts);
+ status = spi_sync(spi, &req->msg);
+ ads7846_restart(ts);
+ }
if (status == 0) {
/* BE12 value, then padding */
@@ -467,7 +460,6 @@ static int ads7845_read12_ser(struct device *dev, unsigned command)
status &= 0x0fff;
}
- kfree(req);
return status;
}
@@ -966,7 +958,7 @@ static int ads7846_suspend(struct device *dev)
{
struct ads7846 *ts = dev_get_drvdata(dev);
- mutex_lock(&ts->lock);
+ guard(mutex)(&ts->lock);
if (!ts->suspended) {
@@ -979,8 +971,6 @@ static int ads7846_suspend(struct device *dev)
ts->suspended = true;
}
- mutex_unlock(&ts->lock);
-
return 0;
}
@@ -988,7 +978,7 @@ static int ads7846_resume(struct device *dev)
{
struct ads7846 *ts = dev_get_drvdata(dev);
- mutex_lock(&ts->lock);
+ guard(mutex)(&ts->lock);
if (ts->suspended) {
@@ -1001,8 +991,6 @@ static int ads7846_resume(struct device *dev)
__ads7846_enable(ts);
}
- mutex_unlock(&ts->lock);
-
return 0;
}
diff --git a/drivers/input/touchscreen/apple_z2.c b/drivers/input/touchscreen/apple_z2.c
new file mode 100644
index 000000000000..271ababf0ad5
--- /dev/null
+++ b/drivers/input/touchscreen/apple_z2.c
@@ -0,0 +1,481 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Apple Z2 touchscreen driver
+ *
+ * Copyright (C) The Asahi Linux Contributors
+ */
+
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/input.h>
+#include <linux/input/mt.h>
+#include <linux/input/touchscreen.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/spi/spi.h>
+#include <linux/unaligned.h>
+
+#define APPLE_Z2_NUM_FINGERS_OFFSET 16
+#define APPLE_Z2_FINGERS_OFFSET 24
+#define APPLE_Z2_TOUCH_STARTED 3
+#define APPLE_Z2_TOUCH_MOVED 4
+#define APPLE_Z2_CMD_READ_INTERRUPT_DATA 0xEB
+#define APPLE_Z2_REPLY_INTERRUPT_DATA 0xE1
+#define APPLE_Z2_HBPP_CMD_BLOB 0x3001
+#define APPLE_Z2_FW_MAGIC 0x5746325A
+#define LOAD_COMMAND_INIT_PAYLOAD 0
+#define LOAD_COMMAND_SEND_BLOB 1
+#define LOAD_COMMAND_SEND_CALIBRATION 2
+#define CAL_PROP_NAME "apple,z2-cal-blob"
+
+struct apple_z2 {
+ struct spi_device *spidev;
+ struct gpio_desc *reset_gpio;
+ struct input_dev *input_dev;
+ struct completion boot_irq;
+ bool booted;
+ int index_parity;
+ struct touchscreen_properties props;
+ const char *fw_name;
+ u8 *tx_buf;
+ u8 *rx_buf;
+};
+
+struct apple_z2_finger {
+ u8 finger;
+ u8 state;
+ __le16 unknown2;
+ __le16 abs_x;
+ __le16 abs_y;
+ __le16 rel_x;
+ __le16 rel_y;
+ __le16 tool_major;
+ __le16 tool_minor;
+ __le16 orientation;
+ __le16 touch_major;
+ __le16 touch_minor;
+ __le16 unused[2];
+ __le16 pressure;
+ __le16 multi;
+} __packed;
+
+struct apple_z2_hbpp_blob_hdr {
+ __le16 cmd;
+ __le16 len;
+ __le32 addr;
+ __le16 checksum;
+};
+
+struct apple_z2_fw_hdr {
+ __le32 magic;
+ __le32 version;
+};
+
+struct apple_z2_read_interrupt_cmd {
+ u8 cmd;
+ u8 counter;
+ u8 unused[12];
+ __le16 checksum;
+};
+
+static void apple_z2_parse_touches(struct apple_z2 *z2,
+ const u8 *msg, size_t msg_len)
+{
+ int i;
+ int nfingers;
+ int slot;
+ int slot_valid;
+ struct apple_z2_finger *fingers;
+
+ if (msg_len <= APPLE_Z2_NUM_FINGERS_OFFSET)
+ return;
+ nfingers = msg[APPLE_Z2_NUM_FINGERS_OFFSET];
+ fingers = (struct apple_z2_finger *)(msg + APPLE_Z2_FINGERS_OFFSET);
+ for (i = 0; i < nfingers; i++) {
+ slot = input_mt_get_slot_by_key(z2->input_dev, fingers[i].finger);
+ if (slot < 0) {
+ dev_warn(&z2->spidev->dev, "unable to get slot for finger\n");
+ continue;
+ }
+ slot_valid = fingers[i].state == APPLE_Z2_TOUCH_STARTED ||
+ fingers[i].state == APPLE_Z2_TOUCH_MOVED;
+ input_mt_slot(z2->input_dev, slot);
+ if (!input_mt_report_slot_state(z2->input_dev, MT_TOOL_FINGER, slot_valid))
+ continue;
+ touchscreen_report_pos(z2->input_dev, &z2->props,
+ le16_to_cpu(fingers[i].abs_x),
+ le16_to_cpu(fingers[i].abs_y),
+ true);
+ input_report_abs(z2->input_dev, ABS_MT_WIDTH_MAJOR,
+ le16_to_cpu(fingers[i].tool_major));
+ input_report_abs(z2->input_dev, ABS_MT_WIDTH_MINOR,
+ le16_to_cpu(fingers[i].tool_minor));
+ input_report_abs(z2->input_dev, ABS_MT_ORIENTATION,
+ le16_to_cpu(fingers[i].orientation));
+ input_report_abs(z2->input_dev, ABS_MT_TOUCH_MAJOR,
+ le16_to_cpu(fingers[i].touch_major));
+ input_report_abs(z2->input_dev, ABS_MT_TOUCH_MINOR,
+ le16_to_cpu(fingers[i].touch_minor));
+ }
+ input_mt_sync_frame(z2->input_dev);
+ input_sync(z2->input_dev);
+}
+
+static int apple_z2_read_packet(struct apple_z2 *z2)
+{
+ struct apple_z2_read_interrupt_cmd *len_cmd = (void *)z2->tx_buf;
+ struct spi_transfer xfer;
+ int error;
+ size_t pkt_len;
+
+ memset(&xfer, 0, sizeof(xfer));
+ len_cmd->cmd = APPLE_Z2_CMD_READ_INTERRUPT_DATA;
+ len_cmd->counter = z2->index_parity + 1;
+ len_cmd->checksum =
+ cpu_to_le16(APPLE_Z2_CMD_READ_INTERRUPT_DATA + len_cmd->counter);
+ z2->index_parity = !z2->index_parity;
+ xfer.tx_buf = z2->tx_buf;
+ xfer.rx_buf = z2->rx_buf;
+ xfer.len = sizeof(*len_cmd);
+
+ error = spi_sync_transfer(z2->spidev, &xfer, 1);
+ if (error)
+ return error;
+
+ if (z2->rx_buf[0] != APPLE_Z2_REPLY_INTERRUPT_DATA)
+ return 0;
+
+ pkt_len = (get_unaligned_le16(z2->rx_buf + 1) + 8) & 0xfffffffc;
+
+ error = spi_read(z2->spidev, z2->rx_buf, pkt_len);
+ if (error)
+ return error;
+
+ apple_z2_parse_touches(z2, z2->rx_buf + 5, pkt_len - 5);
+
+ return 0;
+}
+
+static irqreturn_t apple_z2_irq(int irq, void *data)
+{
+ struct apple_z2 *z2 = data;
+
+ if (unlikely(!z2->booted))
+ complete(&z2->boot_irq);
+ else
+ apple_z2_read_packet(z2);
+
+ return IRQ_HANDLED;
+}
+
+/* Build calibration blob, caller is responsible for freeing the blob data. */
+static const u8 *apple_z2_build_cal_blob(struct apple_z2 *z2,
+ u32 address, size_t *size)
+{
+ u8 *cal_data;
+ int cal_size;
+ size_t blob_size;
+ u32 checksum;
+ u16 checksum_hdr;
+ int i;
+ struct apple_z2_hbpp_blob_hdr *hdr;
+ int error;
+
+ if (!device_property_present(&z2->spidev->dev, CAL_PROP_NAME))
+ return NULL;
+
+ cal_size = device_property_count_u8(&z2->spidev->dev, CAL_PROP_NAME);
+ if (cal_size < 0)
+ return ERR_PTR(cal_size);
+
+ blob_size = sizeof(struct apple_z2_hbpp_blob_hdr) + cal_size + sizeof(__le32);
+ u8 *blob_data __free(kfree) = kzalloc(blob_size, GFP_KERNEL);
+ if (!blob_data)
+ return ERR_PTR(-ENOMEM);
+
+ hdr = (struct apple_z2_hbpp_blob_hdr *)blob_data;
+ hdr->cmd = cpu_to_le16(APPLE_Z2_HBPP_CMD_BLOB);
+ hdr->len = cpu_to_le16(round_up(cal_size, 4) / 4);
+ hdr->addr = cpu_to_le32(address);
+
+ checksum_hdr = 0;
+ for (i = 2; i < 8; i++)
+ checksum_hdr += blob_data[i];
+ hdr->checksum = cpu_to_le16(checksum_hdr);
+
+ cal_data = blob_data + sizeof(struct apple_z2_hbpp_blob_hdr);
+ error = device_property_read_u8_array(&z2->spidev->dev, CAL_PROP_NAME,
+ cal_data, cal_size);
+ if (error)
+ return ERR_PTR(error);
+
+ checksum = 0;
+ for (i = 0; i < cal_size; i++)
+ checksum += cal_data[i];
+ put_unaligned_le32(checksum, cal_data + cal_size);
+
+ *size = blob_size;
+ return no_free_ptr(blob_data);
+}
+
+static int apple_z2_send_firmware_blob(struct apple_z2 *z2, const u8 *data,
+ u32 size, bool init)
+{
+ struct spi_message msg;
+ struct spi_transfer blob_xfer, ack_xfer;
+ int error;
+
+ z2->tx_buf[0] = 0x1a;
+ z2->tx_buf[1] = 0xa1;
+
+ spi_message_init(&msg);
+ memset(&blob_xfer, 0, sizeof(blob_xfer));
+ memset(&ack_xfer, 0, sizeof(ack_xfer));
+
+ blob_xfer.tx_buf = data;
+ blob_xfer.len = size;
+ blob_xfer.bits_per_word = init ? 8 : 16;
+ spi_message_add_tail(&blob_xfer, &msg);
+
+ ack_xfer.tx_buf = z2->tx_buf;
+ ack_xfer.len = 2;
+ spi_message_add_tail(&ack_xfer, &msg);
+
+ reinit_completion(&z2->boot_irq);
+ error = spi_sync(z2->spidev, &msg);
+ if (error)
+ return error;
+
+ /* Irq only happens sometimes, but the thing boots reliably nonetheless */
+ wait_for_completion_timeout(&z2->boot_irq, msecs_to_jiffies(20));
+
+ return 0;
+}
+
+static int apple_z2_upload_firmware(struct apple_z2 *z2)
+{
+ const struct apple_z2_fw_hdr *fw_hdr;
+ size_t fw_idx = sizeof(struct apple_z2_fw_hdr);
+ int error;
+ u32 load_cmd;
+ u32 address;
+ bool init;
+ size_t size;
+
+ const struct firmware *fw __free(firmware) = NULL;
+ error = request_firmware(&fw, z2->fw_name, &z2->spidev->dev);
+ if (error) {
+ dev_err(&z2->spidev->dev, "unable to load firmware\n");
+ return error;
+ }
+
+ fw_hdr = (const struct apple_z2_fw_hdr *)fw->data;
+ if (le32_to_cpu(fw_hdr->magic) != APPLE_Z2_FW_MAGIC || le32_to_cpu(fw_hdr->version) != 1) {
+ dev_err(&z2->spidev->dev, "invalid firmware header\n");
+ return -EINVAL;
+ }
+
+ /*
+ * This will interrupt the upload half-way if the file is malformed
+ * As the device has no non-volatile storage to corrupt, and gets reset
+ * on boot anyway, this is fine.
+ */
+ while (fw_idx < fw->size) {
+ if (fw->size - fw_idx < 8) {
+ dev_err(&z2->spidev->dev, "firmware malformed\n");
+ return -EINVAL;
+ }
+
+ load_cmd = le32_to_cpup((__force __le32 *)(fw->data + fw_idx));
+ fw_idx += sizeof(u32);
+ if (load_cmd == LOAD_COMMAND_INIT_PAYLOAD || load_cmd == LOAD_COMMAND_SEND_BLOB) {
+ size = le32_to_cpup((__force __le32 *)(fw->data + fw_idx));
+ fw_idx += sizeof(u32);
+ if (fw->size - fw_idx < size) {
+ dev_err(&z2->spidev->dev, "firmware malformed\n");
+ return -EINVAL;
+ }
+ init = load_cmd == LOAD_COMMAND_INIT_PAYLOAD;
+ error = apple_z2_send_firmware_blob(z2, fw->data + fw_idx,
+ size, init);
+ if (error)
+ return error;
+ fw_idx += size;
+ } else if (load_cmd == LOAD_COMMAND_SEND_CALIBRATION) {
+ address = le32_to_cpup((__force __le32 *)(fw->data + fw_idx));
+ fw_idx += sizeof(u32);
+
+ const u8 *data __free(kfree) =
+ apple_z2_build_cal_blob(z2, address, &size);
+ if (IS_ERR(data))
+ return PTR_ERR(data);
+
+ if (data) {
+ error = apple_z2_send_firmware_blob(z2, data, size, false);
+ if (error)
+ return error;
+ }
+ } else {
+ dev_err(&z2->spidev->dev, "firmware malformed\n");
+ return -EINVAL;
+ }
+ fw_idx = round_up(fw_idx, 4);
+ }
+
+
+ z2->booted = true;
+ apple_z2_read_packet(z2);
+ return 0;
+}
+
+static int apple_z2_boot(struct apple_z2 *z2)
+{
+ int error;
+
+ reinit_completion(&z2->boot_irq);
+ enable_irq(z2->spidev->irq);
+ gpiod_set_value(z2->reset_gpio, 0);
+ if (!wait_for_completion_timeout(&z2->boot_irq, msecs_to_jiffies(20)))
+ return -ETIMEDOUT;
+
+ error = apple_z2_upload_firmware(z2);
+ if (error) {
+ gpiod_set_value(z2->reset_gpio, 1);
+ disable_irq(z2->spidev->irq);
+ return error;
+ }
+
+ return 0;
+}
+
+static int apple_z2_probe(struct spi_device *spi)
+{
+ struct device *dev = &spi->dev;
+ struct apple_z2 *z2;
+ int error;
+
+ z2 = devm_kzalloc(dev, sizeof(*z2), GFP_KERNEL);
+ if (!z2)
+ return -ENOMEM;
+
+ z2->tx_buf = devm_kzalloc(dev, sizeof(struct apple_z2_read_interrupt_cmd), GFP_KERNEL);
+ if (!z2->tx_buf)
+ return -ENOMEM;
+ /* 4096 will end up being rounded up to 8192 due to devres header */
+ z2->rx_buf = devm_kzalloc(dev, 4000, GFP_KERNEL);
+ if (!z2->rx_buf)
+ return -ENOMEM;
+
+ z2->spidev = spi;
+ init_completion(&z2->boot_irq);
+ spi_set_drvdata(spi, z2);
+
+ /* Reset the device on boot */
+ z2->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(z2->reset_gpio))
+ return dev_err_probe(dev, PTR_ERR(z2->reset_gpio), "unable to get reset\n");
+
+ error = devm_request_threaded_irq(dev, z2->spidev->irq, NULL, apple_z2_irq,
+ IRQF_ONESHOT | IRQF_NO_AUTOEN,
+ "apple-z2-irq", z2);
+ if (error)
+ return dev_err_probe(dev, error, "unable to request irq\n");
+
+ error = device_property_read_string(dev, "firmware-name", &z2->fw_name);
+ if (error)
+ return dev_err_probe(dev, error, "unable to get firmware name\n");
+
+ z2->input_dev = devm_input_allocate_device(dev);
+ if (!z2->input_dev)
+ return -ENOMEM;
+
+ z2->input_dev->name = (char *)spi_get_device_id(spi)->driver_data;
+ z2->input_dev->phys = "apple_z2";
+ z2->input_dev->id.bustype = BUS_SPI;
+
+ /* Allocate the axes before setting from DT */
+ input_set_abs_params(z2->input_dev, ABS_MT_POSITION_X, 0, 0, 0, 0);
+ input_set_abs_params(z2->input_dev, ABS_MT_POSITION_Y, 0, 0, 0, 0);
+ touchscreen_parse_properties(z2->input_dev, true, &z2->props);
+ input_abs_set_res(z2->input_dev, ABS_MT_POSITION_X, 100);
+ input_abs_set_res(z2->input_dev, ABS_MT_POSITION_Y, 100);
+ input_set_abs_params(z2->input_dev, ABS_MT_WIDTH_MAJOR, 0, 65535, 0, 0);
+ input_set_abs_params(z2->input_dev, ABS_MT_WIDTH_MINOR, 0, 65535, 0, 0);
+ input_set_abs_params(z2->input_dev, ABS_MT_TOUCH_MAJOR, 0, 65535, 0, 0);
+ input_set_abs_params(z2->input_dev, ABS_MT_TOUCH_MINOR, 0, 65535, 0, 0);
+ input_set_abs_params(z2->input_dev, ABS_MT_ORIENTATION, -32768, 32767, 0, 0);
+
+ error = input_mt_init_slots(z2->input_dev, 256, INPUT_MT_DIRECT);
+ if (error)
+ return dev_err_probe(dev, error, "unable to initialize multitouch slots\n");
+
+ error = input_register_device(z2->input_dev);
+ if (error)
+ return dev_err_probe(dev, error, "unable to register input device\n");
+
+ /* Wait for device reset to finish */
+ usleep_range(5000, 10000);
+ error = apple_z2_boot(z2);
+ if (error)
+ return error;
+
+ return 0;
+}
+
+static void apple_z2_shutdown(struct spi_device *spi)
+{
+ struct apple_z2 *z2 = spi_get_drvdata(spi);
+
+ disable_irq(z2->spidev->irq);
+ gpiod_direction_output(z2->reset_gpio, 1);
+ z2->booted = false;
+}
+
+static int apple_z2_suspend(struct device *dev)
+{
+ apple_z2_shutdown(to_spi_device(dev));
+
+ return 0;
+}
+
+static int apple_z2_resume(struct device *dev)
+{
+ struct apple_z2 *z2 = spi_get_drvdata(to_spi_device(dev));
+
+ return apple_z2_boot(z2);
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(apple_z2_pm, apple_z2_suspend, apple_z2_resume);
+
+static const struct of_device_id apple_z2_of_match[] = {
+ { .compatible = "apple,j293-touchbar" },
+ { .compatible = "apple,j493-touchbar" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, apple_z2_of_match);
+
+static struct spi_device_id apple_z2_of_id[] = {
+ { .name = "j293-touchbar", .driver_data = (kernel_ulong_t)"MacBookPro17,1 Touch Bar" },
+ { .name = "j493-touchbar", .driver_data = (kernel_ulong_t)"Mac14,7 Touch Bar" },
+ {}
+};
+MODULE_DEVICE_TABLE(spi, apple_z2_of_id);
+
+static struct spi_driver apple_z2_driver = {
+ .driver = {
+ .name = "apple-z2",
+ .pm = pm_sleep_ptr(&apple_z2_pm),
+ .of_match_table = apple_z2_of_match,
+ .probe_type = PROBE_PREFER_ASYNCHRONOUS,
+ },
+ .id_table = apple_z2_of_id,
+ .probe = apple_z2_probe,
+ .remove = apple_z2_shutdown,
+};
+
+module_spi_driver(apple_z2_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_FIRMWARE("apple/dfrmtfw-*.bin");
+MODULE_DESCRIPTION("Apple Z2 touchscreens driver");
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 3ddabc5a2c99..f21bf2844112 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -19,6 +19,7 @@
#include <linux/firmware.h>
#include <linux/i2c.h>
#include <linux/input/mt.h>
+#include <linux/input/touchscreen.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/of.h>
@@ -274,8 +275,8 @@ struct mxt_cfg {
off_t raw_pos;
u8 *mem;
- size_t mem_size;
- int start_ofs;
+ u16 mem_size;
+ u16 start_ofs;
struct mxt_info info;
};
@@ -355,6 +356,8 @@ struct mxt_data {
enum mxt_suspend_mode suspend_mode;
u32 wakeup_method;
+
+ struct touchscreen_properties prop;
};
struct mxt_vb2_buffer {
@@ -710,12 +713,11 @@ static int __mxt_write_reg(struct i2c_client *client, u16 reg, u16 len,
const void *val)
{
bool retried = false;
- u8 *buf;
- size_t count;
+ size_t count = len + 2;
+ int error;
int ret;
- count = len + 2;
- buf = kmalloc(count, GFP_KERNEL);
+ u8 *buf __free(kfree) = kmalloc(count, GFP_KERNEL);
if (!buf)
return -ENOMEM;
@@ -725,20 +727,17 @@ static int __mxt_write_reg(struct i2c_client *client, u16 reg, u16 len,
retry:
ret = i2c_master_send(client, buf, count);
- if (ret == count) {
- ret = 0;
- } else if (!retried && mxt_wakeup_toggle(client, true, true)) {
+ if (ret == count)
+ return 0;
+
+ if (!retried && mxt_wakeup_toggle(client, true, true)) {
retried = true;
goto retry;
- } else {
- if (ret >= 0)
- ret = -EIO;
- dev_err(&client->dev, "%s: i2c send failed (%d)\n",
- __func__, ret);
}
- kfree(buf);
- return ret;
+ error = ret < 0 ? ret : -EIO;
+ dev_err(&client->dev, "%s: i2c send failed (%d)\n", __func__, error);
+ return error;
}
static int mxt_write_reg(struct i2c_client *client, u16 reg, u8 val)
@@ -888,8 +887,7 @@ static void mxt_proc_t9_message(struct mxt_data *data, u8 *message)
/* Touch active */
input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, 1);
- input_report_abs(input_dev, ABS_MT_POSITION_X, x);
- input_report_abs(input_dev, ABS_MT_POSITION_Y, y);
+ touchscreen_report_pos(input_dev, &data->prop, x, y, true);
input_report_abs(input_dev, ABS_MT_PRESSURE, amplitude);
input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, area);
} else {
@@ -1010,8 +1008,7 @@ static void mxt_proc_t100_message(struct mxt_data *data, u8 *message)
id, type, x, y, major, pressure, orientation);
input_mt_report_slot_state(input_dev, tool, 1);
- input_report_abs(input_dev, ABS_MT_POSITION_X, x);
- input_report_abs(input_dev, ABS_MT_POSITION_Y, y);
+ touchscreen_report_pos(input_dev, &data->prop, x, y, true);
input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, major);
input_report_abs(input_dev, ABS_MT_PRESSURE, pressure);
input_report_abs(input_dev, ABS_MT_DISTANCE, distance);
@@ -1476,7 +1473,7 @@ static int mxt_prepare_cfg_mem(struct mxt_data *data, struct mxt_cfg *cfg)
}
cfg->raw_pos += offset;
- if (i > mxt_obj_size(object))
+ if (i >= mxt_obj_size(object))
continue;
byte_offset = reg + i - cfg->start_ofs;
@@ -1546,14 +1543,15 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *fw)
{
struct device *dev = &data->client->dev;
struct mxt_cfg cfg;
- int ret;
+ int error;
int offset;
int i;
u32 info_crc, config_crc, calculated_crc;
u16 crc_start = 0;
/* Make zero terminated copy of the OBP_RAW file */
- cfg.raw = kmemdup_nul(fw->data, fw->size, GFP_KERNEL);
+ u8 *raw_buf __free(kfree) = cfg.raw = kmemdup_nul(fw->data, fw->size,
+ GFP_KERNEL);
if (!cfg.raw)
return -ENOMEM;
@@ -1563,21 +1561,17 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *fw)
if (strncmp(cfg.raw, MXT_CFG_MAGIC, strlen(MXT_CFG_MAGIC))) {
dev_err(dev, "Unrecognised config file\n");
- ret = -EINVAL;
- goto release_raw;
+ return -EINVAL;
}
cfg.raw_pos = strlen(MXT_CFG_MAGIC);
/* Load information block and check */
for (i = 0; i < sizeof(struct mxt_info); i++) {
- ret = sscanf(cfg.raw + cfg.raw_pos, "%hhx%n",
- (unsigned char *)&cfg.info + i,
- &offset);
- if (ret != 1) {
+ if (sscanf(cfg.raw + cfg.raw_pos, "%hhx%n",
+ (unsigned char *)&cfg.info + i, &offset) != 1) {
dev_err(dev, "Bad format\n");
- ret = -EINVAL;
- goto release_raw;
+ return -EINVAL;
}
cfg.raw_pos += offset;
@@ -1585,30 +1579,24 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *fw)
if (cfg.info.family_id != data->info->family_id) {
dev_err(dev, "Family ID mismatch!\n");
- ret = -EINVAL;
- goto release_raw;
+ return -EINVAL;
}
if (cfg.info.variant_id != data->info->variant_id) {
dev_err(dev, "Variant ID mismatch!\n");
- ret = -EINVAL;
- goto release_raw;
+ return -EINVAL;
}
/* Read CRCs */
- ret = sscanf(cfg.raw + cfg.raw_pos, "%x%n", &info_crc, &offset);
- if (ret != 1) {
+ if (sscanf(cfg.raw + cfg.raw_pos, "%x%n", &info_crc, &offset) != 1) {
dev_err(dev, "Bad format: failed to parse Info CRC\n");
- ret = -EINVAL;
- goto release_raw;
+ return -EINVAL;
}
cfg.raw_pos += offset;
- ret = sscanf(cfg.raw + cfg.raw_pos, "%x%n", &config_crc, &offset);
- if (ret != 1) {
+ if (sscanf(cfg.raw + cfg.raw_pos, "%x%n", &config_crc, &offset) != 1) {
dev_err(dev, "Bad format: failed to parse Config CRC\n");
- ret = -EINVAL;
- goto release_raw;
+ return -EINVAL;
}
cfg.raw_pos += offset;
@@ -1624,8 +1612,7 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *fw)
} else if (config_crc == data->config_crc) {
dev_dbg(dev, "Config CRC 0x%06X: OK\n",
data->config_crc);
- ret = 0;
- goto release_raw;
+ return 0;
} else {
dev_info(dev, "Config CRC 0x%06X: does not match file 0x%06X\n",
data->config_crc, config_crc);
@@ -1640,16 +1627,22 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *fw)
cfg.start_ofs = MXT_OBJECT_START +
data->info->object_num * sizeof(struct mxt_object) +
MXT_INFO_CHECKSUM_SIZE;
- cfg.mem_size = data->mem_size - cfg.start_ofs;
- cfg.mem = kzalloc(cfg.mem_size, GFP_KERNEL);
- if (!cfg.mem) {
- ret = -ENOMEM;
- goto release_raw;
+
+ if (data->mem_size <= cfg.start_ofs) {
+ dev_err(dev, "Memory size too small: %u < %u\n",
+ data->mem_size, cfg.start_ofs);
+ return -EINVAL;
}
- ret = mxt_prepare_cfg_mem(data, &cfg);
- if (ret)
- goto release_mem;
+ cfg.mem_size = data->mem_size - cfg.start_ofs;
+
+ u8 *mem_buf __free(kfree) = cfg.mem = kzalloc(cfg.mem_size, GFP_KERNEL);
+ if (!cfg.mem)
+ return -ENOMEM;
+
+ error = mxt_prepare_cfg_mem(data, &cfg);
+ if (error)
+ return error;
/* Calculate crc of the received configs (not the raw config file) */
if (data->T71_address)
@@ -1669,30 +1662,26 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *fw)
calculated_crc, config_crc);
}
- ret = mxt_upload_cfg_mem(data, &cfg);
- if (ret)
- goto release_mem;
+ error = mxt_upload_cfg_mem(data, &cfg);
+ if (error)
+ return error;
mxt_update_crc(data, MXT_COMMAND_BACKUPNV, MXT_BACKUP_VALUE);
- ret = mxt_check_retrigen(data);
- if (ret)
- goto release_mem;
+ error = mxt_check_retrigen(data);
+ if (error)
+ return error;
- ret = mxt_soft_reset(data);
- if (ret)
- goto release_mem;
+ error = mxt_soft_reset(data);
+ if (error)
+ return error;
dev_info(dev, "Config successfully updated\n");
/* T7 config may have changed */
mxt_init_t7_power_cfg(data);
-release_mem:
- kfree(cfg.mem);
-release_raw:
- kfree(cfg.raw);
- return ret;
+ return 0;
}
static void mxt_free_input_device(struct mxt_data *data)
@@ -1856,7 +1845,6 @@ static int mxt_read_info_block(struct mxt_data *data)
struct i2c_client *client = data->client;
int error;
size_t size;
- void *id_buf, *buf;
uint8_t num_objects;
u32 calculated_crc;
u8 *crc_ptr;
@@ -1867,24 +1855,23 @@ static int mxt_read_info_block(struct mxt_data *data)
/* Read 7-byte ID information block starting at address 0 */
size = sizeof(struct mxt_info);
- id_buf = kzalloc(size, GFP_KERNEL);
+ void *id_buf __free(kfree) = kzalloc(size, GFP_KERNEL);
if (!id_buf)
return -ENOMEM;
error = __mxt_read_reg(client, 0, size, id_buf);
if (error)
- goto err_free_mem;
+ return error;
/* Resize buffer to give space for rest of info block */
num_objects = ((struct mxt_info *)id_buf)->object_num;
size += (num_objects * sizeof(struct mxt_object))
+ MXT_INFO_CHECKSUM_SIZE;
- buf = krealloc(id_buf, size, GFP_KERNEL);
- if (!buf) {
- error = -ENOMEM;
- goto err_free_mem;
- }
+ void *buf = krealloc(id_buf, size, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
id_buf = buf;
/* Read rest of info block */
@@ -1892,7 +1879,7 @@ static int mxt_read_info_block(struct mxt_data *data)
size - MXT_OBJECT_START,
id_buf + MXT_OBJECT_START);
if (error)
- goto err_free_mem;
+ return error;
/* Extract & calculate checksum */
crc_ptr = id_buf + size - MXT_INFO_CHECKSUM_SIZE;
@@ -1909,12 +1896,11 @@ static int mxt_read_info_block(struct mxt_data *data)
dev_err(&client->dev,
"Info Block CRC error calculated=0x%06X read=0x%06X\n",
calculated_crc, data->info_crc);
- error = -EIO;
- goto err_free_mem;
+ return -EIO;
}
- data->raw_info_block = id_buf;
- data->info = (struct mxt_info *)id_buf;
+ data->raw_info_block = no_free_ptr(id_buf);
+ data->info = (struct mxt_info *)data->raw_info_block;
dev_info(&client->dev,
"Family: %u Variant: %u Firmware V%u.%u.%02X Objects: %u\n",
@@ -1923,20 +1909,18 @@ static int mxt_read_info_block(struct mxt_data *data)
data->info->build, data->info->object_num);
/* Parse object table information */
- error = mxt_parse_object_table(data, id_buf + MXT_OBJECT_START);
+ error = mxt_parse_object_table(data,
+ data->raw_info_block + MXT_OBJECT_START);
if (error) {
dev_err(&client->dev, "Error %d parsing object table\n", error);
mxt_free_object_table(data);
return error;
}
- data->object_table = (struct mxt_object *)(id_buf + MXT_OBJECT_START);
+ data->object_table =
+ (struct mxt_object *)(data->raw_info_block + MXT_OBJECT_START);
return 0;
-
-err_free_mem:
- kfree(id_buf);
- return error;
}
static int mxt_read_t9_resolution(struct mxt_data *data)
@@ -2212,6 +2196,8 @@ static int mxt_initialize_input_device(struct mxt_data *data)
0, 255, 0, 0);
}
+ touchscreen_parse_properties(input_dev, true, &data->prop);
+
/* For T15 and T97 Key Array */
if (data->T15_reportid_min || data->T97_reportid_min) {
for (i = 0; i < data->t15_num_keys; i++)
@@ -2535,8 +2521,6 @@ fault:
static const struct vb2_ops mxt_queue_ops = {
.queue_setup = mxt_queue_setup,
.buf_queue = mxt_buffer_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static const struct vb2_queue mxt_queue = {
@@ -2913,70 +2897,38 @@ static int mxt_check_firmware_format(struct device *dev,
return -EINVAL;
}
-static int mxt_load_fw(struct device *dev, const char *fn)
+static int mxt_flash_fw(struct mxt_data *data, const struct firmware *fw)
{
- struct mxt_data *data = dev_get_drvdata(dev);
- const struct firmware *fw = NULL;
+ struct device *dev = &data->client->dev;
unsigned int frame_size;
unsigned int pos = 0;
unsigned int retry = 0;
unsigned int frame = 0;
- int ret;
-
- ret = request_firmware(&fw, fn, dev);
- if (ret) {
- dev_err(dev, "Unable to open firmware %s\n", fn);
- return ret;
- }
-
- /* Check for incorrect enc file */
- ret = mxt_check_firmware_format(dev, fw);
- if (ret)
- goto release_firmware;
-
- if (!data->in_bootloader) {
- /* Change to the bootloader mode */
- data->in_bootloader = true;
-
- ret = mxt_t6_command(data, MXT_COMMAND_RESET,
- MXT_BOOT_VALUE, false);
- if (ret)
- goto release_firmware;
-
- msleep(MXT_RESET_TIME);
-
- /* Do not need to scan since we know family ID */
- ret = mxt_lookup_bootloader_address(data, 0);
- if (ret)
- goto release_firmware;
-
- mxt_free_input_device(data);
- mxt_free_object_table(data);
- } else {
- enable_irq(data->irq);
- }
+ int error;
reinit_completion(&data->bl_completion);
- ret = mxt_check_bootloader(data, MXT_WAITING_BOOTLOAD_CMD, false);
- if (ret) {
+ error = mxt_check_bootloader(data, MXT_WAITING_BOOTLOAD_CMD, false);
+ if (error) {
/* Bootloader may still be unlocked from previous attempt */
- ret = mxt_check_bootloader(data, MXT_WAITING_FRAME_DATA, false);
- if (ret)
- goto disable_irq;
+ error = mxt_check_bootloader(data, MXT_WAITING_FRAME_DATA,
+ false);
+ if (error)
+ return error;
} else {
dev_info(dev, "Unlocking bootloader\n");
/* Unlock bootloader */
- ret = mxt_send_bootloader_cmd(data, true);
- if (ret)
- goto disable_irq;
+ error = mxt_send_bootloader_cmd(data, true);
+ if (error)
+ return error;
}
while (pos < fw->size) {
- ret = mxt_check_bootloader(data, MXT_WAITING_FRAME_DATA, true);
- if (ret)
- goto disable_irq;
+ error = mxt_check_bootloader(data, MXT_WAITING_FRAME_DATA,
+ true);
+ if (error)
+ return error;
frame_size = ((*(fw->data + pos) << 8) | *(fw->data + pos + 1));
@@ -2984,12 +2936,12 @@ static int mxt_load_fw(struct device *dev, const char *fn)
frame_size += 2;
/* Write one frame to device */
- ret = mxt_bootloader_write(data, fw->data + pos, frame_size);
- if (ret)
- goto disable_irq;
+ error = mxt_bootloader_write(data, fw->data + pos, frame_size);
+ if (error)
+ return error;
- ret = mxt_check_bootloader(data, MXT_FRAME_CRC_PASS, true);
- if (ret) {
+ error = mxt_check_bootloader(data, MXT_FRAME_CRC_PASS, true);
+ if (error) {
retry++;
/* Back off by 20ms per retry */
@@ -2997,7 +2949,7 @@ static int mxt_load_fw(struct device *dev, const char *fn)
if (retry > 20) {
dev_err(dev, "Retry count exceeded\n");
- goto disable_irq;
+ return error;
}
} else {
retry = 0;
@@ -3011,10 +2963,10 @@ static int mxt_load_fw(struct device *dev, const char *fn)
}
/* Wait for flash. */
- ret = mxt_wait_for_completion(data, &data->bl_completion,
- MXT_FW_RESET_TIME);
- if (ret)
- goto disable_irq;
+ error = mxt_wait_for_completion(data, &data->bl_completion,
+ MXT_FW_RESET_TIME);
+ if (error)
+ return error;
dev_dbg(dev, "Sent %d frames, %d bytes\n", frame, pos);
@@ -3024,14 +2976,56 @@ static int mxt_load_fw(struct device *dev, const char *fn)
* errors.
*/
mxt_wait_for_completion(data, &data->bl_completion, MXT_FW_RESET_TIME);
-
data->in_bootloader = false;
-disable_irq:
+ return 0;
+}
+
+static int mxt_load_fw(struct device *dev, const char *fn)
+{
+ struct mxt_data *data = dev_get_drvdata(dev);
+ int retval;
+ int error;
+
+ const struct firmware *fw __free(firmware) = NULL;
+ error = request_firmware(&fw, fn, dev);
+ if (error) {
+ dev_err(dev, "Unable to open firmware %s\n", fn);
+ return error;
+ }
+
+ /* Check for incorrect enc file */
+ error = mxt_check_firmware_format(dev, fw);
+ if (error)
+ return error;
+
+ if (!data->in_bootloader) {
+ /* Change to the bootloader mode */
+ data->in_bootloader = true;
+
+ error = mxt_t6_command(data, MXT_COMMAND_RESET,
+ MXT_BOOT_VALUE, false);
+ if (error)
+ return error;
+
+ msleep(MXT_RESET_TIME);
+
+ /* Do not need to scan since we know family ID */
+ error = mxt_lookup_bootloader_address(data, 0);
+ if (error)
+ return error;
+
+ mxt_free_input_device(data);
+ mxt_free_object_table(data);
+ } else {
+ enable_irq(data->irq);
+ }
+
+ retval = mxt_flash_fw(data, fw);
+
disable_irq(data->irq);
-release_firmware:
- release_firmware(fw);
- return ret;
+
+ return retval;
}
static ssize_t mxt_update_fw_store(struct device *dev,
@@ -3319,7 +3313,7 @@ static int mxt_probe(struct i2c_client *client)
if (data->reset_gpio) {
/* Wait a while and then de-assert the RESET GPIO line */
msleep(MXT_RESET_GPIO_TIME);
- gpiod_set_value(data->reset_gpio, 0);
+ gpiod_set_value_cansleep(data->reset_gpio, 0);
msleep(MXT_RESET_INVALID_CHG);
}
@@ -3374,12 +3368,10 @@ static int mxt_suspend(struct device *dev)
if (!input_dev)
return 0;
- mutex_lock(&input_dev->mutex);
-
- if (input_device_enabled(input_dev))
- mxt_stop(data);
-
- mutex_unlock(&input_dev->mutex);
+ scoped_guard(mutex, &input_dev->mutex) {
+ if (input_device_enabled(input_dev))
+ mxt_stop(data);
+ }
disable_irq(data->irq);
@@ -3397,12 +3389,10 @@ static int mxt_resume(struct device *dev)
enable_irq(data->irq);
- mutex_lock(&input_dev->mutex);
-
- if (input_device_enabled(input_dev))
- mxt_start(data);
-
- mutex_unlock(&input_dev->mutex);
+ scoped_guard(mutex, &input_dev->mutex) {
+ if (input_device_enabled(input_dev))
+ mxt_start(data);
+ }
return 0;
}
diff --git a/drivers/input/touchscreen/auo-pixcir-ts.c b/drivers/input/touchscreen/auo-pixcir-ts.c
index 363a4a1f1560..401b2264f585 100644
--- a/drivers/input/touchscreen/auo-pixcir-ts.c
+++ b/drivers/input/touchscreen/auo-pixcir-ts.c
@@ -415,9 +415,9 @@ static int auo_pixcir_suspend(struct device *dev)
struct i2c_client *client = to_i2c_client(dev);
struct auo_pixcir_ts *ts = i2c_get_clientdata(client);
struct input_dev *input = ts->input;
- int ret = 0;
+ int error;
- mutex_lock(&input->mutex);
+ guard(mutex)(&input->mutex);
/* when configured as wakeup source, device should always wake system
* therefore start device if necessary
@@ -425,21 +425,23 @@ static int auo_pixcir_suspend(struct device *dev)
if (device_may_wakeup(&client->dev)) {
/* need to start device if not open, to be wakeup source */
if (!input_device_enabled(input)) {
- ret = auo_pixcir_start(ts);
- if (ret)
- goto unlock;
+ error = auo_pixcir_start(ts);
+ if (error)
+ return error;
}
enable_irq_wake(client->irq);
- ret = auo_pixcir_power_mode(ts, AUO_PIXCIR_POWER_SLEEP);
+ error = auo_pixcir_power_mode(ts, AUO_PIXCIR_POWER_SLEEP);
+ if (error)
+ return error;
+
} else if (input_device_enabled(input)) {
- ret = auo_pixcir_stop(ts);
+ error = auo_pixcir_stop(ts);
+ if (error)
+ return error;
}
-unlock:
- mutex_unlock(&input->mutex);
-
- return ret;
+ return 0;
}
static int auo_pixcir_resume(struct device *dev)
@@ -447,29 +449,28 @@ static int auo_pixcir_resume(struct device *dev)
struct i2c_client *client = to_i2c_client(dev);
struct auo_pixcir_ts *ts = i2c_get_clientdata(client);
struct input_dev *input = ts->input;
- int ret = 0;
+ int error;
- mutex_lock(&input->mutex);
+ guard(mutex)(&input->mutex);
if (device_may_wakeup(&client->dev)) {
disable_irq_wake(client->irq);
/* need to stop device if it was not open on suspend */
if (!input_device_enabled(input)) {
- ret = auo_pixcir_stop(ts);
- if (ret)
- goto unlock;
+ error = auo_pixcir_stop(ts);
+ if (error)
+ return error;
}
/* device wakes automatically from SLEEP */
} else if (input_device_enabled(input)) {
- ret = auo_pixcir_start(ts);
+ error = auo_pixcir_start(ts);
+ if (error)
+ return error;
}
-unlock:
- mutex_unlock(&input->mutex);
-
- return ret;
+ return 0;
}
static DEFINE_SIMPLE_DEV_PM_OPS(auo_pixcir_pm_ops,
diff --git a/drivers/input/touchscreen/bu21029_ts.c b/drivers/input/touchscreen/bu21029_ts.c
index 686d0a6b1570..68d9cd55ceeb 100644
--- a/drivers/input/touchscreen/bu21029_ts.c
+++ b/drivers/input/touchscreen/bu21029_ts.c
@@ -209,7 +209,8 @@ static void bu21029_touch_report(struct bu21029_ts_data *bu21029, const u8 *buf)
static void bu21029_touch_release(struct timer_list *t)
{
- struct bu21029_ts_data *bu21029 = from_timer(bu21029, t, timer);
+ struct bu21029_ts_data *bu21029 = timer_container_of(bu21029, t,
+ timer);
input_report_abs(bu21029->in_dev, ABS_PRESSURE, 0);
input_report_key(bu21029->in_dev, BTN_TOUCH, 0);
@@ -325,7 +326,7 @@ static void bu21029_stop_chip(struct input_dev *dev)
struct bu21029_ts_data *bu21029 = input_get_drvdata(dev);
disable_irq(bu21029->client->irq);
- del_timer_sync(&bu21029->timer);
+ timer_delete_sync(&bu21029->timer);
bu21029_put_chip_in_reset(bu21029);
regulator_disable(bu21029->vdd);
@@ -415,10 +416,10 @@ static int bu21029_suspend(struct device *dev)
struct bu21029_ts_data *bu21029 = i2c_get_clientdata(i2c);
if (!device_may_wakeup(dev)) {
- mutex_lock(&bu21029->in_dev->mutex);
+ guard(mutex)(&bu21029->in_dev->mutex);
+
if (input_device_enabled(bu21029->in_dev))
bu21029_stop_chip(bu21029->in_dev);
- mutex_unlock(&bu21029->in_dev->mutex);
}
return 0;
@@ -430,10 +431,10 @@ static int bu21029_resume(struct device *dev)
struct bu21029_ts_data *bu21029 = i2c_get_clientdata(i2c);
if (!device_may_wakeup(dev)) {
- mutex_lock(&bu21029->in_dev->mutex);
+ guard(mutex)(&bu21029->in_dev->mutex);
+
if (input_device_enabled(bu21029->in_dev))
bu21029_start_chip(bu21029->in_dev);
- mutex_unlock(&bu21029->in_dev->mutex);
}
return 0;
diff --git a/drivers/input/touchscreen/chipone_icn8318.c b/drivers/input/touchscreen/chipone_icn8318.c
index d6876d10b252..1b10a757313c 100644
--- a/drivers/input/touchscreen/chipone_icn8318.c
+++ b/drivers/input/touchscreen/chipone_icn8318.c
@@ -152,10 +152,10 @@ static int icn8318_suspend(struct device *dev)
{
struct icn8318_data *data = i2c_get_clientdata(to_i2c_client(dev));
- mutex_lock(&data->input->mutex);
+ guard(mutex)(&data->input->mutex);
+
if (input_device_enabled(data->input))
icn8318_stop(data->input);
- mutex_unlock(&data->input->mutex);
return 0;
}
@@ -164,10 +164,10 @@ static int icn8318_resume(struct device *dev)
{
struct icn8318_data *data = i2c_get_clientdata(to_i2c_client(dev));
- mutex_lock(&data->input->mutex);
+ guard(mutex)(&data->input->mutex);
+
if (input_device_enabled(data->input))
icn8318_start(data->input);
- mutex_unlock(&data->input->mutex);
return 0;
}
diff --git a/drivers/input/touchscreen/cyttsp5.c b/drivers/input/touchscreen/cyttsp5.c
index eafe5a9b8964..47f4271395a6 100644
--- a/drivers/input/touchscreen/cyttsp5.c
+++ b/drivers/input/touchscreen/cyttsp5.c
@@ -580,7 +580,7 @@ static int cyttsp5_power_control(struct cyttsp5 *ts, bool on)
int rc;
SET_CMD_REPORT_TYPE(cmd[0], 0);
- SET_CMD_REPORT_ID(cmd[0], HID_POWER_SLEEP);
+ SET_CMD_REPORT_ID(cmd[0], state);
SET_CMD_OPCODE(cmd[1], HID_CMD_SET_POWER);
rc = cyttsp5_write(ts, HID_COMMAND_REG, cmd, sizeof(cmd));
@@ -870,13 +870,16 @@ static int cyttsp5_probe(struct device *dev, struct regmap *regmap, int irq,
ts->input->phys = ts->phys;
input_set_drvdata(ts->input, ts);
- /* Reset the gpio to be in a reset state */
+ /* Assert gpio to be in a reset state */
ts->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
if (IS_ERR(ts->reset_gpio)) {
error = PTR_ERR(ts->reset_gpio);
dev_err(dev, "Failed to request reset gpio, error %d\n", error);
return error;
}
+
+ fsleep(10); /* Ensure long-enough reset pulse (minimum 10us). */
+
gpiod_set_value_cansleep(ts->reset_gpio, 0);
/* Need a delay to have device up */
@@ -920,8 +923,8 @@ static int cyttsp5_i2c_probe(struct i2c_client *client)
regmap = devm_regmap_init_i2c(client, &config);
if (IS_ERR(regmap)) {
- dev_err(&client->dev, "regmap allocation failed: %ld\n",
- PTR_ERR(regmap));
+ dev_err(&client->dev, "regmap allocation failed: %pe\n",
+ regmap);
return PTR_ERR(regmap);
}
diff --git a/drivers/input/touchscreen/cyttsp_core.c b/drivers/input/touchscreen/cyttsp_core.c
index b8ce6012364c..012dfcae01cc 100644
--- a/drivers/input/touchscreen/cyttsp_core.c
+++ b/drivers/input/touchscreen/cyttsp_core.c
@@ -14,6 +14,7 @@
*/
#include <linux/delay.h>
+#include <linux/export.h>
#include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/input/touchscreen.h>
@@ -493,34 +494,30 @@ static int cyttsp_disable(struct cyttsp *ts)
static int cyttsp_suspend(struct device *dev)
{
struct cyttsp *ts = dev_get_drvdata(dev);
- int retval = 0;
+ int error;
- mutex_lock(&ts->input->mutex);
+ guard(mutex)(&ts->input->mutex);
if (input_device_enabled(ts->input)) {
- retval = cyttsp_disable(ts);
- if (retval == 0)
- ts->suspended = true;
+ error = cyttsp_disable(ts);
+ if (error)
+ return error;
}
- mutex_unlock(&ts->input->mutex);
-
- return retval;
+ ts->suspended = true;
+ return 0;
}
static int cyttsp_resume(struct device *dev)
{
struct cyttsp *ts = dev_get_drvdata(dev);
- mutex_lock(&ts->input->mutex);
+ guard(mutex)(&ts->input->mutex);
if (input_device_enabled(ts->input))
cyttsp_enable(ts);
ts->suspended = false;
-
- mutex_unlock(&ts->input->mutex);
-
return 0;
}
diff --git a/drivers/input/touchscreen/da9052_tsi.c b/drivers/input/touchscreen/da9052_tsi.c
index c2d3252f8466..a8e3d85eece7 100644
--- a/drivers/input/touchscreen/da9052_tsi.c
+++ b/drivers/input/touchscreen/da9052_tsi.c
@@ -232,7 +232,7 @@ static int da9052_ts_probe(struct platform_device *pdev)
if (!da9052)
return -EINVAL;
- tsi = kzalloc(sizeof(*tsi), GFP_KERNEL);
+ tsi = kzalloc_obj(*tsi);
input_dev = input_allocate_device();
if (!tsi || !input_dev) {
error = -ENOMEM;
diff --git a/drivers/input/touchscreen/dynapro.c b/drivers/input/touchscreen/dynapro.c
index fe626a226b85..943ba8c2fb6c 100644
--- a/drivers/input/touchscreen/dynapro.c
+++ b/drivers/input/touchscreen/dynapro.c
@@ -110,7 +110,7 @@ static int dynapro_connect(struct serio *serio, struct serio_driver *drv)
struct input_dev *input_dev;
int err;
- pdynapro = kzalloc(sizeof(*pdynapro), GFP_KERNEL);
+ pdynapro = kzalloc_obj(*pdynapro);
input_dev = input_allocate_device();
if (!pdynapro || !input_dev) {
err = -ENOMEM;
@@ -119,8 +119,8 @@ static int dynapro_connect(struct serio *serio, struct serio_driver *drv)
pdynapro->serio = serio;
pdynapro->dev = input_dev;
- snprintf(pdynapro->phys, sizeof(pdynapro->phys),
- "%s/input0", serio->phys);
+ scnprintf(pdynapro->phys, sizeof(pdynapro->phys),
+ "%s/input0", serio->phys);
input_dev->name = "Dynapro Serial TouchScreen";
input_dev->phys = pdynapro->phys;
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
index 0d7bf18e2508..d3b1177185a3 100644
--- a/drivers/input/touchscreen/edt-ft5x06.c
+++ b/drivers/input/touchscreen/edt-ft5x06.c
@@ -120,7 +120,6 @@ struct edt_ft5x06_ts_data {
struct regmap *regmap;
#if defined(CONFIG_DEBUG_FS)
- struct dentry *debug_dir;
u8 *raw_buffer;
size_t raw_bufsize;
#endif
@@ -381,16 +380,13 @@ static ssize_t edt_ft5x06_setting_show(struct device *dev,
container_of(dattr, struct edt_ft5x06_attribute, dattr);
u8 *field = (u8 *)tsdata + attr->field_offset;
unsigned int val;
- size_t count = 0;
- int error = 0;
+ int error;
u8 addr;
- mutex_lock(&tsdata->mutex);
+ guard(mutex)(&tsdata->mutex);
- if (tsdata->factory_mode) {
- error = -EIO;
- goto out;
- }
+ if (tsdata->factory_mode)
+ return -EIO;
switch (tsdata->version) {
case EDT_M06:
@@ -408,8 +404,7 @@ static ssize_t edt_ft5x06_setting_show(struct device *dev,
break;
default:
- error = -ENODEV;
- goto out;
+ return -ENODEV;
}
if (addr != NO_REGISTER) {
@@ -418,7 +413,7 @@ static ssize_t edt_ft5x06_setting_show(struct device *dev,
dev_err(&tsdata->client->dev,
"Failed to fetch attribute %s, error %d\n",
dattr->attr.name, error);
- goto out;
+ return error;
}
} else {
val = *field;
@@ -431,10 +426,7 @@ static ssize_t edt_ft5x06_setting_show(struct device *dev,
*field = val;
}
- count = sysfs_emit(buf, "%d\n", val);
-out:
- mutex_unlock(&tsdata->mutex);
- return error ?: count;
+ return sysfs_emit(buf, "%d\n", val);
}
static ssize_t edt_ft5x06_setting_store(struct device *dev,
@@ -450,21 +442,17 @@ static ssize_t edt_ft5x06_setting_store(struct device *dev,
int error;
u8 addr;
- mutex_lock(&tsdata->mutex);
+ guard(mutex)(&tsdata->mutex);
- if (tsdata->factory_mode) {
- error = -EIO;
- goto out;
- }
+ if (tsdata->factory_mode)
+ return -EIO;
error = kstrtouint(buf, 0, &val);
if (error)
- goto out;
+ return error;
- if (val < attr->limit_low || val > attr->limit_high) {
- error = -ERANGE;
- goto out;
- }
+ if (val < attr->limit_low || val > attr->limit_high)
+ return -ERANGE;
switch (tsdata->version) {
case EDT_M06:
@@ -482,8 +470,7 @@ static ssize_t edt_ft5x06_setting_store(struct device *dev,
break;
default:
- error = -ENODEV;
- goto out;
+ return -ENODEV;
}
if (addr != NO_REGISTER) {
@@ -492,14 +479,12 @@ static ssize_t edt_ft5x06_setting_store(struct device *dev,
dev_err(&tsdata->client->dev,
"Failed to update attribute %s, error: %d\n",
dattr->attr.name, error);
- goto out;
+ return error;
}
}
*field = val;
-out:
- mutex_unlock(&tsdata->mutex);
- return error ?: count;
+ return count;
}
/* m06, m09: range 0-31, m12: range 0-5 */
@@ -715,21 +700,17 @@ static int edt_ft5x06_debugfs_mode_get(void *data, u64 *mode)
static int edt_ft5x06_debugfs_mode_set(void *data, u64 mode)
{
struct edt_ft5x06_ts_data *tsdata = data;
- int retval = 0;
if (mode > 1)
return -ERANGE;
- mutex_lock(&tsdata->mutex);
-
- if (mode != tsdata->factory_mode) {
- retval = mode ? edt_ft5x06_factory_mode(tsdata) :
- edt_ft5x06_work_mode(tsdata);
- }
+ guard(mutex)(&tsdata->mutex);
- mutex_unlock(&tsdata->mutex);
+ if (mode == tsdata->factory_mode)
+ return 0;
- return retval;
+ return mode ? edt_ft5x06_factory_mode(tsdata) :
+ edt_ft5x06_work_mode(tsdata);
};
DEFINE_SIMPLE_ATTRIBUTE(debugfs_mode_fops, edt_ft5x06_debugfs_mode_get,
@@ -751,18 +732,16 @@ static ssize_t edt_ft5x06_debugfs_raw_data_read(struct file *file,
if (*off < 0 || *off >= tsdata->raw_bufsize)
return 0;
- mutex_lock(&tsdata->mutex);
+ guard(mutex)(&tsdata->mutex);
- if (!tsdata->factory_mode || !tsdata->raw_buffer) {
- error = -EIO;
- goto out;
- }
+ if (!tsdata->factory_mode || !tsdata->raw_buffer)
+ return -EIO;
error = regmap_write(tsdata->regmap, 0x08, 0x01);
if (error) {
dev_err(&client->dev,
"failed to write 0x08 register, error %d\n", error);
- goto out;
+ return error;
}
do {
@@ -772,7 +751,7 @@ static ssize_t edt_ft5x06_debugfs_raw_data_read(struct file *file,
dev_err(&client->dev,
"failed to read 0x08 register, error %d\n",
error);
- goto out;
+ return error;
}
if (val == 1)
@@ -782,8 +761,7 @@ static ssize_t edt_ft5x06_debugfs_raw_data_read(struct file *file,
if (retries == 0) {
dev_err(&client->dev,
"timed out waiting for register to settle\n");
- error = -ETIMEDOUT;
- goto out;
+ return -ETIMEDOUT;
}
rdbuf = tsdata->raw_buffer;
@@ -793,21 +771,17 @@ static ssize_t edt_ft5x06_debugfs_raw_data_read(struct file *file,
rdbuf[0] = i; /* column index */
error = regmap_bulk_read(tsdata->regmap, 0xf5, rdbuf, colbytes);
if (error)
- goto out;
+ return error;
rdbuf += colbytes;
}
read = min_t(size_t, count, tsdata->raw_bufsize - *off);
- if (copy_to_user(buf, tsdata->raw_buffer + *off, read)) {
- error = -EFAULT;
- goto out;
- }
+ if (copy_to_user(buf, tsdata->raw_buffer + *off, read))
+ return -EFAULT;
*off += read;
-out:
- mutex_unlock(&tsdata->mutex);
- return error ?: read;
+ return read;
};
static const struct file_operations debugfs_raw_data_fops = {
@@ -815,24 +789,25 @@ static const struct file_operations debugfs_raw_data_fops = {
.read = edt_ft5x06_debugfs_raw_data_read,
};
-static void edt_ft5x06_ts_prepare_debugfs(struct edt_ft5x06_ts_data *tsdata,
- const char *debugfs_name)
+static void edt_ft5x06_ts_prepare_debugfs(struct edt_ft5x06_ts_data *tsdata)
{
- tsdata->debug_dir = debugfs_create_dir(debugfs_name, NULL);
+ struct dentry *debug_dir = tsdata->client->debugfs;
- debugfs_create_u16("num_x", S_IRUSR, tsdata->debug_dir, &tsdata->num_x);
- debugfs_create_u16("num_y", S_IRUSR, tsdata->debug_dir, &tsdata->num_y);
+ debugfs_create_u16("num_x", S_IRUSR, debug_dir, &tsdata->num_x);
+ debugfs_create_u16("num_y", S_IRUSR, debug_dir, &tsdata->num_y);
debugfs_create_file("mode", S_IRUSR | S_IWUSR,
- tsdata->debug_dir, tsdata, &debugfs_mode_fops);
+ debug_dir, tsdata, &debugfs_mode_fops);
debugfs_create_file("raw_data", S_IRUSR,
- tsdata->debug_dir, tsdata, &debugfs_raw_data_fops);
+ debug_dir, tsdata, &debugfs_raw_data_fops);
}
static void edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata)
{
- debugfs_remove_recursive(tsdata->debug_dir);
+ guard(mutex)(&tsdata->mutex);
+
kfree(tsdata->raw_buffer);
+ tsdata->raw_buffer = NULL;
}
#else
@@ -842,8 +817,7 @@ static int edt_ft5x06_factory_mode(struct edt_ft5x06_ts_data *tsdata)
return -ENOSYS;
}
-static void edt_ft5x06_ts_prepare_debugfs(struct edt_ft5x06_ts_data *tsdata,
- const char *debugfs_name)
+static void edt_ft5x06_ts_prepare_debugfs(struct edt_ft5x06_ts_data *tsdata)
{
}
@@ -1349,7 +1323,7 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client)
if (error)
return error;
- edt_ft5x06_ts_prepare_debugfs(tsdata, dev_driver_string(&client->dev));
+ edt_ft5x06_ts_prepare_debugfs(tsdata);
dev_dbg(&client->dev,
"EDT FT5x06 initialized: IRQ %d, WAKE pin %d, Reset pin %d.\n",
@@ -1479,6 +1453,10 @@ static const struct edt_i2c_chip_data edt_ft5x06_data = {
.max_support_points = 5,
};
+static const struct edt_i2c_chip_data edt_ft3518_data = {
+ .max_support_points = 10,
+};
+
static const struct edt_i2c_chip_data edt_ft5452_data = {
.max_support_points = 5,
};
@@ -1495,6 +1473,10 @@ static const struct edt_i2c_chip_data edt_ft8201_data = {
.max_support_points = 10,
};
+static const struct edt_i2c_chip_data edt_ft8716_data = {
+ .max_support_points = 10,
+};
+
static const struct edt_i2c_chip_data edt_ft8719_data = {
.max_support_points = 10,
};
@@ -1503,10 +1485,12 @@ static const struct i2c_device_id edt_ft5x06_ts_id[] = {
{ .name = "edt-ft5x06", .driver_data = (long)&edt_ft5x06_data },
{ .name = "edt-ft5506", .driver_data = (long)&edt_ft5506_data },
{ .name = "ev-ft5726", .driver_data = (long)&edt_ft5506_data },
+ { .name = "ft3518", .driver_data = (long)&edt_ft3518_data },
{ .name = "ft5452", .driver_data = (long)&edt_ft5452_data },
/* Note no edt- prefix for compatibility with the ft6236.c driver */
{ .name = "ft6236", .driver_data = (long)&edt_ft6236_data },
{ .name = "ft8201", .driver_data = (long)&edt_ft8201_data },
+ { .name = "ft8716", .driver_data = (long)&edt_ft8716_data },
{ .name = "ft8719", .driver_data = (long)&edt_ft8719_data },
{ /* sentinel */ }
};
@@ -1518,11 +1502,13 @@ static const struct of_device_id edt_ft5x06_of_match[] = {
{ .compatible = "edt,edt-ft5406", .data = &edt_ft5x06_data },
{ .compatible = "edt,edt-ft5506", .data = &edt_ft5506_data },
{ .compatible = "evervision,ev-ft5726", .data = &edt_ft5506_data },
+ { .compatible = "focaltech,ft3518", .data = &edt_ft3518_data },
{ .compatible = "focaltech,ft5426", .data = &edt_ft5506_data },
{ .compatible = "focaltech,ft5452", .data = &edt_ft5452_data },
/* Note focaltech vendor prefix for compatibility with ft6236.c */
{ .compatible = "focaltech,ft6236", .data = &edt_ft6236_data },
{ .compatible = "focaltech,ft8201", .data = &edt_ft8201_data },
+ { .compatible = "focaltech,ft8716", .data = &edt_ft8716_data },
{ .compatible = "focaltech,ft8719", .data = &edt_ft8719_data },
{ /* sentinel */ }
};
diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c
index 87eb18977b71..492e19a28a74 100644
--- a/drivers/input/touchscreen/eeti_ts.c
+++ b/drivers/input/touchscreen/eeti_ts.c
@@ -89,7 +89,7 @@ static irqreturn_t eeti_ts_isr(int irq, void *dev_id)
struct eeti_ts *eeti = dev_id;
int error;
- mutex_lock(&eeti->mutex);
+ guard(mutex)(&eeti->mutex);
do {
/*
@@ -109,13 +109,12 @@ static irqreturn_t eeti_ts_isr(int irq, void *dev_id)
} while (eeti->running && eeti->attn_gpio);
- mutex_unlock(&eeti->mutex);
return IRQ_HANDLED;
}
static void eeti_ts_start(struct eeti_ts *eeti)
{
- mutex_lock(&eeti->mutex);
+ guard(mutex)(&eeti->mutex);
eeti->running = true;
enable_irq(eeti->client->irq);
@@ -127,8 +126,6 @@ static void eeti_ts_start(struct eeti_ts *eeti)
*/
if (eeti->attn_gpio && gpiod_get_value_cansleep(eeti->attn_gpio))
eeti_ts_read(eeti);
-
- mutex_unlock(&eeti->mutex);
}
static void eeti_ts_stop(struct eeti_ts *eeti)
@@ -238,12 +235,10 @@ static int eeti_ts_suspend(struct device *dev)
struct eeti_ts *eeti = i2c_get_clientdata(client);
struct input_dev *input_dev = eeti->input;
- mutex_lock(&input_dev->mutex);
-
- if (input_device_enabled(input_dev))
- eeti_ts_stop(eeti);
-
- mutex_unlock(&input_dev->mutex);
+ scoped_guard(mutex, &input_dev->mutex) {
+ if (input_device_enabled(input_dev))
+ eeti_ts_stop(eeti);
+ }
if (device_may_wakeup(&client->dev))
enable_irq_wake(client->irq);
@@ -260,12 +255,10 @@ static int eeti_ts_resume(struct device *dev)
if (device_may_wakeup(&client->dev))
disable_irq_wake(client->irq);
- mutex_lock(&input_dev->mutex);
-
- if (input_device_enabled(input_dev))
- eeti_ts_start(eeti);
-
- mutex_unlock(&input_dev->mutex);
+ scoped_guard(mutex, &input_dev->mutex) {
+ if (input_device_enabled(input_dev))
+ eeti_ts_start(eeti);
+ }
return 0;
}
diff --git a/drivers/input/touchscreen/egalax_ts_serial.c b/drivers/input/touchscreen/egalax_ts_serial.c
index 07a4aa1c19bb..e04ea1fea4ad 100644
--- a/drivers/input/touchscreen/egalax_ts_serial.c
+++ b/drivers/input/touchscreen/egalax_ts_serial.c
@@ -99,7 +99,7 @@ static int egalax_connect(struct serio *serio, struct serio_driver *drv)
struct input_dev *input_dev;
int error;
- egalax = kzalloc(sizeof(*egalax), GFP_KERNEL);
+ egalax = kzalloc_obj(*egalax);
input_dev = input_allocate_device();
if (!egalax || !input_dev) {
error = -ENOMEM;
@@ -108,8 +108,7 @@ static int egalax_connect(struct serio *serio, struct serio_driver *drv)
egalax->serio = serio;
egalax->input = input_dev;
- snprintf(egalax->phys, sizeof(egalax->phys),
- "%s/input0", serio->phys);
+ scnprintf(egalax->phys, sizeof(egalax->phys), "%s/input0", serio->phys);
input_dev->name = "EETI eGalaxTouch Serial TouchScreen";
input_dev->phys = egalax->phys;
diff --git a/drivers/input/touchscreen/ektf2127.c b/drivers/input/touchscreen/ektf2127.c
index 46a0611fac82..572a37d4e0aa 100644
--- a/drivers/input/touchscreen/ektf2127.c
+++ b/drivers/input/touchscreen/ektf2127.c
@@ -187,10 +187,10 @@ static int ektf2127_suspend(struct device *dev)
{
struct ektf2127_ts *ts = i2c_get_clientdata(to_i2c_client(dev));
- mutex_lock(&ts->input->mutex);
+ guard(mutex)(&ts->input->mutex);
+
if (input_device_enabled(ts->input))
ektf2127_stop(ts->input);
- mutex_unlock(&ts->input->mutex);
return 0;
}
@@ -199,10 +199,10 @@ static int ektf2127_resume(struct device *dev)
{
struct ektf2127_ts *ts = i2c_get_clientdata(to_i2c_client(dev));
- mutex_lock(&ts->input->mutex);
+ guard(mutex)(&ts->input->mutex);
+
if (input_device_enabled(ts->input))
ektf2127_start(ts->input);
- mutex_unlock(&ts->input->mutex);
return 0;
}
diff --git a/drivers/input/touchscreen/elants_i2c.c b/drivers/input/touchscreen/elants_i2c.c
index 3fd170f75b4a..835d91dff0a4 100644
--- a/drivers/input/touchscreen/elants_i2c.c
+++ b/drivers/input/touchscreen/elants_i2c.c
@@ -303,15 +303,13 @@ static int elants_i2c_calibrate(struct elants_data *ts)
static const u8 rek[] = { CMD_HEADER_WRITE, 0x29, 0x00, 0x01 };
static const u8 rek_resp[] = { CMD_HEADER_REK, 0x66, 0x66, 0x66 };
- disable_irq(client->irq);
-
- ts->state = ELAN_WAIT_RECALIBRATION;
- reinit_completion(&ts->cmd_done);
-
- elants_i2c_send(client, w_flashkey, sizeof(w_flashkey));
- elants_i2c_send(client, rek, sizeof(rek));
+ scoped_guard(disable_irq, &client->irq) {
+ ts->state = ELAN_WAIT_RECALIBRATION;
+ reinit_completion(&ts->cmd_done);
- enable_irq(client->irq);
+ elants_i2c_send(client, w_flashkey, sizeof(w_flashkey));
+ elants_i2c_send(client, rek, sizeof(rek));
+ }
ret = wait_for_completion_interruptible_timeout(&ts->cmd_done,
msecs_to_jiffies(ELAN_CALI_TIMEOUT_MSEC));
@@ -906,17 +904,17 @@ static int elants_i2c_do_update_firmware(struct i2c_client *client,
static int elants_i2c_fw_update(struct elants_data *ts)
{
struct i2c_client *client = ts->client;
- const struct firmware *fw;
- char *fw_name;
int error;
- fw_name = kasprintf(GFP_KERNEL, "elants_i2c_%04x.bin", ts->hw_version);
+ const char *fw_name __free(kfree) =
+ kasprintf(GFP_KERNEL, "elants_i2c_%04x.bin", ts->hw_version);
if (!fw_name)
return -ENOMEM;
dev_info(&client->dev, "requesting fw name = %s\n", fw_name);
+
+ const struct firmware *fw __free(firmware) = NULL;
error = request_firmware(&fw, fw_name, &client->dev);
- kfree(fw_name);
if (error) {
dev_err(&client->dev, "failed to request firmware: %d\n",
error);
@@ -926,40 +924,32 @@ static int elants_i2c_fw_update(struct elants_data *ts)
if (fw->size % ELAN_FW_PAGESIZE) {
dev_err(&client->dev, "invalid firmware length: %zu\n",
fw->size);
- error = -EINVAL;
- goto out;
+ return -EINVAL;
}
- disable_irq(client->irq);
+ scoped_guard(disable_irq, &client->irq) {
+ bool force_update = ts->iap_mode == ELAN_IAP_RECOVERY;
- error = elants_i2c_do_update_firmware(client, fw,
- ts->iap_mode == ELAN_IAP_RECOVERY);
- if (error) {
- dev_err(&client->dev, "firmware update failed: %d\n", error);
- ts->iap_mode = ELAN_IAP_RECOVERY;
- goto out_enable_irq;
- }
+ error = elants_i2c_do_update_firmware(client, fw, force_update);
+ if (error) {
+ dev_err(&client->dev, "firmware update failed: %d\n",
+ error);
+ } else {
+ error = elants_i2c_initialize(ts);
+ if (error)
+ dev_err(&client->dev,
+ "failed to initialize device after firmware update: %d\n",
+ error);
+ }
- error = elants_i2c_initialize(ts);
- if (error) {
- dev_err(&client->dev,
- "failed to initialize device after firmware update: %d\n",
- error);
- ts->iap_mode = ELAN_IAP_RECOVERY;
- goto out_enable_irq;
+ ts->iap_mode = error ? ELAN_IAP_RECOVERY : ELAN_IAP_OPERATIONAL;
+ ts->state = ELAN_STATE_NORMAL;
}
-
- ts->iap_mode = ELAN_IAP_OPERATIONAL;
-
-out_enable_irq:
- ts->state = ELAN_STATE_NORMAL;
- enable_irq(client->irq);
msleep(100);
if (!error)
elants_i2c_calibrate(ts);
-out:
- release_firmware(fw);
+
return error;
}
@@ -1186,14 +1176,13 @@ static ssize_t calibrate_store(struct device *dev,
struct elants_data *ts = i2c_get_clientdata(client);
int error;
- error = mutex_lock_interruptible(&ts->sysfs_mutex);
- if (error)
- return error;
-
- error = elants_i2c_calibrate(ts);
+ scoped_cond_guard(mutex_intr, return -EINTR, &ts->sysfs_mutex) {
+ error = elants_i2c_calibrate(ts);
+ if (error)
+ return error;
+ }
- mutex_unlock(&ts->sysfs_mutex);
- return error ?: count;
+ return count;
}
static ssize_t write_update_fw(struct device *dev,
@@ -1204,15 +1193,13 @@ static ssize_t write_update_fw(struct device *dev,
struct elants_data *ts = i2c_get_clientdata(client);
int error;
- error = mutex_lock_interruptible(&ts->sysfs_mutex);
- if (error)
- return error;
-
- error = elants_i2c_fw_update(ts);
- dev_dbg(dev, "firmware update result: %d\n", error);
+ scoped_cond_guard(mutex_intr, return -EINTR, &ts->sysfs_mutex) {
+ error = elants_i2c_fw_update(ts);
+ if (error)
+ return error;
+ }
- mutex_unlock(&ts->sysfs_mutex);
- return error ?: count;
+ return count;
}
static ssize_t show_iap_mode(struct device *dev,
diff --git a/drivers/input/touchscreen/elo.c b/drivers/input/touchscreen/elo.c
index ad209e6e82a6..6814d5789b6f 100644
--- a/drivers/input/touchscreen/elo.c
+++ b/drivers/input/touchscreen/elo.c
@@ -219,40 +219,40 @@ static irqreturn_t elo_interrupt(struct serio *serio,
static int elo_command_10(struct elo *elo, unsigned char *packet)
{
- int rc = -1;
+ int error;
int i;
unsigned char csum = 0xaa + ELO10_LEAD_BYTE;
- mutex_lock(&elo->cmd_mutex);
+ guard(mutex)(&elo->cmd_mutex);
scoped_guard(serio_pause_rx, elo->serio) {
elo->expected_packet = toupper(packet[0]);
init_completion(&elo->cmd_done);
}
- if (serio_write(elo->serio, ELO10_LEAD_BYTE))
- goto out;
+ error = serio_write(elo->serio, ELO10_LEAD_BYTE);
+ if (error)
+ return error;
for (i = 0; i < ELO10_PACKET_LEN; i++) {
csum += packet[i];
- if (serio_write(elo->serio, packet[i]))
- goto out;
+ error = serio_write(elo->serio, packet[i]);
+ if (error)
+ return error;
}
- if (serio_write(elo->serio, csum))
- goto out;
+ error = serio_write(elo->serio, csum);
+ if (error)
+ return error;
wait_for_completion_timeout(&elo->cmd_done, HZ);
- if (elo->expected_packet == ELO10_TOUCH_PACKET) {
- /* We are back in reporting mode, the command was ACKed */
- memcpy(packet, elo->response, ELO10_PACKET_LEN);
- rc = 0;
- }
+ if (elo->expected_packet != ELO10_TOUCH_PACKET)
+ return -EIO;
- out:
- mutex_unlock(&elo->cmd_mutex);
- return rc;
+ /* We are back in reporting mode, the command was ACKed */
+ memcpy(packet, elo->response, ELO10_PACKET_LEN);
+ return 0;
}
static int elo_setup_10(struct elo *elo)
@@ -307,7 +307,7 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv)
struct input_dev *input_dev;
int err;
- elo = kzalloc(sizeof(*elo), GFP_KERNEL);
+ elo = kzalloc_obj(*elo);
input_dev = input_allocate_device();
if (!elo || !input_dev) {
err = -ENOMEM;
@@ -320,7 +320,7 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv)
elo->expected_packet = ELO10_TOUCH_PACKET;
mutex_init(&elo->cmd_mutex);
init_completion(&elo->cmd_done);
- snprintf(elo->phys, sizeof(elo->phys), "%s/input0", serio->phys);
+ scnprintf(elo->phys, sizeof(elo->phys), "%s/input0", serio->phys);
input_dev->name = "Elo Serial TouchScreen";
input_dev->phys = elo->phys;
diff --git a/drivers/input/touchscreen/exc3000.c b/drivers/input/touchscreen/exc3000.c
index fdda8412b164..78c0911ba6e2 100644
--- a/drivers/input/touchscreen/exc3000.c
+++ b/drivers/input/touchscreen/exc3000.c
@@ -105,7 +105,7 @@ static void exc3000_report_slots(struct input_dev *input,
static void exc3000_timer(struct timer_list *t)
{
- struct exc3000_data *data = from_timer(data, t, timer);
+ struct exc3000_data *data = timer_container_of(data, t, timer);
input_mt_sync_frame(data->input);
input_sync(data->input);
@@ -174,7 +174,7 @@ static int exc3000_handle_mt_event(struct exc3000_data *data)
/*
* We read full state successfully, no contacts will be "stuck".
*/
- del_timer_sync(&data->timer);
+ timer_delete_sync(&data->timer);
while (total_slots > 0) {
int slots = min(total_slots, EXC3000_SLOTS_PER_FRAME);
@@ -234,7 +234,7 @@ static int exc3000_vendor_data_request(struct exc3000_data *data, u8 *request,
int ret;
unsigned long time_left;
- mutex_lock(&data->query_lock);
+ guard(mutex)(&data->query_lock);
reinit_completion(&data->wait_event);
@@ -243,29 +243,18 @@ static int exc3000_vendor_data_request(struct exc3000_data *data, u8 *request,
ret = i2c_master_send(data->client, buf, EXC3000_LEN_VENDOR_REQUEST);
if (ret < 0)
- goto out_unlock;
-
- if (response) {
- time_left = wait_for_completion_timeout(&data->wait_event,
- timeout * HZ);
- if (time_left == 0) {
- ret = -ETIMEDOUT;
- goto out_unlock;
- }
-
- if (data->buf[3] >= EXC3000_LEN_FRAME) {
- ret = -ENOSPC;
- goto out_unlock;
- }
+ return ret;
- memcpy(response, &data->buf[4], data->buf[3]);
- ret = data->buf[3];
- }
+ time_left = wait_for_completion_timeout(&data->wait_event,
+ timeout * HZ);
+ if (time_left == 0)
+ return -ETIMEDOUT;
-out_unlock:
- mutex_unlock(&data->query_lock);
+ if (data->buf[3] >= EXC3000_LEN_FRAME)
+ return -ENOSPC;
- return ret;
+ memcpy(response, &data->buf[4], data->buf[3]);
+ return data->buf[3];
}
static ssize_t fw_version_show(struct device *dev,
diff --git a/drivers/input/touchscreen/fsl-imx25-tcq.c b/drivers/input/touchscreen/fsl-imx25-tcq.c
index a32708652d10..ff270b3b8572 100644
--- a/drivers/input/touchscreen/fsl-imx25-tcq.c
+++ b/drivers/input/touchscreen/fsl-imx25-tcq.c
@@ -39,7 +39,6 @@ struct mx25_tcq_priv {
};
static const struct regmap_config mx25_tcq_regconfig = {
- .fast_io = true,
.max_register = 0x5c,
.reg_bits = 32,
.val_bits = 32,
diff --git a/drivers/input/touchscreen/fujitsu_ts.c b/drivers/input/touchscreen/fujitsu_ts.c
index 1a3e14ea2e08..8ed592294b17 100644
--- a/drivers/input/touchscreen/fujitsu_ts.c
+++ b/drivers/input/touchscreen/fujitsu_ts.c
@@ -99,7 +99,7 @@ static int fujitsu_connect(struct serio *serio, struct serio_driver *drv)
struct input_dev *input_dev;
int err;
- fujitsu = kzalloc(sizeof(*fujitsu), GFP_KERNEL);
+ fujitsu = kzalloc_obj(*fujitsu);
input_dev = input_allocate_device();
if (!fujitsu || !input_dev) {
err = -ENOMEM;
@@ -108,8 +108,7 @@ static int fujitsu_connect(struct serio *serio, struct serio_driver *drv)
fujitsu->serio = serio;
fujitsu->dev = input_dev;
- snprintf(fujitsu->phys, sizeof(fujitsu->phys),
- "%s/input0", serio->phys);
+ scnprintf(fujitsu->phys, sizeof(fujitsu->phys), "%s/input0", serio->phys);
input_dev->name = "Fujitsu Serial Touchscreen";
input_dev->phys = fujitsu->phys;
diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c
index a3e8a51c9144..f8798d11ec03 100644
--- a/drivers/input/touchscreen/goodix.c
+++ b/drivers/input/touchscreen/goodix.c
@@ -44,9 +44,11 @@
#define GOODIX_HAVE_KEY BIT(4)
#define GOODIX_BUFFER_STATUS_TIMEOUT 20
-#define RESOLUTION_LOC 1
-#define MAX_CONTACTS_LOC 5
-#define TRIGGER_LOC 6
+#define RESOLUTION_LOC 1
+#define MAX_CONTACTS_LOC 5
+#define TRIGGER_LOC 6
+
+#define GOODIX_POLL_INTERVAL_MS 17 /* 17ms = 60fps */
/* Our special handling for GPIO accesses through ACPI is x86 specific */
#if defined CONFIG_X86 && defined CONFIG_ACPI
@@ -497,6 +499,14 @@ sync:
input_sync(ts->input_dev);
}
+static void goodix_ts_work_i2c_poll(struct input_dev *input)
+{
+ struct goodix_ts_data *ts = input_get_drvdata(input);
+
+ goodix_process_events(ts);
+ goodix_i2c_write_u8(ts->client, GOODIX_READ_COOR_ADDR, 0);
+}
+
/**
* goodix_ts_irq_handler - The IRQ handler
*
@@ -513,13 +523,29 @@ static irqreturn_t goodix_ts_irq_handler(int irq, void *dev_id)
return IRQ_HANDLED;
}
+static void goodix_enable_irq(struct goodix_ts_data *ts)
+{
+ if (ts->client->irq)
+ enable_irq(ts->client->irq);
+}
+
+static void goodix_disable_irq(struct goodix_ts_data *ts)
+{
+ if (ts->client->irq)
+ disable_irq(ts->client->irq);
+}
+
static void goodix_free_irq(struct goodix_ts_data *ts)
{
- devm_free_irq(&ts->client->dev, ts->client->irq, ts);
+ if (ts->client->irq)
+ devm_free_irq(&ts->client->dev, ts->client->irq, ts);
}
static int goodix_request_irq(struct goodix_ts_data *ts)
{
+ if (!ts->client->irq)
+ return 0;
+
return devm_request_threaded_irq(&ts->client->dev, ts->client->irq,
NULL, goodix_ts_irq_handler,
ts->irq_flags, ts->client->name, ts);
@@ -770,17 +796,6 @@ int goodix_reset_no_int_sync(struct goodix_ts_data *ts)
usleep_range(6000, 10000); /* T4: > 5ms */
- /*
- * Put the reset pin back in to input / high-impedance mode to save
- * power. Only do this in the non ACPI case since some ACPI boards
- * don't have a pull-up, so there the reset pin must stay active-high.
- */
- if (ts->irq_pin_access_method == IRQ_PIN_ACCESS_GPIO) {
- error = gpiod_direction_input(ts->gpiod_rst);
- if (error)
- goto error;
- }
-
return 0;
error:
@@ -931,14 +946,6 @@ static int goodix_add_acpi_gpio_mappings(struct goodix_ts_data *ts)
return -EINVAL;
}
- /*
- * Normally we put the reset pin in input / high-impedance mode to save
- * power. But some x86/ACPI boards don't have a pull-up, so for the ACPI
- * case, leave the pin as is. This results in the pin not being touched
- * at all on x86/ACPI boards, except when needed for error-recover.
- */
- ts->gpiod_rst_flags = GPIOD_ASIS;
-
return devm_acpi_dev_add_driver_gpios(dev, gpio_mapping);
}
#else
@@ -963,12 +970,6 @@ static int goodix_get_gpio_config(struct goodix_ts_data *ts)
return -EINVAL;
dev = &ts->client->dev;
- /*
- * By default we request the reset pin as input, leaving it in
- * high-impedance when not resetting the controller to save power.
- */
- ts->gpiod_rst_flags = GPIOD_IN;
-
ts->avdd28 = devm_regulator_get(dev, "AVDD28");
if (IS_ERR(ts->avdd28))
return dev_err_probe(dev, PTR_ERR(ts->avdd28), "Failed to get AVDD28 regulator\n");
@@ -993,7 +994,7 @@ retry_get_irq_gpio:
ts->gpiod_int = gpiod;
/* Get the reset line GPIO pin number */
- gpiod = devm_gpiod_get_optional(dev, GOODIX_GPIO_RST_NAME, ts->gpiod_rst_flags);
+ gpiod = devm_gpiod_get_optional(dev, GOODIX_GPIO_RST_NAME, GPIOD_ASIS);
if (IS_ERR(gpiod))
return dev_err_probe(dev, PTR_ERR(gpiod), "Failed to get %s GPIO\n",
GOODIX_GPIO_RST_NAME);
@@ -1219,6 +1220,18 @@ retry_read_config:
return error;
}
+ input_set_drvdata(ts->input_dev, ts);
+
+ if (!ts->client->irq) {
+ error = input_setup_polling(ts->input_dev, goodix_ts_work_i2c_poll);
+ if (error) {
+ dev_err(&ts->client->dev,
+ "could not set up polling mode, %d\n", error);
+ return error;
+ }
+ input_set_poll_interval(ts->input_dev, GOODIX_POLL_INTERVAL_MS);
+ }
+
error = input_register_device(ts->input_dev);
if (error) {
dev_err(&ts->client->dev,
@@ -1422,7 +1435,7 @@ static int goodix_suspend(struct device *dev)
/* We need gpio pins to suspend/resume */
if (ts->irq_pin_access_method == IRQ_PIN_ACCESS_NONE) {
- disable_irq(client->irq);
+ goodix_disable_irq(ts);
return 0;
}
@@ -1466,7 +1479,7 @@ static int goodix_resume(struct device *dev)
int error;
if (ts->irq_pin_access_method == IRQ_PIN_ACCESS_NONE) {
- enable_irq(client->irq);
+ goodix_enable_irq(ts);
return 0;
}
@@ -1519,6 +1532,7 @@ MODULE_DEVICE_TABLE(i2c, goodix_ts_id);
static const struct acpi_device_id goodix_acpi_match[] = {
{ "GDIX1001", 0 },
{ "GDIX1002", 0 },
+ { "GDIX1003", 0 },
{ "GDX9110", 0 },
{ }
};
diff --git a/drivers/input/touchscreen/goodix.h b/drivers/input/touchscreen/goodix.h
index 87797cc88b32..0d1e8a8d2cba 100644
--- a/drivers/input/touchscreen/goodix.h
+++ b/drivers/input/touchscreen/goodix.h
@@ -88,7 +88,6 @@ struct goodix_ts_data {
struct gpio_desc *gpiod_rst;
int gpio_count;
int gpio_int_idx;
- enum gpiod_flags gpiod_rst_flags;
char id[GOODIX_ID_MAX_LEN + 1];
char cfg_name[64];
u16 version;
diff --git a/drivers/input/touchscreen/goodix_berlin.h b/drivers/input/touchscreen/goodix_berlin.h
index 38b6f9ddbdef..d8bbd4853206 100644
--- a/drivers/input/touchscreen/goodix_berlin.h
+++ b/drivers/input/touchscreen/goodix_berlin.h
@@ -12,12 +12,26 @@
#include <linux/pm.h>
+#define GOODIX_BERLIN_FW_VERSION_INFO_ADDR_A 0x1000C
+#define GOODIX_BERLIN_FW_VERSION_INFO_ADDR_D 0x10014
+
+#define GOODIX_BERLIN_IC_INFO_ADDR_A 0x10068
+#define GOODIX_BERLIN_IC_INFO_ADDR_D 0x10070
+
+struct goodix_berlin_ic_data {
+ int fw_version_info_addr;
+ int ic_info_addr;
+ ssize_t read_dummy_len;
+ ssize_t read_prefix_len;
+};
+
struct device;
struct input_id;
struct regmap;
int goodix_berlin_probe(struct device *dev, int irq, const struct input_id *id,
- struct regmap *regmap);
+ struct regmap *regmap,
+ const struct goodix_berlin_ic_data *ic_data);
extern const struct dev_pm_ops goodix_berlin_pm_ops;
extern const struct attribute_group *goodix_berlin_groups[];
diff --git a/drivers/input/touchscreen/goodix_berlin_core.c b/drivers/input/touchscreen/goodix_berlin_core.c
index 7f8cfdd106fa..b0938a4f3fec 100644
--- a/drivers/input/touchscreen/goodix_berlin_core.c
+++ b/drivers/input/touchscreen/goodix_berlin_core.c
@@ -12,7 +12,7 @@
* to the previous generations.
*
* Currently the driver only handles Multitouch events with already
- * programmed firmware and "config" for "Revision D" Berlin IC.
+ * programmed firmware and "config" for "Revision A/D" Berlin IC.
*
* Support is missing for:
* - ESD Management
@@ -20,14 +20,16 @@
* - "Config" update/flashing
* - Stylus Events
* - Gesture Events
- * - Support for older revisions (A & B)
+ * - Support for revision B
*/
#include <linux/bitfield.h>
+#include <linux/export.h>
#include <linux/gpio/consumer.h>
#include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/input/touchscreen.h>
+#include <linux/property.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/sizes.h>
@@ -53,10 +55,8 @@
#define GOODIX_BERLIN_DEV_CONFIRM_VAL 0xAA
#define GOODIX_BERLIN_BOOTOPTION_ADDR 0x10000
-#define GOODIX_BERLIN_FW_VERSION_INFO_ADDR 0x10014
#define GOODIX_BERLIN_IC_INFO_MAX_LEN SZ_1K
-#define GOODIX_BERLIN_IC_INFO_ADDR 0x10070
#define GOODIX_BERLIN_CHECKSUM_SIZE sizeof(u16)
@@ -175,6 +175,8 @@ struct goodix_berlin_core {
/* Runtime parameters extracted from IC_INFO buffer */
u32 touch_data_addr;
+ const struct goodix_berlin_ic_data *ic_data;
+
struct goodix_berlin_event event;
};
@@ -299,7 +301,7 @@ static int goodix_berlin_read_version(struct goodix_berlin_core *cd)
{
int error;
- error = regmap_raw_read(cd->regmap, GOODIX_BERLIN_FW_VERSION_INFO_ADDR,
+ error = regmap_raw_read(cd->regmap, cd->ic_data->fw_version_info_addr,
&cd->fw_version, sizeof(cd->fw_version));
if (error) {
dev_err(cd->dev, "error reading fw version, %d\n", error);
@@ -367,7 +369,7 @@ static int goodix_berlin_get_ic_info(struct goodix_berlin_core *cd)
if (!afe_data)
return -ENOMEM;
- error = regmap_raw_read(cd->regmap, GOODIX_BERLIN_IC_INFO_ADDR,
+ error = regmap_raw_read(cd->regmap, cd->ic_data->ic_info_addr,
&length_raw, sizeof(length_raw));
if (error) {
dev_err(cd->dev, "failed get ic info length, %d\n", error);
@@ -380,8 +382,8 @@ static int goodix_berlin_get_ic_info(struct goodix_berlin_core *cd)
return -EINVAL;
}
- error = regmap_raw_read(cd->regmap, GOODIX_BERLIN_IC_INFO_ADDR,
- afe_data, length);
+ error = regmap_raw_read(cd->regmap, cd->ic_data->ic_info_addr, afe_data,
+ length);
if (error) {
dev_err(cd->dev, "failed get ic info data, %d\n", error);
return error;
@@ -626,6 +628,14 @@ static int goodix_berlin_input_dev_config(struct goodix_berlin_core *cd,
touchscreen_parse_properties(cd->input_dev, true, &cd->props);
+ /*
+ * The resolution of these touchscreens is about 10 units/mm, the actual
+ * resolution does not matter much since we set INPUT_PROP_DIRECT.
+ * Set it to 10 to ensure userspace isn't off by an order of magnitude.
+ */
+ input_abs_set_res(cd->input_dev, ABS_MT_POSITION_X, 10);
+ input_abs_set_res(cd->input_dev, ABS_MT_POSITION_Y, 10);
+
error = input_mt_init_slots(cd->input_dev, GOODIX_BERLIN_MAX_TOUCH,
INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
if (error)
@@ -673,7 +683,7 @@ static void goodix_berlin_power_off_act(void *data)
}
static ssize_t registers_read(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr,
+ const struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct device *dev = kobj_to_dev(kobj);
@@ -686,7 +696,7 @@ static ssize_t registers_read(struct file *filp, struct kobject *kobj,
}
static ssize_t registers_write(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr,
+ const struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct device *dev = kobj_to_dev(kobj);
@@ -698,9 +708,9 @@ static ssize_t registers_write(struct file *filp, struct kobject *kobj,
return error ? error : count;
}
-static BIN_ATTR_ADMIN_RW(registers, 0);
+static const BIN_ATTR_ADMIN_RW(registers, 0);
-static struct bin_attribute *goodix_berlin_bin_attrs[] = {
+static const struct bin_attribute *const goodix_berlin_bin_attrs[] = {
&bin_attr_registers,
NULL,
};
@@ -716,7 +726,8 @@ const struct attribute_group *goodix_berlin_groups[] = {
EXPORT_SYMBOL_GPL(goodix_berlin_groups);
int goodix_berlin_probe(struct device *dev, int irq, const struct input_id *id,
- struct regmap *regmap)
+ struct regmap *regmap,
+ const struct goodix_berlin_ic_data *ic_data)
{
struct goodix_berlin_core *cd;
int error;
@@ -733,6 +744,7 @@ int goodix_berlin_probe(struct device *dev, int irq, const struct input_id *id,
cd->dev = dev;
cd->regmap = regmap;
cd->irq = irq;
+ cd->ic_data = ic_data;
cd->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
if (IS_ERR(cd->reset_gpio))
diff --git a/drivers/input/touchscreen/goodix_berlin_i2c.c b/drivers/input/touchscreen/goodix_berlin_i2c.c
index ad7a60d94338..929090a094bf 100644
--- a/drivers/input/touchscreen/goodix_berlin_i2c.c
+++ b/drivers/input/touchscreen/goodix_berlin_i2c.c
@@ -31,6 +31,8 @@ static const struct input_id goodix_berlin_i2c_input_id = {
static int goodix_berlin_i2c_probe(struct i2c_client *client)
{
+ const struct goodix_berlin_ic_data *ic_data =
+ i2c_get_match_data(client);
struct regmap *regmap;
int error;
@@ -39,22 +41,28 @@ static int goodix_berlin_i2c_probe(struct i2c_client *client)
return PTR_ERR(regmap);
error = goodix_berlin_probe(&client->dev, client->irq,
- &goodix_berlin_i2c_input_id, regmap);
+ &goodix_berlin_i2c_input_id, regmap,
+ ic_data);
if (error)
return error;
return 0;
}
+static const struct goodix_berlin_ic_data gt9916_data = {
+ .fw_version_info_addr = GOODIX_BERLIN_FW_VERSION_INFO_ADDR_D,
+ .ic_info_addr = GOODIX_BERLIN_IC_INFO_ADDR_D,
+};
+
static const struct i2c_device_id goodix_berlin_i2c_id[] = {
- { "gt9916" },
+ { .name = "gt9916", .driver_data = (long)&gt9916_data },
{ }
};
MODULE_DEVICE_TABLE(i2c, goodix_berlin_i2c_id);
static const struct of_device_id goodix_berlin_i2c_of_match[] = {
- { .compatible = "goodix,gt9916", },
+ { .compatible = "goodix,gt9916", .data = &gt9916_data },
{ }
};
MODULE_DEVICE_TABLE(of, goodix_berlin_i2c_of_match);
diff --git a/drivers/input/touchscreen/goodix_berlin_spi.c b/drivers/input/touchscreen/goodix_berlin_spi.c
index 0662e87b8692..01f850f484c2 100644
--- a/drivers/input/touchscreen/goodix_berlin_spi.c
+++ b/drivers/input/touchscreen/goodix_berlin_spi.c
@@ -18,10 +18,14 @@
#define GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN 1
#define GOODIX_BERLIN_REGISTER_WIDTH 4
-#define GOODIX_BERLIN_SPI_READ_DUMMY_LEN 3
-#define GOODIX_BERLIN_SPI_READ_PREFIX_LEN (GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN + \
+#define GOODIX_BERLIN_SPI_READ_DUMMY_LEN_A 4
+#define GOODIX_BERLIN_SPI_READ_DUMMY_LEN_D 3
+#define GOODIX_BERLIN_SPI_READ_PREFIX_LEN_A (GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN + \
GOODIX_BERLIN_REGISTER_WIDTH + \
- GOODIX_BERLIN_SPI_READ_DUMMY_LEN)
+ GOODIX_BERLIN_SPI_READ_DUMMY_LEN_A)
+#define GOODIX_BERLIN_SPI_READ_PREFIX_LEN_D (GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN + \
+ GOODIX_BERLIN_REGISTER_WIDTH + \
+ GOODIX_BERLIN_SPI_READ_DUMMY_LEN_D)
#define GOODIX_BERLIN_SPI_WRITE_PREFIX_LEN (GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN + \
GOODIX_BERLIN_REGISTER_WIDTH)
@@ -33,6 +37,7 @@ static int goodix_berlin_spi_read(void *context, const void *reg_buf,
size_t val_size)
{
struct spi_device *spi = context;
+ const struct goodix_berlin_ic_data *ic_data = spi_get_device_match_data(spi);
struct spi_transfer xfers;
struct spi_message spi_msg;
const u32 *reg = reg_buf; /* reg is stored as native u32 at start of buffer */
@@ -42,23 +47,22 @@ static int goodix_berlin_spi_read(void *context, const void *reg_buf,
return -EINVAL;
u8 *buf __free(kfree) =
- kzalloc(GOODIX_BERLIN_SPI_READ_PREFIX_LEN + val_size,
- GFP_KERNEL);
+ kzalloc(ic_data->read_prefix_len + val_size, GFP_KERNEL);
if (!buf)
return -ENOMEM;
spi_message_init(&spi_msg);
memset(&xfers, 0, sizeof(xfers));
- /* buffer format: 0xF1 + addr(4bytes) + dummy(3bytes) + data */
+ /* buffer format: 0xF1 + addr(4bytes) + dummy(3/4bytes) + data */
buf[0] = GOODIX_BERLIN_SPI_READ_FLAG;
put_unaligned_be32(*reg, buf + GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN);
memset(buf + GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN + GOODIX_BERLIN_REGISTER_WIDTH,
- 0xff, GOODIX_BERLIN_SPI_READ_DUMMY_LEN);
+ 0xff, ic_data->read_dummy_len);
xfers.tx_buf = buf;
xfers.rx_buf = buf;
- xfers.len = GOODIX_BERLIN_SPI_READ_PREFIX_LEN + val_size;
+ xfers.len = ic_data->read_prefix_len + val_size;
xfers.cs_change = 0;
spi_message_add_tail(&xfers, &spi_msg);
@@ -68,7 +72,7 @@ static int goodix_berlin_spi_read(void *context, const void *reg_buf,
return error;
}
- memcpy(val_buf, buf + GOODIX_BERLIN_SPI_READ_PREFIX_LEN, val_size);
+ memcpy(val_buf, buf + ic_data->read_prefix_len, val_size);
return error;
}
@@ -123,6 +127,7 @@ static const struct input_id goodix_berlin_spi_input_id = {
static int goodix_berlin_spi_probe(struct spi_device *spi)
{
+ const struct goodix_berlin_ic_data *ic_data = spi_get_device_match_data(spi);
struct regmap_config regmap_config;
struct regmap *regmap;
size_t max_size;
@@ -137,7 +142,7 @@ static int goodix_berlin_spi_probe(struct spi_device *spi)
max_size = spi_max_transfer_size(spi);
regmap_config = goodix_berlin_spi_regmap_conf;
- regmap_config.max_raw_read = max_size - GOODIX_BERLIN_SPI_READ_PREFIX_LEN;
+ regmap_config.max_raw_read = max_size - ic_data->read_prefix_len;
regmap_config.max_raw_write = max_size - GOODIX_BERLIN_SPI_WRITE_PREFIX_LEN;
regmap = devm_regmap_init(&spi->dev, NULL, spi, &regmap_config);
@@ -145,21 +150,38 @@ static int goodix_berlin_spi_probe(struct spi_device *spi)
return PTR_ERR(regmap);
error = goodix_berlin_probe(&spi->dev, spi->irq,
- &goodix_berlin_spi_input_id, regmap);
+ &goodix_berlin_spi_input_id, regmap,
+ ic_data);
if (error)
return error;
return 0;
}
+static const struct goodix_berlin_ic_data gt9897_data = {
+ .fw_version_info_addr = GOODIX_BERLIN_FW_VERSION_INFO_ADDR_A,
+ .ic_info_addr = GOODIX_BERLIN_IC_INFO_ADDR_A,
+ .read_dummy_len = GOODIX_BERLIN_SPI_READ_DUMMY_LEN_A,
+ .read_prefix_len = GOODIX_BERLIN_SPI_READ_PREFIX_LEN_A,
+};
+
+static const struct goodix_berlin_ic_data gt9916_data = {
+ .fw_version_info_addr = GOODIX_BERLIN_FW_VERSION_INFO_ADDR_D,
+ .ic_info_addr = GOODIX_BERLIN_IC_INFO_ADDR_D,
+ .read_dummy_len = GOODIX_BERLIN_SPI_READ_DUMMY_LEN_D,
+ .read_prefix_len = GOODIX_BERLIN_SPI_READ_PREFIX_LEN_D,
+};
+
static const struct spi_device_id goodix_berlin_spi_ids[] = {
- { "gt9916" },
+ { .name = "gt9897", .driver_data = (long)&gt9897_data },
+ { .name = "gt9916", .driver_data = (long)&gt9916_data },
{ },
};
MODULE_DEVICE_TABLE(spi, goodix_berlin_spi_ids);
static const struct of_device_id goodix_berlin_spi_of_match[] = {
- { .compatible = "goodix,gt9916", },
+ { .compatible = "goodix,gt9897", .data = &gt9897_data },
+ { .compatible = "goodix,gt9916", .data = &gt9916_data },
{ }
};
MODULE_DEVICE_TABLE(of, goodix_berlin_spi_of_match);
diff --git a/drivers/input/touchscreen/goodix_fwupload.c b/drivers/input/touchscreen/goodix_fwupload.c
index 191d4f38d991..5ae9a109ba0d 100644
--- a/drivers/input/touchscreen/goodix_fwupload.c
+++ b/drivers/input/touchscreen/goodix_fwupload.c
@@ -188,13 +188,13 @@ static int goodix_start_firmware(struct i2c_client *client)
static int goodix_firmware_upload(struct goodix_ts_data *ts)
{
- const struct firmware *fw;
char fw_name[64];
const u8 *data;
int error;
snprintf(fw_name, sizeof(fw_name), "goodix/%s", ts->firmware_name);
+ const struct firmware *fw __free(firmware) = NULL;
error = request_firmware(&fw, fw_name, &ts->client->dev);
if (error) {
dev_err(&ts->client->dev, "Firmware request error %d\n", error);
@@ -203,60 +203,61 @@ static int goodix_firmware_upload(struct goodix_ts_data *ts)
error = goodix_firmware_verify(&ts->client->dev, fw);
if (error)
- goto release;
+ return error;
error = goodix_reset_no_int_sync(ts);
if (error)
- goto release;
+ return error;
error = goodix_enter_upload_mode(ts->client);
if (error)
- goto release;
+ return error;
/* Select SRAM bank 0 and upload section 1 & 2 */
error = goodix_i2c_write_u8(ts->client,
GOODIX_REG_MISCTL_SRAM_BANK, 0x00);
if (error)
- goto release;
+ return error;
data = fw->data + GOODIX_FW_HEADER_LENGTH;
error = goodix_i2c_write(ts->client, GOODIX_FW_UPLOAD_ADDRESS,
data, 2 * GOODIX_FW_SECTION_LENGTH);
if (error)
- goto release;
+ return error;
/* Select SRAM bank 1 and upload section 3 & 4 */
error = goodix_i2c_write_u8(ts->client,
GOODIX_REG_MISCTL_SRAM_BANK, 0x01);
if (error)
- goto release;
+ return error;
data += 2 * GOODIX_FW_SECTION_LENGTH;
error = goodix_i2c_write(ts->client, GOODIX_FW_UPLOAD_ADDRESS,
data, 2 * GOODIX_FW_SECTION_LENGTH);
if (error)
- goto release;
+ return error;
/* Select SRAM bank 2 and upload the DSP firmware */
error = goodix_i2c_write_u8(ts->client,
GOODIX_REG_MISCTL_SRAM_BANK, 0x02);
if (error)
- goto release;
+ return error;
data += 2 * GOODIX_FW_SECTION_LENGTH;
error = goodix_i2c_write(ts->client, GOODIX_FW_UPLOAD_ADDRESS,
data, GOODIX_FW_DSP_LENGTH);
if (error)
- goto release;
+ return error;
error = goodix_start_firmware(ts->client);
if (error)
- goto release;
+ return error;
error = goodix_int_sync(ts);
-release:
- release_firmware(fw);
- return error;
+ if (error)
+ return error;
+
+ return 0;
}
static int goodix_prepare_bak_ref(struct goodix_ts_data *ts)
diff --git a/drivers/input/touchscreen/gunze.c b/drivers/input/touchscreen/gunze.c
index dbf92fb02f80..2baeb4f3b941 100644
--- a/drivers/input/touchscreen/gunze.c
+++ b/drivers/input/touchscreen/gunze.c
@@ -97,7 +97,7 @@ static int gunze_connect(struct serio *serio, struct serio_driver *drv)
struct input_dev *input_dev;
int err;
- gunze = kzalloc(sizeof(*gunze), GFP_KERNEL);
+ gunze = kzalloc_obj(*gunze);
input_dev = input_allocate_device();
if (!gunze || !input_dev) {
err = -ENOMEM;
@@ -106,7 +106,7 @@ static int gunze_connect(struct serio *serio, struct serio_driver *drv)
gunze->serio = serio;
gunze->dev = input_dev;
- snprintf(gunze->phys, sizeof(serio->phys), "%s/input0", serio->phys);
+ scnprintf(gunze->phys, sizeof(serio->phys), "%s/input0", serio->phys);
input_dev->name = "Gunze AHL-51S TouchScreen";
input_dev->phys = gunze->phys;
diff --git a/drivers/input/touchscreen/hampshire.c b/drivers/input/touchscreen/hampshire.c
index dc0a2482ddd6..394ae8c88d50 100644
--- a/drivers/input/touchscreen/hampshire.c
+++ b/drivers/input/touchscreen/hampshire.c
@@ -109,7 +109,7 @@ static int hampshire_connect(struct serio *serio, struct serio_driver *drv)
struct input_dev *input_dev;
int err;
- phampshire = kzalloc(sizeof(*phampshire), GFP_KERNEL);
+ phampshire = kzalloc_obj(*phampshire);
input_dev = input_allocate_device();
if (!phampshire || !input_dev) {
err = -ENOMEM;
@@ -118,8 +118,8 @@ static int hampshire_connect(struct serio *serio, struct serio_driver *drv)
phampshire->serio = serio;
phampshire->dev = input_dev;
- snprintf(phampshire->phys, sizeof(phampshire->phys),
- "%s/input0", serio->phys);
+ scnprintf(phampshire->phys, sizeof(phampshire->phys),
+ "%s/input0", serio->phys);
input_dev->name = "Hampshire Serial TouchScreen";
input_dev->phys = phampshire->phys;
diff --git a/drivers/input/touchscreen/hideep.c b/drivers/input/touchscreen/hideep.c
index a73369e15dda..62041bcca83d 100644
--- a/drivers/input/touchscreen/hideep.c
+++ b/drivers/input/touchscreen/hideep.c
@@ -869,8 +869,6 @@ static ssize_t hideep_update_fw(struct device *dev,
{
struct i2c_client *client = to_i2c_client(dev);
struct hideep_ts *ts = i2c_get_clientdata(client);
- const struct firmware *fw_entry;
- char *fw_name;
int mode;
int error;
@@ -878,46 +876,42 @@ static ssize_t hideep_update_fw(struct device *dev,
if (error)
return error;
- fw_name = kasprintf(GFP_KERNEL, "hideep_ts_%04x.bin",
- be16_to_cpu(ts->dwz_info.product_id));
+ const char *fw_name __free(kfree) =
+ kasprintf(GFP_KERNEL, "hideep_ts_%04x.bin",
+ be16_to_cpu(ts->dwz_info.product_id));
if (!fw_name)
return -ENOMEM;
+ const struct firmware *fw_entry __free(firmware) = NULL;
error = request_firmware(&fw_entry, fw_name, dev);
if (error) {
dev_err(dev, "failed to request firmware %s: %d",
fw_name, error);
- goto out_free_fw_name;
+ return error;
}
if (fw_entry->size % sizeof(__be32)) {
dev_err(dev, "invalid firmware size %zu\n", fw_entry->size);
- error = -EINVAL;
- goto out_release_fw;
+ return -EINVAL;
}
if (fw_entry->size > ts->fw_size) {
dev_err(dev, "fw size (%zu) is too big (memory size %d)\n",
fw_entry->size, ts->fw_size);
- error = -EFBIG;
- goto out_release_fw;
+ return -EFBIG;
}
- mutex_lock(&ts->dev_mutex);
- disable_irq(client->irq);
-
- error = hideep_update_firmware(ts, (const __be32 *)fw_entry->data,
- fw_entry->size);
-
- enable_irq(client->irq);
- mutex_unlock(&ts->dev_mutex);
+ scoped_guard(mutex, &ts->dev_mutex) {
+ guard(disable_irq)(&client->irq);
-out_release_fw:
- release_firmware(fw_entry);
-out_free_fw_name:
- kfree(fw_name);
+ error = hideep_update_firmware(ts,
+ (const __be32 *)fw_entry->data,
+ fw_entry->size);
+ if (error)
+ return error;
+ }
- return error ?: count;
+ return count;
}
static ssize_t hideep_fw_version_show(struct device *dev,
@@ -925,13 +919,9 @@ static ssize_t hideep_fw_version_show(struct device *dev,
{
struct i2c_client *client = to_i2c_client(dev);
struct hideep_ts *ts = i2c_get_clientdata(client);
- ssize_t len;
- mutex_lock(&ts->dev_mutex);
- len = sysfs_emit(buf, "%04x\n", be16_to_cpu(ts->dwz_info.release_ver));
- mutex_unlock(&ts->dev_mutex);
-
- return len;
+ guard(mutex)(&ts->dev_mutex);
+ return sysfs_emit(buf, "%04x\n", be16_to_cpu(ts->dwz_info.release_ver));
}
static ssize_t hideep_product_id_show(struct device *dev,
@@ -939,13 +929,9 @@ static ssize_t hideep_product_id_show(struct device *dev,
{
struct i2c_client *client = to_i2c_client(dev);
struct hideep_ts *ts = i2c_get_clientdata(client);
- ssize_t len;
-
- mutex_lock(&ts->dev_mutex);
- len = sysfs_emit(buf, "%04x\n", be16_to_cpu(ts->dwz_info.product_id));
- mutex_unlock(&ts->dev_mutex);
- return len;
+ guard(mutex)(&ts->dev_mutex);
+ return sysfs_emit(buf, "%04x\n", be16_to_cpu(ts->dwz_info.product_id));
}
static DEVICE_ATTR(version, 0664, hideep_fw_version_show, NULL);
diff --git a/drivers/input/touchscreen/himax_hx852x.c b/drivers/input/touchscreen/himax_hx852x.c
new file mode 100644
index 000000000000..83c60e137a55
--- /dev/null
+++ b/drivers/input/touchscreen/himax_hx852x.c
@@ -0,0 +1,503 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Himax HX852x(ES) Touchscreen Driver
+ * Copyright (c) 2020-2024 Stephan Gerhold <stephan@gerhold.net>
+ * Copyright (c) 2020 Jonathan Albrieux <jonathan.albrieux@gmail.com>
+ *
+ * Based on the Himax Android Driver Sample Code Ver 0.3 for HMX852xES chipset:
+ * Copyright (c) 2014 Himax Corporation.
+ */
+
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/input/mt.h>
+#include <linux/input/touchscreen.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+#include <linux/unaligned.h>
+
+#define HX852X_COORD_SIZE(fingers) ((fingers) * sizeof(struct hx852x_coord))
+#define HX852X_WIDTH_SIZE(fingers) ALIGN(fingers, 4)
+#define HX852X_BUF_SIZE(fingers) (HX852X_COORD_SIZE(fingers) + \
+ HX852X_WIDTH_SIZE(fingers) + \
+ sizeof(struct hx852x_touch_info))
+
+#define HX852X_MAX_FINGERS 12
+#define HX852X_MAX_KEY_COUNT 4
+#define HX852X_MAX_BUF_SIZE HX852X_BUF_SIZE(HX852X_MAX_FINGERS)
+
+#define HX852X_TS_SLEEP_IN 0x80
+#define HX852X_TS_SLEEP_OUT 0x81
+#define HX852X_TS_SENSE_OFF 0x82
+#define HX852X_TS_SENSE_ON 0x83
+#define HX852X_READ_ONE_EVENT 0x85
+#define HX852X_READ_ALL_EVENTS 0x86
+#define HX852X_READ_LATEST_EVENT 0x87
+#define HX852X_CLEAR_EVENT_STACK 0x88
+
+#define HX852X_REG_SRAM_SWITCH 0x8c
+#define HX852X_REG_SRAM_ADDR 0x8b
+#define HX852X_REG_FLASH_RPLACE 0x5a
+
+#define HX852X_SRAM_SWITCH_TEST_MODE 0x14
+#define HX852X_SRAM_ADDR_CONFIG 0x7000
+
+struct hx852x {
+ struct i2c_client *client;
+ struct input_dev *input_dev;
+ struct touchscreen_properties props;
+ struct gpio_desc *reset_gpiod;
+ struct regulator_bulk_data supplies[2];
+ unsigned int max_fingers;
+ unsigned int keycount;
+ unsigned int keycodes[HX852X_MAX_KEY_COUNT];
+};
+
+struct hx852x_config {
+ u8 rx_num;
+ u8 tx_num;
+ u8 max_pt;
+ u8 padding1[3];
+ __be16 x_res;
+ __be16 y_res;
+ u8 padding2[2];
+} __packed __aligned(4);
+
+struct hx852x_coord {
+ __be16 x;
+ __be16 y;
+} __packed __aligned(4);
+
+struct hx852x_touch_info {
+ u8 finger_num;
+ __le16 finger_pressed;
+ u8 padding;
+} __packed __aligned(4);
+
+static int hx852x_i2c_read(struct hx852x *hx, u8 cmd, void *data, u16 len)
+{
+ struct i2c_client *client = hx->client;
+ int error;
+ int ret;
+
+ struct i2c_msg msg[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = 1,
+ .buf = &cmd,
+ },
+ {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = len,
+ .buf = data,
+ },
+ };
+
+ ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
+ if (ret != ARRAY_SIZE(msg)) {
+ error = ret < 0 ? ret : -EIO;
+ dev_err(&client->dev, "failed to read %#x: %d\n", cmd, error);
+ return error;
+ }
+
+ return 0;
+}
+
+static int hx852x_power_on(struct hx852x *hx)
+{
+ struct device *dev = &hx->client->dev;
+ int error;
+
+ error = regulator_bulk_enable(ARRAY_SIZE(hx->supplies), hx->supplies);
+ if (error) {
+ dev_err(dev, "failed to enable regulators: %d\n", error);
+ return error;
+ }
+
+ gpiod_set_value_cansleep(hx->reset_gpiod, 1);
+ msleep(20);
+ gpiod_set_value_cansleep(hx->reset_gpiod, 0);
+ msleep(50);
+
+ return 0;
+}
+
+static int hx852x_start(struct hx852x *hx)
+{
+ struct device *dev = &hx->client->dev;
+ int error;
+
+ error = i2c_smbus_write_byte(hx->client, HX852X_TS_SLEEP_OUT);
+ if (error) {
+ dev_err(dev, "failed to send TS_SLEEP_OUT: %d\n", error);
+ return error;
+ }
+ msleep(30);
+
+ error = i2c_smbus_write_byte(hx->client, HX852X_TS_SENSE_ON);
+ if (error) {
+ dev_err(dev, "failed to send TS_SENSE_ON: %d\n", error);
+ return error;
+ }
+ msleep(20);
+
+ return 0;
+}
+
+static int hx852x_stop(struct hx852x *hx)
+{
+ struct device *dev = &hx->client->dev;
+ int error;
+
+ error = i2c_smbus_write_byte(hx->client, HX852X_TS_SENSE_OFF);
+ if (error) {
+ dev_err(dev, "failed to send TS_SENSE_OFF: %d\n", error);
+ return error;
+ }
+ msleep(20);
+
+ error = i2c_smbus_write_byte(hx->client, HX852X_TS_SLEEP_IN);
+ if (error) {
+ dev_err(dev, "failed to send TS_SLEEP_IN: %d\n", error);
+ return error;
+ }
+ msleep(30);
+
+ return 0;
+}
+
+static int hx852x_power_off(struct hx852x *hx)
+{
+ struct device *dev = &hx->client->dev;
+ int error;
+
+ error = regulator_bulk_disable(ARRAY_SIZE(hx->supplies), hx->supplies);
+ if (error) {
+ dev_err(dev, "failed to disable regulators: %d\n", error);
+ return error;
+ }
+
+ return 0;
+}
+
+static int hx852x_read_config(struct hx852x *hx)
+{
+ struct device *dev = &hx->client->dev;
+ struct hx852x_config conf;
+ int x_res, y_res;
+ int error, error2;
+
+ error = hx852x_power_on(hx);
+ if (error)
+ return error;
+
+ /* Sensing must be turned on briefly to load the config */
+ error = hx852x_start(hx);
+ if (error)
+ goto err_power_off;
+
+ error = hx852x_stop(hx);
+ if (error)
+ goto err_power_off;
+
+ error = i2c_smbus_write_byte_data(hx->client, HX852X_REG_SRAM_SWITCH,
+ HX852X_SRAM_SWITCH_TEST_MODE);
+ if (error)
+ goto err_power_off;
+
+ error = i2c_smbus_write_word_data(hx->client, HX852X_REG_SRAM_ADDR,
+ HX852X_SRAM_ADDR_CONFIG);
+ if (error)
+ goto err_test_mode;
+
+ error = hx852x_i2c_read(hx, HX852X_REG_FLASH_RPLACE, &conf, sizeof(conf));
+ if (error)
+ goto err_test_mode;
+
+ x_res = be16_to_cpu(conf.x_res);
+ y_res = be16_to_cpu(conf.y_res);
+ hx->max_fingers = (conf.max_pt & 0xf0) >> 4;
+ dev_dbg(dev, "x res: %u, y res: %u, max fingers: %u\n",
+ x_res, y_res, hx->max_fingers);
+
+ if (hx->max_fingers > HX852X_MAX_FINGERS) {
+ dev_err(dev, "max supported fingers: %u, found: %u\n",
+ HX852X_MAX_FINGERS, hx->max_fingers);
+ error = -EINVAL;
+ goto err_test_mode;
+ }
+
+ if (x_res && y_res) {
+ input_set_abs_params(hx->input_dev, ABS_MT_POSITION_X, 0, x_res - 1, 0, 0);
+ input_set_abs_params(hx->input_dev, ABS_MT_POSITION_Y, 0, y_res - 1, 0, 0);
+ }
+
+err_test_mode:
+ error2 = i2c_smbus_write_byte_data(hx->client, HX852X_REG_SRAM_SWITCH, 0);
+ error = error ?: error2;
+err_power_off:
+ error2 = hx852x_power_off(hx);
+ return error ?: error2;
+}
+
+static int hx852x_handle_events(struct hx852x *hx)
+{
+ /*
+ * The event packets have variable size, depending on the amount of
+ * supported fingers (hx->max_fingers). They are laid out as follows:
+ * - struct hx852x_coord[hx->max_fingers]: Coordinates for each finger
+ * - u8[ALIGN(hx->max_fingers, 4)]: Touch width for each finger
+ * with padding for 32-bit alignment
+ * - struct hx852x_touch_info
+ *
+ * Load everything into a 32-bit aligned buffer so the coordinates
+ * can be assigned directly, without using get_unaligned_*().
+ */
+ u8 buf[HX852X_MAX_BUF_SIZE] __aligned(4);
+ struct hx852x_coord *coord = (struct hx852x_coord *)buf;
+ u8 *width = &buf[HX852X_COORD_SIZE(hx->max_fingers)];
+ struct hx852x_touch_info *info = (struct hx852x_touch_info *)
+ &width[HX852X_WIDTH_SIZE(hx->max_fingers)];
+ unsigned long finger_pressed, key_pressed;
+ unsigned int i, x, y, w;
+ int error;
+
+ error = hx852x_i2c_read(hx, HX852X_READ_ALL_EVENTS, buf,
+ HX852X_BUF_SIZE(hx->max_fingers));
+ if (error)
+ return error;
+
+ finger_pressed = get_unaligned_le16(&info->finger_pressed);
+ key_pressed = finger_pressed >> HX852X_MAX_FINGERS;
+
+ /* All bits are set when no touch is detected */
+ if (info->finger_num == 0xff || !(info->finger_num & 0x0f))
+ finger_pressed = 0;
+ if (key_pressed == 0xf)
+ key_pressed = 0;
+
+ for_each_set_bit(i, &finger_pressed, hx->max_fingers) {
+ x = be16_to_cpu(coord[i].x);
+ y = be16_to_cpu(coord[i].y);
+ w = width[i];
+
+ input_mt_slot(hx->input_dev, i);
+ input_mt_report_slot_state(hx->input_dev, MT_TOOL_FINGER, 1);
+ touchscreen_report_pos(hx->input_dev, &hx->props, x, y, true);
+ input_report_abs(hx->input_dev, ABS_MT_TOUCH_MAJOR, w);
+ }
+ input_mt_sync_frame(hx->input_dev);
+
+ for (i = 0; i < hx->keycount; i++)
+ input_report_key(hx->input_dev, hx->keycodes[i], key_pressed & BIT(i));
+
+ input_sync(hx->input_dev);
+ return 0;
+}
+
+static irqreturn_t hx852x_interrupt(int irq, void *ptr)
+{
+ struct hx852x *hx = ptr;
+ int error;
+
+ error = hx852x_handle_events(hx);
+ if (error) {
+ dev_err_ratelimited(&hx->client->dev,
+ "failed to handle events: %d\n", error);
+ return IRQ_NONE;
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int hx852x_input_open(struct input_dev *dev)
+{
+ struct hx852x *hx = input_get_drvdata(dev);
+ int error;
+
+ error = hx852x_power_on(hx);
+ if (error)
+ return error;
+
+ error = hx852x_start(hx);
+ if (error) {
+ hx852x_power_off(hx);
+ return error;
+ }
+
+ enable_irq(hx->client->irq);
+ return 0;
+}
+
+static void hx852x_input_close(struct input_dev *dev)
+{
+ struct hx852x *hx = input_get_drvdata(dev);
+
+ hx852x_stop(hx);
+ disable_irq(hx->client->irq);
+ hx852x_power_off(hx);
+}
+
+static int hx852x_parse_properties(struct hx852x *hx)
+{
+ struct device *dev = &hx->client->dev;
+ int error, count;
+
+ count = device_property_count_u32(dev, "linux,keycodes");
+ if (count == -EINVAL) {
+ /* Property does not exist, keycodes are optional */
+ return 0;
+ } else if (count < 0) {
+ dev_err(dev, "Failed to read linux,keycodes: %d\n", count);
+ return count;
+ } else if (count > HX852X_MAX_KEY_COUNT) {
+ dev_err(dev, "max supported keys: %u, found: %u\n",
+ HX852X_MAX_KEY_COUNT, hx->keycount);
+ return -EINVAL;
+ }
+ hx->keycount = count;
+
+ error = device_property_read_u32_array(dev, "linux,keycodes",
+ hx->keycodes, hx->keycount);
+ if (error) {
+ dev_err(dev, "failed to read linux,keycodes: %d\n", error);
+ return error;
+ }
+
+ return 0;
+}
+
+static int hx852x_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct hx852x *hx;
+ int error, i;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C |
+ I2C_FUNC_SMBUS_WRITE_BYTE |
+ I2C_FUNC_SMBUS_WRITE_BYTE_DATA |
+ I2C_FUNC_SMBUS_WRITE_WORD_DATA)) {
+ dev_err(dev, "not all required i2c functionality supported\n");
+ return -ENXIO;
+ }
+
+ hx = devm_kzalloc(dev, sizeof(*hx), GFP_KERNEL);
+ if (!hx)
+ return -ENOMEM;
+
+ hx->client = client;
+ hx->input_dev = devm_input_allocate_device(dev);
+ if (!hx->input_dev)
+ return -ENOMEM;
+
+ hx->input_dev->name = "Himax HX852x";
+ hx->input_dev->id.bustype = BUS_I2C;
+ hx->input_dev->open = hx852x_input_open;
+ hx->input_dev->close = hx852x_input_close;
+
+ i2c_set_clientdata(client, hx);
+ input_set_drvdata(hx->input_dev, hx);
+
+ hx->supplies[0].supply = "vcca";
+ hx->supplies[1].supply = "vccd";
+ error = devm_regulator_bulk_get(dev, ARRAY_SIZE(hx->supplies), hx->supplies);
+ if (error)
+ return dev_err_probe(dev, error, "failed to get regulators\n");
+
+ hx->reset_gpiod = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(hx->reset_gpiod))
+ return dev_err_probe(dev, PTR_ERR(hx->reset_gpiod),
+ "failed to get reset gpio\n");
+
+ error = devm_request_threaded_irq(dev, client->irq, NULL, hx852x_interrupt,
+ IRQF_ONESHOT | IRQF_NO_AUTOEN, NULL, hx);
+ if (error)
+ return dev_err_probe(dev, error, "failed to request irq %d", client->irq);
+
+ error = hx852x_read_config(hx);
+ if (error)
+ return error;
+
+ input_set_capability(hx->input_dev, EV_ABS, ABS_MT_POSITION_X);
+ input_set_capability(hx->input_dev, EV_ABS, ABS_MT_POSITION_Y);
+ input_set_abs_params(hx->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
+
+ touchscreen_parse_properties(hx->input_dev, true, &hx->props);
+ error = hx852x_parse_properties(hx);
+ if (error)
+ return error;
+
+ hx->input_dev->keycode = hx->keycodes;
+ hx->input_dev->keycodemax = hx->keycount;
+ hx->input_dev->keycodesize = sizeof(hx->keycodes[0]);
+ for (i = 0; i < hx->keycount; i++)
+ input_set_capability(hx->input_dev, EV_KEY, hx->keycodes[i]);
+
+ error = input_mt_init_slots(hx->input_dev, hx->max_fingers,
+ INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
+ if (error)
+ return dev_err_probe(dev, error, "failed to init MT slots\n");
+
+ error = input_register_device(hx->input_dev);
+ if (error)
+ return dev_err_probe(dev, error, "failed to register input device\n");
+
+ return 0;
+}
+
+static int hx852x_suspend(struct device *dev)
+{
+ struct hx852x *hx = dev_get_drvdata(dev);
+
+ guard(mutex)(&hx->input_dev->mutex);
+
+ if (input_device_enabled(hx->input_dev))
+ return hx852x_stop(hx);
+
+ return 0;
+}
+
+static int hx852x_resume(struct device *dev)
+{
+ struct hx852x *hx = dev_get_drvdata(dev);
+
+ guard(mutex)(&hx->input_dev->mutex);
+
+ if (input_device_enabled(hx->input_dev))
+ return hx852x_start(hx);
+
+ return 0;
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(hx852x_pm_ops, hx852x_suspend, hx852x_resume);
+
+#ifdef CONFIG_OF
+static const struct of_device_id hx852x_of_match[] = {
+ { .compatible = "himax,hx852es" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, hx852x_of_match);
+#endif
+
+static struct i2c_driver hx852x_driver = {
+ .probe = hx852x_probe,
+ .driver = {
+ .name = "himax_hx852x",
+ .pm = pm_sleep_ptr(&hx852x_pm_ops),
+ .of_match_table = of_match_ptr(hx852x_of_match),
+ },
+};
+module_i2c_driver(hx852x_driver);
+
+MODULE_DESCRIPTION("Himax HX852x(ES) Touchscreen Driver");
+MODULE_AUTHOR("Jonathan Albrieux <jonathan.albrieux@gmail.com>");
+MODULE_AUTHOR("Stephan Gerhold <stephan@gerhold.net>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/hycon-hy46xx.c b/drivers/input/touchscreen/hycon-hy46xx.c
index b2ff7a45b908..1513f20cbf51 100644
--- a/drivers/input/touchscreen/hycon-hy46xx.c
+++ b/drivers/input/touchscreen/hycon-hy46xx.c
@@ -181,18 +181,17 @@ static ssize_t hycon_hy46xx_setting_show(struct device *dev,
struct hycon_hy46xx_attribute *attr =
container_of(dattr, struct hycon_hy46xx_attribute, dattr);
u8 *field = (u8 *)tsdata + attr->field_offset;
- size_t count = 0;
int error = 0;
int val;
- mutex_lock(&tsdata->mutex);
+ guard(mutex)(&tsdata->mutex);
error = regmap_read(tsdata->regmap, attr->address, &val);
- if (error < 0) {
+ if (error) {
dev_err(&tsdata->client->dev,
"Failed to fetch attribute %s, error %d\n",
dattr->attr.name, error);
- goto out;
+ return error;
}
if (val != *field) {
@@ -202,11 +201,7 @@ static ssize_t hycon_hy46xx_setting_show(struct device *dev,
*field = val;
}
- count = sysfs_emit(buf, "%d\n", val);
-
-out:
- mutex_unlock(&tsdata->mutex);
- return error ?: count;
+ return sysfs_emit(buf, "%d\n", val);
}
static ssize_t hycon_hy46xx_setting_store(struct device *dev,
@@ -221,29 +216,25 @@ static ssize_t hycon_hy46xx_setting_store(struct device *dev,
unsigned int val;
int error;
- mutex_lock(&tsdata->mutex);
+ guard(mutex)(&tsdata->mutex);
error = kstrtouint(buf, 0, &val);
if (error)
- goto out;
+ return error;
- if (val < attr->limit_low || val > attr->limit_high) {
- error = -ERANGE;
- goto out;
- }
+ if (val < attr->limit_low || val > attr->limit_high)
+ return -ERANGE;
error = regmap_write(tsdata->regmap, attr->address, val);
- if (error < 0) {
+ if (error) {
dev_err(&tsdata->client->dev,
"Failed to update attribute %s, error: %d\n",
dattr->attr.name, error);
- goto out;
+ return error;
}
*field = val;
-out:
- mutex_unlock(&tsdata->mutex);
- return error ?: count;
+ return count;
}
static HYCON_ATTR_U8(threshold, 0644, HY46XX_THRESHOLD, 0, 255);
diff --git a/drivers/input/touchscreen/hynitron-cst816x.c b/drivers/input/touchscreen/hynitron-cst816x.c
new file mode 100644
index 000000000000..b64d7928e18f
--- /dev/null
+++ b/drivers/input/touchscreen/hynitron-cst816x.c
@@ -0,0 +1,253 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Driver for I2C connected Hynitron CST816x Series Touchscreen
+ *
+ * Copyright (C) 2025 Oleh Kuzhylnyi <kuzhylol@gmail.com>
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/unaligned.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+
+#define CST816X_RD_REG 0x01
+#define CST816X_NUM_KEYS 5
+
+struct cst816x_touch {
+ u8 gest;
+ u8 active;
+ u16 abs_x;
+ u16 abs_y;
+} __packed;
+
+struct cst816x_priv {
+ struct i2c_client *client;
+ struct gpio_desc *reset;
+ struct input_dev *input;
+ unsigned int keycode[CST816X_NUM_KEYS];
+ unsigned int keycodemax;
+};
+
+static int cst816x_parse_keycodes(struct device *dev, struct cst816x_priv *priv)
+{
+ int count;
+ int error;
+
+ if (device_property_present(dev, "linux,keycodes")) {
+ count = device_property_count_u32(dev, "linux,keycodes");
+ if (count < 0) {
+ error = count;
+ dev_err(dev, "failed to count keys: %d\n", error);
+ return error;
+ } else if (count > ARRAY_SIZE(priv->keycode)) {
+ dev_err(dev, "too many keys defined: %d\n", count);
+ return -EINVAL;
+ }
+ priv->keycodemax = count;
+
+ error = device_property_read_u32_array(dev, "linux,keycodes",
+ priv->keycode,
+ priv->keycodemax);
+ if (error) {
+ dev_err(dev, "failed to read keycodes: %d\n", error);
+ return error;
+ }
+ }
+
+ return 0;
+}
+
+static int cst816x_i2c_read_register(struct cst816x_priv *priv, u8 reg,
+ void *buf, size_t len)
+{
+ struct i2c_msg xfer[] = {
+ {
+ .addr = priv->client->addr,
+ .flags = 0,
+ .buf = &reg,
+ .len = sizeof(reg),
+ },
+ {
+ .addr = priv->client->addr,
+ .flags = I2C_M_RD,
+ .buf = buf,
+ .len = len,
+ },
+ };
+ int error;
+ int ret;
+
+ ret = i2c_transfer(priv->client->adapter, xfer, ARRAY_SIZE(xfer));
+ if (ret != ARRAY_SIZE(xfer)) {
+ error = ret < 0 ? ret : -EIO;
+ dev_err(&priv->client->dev, "i2c rx err: %d\n", error);
+ return error;
+ }
+
+ return 0;
+}
+
+static u8 cst816x_gest_idx(u8 gest)
+{
+ u8 index;
+
+ switch (gest) {
+ case 0x01: /* Slide up gesture */
+ case 0x02: /* Slide down gesture */
+ case 0x03: /* Slide left gesture */
+ case 0x04: /* Slide right gesture */
+ index = gest;
+ break;
+ case 0x0c: /* Long press gesture */
+ default:
+ index = CST816X_NUM_KEYS;
+ break;
+ }
+
+ return index - 1;
+}
+
+static bool cst816x_process_touch(struct cst816x_priv *priv,
+ struct cst816x_touch *tch)
+{
+ if (cst816x_i2c_read_register(priv, CST816X_RD_REG, tch, sizeof(*tch)))
+ return false;
+
+ tch->abs_x = get_unaligned_be16(&tch->abs_x) & GENMASK(11, 0);
+ tch->abs_y = get_unaligned_be16(&tch->abs_y) & GENMASK(11, 0);
+
+ dev_dbg(&priv->client->dev, "x: %u, y: %u, t: %u, g: 0x%x\n",
+ tch->abs_x, tch->abs_y, tch->active, tch->gest);
+
+ return true;
+}
+
+static int cst816x_register_input(struct cst816x_priv *priv)
+{
+ priv->input = devm_input_allocate_device(&priv->client->dev);
+ if (!priv->input)
+ return -ENOMEM;
+
+ priv->input->name = "Hynitron CST816x Series Touchscreen";
+ priv->input->phys = "input/ts";
+ priv->input->id.bustype = BUS_I2C;
+
+ input_set_drvdata(priv->input, priv);
+
+ input_set_abs_params(priv->input, ABS_X, 0, 240, 0, 0);
+ input_set_abs_params(priv->input, ABS_Y, 0, 240, 0, 0);
+ input_set_capability(priv->input, EV_KEY, BTN_TOUCH);
+
+ priv->input->keycode = priv->keycode;
+ priv->input->keycodesize = sizeof(priv->keycode[0]);
+ priv->input->keycodemax = priv->keycodemax;
+
+ for (int i = 0; i < priv->keycodemax; i++) {
+ if (priv->keycode[i] == KEY_RESERVED)
+ continue;
+
+ input_set_capability(priv->input, EV_KEY, priv->keycode[i]);
+ }
+
+ return input_register_device(priv->input);
+}
+
+static void cst816x_reset(struct cst816x_priv *priv)
+{
+ gpiod_set_value_cansleep(priv->reset, 1);
+ msleep(50);
+ gpiod_set_value_cansleep(priv->reset, 0);
+ msleep(100);
+}
+
+static irqreturn_t cst816x_irq_cb(int irq, void *cookie)
+{
+ struct cst816x_priv *priv = cookie;
+ struct cst816x_touch tch;
+
+ if (!cst816x_process_touch(priv, &tch))
+ return IRQ_HANDLED;
+
+ input_report_abs(priv->input, ABS_X, tch.abs_x);
+ input_report_abs(priv->input, ABS_Y, tch.abs_y);
+
+ if (tch.gest)
+ input_report_key(priv->input,
+ priv->keycode[cst816x_gest_idx(tch.gest)],
+ tch.active);
+
+ input_report_key(priv->input, BTN_TOUCH, tch.active);
+
+ input_sync(priv->input);
+
+ return IRQ_HANDLED;
+}
+
+static int cst816x_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct cst816x_priv *priv;
+ int error;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->client = client;
+
+ priv->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(priv->reset))
+ return dev_err_probe(dev, PTR_ERR(priv->reset),
+ "gpio reset request failed\n");
+
+ if (priv->reset)
+ cst816x_reset(priv);
+
+ error = cst816x_parse_keycodes(dev, priv);
+ if (error)
+ dev_warn(dev, "no gestures found in dt\n");
+
+ error = cst816x_register_input(priv);
+ if (error)
+ return dev_err_probe(dev, error, "input register failed\n");
+
+ error = devm_request_threaded_irq(dev, client->irq,
+ NULL, cst816x_irq_cb, IRQF_ONESHOT,
+ dev_driver_string(dev), priv);
+ if (error)
+ return dev_err_probe(dev, error, "irq request failed\n");
+
+ return 0;
+}
+
+static const struct i2c_device_id cst816x_id[] = {
+ { .name = "cst816s", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, cst816x_id);
+
+static const struct of_device_id cst816x_of_match[] = {
+ { .compatible = "hynitron,cst816s", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, cst816x_of_match);
+
+static struct i2c_driver cst816x_driver = {
+ .driver = {
+ .name = "cst816x",
+ .of_match_table = cst816x_of_match,
+ },
+ .id_table = cst816x_id,
+ .probe = cst816x_probe,
+};
+
+module_i2c_driver(cst816x_driver);
+
+MODULE_AUTHOR("Oleh Kuzhylnyi <kuzhylol@gmail.com>");
+MODULE_DESCRIPTION("Hynitron CST816x Series Touchscreen Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c
index fa38d70aded7..3bf524a6ee20 100644
--- a/drivers/input/touchscreen/ili210x.c
+++ b/drivers/input/touchscreen/ili210x.c
@@ -327,9 +327,8 @@ static bool ili210x_report_events(struct ili210x *priv, u8 *touchdata)
return contact;
}
-static irqreturn_t ili210x_irq(int irq, void *irq_data)
+static void ili210x_process_events(struct ili210x *priv)
{
- struct ili210x *priv = irq_data;
struct i2c_client *client = priv->client;
const struct ili2xxx_chip *chip = priv->chip;
u8 touchdata[ILI210X_DATA_SIZE] = { 0 };
@@ -356,8 +355,22 @@ static irqreturn_t ili210x_irq(int irq, void *irq_data)
usleep_range(time_delta, time_delta + 1000);
}
} while (!priv->stop && keep_polling);
+}
+
+static irqreturn_t ili210x_irq(int irq, void *irq_data)
+{
+ struct ili210x *priv = irq_data;
+
+ ili210x_process_events(priv);
return IRQ_HANDLED;
+};
+
+static void ili210x_work_i2c_poll(struct input_dev *input)
+{
+ struct ili210x *priv = input_get_drvdata(input);
+
+ ili210x_process_events(priv);
}
static int ili251x_firmware_update_resolution(struct device *dev)
@@ -829,12 +842,32 @@ static int ili210x_do_firmware_update(struct ili210x *priv,
return 0;
}
+static ssize_t ili210x_firmware_update(struct device *dev, const u8 *fwbuf,
+ u16 ac_end, u16 df_end)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct ili210x *priv = i2c_get_clientdata(client);
+ const char *fwname = ILI251X_FW_FILENAME;
+ int error;
+
+ dev_dbg(dev, "Firmware update started, firmware=%s\n", fwname);
+
+ ili210x_hardware_reset(priv->reset_gpio);
+
+ error = ili210x_do_firmware_update(priv, fwbuf, ac_end, df_end);
+
+ ili210x_hardware_reset(priv->reset_gpio);
+
+ dev_dbg(dev, "Firmware update ended, error=%i\n", error);
+
+ return error;
+}
+
static ssize_t ili210x_firmware_update_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
- struct ili210x *priv = i2c_get_clientdata(client);
const char *fwname = ILI251X_FW_FILENAME;
u16 ac_end, df_end;
int error;
@@ -860,16 +893,11 @@ static ssize_t ili210x_firmware_update_store(struct device *dev,
* the touch controller to disable the IRQs during update, so we have
* to do it this way here.
*/
- scoped_guard(disable_irq, &client->irq) {
- dev_dbg(dev, "Firmware update started, firmware=%s\n", fwname);
-
- ili210x_hardware_reset(priv->reset_gpio);
-
- error = ili210x_do_firmware_update(priv, fwbuf, ac_end, df_end);
-
- ili210x_hardware_reset(priv->reset_gpio);
-
- dev_dbg(dev, "Firmware update ended, error=%i\n", error);
+ if (client->irq > 0) {
+ guard(disable_irq)(&client->irq);
+ error = ili210x_firmware_update(dev, fwbuf, ac_end, df_end);
+ } else {
+ error = ili210x_firmware_update(dev, fwbuf, ac_end, df_end);
}
return error ?: count;
@@ -942,15 +970,8 @@ static int ili210x_i2c_probe(struct i2c_client *client)
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;
- }
+ if (!chip)
+ return dev_err_probe(&client->dev, -ENODEV, "unknown device model\n");
reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
if (IS_ERR(reset_gpio))
@@ -998,17 +1019,22 @@ static int ili210x_i2c_probe(struct i2c_client *client)
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;
- }
+ if (error)
+ return dev_err_probe(dev, error, "Unable to set up slots\n");
- 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;
+ input_set_drvdata(input, priv);
+
+ if (client->irq > 0) {
+ error = devm_request_threaded_irq(dev, client->irq, NULL, ili210x_irq,
+ IRQF_ONESHOT, client->name, priv);
+ if (error)
+ return dev_err_probe(dev, error, "Unable to request touchscreen IRQ\n");
+ } else {
+ error = input_setup_polling(input, ili210x_work_i2c_poll);
+ if (error)
+ return dev_err_probe(dev, error, "Could not set up polling mode\n");
+
+ input_set_poll_interval(input, ILI2XXX_POLL_PERIOD);
}
error = devm_add_action_or_reset(dev, ili210x_stop, priv);
@@ -1016,10 +1042,8 @@ static int ili210x_i2c_probe(struct i2c_client *client)
return error;
error = input_register_device(priv->input);
- if (error) {
- dev_err(dev, "Cannot register input device, err: %d\n", error);
- return error;
- }
+ if (error)
+ return dev_err_probe(dev, error, "Cannot register input device\n");
return 0;
}
diff --git a/drivers/input/touchscreen/ilitek_ts_i2c.c b/drivers/input/touchscreen/ilitek_ts_i2c.c
index 0dd632724a00..0706443792ba 100644
--- a/drivers/input/touchscreen/ilitek_ts_i2c.c
+++ b/drivers/input/touchscreen/ilitek_ts_i2c.c
@@ -122,7 +122,7 @@ static int ilitek_i2c_write_and_read(struct ilitek_ts_data *ts,
return error;
}
if (delay > 0)
- mdelay(delay);
+ fsleep(delay * 1000);
if (read_len > 0) {
error = i2c_transfer(client->adapter, msgs + 1, 1);
@@ -396,10 +396,10 @@ static const struct ilitek_protocol_map ptl_func_map[] = {
static void ilitek_reset(struct ilitek_ts_data *ts, int delay)
{
if (ts->reset_gpio) {
- gpiod_set_value(ts->reset_gpio, 1);
- mdelay(10);
- gpiod_set_value(ts->reset_gpio, 0);
- mdelay(delay);
+ gpiod_set_value_cansleep(ts->reset_gpio, 1);
+ fsleep(10000);
+ gpiod_set_value_cansleep(ts->reset_gpio, 0);
+ fsleep(delay * 1000);
}
}
diff --git a/drivers/input/touchscreen/imagis.c b/drivers/input/touchscreen/imagis.c
index 3c8bbe284b73..7bbb00beec3b 100644
--- a/drivers/input/touchscreen/imagis.c
+++ b/drivers/input/touchscreen/imagis.c
@@ -366,32 +366,34 @@ static int imagis_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct imagis_ts *ts = i2c_get_clientdata(client);
- int retval = 0;
-
- mutex_lock(&ts->input_dev->mutex);
+ int error;
- if (input_device_enabled(ts->input_dev))
- retval = imagis_stop(ts);
+ guard(mutex)(&ts->input_dev->mutex);
- mutex_unlock(&ts->input_dev->mutex);
+ if (input_device_enabled(ts->input_dev)) {
+ error = imagis_stop(ts);
+ if (error)
+ return error;
+ }
- return retval;
+ return 0;
}
static int imagis_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct imagis_ts *ts = i2c_get_clientdata(client);
- int retval = 0;
-
- mutex_lock(&ts->input_dev->mutex);
+ int error;
- if (input_device_enabled(ts->input_dev))
- retval = imagis_start(ts);
+ guard(mutex)(&ts->input_dev->mutex);
- mutex_unlock(&ts->input_dev->mutex);
+ if (input_device_enabled(ts->input_dev)) {
+ error = imagis_start(ts);
+ if (error)
+ return error;
+ }
- return retval;
+ return 0;
}
static DEFINE_SIMPLE_DEV_PM_OPS(imagis_pm_ops, imagis_suspend, imagis_resume);
diff --git a/drivers/input/touchscreen/imx6ul_tsc.c b/drivers/input/touchscreen/imx6ul_tsc.c
index 6ac8fa84ed9f..43d6c69e3088 100644
--- a/drivers/input/touchscreen/imx6ul_tsc.c
+++ b/drivers/input/touchscreen/imx6ul_tsc.c
@@ -7,6 +7,7 @@
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/bitfield.h>
#include <linux/gpio/consumer.h>
#include <linux/input.h>
#include <linux/slab.h>
@@ -20,25 +21,23 @@
#include <linux/log2.h>
/* ADC configuration registers field define */
-#define ADC_AIEN (0x1 << 7)
+#define ADC_AIEN BIT(7)
+#define ADC_ADCH_MASK GENMASK(4, 0)
#define ADC_CONV_DISABLE 0x1F
-#define ADC_AVGE (0x1 << 5)
-#define ADC_CAL (0x1 << 7)
-#define ADC_CALF 0x2
-#define ADC_12BIT_MODE (0x2 << 2)
-#define ADC_CONV_MODE_MASK (0x3 << 2)
+#define ADC_AVGE BIT(5)
+#define ADC_CAL BIT(7)
+#define ADC_CALF BIT(1)
+#define ADC_CONV_MODE_MASK GENMASK(3, 2)
+#define ADC_12BIT_MODE 0x2
#define ADC_IPG_CLK 0x00
-#define ADC_INPUT_CLK_MASK 0x3
-#define ADC_CLK_DIV_8 (0x03 << 5)
-#define ADC_CLK_DIV_MASK (0x3 << 5)
-#define ADC_SHORT_SAMPLE_MODE (0x0 << 4)
-#define ADC_SAMPLE_MODE_MASK (0x1 << 4)
-#define ADC_HARDWARE_TRIGGER (0x1 << 13)
-#define ADC_AVGS_SHIFT 14
-#define ADC_AVGS_MASK (0x3 << 14)
+#define ADC_INPUT_CLK_MASK GENMASK(1, 0)
+#define ADC_CLK_DIV_8 0x03
+#define ADC_CLK_DIV_MASK GENMASK(6, 5)
+#define ADC_SAMPLE_MODE BIT(4)
+#define ADC_HARDWARE_TRIGGER BIT(13)
+#define ADC_AVGS_MASK GENMASK(15, 14)
#define SELECT_CHANNEL_4 0x04
#define SELECT_CHANNEL_1 0x01
-#define DISABLE_CONVERSION_INT (0x0 << 7)
/* ADC registers */
#define REG_ADC_HC0 0x00
@@ -55,7 +54,7 @@
#define ADC_TIMEOUT msecs_to_jiffies(100)
/* TSC registers */
-#define REG_TSC_BASIC_SETING 0x00
+#define REG_TSC_BASIC_SETTING 0x00
#define REG_TSC_PRE_CHARGE_TIME 0x10
#define REG_TSC_FLOW_CONTROL 0x20
#define REG_TSC_MEASURE_VALUE 0x30
@@ -65,19 +64,26 @@
#define REG_TSC_DEBUG_MODE 0x70
#define REG_TSC_DEBUG_MODE2 0x80
+/* TSC_MEASURE_VALUE register field define */
+#define X_VALUE_MASK GENMASK(27, 16)
+#define Y_VALUE_MASK GENMASK(11, 0)
+
/* TSC configuration registers field define */
-#define DETECT_4_WIRE_MODE (0x0 << 4)
-#define AUTO_MEASURE 0x1
-#define MEASURE_SIGNAL 0x1
-#define DETECT_SIGNAL (0x1 << 4)
-#define VALID_SIGNAL (0x1 << 8)
-#define MEASURE_INT_EN 0x1
-#define MEASURE_SIG_EN 0x1
-#define VALID_SIG_EN (0x1 << 8)
-#define DE_GLITCH_2 (0x2 << 29)
-#define START_SENSE (0x1 << 12)
-#define TSC_DISABLE (0x1 << 16)
+#define MEASURE_DELAY_TIME_MASK GENMASK(31, 8)
+#define DETECT_5_WIRE_MODE BIT(4)
+#define AUTO_MEASURE BIT(0)
+#define MEASURE_SIGNAL BIT(0)
+#define DETECT_SIGNAL BIT(4)
+#define VALID_SIGNAL BIT(8)
+#define MEASURE_INT_EN BIT(0)
+#define MEASURE_SIG_EN BIT(0)
+#define VALID_SIG_EN BIT(8)
+#define DE_GLITCH_MASK GENMASK(30, 29)
+#define DE_GLITCH_DEF 0x02
+#define START_SENSE BIT(12)
+#define TSC_DISABLE BIT(16)
#define DETECT_MODE 0x2
+#define STATE_MACHINE_MASK GENMASK(22, 20)
struct imx6ul_tsc {
struct device *dev;
@@ -92,6 +98,7 @@ struct imx6ul_tsc {
u32 pre_charge_time;
bool average_enable;
u32 average_select;
+ u32 de_glitch;
struct completion completion;
};
@@ -112,19 +119,20 @@ static int imx6ul_adc_init(struct imx6ul_tsc *tsc)
adc_cfg = readl(tsc->adc_regs + REG_ADC_CFG);
adc_cfg &= ~(ADC_CONV_MODE_MASK | ADC_INPUT_CLK_MASK);
- adc_cfg |= ADC_12BIT_MODE | ADC_IPG_CLK;
- adc_cfg &= ~(ADC_CLK_DIV_MASK | ADC_SAMPLE_MODE_MASK);
- adc_cfg |= ADC_CLK_DIV_8 | ADC_SHORT_SAMPLE_MODE;
+ adc_cfg |= FIELD_PREP(ADC_CONV_MODE_MASK, ADC_12BIT_MODE) |
+ FIELD_PREP(ADC_INPUT_CLK_MASK, ADC_IPG_CLK);
+ adc_cfg &= ~(ADC_CLK_DIV_MASK | ADC_SAMPLE_MODE);
+ adc_cfg |= FIELD_PREP(ADC_CLK_DIV_MASK, ADC_CLK_DIV_8);
if (tsc->average_enable) {
adc_cfg &= ~ADC_AVGS_MASK;
- adc_cfg |= (tsc->average_select) << ADC_AVGS_SHIFT;
+ adc_cfg |= FIELD_PREP(ADC_AVGS_MASK, tsc->average_select);
}
adc_cfg &= ~ADC_HARDWARE_TRIGGER;
writel(adc_cfg, tsc->adc_regs + REG_ADC_CFG);
/* enable calibration interrupt */
adc_hc |= ADC_AIEN;
- adc_hc |= ADC_CONV_DISABLE;
+ adc_hc |= FIELD_PREP(ADC_ADCH_MASK, ADC_CONV_DISABLE);
writel(adc_hc, tsc->adc_regs + REG_ADC_HC0);
/* start ADC calibration */
@@ -164,19 +172,21 @@ static void imx6ul_tsc_channel_config(struct imx6ul_tsc *tsc)
{
u32 adc_hc0, adc_hc1, adc_hc2, adc_hc3, adc_hc4;
- adc_hc0 = DISABLE_CONVERSION_INT;
+ adc_hc0 = FIELD_PREP(ADC_AIEN, 0);
writel(adc_hc0, tsc->adc_regs + REG_ADC_HC0);
- adc_hc1 = DISABLE_CONVERSION_INT | SELECT_CHANNEL_4;
+ adc_hc1 = FIELD_PREP(ADC_AIEN, 0) |
+ FIELD_PREP(ADC_ADCH_MASK, SELECT_CHANNEL_4);
writel(adc_hc1, tsc->adc_regs + REG_ADC_HC1);
- adc_hc2 = DISABLE_CONVERSION_INT;
+ adc_hc2 = FIELD_PREP(ADC_AIEN, 0);
writel(adc_hc2, tsc->adc_regs + REG_ADC_HC2);
- adc_hc3 = DISABLE_CONVERSION_INT | SELECT_CHANNEL_1;
+ adc_hc3 = FIELD_PREP(ADC_AIEN, 0) |
+ FIELD_PREP(ADC_ADCH_MASK, SELECT_CHANNEL_1);
writel(adc_hc3, tsc->adc_regs + REG_ADC_HC3);
- adc_hc4 = DISABLE_CONVERSION_INT;
+ adc_hc4 = FIELD_PREP(ADC_AIEN, 0);
writel(adc_hc4, tsc->adc_regs + REG_ADC_HC4);
}
@@ -188,13 +198,16 @@ static void imx6ul_tsc_channel_config(struct imx6ul_tsc *tsc)
static void imx6ul_tsc_set(struct imx6ul_tsc *tsc)
{
u32 basic_setting = 0;
+ u32 debug_mode2;
u32 start;
- basic_setting |= tsc->measure_delay_time << 8;
- basic_setting |= DETECT_4_WIRE_MODE | AUTO_MEASURE;
- writel(basic_setting, tsc->tsc_regs + REG_TSC_BASIC_SETING);
+ basic_setting |= FIELD_PREP(MEASURE_DELAY_TIME_MASK,
+ tsc->measure_delay_time);
+ basic_setting |= AUTO_MEASURE;
+ writel(basic_setting, tsc->tsc_regs + REG_TSC_BASIC_SETTING);
- writel(DE_GLITCH_2, tsc->tsc_regs + REG_TSC_DEBUG_MODE2);
+ debug_mode2 = FIELD_PREP(DE_GLITCH_MASK, tsc->de_glitch);
+ writel(debug_mode2, tsc->tsc_regs + REG_TSC_DEBUG_MODE2);
writel(tsc->pre_charge_time, tsc->tsc_regs + REG_TSC_PRE_CHARGE_TIME);
writel(MEASURE_INT_EN, tsc->tsc_regs + REG_TSC_INT_EN);
@@ -250,7 +263,7 @@ static bool tsc_wait_detect_mode(struct imx6ul_tsc *tsc)
usleep_range(200, 400);
debug_mode2 = readl(tsc->tsc_regs + REG_TSC_DEBUG_MODE2);
- state_machine = (debug_mode2 >> 20) & 0x7;
+ state_machine = FIELD_GET(STATE_MACHINE_MASK, debug_mode2);
} while (state_machine != DETECT_MODE);
usleep_range(200, 400);
@@ -278,8 +291,8 @@ static irqreturn_t tsc_irq_fn(int irq, void *dev_id)
if (status & MEASURE_SIGNAL) {
value = readl(tsc->tsc_regs + REG_TSC_MEASURE_VALUE);
- x = (value >> 16) & 0x0fff;
- y = value & 0x0fff;
+ x = FIELD_GET(X_VALUE_MASK, value);
+ y = FIELD_GET(Y_VALUE_MASK, value);
/*
* In detect mode, we can get the xnur gpio value,
@@ -379,6 +392,7 @@ static int imx6ul_tsc_probe(struct platform_device *pdev)
int tsc_irq;
int adc_irq;
u32 average_samples;
+ u32 de_glitch;
tsc = devm_kzalloc(&pdev->dev, sizeof(*tsc), GFP_KERNEL);
if (!tsc)
@@ -501,6 +515,25 @@ static int imx6ul_tsc_probe(struct platform_device *pdev)
return -EINVAL;
}
+ err = of_property_read_u32(np, "debounce-delay-us", &de_glitch);
+ if (err) {
+ tsc->de_glitch = DE_GLITCH_DEF;
+ } else {
+ u64 cycles;
+ unsigned long rate = clk_get_rate(tsc->tsc_clk);
+
+ cycles = DIV64_U64_ROUND_UP((u64)de_glitch * rate, USEC_PER_SEC);
+
+ if (cycles <= 0x3ff)
+ tsc->de_glitch = 3;
+ else if (cycles <= 0x7ff)
+ tsc->de_glitch = 2;
+ else if (cycles <= 0xfff)
+ tsc->de_glitch = 1;
+ else
+ tsc->de_glitch = 0;
+ }
+
err = input_register_device(tsc->input);
if (err) {
dev_err(&pdev->dev,
@@ -518,13 +551,11 @@ static int imx6ul_tsc_suspend(struct device *dev)
struct imx6ul_tsc *tsc = platform_get_drvdata(pdev);
struct input_dev *input_dev = tsc->input;
- mutex_lock(&input_dev->mutex);
+ guard(mutex)(&input_dev->mutex);
if (input_device_enabled(input_dev))
imx6ul_tsc_stop(tsc);
- mutex_unlock(&input_dev->mutex);
-
return 0;
}
@@ -533,16 +564,17 @@ static int imx6ul_tsc_resume(struct device *dev)
struct platform_device *pdev = to_platform_device(dev);
struct imx6ul_tsc *tsc = platform_get_drvdata(pdev);
struct input_dev *input_dev = tsc->input;
- int retval = 0;
-
- mutex_lock(&input_dev->mutex);
+ int error;
- if (input_device_enabled(input_dev))
- retval = imx6ul_tsc_start(tsc);
+ guard(mutex)(&input_dev->mutex);
- mutex_unlock(&input_dev->mutex);
+ if (input_device_enabled(input_dev)) {
+ error = imx6ul_tsc_start(tsc);
+ if (error)
+ return error;
+ }
- return retval;
+ return 0;
}
static DEFINE_SIMPLE_DEV_PM_OPS(imx6ul_tsc_pm_ops,
diff --git a/drivers/input/touchscreen/inexio.c b/drivers/input/touchscreen/inexio.c
index 82f7ac62a4f2..ac3836ff2a30 100644
--- a/drivers/input/touchscreen/inexio.c
+++ b/drivers/input/touchscreen/inexio.c
@@ -114,7 +114,7 @@ static int inexio_connect(struct serio *serio, struct serio_driver *drv)
struct input_dev *input_dev;
int err;
- pinexio = kzalloc(sizeof(*pinexio), GFP_KERNEL);
+ pinexio = kzalloc_obj(*pinexio);
input_dev = input_allocate_device();
if (!pinexio || !input_dev) {
err = -ENOMEM;
@@ -123,7 +123,7 @@ static int inexio_connect(struct serio *serio, struct serio_driver *drv)
pinexio->serio = serio;
pinexio->dev = input_dev;
- snprintf(pinexio->phys, sizeof(pinexio->phys), "%s/input0", serio->phys);
+ scnprintf(pinexio->phys, sizeof(pinexio->phys), "%s/input0", serio->phys);
input_dev->name = "iNexio Serial TouchScreen";
input_dev->phys = pinexio->phys;
diff --git a/drivers/input/touchscreen/ipaq-micro-ts.c b/drivers/input/touchscreen/ipaq-micro-ts.c
index 94720c41c9be..243e6465d9bd 100644
--- a/drivers/input/touchscreen/ipaq-micro-ts.c
+++ b/drivers/input/touchscreen/ipaq-micro-ts.c
@@ -47,7 +47,7 @@ static void micro_ts_toggle_receive(struct touchscreen_data *ts, bool enable)
{
struct ipaq_micro *micro = ts->micro;
- spin_lock_irq(&micro->lock);
+ guard(spinlock_irq)(&micro->lock);
if (enable) {
micro->ts = micro_ts_receive;
@@ -56,8 +56,6 @@ static void micro_ts_toggle_receive(struct touchscreen_data *ts, bool enable)
micro->ts = NULL;
micro->ts_data = NULL;
}
-
- spin_unlock_irq(&ts->micro->lock);
}
static int micro_ts_open(struct input_dev *input)
@@ -133,13 +131,11 @@ static int micro_ts_resume(struct device *dev)
struct touchscreen_data *ts = dev_get_drvdata(dev);
struct input_dev *input = ts->input;
- mutex_lock(&input->mutex);
+ guard(mutex)(&input->mutex);
if (input_device_enabled(input))
micro_ts_toggle_receive(ts, true);
- mutex_unlock(&input->mutex);
-
return 0;
}
diff --git a/drivers/input/touchscreen/iqs5xx.c b/drivers/input/touchscreen/iqs5xx.c
index 4ebd7565ae6e..587665e4e6fd 100644
--- a/drivers/input/touchscreen/iqs5xx.c
+++ b/drivers/input/touchscreen/iqs5xx.c
@@ -17,6 +17,7 @@
#include <linux/err.h>
#include <linux/firmware.h>
#include <linux/gpio/consumer.h>
+#include <linux/hex.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/input/mt.h>
@@ -72,8 +73,11 @@
#define IQS5XX_CSTM_LEN (IQS5XX_PMAP_END + 1 - IQS5XX_CSTM)
#define IQS5XX_PMAP_LEN (IQS5XX_PMAP_END + 1 - IQS5XX_CHKSM)
-#define IQS5XX_REC_HDR_LEN 4
-#define IQS5XX_REC_LEN_MAX 255
+/* Length of firmware header in hexadecimal characters */
+#define IQS5XX_REC_HDR_LEN_HEX (1 /* start */ + 2 /* size */ + \
+ 4 /* addr */ + 2 /* type */)
+#define IQS5XX_REC_HDR_SIZE 4 /* size + addr (2 bytes) + type, in bytes*/
+#define IQS5XX_REC_DATA_SIZE 255 /* maximum size of the data portion */
#define IQS5XX_REC_TYPE_DATA 0x00
#define IQS5XX_REC_TYPE_EOF 0x01
@@ -97,14 +101,6 @@ struct iqs5xx_dev_id_info {
u8 bl_status;
} __packed;
-struct iqs5xx_ihex_rec {
- char start;
- char len[2];
- char addr[4];
- char type[2];
- char data[2];
-} __packed;
-
struct iqs5xx_touch_data {
__be16 abs_x;
__be16 abs_y;
@@ -355,7 +351,7 @@ static int iqs5xx_bl_open(struct i2c_client *client)
}
static int iqs5xx_bl_write(struct i2c_client *client,
- u16 bl_addr, u8 *pmap_data, u16 pmap_len)
+ u16 bl_addr, const u8 *pmap_data, u16 pmap_len)
{
struct i2c_msg msg;
int ret, i;
@@ -394,7 +390,7 @@ msg_fail:
}
static int iqs5xx_bl_verify(struct i2c_client *client,
- u16 bl_addr, u8 *pmap_data, u16 pmap_len)
+ u16 bl_addr, const u8 *pmap_data, u16 pmap_len)
{
struct i2c_msg msg;
int ret, i;
@@ -445,27 +441,21 @@ static int iqs5xx_set_state(struct i2c_client *client, u8 state)
if (!iqs5xx->dev_id_info.bl_status)
return 0;
- mutex_lock(&iqs5xx->lock);
+ guard(mutex)(&iqs5xx->lock);
/*
* Addressing the device outside of a communication window prompts it
* to assert the RDY output, so disable the interrupt line to prevent
* the handler from servicing a false interrupt.
*/
- disable_irq(client->irq);
+ guard(disable_irq)(&client->irq);
error1 = iqs5xx_write_byte(client, IQS5XX_SYS_CTRL1, state);
error2 = iqs5xx_write_byte(client, IQS5XX_END_COMM, 0);
usleep_range(50, 100);
- enable_irq(client->irq);
-
- mutex_unlock(&iqs5xx->lock);
- if (error1)
- return error1;
-
- return error2;
+ return error1 ?: error2;
}
static int iqs5xx_open(struct input_dev *input)
@@ -702,15 +692,13 @@ static irqreturn_t iqs5xx_irq(int irq, void *data)
static int iqs5xx_fw_file_parse(struct i2c_client *client,
const char *fw_file, u8 *pmap)
{
- const struct firmware *fw;
- struct iqs5xx_ihex_rec *rec;
size_t pos = 0;
int error, i;
u16 rec_num = 1;
u16 rec_addr;
u8 rec_len, rec_type, rec_chksm, chksm;
- u8 rec_hdr[IQS5XX_REC_HDR_LEN];
- u8 rec_data[IQS5XX_REC_LEN_MAX];
+ u8 rec_hdr[IQS5XX_REC_HDR_SIZE];
+ u8 rec_data[IQS5XX_REC_DATA_SIZE];
/*
* Firmware exported from the vendor's configuration tool deviates from
@@ -721,6 +709,7 @@ static int iqs5xx_fw_file_parse(struct i2c_client *client,
* Because the ihex2fw tool tolerates neither (1) nor (2), the slightly
* nonstandard ihex firmware is parsed directly by the driver.
*/
+ const struct firmware *fw __free(firmware) = NULL;
error = request_firmware(&fw, fw_file, &client->dev);
if (error) {
dev_err(&client->dev, "Failed to request firmware %s: %d\n",
@@ -729,53 +718,55 @@ static int iqs5xx_fw_file_parse(struct i2c_client *client,
}
do {
- if (pos + sizeof(*rec) > fw->size) {
+ if (pos + IQS5XX_REC_HDR_LEN_HEX > fw->size) {
dev_err(&client->dev, "Insufficient firmware size\n");
- error = -EINVAL;
- break;
+ return -EINVAL;
}
- rec = (struct iqs5xx_ihex_rec *)(fw->data + pos);
- pos += sizeof(*rec);
- if (rec->start != ':') {
+ if (fw->data[pos] != ':') {
dev_err(&client->dev, "Invalid start at record %u\n",
rec_num);
- error = -EINVAL;
- break;
+ return -EINVAL;
}
- error = hex2bin(rec_hdr, rec->len, sizeof(rec_hdr));
+ /* Convert all 3 fields (length, address, and type) in one go */
+ error = hex2bin(rec_hdr, &fw->data[pos + 1], sizeof(rec_hdr));
if (error) {
dev_err(&client->dev, "Invalid header at record %u\n",
rec_num);
- break;
+ return error;
}
+ pos += IQS5XX_REC_HDR_LEN_HEX;
rec_len = *rec_hdr;
rec_addr = get_unaligned_be16(rec_hdr + sizeof(rec_len));
rec_type = *(rec_hdr + sizeof(rec_len) + sizeof(rec_addr));
- if (pos + rec_len * 2 > fw->size) {
+ /*
+ * Check if we have enough data for the data portion of the
+ * record, as well as the checksum byte. Everything is doubled
+ * because data is in ASCII HEX and not binary format.
+ */
+ if (pos + (rec_len + sizeof(rec_chksm)) * 2 > fw->size) {
dev_err(&client->dev, "Insufficient firmware size\n");
- error = -EINVAL;
- break;
+ return -EINVAL;
}
- pos += (rec_len * 2);
- error = hex2bin(rec_data, rec->data, rec_len);
+ error = hex2bin(rec_data, &fw->data[pos], rec_len);
if (error) {
dev_err(&client->dev, "Invalid data at record %u\n",
rec_num);
- break;
+ return error;
}
+ pos += rec_len * 2;
- error = hex2bin(&rec_chksm,
- rec->data + rec_len * 2, sizeof(rec_chksm));
+ error = hex2bin(&rec_chksm, &fw->data[pos], sizeof(rec_chksm));
if (error) {
dev_err(&client->dev, "Invalid checksum at record %u\n",
rec_num);
- break;
+ return error;
}
+ pos += 2;
chksm = 0;
for (i = 0; i < sizeof(rec_hdr); i++)
@@ -799,23 +790,22 @@ static int iqs5xx_fw_file_parse(struct i2c_client *client,
dev_err(&client->dev,
"Invalid address at record %u\n",
rec_num);
- error = -EINVAL;
- } else {
- memcpy(pmap + rec_addr - IQS5XX_CHKSM,
- rec_data, rec_len);
+ return -EINVAL;
}
+
+ memcpy(pmap + rec_addr - IQS5XX_CHKSM,
+ rec_data, rec_len);
break;
+
case IQS5XX_REC_TYPE_EOF:
break;
+
default:
dev_err(&client->dev, "Invalid type at record %u\n",
rec_num);
- error = -EINVAL;
+ return -EINVAL;
}
- if (error)
- break;
-
rec_num++;
while (pos < fw->size) {
if (*(fw->data + pos) == ':')
@@ -824,33 +814,13 @@ static int iqs5xx_fw_file_parse(struct i2c_client *client,
}
} while (rec_type != IQS5XX_REC_TYPE_EOF);
- release_firmware(fw);
-
- return error;
+ return 0;
}
-static int iqs5xx_fw_file_write(struct i2c_client *client, const char *fw_file)
+static int iqs5xx_update_firmware(struct iqs5xx_private *iqs5xx, const u8 *pmap)
{
- struct iqs5xx_private *iqs5xx = i2c_get_clientdata(client);
- int error, error_init = 0;
- u8 *pmap;
-
- pmap = kzalloc(IQS5XX_PMAP_LEN, GFP_KERNEL);
- if (!pmap)
- return -ENOMEM;
-
- error = iqs5xx_fw_file_parse(client, fw_file, pmap);
- if (error)
- goto err_kfree;
-
- mutex_lock(&iqs5xx->lock);
-
- /*
- * Disable the interrupt line in case the first attempt(s) to enter the
- * bootloader don't happen quickly enough, in which case the device may
- * assert the RDY output until the next attempt.
- */
- disable_irq(client->irq);
+ struct i2c_client *client = iqs5xx->client;
+ int error;
iqs5xx->dev_id_info.bl_status = 0;
@@ -858,22 +828,50 @@ static int iqs5xx_fw_file_write(struct i2c_client *client, const char *fw_file)
if (error) {
error = iqs5xx_bl_open(client);
if (error)
- goto err_reset;
+ return error;
}
error = iqs5xx_bl_write(client, IQS5XX_CHKSM, pmap, IQS5XX_PMAP_LEN);
if (error)
- goto err_reset;
+ return error;
error = iqs5xx_bl_cmd(client, IQS5XX_BL_CMD_CRC, 0);
if (error)
- goto err_reset;
+ return error;
error = iqs5xx_bl_verify(client, IQS5XX_CSTM,
pmap + IQS5XX_CHKSM_LEN + IQS5XX_APP_LEN,
IQS5XX_CSTM_LEN);
+ if (error)
+ return error;
+
+ return 0;
+}
+
+static int iqs5xx_fw_file_write(struct i2c_client *client, const char *fw_file)
+{
+ struct iqs5xx_private *iqs5xx = i2c_get_clientdata(client);
+ int error, error_init = 0;
+
+ u8 *pmap __free(kfree) = kzalloc(IQS5XX_PMAP_LEN, GFP_KERNEL);
+ if (!pmap)
+ return -ENOMEM;
+
+ error = iqs5xx_fw_file_parse(client, fw_file, pmap);
+ if (error)
+ return error;
+
+ guard(mutex)(&iqs5xx->lock);
+
+ /*
+ * Disable the interrupt line in case the first attempt(s) to enter the
+ * bootloader don't happen quickly enough, in which case the device may
+ * assert the RDY output until the next attempt.
+ */
+ guard(disable_irq)(&client->irq);
+
+ error = iqs5xx_update_firmware(iqs5xx, pmap);
-err_reset:
iqs5xx_reset(client);
usleep_range(15000, 15100);
@@ -881,14 +879,7 @@ err_reset:
if (!iqs5xx->dev_id_info.bl_status)
error_init = error_init ? : -EINVAL;
- enable_irq(client->irq);
-
- mutex_unlock(&iqs5xx->lock);
-
-err_kfree:
- kfree(pmap);
-
- return error ? : error_init;
+ return error ?: error_init;
}
static ssize_t fw_file_store(struct device *dev,
@@ -984,38 +975,30 @@ static int iqs5xx_suspend(struct device *dev)
{
struct iqs5xx_private *iqs5xx = dev_get_drvdata(dev);
struct input_dev *input = iqs5xx->input;
- int error = 0;
if (!input || device_may_wakeup(dev))
- return error;
-
- mutex_lock(&input->mutex);
+ return 0;
+ guard(mutex)(&input->mutex);
if (input_device_enabled(input))
- error = iqs5xx_set_state(iqs5xx->client, IQS5XX_SUSPEND);
-
- mutex_unlock(&input->mutex);
+ return iqs5xx_set_state(iqs5xx->client, IQS5XX_SUSPEND);
- return error;
+ return 0;
}
static int iqs5xx_resume(struct device *dev)
{
struct iqs5xx_private *iqs5xx = dev_get_drvdata(dev);
struct input_dev *input = iqs5xx->input;
- int error = 0;
if (!input || device_may_wakeup(dev))
- return error;
-
- mutex_lock(&input->mutex);
+ return 0;
+ guard(mutex)(&input->mutex);
if (input_device_enabled(input))
- error = iqs5xx_set_state(iqs5xx->client, IQS5XX_RESUME);
-
- mutex_unlock(&input->mutex);
+ return iqs5xx_set_state(iqs5xx->client, IQS5XX_RESUME);
- return error;
+ return 0;
}
static DEFINE_SIMPLE_DEV_PM_OPS(iqs5xx_pm, iqs5xx_suspend, iqs5xx_resume);
diff --git a/drivers/input/touchscreen/iqs7211.c b/drivers/input/touchscreen/iqs7211.c
index c5d447ee6f53..26e0b501c5fc 100644
--- a/drivers/input/touchscreen/iqs7211.c
+++ b/drivers/input/touchscreen/iqs7211.c
@@ -2060,19 +2060,16 @@ static int iqs7211_parse_reg_grp(struct iqs7211_private *iqs7211,
for (i = 0; i < dev_desc->num_kp_events; i++) {
const char *event_name = dev_desc->kp_events[i].name;
- struct fwnode_handle *event_node;
if (dev_desc->kp_events[i].reg_grp != reg_grp)
continue;
reg_field.mask |= dev_desc->kp_events[i].enable;
- if (event_name)
- event_node = fwnode_get_named_child_node(reg_grp_node,
- event_name);
- else
- event_node = fwnode_handle_get(reg_grp_node);
-
+ struct fwnode_handle *event_node __free(fwnode_handle) =
+ event_name ? fwnode_get_named_child_node(reg_grp_node,
+ event_name) :
+ fwnode_handle_get(reg_grp_node);
if (!event_node)
continue;
@@ -2080,7 +2077,6 @@ static int iqs7211_parse_reg_grp(struct iqs7211_private *iqs7211,
dev_desc->kp_events[i].reg_grp,
dev_desc->kp_events[i].reg_key,
&iqs7211->kp_code[i]);
- fwnode_handle_put(event_node);
if (error)
return error;
@@ -2496,19 +2492,15 @@ static int iqs7211_probe(struct i2c_client *client)
for (reg_grp = 0; reg_grp < IQS7211_NUM_REG_GRPS; reg_grp++) {
const char *reg_grp_name = iqs7211_reg_grp_names[reg_grp];
- struct fwnode_handle *reg_grp_node;
-
- if (reg_grp_name)
- reg_grp_node = device_get_named_child_node(&client->dev,
- reg_grp_name);
- else
- reg_grp_node = fwnode_handle_get(dev_fwnode(&client->dev));
+ struct fwnode_handle *reg_grp_node __free(fwnode_handle) =
+ reg_grp_name ? device_get_named_child_node(&client->dev,
+ reg_grp_name) :
+ fwnode_handle_get(dev_fwnode(&client->dev));
if (!reg_grp_node)
continue;
error = iqs7211_parse_reg_grp(iqs7211, reg_grp_node, reg_grp);
- fwnode_handle_put(reg_grp_node);
if (error)
return error;
}
diff --git a/drivers/input/touchscreen/lpc32xx_ts.c b/drivers/input/touchscreen/lpc32xx_ts.c
index 9bad8b93c039..5de752a06b26 100644
--- a/drivers/input/touchscreen/lpc32xx_ts.c
+++ b/drivers/input/touchscreen/lpc32xx_ts.c
@@ -279,7 +279,7 @@ static int lpc32xx_ts_suspend(struct device *dev)
* avoid calling the TSC stop and start functions as the TSC
* isn't yet clocked.
*/
- mutex_lock(&input->mutex);
+ guard(mutex)(&input->mutex);
if (input_device_enabled(input)) {
if (device_may_wakeup(dev))
@@ -288,8 +288,6 @@ static int lpc32xx_ts_suspend(struct device *dev)
lpc32xx_stop_tsc(tsc);
}
- mutex_unlock(&input->mutex);
-
return 0;
}
@@ -298,7 +296,7 @@ static int lpc32xx_ts_resume(struct device *dev)
struct lpc32xx_tsc *tsc = dev_get_drvdata(dev);
struct input_dev *input = tsc->dev;
- mutex_lock(&input->mutex);
+ guard(mutex)(&input->mutex);
if (input_device_enabled(input)) {
if (device_may_wakeup(dev))
@@ -307,8 +305,6 @@ static int lpc32xx_ts_resume(struct device *dev)
lpc32xx_setup_tsc(tsc);
}
- mutex_unlock(&input->mutex);
-
return 0;
}
diff --git a/drivers/input/touchscreen/mc13783_ts.c b/drivers/input/touchscreen/mc13783_ts.c
index 33635da85079..4b7e70a4c6d5 100644
--- a/drivers/input/touchscreen/mc13783_ts.c
+++ b/drivers/input/touchscreen/mc13783_ts.c
@@ -42,8 +42,6 @@ static irqreturn_t mc13783_ts_handler(int irq, void *data)
{
struct mc13783_ts_priv *priv = data;
- mc13xxx_irq_ack(priv->mc13xxx, irq);
-
/*
* Kick off reading coordinates. Note that if work happens already
* be queued for future execution (it rearms itself) it will not
@@ -137,8 +135,6 @@ static int mc13783_ts_open(struct input_dev *dev)
mc13xxx_lock(priv->mc13xxx);
- mc13xxx_irq_ack(priv->mc13xxx, MC13XXX_IRQ_TS);
-
ret = mc13xxx_irq_request(priv->mc13xxx, MC13XXX_IRQ_TS,
mc13783_ts_handler, MC13783_TS_NAME, priv);
if (ret)
@@ -172,7 +168,7 @@ static int __init mc13783_ts_probe(struct platform_device *pdev)
struct input_dev *idev;
int ret = -ENOMEM;
- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ priv = kzalloc_obj(*priv);
idev = input_allocate_device();
if (!priv || !idev)
goto err_free_mem;
diff --git a/drivers/input/touchscreen/melfas_mip4.c b/drivers/input/touchscreen/melfas_mip4.c
index a6946e3d8376..10fccf4e5bb1 100644
--- a/drivers/input/touchscreen/melfas_mip4.c
+++ b/drivers/input/touchscreen/melfas_mip4.c
@@ -881,8 +881,6 @@ static int mip4_bl_program_page(struct mip4_ts *ts, int offset,
const u8 *data, int length, u16 buf_addr)
{
u8 cmd[6];
- u8 *data_buf;
- u16 buf_offset;
int ret;
int error;
@@ -895,7 +893,8 @@ static int mip4_bl_program_page(struct mip4_ts *ts, int offset,
return -EINVAL;
}
- data_buf = kmalloc(2 + MIP4_BL_PACKET_SIZE, GFP_KERNEL);
+ u8 *data_buf __free(kfree) = kmalloc(2 + MIP4_BL_PACKET_SIZE,
+ GFP_KERNEL);
if (!data_buf)
return -ENOMEM;
@@ -908,7 +907,7 @@ static int mip4_bl_program_page(struct mip4_ts *ts, int offset,
error = ret < 0 ? ret : -EIO;
dev_err(&ts->client->dev,
"Failed to send write page address: %d\n", error);
- goto out;
+ return error;
}
/* Size */
@@ -920,11 +919,11 @@ static int mip4_bl_program_page(struct mip4_ts *ts, int offset,
error = ret < 0 ? ret : -EIO;
dev_err(&ts->client->dev,
"Failed to send write page size: %d\n", error);
- goto out;
+ return error;
}
/* Data */
- for (buf_offset = 0;
+ for (int buf_offset = 0;
buf_offset < length;
buf_offset += MIP4_BL_PACKET_SIZE) {
dev_dbg(&ts->client->dev,
@@ -939,7 +938,7 @@ static int mip4_bl_program_page(struct mip4_ts *ts, int offset,
dev_err(&ts->client->dev,
"Failed to read chunk at %#04x (size %d): %d\n",
buf_offset, MIP4_BL_PACKET_SIZE, error);
- goto out;
+ return error;
}
}
@@ -952,35 +951,21 @@ static int mip4_bl_program_page(struct mip4_ts *ts, int offset,
error = ret < 0 ? ret : -EIO;
dev_err(&ts->client->dev,
"Failed to send 'write' command: %d\n", error);
- goto out;
+ return error;
}
/* Status */
error = mip4_bl_read_status(ts);
+ if (error)
+ return error;
-out:
- kfree(data_buf);
- return error ? error : 0;
+ return 0;
}
static int mip4_bl_verify_page(struct mip4_ts *ts, int offset,
const u8 *data, int length, int buf_addr)
{
u8 cmd[8];
- u8 *read_buf;
- int buf_offset;
- struct i2c_msg msg[] = {
- {
- .addr = ts->client->addr,
- .flags = 0,
- .buf = cmd,
- .len = 2,
- }, {
- .addr = ts->client->addr,
- .flags = I2C_M_RD,
- .len = MIP4_BL_PACKET_SIZE,
- },
- };
int ret;
int error;
@@ -1029,11 +1014,25 @@ static int mip4_bl_verify_page(struct mip4_ts *ts, int offset,
return error;
/* Read */
- msg[1].buf = read_buf = kmalloc(MIP4_BL_PACKET_SIZE, GFP_KERNEL);
+ u8 *read_buf __free(kfree) = kmalloc(MIP4_BL_PACKET_SIZE, GFP_KERNEL);
if (!read_buf)
return -ENOMEM;
- for (buf_offset = 0;
+ struct i2c_msg msg[] = {
+ {
+ .addr = ts->client->addr,
+ .flags = 0,
+ .buf = cmd,
+ .len = 2,
+ }, {
+ .addr = ts->client->addr,
+ .flags = I2C_M_RD,
+ .buf = read_buf,
+ .len = MIP4_BL_PACKET_SIZE,
+ },
+ };
+
+ for (int buf_offset = 0;
buf_offset < length;
buf_offset += MIP4_BL_PACKET_SIZE) {
dev_dbg(&ts->client->dev,
@@ -1046,7 +1045,7 @@ static int mip4_bl_verify_page(struct mip4_ts *ts, int offset,
dev_err(&ts->client->dev,
"Failed to read chunk at %#04x (size %d): %d\n",
buf_offset, MIP4_BL_PACKET_SIZE, error);
- break;
+ return error;
}
if (memcmp(&data[buf_offset], read_buf, MIP4_BL_PACKET_SIZE)) {
@@ -1064,13 +1063,11 @@ static int mip4_bl_verify_page(struct mip4_ts *ts, int offset,
DUMP_PREFIX_OFFSET, 16, 1,
read_buf, MIP4_BL_PAGE_SIZE, false);
#endif
- error = -EINVAL;
- break;
+ return -EINVAL;
}
}
- kfree(read_buf);
- return error ? error : 0;
+ return 0;
}
/*
@@ -1290,9 +1287,9 @@ static ssize_t mip4_sysfs_fw_update(struct device *dev,
{
struct i2c_client *client = to_i2c_client(dev);
struct mip4_ts *ts = i2c_get_clientdata(client);
- const struct firmware *fw;
int error;
+ const struct firmware *fw __free(firmware) = NULL;
error = request_firmware(&fw, ts->fw_name, dev);
if (error) {
dev_err(&ts->client->dev,
@@ -1306,14 +1303,9 @@ static ssize_t mip4_sysfs_fw_update(struct device *dev,
* userspace opening and closing the device and also suspend/resume
* transitions.
*/
- mutex_lock(&ts->input->mutex);
+ guard(mutex)(&ts->input->mutex);
error = mip4_execute_fw_update(ts, fw);
-
- mutex_unlock(&ts->input->mutex);
-
- release_firmware(fw);
-
if (error) {
dev_err(&ts->client->dev,
"Firmware update failed: %d\n", error);
@@ -1331,18 +1323,13 @@ static ssize_t mip4_sysfs_read_fw_version(struct device *dev,
{
struct i2c_client *client = to_i2c_client(dev);
struct mip4_ts *ts = i2c_get_clientdata(client);
- size_t count;
/* Take lock to prevent racing with firmware update */
- mutex_lock(&ts->input->mutex);
-
- count = sysfs_emit(buf, "%04X %04X %04X %04X\n",
- ts->fw_version.boot, ts->fw_version.core,
- ts->fw_version.app, ts->fw_version.param);
+ guard(mutex)(&ts->input->mutex);
- mutex_unlock(&ts->input->mutex);
-
- return count;
+ return sysfs_emit(buf, "%04X %04X %04X %04X\n",
+ ts->fw_version.boot, ts->fw_version.core,
+ ts->fw_version.app, ts->fw_version.param);
}
static DEVICE_ATTR(fw_version, S_IRUGO, mip4_sysfs_read_fw_version, NULL);
@@ -1353,21 +1340,16 @@ static ssize_t mip4_sysfs_read_hw_version(struct device *dev,
{
struct i2c_client *client = to_i2c_client(dev);
struct mip4_ts *ts = i2c_get_clientdata(client);
- size_t count;
/* Take lock to prevent racing with firmware update */
- mutex_lock(&ts->input->mutex);
+ guard(mutex)(&ts->input->mutex);
/*
* product_name shows the name or version of the hardware
* paired with current firmware in the chip.
*/
- count = sysfs_emit(buf, "%.*s\n",
- (int)sizeof(ts->product_name), ts->product_name);
-
- mutex_unlock(&ts->input->mutex);
-
- return count;
+ return sysfs_emit(buf, "%.*s\n",
+ (int)sizeof(ts->product_name), ts->product_name);
}
static DEVICE_ATTR(hw_version, S_IRUGO, mip4_sysfs_read_hw_version, NULL);
@@ -1378,15 +1360,10 @@ static ssize_t mip4_sysfs_read_product_id(struct device *dev,
{
struct i2c_client *client = to_i2c_client(dev);
struct mip4_ts *ts = i2c_get_clientdata(client);
- size_t count;
-
- mutex_lock(&ts->input->mutex);
- count = sysfs_emit(buf, "%04X\n", ts->product_id);
+ guard(mutex)(&ts->input->mutex);
- mutex_unlock(&ts->input->mutex);
-
- return count;
+ return sysfs_emit(buf, "%04X\n", ts->product_id);
}
static DEVICE_ATTR(product_id, S_IRUGO, mip4_sysfs_read_product_id, NULL);
@@ -1397,16 +1374,10 @@ static ssize_t mip4_sysfs_read_ic_name(struct device *dev,
{
struct i2c_client *client = to_i2c_client(dev);
struct mip4_ts *ts = i2c_get_clientdata(client);
- size_t count;
-
- mutex_lock(&ts->input->mutex);
-
- count = sysfs_emit(buf, "%.*s\n",
- (int)sizeof(ts->ic_name), ts->ic_name);
- mutex_unlock(&ts->input->mutex);
+ guard(mutex)(&ts->input->mutex);
- return count;
+ return sysfs_emit(buf, "%.*s\n", (int)sizeof(ts->ic_name), ts->ic_name);
}
static DEVICE_ATTR(ic_name, S_IRUGO, mip4_sysfs_read_ic_name, NULL);
@@ -1520,15 +1491,13 @@ static int mip4_suspend(struct device *dev)
struct mip4_ts *ts = i2c_get_clientdata(client);
struct input_dev *input = ts->input;
- mutex_lock(&input->mutex);
+ guard(mutex)(&input->mutex);
if (device_may_wakeup(dev))
ts->wake_irq_enabled = enable_irq_wake(client->irq) == 0;
else if (input_device_enabled(input))
mip4_disable(ts);
- mutex_unlock(&input->mutex);
-
return 0;
}
@@ -1538,15 +1507,13 @@ static int mip4_resume(struct device *dev)
struct mip4_ts *ts = i2c_get_clientdata(client);
struct input_dev *input = ts->input;
- mutex_lock(&input->mutex);
+ guard(mutex)(&input->mutex);
if (ts->wake_irq_enabled)
disable_irq_wake(client->irq);
else if (input_device_enabled(input))
mip4_enable(ts);
- mutex_unlock(&input->mutex);
-
return 0;
}
@@ -1554,7 +1521,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(mip4_pm_ops, mip4_suspend, mip4_resume);
#ifdef CONFIG_OF
static const struct of_device_id mip4_of_match[] = {
- { .compatible = "melfas,"MIP4_DEVICE_NAME, },
+ { .compatible = "melfas,mip4_ts", },
{ },
};
MODULE_DEVICE_TABLE(of, mip4_of_match);
diff --git a/drivers/input/touchscreen/migor_ts.c b/drivers/input/touchscreen/migor_ts.c
index 7511a134e302..993d945dcd23 100644
--- a/drivers/input/touchscreen/migor_ts.c
+++ b/drivers/input/touchscreen/migor_ts.c
@@ -122,7 +122,7 @@ static int migor_ts_probe(struct i2c_client *client)
struct input_dev *input;
int error;
- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ priv = kzalloc_obj(*priv);
input = input_allocate_device();
if (!priv || !input) {
dev_err(&client->dev, "failed to allocate memory\n");
diff --git a/drivers/input/touchscreen/mk712.c b/drivers/input/touchscreen/mk712.c
deleted file mode 100644
index 753d9cc1de1f..000000000000
--- a/drivers/input/touchscreen/mk712.c
+++ /dev/null
@@ -1,215 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * ICS MK712 touchscreen controller driver
- *
- * Copyright (c) 1999-2002 Transmeta Corporation
- * Copyright (c) 2005 Rick Koch <n1gp@hotmail.com>
- * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz>
- */
-
-
-/*
- * This driver supports the ICS MicroClock MK712 TouchScreen controller,
- * found in Gateway AOL Connected Touchpad computers.
- *
- * Documentation for ICS MK712 can be found at:
- * https://www.idt.com/general-parts/mk712-touch-screen-controller
- */
-
-/*
- * 1999-12-18: original version, Daniel Quinlan
- * 1999-12-19: added anti-jitter code, report pen-up events, fixed mk712_poll
- * to use queue_empty, Nathan Laredo
- * 1999-12-20: improved random point rejection, Nathan Laredo
- * 2000-01-05: checked in new anti-jitter code, changed mouse protocol, fixed
- * queue code, added module options, other fixes, Daniel Quinlan
- * 2002-03-15: Clean up for kernel merge <alan@redhat.com>
- * Fixed multi open race, fixed memory checks, fixed resource
- * allocation, fixed close/powerdown bug, switched to new init
- * 2005-01-18: Ported to 2.6 from 2.4.28, Rick Koch
- * 2005-02-05: Rewritten for the input layer, Vojtech Pavlik
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/input.h>
-#include <asm/io.h>
-
-MODULE_AUTHOR("Daniel Quinlan <quinlan@pathname.com>, Vojtech Pavlik <vojtech@suse.cz>");
-MODULE_DESCRIPTION("ICS MicroClock MK712 TouchScreen driver");
-MODULE_LICENSE("GPL");
-
-static unsigned int mk712_io = 0x260; /* Also 0x200, 0x208, 0x300 */
-module_param_hw_named(io, mk712_io, uint, ioport, 0);
-MODULE_PARM_DESC(io, "I/O base address of MK712 touchscreen controller");
-
-static unsigned int mk712_irq = 10; /* Also 12, 14, 15 */
-module_param_hw_named(irq, mk712_irq, uint, irq, 0);
-MODULE_PARM_DESC(irq, "IRQ of MK712 touchscreen controller");
-
-/* eight 8-bit registers */
-#define MK712_STATUS 0
-#define MK712_X 2
-#define MK712_Y 4
-#define MK712_CONTROL 6
-#define MK712_RATE 7
-
-/* status */
-#define MK712_STATUS_TOUCH 0x10
-#define MK712_CONVERSION_COMPLETE 0x80
-
-/* control */
-#define MK712_ENABLE_INT 0x01
-#define MK712_INT_ON_CONVERSION_COMPLETE 0x02
-#define MK712_INT_ON_CHANGE_IN_TOUCH_STATUS 0x04
-#define MK712_ENABLE_PERIODIC_CONVERSIONS 0x10
-#define MK712_READ_ONE_POINT 0x20
-#define MK712_POWERUP 0x40
-
-static struct input_dev *mk712_dev;
-static DEFINE_SPINLOCK(mk712_lock);
-
-static irqreturn_t mk712_interrupt(int irq, void *dev_id)
-{
- unsigned char status;
- static int debounce = 1;
- static unsigned short last_x;
- static unsigned short last_y;
-
- spin_lock(&mk712_lock);
-
- status = inb(mk712_io + MK712_STATUS);
-
- if (~status & MK712_CONVERSION_COMPLETE) {
- debounce = 1;
- goto end;
- }
-
- if (~status & MK712_STATUS_TOUCH) {
- debounce = 1;
- input_report_key(mk712_dev, BTN_TOUCH, 0);
- goto end;
- }
-
- if (debounce) {
- debounce = 0;
- goto end;
- }
-
- input_report_key(mk712_dev, BTN_TOUCH, 1);
- input_report_abs(mk712_dev, ABS_X, last_x);
- input_report_abs(mk712_dev, ABS_Y, last_y);
-
- end:
- last_x = inw(mk712_io + MK712_X) & 0x0fff;
- last_y = inw(mk712_io + MK712_Y) & 0x0fff;
- input_sync(mk712_dev);
- spin_unlock(&mk712_lock);
- return IRQ_HANDLED;
-}
-
-static int mk712_open(struct input_dev *dev)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&mk712_lock, flags);
-
- outb(0, mk712_io + MK712_CONTROL); /* Reset */
-
- outb(MK712_ENABLE_INT | MK712_INT_ON_CONVERSION_COMPLETE |
- MK712_INT_ON_CHANGE_IN_TOUCH_STATUS |
- MK712_ENABLE_PERIODIC_CONVERSIONS |
- MK712_POWERUP, mk712_io + MK712_CONTROL);
-
- outb(10, mk712_io + MK712_RATE); /* 187 points per second */
-
- spin_unlock_irqrestore(&mk712_lock, flags);
-
- return 0;
-}
-
-static void mk712_close(struct input_dev *dev)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&mk712_lock, flags);
-
- outb(0, mk712_io + MK712_CONTROL);
-
- spin_unlock_irqrestore(&mk712_lock, flags);
-}
-
-static int __init mk712_init(void)
-{
- int err;
-
- if (!request_region(mk712_io, 8, "mk712")) {
- printk(KERN_WARNING "mk712: unable to get IO region\n");
- return -ENODEV;
- }
-
- outb(0, mk712_io + MK712_CONTROL);
-
- if ((inw(mk712_io + MK712_X) & 0xf000) || /* Sanity check */
- (inw(mk712_io + MK712_Y) & 0xf000) ||
- (inw(mk712_io + MK712_STATUS) & 0xf333)) {
- printk(KERN_WARNING "mk712: device not present\n");
- err = -ENODEV;
- goto fail1;
- }
-
- mk712_dev = input_allocate_device();
- if (!mk712_dev) {
- printk(KERN_ERR "mk712: not enough memory\n");
- err = -ENOMEM;
- goto fail1;
- }
-
- mk712_dev->name = "ICS MicroClock MK712 TouchScreen";
- mk712_dev->phys = "isa0260/input0";
- mk712_dev->id.bustype = BUS_ISA;
- mk712_dev->id.vendor = 0x0005;
- mk712_dev->id.product = 0x0001;
- mk712_dev->id.version = 0x0100;
-
- mk712_dev->open = mk712_open;
- mk712_dev->close = mk712_close;
-
- mk712_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
- mk712_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
- input_set_abs_params(mk712_dev, ABS_X, 0, 0xfff, 88, 0);
- input_set_abs_params(mk712_dev, ABS_Y, 0, 0xfff, 88, 0);
-
- if (request_irq(mk712_irq, mk712_interrupt, 0, "mk712", mk712_dev)) {
- printk(KERN_WARNING "mk712: unable to get IRQ\n");
- err = -EBUSY;
- goto fail1;
- }
-
- err = input_register_device(mk712_dev);
- if (err)
- goto fail2;
-
- return 0;
-
- fail2: free_irq(mk712_irq, mk712_dev);
- fail1: input_free_device(mk712_dev);
- release_region(mk712_io, 8);
- return err;
-}
-
-static void __exit mk712_exit(void)
-{
- input_unregister_device(mk712_dev);
- free_irq(mk712_irq, mk712_dev);
- release_region(mk712_io, 8);
-}
-
-module_init(mk712_init);
-module_exit(mk712_exit);
diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c
index 9f947044c4d9..af462086a65c 100644
--- a/drivers/input/touchscreen/mms114.c
+++ b/drivers/input/touchscreen/mms114.c
@@ -216,20 +216,12 @@ static irqreturn_t mms114_interrupt(int irq, void *dev_id)
{
struct mms114_data *data = dev_id;
struct i2c_client *client = data->client;
- struct input_dev *input_dev = data->input_dev;
struct mms114_touch touch[MMS114_MAX_TOUCH];
int packet_size;
int touch_size;
int index;
int error;
- mutex_lock(&input_dev->mutex);
- if (!input_device_enabled(input_dev)) {
- mutex_unlock(&input_dev->mutex);
- goto out;
- }
- mutex_unlock(&input_dev->mutex);
-
packet_size = mms114_read_reg(data, MMS114_PACKET_SIZE);
if (packet_size <= 0)
goto out;
@@ -646,10 +638,10 @@ static int mms114_suspend(struct device *dev)
input_mt_report_pointer_emulation(input_dev, true);
input_sync(input_dev);
- mutex_lock(&input_dev->mutex);
+ guard(mutex)(&input_dev->mutex);
+
if (input_device_enabled(input_dev))
mms114_stop(data);
- mutex_unlock(&input_dev->mutex);
return 0;
}
@@ -661,15 +653,13 @@ static int mms114_resume(struct device *dev)
struct input_dev *input_dev = data->input_dev;
int error;
- mutex_lock(&input_dev->mutex);
+ guard(mutex)(&input_dev->mutex);
+
if (input_device_enabled(input_dev)) {
error = mms114_start(data);
- if (error < 0) {
- mutex_unlock(&input_dev->mutex);
+ if (error)
return error;
- }
}
- mutex_unlock(&input_dev->mutex);
return 0;
}
diff --git a/drivers/input/touchscreen/msg2638.c b/drivers/input/touchscreen/msg2638.c
index a38af3fee34a..240d2eebf1c9 100644
--- a/drivers/input/touchscreen/msg2638.c
+++ b/drivers/input/touchscreen/msg2638.c
@@ -446,13 +446,11 @@ static int msg2638_suspend(struct device *dev)
struct i2c_client *client = to_i2c_client(dev);
struct msg2638_ts_data *msg2638 = i2c_get_clientdata(client);
- mutex_lock(&msg2638->input_dev->mutex);
+ guard(mutex)(&msg2638->input_dev->mutex);
if (input_device_enabled(msg2638->input_dev))
msg2638_stop(msg2638);
- mutex_unlock(&msg2638->input_dev->mutex);
-
return 0;
}
@@ -460,16 +458,17 @@ static int msg2638_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct msg2638_ts_data *msg2638 = i2c_get_clientdata(client);
- int ret = 0;
-
- mutex_lock(&msg2638->input_dev->mutex);
+ int error;
- if (input_device_enabled(msg2638->input_dev))
- ret = msg2638_start(msg2638);
+ guard(mutex)(&msg2638->input_dev->mutex);
- mutex_unlock(&msg2638->input_dev->mutex);
+ if (input_device_enabled(msg2638->input_dev)) {
+ error = msg2638_start(msg2638);
+ if (error)
+ return error;
+ }
- return ret;
+ return 0;
}
static DEFINE_SIMPLE_DEV_PM_OPS(msg2638_pm_ops, msg2638_suspend, msg2638_resume);
diff --git a/drivers/input/touchscreen/mtouch.c b/drivers/input/touchscreen/mtouch.c
index eefae96a2d40..cc2d206d2f3d 100644
--- a/drivers/input/touchscreen/mtouch.c
+++ b/drivers/input/touchscreen/mtouch.c
@@ -128,7 +128,7 @@ static int mtouch_connect(struct serio *serio, struct serio_driver *drv)
struct input_dev *input_dev;
int err;
- mtouch = kzalloc(sizeof(*mtouch), GFP_KERNEL);
+ mtouch = kzalloc_obj(*mtouch);
input_dev = input_allocate_device();
if (!mtouch || !input_dev) {
err = -ENOMEM;
@@ -137,7 +137,7 @@ static int mtouch_connect(struct serio *serio, struct serio_driver *drv)
mtouch->serio = serio;
mtouch->dev = input_dev;
- snprintf(mtouch->phys, sizeof(mtouch->phys), "%s/input0", serio->phys);
+ scnprintf(mtouch->phys, sizeof(mtouch->phys), "%s/input0", serio->phys);
input_dev->name = "MicroTouch Serial TouchScreen";
input_dev->phys = mtouch->phys;
diff --git a/drivers/input/touchscreen/mxs-lradc-ts.c b/drivers/input/touchscreen/mxs-lradc-ts.c
index 9e36fee38d61..137ab3b60f2d 100644
--- a/drivers/input/touchscreen/mxs-lradc-ts.c
+++ b/drivers/input/touchscreen/mxs-lradc-ts.c
@@ -500,15 +500,14 @@ static irqreturn_t mxs_lradc_ts_handle_irq(int irq, void *data)
LRADC_CTRL1_TOUCH_DETECT_IRQ |
LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL1) |
LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL2);
- unsigned long flags;
if (!(reg & mxs_lradc_irq_mask(lradc)))
return IRQ_NONE;
if (reg & ts_irq_mask) {
- spin_lock_irqsave(&ts->lock, flags);
- mxs_lradc_handle_touch(ts);
- spin_unlock_irqrestore(&ts->lock, flags);
+ scoped_guard(spinlock_irqsave, &ts->lock) {
+ mxs_lradc_handle_touch(ts);
+ }
/* Make sure we don't clear the next conversion's interrupt. */
clr_irq &= ~(LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL1) |
LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL2));
diff --git a/drivers/input/touchscreen/novatek-nvt-ts.c b/drivers/input/touchscreen/novatek-nvt-ts.c
index 44b58e0dc1ad..708bfb933ddd 100644
--- a/drivers/input/touchscreen/novatek-nvt-ts.c
+++ b/drivers/input/touchscreen/novatek-nvt-ts.c
@@ -27,7 +27,6 @@
#define NVT_TS_PARAMS_MAX_TOUCH 0x09
#define NVT_TS_PARAMS_MAX_BUTTONS 0x0a
#define NVT_TS_PARAMS_IRQ_TYPE 0x0b
-#define NVT_TS_PARAMS_WAKE_TYPE 0x0c
#define NVT_TS_PARAMS_CHIP_ID 0x0e
#define NVT_TS_PARAMS_SIZE 0x0f
@@ -49,7 +48,6 @@ static const int nvt_ts_irq_type[4] = {
};
struct nvt_ts_i2c_chip_data {
- u8 wake_type;
u8 chip_id;
};
@@ -172,10 +170,10 @@ static int nvt_ts_suspend(struct device *dev)
{
struct nvt_ts_data *data = i2c_get_clientdata(to_i2c_client(dev));
- mutex_lock(&data->input->mutex);
+ guard(mutex)(&data->input->mutex);
+
if (input_device_enabled(data->input))
nvt_ts_stop(data->input);
- mutex_unlock(&data->input->mutex);
return 0;
}
@@ -184,10 +182,10 @@ static int nvt_ts_resume(struct device *dev)
{
struct nvt_ts_data *data = i2c_get_clientdata(to_i2c_client(dev));
- mutex_lock(&data->input->mutex);
+ guard(mutex)(&data->input->mutex);
+
if (input_device_enabled(data->input))
nvt_ts_start(data->input);
- mutex_unlock(&data->input->mutex);
return 0;
}
@@ -261,7 +259,6 @@ static int nvt_ts_probe(struct i2c_client *client)
if (width > NVT_TS_MAX_SIZE || height >= NVT_TS_MAX_SIZE ||
data->max_touches > NVT_TS_MAX_TOUCHES ||
irq_type >= ARRAY_SIZE(nvt_ts_irq_type) ||
- data->buf[NVT_TS_PARAMS_WAKE_TYPE] != chip->wake_type ||
data->buf[NVT_TS_PARAMS_CHIP_ID] != chip->chip_id) {
dev_err(dev, "Unsupported touchscreen parameters: %*ph\n",
NVT_TS_PARAMS_SIZE, data->buf);
@@ -314,12 +311,10 @@ static int nvt_ts_probe(struct i2c_client *client)
}
static const struct nvt_ts_i2c_chip_data nvt_nt11205_ts_data = {
- .wake_type = 0x05,
.chip_id = 0x05,
};
static const struct nvt_ts_i2c_chip_data nvt_nt36672a_ts_data = {
- .wake_type = 0x01,
.chip_id = 0x08,
};
diff --git a/drivers/input/touchscreen/pcap_ts.c b/drivers/input/touchscreen/pcap_ts.c
index 083206a3457b..7b89eb74b9de 100644
--- a/drivers/input/touchscreen/pcap_ts.c
+++ b/drivers/input/touchscreen/pcap_ts.c
@@ -138,7 +138,7 @@ static int pcap_ts_probe(struct platform_device *pdev)
struct pcap_ts *pcap_ts;
int err = -ENOMEM;
- pcap_ts = kzalloc(sizeof(*pcap_ts), GFP_KERNEL);
+ pcap_ts = kzalloc_obj(*pcap_ts);
if (!pcap_ts)
return err;
diff --git a/drivers/input/touchscreen/penmount.c b/drivers/input/touchscreen/penmount.c
index 95adede26703..4b57b6664e37 100644
--- a/drivers/input/touchscreen/penmount.c
+++ b/drivers/input/touchscreen/penmount.c
@@ -199,7 +199,7 @@ static int pm_connect(struct serio *serio, struct serio_driver *drv)
int max_x, max_y;
int err;
- pm = kzalloc(sizeof(*pm), GFP_KERNEL);
+ pm = kzalloc_obj(*pm);
input_dev = input_allocate_device();
if (!pm || !input_dev) {
err = -ENOMEM;
@@ -208,7 +208,7 @@ static int pm_connect(struct serio *serio, struct serio_driver *drv)
pm->serio = serio;
pm->dev = input_dev;
- snprintf(pm->phys, sizeof(pm->phys), "%s/input0", serio->phys);
+ scnprintf(pm->phys, sizeof(pm->phys), "%s/input0", serio->phys);
pm->maxcontacts = 1;
input_dev->name = "PenMount Serial TouchScreen";
diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c
index dad5786e82a4..c6b3615c8775 100644
--- a/drivers/input/touchscreen/pixcir_i2c_ts.c
+++ b/drivers/input/touchscreen/pixcir_i2c_ts.c
@@ -410,26 +410,25 @@ static int pixcir_i2c_ts_suspend(struct device *dev)
struct i2c_client *client = to_i2c_client(dev);
struct pixcir_i2c_ts_data *ts = i2c_get_clientdata(client);
struct input_dev *input = ts->input;
- int ret = 0;
+ int error;
- mutex_lock(&input->mutex);
+ guard(mutex)(&input->mutex);
if (device_may_wakeup(&client->dev)) {
if (!input_device_enabled(input)) {
- ret = pixcir_start(ts);
- if (ret) {
+ error = pixcir_start(ts);
+ if (error) {
dev_err(dev, "Failed to start\n");
- goto unlock;
+ return error;
}
}
} else if (input_device_enabled(input)) {
- ret = pixcir_stop(ts);
+ error = pixcir_stop(ts);
+ if (error)
+ return error;
}
-unlock:
- mutex_unlock(&input->mutex);
-
- return ret;
+ return 0;
}
static int pixcir_i2c_ts_resume(struct device *dev)
@@ -437,26 +436,25 @@ static int pixcir_i2c_ts_resume(struct device *dev)
struct i2c_client *client = to_i2c_client(dev);
struct pixcir_i2c_ts_data *ts = i2c_get_clientdata(client);
struct input_dev *input = ts->input;
- int ret = 0;
+ int error;
- mutex_lock(&input->mutex);
+ guard(mutex)(&input->mutex);
if (device_may_wakeup(&client->dev)) {
if (!input_device_enabled(input)) {
- ret = pixcir_stop(ts);
- if (ret) {
+ error = pixcir_stop(ts);
+ if (error) {
dev_err(dev, "Failed to stop\n");
- goto unlock;
+ return error;
}
}
} else if (input_device_enabled(input)) {
- ret = pixcir_start(ts);
+ error = pixcir_start(ts);
+ if (error)
+ return error;
}
-unlock:
- mutex_unlock(&input->mutex);
-
- return ret;
+ return 0;
}
static DEFINE_SIMPLE_DEV_PM_OPS(pixcir_dev_pm_ops,
diff --git a/drivers/input/touchscreen/raydium_i2c_ts.c b/drivers/input/touchscreen/raydium_i2c_ts.c
index f975b53e8825..f2d33ad86fd2 100644
--- a/drivers/input/touchscreen/raydium_i2c_ts.c
+++ b/drivers/input/touchscreen/raydium_i2c_ts.c
@@ -169,10 +169,9 @@ static int raydium_i2c_send(struct i2c_client *client,
{
int tries = 0;
int error;
- u8 *tx_buf;
u8 reg_addr = addr & 0xff;
- tx_buf = kmalloc(len + 1, GFP_KERNEL);
+ u8 *tx_buf __free(kfree) = kmalloc(len + 1, GFP_KERNEL);
if (!tx_buf)
return -ENOMEM;
@@ -210,14 +209,12 @@ static int raydium_i2c_send(struct i2c_client *client,
error = raydium_i2c_xfer(client, addr, xfer, ARRAY_SIZE(xfer));
if (likely(!error))
- goto out;
+ return 0;
msleep(RM_RETRY_DELAY_MS);
} while (++tries < RM_MAX_RETRIES);
dev_err(&client->dev, "%s failed: %d\n", __func__, error);
-out:
- kfree(tx_buf);
return error;
}
@@ -815,21 +812,21 @@ static int raydium_i2c_do_update_firmware(struct raydium_data *ts,
static int raydium_i2c_fw_update(struct raydium_data *ts)
{
struct i2c_client *client = ts->client;
- const struct firmware *fw = NULL;
- char *fw_file;
int error;
- fw_file = kasprintf(GFP_KERNEL, "raydium_%#04x.fw",
- le32_to_cpu(ts->info.hw_ver));
+ const char *fw_file __free(kfree) =
+ kasprintf(GFP_KERNEL, "raydium_%#04x.fw",
+ le32_to_cpu(ts->info.hw_ver));
if (!fw_file)
return -ENOMEM;
dev_dbg(&client->dev, "firmware name: %s\n", fw_file);
+ const struct firmware *fw __free(firmware) = NULL;
error = request_firmware(&fw, fw_file, &client->dev);
if (error) {
dev_err(&client->dev, "Unable to open firmware %s\n", fw_file);
- goto out_free_fw_file;
+ return error;
}
disable_irq(client->irq);
@@ -856,11 +853,6 @@ out_enable_irq:
enable_irq(client->irq);
msleep(100);
- release_firmware(fw);
-
-out_free_fw_file:
- kfree(fw_file);
-
return error;
}
@@ -965,15 +957,12 @@ static ssize_t raydium_i2c_update_fw_store(struct device *dev,
struct raydium_data *ts = i2c_get_clientdata(client);
int error;
- error = mutex_lock_interruptible(&ts->sysfs_mutex);
- if (error)
- return error;
-
- error = raydium_i2c_fw_update(ts);
-
- mutex_unlock(&ts->sysfs_mutex);
+ scoped_guard(mutex_intr, &ts->sysfs_mutex) {
+ error = raydium_i2c_fw_update(ts);
+ return error ?: count;
+ }
- return error ?: count;
+ return -EINTR;
}
static ssize_t raydium_i2c_calibrate_store(struct device *dev,
@@ -985,17 +974,20 @@ static ssize_t raydium_i2c_calibrate_store(struct device *dev,
static const u8 cal_cmd[] = { 0x00, 0x01, 0x9E };
int error;
- error = mutex_lock_interruptible(&ts->sysfs_mutex);
- if (error)
- return error;
+ scoped_guard(mutex_intr, &ts->sysfs_mutex) {
+ error = raydium_i2c_write_object(client,
+ cal_cmd, sizeof(cal_cmd),
+ RAYDIUM_WAIT_READY);
+ if (error) {
+ dev_err(&client->dev,
+ "calibrate command failed: %d\n", error);
+ return error;
+ }
- error = raydium_i2c_write_object(client, cal_cmd, sizeof(cal_cmd),
- RAYDIUM_WAIT_READY);
- if (error)
- dev_err(&client->dev, "calibrate command failed: %d\n", error);
+ return count;
+ }
- mutex_unlock(&ts->sysfs_mutex);
- return error ?: count;
+ return -EINTR;
}
static DEVICE_ATTR(fw_version, S_IRUGO, raydium_i2c_fw_ver_show, NULL);
diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c
index 6475084aee1b..9b266927b7fe 100644
--- a/drivers/input/touchscreen/st1232.c
+++ b/drivers/input/touchscreen/st1232.c
@@ -15,6 +15,7 @@
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/input/mt.h>
+#include <linux/input/touch-overlay.h>
#include <linux/input/touchscreen.h>
#include <linux/interrupt.h>
#include <linux/module.h>
@@ -22,10 +23,14 @@
#include <linux/pm_qos.h>
#include <linux/slab.h>
#include <linux/types.h>
+#include <asm/byteorder.h>
#define ST1232_TS_NAME "st1232-ts"
#define ST1633_TS_NAME "st1633-ts"
+#define REG_FIRMWARE_VERSION 0x00
+#define REG_FIRMWARE_REVISION_3 0x0C
+
#define REG_STATUS 0x01 /* Device Status | Error Code */
#define STATUS_NORMAL 0x00
@@ -57,10 +62,41 @@ struct st1232_ts_data {
struct dev_pm_qos_request low_latency_req;
struct gpio_desc *reset_gpio;
const struct st_chip_info *chip_info;
+ struct list_head touch_overlay_list;
int read_buf_len;
u8 *read_buf;
+ u8 fw_version;
+ u32 fw_revision;
};
+static ssize_t fw_version_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct st1232_ts_data *st1232_ts = i2c_get_clientdata(client);
+
+ return sysfs_emit(buf, "%u\n", st1232_ts->fw_version);
+}
+
+static ssize_t fw_revision_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct st1232_ts_data *st1232_ts = i2c_get_clientdata(client);
+
+ return sysfs_emit(buf, "%08x\n", st1232_ts->fw_revision);
+}
+
+static DEVICE_ATTR_RO(fw_version);
+static DEVICE_ATTR_RO(fw_revision);
+
+static struct attribute *st1232_attrs[] = {
+ &dev_attr_fw_version.attr,
+ &dev_attr_fw_revision.attr,
+ NULL,
+};
+ATTRIBUTE_GROUPS(st1232);
+
static int st1232_ts_read_data(struct st1232_ts_data *ts, u8 reg,
unsigned int n)
{
@@ -108,6 +144,26 @@ static int st1232_ts_wait_ready(struct st1232_ts_data *ts)
return -ENXIO;
}
+static int st1232_ts_read_fw_version(struct st1232_ts_data *ts,
+ u8 *fw_version, u32 *fw_revision)
+{
+ int error;
+
+ /* select firmware version register */
+ error = st1232_ts_read_data(ts, REG_FIRMWARE_VERSION, 1);
+ if (error)
+ return error;
+ *fw_version = ts->read_buf[0];
+
+ /* select firmware revision register */
+ error = st1232_ts_read_data(ts, REG_FIRMWARE_REVISION_3, 4);
+ if (error)
+ return error;
+ *fw_revision = le32_to_cpup((__le32 *)ts->read_buf);
+
+ return 0;
+}
+
static int st1232_ts_read_resolution(struct st1232_ts_data *ts, u16 *max_x,
u16 *max_y)
{
@@ -156,6 +212,10 @@ static int st1232_ts_parse_and_report(struct st1232_ts_data *ts)
input_mt_assign_slots(input, slots, pos, n_contacts, 0);
for (i = 0; i < n_contacts; i++) {
+ if (touch_overlay_process_contact(&ts->touch_overlay_list,
+ input, &pos[i], slots[i]))
+ continue;
+
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);
@@ -164,6 +224,7 @@ static int st1232_ts_parse_and_report(struct st1232_ts_data *ts)
input_report_abs(input, ABS_MT_TOUCH_MAJOR, z[i]);
}
+ touch_overlay_sync_frame(&ts->touch_overlay_list, input);
input_mt_sync_frame(input);
input_sync(input);
@@ -292,18 +353,40 @@ static int st1232_ts_probe(struct i2c_client *client)
if (error)
return error;
- /* Read resolution from the chip */
- error = st1232_ts_read_resolution(ts, &max_x, &max_y);
+ /* Read firmware version from the chip */
+ error = st1232_ts_read_fw_version(ts, &ts->fw_version, &ts->fw_revision);
if (error) {
dev_err(&client->dev,
- "Failed to read resolution: %d\n", error);
+ "Failed to read firmware version: %d\n", error);
return error;
}
+ dev_dbg(&client->dev, "Detected firmware version %u, rev %08x\n",
+ ts->fw_version, ts->fw_revision);
if (ts->chip_info->have_z)
input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0,
ts->chip_info->max_area, 0, 0);
+ /* map overlay objects if defined in the device tree */
+ INIT_LIST_HEAD(&ts->touch_overlay_list);
+ error = touch_overlay_map(&ts->touch_overlay_list, input_dev);
+ if (error)
+ return error;
+
+ if (touch_overlay_mapped_touchscreen(&ts->touch_overlay_list)) {
+ /* Read resolution from the overlay touchscreen if defined */
+ touch_overlay_get_touchscreen_abs(&ts->touch_overlay_list,
+ &max_x, &max_y);
+ } else {
+ /* Read resolution from the chip */
+ error = st1232_ts_read_resolution(ts, &max_x, &max_y);
+ if (error) {
+ dev_err(&client->dev,
+ "Failed to read resolution: %d\n", error);
+ return error;
+ }
+ }
+
input_set_abs_params(input_dev, ABS_MT_POSITION_X,
0, max_x, 0, 0);
input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
@@ -389,6 +472,7 @@ static struct i2c_driver st1232_ts_driver = {
.driver = {
.name = ST1232_TS_NAME,
.of_match_table = st1232_ts_dt_ids,
+ .dev_groups = st1232_groups,
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.pm = pm_sleep_ptr(&st1232_ts_pm_ops),
},
diff --git a/drivers/input/touchscreen/stmfts.c b/drivers/input/touchscreen/stmfts.c
index 119cd26851cf..8af87d0b6eb6 100644
--- a/drivers/input/touchscreen/stmfts.c
+++ b/drivers/input/touchscreen/stmfts.c
@@ -120,7 +120,7 @@ static int stmfts_brightness_set(struct led_classdev *led_cdev,
err = regulator_enable(sdata->ledvdd);
if (err) {
dev_warn(&sdata->client->dev,
- "failed to disable ledvdd regulator: %d\n",
+ "failed to enable ledvdd regulator: %d\n",
err);
return err;
}
@@ -141,7 +141,7 @@ static enum led_brightness stmfts_brightness_get(struct led_classdev *led_cdev)
/*
* We can't simply use i2c_smbus_read_i2c_block_data because we
- * need to read more than 255 bytes (
+ * need to read 256 bytes, which exceeds the 255-byte SMBus block limit.
*/
static int stmfts_read_events(struct stmfts_data *sdata)
{
@@ -302,7 +302,7 @@ static irqreturn_t stmfts_irq_handler(int irq, void *dev)
struct stmfts_data *sdata = dev;
int err;
- mutex_lock(&sdata->mutex);
+ guard(mutex)(&sdata->mutex);
err = stmfts_read_events(sdata);
if (unlikely(err))
@@ -311,7 +311,6 @@ static irqreturn_t stmfts_irq_handler(int irq, void *dev)
else
stmfts_parse_events(sdata);
- mutex_unlock(&sdata->mutex);
return IRQ_HANDLED;
}
@@ -347,17 +346,17 @@ static int stmfts_input_open(struct input_dev *dev)
return err;
}
- mutex_lock(&sdata->mutex);
- sdata->running = true;
+ scoped_guard(mutex, &sdata->mutex) {
+ sdata->running = true;
- if (sdata->hover_enabled) {
- err = i2c_smbus_write_byte(sdata->client,
- STMFTS_SS_HOVER_SENSE_ON);
- if (err)
- dev_warn(&sdata->client->dev,
- "failed to enable hover\n");
+ if (sdata->hover_enabled) {
+ err = i2c_smbus_write_byte(sdata->client,
+ STMFTS_SS_HOVER_SENSE_ON);
+ if (err)
+ dev_warn(&sdata->client->dev,
+ "failed to enable hover\n");
+ }
}
- mutex_unlock(&sdata->mutex);
if (sdata->use_key) {
err = i2c_smbus_write_byte(sdata->client,
@@ -381,18 +380,17 @@ static void stmfts_input_close(struct input_dev *dev)
dev_warn(&sdata->client->dev,
"failed to disable touchscreen: %d\n", err);
- mutex_lock(&sdata->mutex);
+ scoped_guard(mutex, &sdata->mutex) {
+ sdata->running = false;
- sdata->running = false;
-
- if (sdata->hover_enabled) {
- err = i2c_smbus_write_byte(sdata->client,
- STMFTS_SS_HOVER_SENSE_OFF);
- if (err)
- dev_warn(&sdata->client->dev,
- "failed to disable hover: %d\n", err);
+ if (sdata->hover_enabled) {
+ err = i2c_smbus_write_byte(sdata->client,
+ STMFTS_SS_HOVER_SENSE_OFF);
+ if (err)
+ dev_warn(&sdata->client->dev,
+ "failed to disable hover: %d\n", err);
+ }
}
- mutex_unlock(&sdata->mutex);
if (sdata->use_key) {
err = i2c_smbus_write_byte(sdata->client,
@@ -410,7 +408,7 @@ static ssize_t stmfts_sysfs_chip_id(struct device *dev,
{
struct stmfts_data *sdata = dev_get_drvdata(dev);
- return sprintf(buf, "%#x\n", sdata->chip_id);
+ return sysfs_emit(buf, "%#x\n", sdata->chip_id);
}
static ssize_t stmfts_sysfs_chip_version(struct device *dev,
@@ -418,7 +416,7 @@ static ssize_t stmfts_sysfs_chip_version(struct device *dev,
{
struct stmfts_data *sdata = dev_get_drvdata(dev);
- return sprintf(buf, "%u\n", sdata->chip_ver);
+ return sysfs_emit(buf, "%u\n", sdata->chip_ver);
}
static ssize_t stmfts_sysfs_fw_ver(struct device *dev,
@@ -426,7 +424,7 @@ static ssize_t stmfts_sysfs_fw_ver(struct device *dev,
{
struct stmfts_data *sdata = dev_get_drvdata(dev);
- return sprintf(buf, "%u\n", sdata->fw_ver);
+ return sysfs_emit(buf, "%u\n", sdata->fw_ver);
}
static ssize_t stmfts_sysfs_config_id(struct device *dev,
@@ -434,7 +432,7 @@ static ssize_t stmfts_sysfs_config_id(struct device *dev,
{
struct stmfts_data *sdata = dev_get_drvdata(dev);
- return sprintf(buf, "%#x\n", sdata->config_id);
+ return sysfs_emit(buf, "%#x\n", sdata->config_id);
}
static ssize_t stmfts_sysfs_config_version(struct device *dev,
@@ -442,7 +440,7 @@ static ssize_t stmfts_sysfs_config_version(struct device *dev,
{
struct stmfts_data *sdata = dev_get_drvdata(dev);
- return sprintf(buf, "%u\n", sdata->config_ver);
+ return sysfs_emit(buf, "%u\n", sdata->config_ver);
}
static ssize_t stmfts_sysfs_read_status(struct device *dev,
@@ -457,7 +455,7 @@ static ssize_t stmfts_sysfs_read_status(struct device *dev,
if (err)
return err;
- return sprintf(buf, "%#02x\n", status[0]);
+ return sysfs_emit(buf, "%#02x\n", status[0]);
}
static ssize_t stmfts_sysfs_hover_enable_read(struct device *dev,
@@ -465,7 +463,7 @@ static ssize_t stmfts_sysfs_hover_enable_read(struct device *dev,
{
struct stmfts_data *sdata = dev_get_drvdata(dev);
- return sprintf(buf, "%u\n", sdata->hover_enabled);
+ return sysfs_emit(buf, "%u\n", sdata->hover_enabled);
}
static ssize_t stmfts_sysfs_hover_enable_write(struct device *dev,
@@ -474,26 +472,27 @@ static ssize_t stmfts_sysfs_hover_enable_write(struct device *dev,
{
struct stmfts_data *sdata = dev_get_drvdata(dev);
unsigned long value;
- int err = 0;
+ bool hover;
+ int err;
if (kstrtoul(buf, 0, &value))
return -EINVAL;
- mutex_lock(&sdata->mutex);
+ hover = !!value;
- if (value && sdata->hover_enabled)
- goto out;
+ guard(mutex)(&sdata->mutex);
- if (sdata->running)
- err = i2c_smbus_write_byte(sdata->client,
+ if (hover != sdata->hover_enabled) {
+ if (sdata->running) {
+ err = i2c_smbus_write_byte(sdata->client,
value ? STMFTS_SS_HOVER_SENSE_ON :
STMFTS_SS_HOVER_SENSE_OFF);
+ if (err)
+ return err;
+ }
- if (!err)
- sdata->hover_enabled = !!value;
-
-out:
- mutex_unlock(&sdata->mutex);
+ sdata->hover_enabled = hover;
+ }
return len;
}
@@ -594,9 +593,6 @@ static void stmfts_power_off(void *data)
sdata->regulators);
}
-/* This function is void because I don't want to prevent using the touch key
- * only because the LEDs don't get registered
- */
static int stmfts_enable_led(struct stmfts_data *sdata)
{
int err;
diff --git a/drivers/input/touchscreen/stmpe-ts.c b/drivers/input/touchscreen/stmpe-ts.c
index a94a1997f96b..af0fb38bcfdc 100644
--- a/drivers/input/touchscreen/stmpe-ts.c
+++ b/drivers/input/touchscreen/stmpe-ts.c
@@ -366,12 +366,7 @@ static struct platform_driver stmpe_ts_driver = {
};
module_platform_driver(stmpe_ts_driver);
-static const struct of_device_id stmpe_ts_ids[] = {
- { .compatible = "st,stmpe-ts", },
- { },
-};
-MODULE_DEVICE_TABLE(of, stmpe_ts_ids);
-
+MODULE_ALIAS("platform:stmpe-ts");
MODULE_AUTHOR("Luotao Fu <l.fu@pengutronix.de>");
MODULE_DESCRIPTION("STMPEXXX touchscreen driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/sur40.c b/drivers/input/touchscreen/sur40.c
index 8365a2ac6fce..fe63d53d56db 100644
--- a/drivers/input/touchscreen/sur40.c
+++ b/drivers/input/touchscreen/sur40.c
@@ -538,15 +538,15 @@ static void sur40_process_video(struct sur40_state *sur40)
return;
/* get a new buffer from the list */
- spin_lock(&sur40->qlock);
- if (list_empty(&sur40->buf_list)) {
- dev_dbg(sur40->dev, "buffer queue empty\n");
- spin_unlock(&sur40->qlock);
- return;
+ scoped_guard(spinlock, &sur40->qlock) {
+ if (list_empty(&sur40->buf_list)) {
+ dev_dbg(sur40->dev, "buffer queue empty\n");
+ return;
+ }
+ new_buf = list_first_entry(&sur40->buf_list,
+ struct sur40_buffer, list);
+ list_del(&new_buf->list);
}
- new_buf = list_entry(sur40->buf_list.next, struct sur40_buffer, list);
- list_del(&new_buf->list);
- spin_unlock(&sur40->qlock);
dev_dbg(sur40->dev, "buffer acquired\n");
@@ -672,7 +672,7 @@ static int sur40_probe(struct usb_interface *interface,
return -ENODEV;
/* Allocate memory for our device state and initialize it. */
- sur40 = kzalloc(sizeof(*sur40), GFP_KERNEL);
+ sur40 = kzalloc_obj(*sur40);
if (!sur40)
return -ENOMEM;
@@ -888,9 +888,8 @@ static void sur40_buffer_queue(struct vb2_buffer *vb)
struct sur40_state *sur40 = vb2_get_drv_priv(vb->vb2_queue);
struct sur40_buffer *buf = (struct sur40_buffer *)vb;
- spin_lock(&sur40->qlock);
+ guard(spinlock)(&sur40->qlock);
list_add_tail(&buf->list, &sur40->buf_list);
- spin_unlock(&sur40->qlock);
}
static void return_all_buffers(struct sur40_state *sur40,
@@ -898,12 +897,12 @@ static void return_all_buffers(struct sur40_state *sur40,
{
struct sur40_buffer *buf, *node;
- spin_lock(&sur40->qlock);
+ guard(spinlock)(&sur40->qlock);
+
list_for_each_entry_safe(buf, node, &sur40->buf_list, list) {
vb2_buffer_done(&buf->vb.vb2_buf, state);
list_del(&buf->list);
}
- spin_unlock(&sur40->qlock);
}
/*
@@ -1108,8 +1107,6 @@ static const struct vb2_ops sur40_queue_ops = {
.buf_queue = sur40_buffer_queue,
.start_streaming = sur40_start_streaming,
.stop_streaming = sur40_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static const struct vb2_queue sur40_queue = {
diff --git a/drivers/input/touchscreen/sx8654.c b/drivers/input/touchscreen/sx8654.c
index f5c5881cef6b..0d92aaeea3e0 100644
--- a/drivers/input/touchscreen/sx8654.c
+++ b/drivers/input/touchscreen/sx8654.c
@@ -116,13 +116,12 @@ static inline void sx865x_penrelease(struct sx8654 *ts)
static void sx865x_penrelease_timer_handler(struct timer_list *t)
{
- struct sx8654 *ts = from_timer(ts, t, timer);
- unsigned long flags;
+ struct sx8654 *ts = timer_container_of(ts, t, timer);
- spin_lock_irqsave(&ts->lock, flags);
- sx865x_penrelease(ts);
- spin_unlock_irqrestore(&ts->lock, flags);
dev_dbg(&ts->client->dev, "penrelease by timer\n");
+
+ guard(spinlock_irqsave)(&ts->lock);
+ sx865x_penrelease(ts);
}
static irqreturn_t sx8650_irq(int irq, void *handle)
@@ -130,7 +129,6 @@ static irqreturn_t sx8650_irq(int irq, void *handle)
struct sx8654 *ts = handle;
struct device *dev = &ts->client->dev;
int len, i;
- unsigned long flags;
u8 stat;
u16 x, y;
u16 ch;
@@ -153,7 +151,7 @@ static irqreturn_t sx8650_irq(int irq, void *handle)
return IRQ_HANDLED;
}
- spin_lock_irqsave(&ts->lock, flags);
+ guard(spinlock_irqsave)(&ts->lock);
x = 0;
y = 0;
@@ -184,7 +182,6 @@ static irqreturn_t sx8650_irq(int irq, void *handle)
dev_dbg(dev, "point(%4d,%4d)\n", x, y);
mod_timer(&ts->timer, jiffies + SX8650_PENIRQ_TIMEOUT);
- spin_unlock_irqrestore(&ts->lock, flags);
return IRQ_HANDLED;
}
@@ -290,7 +287,7 @@ static void sx8654_close(struct input_dev *dev)
disable_irq(client->irq);
if (!sx8654->data->has_irq_penrelease)
- del_timer_sync(&sx8654->timer);
+ timer_delete_sync(&sx8654->timer);
/* enable manual mode mode */
error = i2c_smbus_write_byte(client, sx8654->data->cmd_manual);
@@ -394,9 +391,13 @@ static int sx8654_probe(struct i2c_client *client)
return error;
}
+ /*
+ * Start with the interrupt disabled, it will be enabled in
+ * sx8654_open().
+ */
error = devm_request_threaded_irq(&client->dev, client->irq,
NULL, sx8654->data->irqh,
- IRQF_ONESHOT,
+ IRQF_ONESHOT | IRQF_NO_AUTOEN,
client->name, sx8654);
if (error) {
dev_err(&client->dev,
@@ -405,9 +406,6 @@ static int sx8654_probe(struct i2c_client *client)
return error;
}
- /* Disable the IRQ, we'll enable it in sx8654_open() */
- disable_irq(client->irq);
-
error = input_register_device(sx8654->input);
if (error)
return error;
diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
index 93d659ff90aa..623546e80668 100644
--- a/drivers/input/touchscreen/ti_am335x_tsc.c
+++ b/drivers/input/touchscreen/ti_am335x_tsc.c
@@ -85,7 +85,7 @@ static int titsc_config_wires(struct titsc *ts_dev)
wire_order[i] = ts_dev->config_inp[i] & 0x0F;
if (WARN_ON(analog_line[i] > 7))
return -EINVAL;
- if (WARN_ON(wire_order[i] > ARRAY_SIZE(config_pins)))
+ if (WARN_ON(wire_order[i] >= ARRAY_SIZE(config_pins)))
return -EINVAL;
}
@@ -389,6 +389,10 @@ static int titsc_parse_dt(struct platform_device *pdev,
dev_warn(&pdev->dev,
"invalid co-ordinate readouts, resetting it to 5\n");
ts_dev->coordinate_readouts = 5;
+ } else if (ts_dev->coordinate_readouts > 6) {
+ dev_warn(&pdev->dev,
+ "co-ordinate readouts too large, limiting to 6\n");
+ ts_dev->coordinate_readouts = 6;
}
err = of_property_read_u32(node, "ti,charge-delay",
@@ -418,7 +422,7 @@ static int titsc_probe(struct platform_device *pdev)
int err;
/* Allocate memory for device */
- ts_dev = kzalloc(sizeof(*ts_dev), GFP_KERNEL);
+ ts_dev = kzalloc_obj(*ts_dev);
input_dev = input_allocate_device();
if (!ts_dev || !input_dev) {
dev_err(&pdev->dev, "failed to allocate memory.\n");
diff --git a/drivers/input/touchscreen/touchit213.c b/drivers/input/touchscreen/touchit213.c
index c2718350815c..6d4a1acf57c9 100644
--- a/drivers/input/touchscreen/touchit213.c
+++ b/drivers/input/touchscreen/touchit213.c
@@ -139,7 +139,7 @@ static int touchit213_connect(struct serio *serio, struct serio_driver *drv)
struct input_dev *input_dev;
int err;
- touchit213 = kzalloc(sizeof(*touchit213), GFP_KERNEL);
+ touchit213 = kzalloc_obj(*touchit213);
input_dev = input_allocate_device();
if (!touchit213 || !input_dev) {
err = -ENOMEM;
@@ -148,8 +148,8 @@ static int touchit213_connect(struct serio *serio, struct serio_driver *drv)
touchit213->serio = serio;
touchit213->dev = input_dev;
- snprintf(touchit213->phys, sizeof(touchit213->phys),
- "%s/input0", serio->phys);
+ scnprintf(touchit213->phys, sizeof(touchit213->phys),
+ "%s/input0", serio->phys);
input_dev->name = "Sahara Touch-iT213 Serial TouchScreen";
input_dev->phys = touchit213->phys;
diff --git a/drivers/input/touchscreen/touchright.c b/drivers/input/touchscreen/touchright.c
index 30ba97bd00a1..d7fdf201e4d1 100644
--- a/drivers/input/touchscreen/touchright.c
+++ b/drivers/input/touchscreen/touchright.c
@@ -102,7 +102,7 @@ static int tr_connect(struct serio *serio, struct serio_driver *drv)
struct input_dev *input_dev;
int err;
- tr = kzalloc(sizeof(*tr), GFP_KERNEL);
+ tr = kzalloc_obj(*tr);
input_dev = input_allocate_device();
if (!tr || !input_dev) {
err = -ENOMEM;
@@ -111,7 +111,7 @@ static int tr_connect(struct serio *serio, struct serio_driver *drv)
tr->serio = serio;
tr->dev = input_dev;
- snprintf(tr->phys, sizeof(tr->phys), "%s/input0", serio->phys);
+ scnprintf(tr->phys, sizeof(tr->phys), "%s/input0", serio->phys);
input_dev->name = "Touchright Serial TouchScreen";
input_dev->phys = tr->phys;
diff --git a/drivers/input/touchscreen/touchwin.c b/drivers/input/touchscreen/touchwin.c
index fbd72789ea80..099fd88e65d8 100644
--- a/drivers/input/touchscreen/touchwin.c
+++ b/drivers/input/touchscreen/touchwin.c
@@ -109,7 +109,7 @@ static int tw_connect(struct serio *serio, struct serio_driver *drv)
struct input_dev *input_dev;
int err;
- tw = kzalloc(sizeof(*tw), GFP_KERNEL);
+ tw = kzalloc_obj(*tw);
input_dev = input_allocate_device();
if (!tw || !input_dev) {
err = -ENOMEM;
@@ -118,7 +118,7 @@ static int tw_connect(struct serio *serio, struct serio_driver *drv)
tw->serio = serio;
tw->dev = input_dev;
- snprintf(tw->phys, sizeof(tw->phys), "%s/input0", serio->phys);
+ scnprintf(tw->phys, sizeof(tw->phys), "%s/input0", serio->phys);
input_dev->name = "Touchwindow Serial TouchScreen";
input_dev->phys = tw->phys;
diff --git a/drivers/input/touchscreen/tsc2007.h b/drivers/input/touchscreen/tsc2007.h
index 69b08dd6c8df..e346fb4f7552 100644
--- a/drivers/input/touchscreen/tsc2007.h
+++ b/drivers/input/touchscreen/tsc2007.h
@@ -19,6 +19,7 @@
#ifndef _TSC2007_H
#define _TSC2007_H
+#include <linux/input/touchscreen.h>
struct gpio_desc;
#define TSC2007_MEASURE_TEMP0 (0x0 << 4)
@@ -63,6 +64,7 @@ struct tsc2007 {
struct i2c_client *client;
+ struct touchscreen_properties prop;
u16 model;
u16 x_plate_ohms;
u16 max_rt;
diff --git a/drivers/input/touchscreen/tsc2007_core.c b/drivers/input/touchscreen/tsc2007_core.c
index 8d832a372b89..524f14eb3da2 100644
--- a/drivers/input/touchscreen/tsc2007_core.c
+++ b/drivers/input/touchscreen/tsc2007_core.c
@@ -23,6 +23,7 @@
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/i2c.h>
+#include <linux/math64.h>
#include <linux/mod_devicetable.h>
#include <linux/property.h>
#include <linux/platform_data/tsc2007.h>
@@ -68,7 +69,7 @@ static void tsc2007_read_values(struct tsc2007 *tsc, struct ts_event *tc)
u32 tsc2007_calculate_resistance(struct tsc2007 *tsc, struct ts_event *tc)
{
- u32 rt = 0;
+ u64 rt = 0;
/* range filtering */
if (tc->x == MAX_12BIT)
@@ -79,11 +80,13 @@ u32 tsc2007_calculate_resistance(struct tsc2007 *tsc, struct ts_event *tc)
rt = tc->z2 - tc->z1;
rt *= tc->x;
rt *= tsc->x_plate_ohms;
- rt /= tc->z1;
+ rt = div_u64(rt, tc->z1);
rt = (rt + 2047) >> 12;
}
- return rt;
+ if (rt > U32_MAX)
+ return U32_MAX;
+ return (u32) rt;
}
bool tsc2007_is_pen_down(struct tsc2007 *ts)
@@ -119,9 +122,10 @@ static irqreturn_t tsc2007_soft_irq(int irq, void *handle)
/* pen is down, continue with the measurement */
- mutex_lock(&ts->mlock);
- tsc2007_read_values(ts, &tc);
- mutex_unlock(&ts->mlock);
+ /* Serialize access between the ISR and IIO reads. */
+ scoped_guard(mutex, &ts->mlock) {
+ tsc2007_read_values(ts, &tc);
+ }
rt = tsc2007_calculate_resistance(ts, &tc);
@@ -142,8 +146,7 @@ static irqreturn_t tsc2007_soft_irq(int irq, void *handle)
rt = ts->max_rt - rt;
input_report_key(input, BTN_TOUCH, 1);
- input_report_abs(input, ABS_X, tc.x);
- input_report_abs(input, ABS_Y, tc.y);
+ touchscreen_report_pos(input, &ts->prop, tc.x, tc.y, false);
input_report_abs(input, ABS_PRESSURE, rt);
input_sync(input);
@@ -178,7 +181,8 @@ static void tsc2007_stop(struct tsc2007 *ts)
mb();
wake_up(&ts->wait);
- disable_irq(ts->irq);
+ if (ts->irq)
+ disable_irq(ts->irq);
}
static int tsc2007_open(struct input_dev *input_dev)
@@ -189,7 +193,8 @@ static int tsc2007_open(struct input_dev *input_dev)
ts->stopped = false;
mb();
- enable_irq(ts->irq);
+ if (ts->irq)
+ enable_irq(ts->irq);
/* Prepare for touch readings - power down ADC and enable PENIRQ */
err = tsc2007_xfer(ts, PWRDOWN);
@@ -254,7 +259,7 @@ static int tsc2007_probe_properties(struct device *dev, struct tsc2007 *ts)
if (ts->gpiod)
ts->get_pendown_state = tsc2007_get_pendown_state_gpio;
else
- dev_warn(dev, "Pen down GPIO is not specified in properties\n");
+ dev_dbg(dev, "Pen down GPIO is not specified in properties\n");
return 0;
}
@@ -339,9 +344,9 @@ static int tsc2007_probe(struct i2c_client *client)
input_set_drvdata(input_dev, ts);
input_set_capability(input_dev, EV_KEY, BTN_TOUCH);
-
input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, ts->fuzzx, 0);
input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, ts->fuzzy, 0);
+ touchscreen_parse_properties(input_dev, false, &ts->prop);
input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT,
ts->fuzzz, 0);
@@ -362,17 +367,19 @@ static int tsc2007_probe(struct i2c_client *client)
pdata->init_platform_hw();
}
- err = devm_request_threaded_irq(&client->dev, ts->irq,
- NULL, tsc2007_soft_irq,
- IRQF_ONESHOT,
- client->dev.driver->name, ts);
- if (err) {
- dev_err(&client->dev, "Failed to request irq %d: %d\n",
- ts->irq, err);
- return err;
- }
+ if (ts->irq) {
+ err = devm_request_threaded_irq(&client->dev, ts->irq,
+ NULL, tsc2007_soft_irq,
+ IRQF_ONESHOT,
+ client->dev.driver->name, ts);
+ if (err) {
+ dev_err(&client->dev, "Failed to request irq %d: %d\n",
+ ts->irq, err);
+ return err;
+ }
- tsc2007_stop(ts);
+ tsc2007_stop(ts);
+ }
/* power down the chip (TSC2007_SETUP does not ACK on I2C) */
err = tsc2007_xfer(ts, PWRDOWN);
diff --git a/drivers/input/touchscreen/tsc2007_iio.c b/drivers/input/touchscreen/tsc2007_iio.c
index 752eb7fe5da3..e9e495ec0b6c 100644
--- a/drivers/input/touchscreen/tsc2007_iio.c
+++ b/drivers/input/touchscreen/tsc2007_iio.c
@@ -41,7 +41,6 @@ static int tsc2007_read_raw(struct iio_dev *indio_dev,
struct tsc2007_iio *iio = iio_priv(indio_dev);
struct tsc2007 *tsc = iio->ts;
int adc_chan = chan->channel;
- int ret = 0;
if (adc_chan >= ARRAY_SIZE(tsc2007_iio_channel))
return -EINVAL;
@@ -49,7 +48,7 @@ static int tsc2007_read_raw(struct iio_dev *indio_dev,
if (mask != IIO_CHAN_INFO_RAW)
return -EINVAL;
- mutex_lock(&tsc->mlock);
+ guard(mutex)(&tsc->mlock);
switch (chan->channel) {
case 0:
@@ -92,11 +91,7 @@ static int tsc2007_read_raw(struct iio_dev *indio_dev,
/* Prepare for next touch reading - power down ADC, enable PENIRQ */
tsc2007_xfer(tsc, PWRDOWN);
- mutex_unlock(&tsc->mlock);
-
- ret = IIO_VAL_INT;
-
- return ret;
+ return IIO_VAL_INT;
}
static const struct iio_info tsc2007_iio_info = {
diff --git a/drivers/input/touchscreen/tsc200x-core.c b/drivers/input/touchscreen/tsc200x-core.c
index df39dee13e1c..eba53613b005 100644
--- a/drivers/input/touchscreen/tsc200x-core.c
+++ b/drivers/input/touchscreen/tsc200x-core.c
@@ -10,6 +10,7 @@
* based on TSC2301 driver by Klaus K. Pedersen <klaus.k.pedersen@nokia.com>
*/
+#include <linux/export.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/input.h>
@@ -194,7 +195,7 @@ out:
static void tsc200x_penup_timer(struct timer_list *t)
{
- struct tsc200x *ts = from_timer(ts, t, penup_timer);
+ struct tsc200x *ts = timer_container_of(ts, t, penup_timer);
guard(spinlock_irqsave)(&ts->lock);
tsc200x_update_pen_state(ts, 0, 0, 0);
@@ -229,7 +230,7 @@ static void __tsc200x_disable(struct tsc200x *ts)
guard(disable_irq)(&ts->irq);
- del_timer_sync(&ts->penup_timer);
+ timer_delete_sync(&ts->penup_timer);
cancel_delayed_work_sync(&ts->esd_work);
}
@@ -388,7 +389,7 @@ static void tsc200x_esd_work(struct work_struct *work)
dev_info(ts->dev, "TSC200X not responding - resetting\n");
scoped_guard(disable_irq, &ts->irq) {
- del_timer_sync(&ts->penup_timer);
+ timer_delete_sync(&ts->penup_timer);
tsc200x_update_pen_state(ts, 0, 0, 0);
tsc200x_reset(ts);
}
diff --git a/drivers/input/touchscreen/tsc40.c b/drivers/input/touchscreen/tsc40.c
index 9f485cf57a72..2a28a309eab5 100644
--- a/drivers/input/touchscreen/tsc40.c
+++ b/drivers/input/touchscreen/tsc40.c
@@ -83,7 +83,7 @@ static int tsc_connect(struct serio *serio, struct serio_driver *drv)
struct input_dev *input_dev;
int error;
- ptsc = kzalloc(sizeof(*ptsc), GFP_KERNEL);
+ ptsc = kzalloc_obj(*ptsc);
input_dev = input_allocate_device();
if (!ptsc || !input_dev) {
error = -ENOMEM;
@@ -92,7 +92,7 @@ static int tsc_connect(struct serio *serio, struct serio_driver *drv)
ptsc->serio = serio;
ptsc->dev = input_dev;
- snprintf(ptsc->phys, sizeof(ptsc->phys), "%s/input0", serio->phys);
+ scnprintf(ptsc->phys, sizeof(ptsc->phys), "%s/input0", serio->phys);
input_dev->name = "TSC-10/25/40 Serial TouchScreen";
input_dev->phys = ptsc->phys;
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c
index 7567efabe014..0bbacb517c28 100644
--- a/drivers/input/touchscreen/usbtouchscreen.c
+++ b/drivers/input/touchscreen/usbtouchscreen.c
@@ -378,7 +378,7 @@ static int mtouch_alloc(struct usbtouch_usb *usbtouch)
{
struct mtouch_priv *priv;
- priv = kmalloc(sizeof(*priv), GFP_KERNEL);
+ priv = kmalloc_obj(*priv);
if (!priv)
return -ENOMEM;
@@ -938,7 +938,7 @@ static int nexio_alloc(struct usbtouch_usb *usbtouch)
struct nexio_priv *priv;
int ret = -ENOMEM;
- priv = kmalloc(sizeof(*priv), GFP_KERNEL);
+ priv = kmalloc_obj(*priv);
if (!priv)
goto out_buf;
@@ -969,24 +969,21 @@ static int nexio_init(struct usbtouch_usb *usbtouch)
{
struct usb_device *dev = interface_to_usbdev(usbtouch->interface);
struct usb_host_interface *interface = usbtouch->interface->cur_altsetting;
+ struct usb_endpoint_descriptor *ep_in, *ep_out;
struct nexio_priv *priv = usbtouch->priv;
- int ret = -ENOMEM;
int actual_len, i;
char *firmware_ver = NULL, *device_name = NULL;
- int input_ep = 0, output_ep = 0;
+ int input_ep, output_ep;
+ int ret;
/* find first input and output endpoint */
- for (i = 0; i < interface->desc.bNumEndpoints; i++) {
- if (!input_ep &&
- usb_endpoint_dir_in(&interface->endpoint[i].desc))
- input_ep = interface->endpoint[i].desc.bEndpointAddress;
- if (!output_ep &&
- usb_endpoint_dir_out(&interface->endpoint[i].desc))
- output_ep = interface->endpoint[i].desc.bEndpointAddress;
- }
- if (!input_ep || !output_ep)
+ ret = usb_find_common_endpoints(interface, &ep_in, &ep_out, NULL, NULL);
+ if (ret)
return -ENXIO;
+ input_ep = usb_endpoint_num(ep_in);
+ output_ep = usb_endpoint_num(ep_out);
+
u8 *buf __free(kfree) = kmalloc(NEXIO_BUFSIZE, GFP_NOIO);
if (!buf)
return -ENOMEM;
@@ -1070,6 +1067,11 @@ static int nexio_read_data(struct usbtouch_usb *usbtouch, unsigned char *pkt)
if (x_len > 0xff)
x_len -= 0x80;
+ if (data_len > usbtouch->data_size - sizeof(*packet))
+ data_len = usbtouch->data_size - sizeof(*packet);
+ if (x_len > data_len)
+ x_len = data_len;
+
/* send ACK */
ret = usb_submit_urb(priv->ack, GFP_ATOMIC);
if (ret)
@@ -1427,18 +1429,6 @@ static void usbtouch_free_buffers(struct usb_device *udev,
kfree(usbtouch->buffer);
}
-static struct usb_endpoint_descriptor *
-usbtouch_get_input_endpoint(struct usb_host_interface *interface)
-{
- int i;
-
- for (i = 0; i < interface->desc.bNumEndpoints; i++)
- if (usb_endpoint_dir_in(&interface->endpoint[i].desc))
- return &interface->endpoint[i].desc;
-
- return NULL;
-}
-
static int usbtouch_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
@@ -1447,18 +1437,22 @@ static int usbtouch_probe(struct usb_interface *intf,
struct usb_endpoint_descriptor *endpoint;
struct usb_device *udev = interface_to_usbdev(intf);
const struct usbtouch_device_info *type;
- int err = -ENOMEM;
+ int err;
/* some devices are ignored */
type = (const struct usbtouch_device_info *)id->driver_info;
if (!type)
return -ENODEV;
- endpoint = usbtouch_get_input_endpoint(intf->cur_altsetting);
- if (!endpoint)
- return -ENXIO;
+ err = usb_find_int_in_endpoint(intf->cur_altsetting, &endpoint);
+ if (err) {
+ err = usb_find_bulk_in_endpoint(intf->cur_altsetting, &endpoint);
+ if (err)
+ return -ENXIO;
+ }
- usbtouch = kzalloc(sizeof(*usbtouch), GFP_KERNEL);
+ err = -ENOMEM;
+ usbtouch = kzalloc_obj(*usbtouch);
input_dev = input_allocate_device();
if (!usbtouch || !input_dev)
goto out_free;
diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c
index ed2ca8a689d5..45930d731873 100644
--- a/drivers/input/touchscreen/wacom_w8001.c
+++ b/drivers/input/touchscreen/wacom_w8001.c
@@ -596,7 +596,7 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv)
char basename[64] = "Wacom Serial";
int err, err_pen, err_touch;
- w8001 = kzalloc(sizeof(*w8001), GFP_KERNEL);
+ w8001 = kzalloc_obj(*w8001);
input_dev_pen = input_allocate_device();
input_dev_touch = input_allocate_device();
if (!w8001 || !input_dev_pen || !input_dev_touch) {
diff --git a/drivers/input/touchscreen/wdt87xx_i2c.c b/drivers/input/touchscreen/wdt87xx_i2c.c
index 88d376090e6e..bdaabb14dc8c 100644
--- a/drivers/input/touchscreen/wdt87xx_i2c.c
+++ b/drivers/input/touchscreen/wdt87xx_i2c.c
@@ -813,56 +813,46 @@ static int wdt87xx_load_chunk(struct i2c_client *client,
return 0;
}
-static int wdt87xx_do_update_firmware(struct i2c_client *client,
+static int wdt87xx_do_update_firmware(struct wdt87xx_data *wdt,
const struct firmware *fw,
unsigned int chunk_id)
{
- struct wdt87xx_data *wdt = i2c_get_clientdata(client);
+ struct i2c_client *client = wdt->client;
int error;
- error = wdt87xx_validate_firmware(wdt, fw);
- if (error)
- return error;
-
- error = mutex_lock_interruptible(&wdt->fw_mutex);
- if (error)
- return error;
-
- disable_irq(client->irq);
-
error = wdt87xx_load_chunk(client, fw, chunk_id);
if (error) {
dev_err(&client->dev,
"firmware load failed (type: %d): %d\n",
chunk_id, error);
- goto out;
+ return error;
}
error = wdt87xx_sw_reset(client);
if (error) {
dev_err(&client->dev, "soft reset failed: %d\n", error);
- goto out;
+ return error;
}
/* Refresh the parameters */
error = wdt87xx_get_sysparam(client, &wdt->param);
- if (error)
+ if (error) {
dev_err(&client->dev,
"failed to refresh system parameters: %d\n", error);
-out:
- enable_irq(client->irq);
- mutex_unlock(&wdt->fw_mutex);
+ return error;
+ }
- return error ? error : 0;
+ return 0;
}
static int wdt87xx_update_firmware(struct device *dev,
const char *fw_name, unsigned int chunk_id)
{
struct i2c_client *client = to_i2c_client(dev);
- const struct firmware *fw;
+ struct wdt87xx_data *wdt = i2c_get_clientdata(client);
int error;
+ const struct firmware *fw __free(firmware) = NULL;
error = request_firmware(&fw, fw_name, dev);
if (error) {
dev_err(&client->dev, "unable to retrieve firmware %s: %d\n",
@@ -870,11 +860,19 @@ static int wdt87xx_update_firmware(struct device *dev,
return error;
}
- error = wdt87xx_do_update_firmware(client, fw, chunk_id);
+ error = wdt87xx_validate_firmware(wdt, fw);
+ if (error)
+ return error;
- release_firmware(fw);
+ scoped_cond_guard(mutex_intr, return -EINTR, &wdt->fw_mutex) {
+ guard(disable_irq)(&client->irq);
+
+ error = wdt87xx_do_update_firmware(wdt, fw, chunk_id);
+ if (error)
+ return error;
+ }
- return error ? error : 0;
+ return 0;
}
static ssize_t config_csum_show(struct device *dev,
@@ -1026,10 +1024,8 @@ static int wdt87xx_ts_create_input_device(struct wdt87xx_data *wdt)
int error;
input = devm_input_allocate_device(dev);
- if (!input) {
- dev_err(dev, "failed to allocate input device\n");
+ if (!input)
return -ENOMEM;
- }
wdt->input = input;
input->name = "WDT87xx Touchscreen";
@@ -1053,10 +1049,8 @@ static int wdt87xx_ts_create_input_device(struct wdt87xx_data *wdt)
INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
error = input_register_device(input);
- if (error) {
- dev_err(dev, "failed to register input device: %d\n", error);
- return error;
- }
+ if (error)
+ return dev_err_probe(dev, error, "failed to register input device\n");
return 0;
}
@@ -1096,10 +1090,8 @@ static int wdt87xx_ts_probe(struct i2c_client *client)
NULL, wdt87xx_ts_interrupt,
IRQF_ONESHOT,
client->name, wdt);
- if (error) {
- dev_err(&client->dev, "request irq failed: %d\n", error);
+ if (error)
return error;
- }
return 0;
}
diff --git a/drivers/input/touchscreen/wm9705.c b/drivers/input/touchscreen/wm9705.c
index 4b55d5e1ea0f..96484aae030c 100644
--- a/drivers/input/touchscreen/wm9705.c
+++ b/drivers/input/touchscreen/wm9705.c
@@ -9,6 +9,7 @@
* Russell King <rmk@arm.linux.org.uk>
*/
+#include <linux/export.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
diff --git a/drivers/input/touchscreen/wm9712.c b/drivers/input/touchscreen/wm9712.c
index 6947714dfefa..087ece57741a 100644
--- a/drivers/input/touchscreen/wm9712.c
+++ b/drivers/input/touchscreen/wm9712.c
@@ -9,6 +9,7 @@
* Russell King <rmk@arm.linux.org.uk>
*/
+#include <linux/export.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
diff --git a/drivers/input/touchscreen/wm9713.c b/drivers/input/touchscreen/wm9713.c
index a67fbe304f92..6f13f46ce6e6 100644
--- a/drivers/input/touchscreen/wm9713.c
+++ b/drivers/input/touchscreen/wm9713.c
@@ -9,6 +9,7 @@
* Russell King <rmk@arm.linux.org.uk>
*/
+#include <linux/export.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c
index b25771a8df2b..c51822563f3f 100644
--- a/drivers/input/touchscreen/wm97xx-core.c
+++ b/drivers/input/touchscreen/wm97xx-core.c
@@ -29,6 +29,7 @@
* - Support for async sampling control for noisy LCDs.
*/
+#include <linux/export.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
@@ -125,7 +126,7 @@ int wm97xx_read_aux_adc(struct wm97xx *wm, u16 adcsel)
int timeout = 0;
/* get codec */
- mutex_lock(&wm->codec_mutex);
+ guard(mutex)(&wm->codec_mutex);
/* When the touchscreen is not in use, we may have to power up
* the AUX ADC before we can use sample the AUX inputs->
@@ -159,7 +160,6 @@ int wm97xx_read_aux_adc(struct wm97xx *wm, u16 adcsel)
wm->codec->dig_enable(wm, false);
}
- mutex_unlock(&wm->codec_mutex);
return (rc == RC_VALID ? auxval & 0xfff : -EBUSY);
}
EXPORT_SYMBOL_GPL(wm97xx_read_aux_adc);
@@ -175,18 +175,11 @@ EXPORT_SYMBOL_GPL(wm97xx_read_aux_adc);
enum wm97xx_gpio_status wm97xx_get_gpio(struct wm97xx *wm, u32 gpio)
{
u16 status;
- enum wm97xx_gpio_status ret;
- mutex_lock(&wm->codec_mutex);
- status = wm97xx_reg_read(wm, AC97_GPIO_STATUS);
-
- if (status & gpio)
- ret = WM97XX_GPIO_HIGH;
- else
- ret = WM97XX_GPIO_LOW;
+ guard(mutex)(&wm->codec_mutex);
- mutex_unlock(&wm->codec_mutex);
- return ret;
+ status = wm97xx_reg_read(wm, AC97_GPIO_STATUS);
+ return (status & gpio) ? WM97XX_GPIO_HIGH : WM97XX_GPIO_LOW;
}
EXPORT_SYMBOL_GPL(wm97xx_get_gpio);
@@ -204,7 +197,8 @@ void wm97xx_set_gpio(struct wm97xx *wm, u32 gpio,
{
u16 reg;
- mutex_lock(&wm->codec_mutex);
+ guard(mutex)(&wm->codec_mutex);
+
reg = wm97xx_reg_read(wm, AC97_GPIO_STATUS);
if (status == WM97XX_GPIO_HIGH)
@@ -216,7 +210,6 @@ void wm97xx_set_gpio(struct wm97xx *wm, u32 gpio,
wm97xx_reg_write(wm, AC97_GPIO_STATUS, reg << 1);
else
wm97xx_reg_write(wm, AC97_GPIO_STATUS, reg);
- mutex_unlock(&wm->codec_mutex);
}
EXPORT_SYMBOL_GPL(wm97xx_set_gpio);
@@ -230,7 +223,8 @@ void wm97xx_config_gpio(struct wm97xx *wm, u32 gpio, enum wm97xx_gpio_dir dir,
{
u16 reg;
- mutex_lock(&wm->codec_mutex);
+ guard(mutex)(&wm->codec_mutex);
+
reg = wm97xx_reg_read(wm, AC97_GPIO_POLARITY);
if (pol == WM97XX_GPIO_POL_HIGH)
@@ -263,7 +257,6 @@ void wm97xx_config_gpio(struct wm97xx *wm, u32 gpio, enum wm97xx_gpio_dir dir,
reg &= ~gpio;
wm97xx_reg_write(wm, AC97_GPIO_CFG, reg);
- mutex_unlock(&wm->codec_mutex);
}
EXPORT_SYMBOL_GPL(wm97xx_config_gpio);
@@ -302,7 +295,9 @@ static irqreturn_t wm97xx_pen_interrupt(int irq, void *dev_id)
wm->pen_is_down = 0;
} else {
u16 status, pol;
- mutex_lock(&wm->codec_mutex);
+
+ guard(mutex)(&wm->codec_mutex);
+
status = wm97xx_reg_read(wm, AC97_GPIO_STATUS);
pol = wm97xx_reg_read(wm, AC97_GPIO_POLARITY);
@@ -322,7 +317,6 @@ static irqreturn_t wm97xx_pen_interrupt(int irq, void *dev_id)
else
wm97xx_reg_write(wm, AC97_GPIO_STATUS, status &
~WM97XX_GPIO_13);
- mutex_unlock(&wm->codec_mutex);
}
/* If the system is not using continuous mode or it provides a
@@ -381,7 +375,7 @@ static int wm97xx_read_samples(struct wm97xx *wm)
struct wm97xx_data data;
int rc;
- mutex_lock(&wm->codec_mutex);
+ guard(mutex)(&wm->codec_mutex);
if (wm->mach_ops && wm->mach_ops->acc_enabled)
rc = wm->mach_ops->acc_pen_down(wm);
@@ -421,8 +415,7 @@ static int wm97xx_read_samples(struct wm97xx *wm)
abs_y[0] > (data.y & 0xfff) ||
abs_y[1] < (data.y & 0xfff)) {
dev_dbg(wm->dev, "Measurement out of range, dropping it\n");
- rc = RC_AGAIN;
- goto out;
+ return RC_AGAIN;
}
input_report_abs(wm->input_dev, ABS_X, data.x & 0xfff);
@@ -438,8 +431,6 @@ static int wm97xx_read_samples(struct wm97xx *wm)
wm->ts_reader_interval = wm->ts_reader_min_interval;
}
-out:
- mutex_unlock(&wm->codec_mutex);
return rc;
}
@@ -772,7 +763,8 @@ static int wm97xx_suspend(struct device *dev)
else
suspend_mode = 0;
- mutex_lock(&wm->input_dev->mutex);
+ guard(mutex)(&wm->input_dev->mutex);
+
if (input_device_enabled(wm->input_dev))
cancel_delayed_work_sync(&wm->ts_reader);
@@ -790,7 +782,6 @@ static int wm97xx_suspend(struct device *dev)
reg = wm97xx_reg_read(wm, AC97_EXTENDED_MID) | 0x8000;
wm97xx_reg_write(wm, AC97_EXTENDED_MID, reg);
}
- mutex_unlock(&wm->input_dev->mutex);
return 0;
}
@@ -799,7 +790,8 @@ static int wm97xx_resume(struct device *dev)
{
struct wm97xx *wm = dev_get_drvdata(dev);
- mutex_lock(&wm->input_dev->mutex);
+ guard(mutex)(&wm->input_dev->mutex);
+
/* restore digitiser and gpios */
if (wm->id == WM9713_ID2) {
wm97xx_reg_write(wm, AC97_WM9713_DIG1, wm->dig[0]);
@@ -826,7 +818,6 @@ static int wm97xx_resume(struct device *dev)
queue_delayed_work(wm->ts_workq, &wm->ts_reader,
wm->ts_reader_interval);
}
- mutex_unlock(&wm->input_dev->mutex);
return 0;
}
@@ -839,13 +830,12 @@ static DEFINE_SIMPLE_DEV_PM_OPS(wm97xx_pm_ops, wm97xx_suspend, wm97xx_resume);
int wm97xx_register_mach_ops(struct wm97xx *wm,
struct wm97xx_mach_ops *mach_ops)
{
- mutex_lock(&wm->codec_mutex);
- if (wm->mach_ops) {
- mutex_unlock(&wm->codec_mutex);
+ guard(mutex)(&wm->codec_mutex);
+
+ if (wm->mach_ops)
return -EINVAL;
- }
+
wm->mach_ops = mach_ops;
- mutex_unlock(&wm->codec_mutex);
return 0;
}
@@ -853,9 +843,9 @@ EXPORT_SYMBOL_GPL(wm97xx_register_mach_ops);
void wm97xx_unregister_mach_ops(struct wm97xx *wm)
{
- mutex_lock(&wm->codec_mutex);
+ guard(mutex)(&wm->codec_mutex);
+
wm->mach_ops = NULL;
- mutex_unlock(&wm->codec_mutex);
}
EXPORT_SYMBOL_GPL(wm97xx_unregister_mach_ops);
diff --git a/drivers/input/touchscreen/zforce_ts.c b/drivers/input/touchscreen/zforce_ts.c
index df42fdf36ae3..a360749fa076 100644
--- a/drivers/input/touchscreen/zforce_ts.c
+++ b/drivers/input/touchscreen/zforce_ts.c
@@ -747,8 +747,7 @@ static int zforce_probe(struct i2c_client *client)
input_dev = devm_input_allocate_device(&client->dev);
if (!input_dev)
- return dev_err_probe(&client->dev, -ENOMEM,
- "could not allocate input device\n");
+ return -ENOMEM;
ts->client = client;
ts->input = input_dev;
diff --git a/drivers/input/touchscreen/zinitix.c b/drivers/input/touchscreen/zinitix.c
index 716d6fa60f86..0c36765bd79f 100644
--- a/drivers/input/touchscreen/zinitix.c
+++ b/drivers/input/touchscreen/zinitix.c
@@ -703,13 +703,11 @@ static int zinitix_suspend(struct device *dev)
struct i2c_client *client = to_i2c_client(dev);
struct bt541_ts_data *bt541 = i2c_get_clientdata(client);
- mutex_lock(&bt541->input_dev->mutex);
+ guard(mutex)(&bt541->input_dev->mutex);
if (input_device_enabled(bt541->input_dev))
zinitix_stop(bt541);
- mutex_unlock(&bt541->input_dev->mutex);
-
return 0;
}
@@ -717,16 +715,17 @@ static int zinitix_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct bt541_ts_data *bt541 = i2c_get_clientdata(client);
- int ret = 0;
-
- mutex_lock(&bt541->input_dev->mutex);
+ int error;
- if (input_device_enabled(bt541->input_dev))
- ret = zinitix_start(bt541);
+ guard(mutex)(&bt541->input_dev->mutex);
- mutex_unlock(&bt541->input_dev->mutex);
+ if (input_device_enabled(bt541->input_dev)) {
+ error = zinitix_start(bt541);
+ if (error)
+ return error;
+ }
- return ret;
+ return 0;
}
static DEFINE_SIMPLE_DEV_PM_OPS(zinitix_pm_ops, zinitix_suspend, zinitix_resume);