summaryrefslogtreecommitdiff
path: root/drivers/input
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-07-13 18:05:13 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-13 18:05:13 -0700
commit18fb38e2f58ff7a66e30cbb71af81425edf1c9a1 (patch)
tree8ff2cc5b0d1a11c87a0e2576d6fe863b87faf69a /drivers/input
parentbe9c6d9169705504296bdb42ffec8f406691d99f (diff)
parent88ce3c3ca3df754e8a2a63b01c38bd1667fcae70 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull second round of input updates from Dmitry Torokhov: "An update to Elantech driver to support hardware v7, fix to the new cyttsp4 driver to use proper addressing, ads7846 device tree support and nspire-keypad got a small cleanup." * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: Input: nspire-keypad - replace magic offset with define Input: elantech - fix for newer hardware versions (v7) Input: cyttsp4 - use 16bit address for I2C/SPI communication Input: ads7846 - add device tree bindings Input: ads7846 - make sure we do not change platform data
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/keyboard/nspire-keypad.c2
-rw-r--r--drivers/input/mouse/elantech.c17
-rw-r--r--drivers/input/touchscreen/ads7846.c123
-rw-r--r--drivers/input/touchscreen/cyttsp4_core.h12
-rw-r--r--drivers/input/touchscreen/cyttsp4_spi.c20
-rw-r--r--drivers/input/touchscreen/cyttsp_core.h8
-rw-r--r--drivers/input/touchscreen/cyttsp_i2c_common.c30
-rw-r--r--drivers/input/touchscreen/cyttsp_spi.c6
8 files changed, 162 insertions, 56 deletions
diff --git a/drivers/input/keyboard/nspire-keypad.c b/drivers/input/keyboard/nspire-keypad.c
index e0a1339e40e6..20d872d6f603 100644
--- a/drivers/input/keyboard/nspire-keypad.c
+++ b/drivers/input/keyboard/nspire-keypad.c
@@ -122,7 +122,7 @@ static int nspire_keypad_chip_init(struct nspire_keypad *keypad)
/* Enable interrupts */
keypad->int_mask = 1 << 1;
- writel(keypad->int_mask, keypad->reg_base + 0xc);
+ writel(keypad->int_mask, keypad->reg_base + KEYPAD_INTMSK);
/* Disable GPIO interrupts to prevent hanging on touchpad */
/* Possibly used to detect touchpad events */
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index 1e8e42fb03a4..57b2637e153a 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -694,18 +694,18 @@ static int elantech_packet_check_v3(struct psmouse *psmouse)
static int elantech_packet_check_v4(struct psmouse *psmouse)
{
unsigned char *packet = psmouse->packet;
+ unsigned char packet_type = packet[3] & 0x03;
- if ((packet[0] & 0x0c) == 0x04 &&
- (packet[3] & 0x1f) == 0x11)
+ switch (packet_type) {
+ case 0:
+ return PACKET_V4_STATUS;
+
+ case 1:
return PACKET_V4_HEAD;
- if ((packet[0] & 0x0c) == 0x04 &&
- (packet[3] & 0x1f) == 0x12)
+ case 2:
return PACKET_V4_MOTION;
-
- if ((packet[0] & 0x0c) == 0x04 &&
- (packet[3] & 0x1f) == 0x10)
- return PACKET_V4_STATUS;
+ }
return PACKET_UNKNOWN;
}
@@ -1282,6 +1282,7 @@ static int elantech_set_properties(struct elantech_data *etd)
etd->hw_version = 3;
break;
case 6:
+ case 7:
etd->hw_version = 4;
break;
default:
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index 84ccf140c1bb..ea195360747e 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -27,6 +27,9 @@
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/pm.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/of_device.h>
#include <linux/gpio.h>
#include <linux/spi/spi.h>
#include <linux/spi/ads7846.h>
@@ -961,9 +964,9 @@ static int ads7846_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(ads7846_pm, ads7846_suspend, ads7846_resume);
static int ads7846_setup_pendown(struct spi_device *spi,
- struct ads7846 *ts)
+ struct ads7846 *ts,
+ const struct ads7846_platform_data *pdata)
{
- struct ads7846_platform_data *pdata = spi->dev.platform_data;
int err;
/*
@@ -1003,7 +1006,7 @@ static int ads7846_setup_pendown(struct spi_device *spi,
* use formula #2 for pressure, not #3.
*/
static void ads7846_setup_spi_msg(struct ads7846 *ts,
- const struct ads7846_platform_data *pdata)
+ const struct ads7846_platform_data *pdata)
{
struct spi_message *m = &ts->msg[0];
struct spi_transfer *x = ts->xfer;
@@ -1201,33 +1204,107 @@ static void ads7846_setup_spi_msg(struct ads7846 *ts,
spi_message_add_tail(x, m);
}
+#ifdef CONFIG_OF
+static const struct of_device_id ads7846_dt_ids[] = {
+ { .compatible = "ti,tsc2046", .data = (void *) 7846 },
+ { .compatible = "ti,ads7843", .data = (void *) 7843 },
+ { .compatible = "ti,ads7845", .data = (void *) 7845 },
+ { .compatible = "ti,ads7846", .data = (void *) 7846 },
+ { .compatible = "ti,ads7873", .data = (void *) 7873 },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ads7846_dt_ids);
+
+static const struct ads7846_platform_data *ads7846_probe_dt(struct device *dev)
+{
+ struct ads7846_platform_data *pdata;
+ struct device_node *node = dev->of_node;
+ const struct of_device_id *match;
+
+ if (!node) {
+ dev_err(dev, "Device does not have associated DT data\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ match = of_match_device(ads7846_dt_ids, dev);
+ if (!match) {
+ dev_err(dev, "Unknown device model\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return ERR_PTR(-ENOMEM);
+
+ pdata->model = (unsigned long)match->data;
+
+ of_property_read_u16(node, "ti,vref-delay-usecs",
+ &pdata->vref_delay_usecs);
+ of_property_read_u16(node, "ti,vref-mv", &pdata->vref_mv);
+ pdata->keep_vref_on = of_property_read_bool(node, "ti,keep-vref-on");
+
+ pdata->swap_xy = of_property_read_bool(node, "ti,swap-xy");
+
+ of_property_read_u16(node, "ti,settle-delay-usec",
+ &pdata->settle_delay_usecs);
+ of_property_read_u16(node, "ti,penirq-recheck-delay-usecs",
+ &pdata->penirq_recheck_delay_usecs);
+
+ of_property_read_u16(node, "ti,x-plate-ohms", &pdata->x_plate_ohms);
+ of_property_read_u16(node, "ti,y-plate-ohms", &pdata->y_plate_ohms);
+
+ of_property_read_u16(node, "ti,x-min", &pdata->x_min);
+ of_property_read_u16(node, "ti,y-min", &pdata->y_min);
+ of_property_read_u16(node, "ti,x-max", &pdata->x_max);
+ of_property_read_u16(node, "ti,y-max", &pdata->y_max);
+
+ of_property_read_u16(node, "ti,pressure-min", &pdata->pressure_min);
+ of_property_read_u16(node, "ti,pressure-max", &pdata->pressure_max);
+
+ of_property_read_u16(node, "ti,debounce-max", &pdata->debounce_max);
+ of_property_read_u16(node, "ti,debounce-tol", &pdata->debounce_tol);
+ of_property_read_u16(node, "ti,debounce-rep", &pdata->debounce_rep);
+
+ of_property_read_u32(node, "ti,pendown-gpio-debounce",
+ &pdata->gpio_pendown_debounce);
+
+ pdata->wakeup = of_property_read_bool(node, "linux,wakeup");
+
+ pdata->gpio_pendown = of_get_named_gpio(dev->of_node, "pendown-gpio", 0);
+
+ return pdata;
+}
+#else
+static const struct ads7846_platform_data *ads7846_probe_dt(struct device *dev)
+{
+ dev_err(dev, "no platform data defined\n");
+ return ERR_PTR(-EINVAL);
+}
+#endif
+
static int ads7846_probe(struct spi_device *spi)
{
+ const struct ads7846_platform_data *pdata;
struct ads7846 *ts;
struct ads7846_packet *packet;
struct input_dev *input_dev;
- struct ads7846_platform_data *pdata = spi->dev.platform_data;
unsigned long irq_flags;
int err;
if (!spi->irq) {
dev_dbg(&spi->dev, "no IRQ?\n");
- return -ENODEV;
- }
-
- if (!pdata) {
- dev_dbg(&spi->dev, "no platform data?\n");
- return -ENODEV;
+ return -EINVAL;
}
/* don't exceed max specified sample rate */
if (spi->max_speed_hz > (125000 * SAMPLE_BITS)) {
- dev_dbg(&spi->dev, "f(sample) %d KHz?\n",
+ dev_err(&spi->dev, "f(sample) %d KHz?\n",
(spi->max_speed_hz/SAMPLE_BITS)/1000);
return -EINVAL;
}
- /* We'd set TX word size 8 bits and RX word size to 13 bits ... except
+ /*
+ * We'd set TX word size 8 bits and RX word size to 13 bits ... except
* that even if the hardware can do that, the SPI controller driver
* may not. So we stick to very-portable 8 bit words, both RX and TX.
*/
@@ -1250,17 +1327,25 @@ static int ads7846_probe(struct spi_device *spi)
ts->packet = packet;
ts->spi = spi;
ts->input = input_dev;
- ts->vref_mv = pdata->vref_mv;
- ts->swap_xy = pdata->swap_xy;
mutex_init(&ts->lock);
init_waitqueue_head(&ts->wait);
+ pdata = dev_get_platdata(&spi->dev);
+ if (!pdata) {
+ pdata = ads7846_probe_dt(&spi->dev);
+ if (IS_ERR(pdata))
+ return PTR_ERR(pdata);
+ }
+
ts->model = pdata->model ? : 7846;
ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100;
ts->x_plate_ohms = pdata->x_plate_ohms ? : 400;
ts->pressure_max = pdata->pressure_max ? : ~0;
+ ts->vref_mv = pdata->vref_mv;
+ ts->swap_xy = pdata->swap_xy;
+
if (pdata->filter != NULL) {
if (pdata->filter_init != NULL) {
err = pdata->filter_init(pdata, &ts->filter_data);
@@ -1281,7 +1366,7 @@ static int ads7846_probe(struct spi_device *spi)
ts->filter = ads7846_no_filter;
}
- err = ads7846_setup_pendown(spi, ts);
+ err = ads7846_setup_pendown(spi, ts, pdata);
if (err)
goto err_cleanup_filter;
@@ -1370,6 +1455,13 @@ static int ads7846_probe(struct spi_device *spi)
device_init_wakeup(&spi->dev, pdata->wakeup);
+ /*
+ * If device does not carry platform data we must have allocated it
+ * when parsing DT data.
+ */
+ if (!dev_get_platdata(&spi->dev))
+ devm_kfree(&spi->dev, (void *)pdata);
+
return 0;
err_remove_attr_group:
@@ -1437,6 +1529,7 @@ static struct spi_driver ads7846_driver = {
.name = "ads7846",
.owner = THIS_MODULE,
.pm = &ads7846_pm,
+ .of_match_table = of_match_ptr(ads7846_dt_ids),
},
.probe = ads7846_probe,
.remove = ads7846_remove,
diff --git a/drivers/input/touchscreen/cyttsp4_core.h b/drivers/input/touchscreen/cyttsp4_core.h
index 86a254354136..8e0d4d490b20 100644
--- a/drivers/input/touchscreen/cyttsp4_core.h
+++ b/drivers/input/touchscreen/cyttsp4_core.h
@@ -369,9 +369,9 @@ struct cyttsp4 {
struct cyttsp4_bus_ops {
u16 bustype;
- int (*write)(struct device *dev, u8 *xfer_buf, u8 addr, u8 length,
+ int (*write)(struct device *dev, u8 *xfer_buf, u16 addr, u8 length,
const void *values);
- int (*read)(struct device *dev, u8 *xfer_buf, u8 addr, u8 length,
+ int (*read)(struct device *dev, u8 *xfer_buf, u16 addr, u8 length,
void *values);
};
@@ -448,13 +448,13 @@ enum cyttsp4_event_id {
/* y-axis, 0:origin is on top side of panel, 1: bottom */
#define CY_PCFG_ORIGIN_Y_MASK 0x80
-static inline int cyttsp4_adap_read(struct cyttsp4 *ts, u8 addr, int size,
+static inline int cyttsp4_adap_read(struct cyttsp4 *ts, u16 addr, int size,
void *buf)
{
return ts->bus_ops->read(ts->dev, ts->xfer_buf, addr, size, buf);
}
-static inline int cyttsp4_adap_write(struct cyttsp4 *ts, u8 addr, int size,
+static inline int cyttsp4_adap_write(struct cyttsp4 *ts, u16 addr, int size,
const void *buf)
{
return ts->bus_ops->write(ts->dev, ts->xfer_buf, addr, size, buf);
@@ -463,9 +463,9 @@ static inline int cyttsp4_adap_write(struct cyttsp4 *ts, u8 addr, int size,
extern struct cyttsp4 *cyttsp4_probe(const struct cyttsp4_bus_ops *ops,
struct device *dev, u16 irq, size_t xfer_buf_size);
extern int cyttsp4_remove(struct cyttsp4 *ts);
-int cyttsp_i2c_write_block_data(struct device *dev, u8 *xfer_buf, u8 addr,
+int cyttsp_i2c_write_block_data(struct device *dev, u8 *xfer_buf, u16 addr,
u8 length, const void *values);
-int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf, u8 addr,
+int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf, u16 addr,
u8 length, void *values);
extern const struct dev_pm_ops cyttsp4_pm_ops;
diff --git a/drivers/input/touchscreen/cyttsp4_spi.c b/drivers/input/touchscreen/cyttsp4_spi.c
index f8f891bead34..a71e1141d638 100644
--- a/drivers/input/touchscreen/cyttsp4_spi.c
+++ b/drivers/input/touchscreen/cyttsp4_spi.c
@@ -44,7 +44,7 @@
#define CY_SPI_DATA_BUF_SIZE (CY_SPI_CMD_BYTES + CY_SPI_DATA_SIZE)
static int cyttsp_spi_xfer(struct device *dev, u8 *xfer_buf,
- u8 op, u8 reg, u8 *buf, int length)
+ u8 op, u16 reg, u8 *buf, int length)
{
struct spi_device *spi = to_spi_device(dev);
struct spi_message msg;
@@ -63,14 +63,12 @@ static int cyttsp_spi_xfer(struct device *dev, u8 *xfer_buf,
memset(wr_buf, 0, CY_SPI_DATA_BUF_SIZE);
memset(rd_buf, 0, CY_SPI_CMD_BYTES);
- if (reg > 255)
- wr_buf[0] = op + CY_SPI_A8_BIT;
- else
- wr_buf[0] = op;
- if (op == CY_SPI_WR_OP)
- wr_buf[1] = reg % 256;
- if (op == CY_SPI_WR_OP && length > 0)
- memcpy(wr_buf + CY_SPI_CMD_BYTES, buf, length);
+ wr_buf[0] = op + (((reg >> 8) & 0x1) ? CY_SPI_A8_BIT : 0);
+ if (op == CY_SPI_WR_OP) {
+ wr_buf[1] = reg & 0xFF;
+ if (length > 0)
+ memcpy(wr_buf + CY_SPI_CMD_BYTES, buf, length);
+ }
memset(xfer, 0, sizeof(xfer));
spi_message_init(&msg);
@@ -130,7 +128,7 @@ static int cyttsp_spi_xfer(struct device *dev, u8 *xfer_buf,
}
static int cyttsp_spi_read_block_data(struct device *dev, u8 *xfer_buf,
- u8 addr, u8 length, void *data)
+ u16 addr, u8 length, void *data)
{
int rc;
@@ -143,7 +141,7 @@ static int cyttsp_spi_read_block_data(struct device *dev, u8 *xfer_buf,
}
static int cyttsp_spi_write_block_data(struct device *dev, u8 *xfer_buf,
- u8 addr, u8 length, const void *data)
+ u16 addr, u8 length, const void *data)
{
return cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_WR_OP, addr, (void *)data,
length);
diff --git a/drivers/input/touchscreen/cyttsp_core.h b/drivers/input/touchscreen/cyttsp_core.h
index 0cf564a79fb5..07074110a902 100644
--- a/drivers/input/touchscreen/cyttsp_core.h
+++ b/drivers/input/touchscreen/cyttsp_core.h
@@ -112,9 +112,9 @@ struct cyttsp;
struct cyttsp_bus_ops {
u16 bustype;
- int (*write)(struct device *dev, u8 *xfer_buf, u8 addr, u8 length,
+ int (*write)(struct device *dev, u8 *xfer_buf, u16 addr, u8 length,
const void *values);
- int (*read)(struct device *dev, u8 *xfer_buf, u8 addr, u8 length,
+ int (*read)(struct device *dev, u8 *xfer_buf, u16 addr, u8 length,
void *values);
};
@@ -145,9 +145,9 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops,
struct device *dev, int irq, size_t xfer_buf_size);
void cyttsp_remove(struct cyttsp *ts);
-int cyttsp_i2c_write_block_data(struct device *dev, u8 *xfer_buf, u8 addr,
+int cyttsp_i2c_write_block_data(struct device *dev, u8 *xfer_buf, u16 addr,
u8 length, const void *values);
-int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf, u8 addr,
+int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf, u16 addr,
u8 length, void *values);
extern const struct dev_pm_ops cyttsp_pm_ops;
diff --git a/drivers/input/touchscreen/cyttsp_i2c_common.c b/drivers/input/touchscreen/cyttsp_i2c_common.c
index 07c553fbcef2..1d7b6f154168 100644
--- a/drivers/input/touchscreen/cyttsp_i2c_common.c
+++ b/drivers/input/touchscreen/cyttsp_i2c_common.c
@@ -32,18 +32,20 @@
#include <linux/types.h>
int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf,
- u8 addr, u8 length, void *values)
+ u16 addr, u8 length, void *values)
{
struct i2c_client *client = to_i2c_client(dev);
+ u8 client_addr = client->addr | ((addr >> 8) & 0x1);
+ u8 addr_lo = addr & 0xFF;
struct i2c_msg msgs[] = {
{
- .addr = client->addr,
+ .addr = client_addr,
.flags = 0,
.len = 1,
- .buf = &addr,
+ .buf = &addr_lo,
},
{
- .addr = client->addr,
+ .addr = client_addr,
.flags = I2C_M_RD,
.len = length,
.buf = values,
@@ -60,17 +62,29 @@ int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf,
EXPORT_SYMBOL_GPL(cyttsp_i2c_read_block_data);
int cyttsp_i2c_write_block_data(struct device *dev, u8 *xfer_buf,
- u8 addr, u8 length, const void *values)
+ u16 addr, u8 length, const void *values)
{
struct i2c_client *client = to_i2c_client(dev);
+ u8 client_addr = client->addr | ((addr >> 8) & 0x1);
+ u8 addr_lo = addr & 0xFF;
+ struct i2c_msg msgs[] = {
+ {
+ .addr = client_addr,
+ .flags = 0,
+ .len = length + 1,
+ .buf = xfer_buf,
+ },
+ };
int retval;
- xfer_buf[0] = addr;
+ xfer_buf[0] = addr_lo;
memcpy(&xfer_buf[1], values, length);
- retval = i2c_master_send(client, xfer_buf, length + 1);
+ retval = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+ if (retval < 0)
+ return retval;
- return retval < 0 ? retval : 0;
+ return retval != ARRAY_SIZE(msgs) ? -EIO : 0;
}
EXPORT_SYMBOL_GPL(cyttsp_i2c_write_block_data);
diff --git a/drivers/input/touchscreen/cyttsp_spi.c b/drivers/input/touchscreen/cyttsp_spi.c
index 1df625337b84..4728bcb1916c 100644
--- a/drivers/input/touchscreen/cyttsp_spi.c
+++ b/drivers/input/touchscreen/cyttsp_spi.c
@@ -41,7 +41,7 @@
#define CY_SPI_BITS_PER_WORD 8
static int cyttsp_spi_xfer(struct device *dev, u8 *xfer_buf,
- u8 op, u8 reg, u8 *buf, int length)
+ u8 op, u16 reg, u8 *buf, int length)
{
struct spi_device *spi = to_spi_device(dev);
struct spi_message msg;
@@ -126,14 +126,14 @@ static int cyttsp_spi_xfer(struct device *dev, u8 *xfer_buf,
}
static int cyttsp_spi_read_block_data(struct device *dev, u8 *xfer_buf,
- u8 addr, u8 length, void *data)
+ u16 addr, u8 length, void *data)
{
return cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_RD_OP, addr, data,
length);
}
static int cyttsp_spi_write_block_data(struct device *dev, u8 *xfer_buf,
- u8 addr, u8 length, const void *data)
+ u16 addr, u8 length, const void *data)
{
return cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_WR_OP, addr, (void *)data,
length);