Commit 18fb38e2 authored by Linus Torvalds's avatar Linus Torvalds

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
parents be9c6d91 88ce3c3c
Device tree bindings for TI's ADS7843, ADS7845, ADS7846, ADS7873, TSC2046
SPI driven touch screen controllers.
The node for this driver must be a child node of a SPI controller, hence
all mandatory properties described in
Documentation/devicetree/bindings/spi/spi-bus.txt
must be specified.
Additional required properties:
compatible Must be one of the following, depending on the
model:
"ti,tsc2046"
"ti,ads7843"
"ti,ads7845"
"ti,ads7846"
"ti,ads7873"
interrupt-parent
interrupts An interrupt node describing the IRQ line the chip's
!PENIRQ pin is connected to.
vcc-supply A regulator node for the supply voltage.
Optional properties:
ti,vref-delay-usecs vref supply delay in usecs, 0 for
external vref (u16).
ti,vref-mv The VREF voltage, in millivolts (u16).
ti,keep-vref-on set to keep vref on for differential
measurements as well
ti,swap-xy swap x and y axis
ti,settle-delay-usec Settling time of the analog signals;
a function of Vcc and the capacitance
on the X/Y drivers. If set to non-zero,
two samples are taken with settle_delay
us apart, and the second one is used.
~150 uSec with 0.01uF caps (u16).
ti,penirq-recheck-delay-usecs If set to non-zero, after samples are
taken this delay is applied and penirq
is rechecked, to help avoid false
events. This value is affected by the
material used to build the touch layer
(u16).
ti,x-plate-ohms Resistance of the X-plate,
in Ohms (u16).
ti,y-plate-ohms Resistance of the Y-plate,
in Ohms (u16).
ti,x-min Minimum value on the X axis (u16).
ti,y-min Minimum value on the Y axis (u16).
ti,x-max Maximum value on the X axis (u16).
ti,y-max Minimum value on the Y axis (u16).
ti,pressure-min Minimum reported pressure value
(threshold) - u16.
ti,pressure-max Maximum reported pressure value (u16).
ti,debounce-max Max number of additional readings per
sample (u16).
ti,debounce-tol Tolerance used for filtering (u16).
ti,debounce-rep Additional consecutive good readings
required after the first two (u16).
ti,pendown-gpio-debounce Platform specific debounce time for the
pendown-gpio (u32).
pendown-gpio GPIO handle describing the pin the !PENIRQ
line is connected to.
linux,wakeup use any event on touchscreen as wakeup event.
Example for a TSC2046 chip connected to an McSPI controller of an OMAP SoC::
spi_controller {
tsc2046@0 {
reg = <0>; /* CS0 */
compatible = "ti,tsc2046";
interrupt-parent = <&gpio1>;
interrupts = <8 0>; /* BOOT6 / GPIO 8 */
spi-max-frequency = <1000000>;
pendown-gpio = <&gpio1 8 0>;
vcc-supply = <&reg_vcc3>;
ti,x-min = /bits/ 16 <0>;
ti,x-max = /bits/ 16 <8000>;
ti,y-min = /bits/ 16 <0>;
ti,y-max = /bits/ 16 <4800>;
ti,x-plate-ohms = /bits/ 16 <40>;
ti,pressure-max = /bits/ 16 <255>;
linux,wakeup;
};
};
......@@ -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 */
......
......@@ -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:
......
......@@ -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;
/*
......@@ -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,
......
......@@ -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;
......
......@@ -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)
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);
......
......@@ -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;
......
......@@ -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);
......
......@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment