summaryrefslogtreecommitdiff
path: root/drivers/input/touchscreen
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/touchscreen')
-rw-r--r--drivers/input/touchscreen/88pm860x-ts.c16
-rw-r--r--drivers/input/touchscreen/Kconfig15
-rw-r--r--drivers/input/touchscreen/Makefile1
-rw-r--r--drivers/input/touchscreen/ad7877.c67
-rw-r--r--drivers/input/touchscreen/atmel-wm97xx.c436
-rw-r--r--drivers/input/touchscreen/auo-pixcir-ts.c6
-rw-r--r--drivers/input/touchscreen/colibri-vf50-ts.c2
-rw-r--r--drivers/input/touchscreen/da9052_tsi.c1
-rw-r--r--drivers/input/touchscreen/edt-ft5x06.c14
-rw-r--r--drivers/input/touchscreen/elants_i2c.c14
-rw-r--r--drivers/input/touchscreen/goodix.c149
-rw-r--r--drivers/input/touchscreen/hideep.c3
-rw-r--r--drivers/input/touchscreen/melfas_mip4.c1
-rw-r--r--drivers/input/touchscreen/mms114.c240
-rw-r--r--drivers/input/touchscreen/of_touchscreen.c4
-rw-r--r--drivers/input/touchscreen/raydium_i2c_ts.c14
-rw-r--r--drivers/input/touchscreen/s6sy761.c15
-rw-r--r--drivers/input/touchscreen/silead.c46
-rw-r--r--drivers/input/touchscreen/stmfts.c26
-rw-r--r--drivers/input/touchscreen/usbtouchscreen.c9
-rw-r--r--drivers/input/touchscreen/wdt87xx_i2c.c2
21 files changed, 323 insertions, 758 deletions
diff --git a/drivers/input/touchscreen/88pm860x-ts.c b/drivers/input/touchscreen/88pm860x-ts.c
index 7ed828a51f4c..3486d9403805 100644
--- a/drivers/input/touchscreen/88pm860x-ts.c
+++ b/drivers/input/touchscreen/88pm860x-ts.c
@@ -126,7 +126,7 @@ static int pm860x_touch_dt_init(struct platform_device *pdev,
int data, n, ret;
if (!np)
return -ENODEV;
- np = of_find_node_by_name(np, "touch");
+ np = of_get_child_by_name(np, "touch");
if (!np) {
dev_err(&pdev->dev, "Can't find touch node\n");
return -EINVAL;
@@ -144,13 +144,13 @@ static int pm860x_touch_dt_init(struct platform_device *pdev,
if (data) {
ret = pm860x_reg_write(i2c, PM8607_GPADC_MISC1, data);
if (ret < 0)
- return -EINVAL;
+ goto err_put_node;
}
/* set tsi prebias time */
if (!of_property_read_u32(np, "marvell,88pm860x-tsi-prebias", &data)) {
ret = pm860x_reg_write(i2c, PM8607_TSI_PREBIAS, data);
if (ret < 0)
- return -EINVAL;
+ goto err_put_node;
}
/* set prebias & prechg time of pen detect */
data = 0;
@@ -161,10 +161,18 @@ static int pm860x_touch_dt_init(struct platform_device *pdev,
if (data) {
ret = pm860x_reg_write(i2c, PM8607_PD_PREBIAS, data);
if (ret < 0)
- return -EINVAL;
+ goto err_put_node;
}
of_property_read_u32(np, "marvell,88pm860x-resistor-X", res_x);
+
+ of_node_put(np);
+
return 0;
+
+err_put_node:
+ of_node_put(np);
+
+ return -EINVAL;
}
#else
#define pm860x_touch_dt_init(x, y, z) (-1)
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 38a226f9fcbd..4f15496fec8b 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -795,21 +795,6 @@ config TOUCHSCREEN_WM9713
Say Y here to enable support for the Wolfson Microelectronics
WM9713 touchscreen controller.
-config TOUCHSCREEN_WM97XX_ATMEL
- tristate "WM97xx Atmel accelerated touch"
- depends on TOUCHSCREEN_WM97XX && AVR32
- help
- Say Y here for support for streaming mode with WM97xx touchscreens
- on Atmel AT91 or AVR32 systems with an AC97C module.
-
- Be aware that this will use channel B in the controller for
- streaming data, this must not conflict with other AC97C drivers.
-
- If unsure, say N.
-
- To compile this driver as a module, choose M here: the module will
- be called atmel-wm97xx.
-
config TOUCHSCREEN_WM97XX_MAINSTONE
tristate "WM97xx Mainstone/Palm accelerated touch"
depends on TOUCHSCREEN_WM97XX && ARCH_PXA
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index d2a2b3b7af27..dddae7973436 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -97,7 +97,6 @@ obj-$(CONFIG_TOUCHSCREEN_WM97XX) += wm97xx-ts.o
wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705) += wm9705.o
wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712) += wm9712.o
wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9713) += wm9713.o
-obj-$(CONFIG_TOUCHSCREEN_WM97XX_ATMEL) += atmel-wm97xx.o
obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o
obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o
obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o
diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c
index 0381c7809d1b..5cfe477ec992 100644
--- a/drivers/input/touchscreen/ad7877.c
+++ b/drivers/input/touchscreen/ad7877.c
@@ -417,8 +417,10 @@ out:
return IRQ_HANDLED;
}
-static void ad7877_disable(struct ad7877 *ts)
+static void ad7877_disable(void *data)
{
+ struct ad7877 *ts = data;
+
mutex_lock(&ts->mutex);
if (!ts->disabled) {
@@ -707,12 +709,17 @@ static int ad7877_probe(struct spi_device *spi)
return err;
}
- ts = kzalloc(sizeof(struct ad7877), GFP_KERNEL);
- input_dev = input_allocate_device();
- if (!ts || !input_dev) {
- err = -ENOMEM;
- goto err_free_mem;
- }
+ ts = devm_kzalloc(&spi->dev, sizeof(struct ad7877), GFP_KERNEL);
+ if (!ts)
+ return -ENOMEM;
+
+ input_dev = devm_input_allocate_device(&spi->dev);
+ if (!input_dev)
+ return -ENOMEM;
+
+ err = devm_add_action_or_reset(&spi->dev, ad7877_disable, ts);
+ if (err)
+ return err;
spi_set_drvdata(spi, ts);
ts->spi = spi;
@@ -761,11 +768,10 @@ static int ad7877_probe(struct spi_device *spi)
verify = ad7877_read(spi, AD7877_REG_SEQ1);
- if (verify != AD7877_MM_SEQUENCE){
+ if (verify != AD7877_MM_SEQUENCE) {
dev_err(&spi->dev, "%s: Failed to probe %s\n",
dev_name(&spi->dev), input_dev->name);
- err = -ENODEV;
- goto err_free_mem;
+ return -ENODEV;
}
if (gpio3)
@@ -775,47 +781,21 @@ static int ad7877_probe(struct spi_device *spi)
/* Request AD7877 /DAV GPIO interrupt */
- err = request_threaded_irq(spi->irq, NULL, ad7877_irq,
- IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
- spi->dev.driver->name, ts);
+ err = devm_request_threaded_irq(&spi->dev, spi->irq, NULL, ad7877_irq,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ spi->dev.driver->name, ts);
if (err) {
dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq);
- goto err_free_mem;
+ return err;
}
- err = sysfs_create_group(&spi->dev.kobj, &ad7877_attr_group);
+ err = devm_device_add_group(&spi->dev, &ad7877_attr_group);
if (err)
- goto err_free_irq;
+ return err;
err = input_register_device(input_dev);
if (err)
- goto err_remove_attr_group;
-
- return 0;
-
-err_remove_attr_group:
- sysfs_remove_group(&spi->dev.kobj, &ad7877_attr_group);
-err_free_irq:
- free_irq(spi->irq, ts);
-err_free_mem:
- input_free_device(input_dev);
- kfree(ts);
- return err;
-}
-
-static int ad7877_remove(struct spi_device *spi)
-{
- struct ad7877 *ts = spi_get_drvdata(spi);
-
- sysfs_remove_group(&spi->dev.kobj, &ad7877_attr_group);
-
- ad7877_disable(ts);
- free_irq(ts->spi->irq, ts);
-
- input_unregister_device(ts->input);
- kfree(ts);
-
- dev_dbg(&spi->dev, "unregistered touchscreen\n");
+ return err;
return 0;
}
@@ -846,7 +826,6 @@ static struct spi_driver ad7877_driver = {
.pm = &ad7877_pm,
},
.probe = ad7877_probe,
- .remove = ad7877_remove,
};
module_spi_driver(ad7877_driver);
diff --git a/drivers/input/touchscreen/atmel-wm97xx.c b/drivers/input/touchscreen/atmel-wm97xx.c
deleted file mode 100644
index 9140a43cfe20..000000000000
--- a/drivers/input/touchscreen/atmel-wm97xx.c
+++ /dev/null
@@ -1,436 +0,0 @@
-/*
- * Atmel AT91 and AVR32 continuous touch screen driver for Wolfson WM97xx AC97
- * codecs.
- *
- * Copyright (C) 2008 - 2009 Atmel Corporation
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- */
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/wm97xx.h>
-#include <linux/timer.h>
-#include <linux/gpio.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-#define AC97C_ICA 0x10
-#define AC97C_CBRHR 0x30
-#define AC97C_CBSR 0x38
-#define AC97C_CBMR 0x3c
-#define AC97C_IER 0x54
-#define AC97C_IDR 0x58
-
-#define AC97C_RXRDY (1 << 4)
-#define AC97C_OVRUN (1 << 5)
-
-#define AC97C_CMR_SIZE_20 (0 << 16)
-#define AC97C_CMR_SIZE_18 (1 << 16)
-#define AC97C_CMR_SIZE_16 (2 << 16)
-#define AC97C_CMR_SIZE_10 (3 << 16)
-#define AC97C_CMR_CEM_LITTLE (1 << 18)
-#define AC97C_CMR_CEM_BIG (0 << 18)
-#define AC97C_CMR_CENA (1 << 21)
-
-#define AC97C_INT_CBEVT (1 << 4)
-
-#define AC97C_SR_CAEVT (1 << 3)
-
-#define AC97C_CH_MASK(slot) \
- (0x7 << (3 * (slot - 3)))
-#define AC97C_CH_ASSIGN(slot, channel) \
- (AC97C_CHANNEL_##channel << (3 * (slot - 3)))
-#define AC97C_CHANNEL_NONE 0x0
-#define AC97C_CHANNEL_B 0x2
-
-#define ac97c_writel(chip, reg, val) \
- __raw_writel((val), (chip)->regs + AC97C_##reg)
-#define ac97c_readl(chip, reg) \
- __raw_readl((chip)->regs + AC97C_##reg)
-
-#ifdef CONFIG_CPU_AT32AP700X
-#define ATMEL_WM97XX_AC97C_IOMEM (0xfff02800)
-#define ATMEL_WM97XX_AC97C_IRQ (29)
-#define ATMEL_WM97XX_GPIO_DEFAULT (32+16) /* Pin 16 on port B. */
-#else
-#error Unknown CPU, this driver only supports AT32AP700X CPUs.
-#endif
-
-struct continuous {
- u16 id; /* codec id */
- u8 code; /* continuous code */
- u8 reads; /* number of coord reads per read cycle */
- u32 speed; /* number of coords per second */
-};
-
-#define WM_READS(sp) ((sp / HZ) + 1)
-
-static const struct continuous cinfo[] = {
- {WM9705_ID2, 0, WM_READS(94), 94},
- {WM9705_ID2, 1, WM_READS(188), 188},
- {WM9705_ID2, 2, WM_READS(375), 375},
- {WM9705_ID2, 3, WM_READS(750), 750},
- {WM9712_ID2, 0, WM_READS(94), 94},
- {WM9712_ID2, 1, WM_READS(188), 188},
- {WM9712_ID2, 2, WM_READS(375), 375},
- {WM9712_ID2, 3, WM_READS(750), 750},
- {WM9713_ID2, 0, WM_READS(94), 94},
- {WM9713_ID2, 1, WM_READS(120), 120},
- {WM9713_ID2, 2, WM_READS(154), 154},
- {WM9713_ID2, 3, WM_READS(188), 188},
-};
-
-/* Continuous speed index. */
-static int sp_idx;
-
-/*
- * Pen sampling frequency (Hz) in continuous mode.
- */
-static int cont_rate = 188;
-module_param(cont_rate, int, 0);
-MODULE_PARM_DESC(cont_rate, "Sampling rate in continuous mode (Hz)");
-
-/*
- * Pen down detection.
- *
- * This driver can either poll or use an interrupt to indicate a pen down
- * event. If the irq request fails then it will fall back to polling mode.
- */
-static int pen_int = 1;
-module_param(pen_int, int, 0);
-MODULE_PARM_DESC(pen_int, "Pen down detection (1 = interrupt, 0 = polling)");
-
-/*
- * Pressure readback.
- *
- * Set to 1 to read back pen down pressure.
- */
-static int pressure;
-module_param(pressure, int, 0);
-MODULE_PARM_DESC(pressure, "Pressure readback (1 = pressure, 0 = no pressure)");
-
-/*
- * AC97 touch data slot.
- *
- * Touch screen readback data ac97 slot.
- */
-static int ac97_touch_slot = 5;
-module_param(ac97_touch_slot, int, 0);
-MODULE_PARM_DESC(ac97_touch_slot, "Touch screen data slot AC97 number");
-
-/*
- * GPIO line number.
- *
- * Set to GPIO number where the signal from the WM97xx device is hooked up.
- */
-static int atmel_gpio_line = ATMEL_WM97XX_GPIO_DEFAULT;
-module_param(atmel_gpio_line, int, 0);
-MODULE_PARM_DESC(atmel_gpio_line, "GPIO line number connected to WM97xx");
-
-struct atmel_wm97xx {
- struct wm97xx *wm;
- struct timer_list pen_timer;
- void __iomem *regs;
- unsigned long ac97c_irq;
- unsigned long gpio_pen;
- unsigned long gpio_irq;
- unsigned short x;
- unsigned short y;
-};
-
-static irqreturn_t atmel_wm97xx_channel_b_interrupt(int irq, void *dev_id)
-{
- struct atmel_wm97xx *atmel_wm97xx = dev_id;
- struct wm97xx *wm = atmel_wm97xx->wm;
- int status = ac97c_readl(atmel_wm97xx, CBSR);
- irqreturn_t retval = IRQ_NONE;
-
- if (status & AC97C_OVRUN) {
- dev_dbg(&wm->touch_dev->dev, "AC97C overrun\n");
- ac97c_readl(atmel_wm97xx, CBRHR);
- retval = IRQ_HANDLED;
- } else if (status & AC97C_RXRDY) {
- u16 data;
- u16 value;
- u16 source;
- u16 pen_down;
-
- data = ac97c_readl(atmel_wm97xx, CBRHR);
- value = data & 0x0fff;
- source = data & WM97XX_ADCSEL_MASK;
- pen_down = (data & WM97XX_PEN_DOWN) >> 8;
-
- if (source == WM97XX_ADCSEL_X)
- atmel_wm97xx->x = value;
- if (source == WM97XX_ADCSEL_Y)
- atmel_wm97xx->y = value;
-
- if (!pressure && source == WM97XX_ADCSEL_Y) {
- input_report_abs(wm->input_dev, ABS_X, atmel_wm97xx->x);
- input_report_abs(wm->input_dev, ABS_Y, atmel_wm97xx->y);
- input_report_key(wm->input_dev, BTN_TOUCH, pen_down);
- input_sync(wm->input_dev);
- } else if (pressure && source == WM97XX_ADCSEL_PRES) {
- input_report_abs(wm->input_dev, ABS_X, atmel_wm97xx->x);
- input_report_abs(wm->input_dev, ABS_Y, atmel_wm97xx->y);
- input_report_abs(wm->input_dev, ABS_PRESSURE, value);
- input_report_key(wm->input_dev, BTN_TOUCH, value);
- input_sync(wm->input_dev);
- }
-
- retval = IRQ_HANDLED;
- }
-
- return retval;
-}
-
-static void atmel_wm97xx_acc_pen_up(struct wm97xx *wm)
-{
- struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(wm->touch_dev);
- struct input_dev *input_dev = wm->input_dev;
- int pen_down = gpio_get_value(atmel_wm97xx->gpio_pen);
-
- if (pen_down != 0) {
- mod_timer(&atmel_wm97xx->pen_timer,
- jiffies + msecs_to_jiffies(1));
- } else {
- if (pressure)
- input_report_abs(input_dev, ABS_PRESSURE, 0);
- input_report_key(input_dev, BTN_TOUCH, 0);
- input_sync(input_dev);
- }
-}
-
-static void atmel_wm97xx_pen_timer(struct timer_list *t)
-{
- struct atmel_wm97xx *atmel_wm97xx = from_timer(atmel_wm97xx, t,
- pen_timer);
-
- atmel_wm97xx_acc_pen_up(atmel_wm97xx->wm);
-}
-
-static int atmel_wm97xx_acc_startup(struct wm97xx *wm)
-{
- struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(wm->touch_dev);
- int idx = 0;
-
- if (wm->ac97 == NULL)
- return -ENODEV;
-
- for (idx = 0; idx < ARRAY_SIZE(cinfo); idx++) {
- if (wm->id != cinfo[idx].id)
- continue;
-
- sp_idx = idx;
-
- if (cont_rate <= cinfo[idx].speed)
- break;
- }
-
- wm->acc_rate = cinfo[sp_idx].code;
- wm->acc_slot = ac97_touch_slot;
- dev_info(&wm->touch_dev->dev, "atmel accelerated touchscreen driver, "
- "%d samples/sec\n", cinfo[sp_idx].speed);
-
- if (pen_int) {
- unsigned long reg;
-
- wm->pen_irq = atmel_wm97xx->gpio_irq;
-
- switch (wm->id) {
- case WM9712_ID2: /* Fall through. */
- case WM9713_ID2:
- /*
- * Use GPIO 13 (PEN_DOWN) to assert GPIO line 3
- * (PENDOWN).
- */
- wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN,
- WM97XX_GPIO_POL_HIGH,
- WM97XX_GPIO_STICKY,
- WM97XX_GPIO_WAKE);
- wm97xx_config_gpio(wm, WM97XX_GPIO_3, WM97XX_GPIO_OUT,
- WM97XX_GPIO_POL_HIGH,
- WM97XX_GPIO_NOTSTICKY,
- WM97XX_GPIO_NOWAKE);
- case WM9705_ID2: /* Fall through. */
- /*
- * Enable touch data slot in AC97 controller channel B.
- */
- reg = ac97c_readl(atmel_wm97xx, ICA);
- reg &= ~AC97C_CH_MASK(wm->acc_slot);
- reg |= AC97C_CH_ASSIGN(wm->acc_slot, B);
- ac97c_writel(atmel_wm97xx, ICA, reg);
-
- /*
- * Enable channel and interrupt for RXRDY and OVERRUN.
- */
- ac97c_writel(atmel_wm97xx, CBMR, AC97C_CMR_CENA
- | AC97C_CMR_CEM_BIG
- | AC97C_CMR_SIZE_16
- | AC97C_OVRUN
- | AC97C_RXRDY);
- /* Dummy read to empty RXRHR. */
- ac97c_readl(atmel_wm97xx, CBRHR);
- /*
- * Enable interrupt for channel B in the AC97
- * controller.
- */
- ac97c_writel(atmel_wm97xx, IER, AC97C_INT_CBEVT);
- break;
- default:
- dev_err(&wm->touch_dev->dev, "pen down irq not "
- "supported on this device\n");
- pen_int = 0;
- break;
- }
- }
-
- return 0;
-}
-
-static void atmel_wm97xx_acc_shutdown(struct wm97xx *wm)
-{
- if (pen_int) {
- struct atmel_wm97xx *atmel_wm97xx =
- platform_get_drvdata(wm->touch_dev);
- unsigned long ica;
-
- switch (wm->id & 0xffff) {
- case WM9705_ID2: /* Fall through. */
- case WM9712_ID2: /* Fall through. */
- case WM9713_ID2:
- /* Disable slot and turn off channel B interrupts. */
- ica = ac97c_readl(atmel_wm97xx, ICA);
- ica &= ~AC97C_CH_MASK(wm->acc_slot);
- ac97c_writel(atmel_wm97xx, ICA, ica);
- ac97c_writel(atmel_wm97xx, IDR, AC97C_INT_CBEVT);
- ac97c_writel(atmel_wm97xx, CBMR, 0);
- wm->pen_irq = 0;
- break;
- default:
- dev_err(&wm->touch_dev->dev, "unknown codec\n");
- break;
- }
- }
-}
-
-static void atmel_wm97xx_irq_enable(struct wm97xx *wm, int enable)
-{
- /* Intentionally left empty. */
-}
-
-static struct wm97xx_mach_ops atmel_mach_ops = {
- .acc_enabled = 1,
- .acc_pen_up = atmel_wm97xx_acc_pen_up,
- .acc_startup = atmel_wm97xx_acc_startup,
- .acc_shutdown = atmel_wm97xx_acc_shutdown,
- .irq_enable = atmel_wm97xx_irq_enable,
- .irq_gpio = WM97XX_GPIO_3,
-};
-
-static int __init atmel_wm97xx_probe(struct platform_device *pdev)
-{
- struct wm97xx *wm = platform_get_drvdata(pdev);
- struct atmel_wm97xx *atmel_wm97xx;
- int ret;
-
- atmel_wm97xx = kzalloc(sizeof(struct atmel_wm97xx), GFP_KERNEL);
- if (!atmel_wm97xx)
- return -ENOMEM;
-
- atmel_wm97xx->wm = wm;
- atmel_wm97xx->regs = (void *)ATMEL_WM97XX_AC97C_IOMEM;
- atmel_wm97xx->ac97c_irq = ATMEL_WM97XX_AC97C_IRQ;
- atmel_wm97xx->gpio_pen = atmel_gpio_line;
- atmel_wm97xx->gpio_irq = gpio_to_irq(atmel_wm97xx->gpio_pen);
-
- timer_setup(&atmel_wm97xx->pen_timer, atmel_wm97xx_pen_timer, 0);
-
- ret = request_irq(atmel_wm97xx->ac97c_irq,
- atmel_wm97xx_channel_b_interrupt,
- IRQF_SHARED, "atmel-wm97xx-ch-b", atmel_wm97xx);
- if (ret) {
- dev_dbg(&pdev->dev, "could not request ac97c irq\n");
- goto err;
- }
-
- platform_set_drvdata(pdev, atmel_wm97xx);
-
- ret = wm97xx_register_mach_ops(wm, &atmel_mach_ops);
- if (ret)
- goto err_irq;
-
- return ret;
-
-err_irq:
- free_irq(atmel_wm97xx->ac97c_irq, atmel_wm97xx);
-err:
- kfree(atmel_wm97xx);
- return ret;
-}
-
-static int __exit atmel_wm97xx_remove(struct platform_device *pdev)
-{
- struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(pdev);
- struct wm97xx *wm = atmel_wm97xx->wm;
-
- ac97c_writel(atmel_wm97xx, IDR, AC97C_INT_CBEVT);
- free_irq(atmel_wm97xx->ac97c_irq, atmel_wm97xx);
- del_timer_sync(&atmel_wm97xx->pen_timer);
- wm97xx_unregister_mach_ops(wm);
- kfree(atmel_wm97xx);
-
- return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int atmel_wm97xx_suspend(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(pdev);
-
- ac97c_writel(atmel_wm97xx, IDR, AC97C_INT_CBEVT);
- disable_irq(atmel_wm97xx->gpio_irq);
- del_timer_sync(&atmel_wm97xx->pen_timer);
-
- return 0;
-}
-
-static int atmel_wm97xx_resume(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(pdev);
- struct wm97xx *wm = atmel_wm97xx->wm;
-
- if (wm->input_dev->users) {
- enable_irq(atmel_wm97xx->gpio_irq);
- ac97c_writel(atmel_wm97xx, IER, AC97C_INT_CBEVT);
- }
-
- return 0;
-}
-#endif
-
-static SIMPLE_DEV_PM_OPS(atmel_wm97xx_pm_ops,
- atmel_wm97xx_suspend, atmel_wm97xx_resume);
-
-static struct platform_driver atmel_wm97xx_driver = {
- .remove = __exit_p(atmel_wm97xx_remove),
- .driver = {
- .name = "wm97xx-touch",
- .pm = &atmel_wm97xx_pm_ops,
- },
-};
-
-module_platform_driver_probe(atmel_wm97xx_driver, atmel_wm97xx_probe);
-
-MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>");
-MODULE_DESCRIPTION("wm97xx continuous touch driver for Atmel AT91 and AVR32");
-MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/auo-pixcir-ts.c b/drivers/input/touchscreen/auo-pixcir-ts.c
index 6592fc5d48b4..df8ca856393b 100644
--- a/drivers/input/touchscreen/auo-pixcir-ts.c
+++ b/drivers/input/touchscreen/auo-pixcir-ts.c
@@ -408,8 +408,6 @@ static void auo_pixcir_input_close(struct input_dev *dev)
struct auo_pixcir_ts *ts = input_get_drvdata(dev);
auo_pixcir_stop(ts);
-
- return;
}
static int __maybe_unused auo_pixcir_suspend(struct device *dev)
@@ -487,10 +485,8 @@ static struct auo_pixcir_ts_platdata *auo_pixcir_parse_dt(struct device *dev)
return ERR_PTR(-ENOENT);
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
- if (!pdata) {
- dev_err(dev, "failed to allocate platform data\n");
+ if (!pdata)
return ERR_PTR(-ENOMEM);
- }
pdata->gpio_int = of_get_gpio(np, 0);
if (!gpio_is_valid(pdata->gpio_int)) {
diff --git a/drivers/input/touchscreen/colibri-vf50-ts.c b/drivers/input/touchscreen/colibri-vf50-ts.c
index 69c08acae264..82ca5ab65cec 100644
--- a/drivers/input/touchscreen/colibri-vf50-ts.c
+++ b/drivers/input/touchscreen/colibri-vf50-ts.c
@@ -28,7 +28,6 @@
#include <linux/types.h>
#define DRIVER_NAME "colibri-vf50-ts"
-#define DRV_VERSION "1.0"
#define VF_ADC_MAX ((1 << 12) - 1)
@@ -382,4 +381,3 @@ module_platform_driver(vf50_touch_driver);
MODULE_AUTHOR("Sanchayan Maity");
MODULE_DESCRIPTION("Colibri VF50 Touchscreen driver");
MODULE_LICENSE("GPL");
-MODULE_VERSION(DRV_VERSION);
diff --git a/drivers/input/touchscreen/da9052_tsi.c b/drivers/input/touchscreen/da9052_tsi.c
index 5a013bb7bcad..b5dfd5944cc3 100644
--- a/drivers/input/touchscreen/da9052_tsi.c
+++ b/drivers/input/touchscreen/da9052_tsi.c
@@ -26,7 +26,6 @@ struct da9052_tsi {
struct da9052 *da9052;
struct input_dev *dev;
struct delayed_work ts_pen_work;
- struct mutex mutex;
bool stopped;
bool adc_on;
};
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
index c53a3d7239e7..1e18ca0d1b4e 100644
--- a/drivers/input/touchscreen/edt-ft5x06.c
+++ b/drivers/input/touchscreen/edt-ft5x06.c
@@ -511,6 +511,12 @@ static int edt_ft5x06_factory_mode(struct edt_ft5x06_ts_data *tsdata)
int ret;
int error;
+ if (tsdata->version != EDT_M06) {
+ dev_err(&client->dev,
+ "No factory mode support for non-M06 devices\n");
+ return -EINVAL;
+ }
+
disable_irq(client->irq);
if (!tsdata->raw_buffer) {
@@ -524,9 +530,6 @@ static int edt_ft5x06_factory_mode(struct edt_ft5x06_ts_data *tsdata)
}
/* mode register is 0x3c when in the work mode */
- if (tsdata->version != EDT_M06)
- goto m09_out;
-
error = edt_ft5x06_register_write(tsdata, WORK_REGISTER_OPMODE, 0x03);
if (error) {
dev_err(&client->dev,
@@ -559,11 +562,6 @@ err_out:
enable_irq(client->irq);
return error;
-
-m09_out:
- dev_err(&client->dev, "No factory mode support for M09/M12/GENERIC_FT\n");
- return -EINVAL;
-
}
static int edt_ft5x06_work_mode(struct edt_ft5x06_ts_data *tsdata)
diff --git a/drivers/input/touchscreen/elants_i2c.c b/drivers/input/touchscreen/elants_i2c.c
index e102d7764bc2..d21ca39b0fdb 100644
--- a/drivers/input/touchscreen/elants_i2c.c
+++ b/drivers/input/touchscreen/elants_i2c.c
@@ -27,6 +27,7 @@
#include <linux/module.h>
#include <linux/input.h>
#include <linux/interrupt.h>
+#include <linux/irq.h>
#include <linux/platform_device.h>
#include <linux/async.h>
#include <linux/i2c.h>
@@ -44,7 +45,6 @@
/* Device, Driver information */
#define DEVICE_NAME "elants_i2c"
-#define DRV_VERSION "1.0.9"
/* Convert from rows or columns into resolution */
#define ELAN_TS_RESOLUTION(n, m) (((n) - 1) * (m))
@@ -999,7 +999,7 @@ static ssize_t show_iap_mode(struct device *dev,
"Normal" : "Recovery");
}
-static DEVICE_ATTR(calibrate, S_IWUSR, NULL, calibrate_store);
+static DEVICE_ATTR_WO(calibrate);
static DEVICE_ATTR(iap_mode, S_IRUGO, show_iap_mode, NULL);
static DEVICE_ATTR(update_fw, S_IWUSR, NULL, write_update_fw);
@@ -1261,10 +1261,13 @@ static int elants_i2c_probe(struct i2c_client *client,
}
/*
- * Systems using device tree should set up interrupt via DTS,
- * the rest will use the default falling edge interrupts.
+ * Platform code (ACPI, DTS) should normally set up interrupt
+ * for us, but in case it did not let's fall back to using falling
+ * edge to be compatible with older Chromebooks.
*/
- irqflags = client->dev.of_node ? 0 : IRQF_TRIGGER_FALLING;
+ irqflags = irq_get_trigger_type(client->irq);
+ if (!irqflags)
+ irqflags = IRQF_TRIGGER_FALLING;
error = devm_request_threaded_irq(&client->dev, client->irq,
NULL, elants_i2c_irq,
@@ -1402,5 +1405,4 @@ module_i2c_driver(elants_i2c_driver);
MODULE_AUTHOR("Scott Liu <scott.liu@emc.com.tw>");
MODULE_DESCRIPTION("Elan I2c Touchscreen driver");
-MODULE_VERSION(DRV_VERSION);
MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c
index 69d0b8cbc71f..9736c83dd418 100644
--- a/drivers/input/touchscreen/goodix.c
+++ b/drivers/input/touchscreen/goodix.c
@@ -22,6 +22,7 @@
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/input/mt.h>
+#include <linux/input/touchscreen.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/irq.h>
@@ -43,11 +44,7 @@ struct goodix_ts_data {
struct i2c_client *client;
struct input_dev *input_dev;
const struct goodix_chip_data *chip;
- int abs_x_max;
- int abs_y_max;
- bool swapped_x_y;
- bool inverted_x;
- bool inverted_y;
+ struct touchscreen_properties prop;
unsigned int max_touch_num;
unsigned int int_trigger_type;
struct gpio_desc *gpiod_int;
@@ -160,7 +157,7 @@ static int goodix_i2c_read(struct i2c_client *client,
u16 reg, u8 *buf, int len)
{
struct i2c_msg msgs[2];
- u16 wbuf = cpu_to_be16(reg);
+ __be16 wbuf = cpu_to_be16(reg);
int ret;
msgs[0].flags = 0;
@@ -295,18 +292,10 @@ static void goodix_ts_report_touch(struct goodix_ts_data *ts, u8 *coor_data)
int input_y = get_unaligned_le16(&coor_data[3]);
int input_w = get_unaligned_le16(&coor_data[5]);
- /* Inversions have to happen before axis swapping */
- if (ts->inverted_x)
- input_x = ts->abs_x_max - input_x;
- if (ts->inverted_y)
- input_y = ts->abs_y_max - input_y;
- if (ts->swapped_x_y)
- swap(input_x, input_y);
-
input_mt_slot(ts->input_dev, id);
input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, true);
- input_report_abs(ts->input_dev, ABS_MT_POSITION_X, input_x);
- input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, input_y);
+ touchscreen_report_pos(ts->input_dev, &ts->prop,
+ input_x, input_y, true);
input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, input_w);
input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, input_w);
}
@@ -579,44 +568,27 @@ static int goodix_get_gpio_config(struct goodix_ts_data *ts)
static void goodix_read_config(struct goodix_ts_data *ts)
{
u8 config[GOODIX_CONFIG_MAX_LENGTH];
+ int x_max, y_max;
int error;
error = goodix_i2c_read(ts->client, ts->chip->config_addr,
config, ts->chip->config_len);
if (error) {
- dev_warn(&ts->client->dev,
- "Error reading config (%d), using defaults\n",
+ dev_warn(&ts->client->dev, "Error reading config: %d\n",
error);
- ts->abs_x_max = GOODIX_MAX_WIDTH;
- ts->abs_y_max = GOODIX_MAX_HEIGHT;
- if (ts->swapped_x_y)
- swap(ts->abs_x_max, ts->abs_y_max);
ts->int_trigger_type = GOODIX_INT_TRIGGER;
ts->max_touch_num = GOODIX_MAX_CONTACTS;
return;
}
- ts->abs_x_max = get_unaligned_le16(&config[RESOLUTION_LOC]);
- ts->abs_y_max = get_unaligned_le16(&config[RESOLUTION_LOC + 2]);
- if (ts->swapped_x_y)
- swap(ts->abs_x_max, ts->abs_y_max);
ts->int_trigger_type = config[TRIGGER_LOC] & 0x03;
ts->max_touch_num = config[MAX_CONTACTS_LOC] & 0x0f;
- if (!ts->abs_x_max || !ts->abs_y_max || !ts->max_touch_num) {
- dev_err(&ts->client->dev,
- "Invalid config, using defaults\n");
- ts->abs_x_max = GOODIX_MAX_WIDTH;
- ts->abs_y_max = GOODIX_MAX_HEIGHT;
- if (ts->swapped_x_y)
- swap(ts->abs_x_max, ts->abs_y_max);
- ts->max_touch_num = GOODIX_MAX_CONTACTS;
- }
- if (dmi_check_system(rotated_screen)) {
- ts->inverted_x = true;
- ts->inverted_y = true;
- dev_dbg(&ts->client->dev,
- "Applying '180 degrees rotated screen' quirk\n");
+ x_max = get_unaligned_le16(&config[RESOLUTION_LOC]);
+ y_max = get_unaligned_le16(&config[RESOLUTION_LOC + 2]);
+ if (x_max && y_max) {
+ input_abs_set_max(ts->input_dev, ABS_MT_POSITION_X, x_max - 1);
+ input_abs_set_max(ts->input_dev, ABS_MT_POSITION_Y, y_max - 1);
}
}
@@ -676,32 +648,28 @@ static int goodix_i2c_test(struct i2c_client *client)
}
/**
- * goodix_request_input_dev - Allocate, populate and register the input device
+ * goodix_configure_dev - Finish device initialization
*
* @ts: our goodix_ts_data pointer
*
- * Must be called during probe
+ * Must be called from probe to finish initialization of the device.
+ * Contains the common initialization code for both devices that
+ * declare gpio pins and devices that do not. It is either called
+ * directly from probe or from request_firmware_wait callback.
*/
-static int goodix_request_input_dev(struct goodix_ts_data *ts)
+static int goodix_configure_dev(struct goodix_ts_data *ts)
{
int error;
+ ts->int_trigger_type = GOODIX_INT_TRIGGER;
+ ts->max_touch_num = GOODIX_MAX_CONTACTS;
+
ts->input_dev = devm_input_allocate_device(&ts->client->dev);
if (!ts->input_dev) {
dev_err(&ts->client->dev, "Failed to allocate input device.");
return -ENOMEM;
}
- input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X,
- 0, ts->abs_x_max, 0, 0);
- input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y,
- 0, ts->abs_y_max, 0, 0);
- input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0);
- input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
-
- input_mt_init_slots(ts->input_dev, ts->max_touch_num,
- INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
-
ts->input_dev->name = "Goodix Capacitive TouchScreen";
ts->input_dev->phys = "input/ts";
ts->input_dev->id.bustype = BUS_I2C;
@@ -712,42 +680,49 @@ static int goodix_request_input_dev(struct goodix_ts_data *ts)
/* Capacitive Windows/Home button on some devices */
input_set_capability(ts->input_dev, EV_KEY, KEY_LEFTMETA);
- error = input_register_device(ts->input_dev);
- if (error) {
- dev_err(&ts->client->dev,
- "Failed to register input device: %d", error);
- return error;
- }
+ input_set_capability(ts->input_dev, EV_ABS, ABS_MT_POSITION_X);
+ input_set_capability(ts->input_dev, EV_ABS, ABS_MT_POSITION_Y);
+ input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0);
+ input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
- return 0;
-}
+ /* Read configuration and apply touchscreen parameters */
+ goodix_read_config(ts);
-/**
- * goodix_configure_dev - Finish device initialization
- *
- * @ts: our goodix_ts_data pointer
- *
- * Must be called from probe to finish initialization of the device.
- * Contains the common initialization code for both devices that
- * declare gpio pins and devices that do not. It is either called
- * directly from probe or from request_firmware_wait callback.
- */
-static int goodix_configure_dev(struct goodix_ts_data *ts)
-{
- int error;
+ /* Try overriding touchscreen parameters via device properties */
+ touchscreen_parse_properties(ts->input_dev, true, &ts->prop);
- ts->swapped_x_y = device_property_read_bool(&ts->client->dev,
- "touchscreen-swapped-x-y");
- ts->inverted_x = device_property_read_bool(&ts->client->dev,
- "touchscreen-inverted-x");
- ts->inverted_y = device_property_read_bool(&ts->client->dev,
- "touchscreen-inverted-y");
+ if (!ts->prop.max_x || !ts->prop.max_y || !ts->max_touch_num) {
+ dev_err(&ts->client->dev, "Invalid config, using defaults\n");
+ ts->prop.max_x = GOODIX_MAX_WIDTH - 1;
+ ts->prop.max_y = GOODIX_MAX_HEIGHT - 1;
+ ts->max_touch_num = GOODIX_MAX_CONTACTS;
+ input_abs_set_max(ts->input_dev,
+ ABS_MT_POSITION_X, ts->prop.max_x);
+ input_abs_set_max(ts->input_dev,
+ ABS_MT_POSITION_Y, ts->prop.max_y);
+ }
- goodix_read_config(ts);
+ if (dmi_check_system(rotated_screen)) {
+ ts->prop.invert_x = true;
+ ts->prop.invert_y = true;
+ dev_dbg(&ts->client->dev,
+ "Applying '180 degrees rotated screen' quirk\n");
+ }
- error = goodix_request_input_dev(ts);
- if (error)
+ error = input_mt_init_slots(ts->input_dev, ts->max_touch_num,
+ INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
+ if (error) {
+ dev_err(&ts->client->dev,
+ "Failed to initialize MT slots: %d", error);
return error;
+ }
+
+ error = input_register_device(ts->input_dev);
+ if (error) {
+ dev_err(&ts->client->dev,
+ "Failed to register input device: %d", error);
+ return error;
+ }
ts->irq_flags = goodix_irq_flags[ts->int_trigger_type] | IRQF_ONESHOT;
error = goodix_request_irq(ts);
@@ -878,8 +853,10 @@ static int __maybe_unused goodix_suspend(struct device *dev)
int error;
/* We need gpio pins to suspend/resume */
- if (!ts->gpiod_int || !ts->gpiod_rst)
+ if (!ts->gpiod_int || !ts->gpiod_rst) {
+ disable_irq(client->irq);
return 0;
+ }
wait_for_completion(&ts->firmware_loading_complete);
@@ -919,8 +896,10 @@ static int __maybe_unused goodix_resume(struct device *dev)
struct goodix_ts_data *ts = i2c_get_clientdata(client);
int error;
- if (!ts->gpiod_int || !ts->gpiod_rst)
+ if (!ts->gpiod_int || !ts->gpiod_rst) {
+ enable_irq(client->irq);
return 0;
+ }
/*
* Exit sleep mode by outputting HIGH level to INT pin
diff --git a/drivers/input/touchscreen/hideep.c b/drivers/input/touchscreen/hideep.c
index fc080a7c2e1f..f1cd4dd9a4a3 100644
--- a/drivers/input/touchscreen/hideep.c
+++ b/drivers/input/touchscreen/hideep.c
@@ -10,8 +10,7 @@
#include <linux/of.h>
#include <linux/firmware.h>
#include <linux/delay.h>
-#include <linux/gpio.h>
-#include <linux/gpio/machine.h>
+#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/acpi.h>
#include <linux/interrupt.h>
diff --git a/drivers/input/touchscreen/melfas_mip4.c b/drivers/input/touchscreen/melfas_mip4.c
index 6892f0e28918..430a2bc5f7ca 100644
--- a/drivers/input/touchscreen/melfas_mip4.c
+++ b/drivers/input/touchscreen/melfas_mip4.c
@@ -1611,6 +1611,5 @@ static struct i2c_driver mip4_driver = {
module_i2c_driver(mip4_driver);
MODULE_DESCRIPTION("MELFAS MIP4 Touchscreen");
-MODULE_VERSION("2016.10.31");
MODULE_AUTHOR("Sangwon Jee <jeesw@melfas.com>");
MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c
index e5eeb6311f7d..db4f6bb502e3 100644
--- a/drivers/input/touchscreen/mms114.c
+++ b/drivers/input/touchscreen/mms114.c
@@ -10,17 +10,18 @@
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/i2c.h>
#include <linux/input/mt.h>
+#include <linux/input/touchscreen.h>
#include <linux/interrupt.h>
-#include <linux/platform_data/mms114.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
/* Write only registers */
#define MMS114_MODE_CONTROL 0x01
#define MMS114_OPERATION_MODE_MASK 0xE
-#define MMS114_ACTIVE (1 << 1)
+#define MMS114_ACTIVE BIT(1)
#define MMS114_XY_RESOLUTION_H 0x02
#define MMS114_X_RESOLUTION 0x03
@@ -30,9 +31,12 @@
/* Read only registers */
#define MMS114_PACKET_SIZE 0x0F
-#define MMS114_INFOMATION 0x10
+#define MMS114_INFORMATION 0x10
#define MMS114_TSP_REV 0xF0
+#define MMS152_FW_REV 0xE1
+#define MMS152_COMPAT_GROUP 0xF2
+
/* Minimum delay time is 50us between stop and start signal of i2c */
#define MMS114_I2C_DELAY 50
@@ -50,12 +54,20 @@
#define MMS114_TYPE_TOUCHSCREEN 1
#define MMS114_TYPE_TOUCHKEY 2
+enum mms_type {
+ TYPE_MMS114 = 114,
+ TYPE_MMS152 = 152,
+};
+
struct mms114_data {
struct i2c_client *client;
struct input_dev *input_dev;
struct regulator *core_reg;
struct regulator *io_reg;
- const struct mms114_platform_data *pdata;
+ struct touchscreen_properties props;
+ enum mms_type type;
+ unsigned int contact_threshold;
+ unsigned int moving_threshold;
/* Use cache data for mode control register(write only) */
u8 cache_mode_control;
@@ -143,7 +155,6 @@ static int mms114_write_reg(struct mms114_data *data, unsigned int reg,
static void mms114_process_mt(struct mms114_data *data, struct mms114_touch *touch)
{
- const struct mms114_platform_data *pdata = data->pdata;
struct i2c_client *client = data->client;
struct input_dev *input_dev = data->input_dev;
unsigned int id;
@@ -163,16 +174,6 @@ static void mms114_process_mt(struct mms114_data *data, struct mms114_touch *tou
id = touch->id - 1;
x = touch->x_lo | touch->x_hi << 8;
y = touch->y_lo | touch->y_hi << 8;
- if (x > pdata->x_size || y > pdata->y_size) {
- dev_dbg(&client->dev,
- "Wrong touch coordinates (%d, %d)\n", x, y);
- return;
- }
-
- if (pdata->x_invert)
- x = pdata->x_size - x;
- if (pdata->y_invert)
- y = pdata->y_size - y;
dev_dbg(&client->dev,
"id: %d, type: %d, pressed: %d, x: %d, y: %d, width: %d, strength: %d\n",
@@ -183,9 +184,8 @@ static void mms114_process_mt(struct mms114_data *data, struct mms114_touch *tou
input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, touch->pressed);
if (touch->pressed) {
+ touchscreen_report_pos(input_dev, &data->props, x, y, true);
input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, touch->width);
- input_report_abs(input_dev, ABS_MT_POSITION_X, x);
- input_report_abs(input_dev, ABS_MT_POSITION_Y, y);
input_report_abs(input_dev, ABS_MT_PRESSURE, touch->strength);
}
}
@@ -213,7 +213,7 @@ static irqreturn_t mms114_interrupt(int irq, void *dev_id)
touch_size = packet_size / MMS114_PACKET_NUM;
- error = __mms114_read_reg(data, MMS114_INFOMATION, packet_size,
+ error = __mms114_read_reg(data, MMS114_INFORMATION, packet_size,
(u8 *)touch);
if (error < 0)
goto out;
@@ -249,21 +249,40 @@ static int mms114_get_version(struct mms114_data *data)
{
struct device *dev = &data->client->dev;
u8 buf[6];
+ int group;
int error;
- error = __mms114_read_reg(data, MMS114_TSP_REV, 6, buf);
- if (error < 0)
- return error;
+ switch (data->type) {
+ case TYPE_MMS152:
+ error = __mms114_read_reg(data, MMS152_FW_REV, 3, buf);
+ if (error)
+ return error;
+
+ group = i2c_smbus_read_byte_data(data->client,
+ MMS152_COMPAT_GROUP);
+ if (group < 0)
+ return group;
+
+ dev_info(dev, "TSP FW Rev: bootloader 0x%x / core 0x%x / config 0x%x, Compat group: %c\n",
+ buf[0], buf[1], buf[2], group);
+ break;
+
+ case TYPE_MMS114:
+ error = __mms114_read_reg(data, MMS114_TSP_REV, 6, buf);
+ if (error)
+ return error;
- dev_info(dev, "TSP Rev: 0x%x, HW Rev: 0x%x, Firmware Ver: 0x%x\n",
- buf[0], buf[1], buf[3]);
+ dev_info(dev, "TSP Rev: 0x%x, HW Rev: 0x%x, Firmware Ver: 0x%x\n",
+ buf[0], buf[1], buf[3]);
+ break;
+ }
return 0;
}
static int mms114_setup_regs(struct mms114_data *data)
{
- const struct mms114_platform_data *pdata = data->pdata;
+ const struct touchscreen_properties *props = &data->props;
int val;
int error;
@@ -271,36 +290,40 @@ static int mms114_setup_regs(struct mms114_data *data)
if (error < 0)
return error;
+ /* MMS152 has no configuration or power on registers */
+ if (data->type == TYPE_MMS152)
+ return 0;
+
error = mms114_set_active(data, true);
if (error < 0)
return error;
- val = (pdata->x_size >> 8) & 0xf;
- val |= ((pdata->y_size >> 8) & 0xf) << 4;
+ val = (props->max_x >> 8) & 0xf;
+ val |= ((props->max_y >> 8) & 0xf) << 4;
error = mms114_write_reg(data, MMS114_XY_RESOLUTION_H, val);
if (error < 0)
return error;
- val = pdata->x_size & 0xff;
+ val = props->max_x & 0xff;
error = mms114_write_reg(data, MMS114_X_RESOLUTION, val);
if (error < 0)
return error;
- val = pdata->y_size & 0xff;
+ val = props->max_x & 0xff;
error = mms114_write_reg(data, MMS114_Y_RESOLUTION, val);
if (error < 0)
return error;
- if (pdata->contact_threshold) {
+ if (data->contact_threshold) {
error = mms114_write_reg(data, MMS114_CONTACT_THRESHOLD,
- pdata->contact_threshold);
+ data->contact_threshold);
if (error < 0)
return error;
}
- if (pdata->moving_threshold) {
+ if (data->moving_threshold) {
error = mms114_write_reg(data, MMS114_MOVING_THRESHOLD,
- pdata->moving_threshold);
+ data->moving_threshold);
if (error < 0)
return error;
}
@@ -326,7 +349,7 @@ static int mms114_start(struct mms114_data *data)
return error;
}
- mdelay(MMS114_POWERON_DELAY);
+ msleep(MMS114_POWERON_DELAY);
error = mms114_setup_regs(data);
if (error < 0) {
@@ -335,9 +358,6 @@ static int mms114_start(struct mms114_data *data)
return error;
}
- if (data->pdata->cfg_pin)
- data->pdata->cfg_pin(true);
-
enable_irq(client->irq);
return 0;
@@ -350,9 +370,6 @@ static void mms114_stop(struct mms114_data *data)
disable_irq(client->irq);
- if (data->pdata->cfg_pin)
- data->pdata->cfg_pin(false);
-
error = regulator_disable(data->io_reg);
if (error)
dev_warn(&client->dev, "Failed to disable vdd: %d\n", error);
@@ -376,67 +393,44 @@ static void mms114_input_close(struct input_dev *dev)
mms114_stop(data);
}
-#ifdef CONFIG_OF
-static struct mms114_platform_data *mms114_parse_dt(struct device *dev)
+static int mms114_parse_legacy_bindings(struct mms114_data *data)
{
- struct mms114_platform_data *pdata;
- struct device_node *np = dev->of_node;
-
- if (!np)
- return NULL;
+ struct device *dev = &data->client->dev;
+ struct touchscreen_properties *props = &data->props;
- pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
- if (!pdata) {
- dev_err(dev, "failed to allocate platform data\n");
- return NULL;
+ if (device_property_read_u32(dev, "x-size", &props->max_x)) {
+ dev_dbg(dev, "failed to get legacy x-size property\n");
+ return -EINVAL;
}
- if (of_property_read_u32(np, "x-size", &pdata->x_size)) {
- dev_err(dev, "failed to get x-size property\n");
- return NULL;
+ if (device_property_read_u32(dev, "y-size", &props->max_y)) {
+ dev_dbg(dev, "failed to get legacy y-size property\n");
+ return -EINVAL;
}
- if (of_property_read_u32(np, "y-size", &pdata->y_size)) {
- dev_err(dev, "failed to get y-size property\n");
- return NULL;
- }
+ device_property_read_u32(dev, "contact-threshold",
+ &data->contact_threshold);
+ device_property_read_u32(dev, "moving-threshold",
+ &data->moving_threshold);
- of_property_read_u32(np, "contact-threshold",
- &pdata->contact_threshold);
- of_property_read_u32(np, "moving-threshold",
- &pdata->moving_threshold);
+ if (device_property_read_bool(dev, "x-invert"))
+ props->invert_x = true;
+ if (device_property_read_bool(dev, "y-invert"))
+ props->invert_y = true;
- if (of_find_property(np, "x-invert", NULL))
- pdata->x_invert = true;
- if (of_find_property(np, "y-invert", NULL))
- pdata->y_invert = true;
+ props->swap_x_y = false;
- return pdata;
-}
-#else
-static inline struct mms114_platform_data *mms114_parse_dt(struct device *dev)
-{
- return NULL;
+ return 0;
}
-#endif
static int mms114_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
- const struct mms114_platform_data *pdata;
struct mms114_data *data;
struct input_dev *input_dev;
+ const void *match_data;
int error;
- pdata = dev_get_platdata(&client->dev);
- if (!pdata)
- pdata = mms114_parse_dt(&client->dev);
-
- if (!pdata) {
- dev_err(&client->dev, "Need platform data\n");
- return -EINVAL;
- }
-
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_PROTOCOL_MANGLING)) {
dev_err(&client->dev,
@@ -454,29 +448,63 @@ static int mms114_probe(struct i2c_client *client,
data->client = client;
data->input_dev = input_dev;
- data->pdata = pdata;
- input_dev->name = "MELFAS MMS114 Touchscreen";
+ /* FIXME: switch to device_get_match_data() when available */
+ match_data = of_device_get_match_data(&client->dev);
+ if (!match_data)
+ return -EINVAL;
+
+ data->type = (enum mms_type)match_data;
+
+ input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_X);
+ input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_Y);
+ input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, 255, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
+ 0, MMS114_MAX_AREA, 0, 0);
+
+ touchscreen_parse_properties(input_dev, true, &data->props);
+ if (!data->props.max_x || !data->props.max_y) {
+ dev_dbg(&client->dev,
+ "missing X/Y size properties, trying legacy bindings\n");
+ error = mms114_parse_legacy_bindings(data);
+ if (error)
+ return error;
+
+ input_set_abs_params(input_dev, ABS_MT_POSITION_X,
+ 0, data->props.max_x, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
+ 0, data->props.max_y, 0, 0);
+ }
+
+ if (data->type == TYPE_MMS114) {
+ /*
+ * The firmware handles movement and pressure fuzz, so
+ * don't duplicate that in software.
+ */
+ data->moving_threshold = input_abs_get_fuzz(input_dev,
+ ABS_MT_POSITION_X);
+ data->contact_threshold = input_abs_get_fuzz(input_dev,
+ ABS_MT_PRESSURE);
+ input_abs_set_fuzz(input_dev, ABS_MT_POSITION_X, 0);
+ input_abs_set_fuzz(input_dev, ABS_MT_POSITION_Y, 0);
+ input_abs_set_fuzz(input_dev, ABS_MT_PRESSURE, 0);
+ }
+
+ input_dev->name = devm_kasprintf(&client->dev, GFP_KERNEL,
+ "MELFAS MMS%d Touchscreen",
+ data->type);
+ if (!input_dev->name)
+ return -ENOMEM;
+
input_dev->id.bustype = BUS_I2C;
input_dev->dev.parent = &client->dev;
input_dev->open = mms114_input_open;
input_dev->close = mms114_input_close;
- __set_bit(EV_ABS, input_dev->evbit);
- __set_bit(EV_KEY, input_dev->evbit);
- __set_bit(BTN_TOUCH, input_dev->keybit);
- input_set_abs_params(input_dev, ABS_X, 0, data->pdata->x_size, 0, 0);
- input_set_abs_params(input_dev, ABS_Y, 0, data->pdata->y_size, 0, 0);
-
- /* For multi touch */
- input_mt_init_slots(input_dev, MMS114_MAX_TOUCH, 0);
- input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
- 0, MMS114_MAX_AREA, 0, 0);
- input_set_abs_params(input_dev, ABS_MT_POSITION_X,
- 0, data->pdata->x_size, 0, 0);
- input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
- 0, data->pdata->y_size, 0, 0);
- input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, 255, 0, 0);
+ error = input_mt_init_slots(input_dev, MMS114_MAX_TOUCH,
+ INPUT_MT_DIRECT);
+ if (error)
+ return error;
input_set_drvdata(input_dev, data);
i2c_set_clientdata(client, data);
@@ -497,9 +525,9 @@ static int mms114_probe(struct i2c_client *client,
return error;
}
- error = devm_request_threaded_irq(&client->dev, client->irq, NULL,
- mms114_interrupt, IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
- dev_name(&client->dev), data);
+ error = devm_request_threaded_irq(&client->dev, client->irq,
+ NULL, mms114_interrupt, IRQF_ONESHOT,
+ dev_name(&client->dev), data);
if (error) {
dev_err(&client->dev, "Failed to register interrupt\n");
return error;
@@ -569,7 +597,13 @@ MODULE_DEVICE_TABLE(i2c, mms114_id);
#ifdef CONFIG_OF
static const struct of_device_id mms114_dt_match[] = {
- { .compatible = "melfas,mms114" },
+ {
+ .compatible = "melfas,mms114",
+ .data = (void *)TYPE_MMS114,
+ }, {
+ .compatible = "melfas,mms152",
+ .data = (void *)TYPE_MMS152,
+ },
{ }
};
MODULE_DEVICE_TABLE(of, mms114_dt_match);
diff --git a/drivers/input/touchscreen/of_touchscreen.c b/drivers/input/touchscreen/of_touchscreen.c
index 8d7f9c8f2771..9642f103b726 100644
--- a/drivers/input/touchscreen/of_touchscreen.c
+++ b/drivers/input/touchscreen/of_touchscreen.c
@@ -13,6 +13,7 @@
#include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/input/touchscreen.h>
+#include <linux/module.h>
static bool touchscreen_get_prop_u32(struct device *dev,
const char *property,
@@ -185,3 +186,6 @@ void touchscreen_report_pos(struct input_dev *input,
input_report_abs(input, multitouch ? ABS_MT_POSITION_Y : ABS_Y, y);
}
EXPORT_SYMBOL(touchscreen_report_pos);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Device-tree helpers functions for touchscreen devices");
diff --git a/drivers/input/touchscreen/raydium_i2c_ts.c b/drivers/input/touchscreen/raydium_i2c_ts.c
index 100538d64fff..d1c09e6a2cb6 100644
--- a/drivers/input/touchscreen/raydium_i2c_ts.c
+++ b/drivers/input/touchscreen/raydium_i2c_ts.c
@@ -752,13 +752,20 @@ static int raydium_i2c_fw_update(struct raydium_data *ts)
{
struct i2c_client *client = ts->client;
const struct firmware *fw = NULL;
- const char *fw_file = "raydium.fw";
+ char *fw_file;
int error;
+ fw_file = 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);
+
error = request_firmware(&fw, fw_file, &client->dev);
if (error) {
dev_err(&client->dev, "Unable to open firmware %s\n", fw_file);
- return error;
+ goto out_free_fw_file;
}
disable_irq(client->irq);
@@ -787,6 +794,9 @@ out_enable_irq:
release_firmware(fw);
+out_free_fw_file:
+ kfree(fw_file);
+
return error;
}
diff --git a/drivers/input/touchscreen/s6sy761.c b/drivers/input/touchscreen/s6sy761.c
index 26b1cb8a88ec..675efa93d444 100644
--- a/drivers/input/touchscreen/s6sy761.c
+++ b/drivers/input/touchscreen/s6sy761.c
@@ -1,13 +1,8 @@
-/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
- * Author: Andi Shyti <andi.shyti@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Samsung S6SY761 Touchscreen device driver
- */
+// SPDX-License-Identifier: GPL-2.0
+// Samsung S6SY761 Touchscreen device driver
+//
+// Copyright (c) 2017 Samsung Electronics Co., Ltd.
+// Copyright (c) 2017 Andi Shyti <andi.shyti@samsung.com>
#include <asm/unaligned.h>
#include <linux/delay.h>
diff --git a/drivers/input/touchscreen/silead.c b/drivers/input/touchscreen/silead.c
index 0dbcf105f7db..646b1e768e6b 100644
--- a/drivers/input/touchscreen/silead.c
+++ b/drivers/input/touchscreen/silead.c
@@ -56,7 +56,7 @@
#define SILEAD_POINT_Y_MSB_OFF 0x01
#define SILEAD_POINT_X_OFF 0x02
#define SILEAD_POINT_X_MSB_OFF 0x03
-#define SILEAD_TOUCH_ID_MASK 0xF0
+#define SILEAD_EXTRA_DATA_MASK 0xF0
#define SILEAD_CMD_SLEEP_MIN 10000
#define SILEAD_CMD_SLEEP_MAX 20000
@@ -109,6 +109,9 @@ static int silead_ts_request_input_dev(struct silead_ts_data *data)
INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED |
INPUT_MT_TRACK);
+ if (device_property_read_bool(dev, "silead,home-button"))
+ input_set_capability(data->input, EV_KEY, KEY_LEFTMETA);
+
data->input->name = SILEAD_TS_NAME;
data->input->phys = "input/ts";
data->input->id.bustype = BUS_I2C;
@@ -139,7 +142,8 @@ static void silead_ts_read_data(struct i2c_client *client)
struct input_dev *input = data->input;
struct device *dev = &client->dev;
u8 *bufp, buf[SILEAD_TS_DATA_LEN];
- int touch_nr, error, i;
+ int touch_nr, softbutton, error, i;
+ bool softbutton_pressed = false;
error = i2c_smbus_read_i2c_block_data(client, SILEAD_REG_DATA,
SILEAD_TS_DATA_LEN, buf);
@@ -148,21 +152,40 @@ static void silead_ts_read_data(struct i2c_client *client)
return;
}
- touch_nr = buf[0];
- if (touch_nr > data->max_fingers) {
+ if (buf[0] > data->max_fingers) {
dev_warn(dev, "More touches reported then supported %d > %d\n",
- touch_nr, data->max_fingers);
- touch_nr = data->max_fingers;
+ buf[0], data->max_fingers);
+ buf[0] = data->max_fingers;
}
+ touch_nr = 0;
bufp = buf + SILEAD_POINT_DATA_LEN;
- for (i = 0; i < touch_nr; i++, bufp += SILEAD_POINT_DATA_LEN) {
- /* Bits 4-7 are the touch id */
- data->id[i] = (bufp[SILEAD_POINT_X_MSB_OFF] &
- SILEAD_TOUCH_ID_MASK) >> 4;
- touchscreen_set_mt_pos(&data->pos[i], &data->prop,
+ for (i = 0; i < buf[0]; i++, bufp += SILEAD_POINT_DATA_LEN) {
+ softbutton = (bufp[SILEAD_POINT_Y_MSB_OFF] &
+ SILEAD_EXTRA_DATA_MASK) >> 4;
+
+ if (softbutton) {
+ /*
+ * For now only respond to softbutton == 0x01, some
+ * tablets *without* a capacative button send 0x04
+ * when crossing the edges of the screen.
+ */
+ if (softbutton == 0x01)
+ softbutton_pressed = true;
+
+ continue;
+ }
+
+ /*
+ * Bits 4-7 are the touch id, note not all models have
+ * hardware touch ids so atm we don't use these.
+ */
+ data->id[touch_nr] = (bufp[SILEAD_POINT_X_MSB_OFF] &
+ SILEAD_EXTRA_DATA_MASK) >> 4;
+ touchscreen_set_mt_pos(&data->pos[touch_nr], &data->prop,
get_unaligned_le16(&bufp[SILEAD_POINT_X_OFF]) & 0xfff,
get_unaligned_le16(&bufp[SILEAD_POINT_Y_OFF]) & 0xfff);
+ touch_nr++;
}
input_mt_assign_slots(input, data->slots, data->pos, touch_nr, 0);
@@ -178,6 +201,7 @@ static void silead_ts_read_data(struct i2c_client *client)
}
input_mt_sync_frame(input);
+ input_report_key(input, KEY_LEFTMETA, softbutton_pressed);
input_sync(input);
}
diff --git a/drivers/input/touchscreen/stmfts.c b/drivers/input/touchscreen/stmfts.c
index c12d01899939..efdb1a75a163 100644
--- a/drivers/input/touchscreen/stmfts.c
+++ b/drivers/input/touchscreen/stmfts.c
@@ -1,13 +1,8 @@
-/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
- * Author: Andi Shyti <andi.shyti@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * STMicroelectronics FTS Touchscreen device driver
- */
+// SPDX-License-Identifier: GPL-2.0
+// STMicroelectronics FTS Touchscreen device driver
+//
+// Copyright (c) 2017 Samsung Electronics Co., Ltd.
+// Copyright (c) 2017 Andi Shyti <andi.shyti@samsung.com>
#include <linux/delay.h>
#include <linux/i2c.h>
@@ -687,6 +682,14 @@ static int stmfts_probe(struct i2c_client *client,
input_set_drvdata(sdata->input, sdata);
+ /*
+ * stmfts_power_on expects interrupt to be disabled, but
+ * at this point the device is still off and I do not trust
+ * the status of the irq line that can generate some spurious
+ * interrupts. To be on the safe side it's better to not enable
+ * the interrupts during their request.
+ */
+ irq_set_status_flags(client->irq, IRQ_NOAUTOEN);
err = devm_request_threaded_irq(&client->dev, client->irq,
NULL, stmfts_irq_handler,
IRQF_ONESHOT,
@@ -694,9 +697,6 @@ static int stmfts_probe(struct i2c_client *client,
if (err)
return err;
- /* stmfts_power_on expects interrupt to be disabled */
- disable_irq(client->irq);
-
dev_dbg(&client->dev, "initializing ST-Microelectronics FTS...\n");
err = stmfts_power_on(sdata);
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c
index 2c41107240de..aa77d243b786 100644
--- a/drivers/input/touchscreen/usbtouchscreen.c
+++ b/drivers/input/touchscreen/usbtouchscreen.c
@@ -55,11 +55,6 @@
#include <linux/usb/input.h>
#include <linux/hid.h>
-
-#define DRIVER_VERSION "v0.6"
-#define DRIVER_AUTHOR "Daniel Ritz <daniel.ritz@gmx.ch>"
-#define DRIVER_DESC "USB Touchscreen Driver"
-
static bool swap_xy;
module_param(swap_xy, bool, 0644);
MODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped.");
@@ -1763,8 +1758,8 @@ static struct usb_driver usbtouch_driver = {
module_usb_driver(usbtouch_driver);
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Daniel Ritz <daniel.ritz@gmx.ch>");
+MODULE_DESCRIPTION("USB Touchscreen Driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("touchkitusb");
diff --git a/drivers/input/touchscreen/wdt87xx_i2c.c b/drivers/input/touchscreen/wdt87xx_i2c.c
index d351efd18f89..20f7f3902757 100644
--- a/drivers/input/touchscreen/wdt87xx_i2c.c
+++ b/drivers/input/touchscreen/wdt87xx_i2c.c
@@ -23,7 +23,6 @@
#include <asm/unaligned.h>
#define WDT87XX_NAME "wdt87xx_i2c"
-#define WDT87XX_DRV_VER "0.9.8"
#define WDT87XX_FW_NAME "wdt87xx_fw.bin"
#define WDT87XX_CFG_NAME "wdt87xx_cfg.bin"
@@ -1183,5 +1182,4 @@ module_i2c_driver(wdt87xx_driver);
MODULE_AUTHOR("HN Chen <hn.chen@weidahitech.com>");
MODULE_DESCRIPTION("WeidaHiTech WDT87XX Touchscreen driver");
-MODULE_VERSION(WDT87XX_DRV_VER);
MODULE_LICENSE("GPL");