Merge branch 'next' into for-linus

Prepare first set of updates for 3.11 merge window.
This commit is contained in:
Dmitry Torokhov
2013-07-02 09:01:31 -07:00
10477 changed files with 592020 additions and 322464 deletions

View File

@@ -237,7 +237,7 @@ static int pm860x_touch_probe(struct platform_device *pdev)
touch = kzalloc(sizeof(struct pm860x_touch), GFP_KERNEL);
if (touch == NULL)
return -ENOMEM;
dev_set_drvdata(&pdev->dev, touch);
platform_set_drvdata(pdev, touch);
touch->idev = input_allocate_device();
if (touch->idev == NULL) {
@@ -299,7 +299,6 @@ static int pm860x_touch_remove(struct platform_device *pdev)
input_unregister_device(touch->idev);
free_irq(touch->irq, touch);
platform_set_drvdata(pdev, NULL);
kfree(touch);
return 0;
}

View File

@@ -167,6 +167,36 @@ config TOUCHSCREEN_CYTTSP_SPI
To compile this driver as a module, choose M here: the
module will be called cyttsp_spi.
config TOUCHSCREEN_CYTTSP4_CORE
tristate "Cypress TrueTouch Gen4 Touchscreen Driver"
help
Core driver for Cypress TrueTouch(tm) Standard Product
Generation4 touchscreen controllers.
Say Y here if you have a Cypress Gen4 touchscreen.
If unsure, say N.
To compile this driver as a module, choose M here.
config TOUCHSCREEN_CYTTSP4_I2C
tristate "support I2C bus connection"
depends on TOUCHSCREEN_CYTTSP4_CORE && I2C
help
Say Y here if the touchscreen is connected via I2C bus.
To compile this driver as a module, choose M here: the
module will be called cyttsp4_i2c.
config TOUCHSCREEN_CYTTSP4_SPI
tristate "support SPI bus connection"
depends on TOUCHSCREEN_CYTTSP4_CORE && SPI_MASTER
help
Say Y here if the touchscreen is connected via SPI bus.
To compile this driver as a module, choose M here: the
module will be called cyttsp4_spi.
config TOUCHSCREEN_DA9034
tristate "Touchscreen support for Dialog Semiconductor DA9034"
depends on PMIC_DA903X

View File

@@ -18,8 +18,11 @@ obj-$(CONFIG_TOUCHSCREEN_AUO_PIXCIR) += auo-pixcir-ts.o
obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o
obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110) += cy8ctmg110_ts.o
obj-$(CONFIG_TOUCHSCREEN_CYTTSP_CORE) += cyttsp_core.o
obj-$(CONFIG_TOUCHSCREEN_CYTTSP_I2C) += cyttsp_i2c.o
obj-$(CONFIG_TOUCHSCREEN_CYTTSP_I2C) += cyttsp_i2c.o cyttsp_i2c_common.o
obj-$(CONFIG_TOUCHSCREEN_CYTTSP_SPI) += cyttsp_spi.o
obj-$(CONFIG_TOUCHSCREEN_CYTTSP4_CORE) += cyttsp4_core.o
obj-$(CONFIG_TOUCHSCREEN_CYTTSP4_I2C) += cyttsp4_i2c.o cyttsp_i2c_common.o
obj-$(CONFIG_TOUCHSCREEN_CYTTSP4_SPI) += cyttsp4_spi.o
obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o
obj-$(CONFIG_TOUCHSCREEN_DA9052) += da9052_tsi.o
obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o

View File

@@ -372,7 +372,6 @@ static int __init atmel_wm97xx_probe(struct platform_device *pdev)
err_irq:
free_irq(atmel_wm97xx->ac97c_irq, atmel_wm97xx);
err:
platform_set_drvdata(pdev, NULL);
kfree(atmel_wm97xx);
return ret;
}
@@ -386,7 +385,6 @@ static int __exit atmel_wm97xx_remove(struct platform_device *pdev)
free_irq(atmel_wm97xx->ac97c_irq, atmel_wm97xx);
del_timer_sync(&atmel_wm97xx->pen_timer);
wm97xx_unregister_mach_ops(wm);
platform_set_drvdata(pdev, NULL);
kfree(atmel_wm97xx);
return 0;

View File

