diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-05-03 22:38:20 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-05-03 22:38:20 +0300 |
commit | 16a12fa9aed176444fc795b09e796be41902bb08 (patch) | |
tree | bd158def3263a8b0d0f0886fd0fcd32728242dc4 /drivers/input/touchscreen | |
parent | d25e436c4b68db2895185b24ad1f22499c2f87b0 (diff) | |
parent | 0337966d121ebebf73a1c346123e8112796e684e (diff) | |
download | linux-16a12fa9aed176444fc795b09e796be41902bb08.tar.xz |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull input subsystem updates from Dmitry Torokhov:
- a big update from Mauro converting input documentation to ReST format
- Synaptics PS/2 is now aware of SMBus companion devices, which means
that we can now use native RMI4 protocol to handle touchpads, instead
of relying on legacy PS/2 mode.
- we removed support from BMA180 accelerometer from input devices as it
is now handled properly by IIO
- update to TSC2007 to corretcly report pressure
- other miscellaneous driver fixes.
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (152 commits)
Input: ar1021_i2c - use BIT to check for a bit
Input: twl4030-pwrbutton - use input_set_capability() helper
Input: twl4030-pwrbutton - use correct device for irq request
Input: ar1021_i2c - enable touch mode during open
Input: add uinput documentation
dt-bindings: input: add bindings document for ar1021_i2c driver
dt-bindings: input: rotary-encoder: fix typo
Input: xen-kbdfront - add module parameter for setting resolution
ARM: pxa/raumfeld: fix compile error in rotary controller resources
Input: xpad - do not suggest writing to Dominic
Input: xpad - don't use literal blocks inside footnotes
Input: xpad - note that usb/devices is now at /sys/kernel/debug/
Input: docs - freshen up introduction
Input: docs - split input docs into kernel- and user-facing
Input: docs - note that MT-A protocol is obsolete
Input: docs - update joystick documentation a bit
Input: docs - remove disclaimer/GPL notice
Input: fix "Game console" heading level in joystick documentation
Input: rotary-encoder - remove references to platform data from docs
Input: move documentation for Amiga CD32
...
Diffstat (limited to 'drivers/input/touchscreen')
-rw-r--r-- | drivers/input/touchscreen/Kconfig | 18 | ||||
-rw-r--r-- | drivers/input/touchscreen/Makefile | 2 | ||||
-rw-r--r-- | drivers/input/touchscreen/ad7879-i2c.c | 67 | ||||
-rw-r--r-- | drivers/input/touchscreen/ad7879-spi.c | 131 | ||||
-rw-r--r-- | drivers/input/touchscreen/ad7879.c | 152 | ||||
-rw-r--r-- | drivers/input/touchscreen/ad7879.h | 14 | ||||
-rw-r--r-- | drivers/input/touchscreen/ads7846.c | 2 | ||||
-rw-r--r-- | drivers/input/touchscreen/ar1021_i2c.c | 30 | ||||
-rw-r--r-- | drivers/input/touchscreen/eeti_ts.c | 226 | ||||
-rw-r--r-- | drivers/input/touchscreen/imx6ul_tsc.c | 15 | ||||
-rw-r--r-- | drivers/input/touchscreen/lpc32xx_ts.c | 13 | ||||
-rw-r--r-- | drivers/input/touchscreen/max11801_ts.c | 7 | ||||
-rw-r--r-- | drivers/input/touchscreen/melfas_mip4.c | 11 | ||||
-rw-r--r-- | drivers/input/touchscreen/silead.c | 13 | ||||
-rw-r--r-- | drivers/input/touchscreen/sur40.c | 2 | ||||
-rw-r--r-- | drivers/input/touchscreen/tps6507x-ts.c | 33 | ||||
-rw-r--r-- | drivers/input/touchscreen/tsc2007.h | 101 | ||||
-rw-r--r-- | drivers/input/touchscreen/tsc2007_core.c (renamed from drivers/input/touchscreen/tsc2007.c) | 102 | ||||
-rw-r--r-- | drivers/input/touchscreen/tsc2007_iio.c | 140 |
19 files changed, 569 insertions, 510 deletions
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 52458cfdf017..cf26ca49ae6d 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -73,6 +73,7 @@ config TOUCHSCREEN_AD7879 config TOUCHSCREEN_AD7879_I2C tristate "support I2C bus connection" depends on TOUCHSCREEN_AD7879 && I2C + select REGMAP_I2C help Say Y here if you have AD7879-1/AD7889-1 hooked to an I2C bus. @@ -82,6 +83,7 @@ config TOUCHSCREEN_AD7879_I2C config TOUCHSCREEN_AD7879_SPI tristate "support SPI bus connection" depends on TOUCHSCREEN_AD7879 && SPI_MASTER + select REGMAP_SPI help Say Y here if you have AD7879-1/AD7889-1 hooked to a SPI bus. @@ -91,11 +93,11 @@ config TOUCHSCREEN_AD7879_SPI module will be called ad7879-spi. config TOUCHSCREEN_AR1021_I2C - tristate "Microchip AR1021 i2c touchscreen" + tristate "Microchip AR1020/1021 i2c touchscreen" depends on I2C && OF help - Say Y here if you have the Microchip AR1021 touchscreen controller - chip in your system. + Say Y here if you have the Microchip AR1020 or AR1021 touchscreen + controller chip in your system. If unsure, say N. @@ -1033,6 +1035,16 @@ config TOUCHSCREEN_TSC2007 To compile this driver as a module, choose M here: the module will be called tsc2007. +config TOUCHSCREEN_TSC2007_IIO + bool "IIO interface for external ADC input and temperature" + depends on TOUCHSCREEN_TSC2007 + depends on IIO=y || IIO=TOUCHSCREEN_TSC2007 + help + Saying Y here adds an iio interface to the tsc2007 which + provides values for the AUX input (used for e.g. battery + or ambient light monitoring), temperature and raw input + values. + config TOUCHSCREEN_W90X900 tristate "W90P910 touchscreen driver" depends on ARCH_W90X900 diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 96761ce2ee6d..18e476948e44 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -80,6 +80,8 @@ obj-$(CONFIG_TOUCHSCREEN_TSC_SERIO) += tsc40.o obj-$(CONFIG_TOUCHSCREEN_TSC200X_CORE) += tsc200x-core.o obj-$(CONFIG_TOUCHSCREEN_TSC2004) += tsc2004.o obj-$(CONFIG_TOUCHSCREEN_TSC2005) += tsc2005.o +tsc2007-y := tsc2007_core.o +tsc2007-$(CONFIG_TOUCHSCREEN_TSC2007_IIO) += tsc2007_iio.o obj-$(CONFIG_TOUCHSCREEN_TSC2007) += tsc2007.o obj-$(CONFIG_TOUCHSCREEN_UCB1400) += ucb1400_ts.o obj-$(CONFIG_TOUCHSCREEN_WACOM_W8001) += wacom_w8001.o diff --git a/drivers/input/touchscreen/ad7879-i2c.c b/drivers/input/touchscreen/ad7879-i2c.c index 58f72e0246ab..49b902b10c5f 100644 --- a/drivers/input/touchscreen/ad7879-i2c.c +++ b/drivers/input/touchscreen/ad7879-i2c.c @@ -12,53 +12,22 @@ #include <linux/types.h> #include <linux/of.h> #include <linux/pm.h> +#include <linux/regmap.h> #include "ad7879.h" #define AD7879_DEVID 0x79 /* AD7879-1/AD7889-1 */ -/* All registers are word-sized. - * AD7879 uses a high-byte first convention. - */ -static int ad7879_i2c_read(struct device *dev, u8 reg) -{ - struct i2c_client *client = to_i2c_client(dev); - - return i2c_smbus_read_word_swapped(client, reg); -} - -static int ad7879_i2c_multi_read(struct device *dev, - u8 first_reg, u8 count, u16 *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - u8 idx; - - i2c_smbus_read_i2c_block_data(client, first_reg, count * 2, (u8 *)buf); - - for (idx = 0; idx < count; ++idx) - buf[idx] = swab16(buf[idx]); - - return 0; -} - -static int ad7879_i2c_write(struct device *dev, u8 reg, u16 val) -{ - struct i2c_client *client = to_i2c_client(dev); - - return i2c_smbus_write_word_swapped(client, reg, val); -} - -static const struct ad7879_bus_ops ad7879_i2c_bus_ops = { - .bustype = BUS_I2C, - .read = ad7879_i2c_read, - .multi_read = ad7879_i2c_multi_read, - .write = ad7879_i2c_write, +static const struct regmap_config ad7879_i2c_regmap_config = { + .reg_bits = 8, + .val_bits = 16, + .max_register = 15, }; static int ad7879_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { - struct ad7879 *ts; + struct regmap *regmap; if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA)) { @@ -66,23 +35,12 @@ static int ad7879_i2c_probe(struct i2c_client *client, return -EIO; } - ts = ad7879_probe(&client->dev, AD7879_DEVID, client->irq, - &ad7879_i2c_bus_ops); - if (IS_ERR(ts)) - return PTR_ERR(ts); - - i2c_set_clientdata(client, ts); - - return 0; -} - -static int ad7879_i2c_remove(struct i2c_client *client) -{ - struct ad7879 *ts = i2c_get_clientdata(client); - - ad7879_remove(ts); + regmap = devm_regmap_init_i2c(client, &ad7879_i2c_regmap_config); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); - return 0; + return ad7879_probe(&client->dev, regmap, client->irq, + BUS_I2C, AD7879_DEVID); } static const struct i2c_device_id ad7879_id[] = { @@ -107,12 +65,11 @@ static struct i2c_driver ad7879_i2c_driver = { .of_match_table = of_match_ptr(ad7879_i2c_dt_ids), }, .probe = ad7879_i2c_probe, - .remove = ad7879_i2c_remove, .id_table = ad7879_id, }; module_i2c_driver(ad7879_i2c_driver); -MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); +MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>"); MODULE_DESCRIPTION("AD7879(-1) touchscreen I2C bus driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/input/touchscreen/ad7879-spi.c b/drivers/input/touchscreen/ad7879-spi.c index d42b6b9af191..3457a5626d75 100644 --- a/drivers/input/touchscreen/ad7879-spi.c +++ b/drivers/input/touchscreen/ad7879-spi.c @@ -11,110 +11,28 @@ #include <linux/spi/spi.h> #include <linux/module.h> #include <linux/of.h> +#include <linux/regmap.h> #include "ad7879.h" #define AD7879_DEVID 0x7A /* AD7879/AD7889 */ #define MAX_SPI_FREQ_HZ 5000000 -#define AD7879_CMD_MAGIC 0xE000 -#define AD7879_CMD_READ (1 << 10) -#define AD7879_CMD(reg) (AD7879_CMD_MAGIC | ((reg) & 0xF)) -#define AD7879_WRITECMD(reg) (AD7879_CMD(reg)) -#define AD7879_READCMD(reg) (AD7879_CMD(reg) | AD7879_CMD_READ) -/* - * ad7879_read/write are only used for initial setup and for sysfs controls. - * The main traffic is done in ad7879_collect(). - */ - -static int ad7879_spi_xfer(struct spi_device *spi, - u16 cmd, u8 count, u16 *tx_buf, u16 *rx_buf) -{ - struct spi_message msg; - struct spi_transfer *xfers; - void *spi_data; - u16 *command; - u16 *_rx_buf = _rx_buf; /* shut gcc up */ - u8 idx; - int ret; - - xfers = spi_data = kzalloc(sizeof(*xfers) * (count + 2), GFP_KERNEL); - if (!spi_data) - return -ENOMEM; - - spi_message_init(&msg); - - command = spi_data; - command[0] = cmd; - if (count == 1) { - /* ad7879_spi_{read,write} gave us buf on stack */ - command[1] = *tx_buf; - tx_buf = &command[1]; - _rx_buf = rx_buf; - rx_buf = &command[2]; - } - - ++xfers; - xfers[0].tx_buf = command; - xfers[0].len = 2; - spi_message_add_tail(&xfers[0], &msg); - ++xfers; - - for (idx = 0; idx < count; ++idx) { - if (rx_buf) - xfers[idx].rx_buf = &rx_buf[idx]; - if (tx_buf) - xfers[idx].tx_buf = &tx_buf[idx]; - xfers[idx].len = 2; - spi_message_add_tail(&xfers[idx], &msg); - } - - ret = spi_sync(spi, &msg); - - if (count == 1) - _rx_buf[0] = command[2]; - - kfree(spi_data); - - return ret; -} - -static int ad7879_spi_multi_read(struct device *dev, - u8 first_reg, u8 count, u16 *buf) -{ - struct spi_device *spi = to_spi_device(dev); +#define AD7879_CMD_MAGIC 0xE0 +#define AD7879_CMD_READ BIT(2) - return ad7879_spi_xfer(spi, AD7879_READCMD(first_reg), count, NULL, buf); -} - -static int ad7879_spi_read(struct device *dev, u8 reg) -{ - struct spi_device *spi = to_spi_device(dev); - u16 ret, dummy; - - return ad7879_spi_xfer(spi, AD7879_READCMD(reg), 1, &dummy, &ret) ? : ret; -} - -static int ad7879_spi_write(struct device *dev, u8 reg, u16 val) -{ - struct spi_device *spi = to_spi_device(dev); - u16 dummy; - - return ad7879_spi_xfer(spi, AD7879_WRITECMD(reg), 1, &val, &dummy); -} - -static const struct ad7879_bus_ops ad7879_spi_bus_ops = { - .bustype = BUS_SPI, - .read = ad7879_spi_read, - .multi_read = ad7879_spi_multi_read, - .write = ad7879_spi_write, +static const struct regmap_config ad7879_spi_regmap_config = { + .reg_bits = 16, + .val_bits = 16, + .max_register = 15, + .read_flag_mask = AD7879_CMD_MAGIC | AD7879_CMD_READ, + .write_flag_mask = AD7879_CMD_MAGIC, }; static int ad7879_spi_probe(struct spi_device *spi) { - struct ad7879 *ts; - int err; + struct regmap *regmap; /* don't exceed max specified SPI CLK frequency */ if (spi->max_speed_hz > MAX_SPI_FREQ_HZ) { @@ -122,29 +40,11 @@ static int ad7879_spi_probe(struct spi_device *spi) return -EINVAL; } - spi->bits_per_word = 16; - err = spi_setup(spi); - if (err) { - dev_dbg(&spi->dev, "spi master doesn't support 16 bits/word\n"); - return err; - } - - ts = ad7879_probe(&spi->dev, AD7879_DEVID, spi->irq, &ad7879_spi_bus_ops); - if (IS_ERR(ts)) - return PTR_ERR(ts); - - spi_set_drvdata(spi, ts); - - return 0; -} - -static int ad7879_spi_remove(struct spi_device *spi) -{ - struct ad7879 *ts = spi_get_drvdata(spi); - - ad7879_remove(ts); + regmap = devm_regmap_init_spi(spi, &ad7879_spi_regmap_config); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); - return 0; + return ad7879_probe(&spi->dev, regmap, spi->irq, BUS_SPI, AD7879_DEVID); } #ifdef CONFIG_OF @@ -162,12 +62,11 @@ static struct spi_driver ad7879_spi_driver = { .of_match_table = of_match_ptr(ad7879_spi_dt_ids), }, .probe = ad7879_spi_probe, - .remove = ad7879_spi_remove, }; module_spi_driver(ad7879_spi_driver); -MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); +MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>"); MODULE_DESCRIPTION("AD7879(-1) touchscreen SPI bus driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("spi:ad7879"); diff --git a/drivers/input/touchscreen/ad7879.c b/drivers/input/touchscreen/ad7879.c index e16a44667da7..196028c45210 100644 --- a/drivers/input/touchscreen/ad7879.c +++ b/drivers/input/touchscreen/ad7879.c @@ -26,9 +26,9 @@ #include <linux/input.h> #include <linux/interrupt.h> #include <linux/irq.h> +#include <linux/property.h> +#include <linux/regmap.h> #include <linux/slab.h> -#include <linux/spi/spi.h> -#include <linux/i2c.h> #include <linux/gpio.h> #include <linux/input/touchscreen.h> @@ -106,8 +106,7 @@ enum { #define TS_PEN_UP_TIMEOUT msecs_to_jiffies(50) struct ad7879 { - const struct ad7879_bus_ops *bops; - + struct regmap *regmap; struct device *dev; struct input_dev *input; struct timer_list timer; @@ -137,17 +136,32 @@ struct ad7879 { static int ad7879_read(struct ad7879 *ts, u8 reg) { - return ts->bops->read(ts->dev, reg); -} + unsigned int val; + int error; -static int ad7879_multi_read(struct ad7879 *ts, u8 first_reg, u8 count, u16 *buf) -{ - return ts->bops->multi_read(ts->dev, first_reg, count, buf); + error = regmap_read(ts->regmap, reg, &val); + if (error) { + dev_err(ts->dev, "failed to read register %#02x: %d\n", + reg, error); + return error; + } + + return val; } static int ad7879_write(struct ad7879 *ts, u8 reg, u16 val) { - return ts->bops->write(ts->dev, reg, val); + int error; + + error = regmap_write(ts->regmap, reg, val); + if (error) { + dev_err(ts->dev, + "failed to write %#04x to register %#02x: %d\n", + val, reg, error); + return error; + } + + return 0; } static int ad7879_report(struct ad7879 *ts) @@ -234,7 +248,8 @@ static irqreturn_t ad7879_irq(int irq, void *handle) { struct ad7879 *ts = handle; - ad7879_multi_read(ts, AD7879_REG_XPLUS, AD7879_NR_SENSE, ts->conversion_data); + regmap_bulk_read(ts->regmap, AD7879_REG_XPLUS, + ts->conversion_data, AD7879_NR_SENSE); if (!ad7879_report(ts)) mod_timer(&ts->timer, jiffies + TS_PEN_UP_TIMEOUT); @@ -440,23 +455,34 @@ static void ad7879_gpio_set_value(struct gpio_chip *chip, static int ad7879_gpio_add(struct ad7879 *ts, const struct ad7879_platform_data *pdata) { + bool gpio_export; + int gpio_base; int ret = 0; + if (pdata) { + gpio_export = pdata->gpio_export; + gpio_base = pdata->gpio_base; + } else { + gpio_export = device_property_read_bool(ts->dev, + "gpio-controller"); + gpio_base = -1; + } + mutex_init(&ts->mutex); - if (pdata->gpio_export) { + if (gpio_export) { ts->gc.direction_input = ad7879_gpio_direction_input; ts->gc.direction_output = ad7879_gpio_direction_output; ts->gc.get = ad7879_gpio_get_value; ts->gc.set = ad7879_gpio_set_value; ts->gc.can_sleep = 1; - ts->gc.base = pdata->gpio_base; + ts->gc.base = gpio_base; ts->gc.ngpio = 1; ts->gc.label = "AD7879-GPIO"; ts->gc.owner = THIS_MODULE; ts->gc.parent = ts->dev; - ret = gpiochip_add_data(&ts->gc, ts); + ret = devm_gpiochip_add_data(ts->dev, &ts->gc, ts); if (ret) dev_err(ts->dev, "failed to register gpio %d\n", ts->gc.base); @@ -464,25 +490,12 @@ static int ad7879_gpio_add(struct ad7879 *ts, return ret; } - -static void ad7879_gpio_remove(struct ad7879 *ts) -{ - const struct ad7879_platform_data *pdata = dev_get_platdata(ts->dev); - - if (pdata && pdata->gpio_export) - gpiochip_remove(&ts->gc); - -} #else -static inline int ad7879_gpio_add(struct ad7879 *ts, - const struct ad7879_platform_data *pdata) +static int ad7879_gpio_add(struct ad7879 *ts, + const struct ad7879_platform_data *pdata) { return 0; } - -static inline void ad7879_gpio_remove(struct ad7879 *ts) -{ -} #endif static int ad7879_parse_dt(struct device *dev, struct ad7879 *ts) @@ -511,8 +524,15 @@ static int ad7879_parse_dt(struct device *dev, struct ad7879 *ts) return 0; } -struct ad7879 *ad7879_probe(struct device *dev, u8 devid, unsigned int irq, - const struct ad7879_bus_ops *bops) +static void ad7879_cleanup_sysfs(void *_ts) +{ + struct ad7879 *ts = _ts; + + sysfs_remove_group(&ts->dev->kobj, &ad7879_attr_group); +} + +int ad7879_probe(struct device *dev, struct regmap *regmap, + int irq, u16 bustype, u8 devid) { struct ad7879_platform_data *pdata = dev_get_platdata(dev); struct ad7879 *ts; @@ -520,14 +540,14 @@ struct ad7879 *ad7879_probe(struct device *dev, u8 devid, unsigned int irq, int err; u16 revid; - if (!irq) { + if (irq <= 0) { dev_err(dev, "No IRQ specified\n"); - return ERR_PTR(-EINVAL); + return -EINVAL; } ts = devm_kzalloc(dev, sizeof(*ts), GFP_KERNEL); if (!ts) - return ERR_PTR(-ENOMEM); + return -ENOMEM; if (pdata) { /* Platform data use swapped axis (backward compatibility) */ @@ -540,23 +560,22 @@ struct ad7879 *ad7879_probe(struct device *dev, u8 devid, unsigned int irq, ts->averaging = pdata->averaging; ts->pen_down_acc_interval = pdata->pen_down_acc_interval; ts->median = pdata->median; - } else if (dev->of_node) { - ad7879_parse_dt(dev, ts); } else { - dev_err(dev, "No platform data\n"); - return ERR_PTR(-EINVAL); + err = ad7879_parse_dt(dev, ts); + if (err) + return err; } input_dev = devm_input_allocate_device(dev); if (!input_dev) { dev_err(dev, "Failed to allocate input device\n"); - return ERR_PTR(-ENOMEM); + return -ENOMEM; } - ts->bops = bops; ts->dev = dev; ts->input = input_dev; ts->irq = irq; + ts->regmap = regmap; setup_timer(&ts->timer, ad7879_timer, (unsigned long) ts); snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(dev)); @@ -564,20 +583,14 @@ struct ad7879 *ad7879_probe(struct device *dev, u8 devid, unsigned int irq, input_dev->name = "AD7879 Touchscreen"; input_dev->phys = ts->phys; input_dev->dev.parent = dev; - input_dev->id.bustype = bops->bustype; + input_dev->id.bustype = bustype; input_dev->open = ad7879_open; input_dev->close = ad7879_close; input_set_drvdata(input_dev, ts); - __set_bit(EV_ABS, input_dev->evbit); - __set_bit(ABS_X, input_dev->absbit); - __set_bit(ABS_Y, input_dev->absbit); - __set_bit(ABS_PRESSURE, input_dev->absbit); - - __set_bit(EV_KEY, input_dev->evbit); - __set_bit(BTN_TOUCH, input_dev->keybit); + input_set_capability(input_dev, EV_KEY, BTN_TOUCH); if (pdata) { input_set_abs_params(input_dev, ABS_X, @@ -595,17 +608,18 @@ struct ad7879 *ad7879_probe(struct device *dev, u8 devid, unsigned int irq, } else { input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0); input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0); + input_set_capability(input_dev, EV_ABS, ABS_PRESSURE); touchscreen_parse_properties(input_dev, false, NULL); if (!input_abs_get_max(input_dev, ABS_PRESSURE)) { dev_err(dev, "Touchscreen pressure is not specified\n"); - return ERR_PTR(-EINVAL); + return -EINVAL; } } err = ad7879_write(ts, AD7879_REG_CTRL2, AD7879_RESET); if (err < 0) { dev_err(dev, "Failed to write %s\n", input_dev->name); - return ERR_PTR(err); + return err; } revid = ad7879_read(ts, AD7879_REG_REVID); @@ -614,7 +628,7 @@ struct ad7879 *ad7879_probe(struct device *dev, u8 devid, unsigned int irq, if (input_dev->id.product != devid) { dev_err(dev, "Failed to probe %s (%x vs %x)\n", input_dev->name, devid, revid); - return ERR_PTR(-ENODEV); + return -ENODEV; } ts->cmd_crtl3 = AD7879_YPLUS_BIT | @@ -639,43 +653,33 @@ struct ad7879 *ad7879_probe(struct device *dev, u8 devid, unsigned int irq, dev_name(dev), ts); if (err) { dev_err(dev, "Failed to request IRQ: %d\n", err); - return ERR_PTR(err); + return err; } __ad7879_disable(ts); err = sysfs_create_group(&dev->kobj, &ad7879_attr_group); if (err) - goto err_out; + return err; - if (pdata) { - err = ad7879_gpio_add(ts, pdata); - if (err) - goto err_remove_attr; - } + err = devm_add_action_or_reset(dev, ad7879_cleanup_sysfs, ts); + if (err) + return err; + + err = ad7879_gpio_add(ts, pdata); + if (err) + return err; err = input_register_device(input_dev); if (err) - goto err_remove_gpio; + return err; - return ts; + dev_set_drvdata(dev, ts); -err_remove_gpio: - ad7879_gpio_remove(ts); -err_remove_attr: - sysfs_remove_group(&dev->kobj, &ad7879_attr_group); -err_out: - return ERR_PTR(err); + return 0; } EXPORT_SYMBOL(ad7879_probe); -void ad7879_remove(struct ad7879 *ts) -{ - ad7879_gpio_remove(ts); - sysfs_remove_group(&ts->dev->kobj, &ad7879_attr_group); -} -EXPORT_SYMBOL(ad7879_remove); - -MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); +MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>"); MODULE_DESCRIPTION("AD7879(-1) touchscreen Driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/input/touchscreen/ad7879.h b/drivers/input/touchscreen/ad7879.h index 6fd13c48d373..7e43066a4b68 100644 --- a/drivers/input/touchscreen/ad7879.h +++ b/drivers/input/touchscreen/ad7879.h @@ -11,20 +11,12 @@ #include <linux/types.h> -struct ad7879; struct device; - -struct ad7879_bus_ops { - u16 bustype; - int (*read)(struct device *dev, u8 reg); - int (*multi_read)(struct device *dev, u8 first_reg, u8 count, u16 *buf); - int (*write)(struct device *dev, u8 reg, u16 val); -}; +struct regmap; extern const struct dev_pm_ops ad7879_pm_ops; -struct ad7879 *ad7879_probe(struct device *dev, u8 devid, unsigned irq, - const struct ad7879_bus_ops *bops); -void ad7879_remove(struct ad7879 *); +int ad7879_probe(struct device *dev, struct regmap *regmap, + int irq, u16 bustype, u8 devid); #endif diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index f5793e3d945f..735a0be1ad95 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -871,7 +871,7 @@ static irqreturn_t ads7846_irq(int irq, void *handle) msecs_to_jiffies(TS_POLL_PERIOD)); } - if (ts->pendown) { + if (ts->pendown && !ts->stopped) { struct input_dev *input = ts->input; input_report_key(input, BTN_TOUCH, 0); diff --git a/drivers/input/touchscreen/ar1021_i2c.c b/drivers/input/touchscreen/ar1021_i2c.c index 6562b17117f7..f9dcbd63e598 100644 --- a/drivers/input/touchscreen/ar1021_i2c.c +++ b/drivers/input/touchscreen/ar1021_i2c.c @@ -1,11 +1,12 @@ /* - * Microchip AR1021 driver for I2C + * Microchip AR1020 and AR1021 driver for I2C * * Author: Christian Gmeiner <christian.gmeiner@gmail.com> * * License: GPLv2 as published by the FSF. */ +#include <linux/bitops.h> #include <linux/module.h> #include <linux/input.h> #include <linux/of.h> @@ -18,6 +19,10 @@ #define AR1021_MAX_X 4095 #define AR1021_MAX_Y 4095 +#define AR1021_CMD 0x55 + +#define AR1021_CMD_ENABLE_TOUCH 0x12 + struct ar1021_i2c { struct i2c_client *client; struct input_dev *input; @@ -33,12 +38,12 @@ static irqreturn_t ar1021_i2c_irq(int irq, void *dev_id) int retval; retval = i2c_master_recv(ar1021->client, - ar1021->data, sizeof(ar1021->data)); + ar1021->data, sizeof(ar1021->data)); if (retval != sizeof(ar1021->data)) goto out; /* sync bit set ? */ - if ((data[0] & 0x80) == 0) + if (!(data[0] & BIT(7))) goto out; button = data[0] & BIT(0); @@ -56,8 +61,19 @@ out: static int ar1021_i2c_open(struct input_dev *dev) { + static const u8 cmd_enable_touch[] = { + AR1021_CMD, + 0x01, /* number of bytes after this */ + AR1021_CMD_ENABLE_TOUCH + }; struct ar1021_i2c *ar1021 = input_get_drvdata(dev); struct i2c_client *client = ar1021->client; + int error; + + error = i2c_master_send(ar1021->client, cmd_enable_touch, + sizeof(cmd_enable_touch)); + if (error < 0) + return error; enable_irq(client->irq); @@ -73,7 +89,7 @@ static void ar1021_i2c_close(struct input_dev *dev) } static int ar1021_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) + const struct i2c_device_id *id) { struct ar1021_i2c *ar1021; struct input_dev *input; @@ -109,7 +125,7 @@ static int ar1021_i2c_probe(struct i2c_client *client, error = devm_request_threaded_irq(&client->dev, client->irq, NULL, ar1021_i2c_irq, - IRQF_TRIGGER_RISING | IRQF_ONESHOT, + IRQF_ONESHOT, "ar1021_i2c", ar1021); if (error) { dev_err(&client->dev, @@ -151,7 +167,7 @@ static int __maybe_unused ar1021_i2c_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(ar1021_i2c_pm, ar1021_i2c_suspend, ar1021_i2c_resume); static const struct i2c_device_id ar1021_i2c_id[] = { - { "MICROCHIP_AR1021_I2C", 0 }, + { "ar1021", 0 }, { }, }; MODULE_DEVICE_TABLE(i2c, ar1021_i2c_id); @@ -175,5 +191,5 @@ static struct i2c_driver ar1021_i2c_driver = { module_i2c_driver(ar1021_i2c_driver); MODULE_AUTHOR("Christian Gmeiner <christian.gmeiner@gmail.com>"); -MODULE_DESCRIPTION("Microchip AR1021 I2C Driver"); +MODULE_DESCRIPTION("Microchip AR1020 and AR1021 I2C Driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c index 16023867b9da..2facad75eb6d 100644 --- a/drivers/input/touchscreen/eeti_ts.c +++ b/drivers/input/touchscreen/eeti_ts.c @@ -31,9 +31,9 @@ #include <linux/interrupt.h> #include <linux/i2c.h> #include <linux/timer.h> -#include <linux/gpio.h> -#include <linux/input/eeti_ts.h> +#include <linux/gpio/consumer.h> #include <linux/slab.h> +#include <asm/unaligned.h> static bool flip_x; module_param(flip_x, bool, 0644); @@ -43,54 +43,31 @@ static bool flip_y; module_param(flip_y, bool, 0644); MODULE_PARM_DESC(flip_y, "flip y coordinate"); -struct eeti_ts_priv { +struct eeti_ts { struct i2c_client *client; struct input_dev *input; - struct work_struct work; - struct mutex mutex; - int irq_gpio, irq, irq_active_high; + struct gpio_desc *attn_gpio; + bool running; }; #define EETI_TS_BITDEPTH (11) #define EETI_MAXVAL ((1 << (EETI_TS_BITDEPTH + 1)) - 1) -#define REPORT_BIT_PRESSED (1 << 0) -#define REPORT_BIT_AD0 (1 << 1) -#define REPORT_BIT_AD1 (1 << 2) -#define REPORT_BIT_HAS_PRESSURE (1 << 6) +#define REPORT_BIT_PRESSED BIT(0) +#define REPORT_BIT_AD0 BIT(1) +#define REPORT_BIT_AD1 BIT(2) +#define REPORT_BIT_HAS_PRESSURE BIT(6) #define REPORT_RES_BITS(v) (((v) >> 1) + EETI_TS_BITDEPTH) -static inline int eeti_ts_irq_active(struct eeti_ts_priv *priv) +static void eeti_ts_report_event(struct eeti_ts *eeti, u8 *buf) { - return gpio_get_value(priv->irq_gpio) == priv->irq_active_high; -} - -static void eeti_ts_read(struct work_struct *work) -{ - char buf[6]; - unsigned int x, y, res, pressed, to = 100; - struct eeti_ts_priv *priv = - container_of(work, struct eeti_ts_priv, work); + unsigned int res; + u16 x, y; - mutex_lock(&priv->mutex); - - while (eeti_ts_irq_active(priv) && --to) - i2c_master_recv(priv->client, buf, sizeof(buf)); - - if (!to) { - dev_err(&priv->client->dev, - "unable to clear IRQ - line stuck?\n"); - goto out; - } - - /* drop non-report packets */ - if (!(buf[0] & 0x80)) - goto out; - - pressed = buf[0] & REPORT_BIT_PRESSED; res = REPORT_RES_BITS(buf[0] & (REPORT_BIT_AD0 | REPORT_BIT_AD1)); - x = buf[2] | (buf[1] << 8); - y = buf[4] | (buf[3] << 8); + + x = get_unaligned_be16(&buf[1]); + y = get_unaligned_be16(&buf[3]); /* fix the range to 11 bits */ x >>= res - EETI_TS_BITDEPTH; @@ -103,65 +80,78 @@ static void eeti_ts_read(struct work_struct *work) y = EETI_MAXVAL - y; if (buf[0] & REPORT_BIT_HAS_PRESSURE) - input_report_abs(priv->input, ABS_PRESSURE, buf[5]); + input_report_abs(eeti->input, ABS_PRESSURE, buf[5]); - input_report_abs(priv->input, ABS_X, x); - input_report_abs(priv->input, ABS_Y, y); - input_report_key(priv->input, BTN_TOUCH, !!pressed); - input_sync(priv->input); - -out: - mutex_unlock(&priv->mutex); + input_report_abs(eeti->input, ABS_X, x); + input_report_abs(eeti->input, ABS_Y, y); + input_report_key(eeti->input, BTN_TOUCH, buf[0] & REPORT_BIT_PRESSED); + input_sync(eeti->input); } static irqreturn_t eeti_ts_isr(int irq, void *dev_id) { - struct eeti_ts_priv *priv = dev_id; + struct eeti_ts *eeti = dev_id; + int len; + int error; + char buf[6]; - /* postpone I2C transactions as we are atomic */ - schedule_work(&priv->work); + do { + len = i2c_master_recv(eeti->client, buf, sizeof(buf)); + if (len != sizeof(buf)) { + error = len < 0 ? len : -EIO; + dev_err(&eeti->client->dev, + "failed to read touchscreen data: %d\n", + error); + break; + } + + if (buf[0] & 0x80) { + /* Motion packet */ + eeti_ts_report_event(eeti, buf); + } + } while (eeti->running && + eeti->attn_gpio && gpiod_get_value_cansleep(eeti->attn_gpio)); return IRQ_HANDLED; } -static void eeti_ts_start(struct eeti_ts_priv *priv) +static void eeti_ts_start(struct eeti_ts *eeti) { - enable_irq(priv->irq); - - /* Read the events once to arm the IRQ */ - eeti_ts_read(&priv->work); + eeti->running = true; + wmb(); + enable_irq(eeti->client->irq); } -static void eeti_ts_stop(struct eeti_ts_priv *priv) +static void eeti_ts_stop(struct eeti_ts *eeti) { - disable_irq(priv->irq); - cancel_work_sync(&priv->work); + eeti->running = false; + wmb(); + disable_irq(eeti->client->irq); } static int eeti_ts_open(struct input_dev *dev) { - struct eeti_ts_priv *priv = input_get_drvdata(dev); + struct eeti_ts *eeti = input_get_drvdata(dev); - eeti_ts_start(priv); + eeti_ts_start(eeti); return 0; } static void eeti_ts_close(struct input_dev *dev) { - struct eeti_ts_priv *priv = input_get_drvdata(dev); + struct eeti_ts *eeti = input_get_drvdata(dev); - eeti_ts_stop(priv); + eeti_ts_stop(eeti); } static int eeti_ts_probe(struct i2c_client *client, - const struct i2c_device_id *idp) + const struct i2c_device_id *idp) { - struct eeti_ts_platform_data *pdata = dev_get_platdata(&client->dev); - struct eeti_ts_priv *priv; + struct device *dev = &client->dev; + struct eeti_ts *eeti; struct input_dev *input; - unsigned int irq_flags; - int err = -ENOMEM; + int error; /* * In contrast to what's described in the datasheet, there seems @@ -170,21 +160,19 @@ static int eeti_ts_probe(struct i2c_client *client, * for interrupts to occur. */ - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) { - dev_err(&client->dev, "failed to allocate driver data\n"); + eeti = devm_kzalloc(dev, sizeof(*eeti), GFP_KERNEL); + if (!eeti) { + dev_err(dev, "failed to allocate driver data\n"); return -ENOMEM; } - mutex_init(&priv->mutex); - input = input_allocate_device(); + input = devm_input_allocate_device(dev); if (!input) { - dev_err(&client->dev, "Failed to allocate input device.\n"); - goto err1; + dev_err(dev, "Failed to allocate input device.\n"); + return -ENOMEM; } - input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); + input_set_capability(input, EV_KEY, BTN_TOUCH); input_set_abs_params(input, ABS_X, 0, EETI_MAXVAL, 0, 0); input_set_abs_params(input, ABS_Y, 0, EETI_MAXVAL, 0, 0); @@ -192,71 +180,38 @@ static int eeti_ts_probe(struct i2c_client *client, input->name = client->name; input->id.bustype = BUS_I2C; - input->dev.parent = &client->dev; input->open = eeti_ts_open; input->close = eeti_ts_close; - priv->client = client; - priv->input = input; - priv->irq_gpio = pdata->irq_gpio; - priv->irq = gpio_to_irq(pdata->irq_gpio); - - err = gpio_request_one(pdata->irq_gpio, GPIOF_IN, client->name); - if (err < 0) - goto err1; - - priv->irq_active_high = pdata->irq_active_high; - - irq_flags = priv->irq_active_high ? - IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING; + eeti->client = client; + eeti->input = input; - INIT_WORK(&priv->work, eeti_ts_read); - i2c_set_clientdata(client, priv); - input_set_drvdata(input, priv); + eeti->attn_gpio = devm_gpiod_get_optional(dev, "attn", GPIOD_IN); + if (IS_ERR(eeti->attn_gpio)) + return PTR_ERR(eeti->attn_gpio); - err = input_register_device(input); - if (err) - goto err2; + i2c_set_clientdata(client, eeti); + input_set_drvdata(input, eeti); - err = request_irq(priv->irq, eeti_ts_isr, irq_flags, - client->name, priv); - if (err) { - dev_err(&client->dev, "Unable to request touchscreen IRQ.\n"); - goto err3; + error = devm_request_threaded_irq(dev, client->irq, + NULL, eeti_ts_isr, + IRQF_ONESHOT, + client->name, eeti); + if (error) { + dev_err(dev, "Unable to request touchscreen IRQ: %d\n", + error); + return error; } /* * Disable the device for now. It will be enabled once the * input device is opened. */ - eeti_ts_stop(priv); - - return 0; - -err3: - input_unregister_device(input); - input = NULL; /* so we dont try to free it below */ -err2: - gpio_free(pdata->irq_gpio); -err1: - input_free_device(input); - kfree(priv); - return err; -} - -static int eeti_ts_remove(struct i2c_client *client) -{ - struct eeti_ts_priv *priv = i2c_get_clientdata(client); - - free_irq(priv->irq, priv); - /* - * eeti_ts_stop() leaves IRQ disabled. We need to re-enable it - * so that device still works if we reload the driver. - */ - enable_irq(priv->irq); + eeti_ts_stop(eeti); - input_unregister_device(priv->input); - kfree(priv); + error = input_register_device(input); + if (error) + return error; return 0; } @@ -264,18 +219,18 @@ static int eeti_ts_remove(struct i2c_client *client) static int __maybe_unused eeti_ts_suspend(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); - struct eeti_ts_priv *priv = i2c_get_clientdata(client); - struct input_dev *input_dev = priv->input; + struct eeti_ts *eeti = i2c_get_clientdata(client); + struct input_dev *input_dev = eeti->input; mutex_lock(&input_dev->mutex); if (input_dev->users) - eeti_ts_stop(priv); + eeti_ts_stop(eeti); mutex_unlock(&input_dev->mutex); if (device_may_wakeup(&client->dev)) - enable_irq_wake(priv->irq); + enable_irq_wake(client->irq); return 0; } @@ -283,16 +238,16 @@ static int __maybe_unused eeti_ts_suspend(struct device *dev) static int __maybe_unused eeti_ts_resume(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); - struct eeti_ts_priv *priv = i2c_get_clientdata(client); - struct input_dev *input_dev = priv->input; + struct eeti_ts *eeti = i2c_get_clientdata(client); + struct input_dev *input_dev = eeti->input; if (device_may_wakeup(&client->dev)) - disable_irq_wake(priv->irq); + disable_irq_wake(client->irq); mutex_lock(&input_dev->mutex); if (input_dev->users) - eeti_ts_start(priv); + eeti_ts_start(eeti); mutex_unlock(&input_dev->mutex); @@ -313,7 +268,6 @@ static struct i2c_driver eeti_ts_driver = { .pm = &eeti_ts_pm, }, .probe = eeti_ts_probe, - .remove = eeti_ts_remove, .id_table = eeti_ts_id, }; diff --git a/drivers/input/touchscreen/imx6ul_tsc.c b/drivers/input/touchscreen/imx6ul_tsc.c index 7098e0a47019..ee82a975bfd2 100644 --- a/drivers/input/touchscreen/imx6ul_tsc.c +++ b/drivers/input/touchscreen/imx6ul_tsc.c @@ -337,11 +337,20 @@ static int imx6ul_tsc_open(struct input_dev *input_dev) dev_err(tsc->dev, "Could not prepare or enable the tsc clock: %d\n", err); - clk_disable_unprepare(tsc->adc_clk); - return err; + goto disable_adc_clk; } - return imx6ul_tsc_init(tsc); + err = imx6ul_tsc_init(tsc); + if (err) + goto disable_tsc_clk; + + return 0; + +disable_tsc_clk: + clk_disable_unprepare(tsc->tsc_clk); +disable_adc_clk: + clk_disable_unprepare(tsc->adc_clk); + return err; } static void imx6ul_tsc_close(struct input_dev *input_dev) diff --git a/drivers/input/touchscreen/lpc32xx_ts.c b/drivers/input/touchscreen/lpc32xx_ts.c index e0baa7de4102..4eb31ec10b18 100644 --- a/drivers/input/touchscreen/lpc32xx_ts.c +++ b/drivers/input/touchscreen/lpc32xx_ts.c @@ -142,11 +142,14 @@ static void lpc32xx_stop_tsc(struct lpc32xx_tsc *tsc) clk_disable_unprepare(tsc->clk); } -static void lpc32xx_setup_tsc(struct lpc32xx_tsc *tsc) +static int lpc32xx_setup_tsc(struct lpc32xx_tsc *tsc) { u32 tmp; + int err; - clk_prepare_enable(tsc->clk); + err = clk_prepare_enable(tsc->clk); + if (err) + return err; tmp = tsc_readl(tsc, LPC32XX_TSC_CON) & ~LPC32XX_TSC_ADCCON_POWER_UP; @@ -184,15 +187,15 @@ static void lpc32xx_setup_tsc(struct lpc32xx_tsc *tsc) /* Enable automatic ts event capture */ tsc_writel(tsc, LPC32XX_TSC_CON, tmp | LPC32XX_TSC_ADCCON_AUTO_EN); + + return 0; } static int lpc32xx_ts_open(struct input_dev *dev) { struct lpc32xx_tsc *tsc = input_get_drvdata(dev); - lpc32xx_setup_tsc(tsc); - - return 0; + return lpc32xx_setup_tsc(tsc); } static void lpc32xx_ts_close(struct input_dev *dev) diff --git a/drivers/input/touchscreen/max11801_ts.c b/drivers/input/touchscreen/max11801_ts.c index a595ae5284e3..72ca3efb5781 100644 --- a/drivers/input/touchscreen/max11801_ts.c +++ b/drivers/input/touchscreen/max11801_ts.c @@ -224,9 +224,16 @@ static const struct i2c_device_id max11801_ts_id[] = { }; MODULE_DEVICE_TABLE(i2c, max11801_ts_id); +static const struct of_device_id max11801_ts_dt_ids[] = { + { .compatible = "maxim,max11801" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, max11801_ts_dt_ids); + static struct i2c_driver max11801_ts_driver = { .driver = { .name = "max11801_ts", + .of_match_table = max11801_ts_dt_ids, }, .id_table = max11801_ts_id, .probe = max11801_ts_probe, diff --git a/drivers/input/touchscreen/melfas_mip4.c b/drivers/input/touchscreen/melfas_mip4.c index 703d7f983d0a..05108c2fea93 100644 --- a/drivers/input/touchscreen/melfas_mip4.c +++ b/drivers/input/touchscreen/melfas_mip4.c @@ -253,10 +253,21 @@ static int mip4_get_fw_version(struct mip4_ts *ts) */ static int mip4_query_device(struct mip4_ts *ts) { + union i2c_smbus_data dummy; int error; u8 cmd[2]; u8 buf[14]; + /* + * Make sure there is something at this address as we do not + * consider subsequent failures as fatal. + */ + if (i2c_smbus_xfer(ts->client->adapter, ts->client->addr, + 0, I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE, &dummy) < 0) { + dev_err(&ts->client->dev, "nothing at this address\n"); + return -ENXIO; + } + /* Product name */ cmd[0] = MIP4_R0_INFO; cmd[1] = MIP4_R1_INFO_PRODUCT_NAME; diff --git a/drivers/input/touchscreen/silead.c b/drivers/input/touchscreen/silead.c index 404830a4a366..813dd68a5c82 100644 --- a/drivers/input/touchscreen/silead.c +++ b/drivers/input/touchscreen/silead.c @@ -580,12 +580,25 @@ static const struct acpi_device_id silead_ts_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, silead_ts_acpi_match); #endif +#ifdef CONFIG_OF +static const struct of_device_id silead_ts_of_match[] = { + { .compatible = "silead,gsl1680" }, + { .compatible = "silead,gsl1688" }, + { .compatible = "silead,gsl3670" }, + { .compatible = "silead,gsl3675" }, + { .compatible = "silead,gsl3692" }, + { }, +}; +MODULE_DEVICE_TABLE(of, silead_ts_of_match); +#endif + static struct i2c_driver silead_ts_driver = { .probe = silead_ts_probe, .id_table = silead_ts_id, .driver = { .name = SILEAD_TS_NAME, .acpi_match_table = ACPI_PTR(silead_ts_acpi_match), + .of_match_table = of_match_ptr(silead_ts_of_match), .pm = &silead_ts_pm, }, }; diff --git a/drivers/input/touchscreen/sur40.c b/drivers/input/touchscreen/sur40.c index 4c0eecae065c..128e5bd74720 100644 --- a/drivers/input/touchscreen/sur40.c +++ b/drivers/input/touchscreen/sur40.c @@ -369,7 +369,7 @@ static void sur40_poll(struct input_polled_dev *polldev) * packet ID will usually increase in the middle of a series * instead of at the end. */ - if (packet_id != header->packet_id) + if (packet_id != le32_to_cpu(header->packet_id)) dev_dbg(sur40->dev, "packet ID mismatch\n"); packet_blobs = result / sizeof(struct sur40_blob); diff --git a/drivers/input/touchscreen/tps6507x-ts.c b/drivers/input/touchscreen/tps6507x-ts.c index a340bfccdfb6..75170a7439b1 100644 --- a/drivers/input/touchscreen/tps6507x-ts.c +++ b/drivers/input/touchscreen/tps6507x-ts.c @@ -226,7 +226,7 @@ static int tps6507x_ts_probe(struct platform_device *pdev) */ init_data = tps_board->tps6507x_ts_init_data; - tsc = kzalloc(sizeof(struct tps6507x_ts), GFP_KERNEL); + tsc = devm_kzalloc(&pdev->dev, sizeof(struct tps6507x_ts), GFP_KERNEL); if (!tsc) { dev_err(tps6507x_dev->dev, "failed to allocate driver data\n"); return -ENOMEM; @@ -240,11 +240,10 @@ static int tps6507x_ts_probe(struct platform_device *pdev) snprintf(tsc->phys, sizeof(tsc->phys), "%s/input0", dev_name(tsc->dev)); - poll_dev = input_allocate_polled_device(); + poll_dev = devm_input_allocate_polled_device(&pdev->dev); if (!poll_dev) { dev_err(tsc->dev, "Failed to allocate polled input device.\n"); - error = -ENOMEM; - goto err_free_mem; + return -ENOMEM; } tsc->poll_dev = poll_dev; @@ -274,32 +273,11 @@ static int tps6507x_ts_probe(struct platform_device *pdev) error = tps6507x_adc_standby(tsc); if (error) - goto err_free_polled_dev; + return error; error = input_register_polled_device(poll_dev); if (error) - goto err_free_polled_dev; - - platform_set_drvdata(pdev, tsc); - - return 0; - -err_free_polled_dev: - input_free_polled_device(poll_dev); -err_free_mem: - kfree(tsc); - return error; -} - -static int tps6507x_ts_remove(struct platform_device *pdev) -{ - struct tps6507x_ts *tsc = platform_get_drvdata(pdev); - struct input_polled_dev *poll_dev = tsc->poll_dev; - - input_unregister_polled_device(poll_dev); - input_free_polled_device(poll_dev); - - kfree(tsc); + return error; return 0; } @@ -309,7 +287,6 @@ static struct platform_driver tps6507x_ts_driver = { .name = "tps6507x-ts", }, .probe = tps6507x_ts_probe, - .remove = tps6507x_ts_remove, }; module_platform_driver(tps6507x_ts_driver); diff --git a/drivers/input/touchscreen/tsc2007.h b/drivers/input/touchscreen/tsc2007.h new file mode 100644 index 000000000000..30fdf5b04a6b --- /dev/null +++ b/drivers/input/touchscreen/tsc2007.h @@ -0,0 +1,101 @@ + +/* + * Copyright (c) 2008 MtekVision Co., Ltd. + * Kwangwoo Lee <kwlee@mtekvision.com> + * + * Using code from: + * - ads7846.c + * Copyright (c) 2005 David Brownell + * Copyright (c) 2006 Nokia Corporation + * - corgi_ts.c + * Copyright (C) 2004-2005 Richard Purdie + * - omap_ts.[hc], ads7846.h, ts_osk.c + * Copyright (C) 2002 MontaVista Software + * Copyright (C) 2004 Texas Instruments + * Copyright (C) 2005 Dirk Behme + * + * 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. + */ + +#ifndef _TSC2007_H +#define _TSC2007_H + +#define TSC2007_MEASURE_TEMP0 (0x0 << 4) +#define TSC2007_MEASURE_AUX (0x2 << 4) +#define TSC2007_MEASURE_TEMP1 (0x4 << 4) +#define TSC2007_ACTIVATE_XN (0x8 << 4) +#define TSC2007_ACTIVATE_YN (0x9 << 4) +#define TSC2007_ACTIVATE_YP_XN (0xa << 4) +#define TSC2007_SETUP (0xb << 4) +#define TSC2007_MEASURE_X (0xc << 4) +#define TSC2007_MEASURE_Y (0xd << 4) +#define TSC2007_MEASURE_Z1 (0xe << 4) +#define TSC2007_MEASURE_Z2 (0xf << 4) + +#define TSC2007_POWER_OFF_IRQ_EN (0x0 << 2) +#define TSC2007_ADC_ON_IRQ_DIS0 (0x1 << 2) +#define TSC2007_ADC_OFF_IRQ_EN (0x2 << 2) +#define TSC2007_ADC_ON_IRQ_DIS1 (0x3 << 2) + +#define TSC2007_12BIT (0x0 << 1) +#define TSC2007_8BIT (0x1 << 1) + +#define MAX_12BIT ((1 << 12) - 1) + +#define ADC_ON_12BIT (TSC2007_12BIT | TSC2007_ADC_ON_IRQ_DIS0) + +#define READ_Y (ADC_ON_12BIT | TSC2007_MEASURE_Y) +#define READ_Z1 (ADC_ON_12BIT | TSC2007_MEASURE_Z1) +#define READ_Z2 (ADC_ON_12BIT | TSC2007_MEASURE_Z2) +#define READ_X (ADC_ON_12BIT | TSC2007_MEASURE_X) +#define PWRDOWN (TSC2007_12BIT | TSC2007_POWER_OFF_IRQ_EN) + +struct ts_event { + u16 x; + u16 y; + u16 z1, z2; +}; + +struct tsc2007 { + struct input_dev *input; + char phys[32]; + + struct i2c_client *client; + + u16 model; + u16 x_plate_ohms; + u16 max_rt; + unsigned long poll_period; /* in jiffies */ + int fuzzx; + int fuzzy; + int fuzzz; + + unsigned int gpio; + int irq; + + wait_queue_head_t wait; + bool stopped; + + int (*get_pendown_state)(struct device *); + void (*clear_penirq)(void); + + struct mutex mlock; +}; + +int tsc2007_xfer(struct tsc2007 *tsc, u8 cmd); +u32 tsc2007_calculate_resistance(struct tsc2007 *tsc, struct ts_event *tc); +bool tsc2007_is_pen_down(struct tsc2007 *ts); + +#if IS_ENABLED(CONFIG_TOUCHSCREEN_TSC2007_IIO) +/* defined in tsc2007_iio.c */ +int tsc2007_iio_configure(struct tsc2007 *ts); +#else +static inline int tsc2007_iio_configure(struct tsc2007 *ts) +{ + return 0; +} +#endif /* CONFIG_TOUCHSCREEN_TSC2007_IIO */ + +#endif /* _TSC2007_H */ diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007_core.c index 5d0cd51c6f41..fc7384936011 100644 --- a/drivers/input/touchscreen/tsc2007.c +++ b/drivers/input/touchscreen/tsc2007_core.c @@ -27,70 +27,10 @@ #include <linux/i2c.h> #include <linux/i2c/tsc2007.h> #include <linux/of_device.h> -#include <linux/of.h> #include <linux/of_gpio.h> +#include "tsc2007.h" -#define TSC2007_MEASURE_TEMP0 (0x0 << 4) -#define TSC2007_MEASURE_AUX (0x2 << 4) -#define TSC2007_MEASURE_TEMP1 (0x4 << 4) -#define TSC2007_ACTIVATE_XN (0x8 << 4) -#define TSC2007_ACTIVATE_YN (0x9 << 4) -#define TSC2007_ACTIVATE_YP_XN (0xa << 4) -#define TSC2007_SETUP (0xb << 4) -#define TSC2007_MEASURE_X (0xc << 4) -#define TSC2007_MEASURE_Y (0xd << 4) -#define TSC2007_MEASURE_Z1 (0xe << 4) -#define TSC2007_MEASURE_Z2 (0xf << 4) - -#define TSC2007_POWER_OFF_IRQ_EN (0x0 << 2) -#define TSC2007_ADC_ON_IRQ_DIS0 (0x1 << 2) -#define TSC2007_ADC_OFF_IRQ_EN (0x2 << 2) -#define TSC2007_ADC_ON_IRQ_DIS1 (0x3 << 2) - -#define TSC2007_12BIT (0x0 << 1) -#define TSC2007_8BIT (0x1 << 1) - -#define MAX_12BIT ((1 << 12) - 1) - -#define ADC_ON_12BIT (TSC2007_12BIT | TSC2007_ADC_ON_IRQ_DIS0) - -#define READ_Y (ADC_ON_12BIT | TSC2007_MEASURE_Y) -#define READ_Z1 (ADC_ON_12BIT | TSC2007_MEASURE_Z1) -#define READ_Z2 (ADC_ON_12BIT | TSC2007_MEASURE_Z2) -#define READ_X (ADC_ON_12BIT | TSC2007_MEASURE_X) -#define PWRDOWN (TSC2007_12BIT | TSC2007_POWER_OFF_IRQ_EN) - -struct ts_event { - u16 x; - u16 y; - u16 z1, z2; -}; - -struct tsc2007 { - struct input_dev *input; - char phys[32]; - - struct i2c_client *client; - - u16 model; - u16 x_plate_ohms; - u16 max_rt; - unsigned long poll_period; /* in jiffies */ - int fuzzx; - int fuzzy; - int fuzzz; - - unsigned gpio; - int irq; - - wait_queue_head_t wait; - bool stopped; - - int (*get_pendown_state)(struct device *); - void (*clear_penirq)(void); -}; - -static inline int tsc2007_xfer(struct tsc2007 *tsc, u8 cmd) +int tsc2007_xfer(struct tsc2007 *tsc, u8 cmd) { s32 data; u16 val; @@ -128,7 +68,7 @@ static void tsc2007_read_values(struct tsc2007 *tsc, struct ts_event *tc) tsc2007_xfer(tsc, PWRDOWN); } -static u32 tsc2007_calculate_pressure(struct tsc2007 *tsc, struct ts_event *tc) +u32 tsc2007_calculate_resistance(struct tsc2007 *tsc, struct ts_event *tc) { u32 rt = 0; @@ -137,7 +77,7 @@ static u32 tsc2007_calculate_pressure(struct tsc2007 *tsc, struct ts_event *tc) tc->x = 0; if (likely(tc->x && tc->z1)) { - /* compute touch pressure resistance using equation #1 */ + /* compute touch resistance using equation #1 */ rt = tc->z2 - tc->z1; rt *= tc->x; rt *= tsc->x_plate_ohms; @@ -148,7 +88,7 @@ static u32 tsc2007_calculate_pressure(struct tsc2007 *tsc, struct ts_event *tc) return rt; } -static bool tsc2007_is_pen_down(struct tsc2007 *ts) +bool tsc2007_is_pen_down(struct tsc2007 *ts) { /* * NOTE: We can't rely on the pressure to determine the pen down @@ -180,9 +120,12 @@ static irqreturn_t tsc2007_soft_irq(int irq, void *handle) while (!ts->stopped && tsc2007_is_pen_down(ts)) { /* pen is down, continue with the measurement */ + + mutex_lock(&ts->mlock); tsc2007_read_values(ts, &tc); + mutex_unlock(&ts->mlock); - rt = tsc2007_calculate_pressure(ts, &tc); + rt = tsc2007_calculate_resistance(ts, &tc); if (!rt && !ts->get_pendown_state) { /* @@ -195,9 +138,11 @@ static irqreturn_t tsc2007_soft_irq(int irq, void *handle) if (rt <= ts->max_rt) { dev_dbg(&ts->client->dev, - "DOWN point(%4d,%4d), pressure (%4u)\n", + "DOWN point(%4d,%4d), resistance (%4u)\n", tc.x, tc.y, rt); + 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); @@ -375,7 +320,8 @@ static void tsc2007_call_exit_platform_hw(void *data) static int tsc2007_probe(struct i2c_client *client, const struct i2c_device_id *id) { - const struct tsc2007_platform_data *pdata = dev_get_platdata(&client->dev); + const struct tsc2007_platform_data *pdata = + dev_get_platdata(&client->dev); struct tsc2007 *ts; struct input_dev *input_dev; int err; @@ -404,7 +350,9 @@ static int tsc2007_probe(struct i2c_client *client, ts->client = client; ts->irq = client->irq; ts->input = input_dev; + init_waitqueue_head(&ts->wait); + mutex_init(&ts->mlock); snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&client->dev)); @@ -418,8 +366,7 @@ static int tsc2007_probe(struct i2c_client *client, input_set_drvdata(input_dev, ts); - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); + input_set_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); @@ -455,6 +402,14 @@ static int tsc2007_probe(struct i2c_client *client, tsc2007_stop(ts); + /* power down the chip (TSC2007_SETUP does not ACK on I2C) */ + err = tsc2007_xfer(ts, PWRDOWN); + if (err < 0) { + dev_err(&client->dev, + "Failed to setup chip: %d\n", err); + return err; /* chip does not respond */ + } + err = input_register_device(input_dev); if (err) { dev_err(&client->dev, @@ -462,6 +417,13 @@ static int tsc2007_probe(struct i2c_client *client, return err; } + err = tsc2007_iio_configure(ts); + if (err) { + dev_err(&client->dev, + "Failed to register with IIO: %d\n", err); + return err; + } + return 0; } diff --git a/drivers/input/touchscreen/tsc2007_iio.c b/drivers/input/touchscreen/tsc2007_iio.c new file mode 100644 index 000000000000..27b25a9fce83 --- /dev/null +++ b/drivers/input/touchscreen/tsc2007_iio.c @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2016 Golden Delicious Comp. GmbH&Co. KG + * Nikolaus Schaller <hns@goldelico.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. + */ + +#include <linux/i2c.h> +#include <linux/iio/iio.h> +#include "tsc2007.h" + +struct tsc2007_iio { + struct tsc2007 *ts; +}; + +#define TSC2007_CHAN_IIO(_chan, _name, _type, _chan_info) \ +{ \ + .datasheet_name = _name, \ + .type = _type, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(_chan_info), \ + .indexed = 1, \ + .channel = _chan, \ +} + +static const struct iio_chan_spec tsc2007_iio_channel[] = { + TSC2007_CHAN_IIO(0, "x", IIO_VOLTAGE, IIO_CHAN_INFO_RAW), + TSC2007_CHAN_IIO(1, "y", IIO_VOLTAGE, IIO_CHAN_INFO_RAW), + TSC2007_CHAN_IIO(2, "z1", IIO_VOLTAGE, IIO_CHAN_INFO_RAW), + TSC2007_CHAN_IIO(3, "z2", IIO_VOLTAGE, IIO_CHAN_INFO_RAW), + TSC2007_CHAN_IIO(4, "adc", IIO_VOLTAGE, IIO_CHAN_INFO_RAW), + TSC2007_CHAN_IIO(5, "rt", IIO_VOLTAGE, IIO_CHAN_INFO_RAW), /* Ohms? */ + TSC2007_CHAN_IIO(6, "pen", IIO_PRESSURE, IIO_CHAN_INFO_RAW), + TSC2007_CHAN_IIO(7, "temp0", IIO_TEMP, IIO_CHAN_INFO_RAW), + TSC2007_CHAN_IIO(8, "temp1", IIO_TEMP, IIO_CHAN_INFO_RAW), +}; + +static int tsc2007_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + 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; + + if (mask != IIO_CHAN_INFO_RAW) + return -EINVAL; + + mutex_lock(&tsc->mlock); + + switch (chan->channel) { + case 0: + *val = tsc2007_xfer(tsc, READ_X); + break; + case 1: + *val = tsc2007_xfer(tsc, READ_Y); + break; + case 2: + *val = tsc2007_xfer(tsc, READ_Z1); + break; + case 3: + *val = tsc2007_xfer(tsc, READ_Z2); + break; + case 4: + *val = tsc2007_xfer(tsc, (ADC_ON_12BIT | TSC2007_MEASURE_AUX)); + break; + case 5: { + struct ts_event tc; + + tc.x = tsc2007_xfer(tsc, READ_X); + tc.z1 = tsc2007_xfer(tsc, READ_Z1); + tc.z2 = tsc2007_xfer(tsc, READ_Z2); + *val = tsc2007_calculate_resistance(tsc, &tc); + break; + } + case 6: + *val = tsc2007_is_pen_down(tsc); + break; + case 7: + *val = tsc2007_xfer(tsc, + (ADC_ON_12BIT | TSC2007_MEASURE_TEMP0)); + break; + case 8: + *val = tsc2007_xfer(tsc, + (ADC_ON_12BIT | TSC2007_MEASURE_TEMP1)); + break; + } + + /* Prepare for next touch reading - power down ADC, enable PENIRQ */ + tsc2007_xfer(tsc, PWRDOWN); + + mutex_unlock(&tsc->mlock); + + ret = IIO_VAL_INT; + + return ret; +} + +static const struct iio_info tsc2007_iio_info = { + .read_raw = tsc2007_read_raw, + .driver_module = THIS_MODULE, +}; + +int tsc2007_iio_configure(struct tsc2007 *ts) +{ + struct iio_dev *indio_dev; + struct tsc2007_iio *iio; + int error; + + indio_dev = devm_iio_device_alloc(&ts->client->dev, sizeof(*iio)); + if (!indio_dev) { + dev_err(&ts->client->dev, "iio_device_alloc failed\n"); + return -ENOMEM; + } + + iio = iio_priv(indio_dev); + iio->ts = ts; + + indio_dev->name = "tsc2007"; + indio_dev->dev.parent = &ts->client->dev; + indio_dev->info = &tsc2007_iio_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = tsc2007_iio_channel; + indio_dev->num_channels = ARRAY_SIZE(tsc2007_iio_channel); + + error = devm_iio_device_register(&ts->client->dev, indio_dev); + if (error) { + dev_err(&ts->client->dev, + "iio_device_register() failed: %d\n", error); + return error; + } + + return 0; +} |