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
  ...
This commit is contained in:
Linus Torvalds
2017-05-03 12:38:20 -07:00
129 changed files with 7664 additions and 5446 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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);
regmap = devm_regmap_init_i2c(client, &ad7879_i2c_regmap_config);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
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);
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");

View File

@@ -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().
*/
#define AD7879_CMD_MAGIC 0xE0
#define AD7879_CMD_READ BIT(2)
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);
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;
}
regmap = devm_regmap_init_spi(spi, &ad7879_spi_regmap_config);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
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);
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");

View File

@@ -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");

View File

@@ -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

View File

@@ -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);

View File

@@ -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");

View File

@@ -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;
}
unsigned int res;
u16 x, y;
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);
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);
eeti->client = client;
eeti->input = input;
err = gpio_request_one(pdata->irq_gpio, GPIOF_IN, client->name);
if (err < 0)
goto err1;
eeti->attn_gpio = devm_gpiod_get_optional(dev, "attn", GPIOD_IN);
if (IS_ERR(eeti->attn_gpio))
return PTR_ERR(eeti->attn_gpio);
priv->irq_active_high = pdata->irq_active_high;
i2c_set_clientdata(client, eeti);
input_set_drvdata(input, eeti);
irq_flags = priv->irq_active_high ?
IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING;
INIT_WORK(&priv->work, eeti_ts_read);
i2c_set_clientdata(client, priv);
input_set_drvdata(input, priv);
err = input_register_device(input);
if (err)
goto err2;
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);
eeti_ts_stop(eeti);
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);
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,
};

View File

@@ -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)

View File

@@ -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)

View File

@@ -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,

View File

@@ -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;

View File

@@ -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,
},
};

View File

@@ -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);

View File

@@ -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);

View File

@@ -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 */

View File

@@ -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 */
tsc2007_read_values(ts, &tc);
rt = tsc2007_calculate_pressure(ts, &tc);
mutex_lock(&ts->mlock);
tsc2007_read_values(ts, &tc);
mutex_unlock(&ts->mlock);
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;
}

View File

@@ -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;
}