@@ -183,10 +183,13 @@ static int atmel_tsadcc_probe(struct platform_device *pdev)
struct input_dev *input_dev;
struct resource *res;
struct at91_tsadcc_data *pdata = pdev->dev.platform_data;
int err = 0;
int err;
unsigned int prsc;
unsigned int reg;
if (!pdata)
return -EINVAL;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "no mmio resource defined.\n");
@@ -265,9 +268,6 @@ static int atmel_tsadcc_probe(struct platform_device *pdev)
prsc = clk_get_rate(ts_dev->clk);
dev_info(&pdev->dev, "Master clock is set at: %d Hz\n", prsc);
if (!pdata)
goto err_fail;
if (!pdata->adc_clock)
pdata->adc_clock = ADC_DEFAULT_CLOCK;
@@ -325,7 +325,7 @@ err_free_mem:
static int atmel_tsadcc_remove(struct platform_device *pdev)
{
struct atmel_tsadcc *ts_dev = dev_get_drvdata(&pdev->dev);
struct atmel_tsadcc *ts_dev = platform_get_drvdata(pdev);
struct resource *res;
free_irq(ts_dev->irq, ts_dev);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,472 @@
/*
* cyttsp4_core.h
* Cypress TrueTouch(TM) Standard Product V4 Core driver module.
* For use with Cypress Txx4xx parts.
* Supported parts include:
* TMA4XX
* TMA1036
*
* Copyright (C) 2012 Cypress Semiconductor
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2, and only version 2, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Contact Cypress Semiconductor at www.cypress.com <ttdrivers@cypress.com>
*
*/
#ifndef _LINUX_CYTTSP4_CORE_H
#define _LINUX_CYTTSP4_CORE_H
#include <linux/device.h>
#include <linux/err.h>
#include <linux/input.h>
#include <linux/kernel.h>
#include <linux/limits.h>
#include <linux/module.h>
#include <linux/stringify.h>
#include <linux/types.h>
#include <linux/platform_data/cyttsp4.h>
#define CY_REG_BASE 0x00
#define CY_POST_CODEL_WDG_RST 0x01
#define CY_POST_CODEL_CFG_DATA_CRC_FAIL 0x02
#define CY_POST_CODEL_PANEL_TEST_FAIL 0x04
#define CY_NUM_BTN_PER_REG 4
/* touch record system information offset masks and shifts */
#define CY_BYTE_OFS_MASK 0x1F
#define CY_BOFS_MASK 0xE0
#define CY_BOFS_SHIFT 5
#define CY_TMA1036_TCH_REC_SIZE 6
#define CY_TMA4XX_TCH_REC_SIZE 9
#define CY_TMA1036_MAX_TCH 0x0E
#define CY_TMA4XX_MAX_TCH 0x1E
#define CY_NORMAL_ORIGIN 0 /* upper, left corner */
#define CY_INVERT_ORIGIN 1 /* lower, right corner */
/* helpers */
#define GET_NUM_TOUCHES(x) ((x) & 0x1F)
#define IS_LARGE_AREA(x) ((x) & 0x20)
#define IS_BAD_PKT(x) ((x) & 0x20)
#define IS_BOOTLOADER(hst_mode, reset_detect) \
((hst_mode) & 0x01 || (reset_detect) != 0)
#define IS_TMO(t) ((t) == 0)
enum cyttsp_cmd_bits {
CY_CMD_COMPLETE = (1 << 6),
};
/* Timeout in ms. */
#define CY_WATCHDOG_TIMEOUT 1000
#define CY_MAX_PRINT_SIZE 512
#ifdef VERBOSE_DEBUG
#define CY_MAX_PRBUF_SIZE PIPE_BUF
#define CY_PR_TRUNCATED " truncated..."
#endif
enum cyttsp4_ic_grpnum {
CY_IC_GRPNUM_RESERVED,
CY_IC_GRPNUM_CMD_REGS,
CY_IC_GRPNUM_TCH_REP,
CY_IC_GRPNUM_DATA_REC,
CY_IC_GRPNUM_TEST_REC,
CY_IC_GRPNUM_PCFG_REC,
CY_IC_GRPNUM_TCH_PARM_VAL,
CY_IC_GRPNUM_TCH_PARM_SIZE,
CY_IC_GRPNUM_RESERVED1,
CY_IC_GRPNUM_RESERVED2,
CY_IC_GRPNUM_OPCFG_REC,
CY_IC_GRPNUM_DDATA_REC,
CY_IC_GRPNUM_MDATA_REC,
CY_IC_GRPNUM_TEST_REGS,
CY_IC_GRPNUM_BTN_KEYS,
CY_IC_GRPNUM_TTHE_REGS,
CY_IC_GRPNUM_NUM
};
enum cyttsp4_int_state {
CY_INT_NONE,
CY_INT_IGNORE = (1 << 0),
CY_INT_MODE_CHANGE = (1 << 1),
CY_INT_EXEC_CMD = (1 << 2),
CY_INT_AWAKE = (1 << 3),
};
enum cyttsp4_mode {
CY_MODE_UNKNOWN,
CY_MODE_BOOTLOADER = (1 << 1),
CY_MODE_OPERATIONAL = (1 << 2),
CY_MODE_SYSINFO = (1 << 3),
CY_MODE_CAT = (1 << 4),
CY_MODE_STARTUP = (1 << 5),
CY_MODE_LOADER = (1 << 6),
CY_MODE_CHANGE_MODE = (1 << 7),
CY_MODE_CHANGED = (1 << 8),
CY_MODE_CMD_COMPLETE = (1 << 9),
};
enum cyttsp4_sleep_state {
SS_SLEEP_OFF,
SS_SLEEP_ON,
SS_SLEEPING,
SS_WAKING,
};
enum cyttsp4_startup_state {
STARTUP_NONE,
STARTUP_QUEUED,
STARTUP_RUNNING,
};
#define CY_NUM_REVCTRL 8
struct cyttsp4_cydata {
u8 ttpidh;
u8 ttpidl;
u8 fw_ver_major;
u8 fw_ver_minor;
u8 revctrl[CY_NUM_REVCTRL];
u8 blver_major;
u8 blver_minor;
u8 jtag_si_id3;
u8 jtag_si_id2;
u8 jtag_si_id1;
u8 jtag_si_id0;
u8 mfgid_sz;
u8 cyito_idh;
u8 cyito_idl;
u8 cyito_verh;
u8 cyito_verl;
u8 ttsp_ver_major;
u8 ttsp_ver_minor;
u8 device_info;
u8 mfg_id[];
} __packed;
struct cyttsp4_test {
u8 post_codeh;
u8 post_codel;
} __packed;
struct cyttsp4_pcfg {
u8 electrodes_x;
u8 electrodes_y;
u8 len_xh;
u8 len_xl;
u8 len_yh;
u8 len_yl;
u8 res_xh;
u8 res_xl;
u8 res_yh;
u8 res_yl;
u8 max_zh;
u8 max_zl;
u8 panel_info0;
} __packed;
struct cyttsp4_tch_rec_params {
u8 loc;
u8 size;
} __packed;
#define CY_NUM_TCH_FIELDS 7
#define CY_NUM_EXT_TCH_FIELDS 3
struct cyttsp4_opcfg {
u8 cmd_ofs;
u8 rep_ofs;
u8 rep_szh;
u8 rep_szl;
u8 num_btns;
u8 tt_stat_ofs;
u8 obj_cfg0;
u8 max_tchs;
u8 tch_rec_size;
struct cyttsp4_tch_rec_params tch_rec_old[CY_NUM_TCH_FIELDS];
u8 btn_rec_size; /* btn record size (in bytes) */
u8 btn_diff_ofs; /* btn data loc, diff counts */
u8 btn_diff_size; /* btn size of diff counts (in bits) */
struct cyttsp4_tch_rec_params tch_rec_new[CY_NUM_EXT_TCH_FIELDS];
} __packed;
struct cyttsp4_sysinfo_ptr {
struct cyttsp4_cydata *cydata;
struct cyttsp4_test *test;
struct cyttsp4_pcfg *pcfg;
struct cyttsp4_opcfg *opcfg;
struct cyttsp4_ddata *ddata;
struct cyttsp4_mdata *mdata;
} __packed;
struct cyttsp4_sysinfo_data {
u8 hst_mode;
u8 reserved;
u8 map_szh;
u8 map_szl;
u8 cydata_ofsh;
u8 cydata_ofsl;
u8 test_ofsh;
u8 test_ofsl;
u8 pcfg_ofsh;
u8 pcfg_ofsl;
u8 opcfg_ofsh;
u8 opcfg_ofsl;
u8 ddata_ofsh;
u8 ddata_ofsl;
u8 mdata_ofsh;
u8 mdata_ofsl;
} __packed;
enum cyttsp4_tch_abs { /* for ordering within the extracted touch data array */
CY_TCH_X, /* X */
CY_TCH_Y, /* Y */
CY_TCH_P, /* P (Z) */
CY_TCH_T, /* TOUCH ID */
CY_TCH_E, /* EVENT ID */
CY_TCH_O, /* OBJECT ID */
CY_TCH_W, /* SIZE */
CY_TCH_MAJ, /* TOUCH_MAJOR */
CY_TCH_MIN, /* TOUCH_MINOR */
CY_TCH_OR, /* ORIENTATION */
CY_TCH_NUM_ABS
};
static const char * const cyttsp4_tch_abs_string[] = {
[CY_TCH_X] = "X",
[CY_TCH_Y] = "Y",
[CY_TCH_P] = "P",
[CY_TCH_T] = "T",
[CY_TCH_E] = "E",
[CY_TCH_O] = "O",
[CY_TCH_W] = "W",
[CY_TCH_MAJ] = "MAJ",
[CY_TCH_MIN] = "MIN",
[CY_TCH_OR] = "OR",
[CY_TCH_NUM_ABS] = "INVALID"
};
struct cyttsp4_touch {
int abs[CY_TCH_NUM_ABS];
};
struct cyttsp4_tch_abs_params {
size_t ofs; /* abs byte offset */
size_t size; /* size in bits */
size_t max; /* max value */
size_t bofs; /* bit offset */
};
struct cyttsp4_sysinfo_ofs {
size_t chip_type;
size_t cmd_ofs;
size_t rep_ofs;
size_t rep_sz;
size_t num_btns;
size_t num_btn_regs; /* ceil(num_btns/4) */
size_t tt_stat_ofs;
size_t tch_rec_size;
size_t obj_cfg0;
size_t max_tchs;
size_t mode_size;
size_t data_size;
size_t map_sz;
size_t max_x;
size_t x_origin; /* left or right corner */
size_t max_y;
size_t y_origin; /* upper or lower corner */
size_t max_p;
size_t cydata_ofs;
size_t test_ofs;
size_t pcfg_ofs;
size_t opcfg_ofs;
size_t ddata_ofs;
size_t mdata_ofs;
size_t cydata_size;
size_t test_size;
size_t pcfg_size;
size_t opcfg_size;
size_t ddata_size;
size_t mdata_size;
size_t btn_keys_size;
struct cyttsp4_tch_abs_params tch_abs[CY_TCH_NUM_ABS];
size_t btn_rec_size; /* btn record size (in bytes) */
size_t btn_diff_ofs;/* btn data loc ,diff counts, (Op-Mode byte ofs) */
size_t btn_diff_size;/* btn size of diff counts (in bits) */
};
enum cyttsp4_btn_state {
CY_BTN_RELEASED,
CY_BTN_PRESSED,
CY_BTN_NUM_STATE
};
struct cyttsp4_btn {
bool enabled;
int state; /* CY_BTN_PRESSED, CY_BTN_RELEASED */
int key_code;
};
struct cyttsp4_sysinfo {
bool ready;
struct cyttsp4_sysinfo_data si_data;
struct cyttsp4_sysinfo_ptr si_ptrs;
struct cyttsp4_sysinfo_ofs si_ofs;
struct cyttsp4_btn *btn; /* button states */
u8 *btn_rec_data; /* button diff count data */
u8 *xy_mode; /* operational mode and status regs */
u8 *xy_data; /* operational touch regs */
};
struct cyttsp4_mt_data {
struct cyttsp4_mt_platform_data *pdata;
struct cyttsp4_sysinfo *si;
struct input_dev *input;
struct mutex report_lock;
bool is_suspended;
char phys[NAME_MAX];
int num_prv_tch;
};
struct cyttsp4 {
struct device *dev;
struct mutex system_lock;
struct mutex adap_lock;
enum cyttsp4_mode mode;
enum cyttsp4_sleep_state sleep_state;
enum cyttsp4_startup_state startup_state;
int int_status;
wait_queue_head_t wait_q;
int irq;
struct work_struct startup_work;
struct work_struct watchdog_work;
struct timer_list watchdog_timer;
struct cyttsp4_sysinfo sysinfo;
void *exclusive_dev;
int exclusive_waits;
atomic_t ignore_irq;
bool invalid_touch_app;
struct cyttsp4_mt_data md;
struct cyttsp4_platform_data *pdata;
struct cyttsp4_core_platform_data *cpdata;
const struct cyttsp4_bus_ops *bus_ops;
u8 *xfer_buf;
#ifdef VERBOSE_DEBUG
u8 pr_buf[CY_MAX_PRBUF_SIZE];
#endif
};
struct cyttsp4_bus_ops {
u16 bustype;
int (*write)(struct device *dev, u8 *xfer_buf, u8 addr, u8 length,
const void *values);
int (*read)(struct device *dev, u8 *xfer_buf, u8 addr, u8 length,
void *values);
};
enum cyttsp4_hst_mode_bits {
CY_HST_TOGGLE = (1 << 7),
CY_HST_MODE_CHANGE = (1 << 3),
CY_HST_MODE = (7 << 4),
CY_HST_OPERATE = (0 << 4),
CY_HST_SYSINFO = (1 << 4),
CY_HST_CAT = (2 << 4),
CY_HST_LOWPOW = (1 << 2),
CY_HST_SLEEP = (1 << 1),
CY_HST_RESET = (1 << 0),
};
/* abs settings */
#define CY_IGNORE_VALUE 0xFFFF
/* abs signal capabilities offsets in the frameworks array */
enum cyttsp4_sig_caps {
CY_SIGNAL_OST,
CY_MIN_OST,
CY_MAX_OST,
CY_FUZZ_OST,
CY_FLAT_OST,
CY_NUM_ABS_SET /* number of signal capability fields */
};
/* abs axis signal offsets in the framworks array */
enum cyttsp4_sig_ost {
CY_ABS_X_OST,
CY_ABS_Y_OST,
CY_ABS_P_OST,
CY_ABS_W_OST,
CY_ABS_ID_OST,
CY_ABS_MAJ_OST,
CY_ABS_MIN_OST,
CY_ABS_OR_OST,
CY_NUM_ABS_OST /* number of abs signals */
};
enum cyttsp4_flags {
CY_FLAG_NONE = 0x00,
CY_FLAG_HOVER = 0x04,
CY_FLAG_FLIP = 0x08,
CY_FLAG_INV_X = 0x10,
CY_FLAG_INV_Y = 0x20,
CY_FLAG_VKEYS = 0x40,
};
enum cyttsp4_object_id {
CY_OBJ_STANDARD_FINGER,
CY_OBJ_LARGE_OBJECT,
CY_OBJ_STYLUS,
CY_OBJ_HOVER,
};
enum cyttsp4_event_id {
CY_EV_NO_EVENT,
CY_EV_TOUCHDOWN,
CY_EV_MOVE, /* significant displacement (> act dist) */
CY_EV_LIFTOFF, /* record reports last position */
};
/* x-axis resolution of panel in pixels */
#define CY_PCFG_RESOLUTION_X_MASK 0x7F
/* y-axis resolution of panel in pixels */
#define CY_PCFG_RESOLUTION_Y_MASK 0x7F
/* x-axis, 0:origin is on left side of panel, 1: right */
#define CY_PCFG_ORIGIN_X_MASK 0x80
/* 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,
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,
const void *buf)
{
return ts->bus_ops->write(ts->dev, ts->xfer_buf, addr, size, buf);
}
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,
u8 length, const void *values);
int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf, u8 addr,
u8 length, void *values);
extern const struct dev_pm_ops cyttsp4_pm_ops;
#endif /* _LINUX_CYTTSP4_CORE_H */

View File

@@ -0,0 +1,90 @@
/*
* cyttsp_i2c.c
* Cypress TrueTouch(TM) Standard Product (TTSP) I2C touchscreen driver.
* For use with Cypress Txx4xx parts.
* Supported parts include:
* TMA4XX
* TMA1036
*
* Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc.
* Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org>
* Copyright (C) 2013 Cypress Semiconductor
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2, and only version 2, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Contact Cypress Semiconductor at www.cypress.com <ttdrivers@cypress.com>
*
*/
#include "cyttsp4_core.h"
#include <linux/i2c.h>
#include <linux/input.h>
#define CYTTSP4_I2C_DATA_SIZE (3 * 256)
static const struct cyttsp4_bus_ops cyttsp4_i2c_bus_ops = {
.bustype = BUS_I2C,
.write = cyttsp_i2c_write_block_data,
.read = cyttsp_i2c_read_block_data,
};
static int cyttsp4_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct cyttsp4 *ts;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
dev_err(&client->dev, "I2C functionality not Supported\n");
return -EIO;
}
ts = cyttsp4_probe(&cyttsp4_i2c_bus_ops, &client->dev, client->irq,
CYTTSP4_I2C_DATA_SIZE);
if (IS_ERR(ts))
return PTR_ERR(ts);
return 0;
}
static int cyttsp4_i2c_remove(struct i2c_client *client)
{
struct cyttsp4 *ts = i2c_get_clientdata(client);
cyttsp4_remove(ts);
return 0;
}
static const struct i2c_device_id cyttsp4_i2c_id[] = {
{ CYTTSP4_I2C_NAME, 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, cyttsp4_i2c_id);
static struct i2c_driver cyttsp4_i2c_driver = {
.driver = {
.name = CYTTSP4_I2C_NAME,
.owner = THIS_MODULE,
.pm = &cyttsp4_pm_ops,
},
.probe = cyttsp4_i2c_probe,
.remove = cyttsp4_i2c_remove,
.id_table = cyttsp4_i2c_id,
};
module_i2c_driver(cyttsp4_i2c_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard Product (TTSP) I2C driver");
MODULE_AUTHOR("Cypress");
MODULE_ALIAS("i2c:cyttsp4");

View File

@@ -0,0 +1,205 @@
/*
* Source for:
* Cypress TrueTouch(TM) Standard Product (TTSP) SPI touchscreen driver.
* For use with Cypress Txx4xx parts.
* Supported parts include:
* TMA4XX
* TMA1036
*
* Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc.
* Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org>
* Copyright (C) 2013 Cypress Semiconductor
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2, and only version 2, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Contact Cypress Semiconductor at www.cypress.com <ttdrivers@cypress.com>
*
*/
#include "cyttsp4_core.h"
#include <linux/delay.h>
#include <linux/input.h>
#include <linux/spi/spi.h>
#define CY_SPI_WR_OP 0x00 /* r/~w */
#define CY_SPI_RD_OP 0x01
#define CY_SPI_BITS_PER_WORD 8
#define CY_SPI_A8_BIT 0x02
#define CY_SPI_WR_HEADER_BYTES 2
#define CY_SPI_RD_HEADER_BYTES 1
#define CY_SPI_CMD_BYTES 2
#define CY_SPI_SYNC_BYTE 0
#define CY_SPI_SYNC_ACK 0x62 /* from TRM *A protocol */
#define CY_SPI_DATA_SIZE (2 * 256)
#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)
{
struct spi_device *spi = to_spi_device(dev);
struct spi_message msg;
struct spi_transfer xfer[2];
u8 *wr_buf = &xfer_buf[0];
u8 rd_buf[CY_SPI_CMD_BYTES];
int retval;
int i;
if (length > CY_SPI_DATA_SIZE) {
dev_err(dev, "%s: length %d is too big.\n",
__func__, length);
return -EINVAL;
}
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);
memset(xfer, 0, sizeof(xfer));
spi_message_init(&msg);
/*
We set both TX and RX buffers because Cypress TTSP
requires full duplex operation.
*/
xfer[0].tx_buf = wr_buf;
xfer[0].rx_buf = rd_buf;
switch (op) {
case CY_SPI_WR_OP:
xfer[0].len = length + CY_SPI_CMD_BYTES;
spi_message_add_tail(&xfer[0], &msg);
break;
case CY_SPI_RD_OP:
xfer[0].len = CY_SPI_RD_HEADER_BYTES;
spi_message_add_tail(&xfer[0], &msg);
xfer[1].rx_buf = buf;
xfer[1].len = length;
spi_message_add_tail(&xfer[1], &msg);
break;
default:
dev_err(dev, "%s: bad operation code=%d\n", __func__, op);
return -EINVAL;
}
retval = spi_sync(spi, &msg);
if (retval < 0) {
dev_dbg(dev, "%s: spi_sync() error %d, len=%d, op=%d\n",
__func__, retval, xfer[1].len, op);
/*
* do not return here since was a bad ACK sequence
* let the following ACK check handle any errors and
* allow silent retries
*/
}
if (rd_buf[CY_SPI_SYNC_BYTE] != CY_SPI_SYNC_ACK) {
dev_dbg(dev, "%s: operation %d failed\n", __func__, op);
for (i = 0; i < CY_SPI_CMD_BYTES; i++)
dev_dbg(dev, "%s: test rd_buf[%d]:0x%02x\n",
__func__, i, rd_buf[i]);
for (i = 0; i < length; i++)
dev_dbg(dev, "%s: test buf[%d]:0x%02x\n",
__func__, i, buf[i]);
return -EIO;
}
return 0;
}
static int cyttsp_spi_read_block_data(struct device *dev, u8 *xfer_buf,
u8 addr, u8 length, void *data)
{
int rc;
rc = cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_WR_OP, addr, NULL, 0);
if (rc)
return rc;
else
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)
{
return cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_WR_OP, addr, (void *)data,
length);
}
static const struct cyttsp4_bus_ops cyttsp_spi_bus_ops = {
.bustype = BUS_SPI,
.write = cyttsp_spi_write_block_data,
.read = cyttsp_spi_read_block_data,
};
static int cyttsp4_spi_probe(struct spi_device *spi)
{
struct cyttsp4 *ts;
int error;
/* Set up SPI*/
spi->bits_per_word = CY_SPI_BITS_PER_WORD;
spi->mode = SPI_MODE_0;
error = spi_setup(spi);
if (error < 0) {
dev_err(&spi->dev, "%s: SPI setup error %d\n",
__func__, error);
return error;
}
ts = cyttsp4_probe(&cyttsp_spi_bus_ops, &spi->dev, spi->irq,
CY_SPI_DATA_BUF_SIZE);
if (IS_ERR(ts))
return PTR_ERR(ts);
return 0;
}
static int cyttsp4_spi_remove(struct spi_device *spi)
{
struct cyttsp4 *ts = spi_get_drvdata(spi);
cyttsp4_remove(ts);
return 0;
}
static struct spi_driver cyttsp4_spi_driver = {
.driver = {
.name = CYTTSP4_SPI_NAME,
.owner = THIS_MODULE,
.pm = &cyttsp4_pm_ops,
},
.probe = cyttsp4_spi_probe,
.remove = cyttsp4_spi_remove,
};
module_spi_driver(cyttsp4_spi_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard Product (TTSP) SPI driver");
MODULE_AUTHOR("Cypress");
MODULE_ALIAS("spi:cyttsp4");

View File

@@ -84,7 +84,8 @@ static int ttsp_read_block_data(struct cyttsp *ts, u8 command,
int tries;
for (tries = 0; tries < CY_NUM_RETRY; tries++) {
error = ts->bus_ops->read(ts, command, length, buf);
error = ts->bus_ops->read(ts->dev, ts->xfer_buf, command,
length, buf);
if (!error)
return 0;
@@ -101,7 +102,8 @@ static int ttsp_write_block_data(struct cyttsp *ts, u8 command,
int tries;
for (tries = 0; tries < CY_NUM_RETRY; tries++) {
error = ts->bus_ops->write(ts, command, length, buf);
error = ts->bus_ops->write(ts->dev, ts->xfer_buf, command,
length, buf);
if (!error)
return 0;

View File

@@ -112,9 +112,10 @@ struct cyttsp;
struct cyttsp_bus_ops {
u16 bustype;
int (*write)(struct cyttsp *ts,
u8 addr, u8 length, const void *values);
int (*read)(struct cyttsp *ts, u8 addr, u8 length, void *values);
int (*write)(struct device *dev, u8 *xfer_buf, u8 addr, u8 length,
const void *values);
int (*read)(struct device *dev, u8 *xfer_buf, u8 addr, u8 length,
void *values);
};
enum cyttsp_state {
@@ -144,6 +145,10 @@ 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,
u8 length, const void *values);
int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf, u8 addr,
u8 length, void *values);
extern const struct dev_pm_ops cyttsp_pm_ops;
#endif /* __CYTTSP_CORE_H__ */

View File

@@ -1,5 +1,5 @@
/*
* Source for:
* cyttsp_i2c.c
* Cypress TrueTouch(TM) Standard Product (TTSP) I2C touchscreen driver.
* For use with Cypress Txx3xx parts.
* Supported parts include:
@@ -19,11 +19,7 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contact Cypress Semiconductor at www.cypress.com <kev@cypress.com>
* Contact Cypress Semiconductor at www.cypress.com <ttdrivers@cypress.com>
*
*/
@@ -34,47 +30,6 @@
#define CY_I2C_DATA_SIZE 128
static int cyttsp_i2c_read_block_data(struct cyttsp *ts,
u8 addr, u8 length, void *values)
{
struct i2c_client *client = to_i2c_client(ts->dev);
struct i2c_msg msgs[] = {
{
.addr = client->addr,
.flags = 0,
.len = 1,
.buf = &addr,
},
{
.addr = client->addr,
.flags = I2C_M_RD,
.len = length,
.buf = values,
},
};
int retval;
retval = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
if (retval < 0)
return retval;
return retval != ARRAY_SIZE(msgs) ? -EIO : 0;
}
static int cyttsp_i2c_write_block_data(struct cyttsp *ts,
u8 addr, u8 length, const void *values)
{
struct i2c_client *client = to_i2c_client(ts->dev);
int retval;
ts->xfer_buf[0] = addr;
memcpy(&ts->xfer_buf[1], values, length);
retval = i2c_master_send(client, ts->xfer_buf, length + 1);
return retval < 0 ? retval : 0;
}
static const struct cyttsp_bus_ops cyttsp_i2c_bus_ops = {
.bustype = BUS_I2C,
.write = cyttsp_i2c_write_block_data,
@@ -98,7 +53,6 @@ static int cyttsp_i2c_probe(struct i2c_client *client,
return PTR_ERR(ts);
i2c_set_clientdata(client, ts);
return 0;
}

View File

@@ -0,0 +1,79 @@
/*
* cyttsp_i2c_common.c
* Cypress TrueTouch(TM) Standard Product (TTSP) I2C touchscreen driver.
* For use with Cypress Txx3xx and Txx4xx parts.
* Supported parts include:
* CY8CTST341
* CY8CTMA340
* TMA4XX
* TMA1036
*
* Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc.
* Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2, and only version 2, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Contact Cypress Semiconductor at www.cypress.com <ttdrivers@cypress.com>
*
*/
#include <linux/device.h>
#include <linux/export.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/types.h>
int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf,
u8 addr, u8 length, void *values)
{
struct i2c_client *client = to_i2c_client(dev);
struct i2c_msg msgs[] = {
{
.addr = client->addr,
.flags = 0,
.len = 1,
.buf = &addr,
},
{
.addr = client->addr,
.flags = I2C_M_RD,
.len = length,
.buf = values,
},
};
int retval;
retval = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
if (retval < 0)
return retval;
return retval != ARRAY_SIZE(msgs) ? -EIO : 0;
}
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)
{
struct i2c_client *client = to_i2c_client(dev);
int retval;
xfer_buf[0] = addr;
memcpy(&xfer_buf[1], values, length);
retval = i2c_master_send(client, xfer_buf, length + 1);
return retval < 0 ? retval : 0;
}
EXPORT_SYMBOL_GPL(cyttsp_i2c_write_block_data);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Cypress");

View File

@@ -8,6 +8,7 @@
*
* Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc.
* Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org>
* Copyright (C) 2013 Cypress Semiconductor
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -19,11 +20,7 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contact Cypress Semiconductor at www.cypress.com <kev@cypress.com>
* Contact Cypress Semiconductor at www.cypress.com <ttdrivers@cypress.com>
*
*/
@@ -43,19 +40,19 @@
#define CY_SPI_DATA_BUF_SIZE (CY_SPI_CMD_BYTES + CY_SPI_DATA_SIZE)
#define CY_SPI_BITS_PER_WORD 8
static int cyttsp_spi_xfer(struct cyttsp *ts,
static int cyttsp_spi_xfer(struct device *dev, u8 *xfer_buf,
u8 op, u8 reg, u8 *buf, int length)
{
struct spi_device *spi = to_spi_device(ts->dev);
struct spi_device *spi = to_spi_device(dev);
struct spi_message msg;
struct spi_transfer xfer[2];
u8 *wr_buf = &ts->xfer_buf[0];
u8 *rd_buf = &ts->xfer_buf[CY_SPI_DATA_BUF_SIZE];
u8 *wr_buf = &xfer_buf[0];
u8 *rd_buf = &xfer_buf[CY_SPI_DATA_BUF_SIZE];
int retval;
int i;
if (length > CY_SPI_DATA_SIZE) {
dev_err(ts->dev, "%s: length %d is too big.\n",
dev_err(dev, "%s: length %d is too big.\n",
__func__, length);
return -EINVAL;
}
@@ -95,13 +92,13 @@ static int cyttsp_spi_xfer(struct cyttsp *ts,
break;
default:
dev_err(ts->dev, "%s: bad operation code=%d\n", __func__, op);
dev_err(dev, "%s: bad operation code=%d\n", __func__, op);
return -EINVAL;
}
retval = spi_sync(spi, &msg);
if (retval < 0) {
dev_dbg(ts->dev, "%s: spi_sync() error %d, len=%d, op=%d\n",
dev_dbg(dev, "%s: spi_sync() error %d, len=%d, op=%d\n",
__func__, retval, xfer[1].len, op);
/*
@@ -113,14 +110,13 @@ static int cyttsp_spi_xfer(struct cyttsp *ts,
if (rd_buf[CY_SPI_SYNC_BYTE] != CY_SPI_SYNC_ACK1 ||
rd_buf[CY_SPI_SYNC_BYTE + 1] != CY_SPI_SYNC_ACK2) {
dev_dbg(ts->dev, "%s: operation %d failed\n", __func__, op);
dev_dbg(dev, "%s: operation %d failed\n", __func__, op);
for (i = 0; i < CY_SPI_CMD_BYTES; i++)
dev_dbg(ts->dev, "%s: test rd_buf[%d]:0x%02x\n",
dev_dbg(dev, "%s: test rd_buf[%d]:0x%02x\n",
__func__, i, rd_buf[i]);
for (i = 0; i < length; i++)
dev_dbg(ts->dev, "%s: test buf[%d]:0x%02x\n",
dev_dbg(dev, "%s: test buf[%d]:0x%02x\n",
__func__, i, buf[i]);
return -EIO;
@@ -129,16 +125,18 @@ static int cyttsp_spi_xfer(struct cyttsp *ts,
return 0;
}
static int cyttsp_spi_read_block_data(struct cyttsp *ts,
static int cyttsp_spi_read_block_data(struct device *dev, u8 *xfer_buf,
u8 addr, u8 length, void *data)
{
return cyttsp_spi_xfer(ts, CY_SPI_RD_OP, addr, data, length);
return cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_RD_OP, addr, data,
length);
}
static int cyttsp_spi_write_block_data(struct cyttsp *ts,
static int cyttsp_spi_write_block_data(struct device *dev, u8 *xfer_buf,
u8 addr, u8 length, const void *data)
{
return cyttsp_spi_xfer(ts, CY_SPI_WR_OP, addr, (void *)data, length);
return cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_WR_OP, addr, (void *)data,
length);
}
static const struct cyttsp_bus_ops cyttsp_spi_bus_ops = {

View File

@@ -329,8 +329,6 @@ static int da9052_ts_remove(struct platform_device *pdev)
input_unregister_device(tsi->dev);
kfree(tsi);
platform_set_drvdata(pdev, NULL);
return 0;
}

View File

@@ -166,24 +166,22 @@ static int egalax_firmware_version(struct i2c_client *client)
}
static int egalax_ts_probe(struct i2c_client *client,
const struct i2c_device_id *id)
const struct i2c_device_id *id)
{
struct egalax_ts *ts;
struct input_dev *input_dev;
int ret;
int error;
ts = kzalloc(sizeof(struct egalax_ts), GFP_KERNEL);
ts = devm_kzalloc(&client->dev, sizeof(struct egalax_ts), GFP_KERNEL);
if (!ts) {
dev_err(&client->dev, "Failed to allocate memory\n");
return -ENOMEM;
}
input_dev = input_allocate_device();
input_dev = devm_input_allocate_device(&client->dev);
if (!input_dev) {
dev_err(&client->dev, "Failed to allocate memory\n");
error = -ENOMEM;
goto err_free_ts;
return -ENOMEM;
}
ts->client = client;
@@ -193,19 +191,17 @@ static int egalax_ts_probe(struct i2c_client *client,
error = egalax_wake_up_device(client);
if (error) {
dev_err(&client->dev, "Failed to wake up the controller\n");
goto err_free_dev;
return error;
}
ret = egalax_firmware_version(client);
if (ret < 0) {
error = egalax_firmware_version(client);
if (error < 0) {
dev_err(&client->dev, "Failed to read firmware version\n");
error = -EIO;
goto err_free_dev;
return error;
}
input_dev->name = "EETI eGalax Touch Screen";
input_dev->id.bustype = BUS_I2C;
input_dev->dev.parent = &client->dev;
__set_bit(EV_ABS, input_dev->evbit);
__set_bit(EV_KEY, input_dev->evbit);
@@ -221,41 +217,21 @@ static int egalax_ts_probe(struct i2c_client *client,
input_set_drvdata(input_dev, ts);
error = request_threaded_irq(client->irq, NULL, egalax_ts_interrupt,
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
"egalax_ts", ts);
error = devm_request_threaded_irq(&client->dev, client->irq, NULL,
egalax_ts_interrupt,
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
"egalax_ts", ts);
if (error < 0) {
dev_err(&client->dev, "Failed to register interrupt\n");
goto err_free_dev;
return error;
}
error = input_register_device(ts->input_dev);
if (error)
goto err_free_irq;
return error;
i2c_set_clientdata(client, ts);
return 0;
err_free_irq:
free_irq(client->irq, ts);
err_free_dev:
input_free_device(input_dev);
err_free_ts:
kfree(ts);
return error;
}
static int egalax_ts_remove(struct i2c_client *client)
{
struct egalax_ts *ts = i2c_get_clientdata(client);
free_irq(client->irq, ts);
input_unregister_device(ts->input_dev);
kfree(ts);
return 0;
}
static const struct i2c_device_id egalax_ts_id[] = {
@@ -301,7 +277,6 @@ static struct i2c_driver egalax_ts_driver = {
},
.id_table = egalax_ts_id,
.probe = egalax_ts_probe,
.remove = egalax_ts_remove,
};
module_i2c_driver(egalax_ts_driver);

View File

@@ -651,8 +651,6 @@ static int mrstouch_remove(struct platform_device *pdev)
input_unregister_device(tsdev->input);
kfree(tsdev);
platform_set_drvdata(pdev, NULL);
return 0;
}

View File

@@ -145,7 +145,6 @@ static int jornada720_ts_probe(struct platform_device *pdev)
fail2:
free_irq(IRQ_GPIO9, pdev);
fail1:
platform_set_drvdata(pdev, NULL);
input_free_device(input_dev);
kfree(jornada_ts);
return error;
@@ -156,7 +155,6 @@ static int jornada720_ts_remove(struct platform_device *pdev)
struct jornada_ts *jornada_ts = platform_get_drvdata(pdev);
free_irq(IRQ_GPIO9, pdev);
platform_set_drvdata(pdev, NULL);
input_unregister_device(jornada_ts->dev);
kfree(jornada_ts);

View File

@@ -233,8 +233,6 @@ static int mc13783_ts_remove(struct platform_device *pdev)
{
struct mc13783_ts_priv *priv = platform_get_drvdata(pdev);
platform_set_drvdata(pdev, NULL);
destroy_workqueue(priv->workq);
input_unregister_device(priv->idev);
kfree(priv);

View File

@@ -336,7 +336,6 @@ static int titsc_remove(struct platform_device *pdev)
input_unregister_device(ts_dev->input);
platform_set_drvdata(pdev, NULL);
kfree(ts_dev);
return 0;
}

View File

@@ -351,7 +351,6 @@ error_clk:
error_map:
release_mem_region(ts->res->start, resource_size(ts->res));
error_res:
platform_set_drvdata(pdev, NULL);
kfree(ts);
return error;
@@ -366,7 +365,6 @@ static int tsc_remove(struct platform_device *pdev)
clk_put(ts->clk);
iounmap(ts->regs);
release_mem_region(ts->res->start, resource_size(ts->res));
platform_set_drvdata(pdev, NULL);
kfree(ts);
return 0;

View File

@@ -318,8 +318,6 @@ static int w90x900ts_remove(struct platform_device *pdev)
input_unregister_device(w90p910_ts->input);
kfree(w90p910_ts);
platform_set_drvdata(pdev, NULL);
return 0;
}

View File

@@ -1,7 +1,7 @@
/*
* Wacom Penabled Driver for I2C
*
* Copyright (c) 2011 Tatsunosuke Tobita, Wacom.
* Copyright (c) 2011 - 2013 Tatsunosuke Tobita, Wacom.
* <tobita.tatsunosuke@wacom.co.jp>
*
* This program is free software; you can redistribute it
@@ -27,7 +27,6 @@
#define WACOM_CMD_THROW0 0x05
#define WACOM_CMD_THROW1 0x00
#define WACOM_QUERY_SIZE 19
#define WACOM_RETRY_CNT 100
struct wacom_features {
int x_max;
@@ -40,6 +39,8 @@ struct wacom_i2c {
struct i2c_client *client;
struct input_dev *input;
u8 data[WACOM_QUERY_SIZE];
bool prox;
int tool;
};
static int wacom_query_device(struct i2c_client *client,
@@ -112,9 +113,14 @@ static irqreturn_t wacom_i2c_irq(int irq, void *dev_id)
y = le16_to_cpup((__le16 *)&data[6]);
pressure = le16_to_cpup((__le16 *)&data[8]);
if (!wac_i2c->prox)
wac_i2c->tool = (data[3] & 0x0c) ?
BTN_TOOL_RUBBER : BTN_TOOL_PEN;
wac_i2c->prox = data[3] & 0x20;
input_report_key(input, BTN_TOUCH, tsw || ers);
input_report_key(input, BTN_TOOL_PEN, tsw);
input_report_key(input, BTN_TOOL_RUBBER, ers);
input_report_key(input, wac_i2c->tool, wac_i2c->prox);
input_report_key(input, BTN_STYLUS, f1);
input_report_key(input, BTN_STYLUS2, f2);
input_report_abs(input, ABS_X, x);