linux-input.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v10 1/3] Input: cyttsp - Cypress TTSP capacitive multi-touch screen support
@ 2012-01-20  0:57 Javier Martinez Canillas
  2012-01-20  0:57 ` [PATCH v10 2/3] Input: cyttsp - add support for Cypress TTSP touchscreen I2C bus interface Javier Martinez Canillas
                   ` (2 more replies)
  0 siblings, 3 replies; 14+ messages in thread
From: Javier Martinez Canillas @ 2012-01-20  0:57 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Henrik Rydberg, Mohan Pallaka, Kevin McNeely, Shubhrajyoti Datta,
	linux-input, Javier Martinez Canillas

Cypress TrueTouch(tm) Standard Product controllers are found in
a wide range of embedded devices. This driver add support for a
variety of TTSP controllers.

Since the hardware is capable of tracking identifiable contacts, multi-touch
protocol type B (stateful) is used to report contact information.

The driver is composed of a core driver that process the data sent by
the contacts and a set of bus specific interface modules. This patch
adds the base core TTSP driver.

Signed-off-by: Javier Martinez Canillas <javier@dowhile0.org>
---

Changes for v10: Fix issues called out by Dmitry Torokhov
	- Remove use_sleep and put device to sleep unconditionally on suspend
	- Cleanup cyttsp_power_on() and remove cyttsp_bl_app_valid() function

 drivers/input/touchscreen/Kconfig       |   31 ++
 drivers/input/touchscreen/Makefile      |    3 +
 drivers/input/touchscreen/cyttsp_core.c |  682 +++++++++++++++++++++++++++++++
 drivers/input/touchscreen/cyttsp_core.h |  141 +++++++
 include/linux/input/cyttsp.h            |   68 +++
 5 files changed, 925 insertions(+), 0 deletions(-)
 create mode 100644 drivers/input/touchscreen/cyttsp_core.c
 create mode 100644 drivers/input/touchscreen/cyttsp_core.h
 create mode 100644 include/linux/input/cyttsp.h

diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 4af2a18..60674e1 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -149,6 +149,37 @@ config TOUCHSCREEN_CY8CTMG110
 	  To compile this driver as a module, choose M here: the
 	  module will be called cy8ctmg110_ts.
 
+config TOUCHSCREEN_CYTTSP_CORE
+	tristate "Cypress TTSP touchscreen"
+	help
+         Say Y here if you have a touchscreen using controller from
+         the Cypress TrueTouch(tm) Standard Product family connected
+         to your system. You will also need to select appropriate
+         bus connection below.
+
+	 If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called cyttsp_core.
+
+config TOUCHSCREEN_CYTTSP_I2C
+        tristate "support I2C bus connection"
+        depends on TOUCHSCREEN_CYTTSP_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 cyttsp_i2c.
+
+config TOUCHSCREEN_CYTTSP_SPI
+        tristate "support SPI bus connection"
+        depends on TOUCHSCREEN_CYTTSP_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 cyttsp_spi.
+
 config TOUCHSCREEN_DA9034
 	tristate "Touchscreen support for Dialog Semiconductor DA9034"
 	depends on PMIC_DA903X
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 496091e..62f3265 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -18,6 +18,9 @@ obj-$(CONFIG_TOUCHSCREEN_AUO_PIXCIR)	+= auo-pixcir-ts.o
 obj-$(CONFIG_TOUCHSCREEN_BITSY)		+= h3600_ts_input.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_SPI)    += cyttsp_spi.o
 obj-$(CONFIG_TOUCHSCREEN_DA9034)	+= da9034-ts.o
 obj-$(CONFIG_TOUCHSCREEN_DYNAPRO)	+= dynapro.o
 obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE)	+= hampshire.o
diff --git a/drivers/input/touchscreen/cyttsp_core.c b/drivers/input/touchscreen/cyttsp_core.c
new file mode 100644
index 0000000..28d5ef0
--- /dev/null
+++ b/drivers/input/touchscreen/cyttsp_core.c
@@ -0,0 +1,682 @@
+/*
+ * Core Source for:
+ * Cypress TrueTouch(TM) Standard Product (TTSP) touchscreen drivers.
+ * For use with Cypress Txx3xx parts.
+ * Supported parts include:
+ * CY8CTST341
+ * CY8CTMA340
+ *
+ * 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.
+ *
+ * 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>
+ *
+ */
+
+#include "cyttsp_core.h"
+
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/input/mt.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+
+/* Bootloader number of command keys */
+#define CY_NUM_BL_KEYS    8
+
+/* helpers */
+#define GET_NUM_TOUCHES(x)          ((x) & 0x0F)
+#define IS_LARGE_AREA(x)            (((x) & 0x10) >> 4)
+#define IS_BAD_PKT(x)               ((x) & 0x20)
+#define IS_VALID_APP(x)             ((x) & 0x01)
+#define IS_OPERATIONAL_ERR(x)       ((x) & 0x3F)
+#define GET_HSTMODE(reg)            ((reg & 0x70) >> 4)
+#define GET_BOOTLOADERMODE(reg)     ((reg & 0x10) >> 4)
+
+#define CY_REG_BASE                 0x00
+#define CY_REG_ACT_DIST             0x1E
+#define CY_REG_ACT_INTRVL           0x1D
+#define CY_REG_TCH_TMOUT            (CY_REG_ACT_INTRVL+1)
+#define CY_REG_LP_INTRVL            (CY_REG_TCH_TMOUT+1)
+#define CY_MAXZ                     255
+#define CY_DELAY_DFLT               20 /* ms */
+#define CY_DELAY_MAX                500
+#define CY_ACT_DIST_DFLT            0xF8
+#define CY_HNDSHK_BIT               0x80
+/* device mode bits */
+#define CY_OPERATE_MODE             0x00
+#define CY_SYSINFO_MODE             0x10
+/* power mode select bits */
+#define CY_SOFT_RESET_MODE          0x01 /* return to Bootloader mode */
+#define CY_DEEP_SLEEP_MODE          0x02
+#define CY_LOW_POWER_MODE           0x04
+
+/* Slots management */
+#define CY_MAX_FINGER               4
+#define CY_MAX_ID                   16
+
+static const u8 bl_command[] = {
+	0x00,			/* file offset */
+	0xFF,			/* command */
+	0xA5,			/* exit bootloader command */
+	0, 1, 2, 3, 4, 5, 6, 7	/* default keys */
+};
+
+static int ttsp_read_block_data(struct cyttsp *ts, u8 command,
+	u8 length, void *buf)
+{
+	int retval = -1;
+	int tries;
+
+	if (!buf || !length)
+		return -EINVAL;
+
+	for (tries = 0; tries < CY_NUM_RETRY && (retval < 0); tries++) {
+		retval = ts->bus_ops->read(ts->dev, command, length, buf);
+		if (retval)
+			msleep(CY_DELAY_DFLT);
+	}
+
+	if (tries >= CY_NUM_RETRY)
+		return -EAGAIN;
+
+	return retval;
+}
+
+static int ttsp_write_block_data(struct cyttsp *ts, u8 command,
+	u8 length, void *buf)
+{
+	int retval = -1;
+	int tries;
+
+	if (!buf || !length)
+		return -EINVAL;
+
+	for (tries = 0; tries < CY_NUM_RETRY && (retval < 0); tries++) {
+		retval = ts->bus_ops->write(ts->dev, command, length, buf);
+		if (retval)
+			msleep(CY_DELAY_DFLT);
+	}
+
+	if (tries >= CY_NUM_RETRY)
+		return -EAGAIN;
+
+	return retval;
+}
+
+static int cyttsp_load_bl_regs(struct cyttsp *ts)
+{
+	memset(&(ts->bl_data), 0, sizeof(struct cyttsp_bootloader_data));
+
+	ts->bl_data.bl_status = 0x10;
+
+	return  ttsp_read_block_data(ts, CY_REG_BASE, sizeof(ts->bl_data),
+				     &ts->bl_data);
+}
+
+static int cyttsp_exit_bl_mode(struct cyttsp *ts)
+{
+	int retval;
+	u8 bl_cmd[sizeof(bl_command)];
+
+	memcpy(bl_cmd, bl_command, sizeof(bl_command));
+	if (ts->pdata->bl_keys)
+		memcpy(&bl_cmd[sizeof(bl_command) - CY_NUM_BL_KEYS],
+			ts->pdata->bl_keys, sizeof(bl_command));
+
+	retval = ttsp_write_block_data(ts, CY_REG_BASE,
+		sizeof(bl_cmd), (void *)bl_cmd);
+
+	if (retval < 0)
+		return retval;
+
+	/* wait for TTSP Device to complete the operation */
+	msleep(CY_DELAY_DFLT);
+	retval = cyttsp_load_bl_regs(ts);
+
+	if (retval || GET_BOOTLOADERMODE(ts->bl_data.bl_status))
+		return -ENODEV;
+
+	return retval;
+}
+
+static int cyttsp_set_operational_mode(struct cyttsp *ts)
+{
+	struct cyttsp_xydata xy_data;
+	int retval;
+	u8 cmd = CY_OPERATE_MODE;
+
+	retval = ttsp_write_block_data(ts, CY_REG_BASE, sizeof(cmd), &cmd);
+
+	if (retval < 0)
+		return retval;
+
+	/* wait for TTSP Device to complete switch to Operational mode */
+	retval = ttsp_read_block_data(ts, CY_REG_BASE,
+				      sizeof(xy_data), &(xy_data));
+
+	if (retval || xy_data.act_dist == CY_ACT_DIST_DFLT)
+		return -EAGAIN;
+
+	return retval;
+}
+
+static int cyttsp_set_sysinfo_mode(struct cyttsp *ts)
+{
+	int retval;
+	u8 cmd = CY_SYSINFO_MODE;
+
+	memset(&(ts->sysinfo_data), 0, sizeof(struct cyttsp_sysinfo_data));
+
+	/* switch to sysinfo mode */
+	retval = ttsp_write_block_data(ts, CY_REG_BASE, sizeof(cmd), &cmd);
+	if (retval < 0)
+		return retval;
+
+	/* read sysinfo registers */
+	msleep(CY_DELAY_DFLT);
+	retval = ttsp_read_block_data(ts, CY_REG_BASE, sizeof(ts->sysinfo_data),
+				      &ts->sysinfo_data);
+
+	if (retval || (!ts->sysinfo_data.tts_verh &&
+		       !ts->sysinfo_data.tts_verl))
+		return -EAGAIN;
+
+	return retval;
+}
+
+static int cyttsp_set_sysinfo_regs(struct cyttsp *ts)
+{
+	int retval = 0;
+
+	if (ts->pdata->act_intrvl != CY_ACT_INTRVL_DFLT ||
+		ts->pdata->tch_tmout != CY_TCH_TMOUT_DFLT ||
+		ts->pdata->lp_intrvl != CY_LP_INTRVL_DFLT) {
+
+		u8 intrvl_ray[3];
+
+		intrvl_ray[0] = ts->pdata->act_intrvl;
+		intrvl_ray[1] = ts->pdata->tch_tmout;
+		intrvl_ray[2] = ts->pdata->lp_intrvl;
+
+		/* set intrvl registers */
+		retval = ttsp_write_block_data(ts,
+				CY_REG_ACT_INTRVL,
+				sizeof(intrvl_ray), intrvl_ray);
+
+		msleep(CY_DELAY_DFLT);
+	}
+
+	return retval;
+}
+
+static int cyttsp_soft_reset(struct cyttsp *ts)
+{
+	int retval;
+	u8 cmd = CY_SOFT_RESET_MODE;
+	long wait_jiffies = msecs_to_jiffies(CY_DELAY_DFLT * CY_DELAY_MAX);
+	/* wait for interrupt to set ready completion */
+	INIT_COMPLETION(ts->bl_ready);
+
+	retval = ttsp_write_block_data(ts, CY_REG_BASE, sizeof(cmd), &cmd);
+	if (retval < 0)
+		return retval;
+
+	return wait_for_completion_timeout(&ts->bl_ready, wait_jiffies);
+}
+
+static int cyttsp_act_dist_setup(struct cyttsp *ts)
+{
+	int retval;
+	u8 act_dist_setup;
+
+	/* Init gesture; active distance setup */
+	act_dist_setup = ts->pdata->act_dist;
+	retval = ttsp_write_block_data(ts, CY_REG_ACT_DIST,
+		sizeof(act_dist_setup), &act_dist_setup);
+
+	return retval;
+}
+
+static int cyttsp_hndshk(struct cyttsp *ts, u8 hst_mode)
+{
+	u8 cmd;
+
+	cmd = hst_mode ^ CY_HNDSHK_BIT;
+
+	return ttsp_write_block_data(ts, CY_REG_BASE, sizeof(cmd), (u8 *)&cmd);
+}
+
+static void cyttsp_report_slot(struct input_dev *dev, int slot,
+			       int x, int y, int z)
+{
+	input_mt_slot(dev, slot);
+	input_mt_report_slot_state(dev, MT_TOOL_FINGER, true);
+	input_report_abs(dev, ABS_MT_POSITION_X, x);
+	input_report_abs(dev, ABS_MT_POSITION_Y, y);
+	input_report_abs(dev, ABS_MT_TOUCH_MAJOR, z);
+}
+
+static void cyttsp_report_slot_empty(struct input_dev *dev, int slot)
+{
+	input_mt_slot(dev, slot);
+	input_mt_report_slot_state(dev, MT_TOOL_FINGER, false);
+}
+
+static void cyttsp_extract_track_ids(struct cyttsp_xydata *xy_data, int *ids)
+{
+	ids[0] = xy_data->touch12_id >> 4;
+	ids[1] = xy_data->touch12_id & 0xF;
+	ids[2] = xy_data->touch34_id >> 4;
+	ids[3] = xy_data->touch34_id & 0xF;
+}
+
+static const struct cyttsp_tch *cyttsp_get_tch(struct cyttsp_xydata *xy_data,
+					       int idx)
+{
+	switch (idx) {
+	case 0:
+		return &xy_data->tch1;
+	case 1:
+		return &xy_data->tch2;
+	case 2:
+		return &xy_data->tch3;
+	case 3:
+		return  &xy_data->tch4;
+	default:
+		return NULL;
+	}
+}
+
+static int cyttsp_handle_tchdata(struct cyttsp *ts)
+{
+	struct cyttsp_xydata xy_data;
+	u8 num_cur_tch;
+	int i;
+	int ids[4];
+	const struct cyttsp_tch *tch = NULL;
+	int x, y, z;
+	int used = 0;
+
+	/* Get touch data from CYTTSP device */
+	if (ttsp_read_block_data(ts,
+		CY_REG_BASE, sizeof(struct cyttsp_xydata), &xy_data))
+		return 0;
+
+	/* provide flow control handshake */
+	if (ts->pdata->use_hndshk)
+		if (cyttsp_hndshk(ts, xy_data.hst_mode))
+			return 0;
+
+	/* determine number of currently active touches */
+	num_cur_tch = GET_NUM_TOUCHES(xy_data.tt_stat);
+
+	/* check for any error conditions */
+	if (ts->power_state == CY_IDLE_STATE)
+		return 0;
+	else if (GET_BOOTLOADERMODE(xy_data.tt_mode)) {
+		return -1;
+	} else if (IS_LARGE_AREA(xy_data.tt_stat) == 1) {
+		/* terminate all active tracks */
+		num_cur_tch = 0;
+		dev_dbg(ts->dev, "%s: Large area detected\n", __func__);
+	} else if (num_cur_tch > CY_MAX_FINGER) {
+		/* terminate all active tracks */
+		num_cur_tch = 0;
+		dev_dbg(ts->dev, "%s: Num touch error detected\n", __func__);
+	} else if (IS_BAD_PKT(xy_data.tt_mode)) {
+		/* terminate all active tracks */
+		num_cur_tch = 0;
+		dev_dbg(ts->dev, "%s: Invalid buffer detected\n", __func__);
+	}
+
+	cyttsp_extract_track_ids(&xy_data, ids);
+
+	for (i = 0; i < num_cur_tch; i++) {
+		used |= (1 << ids[i]);
+
+		tch = cyttsp_get_tch(&xy_data, i);
+
+		x = be16_to_cpu(tch->x);
+		y = be16_to_cpu(tch->y);
+		z = tch->z;
+
+		cyttsp_report_slot(ts->input, ids[i], x, y, z);
+	}
+
+	for (i = 0; i < CY_MAX_ID; i++)
+		if (!(used & (1 << i)))
+			cyttsp_report_slot_empty(ts->input, i);
+
+	input_sync(ts->input);
+
+	return 0;
+}
+
+static void cyttsp_pr_state(struct cyttsp *ts)
+{
+	static char *cyttsp_powerstate_string[] = {
+		"IDLE",
+		"ACTIVE",
+		"LOW_PWR",
+		"SLEEP",
+		"BOOTLOADER",
+		"INVALID"
+	};
+
+	dev_info(ts->dev, "%s: %s\n", __func__,
+		ts->power_state < CY_INVALID_STATE ?
+		cyttsp_powerstate_string[ts->power_state] :
+		"INVALID");
+}
+
+static irqreturn_t cyttsp_irq(int irq, void *handle)
+{
+	struct cyttsp *ts = handle;
+	int retval;
+
+	if (ts->power_state == CY_BL_STATE)
+		complete(&ts->bl_ready);
+	else {
+		/* process the touches */
+		retval = cyttsp_handle_tchdata(ts);
+
+		if (retval < 0) {
+			/*
+			 * TTSP device has reset back to bootloader mode.
+			 * Restore to operational mode.
+			 */
+			retval = cyttsp_exit_bl_mode(ts);
+			if (retval)
+				ts->power_state = CY_IDLE_STATE;
+			else
+				ts->power_state = CY_ACTIVE_STATE;
+			cyttsp_pr_state(ts);
+		}
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int cyttsp_power_on(struct cyttsp *ts)
+{
+	int retval = 0;
+
+	ts->power_state = CY_BL_STATE;
+	enable_irq(ts->irq);
+
+	retval = cyttsp_soft_reset(ts);
+	if (retval < 0)
+		return retval;
+
+	retval = cyttsp_load_bl_regs(ts);
+	if (retval < 0)
+		return retval;
+
+	if (GET_BOOTLOADERMODE(ts->bl_data.bl_status) &&
+	    IS_VALID_APP(ts->bl_data.bl_status))
+		retval = cyttsp_exit_bl_mode(ts);
+
+	if (retval < 0)
+		return retval;
+	else
+		ts->power_state = CY_IDLE_STATE;
+
+	if (GET_HSTMODE(ts->bl_data.bl_file) == CY_OPERATE_MODE &&
+	    !IS_OPERATIONAL_ERR(ts->bl_data.bl_status)) {
+		retval = cyttsp_set_sysinfo_mode(ts);
+		if (retval < 0)
+			return retval;
+
+		retval = cyttsp_set_sysinfo_regs(ts);
+		if (retval < 0)
+			return retval;
+
+		retval = cyttsp_set_operational_mode(ts);
+		if (retval < 0)
+			return retval;
+
+		/* init active distance */
+		retval = cyttsp_act_dist_setup(ts);
+		if (retval < 0)
+			return retval;
+
+		ts->power_state = CY_ACTIVE_STATE;
+
+		return 0;
+	}
+
+	return -ENODEV;
+}
+
+static int __cyttsp_enable(struct cyttsp *ts)
+{
+	struct cyttsp_xydata xydata;
+	int retval = 0;
+
+	if (ts->power_state != CY_ACTIVE_STATE) {
+
+		if (ts->pdata->wakeup)
+			retval = ts->pdata->wakeup();
+
+		if (retval == 0) {
+			retval = ttsp_read_block_data(ts, CY_REG_BASE,
+						      sizeof(xydata),
+						      &xydata);
+			if (retval == 0 &&
+			    !GET_HSTMODE(xydata.hst_mode)) {
+				ts->power_state = CY_ACTIVE_STATE;
+				enable_irq(ts->irq);
+			}
+		}
+	}
+
+	return retval;
+}
+
+static int __cyttsp_disable(struct cyttsp *ts)
+{
+	u8 cmd = CY_LOW_POWER_MODE;
+	int retval = 0;
+
+	if (ts->power_state == CY_ACTIVE_STATE) {
+		retval = ttsp_write_block_data(ts, CY_REG_BASE,
+					       sizeof(cmd), &cmd);
+		if (retval == 0) {
+			ts->power_state = CY_SLEEP_STATE;
+			disable_irq(ts->irq);
+		}
+	}
+
+	return retval;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int cyttsp_resume(struct device *dev)
+{
+	struct cyttsp *ts = dev_get_drvdata(dev);
+	int retval = 0;
+
+	mutex_lock(&ts->input->mutex);
+
+	if (ts->suspended)
+		retval = __cyttsp_enable(ts);
+
+	ts->suspended = false;
+
+	mutex_unlock(&ts->input->mutex);
+
+	return retval;
+}
+
+static int cyttsp_suspend(struct device *dev)
+{
+	struct cyttsp *ts = dev_get_drvdata(dev);
+	int retval = 0;
+
+	mutex_lock(&ts->input->mutex);
+
+	if (!ts->suspended)
+		retval = __cyttsp_disable(ts);
+
+	ts->suspended = true;
+
+	mutex_unlock(&ts->input->mutex);
+
+	return retval;
+}
+#endif
+
+SIMPLE_DEV_PM_OPS(cyttsp_pm_ops, cyttsp_suspend, cyttsp_resume);
+EXPORT_SYMBOL_GPL(cyttsp_pm_ops);
+
+static int cyttsp_open(struct input_dev *dev)
+{
+	struct cyttsp *ts = input_get_drvdata(dev);
+	int retval = 0;
+
+	if (!ts->on) {
+		retval = cyttsp_power_on(ts);
+
+		if (retval) {
+			cyttsp_pr_state(ts);
+			return retval;
+		} else
+			ts->on = true;
+	}
+
+	if (!ts->suspended)
+		retval = __cyttsp_enable(ts);
+
+	return retval;
+}
+
+static void cyttsp_close(struct input_dev *dev)
+{
+	struct cyttsp *ts = input_get_drvdata(dev);
+
+	if (!ts->suspended)
+		__cyttsp_disable(ts);
+}
+
+struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops,
+			    struct device *dev, int irq, size_t xfer_buf_size)
+{
+	const struct cyttsp_platform_data *pdata = dev->platform_data;
+	struct cyttsp *ts;
+	struct input_dev *input_dev;
+	int error;
+
+	if (!dev || !bus_ops || !pdata || !pdata->name || irq <= 0) {
+		error = -EINVAL;
+		goto err_out;
+	}
+
+	ts = kzalloc(sizeof(*ts) + xfer_buf_size, GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!ts || !input_dev) {
+		error = -ENOMEM;
+		goto err_free_mem;
+	}
+
+	ts->dev = dev;
+	ts->input = input_dev;
+	ts->pdata = dev->platform_data;
+	ts->bus_ops = bus_ops;
+	ts->irq = irq;
+	ts->suspended = false;
+	ts->on = false;
+
+	init_completion(&ts->bl_ready);
+	snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(dev));
+
+	if (pdata->init) {
+		error = pdata->init();
+		if (error) {
+			dev_err(ts->dev, "platform init failed, err: %d\n",
+				error);
+			goto err_free_mem;
+		}
+	}
+
+	input_dev->name = pdata->name;
+	input_dev->phys = ts->phys;
+	input_dev->id.bustype = bus_ops->bustype;
+	input_dev->dev.parent = ts->dev;
+
+	input_dev->open = cyttsp_open;
+	input_dev->close = cyttsp_close;
+
+	input_set_drvdata(input_dev, ts);
+
+	__set_bit(EV_ABS, input_dev->evbit);
+	input_set_abs_params(input_dev, ABS_MT_POSITION_X,
+			     0, pdata->maxx, 0, 0);
+	input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
+			     0, pdata->maxy, 0, 0);
+	input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
+			     0, CY_MAXZ, 0, 0);
+
+	input_mt_init_slots(input_dev, CY_MAX_ID);
+
+	error = request_threaded_irq(ts->irq, NULL, cyttsp_irq,
+				     IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+				     pdata->name, ts);
+	if (error) {
+		dev_err(ts->dev, "failed to request IRQ %d, err: %d\n",
+			ts->irq, error);
+		goto err_platform_exit;
+	}
+	disable_irq(ts->irq);
+
+	error = input_register_device(input_dev);
+	if (error) {
+		dev_err(ts->dev, "failed to register input device: %d\n",
+			error);
+		goto err_free_irq;
+	}
+
+	return ts;
+
+err_free_irq:
+	free_irq(ts->irq, ts);
+err_platform_exit:
+	if (pdata->exit)
+		pdata->exit();
+err_free_mem:
+	input_free_device(input_dev);
+	kfree(ts);
+err_out:
+	return ERR_PTR(error);
+}
+EXPORT_SYMBOL_GPL(cyttsp_probe);
+
+void cyttsp_remove(struct cyttsp *ts)
+{
+	free_irq(ts->irq, ts);
+	input_unregister_device(ts->input);
+	if (ts->pdata->exit)
+		ts->pdata->exit();
+	kfree(ts);
+}
+EXPORT_SYMBOL_GPL(cyttsp_remove);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard touchscreen driver core");
+MODULE_AUTHOR("Cypress");
+
diff --git a/drivers/input/touchscreen/cyttsp_core.h b/drivers/input/touchscreen/cyttsp_core.h
new file mode 100644
index 0000000..2b48c17
--- /dev/null
+++ b/drivers/input/touchscreen/cyttsp_core.h
@@ -0,0 +1,141 @@
+/*
+ * Header file for:
+ * Cypress TrueTouch(TM) Standard Product (TTSP) touchscreen drivers.
+ * For use with Cypress Txx3xx parts.
+ * Supported parts include:
+ * CY8CTST341
+ * CY8CTMA340
+ *
+ * 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.
+ *
+ * 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>
+ *
+ */
+
+
+#ifndef __CYTTSP_CORE_H__
+#define __CYTTSP_CORE_H__
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/input/cyttsp.h>
+
+#define CY_NUM_RETRY                16 /* max number of retries for read ops */
+
+struct cyttsp_tch {
+	__be16 x, y;
+	u8 z;
+} __packed;
+
+/* TrueTouch Standard Product Gen3 interface definition */
+struct cyttsp_xydata {
+	u8 hst_mode;
+	u8 tt_mode;
+	u8 tt_stat;
+	struct cyttsp_tch tch1;
+	u8 touch12_id;
+	struct cyttsp_tch tch2;
+	u8 gest_cnt;
+	u8 gest_id;
+	struct cyttsp_tch tch3;
+	u8 touch34_id;
+	struct cyttsp_tch tch4;
+	u8 tt_undef[3];
+	u8 act_dist;
+	u8 tt_reserved;
+} __packed;
+
+
+/* TTSP System Information interface definition */
+struct cyttsp_sysinfo_data {
+	u8 hst_mode;
+	u8 mfg_cmd;
+	u8 mfg_stat;
+	u8 cid[3];
+	u8 tt_undef1;
+	u8 uid[8];
+	u8 bl_verh;
+	u8 bl_verl;
+	u8 tts_verh;
+	u8 tts_verl;
+	u8 app_idh;
+	u8 app_idl;
+	u8 app_verh;
+	u8 app_verl;
+	u8 tt_undef[5];
+	u8 scn_typ;
+	u8 act_intrvl;
+	u8 tch_tmout;
+	u8 lp_intrvl;
+};
+
+/* TTSP Bootloader Register Map interface definition */
+#define CY_BL_CHKSUM_OK 0x01
+struct cyttsp_bootloader_data {
+	u8 bl_file;
+	u8 bl_status;
+	u8 bl_error;
+	u8 blver_hi;
+	u8 blver_lo;
+	u8 bld_blver_hi;
+	u8 bld_blver_lo;
+	u8 ttspver_hi;
+	u8 ttspver_lo;
+	u8 appid_hi;
+	u8 appid_lo;
+	u8 appver_hi;
+	u8 appver_lo;
+	u8 cid_0;
+	u8 cid_1;
+	u8 cid_2;
+};
+
+struct cyttsp_bus_ops {
+	u16 bustype;
+	int (*write)(struct device *dev,
+		     u8 addr, u8 length, const void *values);
+	int (*read)(struct device *dev, u8 addr, u8 length, void *values);
+};
+
+struct cyttsp {
+	struct device *dev;
+	int irq;
+	struct input_dev *input;
+	char phys[32];
+	const struct cyttsp_platform_data *pdata;
+	const struct cyttsp_bus_ops *bus_ops;
+	struct cyttsp_bootloader_data bl_data;
+	struct cyttsp_sysinfo_data sysinfo_data;
+	struct completion bl_ready;
+	enum cyttsp_powerstate power_state;
+	bool suspended;
+	bool on;
+
+	u8 xfer_buf[] ____cacheline_aligned;
+};
+
+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);
+
+extern const struct dev_pm_ops cyttsp_pm_ops;
+
+#endif /* __CYTTSP_CORE_H__ */
diff --git a/include/linux/input/cyttsp.h b/include/linux/input/cyttsp.h
new file mode 100644
index 0000000..f792603
--- /dev/null
+++ b/include/linux/input/cyttsp.h
@@ -0,0 +1,68 @@
+/*
+ * Header file for:
+ * Cypress TrueTouch(TM) Standard Product (TTSP) touchscreen drivers.
+ * For use with Cypress Txx3xx parts.
+ * Supported parts include:
+ * CY8CTST341
+ * CY8CTMA340
+ *
+ * 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.
+ *
+ * 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)
+ *
+ */
+#ifndef _CYTTSP_H_
+#define _CYTTSP_H_
+
+#define CY_SPI_NAME "cyttsp-spi"
+#define CY_I2C_NAME "cyttsp-i2c"
+/* Active Power state scanning/processing refresh interval */
+#define CY_ACT_INTRVL_DFLT 0x00 /* ms */
+/* touch timeout for the Active power */
+#define CY_TCH_TMOUT_DFLT 0xFF /* ms */
+/* Low Power state scanning/processing refresh interval */
+#define CY_LP_INTRVL_DFLT 0x0A /* ms */
+/* Active distance in pixels for a gesture to be reported */
+#define CY_ACT_DIST_DFLT 0xF8 /* pixels */
+
+enum cyttsp_powerstate {
+	CY_IDLE_STATE,
+	CY_ACTIVE_STATE,
+	CY_LOW_PWR_STATE,
+	CY_SLEEP_STATE,
+	CY_BL_STATE,
+	CY_INVALID_STATE	/* always last in the list */
+};
+
+struct cyttsp_platform_data {
+	u32 maxx;
+	u32 maxy;
+	bool use_hndshk;
+	u8 act_dist;	/* Active distance */
+	u8 act_intrvl;  /* Active refresh interval; ms */
+	u8 tch_tmout;   /* Active touch timeout; ms */
+	u8 lp_intrvl;   /* Low power refresh interval; ms */
+	int (*wakeup)(void);
+	int (*init)(void);
+	void (*exit)(void);
+	char *name;
+	s16 irq_gpio;
+	u8 *bl_keys;
+};
+
+#endif /* _CYTTSP_H_ */
-- 
1.7.7.5


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v10 2/3] Input: cyttsp - add support for Cypress TTSP touchscreen I2C bus interface
  2012-01-20  0:57 [PATCH v10 1/3] Input: cyttsp - Cypress TTSP capacitive multi-touch screen support Javier Martinez Canillas
@ 2012-01-20  0:57 ` Javier Martinez Canillas
  2012-01-20  0:57 ` [PATCH v10 3/3] Input: cyttsp - add support for Cypress TTSP touchscreen SPI " Javier Martinez Canillas
  2012-01-24  7:26 ` [PATCH v10 1/3] Input: cyttsp - Cypress TTSP capacitive multi-touch screen support Javier Martinez Canillas
  2 siblings, 0 replies; 14+ messages in thread
From: Javier Martinez Canillas @ 2012-01-20  0:57 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Henrik Rydberg, Mohan Pallaka, Kevin McNeely, Shubhrajyoti Datta,
	linux-input, Javier Martinez Canillas

The driver is composed of a core driver that process the data sent by
the contacts and a set of bus specific interface modules.

This patch add supports for the Cypress TTSP I2C bus interface.

Signed-off-by: Javier Martinez Canillas <javier@dowhile0.org>
---
 drivers/input/touchscreen/cyttsp_i2c.c |  137 ++++++++++++++++++++++++++++++++
 1 files changed, 137 insertions(+), 0 deletions(-)
 create mode 100644 drivers/input/touchscreen/cyttsp_i2c.c

diff --git a/drivers/input/touchscreen/cyttsp_i2c.c b/drivers/input/touchscreen/cyttsp_i2c.c
new file mode 100644
index 0000000..cdbf61d
--- /dev/null
+++ b/drivers/input/touchscreen/cyttsp_i2c.c
@@ -0,0 +1,137 @@
+/*
+ * Source for:
+ * Cypress TrueTouch(TM) Standard Product (TTSP) I2C touchscreen driver.
+ * For use with Cypress Txx3xx parts.
+ * Supported parts include:
+ * CY8CTST341
+ * CY8CTMA340
+ *
+ * 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.
+ *
+ * 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>
+ *
+ */
+
+#include "cyttsp_core.h"
+
+#include <linux/i2c.h>
+#include <linux/input.h>
+
+#define CY_I2C_DATA_SIZE  128
+
+static int cyttsp_i2c_read_block_data(struct device *dev,
+				      u8 addr, u8 length, void *values)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	int retval;
+
+	retval = i2c_master_send(client, &addr, 1);
+	if (retval < 0)
+		return retval;
+
+	retval = i2c_master_recv(client, values, length);
+
+	if (retval < 0)
+		return retval;
+
+	return (retval != length) ? -EIO : 0;
+}
+
+static int cyttsp_i2c_write_block_data(struct device *dev,
+				       u8 addr, u8 length, const void *values)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct cyttsp *ts = i2c_get_clientdata(client);
+	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,
+	.read           = cyttsp_i2c_read_block_data,
+};
+
+static int __devinit cyttsp_i2c_probe(struct i2c_client *client,
+				      const struct i2c_device_id *id)
+{
+	struct cyttsp *ts;
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		dev_err(&client->dev, "I2C functionality not Supported\n");
+		return -EIO;
+	}
+
+	ts = cyttsp_probe(&cyttsp_i2c_bus_ops, &client->dev, client->irq,
+			  CY_I2C_DATA_SIZE);
+
+	if (IS_ERR(ts))
+		return PTR_ERR(ts);
+
+	i2c_set_clientdata(client, ts);
+
+	return 0;
+}
+
+static int __devexit cyttsp_i2c_remove(struct i2c_client *client)
+{
+	struct cyttsp *ts = i2c_get_clientdata(client);
+
+	cyttsp_remove(ts);
+
+	return 0;
+}
+
+static const struct i2c_device_id cyttsp_i2c_id[] = {
+	{ CY_I2C_NAME, 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, cyttsp_i2c_id);
+
+static struct i2c_driver cyttsp_i2c_driver = {
+	.driver = {
+		.name   = CY_I2C_NAME,
+		.owner  = THIS_MODULE,
+		.pm     = &cyttsp_pm_ops,
+	},
+	.probe          = cyttsp_i2c_probe,
+	.remove         = __devexit_p(cyttsp_i2c_remove),
+	.id_table       = cyttsp_i2c_id,
+};
+
+static int __init cyttsp_i2c_init(void)
+{
+	return i2c_add_driver(&cyttsp_i2c_driver);
+}
+module_init(cyttsp_i2c_init);
+
+static void __exit cyttsp_i2c_exit(void)
+{
+	return i2c_del_driver(&cyttsp_i2c_driver);
+}
+module_exit(cyttsp_i2c_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard Product (TTSP) I2C driver");
+MODULE_AUTHOR("Cypress");
+MODULE_ALIAS("i2c:cyttsp");
-- 
1.7.7.5


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v10 3/3] Input: cyttsp - add support for Cypress TTSP touchscreen SPI bus interface
  2012-01-20  0:57 [PATCH v10 1/3] Input: cyttsp - Cypress TTSP capacitive multi-touch screen support Javier Martinez Canillas
  2012-01-20  0:57 ` [PATCH v10 2/3] Input: cyttsp - add support for Cypress TTSP touchscreen I2C bus interface Javier Martinez Canillas
@ 2012-01-20  0:57 ` Javier Martinez Canillas
  2012-01-24  7:26 ` [PATCH v10 1/3] Input: cyttsp - Cypress TTSP capacitive multi-touch screen support Javier Martinez Canillas
  2 siblings, 0 replies; 14+ messages in thread
From: Javier Martinez Canillas @ 2012-01-20  0:57 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Henrik Rydberg, Mohan Pallaka, Kevin McNeely, Shubhrajyoti Datta,
	linux-input, Javier Martinez Canillas

The driver is composed of a core driver that process the data sent by
the contacts and a set of bus specific interface modules.

This patch add supports for the Cypress TTSP SPI bus interface.

Signed-off-by: Javier Martinez Canillas <javier@dowhile0.org>
---
 drivers/input/touchscreen/cyttsp_spi.c |  245 ++++++++++++++++++++++++++++++++
 1 files changed, 245 insertions(+), 0 deletions(-)
 create mode 100644 drivers/input/touchscreen/cyttsp_spi.c

diff --git a/drivers/input/touchscreen/cyttsp_spi.c b/drivers/input/touchscreen/cyttsp_spi.c
new file mode 100644
index 0000000..3238c7d
--- /dev/null
+++ b/drivers/input/touchscreen/cyttsp_spi.c
@@ -0,0 +1,245 @@
+/*
+ * Source for:
+ * Cypress TrueTouch(TM) Standard Product (TTSP) SPI touchscreen driver.
+ * For use with Cypress Txx3xx parts.
+ * Supported parts include:
+ * CY8CTST341
+ * CY8CTMA340
+ *
+ * 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.
+ *
+ * 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>
+ *
+ */
+
+#include "cyttsp_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_CMD_BYTES  4
+#define CY_SPI_SYNC_BYTE  2
+#define CY_SPI_SYNC_ACK1  0x62 /* from protocol v.2 */
+#define CY_SPI_SYNC_ACK2  0x9D /* from protocol v.2 */
+#define CY_SPI_DATA_SIZE  128
+#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(u8 op, struct spi_device *spi,
+			   u8 reg, u8 *buf, int length)
+{
+	struct cyttsp *ts = spi_get_drvdata(spi);
+	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];
+	int retval;
+
+	if (length > CY_SPI_DATA_SIZE) {
+		dev_dbg(&spi->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_DATA_BUF_SIZE);
+
+	wr_buf[0] = 0x00; /* header byte 0 */
+	wr_buf[1] = 0xFF; /* header byte 1 */
+	wr_buf[2] = reg;  /* reg index */
+	wr_buf[3] = op;   /* r/~w */
+	if (op == CY_SPI_WR_OP)
+		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_CMD_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_dbg(&spi->dev,
+			"%s: bad operation code=%d\n", __func__, op);
+		return -EINVAL;
+	}
+
+	retval = spi_sync(spi, &msg);
+	if (retval < 0) {
+		dev_dbg(&spi->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_ACK1 ||
+	    rd_buf[CY_SPI_SYNC_BYTE + 1] != CY_SPI_SYNC_ACK2) {
+		int i;
+		for (i = 0; i < CY_SPI_CMD_BYTES; i++)
+			dev_dbg(&spi->dev,
+				"%s: test rd_buf[%d]:0x%02x\n",
+				__func__, i, rd_buf[i]);
+		for (i = 0; i < length; i++)
+			dev_dbg(&spi->dev,
+				"%s: test buf[%d]:0x%02x\n",
+				__func__, i, buf[i]);
+
+		/* signal ACK error so silent retry */
+		return 1;
+	}
+
+	return 0;
+}
+
+static int cyttsp_spi_read_block_data(struct device *dev,
+				      u8 addr, u8 length, void *data)
+{
+	struct spi_device *spi = to_spi_device(dev);
+	int retval;
+
+	retval = cyttsp_spi_xfer(CY_SPI_RD_OP, spi, addr, data, length);
+	if (retval < 0)
+		dev_err(dev, "cyttsp_spi_read_block_data failed, err: %d\n",
+			retval);
+
+	/*
+	 * Do not print the above error if the data sync bytes were not found.
+	 * This is a normal condition for the bootloader loader startup and need
+	 * to retry until data sync bytes are found.
+	 */
+	if (retval > 0)
+		retval = -EIO;  /* now signal fail; so retry can be done */
+
+	return retval;
+}
+
+static int cyttsp_spi_write_block_data(struct device *dev,
+				       u8 addr, u8 length, const void *data)
+{
+	struct spi_device *spi = to_spi_device(dev);
+	int retval;
+
+	retval = cyttsp_spi_xfer(CY_SPI_WR_OP, spi, addr, (void *)data, length);
+	if (retval < 0)
+		dev_err(dev, "cyttsp_spi_write_block_data failed, err: %d\n",
+			retval);
+
+	/*
+	 * Do not print the above error if the data sync bytes were not found.
+	 * This is a normal condition for the bootloader loader startup and need
+	 * to retry until data sync bytes are found.
+	 */
+	if (retval > 0)
+		retval = -EIO;  /* now signal fail; so retry can be done */
+
+	return retval;
+}
+
+static const struct cyttsp_bus_ops cyttsp_spi_bus_ops = {
+	.bustype        = BUS_SPI,
+	.write          = cyttsp_spi_write_block_data,
+	.read           = cyttsp_spi_read_block_data,
+};
+
+static int __devinit cyttsp_spi_probe(struct spi_device *spi)
+{
+	struct cyttsp *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 = cyttsp_probe(&cyttsp_spi_bus_ops, &spi->dev, spi->irq,
+			  CY_SPI_DATA_BUF_SIZE * 2);
+	if (IS_ERR(ts))
+		return PTR_ERR(ts);
+
+	spi_set_drvdata(spi, ts);
+
+	return 0;
+}
+
+static int __devexit cyttsp_spi_remove(struct spi_device *spi)
+{
+	struct cyttsp *ts = dev_get_drvdata(&spi->dev);
+
+	cyttsp_remove(ts);
+
+	return 0;
+}
+
+static struct spi_driver cyttsp_spi_driver = {
+	.driver = {
+		.name   = CY_SPI_NAME,
+		.owner  = THIS_MODULE,
+		.pm     = &cyttsp_pm_ops,
+	},
+	.probe  = cyttsp_spi_probe,
+	.remove = __devexit_p(cyttsp_spi_remove),
+};
+
+static int __init cyttsp_spi_init(void)
+{
+	return spi_register_driver(&cyttsp_spi_driver);
+}
+module_init(cyttsp_spi_init);
+
+static void __exit cyttsp_spi_exit(void)
+{
+	spi_unregister_driver(&cyttsp_spi_driver);
+}
+module_exit(cyttsp_spi_exit);
+
+MODULE_ALIAS("spi:cyttsp");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard Product (TTSP) SPI driver");
+MODULE_AUTHOR("Cypress");
+MODULE_ALIAS("spi:cyttsp");
+
-- 
1.7.7.5


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH v10 1/3] Input: cyttsp - Cypress TTSP capacitive multi-touch screen support
  2012-01-20  0:57 [PATCH v10 1/3] Input: cyttsp - Cypress TTSP capacitive multi-touch screen support Javier Martinez Canillas
  2012-01-20  0:57 ` [PATCH v10 2/3] Input: cyttsp - add support for Cypress TTSP touchscreen I2C bus interface Javier Martinez Canillas
  2012-01-20  0:57 ` [PATCH v10 3/3] Input: cyttsp - add support for Cypress TTSP touchscreen SPI " Javier Martinez Canillas
@ 2012-01-24  7:26 ` Javier Martinez Canillas
  2012-01-24  7:54   ` Dmitry Torokhov
  2012-01-24  9:26   ` Henrik Rydberg
  2 siblings, 2 replies; 14+ messages in thread
From: Javier Martinez Canillas @ 2012-01-24  7:26 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Henrik Rydberg, Mohan Pallaka, Kevin McNeely, Shubhrajyoti Datta,
	linux-input, Javier Martinez Canillas

On Fri, Jan 20, 2012 at 1:57 AM, Javier Martinez Canillas
<javier@dowhile0.org> wrote:
> Cypress TrueTouch(tm) Standard Product controllers are found in
> a wide range of embedded devices. This driver add support for a
> variety of TTSP controllers.
>
> Since the hardware is capable of tracking identifiable contacts, multi-touch
> protocol type B (stateful) is used to report contact information.
>
> The driver is composed of a core driver that process the data sent by
> the contacts and a set of bus specific interface modules. This patch
> adds the base core TTSP driver.
>
> Signed-off-by: Javier Martinez Canillas <javier@dowhile0.org>
> ---
>
> Changes for v10: Fix issues called out by Dmitry Torokhov
>        - Remove use_sleep and put device to sleep unconditionally on suspend
>        - Cleanup cyttsp_power_on() and remove cyttsp_bl_app_valid() function
>
>  drivers/input/touchscreen/Kconfig       |   31 ++
>  drivers/input/touchscreen/Makefile      |    3 +
>  drivers/input/touchscreen/cyttsp_core.c |  682 +++++++++++++++++++++++++++++++
>  drivers/input/touchscreen/cyttsp_core.h |  141 +++++++
>  include/linux/input/cyttsp.h            |   68 +++
>  5 files changed, 925 insertions(+), 0 deletions(-)

Hello Dmitry,

Any comments on this version?

Thanks for your patience

Henrik,

I didn't know if I should add your:

Reviewed-by: Henrik Rydberg <rydberg@euromail.se>

Since it is a new version of the patch-set. The only changes were
those asked by Dmitry though.

Thanks a lot and best regards,
Javier
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v10 1/3] Input: cyttsp - Cypress TTSP capacitive multi-touch screen support
  2012-01-24  7:26 ` [PATCH v10 1/3] Input: cyttsp - Cypress TTSP capacitive multi-touch screen support Javier Martinez Canillas
@ 2012-01-24  7:54   ` Dmitry Torokhov
  2012-01-24  8:09     ` Javier Martinez Canillas
  2012-01-26  0:12     ` Javier Martinez Canillas
  2012-01-24  9:26   ` Henrik Rydberg
  1 sibling, 2 replies; 14+ messages in thread
From: Dmitry Torokhov @ 2012-01-24  7:54 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: Henrik Rydberg, Mohan Pallaka, Kevin McNeely, Shubhrajyoti Datta,
	linux-input

On Tue, Jan 24, 2012 at 08:26:39AM +0100, Javier Martinez Canillas wrote:
> On Fri, Jan 20, 2012 at 1:57 AM, Javier Martinez Canillas
> <javier@dowhile0.org> wrote:
> > Cypress TrueTouch(tm) Standard Product controllers are found in
> > a wide range of embedded devices. This driver add support for a
> > variety of TTSP controllers.
> >
> > Since the hardware is capable of tracking identifiable contacts, multi-touch
> > protocol type B (stateful) is used to report contact information.
> >
> > The driver is composed of a core driver that process the data sent by
> > the contacts and a set of bus specific interface modules. This patch
> > adds the base core TTSP driver.
> >
> > Signed-off-by: Javier Martinez Canillas <javier@dowhile0.org>
> > ---
> >
> > Changes for v10: Fix issues called out by Dmitry Torokhov
> >        - Remove use_sleep and put device to sleep unconditionally on suspend
> >        - Cleanup cyttsp_power_on() and remove cyttsp_bl_app_valid() function
> >
> >  drivers/input/touchscreen/Kconfig       |   31 ++
> >  drivers/input/touchscreen/Makefile      |    3 +
> >  drivers/input/touchscreen/cyttsp_core.c |  682 +++++++++++++++++++++++++++++++
> >  drivers/input/touchscreen/cyttsp_core.h |  141 +++++++
> >  include/linux/input/cyttsp.h            |   68 +++
> >  5 files changed, 925 insertions(+), 0 deletions(-)
> 
> Hello Dmitry,
> 
> Any comments on this version?

Looking at it... If you do not hear from me by Wednesday please ping
me again.

Thanks.

-- 
Dmitry
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v10 1/3] Input: cyttsp - Cypress TTSP capacitive multi-touch screen support
  2012-01-24  7:54   ` Dmitry Torokhov
@ 2012-01-24  8:09     ` Javier Martinez Canillas
  2012-01-26  0:12     ` Javier Martinez Canillas
  1 sibling, 0 replies; 14+ messages in thread
From: Javier Martinez Canillas @ 2012-01-24  8:09 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Henrik Rydberg, Mohan Pallaka, Kevin McNeely, Shubhrajyoti Datta,
	linux-input

On Tue, Jan 24, 2012 at 8:54 AM, Dmitry Torokhov
<dmitry.torokhov@gmail.com> wrote:
> On Tue, Jan 24, 2012 at 08:26:39AM +0100, Javier Martinez Canillas wrote:
>> On Fri, Jan 20, 2012 at 1:57 AM, Javier Martinez Canillas
>> <javier@dowhile0.org> wrote:
>> > Cypress TrueTouch(tm) Standard Product controllers are found in
>> > a wide range of embedded devices. This driver add support for a
>> > variety of TTSP controllers.
>> >
>> > Since the hardware is capable of tracking identifiable contacts, multi-touch
>> > protocol type B (stateful) is used to report contact information.
>> >
>> > The driver is composed of a core driver that process the data sent by
>> > the contacts and a set of bus specific interface modules. This patch
>> > adds the base core TTSP driver.
>> >
>> > Signed-off-by: Javier Martinez Canillas <javier@dowhile0.org>
>> > ---
>> >
>> > Changes for v10: Fix issues called out by Dmitry Torokhov
>> >        - Remove use_sleep and put device to sleep unconditionally on suspend
>> >        - Cleanup cyttsp_power_on() and remove cyttsp_bl_app_valid() function
>> >
>> >  drivers/input/touchscreen/Kconfig       |   31 ++
>> >  drivers/input/touchscreen/Makefile      |    3 +
>> >  drivers/input/touchscreen/cyttsp_core.c |  682 +++++++++++++++++++++++++++++++
>> >  drivers/input/touchscreen/cyttsp_core.h |  141 +++++++
>> >  include/linux/input/cyttsp.h            |   68 +++
>> >  5 files changed, 925 insertions(+), 0 deletions(-)
>>
>> Hello Dmitry,
>>
>> Any comments on this version?
>
> Looking at it... If you do not hear from me by Wednesday please ping
> me again.
>
> Thanks.
>
> --
> Dmitry

Perfect, will do.

Thanks Dmitry!
--
Javier
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v10 1/3] Input: cyttsp - Cypress TTSP capacitive multi-touch screen support
  2012-01-24  7:26 ` [PATCH v10 1/3] Input: cyttsp - Cypress TTSP capacitive multi-touch screen support Javier Martinez Canillas
  2012-01-24  7:54   ` Dmitry Torokhov
@ 2012-01-24  9:26   ` Henrik Rydberg
  1 sibling, 0 replies; 14+ messages in thread
From: Henrik Rydberg @ 2012-01-24  9:26 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: Dmitry Torokhov, Mohan Pallaka, Kevin McNeely, Shubhrajyoti Datta,
	linux-input

Hi Javier,

> Henrik,
> 
> I didn't know if I should add your:
> 
> Reviewed-by: Henrik Rydberg <rydberg@euromail.se>
> 
> Since it is a new version of the patch-set. The only changes were
> those asked by Dmitry though.

Dmitry will most likely put it back in the final version, thanks for
asking.

Henrik

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v10 1/3] Input: cyttsp - Cypress TTSP capacitive multi-touch screen support
  2012-01-24  7:54   ` Dmitry Torokhov
  2012-01-24  8:09     ` Javier Martinez Canillas
@ 2012-01-26  0:12     ` Javier Martinez Canillas
  2012-01-27  8:18       ` Dmitry Torokhov
  1 sibling, 1 reply; 14+ messages in thread
From: Javier Martinez Canillas @ 2012-01-26  0:12 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Henrik Rydberg, Mohan Pallaka, Kevin McNeely, Shubhrajyoti Datta,
	linux-input

On Tue, Jan 24, 2012 at 8:54 AM, Dmitry Torokhov
<dmitry.torokhov@gmail.com> wrote:
> On Tue, Jan 24, 2012 at 08:26:39AM +0100, Javier Martinez Canillas wrote:
>> On Fri, Jan 20, 2012 at 1:57 AM, Javier Martinez Canillas
>> <javier@dowhile0.org> wrote:
>> > Cypress TrueTouch(tm) Standard Product controllers are found in
>> > a wide range of embedded devices. This driver add support for a
>> > variety of TTSP controllers.
>> >
>> > Since the hardware is capable of tracking identifiable contacts, multi-touch
>> > protocol type B (stateful) is used to report contact information.
>> >
>> > The driver is composed of a core driver that process the data sent by
>> > the contacts and a set of bus specific interface modules. This patch
>> > adds the base core TTSP driver.
>> >
>> > Signed-off-by: Javier Martinez Canillas <javier@dowhile0.org>
>> > ---
>> >
>> > Changes for v10: Fix issues called out by Dmitry Torokhov
>> >        - Remove use_sleep and put device to sleep unconditionally on suspend
>> >        - Cleanup cyttsp_power_on() and remove cyttsp_bl_app_valid() function
>> >
>> >  drivers/input/touchscreen/Kconfig       |   31 ++
>> >  drivers/input/touchscreen/Makefile      |    3 +
>> >  drivers/input/touchscreen/cyttsp_core.c |  682 +++++++++++++++++++++++++++++++
>> >  drivers/input/touchscreen/cyttsp_core.h |  141 +++++++
>> >  include/linux/input/cyttsp.h            |   68 +++
>> >  5 files changed, 925 insertions(+), 0 deletions(-)
>>
>> Hello Dmitry,
>>
>> Any comments on this version?
>
> Looking at it... If you do not hear from me by Wednesday please ping
> me again.
>
> Thanks.
>
> --
> Dmitry

ping :)

Regards,
Javier
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v10 1/3] Input: cyttsp - Cypress TTSP capacitive multi-touch screen support
  2012-01-26  0:12     ` Javier Martinez Canillas
@ 2012-01-27  8:18       ` Dmitry Torokhov
  2012-01-27 15:57         ` Javier Martinez Canillas
  0 siblings, 1 reply; 14+ messages in thread
From: Dmitry Torokhov @ 2012-01-27  8:18 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: Henrik Rydberg, Mohan Pallaka, Kevin McNeely, Shubhrajyoti Datta,
	linux-input

On Thu, Jan 26, 2012 at 01:12:50AM +0100, Javier Martinez Canillas wrote:
> On Tue, Jan 24, 2012 at 8:54 AM, Dmitry Torokhov
> <dmitry.torokhov@gmail.com> wrote:
> > On Tue, Jan 24, 2012 at 08:26:39AM +0100, Javier Martinez Canillas wrote:
> >> On Fri, Jan 20, 2012 at 1:57 AM, Javier Martinez Canillas
> >> <javier@dowhile0.org> wrote:
> >> > Cypress TrueTouch(tm) Standard Product controllers are found in
> >> > a wide range of embedded devices. This driver add support for a
> >> > variety of TTSP controllers.
> >> >
> >> > Since the hardware is capable of tracking identifiable contacts, multi-touch
> >> > protocol type B (stateful) is used to report contact information.
> >> >
> >> > The driver is composed of a core driver that process the data sent by
> >> > the contacts and a set of bus specific interface modules. This patch
> >> > adds the base core TTSP driver.
> >> >
> >> > Signed-off-by: Javier Martinez Canillas <javier@dowhile0.org>
> >> > ---
> >> >
> >> > Changes for v10: Fix issues called out by Dmitry Torokhov
> >> >        - Remove use_sleep and put device to sleep unconditionally on suspend
> >> >        - Cleanup cyttsp_power_on() and remove cyttsp_bl_app_valid() function
> >> >
> >> >  drivers/input/touchscreen/Kconfig       |   31 ++
> >> >  drivers/input/touchscreen/Makefile      |    3 +
> >> >  drivers/input/touchscreen/cyttsp_core.c |  682 +++++++++++++++++++++++++++++++
> >> >  drivers/input/touchscreen/cyttsp_core.h |  141 +++++++
> >> >  include/linux/input/cyttsp.h            |   68 +++
> >> >  5 files changed, 925 insertions(+), 0 deletions(-)
> >>
> >> Hello Dmitry,
> >>
> >> Any comments on this version?
> >
> > Looking at it... If you do not hear from me by Wednesday please ping
> > me again.
> >
> > Thanks.
> >
> > --
> > Dmitry
> 
> ping :)

Is it still Wednesday by any chance? ;)

Anyway, the driver looks pretty good, still below are some changes that
I'd like to get in as well:

- do not return EAGAIN when operation times out, EIO I believe suits
  better.
- introduce ttsp_send_command() to replace host of custom functions.
- reduce numver of states to 3 - IDLE, ACTIVE and BL mode.
  Suspended/full power is already covered by "suspended" attribute.
- streamline some functions.

Please see the FIXME comment in cyttsp_enable() - is there a generic way
to wake up the device, similarly to the way we put it to sleep?

Please tell me if the device still works with this patch.

Thanks!

-- 
Dmitry

Input: cyttsp - random edits

From: Dmitry Torokhov <dmitry.torokhov@gmail.com>

Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
---

 drivers/input/touchscreen/cyttsp_core.c |  562 ++++++++++++++-----------------
 drivers/input/touchscreen/cyttsp_core.h |   10 -
 drivers/input/touchscreen/cyttsp_i2c.c  |   44 +-
 drivers/input/touchscreen/cyttsp_spi.c  |   97 ++---
 include/linux/input/cyttsp.h            |    9 
 5 files changed, 321 insertions(+), 401 deletions(-)


diff --git a/drivers/input/touchscreen/cyttsp_core.c b/drivers/input/touchscreen/cyttsp_core.c
index 28d5ef0..ff74a33 100644
--- a/drivers/input/touchscreen/cyttsp_core.c
+++ b/drivers/input/touchscreen/cyttsp_core.c
@@ -27,8 +27,6 @@
  *
  */
 
-#include "cyttsp_core.h"
-
 #include <linux/delay.h>
 #include <linux/input.h>
 #include <linux/input/mt.h>
@@ -36,39 +34,41 @@
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 
+#include "cyttsp_core.h"
+
 /* Bootloader number of command keys */
-#define CY_NUM_BL_KEYS    8
+#define CY_NUM_BL_KEYS		8
 
 /* helpers */
-#define GET_NUM_TOUCHES(x)          ((x) & 0x0F)
-#define IS_LARGE_AREA(x)            (((x) & 0x10) >> 4)
-#define IS_BAD_PKT(x)               ((x) & 0x20)
-#define IS_VALID_APP(x)             ((x) & 0x01)
-#define IS_OPERATIONAL_ERR(x)       ((x) & 0x3F)
-#define GET_HSTMODE(reg)            ((reg & 0x70) >> 4)
-#define GET_BOOTLOADERMODE(reg)     ((reg & 0x10) >> 4)
-
-#define CY_REG_BASE                 0x00
-#define CY_REG_ACT_DIST             0x1E
-#define CY_REG_ACT_INTRVL           0x1D
-#define CY_REG_TCH_TMOUT            (CY_REG_ACT_INTRVL+1)
-#define CY_REG_LP_INTRVL            (CY_REG_TCH_TMOUT+1)
-#define CY_MAXZ                     255
-#define CY_DELAY_DFLT               20 /* ms */
-#define CY_DELAY_MAX                500
-#define CY_ACT_DIST_DFLT            0xF8
-#define CY_HNDSHK_BIT               0x80
+#define GET_NUM_TOUCHES(x)		((x) & 0x0F)
+#define IS_LARGE_AREA(x)		(((x) & 0x10) >> 4)
+#define IS_BAD_PKT(x)			((x) & 0x20)
+#define IS_VALID_APP(x)			((x) & 0x01)
+#define IS_OPERATIONAL_ERR(x)		((x) & 0x3F)
+#define GET_HSTMODE(reg)		(((reg) & 0x70) >> 4)
+#define GET_BOOTLOADERMODE(reg)		(((reg) & 0x10) >> 4)
+
+#define CY_REG_BASE			0x00
+#define CY_REG_ACT_DIST			0x1E
+#define CY_REG_ACT_INTRVL		0x1D
+#define CY_REG_TCH_TMOUT		(CY_REG_ACT_INTRVL + 1)
+#define CY_REG_LP_INTRVL		(CY_REG_TCH_TMOUT + 1)
+#define CY_MAXZ				255
+#define CY_DELAY_DFLT			20 /* ms */
+#define CY_DELAY_MAX			500
+#define CY_ACT_DIST_DFLT		0xF8
+#define CY_HNDSHK_BIT			0x80
 /* device mode bits */
-#define CY_OPERATE_MODE             0x00
-#define CY_SYSINFO_MODE             0x10
+#define CY_OPERATE_MODE			0x00
+#define CY_SYSINFO_MODE			0x10
 /* power mode select bits */
-#define CY_SOFT_RESET_MODE          0x01 /* return to Bootloader mode */
-#define CY_DEEP_SLEEP_MODE          0x02
-#define CY_LOW_POWER_MODE           0x04
+#define CY_SOFT_RESET_MODE		0x01 /* return to Bootloader mode */
+#define CY_DEEP_SLEEP_MODE		0x02
+#define CY_LOW_POWER_MODE		0x04
 
 /* Slots management */
-#define CY_MAX_FINGER               4
-#define CY_MAX_ID                   16
+#define CY_MAX_FINGER			4
+#define CY_MAX_ID			16
 
 static const u8 bl_command[] = {
 	0x00,			/* file offset */
@@ -78,60 +78,56 @@ static const u8 bl_command[] = {
 };
 
 static int ttsp_read_block_data(struct cyttsp *ts, u8 command,
-	u8 length, void *buf)
+				u8 length, void *buf)
 {
-	int retval = -1;
+	int error;
 	int tries;
 
-	if (!buf || !length)
-		return -EINVAL;
+	for (tries = 0; tries < CY_NUM_RETRY; tries++) {
+		error = ts->bus_ops->read(ts->dev, command, length, buf);
+		if (!error)
+			return 0;
 
-	for (tries = 0; tries < CY_NUM_RETRY && (retval < 0); tries++) {
-		retval = ts->bus_ops->read(ts->dev, command, length, buf);
-		if (retval)
-			msleep(CY_DELAY_DFLT);
+		msleep(CY_DELAY_DFLT);
 	}
 
-	if (tries >= CY_NUM_RETRY)
-		return -EAGAIN;
-
-	return retval;
+	return -EIO;
 }
 
 static int ttsp_write_block_data(struct cyttsp *ts, u8 command,
-	u8 length, void *buf)
+				 u8 length, void *buf)
 {
-	int retval = -1;
+	int error;
 	int tries;
 
-	if (!buf || !length)
-		return -EINVAL;
+	for (tries = 0; tries < CY_NUM_RETRY; tries++) {
+		error = ts->bus_ops->write(ts->dev, command, length, buf);
+		if (!error)
+			return 0;
 
-	for (tries = 0; tries < CY_NUM_RETRY && (retval < 0); tries++) {
-		retval = ts->bus_ops->write(ts->dev, command, length, buf);
-		if (retval)
-			msleep(CY_DELAY_DFLT);
+		msleep(CY_DELAY_DFLT);
 	}
 
-	if (tries >= CY_NUM_RETRY)
-		return -EAGAIN;
+	return -EIO;
+}
 
-	return retval;
+static int ttsp_send_command(struct cyttsp *ts, u8 cmd)
+{
+	return ttsp_write_block_data(ts, CY_REG_BASE, sizeof(cmd), &cmd);
 }
 
 static int cyttsp_load_bl_regs(struct cyttsp *ts)
 {
-	memset(&(ts->bl_data), 0, sizeof(struct cyttsp_bootloader_data));
-
+	memset(&ts->bl_data, 0, sizeof(ts->bl_data));
 	ts->bl_data.bl_status = 0x10;
 
-	return  ttsp_read_block_data(ts, CY_REG_BASE, sizeof(ts->bl_data),
-				     &ts->bl_data);
+	return ttsp_read_block_data(ts, CY_REG_BASE,
+				    sizeof(ts->bl_data), &ts->bl_data);
 }
 
 static int cyttsp_exit_bl_mode(struct cyttsp *ts)
 {
-	int retval;
+	int error;
 	u8 bl_cmd[sizeof(bl_command)];
 
 	memcpy(bl_cmd, bl_command, sizeof(bl_command));
@@ -139,65 +135,63 @@ static int cyttsp_exit_bl_mode(struct cyttsp *ts)
 		memcpy(&bl_cmd[sizeof(bl_command) - CY_NUM_BL_KEYS],
 			ts->pdata->bl_keys, sizeof(bl_command));
 
-	retval = ttsp_write_block_data(ts, CY_REG_BASE,
-		sizeof(bl_cmd), (void *)bl_cmd);
-
-	if (retval < 0)
-		return retval;
+	error = ttsp_write_block_data(ts, CY_REG_BASE,
+				      sizeof(bl_cmd), bl_cmd);
+	if (error)
+		return error;
 
 	/* wait for TTSP Device to complete the operation */
 	msleep(CY_DELAY_DFLT);
-	retval = cyttsp_load_bl_regs(ts);
 
-	if (retval || GET_BOOTLOADERMODE(ts->bl_data.bl_status))
-		return -ENODEV;
+	error = cyttsp_load_bl_regs(ts);
+	if (error)
+		return error;
 
-	return retval;
+	if (GET_BOOTLOADERMODE(ts->bl_data.bl_status))
+		return -EIO;
+
+	return 0;
 }
 
 static int cyttsp_set_operational_mode(struct cyttsp *ts)
 {
-	struct cyttsp_xydata xy_data;
-	int retval;
-	u8 cmd = CY_OPERATE_MODE;
-
-	retval = ttsp_write_block_data(ts, CY_REG_BASE, sizeof(cmd), &cmd);
+	int error;
 
-	if (retval < 0)
-		return retval;
+	error = ttsp_send_command(ts, CY_OPERATE_MODE);
+	if (error)
+		return error;
 
 	/* wait for TTSP Device to complete switch to Operational mode */
-	retval = ttsp_read_block_data(ts, CY_REG_BASE,
-				      sizeof(xy_data), &(xy_data));
+	error = ttsp_read_block_data(ts, CY_REG_BASE,
+				     sizeof(ts->xy_data), &ts->xy_data);
+	if (error)
+		return error;
 
-	if (retval || xy_data.act_dist == CY_ACT_DIST_DFLT)
-		return -EAGAIN;
-
-	return retval;
+	return ts->xy_data.act_dist == CY_ACT_DIST_DFLT ? -EIO : 0;
 }
 
 static int cyttsp_set_sysinfo_mode(struct cyttsp *ts)
 {
-	int retval;
-	u8 cmd = CY_SYSINFO_MODE;
+	int error;
 
-	memset(&(ts->sysinfo_data), 0, sizeof(struct cyttsp_sysinfo_data));
+	memset(&ts->sysinfo_data, 0, sizeof(ts->sysinfo_data));
 
 	/* switch to sysinfo mode */
-	retval = ttsp_write_block_data(ts, CY_REG_BASE, sizeof(cmd), &cmd);
-	if (retval < 0)
-		return retval;
+	error = ttsp_send_command(ts, CY_SYSINFO_MODE);
+	if (error)
+		return error;
 
 	/* read sysinfo registers */
 	msleep(CY_DELAY_DFLT);
-	retval = ttsp_read_block_data(ts, CY_REG_BASE, sizeof(ts->sysinfo_data),
+	error = ttsp_read_block_data(ts, CY_REG_BASE, sizeof(ts->sysinfo_data),
 				      &ts->sysinfo_data);
+	if (error)
+		return error;
 
-	if (retval || (!ts->sysinfo_data.tts_verh &&
-		       !ts->sysinfo_data.tts_verl))
-		return -EAGAIN;
+	if (!ts->sysinfo_data.tts_verh && !ts->sysinfo_data.tts_verl)
+		return -EIO;
 
-	return retval;
+	return 0;
 }
 
 static int cyttsp_set_sysinfo_regs(struct cyttsp *ts)
@@ -205,20 +199,18 @@ static int cyttsp_set_sysinfo_regs(struct cyttsp *ts)
 	int retval = 0;
 
 	if (ts->pdata->act_intrvl != CY_ACT_INTRVL_DFLT ||
-		ts->pdata->tch_tmout != CY_TCH_TMOUT_DFLT ||
-		ts->pdata->lp_intrvl != CY_LP_INTRVL_DFLT) {
-
-		u8 intrvl_ray[3];
+	    ts->pdata->tch_tmout != CY_TCH_TMOUT_DFLT ||
+	    ts->pdata->lp_intrvl != CY_LP_INTRVL_DFLT) {
 
-		intrvl_ray[0] = ts->pdata->act_intrvl;
-		intrvl_ray[1] = ts->pdata->tch_tmout;
-		intrvl_ray[2] = ts->pdata->lp_intrvl;
+		u8 intrvl_ray[] = {
+			ts->pdata->act_intrvl,
+			ts->pdata->tch_tmout,
+			ts->pdata->lp_intrvl
+		};
 
 		/* set intrvl registers */
-		retval = ttsp_write_block_data(ts,
-				CY_REG_ACT_INTRVL,
-				sizeof(intrvl_ray), intrvl_ray);
-
+		retval = ttsp_write_block_data(ts, CY_REG_ACT_INTRVL,
+					sizeof(intrvl_ray), intrvl_ray);
 		msleep(CY_DELAY_DFLT);
 	}
 
@@ -227,55 +219,36 @@ static int cyttsp_set_sysinfo_regs(struct cyttsp *ts)
 
 static int cyttsp_soft_reset(struct cyttsp *ts)
 {
+	unsigned long timeout;
 	int retval;
-	u8 cmd = CY_SOFT_RESET_MODE;
-	long wait_jiffies = msecs_to_jiffies(CY_DELAY_DFLT * CY_DELAY_MAX);
+
 	/* wait for interrupt to set ready completion */
 	INIT_COMPLETION(ts->bl_ready);
+	ts->state = CY_BL_STATE;
 
-	retval = ttsp_write_block_data(ts, CY_REG_BASE, sizeof(cmd), &cmd);
-	if (retval < 0)
-		return retval;
+	enable_irq(ts->irq);
 
-	return wait_for_completion_timeout(&ts->bl_ready, wait_jiffies);
-}
+	retval = ttsp_send_command(ts, CY_SOFT_RESET_MODE);
+	if (retval)
+		goto out;
 
-static int cyttsp_act_dist_setup(struct cyttsp *ts)
-{
-	int retval;
-	u8 act_dist_setup;
-
-	/* Init gesture; active distance setup */
-	act_dist_setup = ts->pdata->act_dist;
-	retval = ttsp_write_block_data(ts, CY_REG_ACT_DIST,
-		sizeof(act_dist_setup), &act_dist_setup);
+	timeout = wait_for_completion_timeout(&ts->bl_ready,
+			msecs_to_jiffies(CY_DELAY_DFLT * CY_DELAY_MAX));
+	retval = timeout ? 0 : -EIO;
 
+out:
+	ts->state = CY_IDLE_STATE;
+	disable_irq(ts->irq);
 	return retval;
 }
 
-static int cyttsp_hndshk(struct cyttsp *ts, u8 hst_mode)
-{
-	u8 cmd;
-
-	cmd = hst_mode ^ CY_HNDSHK_BIT;
-
-	return ttsp_write_block_data(ts, CY_REG_BASE, sizeof(cmd), (u8 *)&cmd);
-}
-
-static void cyttsp_report_slot(struct input_dev *dev, int slot,
-			       int x, int y, int z)
+static int cyttsp_act_dist_setup(struct cyttsp *ts)
 {
-	input_mt_slot(dev, slot);
-	input_mt_report_slot_state(dev, MT_TOOL_FINGER, true);
-	input_report_abs(dev, ABS_MT_POSITION_X, x);
-	input_report_abs(dev, ABS_MT_POSITION_Y, y);
-	input_report_abs(dev, ABS_MT_TOUCH_MAJOR, z);
-}
+	u8 act_dist_setup = ts->pdata->act_dist;
 
-static void cyttsp_report_slot_empty(struct input_dev *dev, int slot)
-{
-	input_mt_slot(dev, slot);
-	input_mt_report_slot_state(dev, MT_TOOL_FINGER, false);
+	/* Init gesture; active distance setup */
+	return ttsp_write_block_data(ts, CY_REG_ACT_DIST,
+				sizeof(act_dist_setup), &act_dist_setup);
 }
 
 static void cyttsp_extract_track_ids(struct cyttsp_xydata *xy_data, int *ids)
@@ -297,249 +270,231 @@ static const struct cyttsp_tch *cyttsp_get_tch(struct cyttsp_xydata *xy_data,
 	case 2:
 		return &xy_data->tch3;
 	case 3:
-		return  &xy_data->tch4;
+		return &xy_data->tch4;
 	default:
 		return NULL;
 	}
 }
 
-static int cyttsp_handle_tchdata(struct cyttsp *ts)
+static void cyttsp_report_tchdata(struct cyttsp *ts)
 {
-	struct cyttsp_xydata xy_data;
-	u8 num_cur_tch;
+	struct cyttsp_xydata *xy_data = &ts->xy_data;
+	struct input_dev *input = ts->input;
+	int num_tch = GET_NUM_TOUCHES(xy_data->tt_stat);
+	const struct cyttsp_tch *tch;
+	int ids[CY_MAX_ID];
 	int i;
-	int ids[4];
-	const struct cyttsp_tch *tch = NULL;
-	int x, y, z;
-	int used = 0;
-
-	/* Get touch data from CYTTSP device */
-	if (ttsp_read_block_data(ts,
-		CY_REG_BASE, sizeof(struct cyttsp_xydata), &xy_data))
-		return 0;
+	DECLARE_BITMAP(used, CY_MAX_ID);
 
-	/* provide flow control handshake */
-	if (ts->pdata->use_hndshk)
-		if (cyttsp_hndshk(ts, xy_data.hst_mode))
-			return 0;
-
-	/* determine number of currently active touches */
-	num_cur_tch = GET_NUM_TOUCHES(xy_data.tt_stat);
-
-	/* check for any error conditions */
-	if (ts->power_state == CY_IDLE_STATE)
-		return 0;
-	else if (GET_BOOTLOADERMODE(xy_data.tt_mode)) {
-		return -1;
-	} else if (IS_LARGE_AREA(xy_data.tt_stat) == 1) {
+	if (IS_LARGE_AREA(xy_data->tt_stat) == 1) {
 		/* terminate all active tracks */
-		num_cur_tch = 0;
+		num_tch = 0;
 		dev_dbg(ts->dev, "%s: Large area detected\n", __func__);
-	} else if (num_cur_tch > CY_MAX_FINGER) {
+	} else if (num_tch > CY_MAX_FINGER) {
 		/* terminate all active tracks */
-		num_cur_tch = 0;
+		num_tch = 0;
 		dev_dbg(ts->dev, "%s: Num touch error detected\n", __func__);
-	} else if (IS_BAD_PKT(xy_data.tt_mode)) {
+	} else if (IS_BAD_PKT(xy_data->tt_mode)) {
 		/* terminate all active tracks */
-		num_cur_tch = 0;
+		num_tch = 0;
 		dev_dbg(ts->dev, "%s: Invalid buffer detected\n", __func__);
 	}
 
-	cyttsp_extract_track_ids(&xy_data, ids);
+	cyttsp_extract_track_ids(xy_data, ids);
 
-	for (i = 0; i < num_cur_tch; i++) {
-		used |= (1 << ids[i]);
+	bitmap_zero(used, CY_MAX_ID);
 
-		tch = cyttsp_get_tch(&xy_data, i);
+	for (i = 0; i < num_tch; i++) {
+		tch = cyttsp_get_tch(xy_data, ids[i]);
 
-		x = be16_to_cpu(tch->x);
-		y = be16_to_cpu(tch->y);
-		z = tch->z;
+		input_mt_slot(input, ids[i]);
+		input_mt_report_slot_state(input, MT_TOOL_FINGER, true);
+		input_report_abs(input, ABS_MT_POSITION_X, be16_to_cpu(tch->x));
+		input_report_abs(input, ABS_MT_POSITION_Y, be16_to_cpu(tch->y));
+		input_report_abs(input, ABS_MT_TOUCH_MAJOR, tch->z);
 
-		cyttsp_report_slot(ts->input, ids[i], x, y, z);
+		__set_bit(ids[i], used);
 	}
 
-	for (i = 0; i < CY_MAX_ID; i++)
-		if (!(used & (1 << i)))
-			cyttsp_report_slot_empty(ts->input, i);
+	for (i = 0; i < CY_MAX_ID; i++) {
+		if (test_bit(i, used))
+			continue;
 
-	input_sync(ts->input);
-
-	return 0;
-}
+		input_mt_slot(input, i);
+		input_mt_report_slot_state(input, MT_TOOL_FINGER, false);
+	}
 
-static void cyttsp_pr_state(struct cyttsp *ts)
-{
-	static char *cyttsp_powerstate_string[] = {
-		"IDLE",
-		"ACTIVE",
-		"LOW_PWR",
-		"SLEEP",
-		"BOOTLOADER",
-		"INVALID"
-	};
-
-	dev_info(ts->dev, "%s: %s\n", __func__,
-		ts->power_state < CY_INVALID_STATE ?
-		cyttsp_powerstate_string[ts->power_state] :
-		"INVALID");
+	input_sync(input);
 }
 
 static irqreturn_t cyttsp_irq(int irq, void *handle)
 {
 	struct cyttsp *ts = handle;
-	int retval;
+	int error;
 
-	if (ts->power_state == CY_BL_STATE)
+	if (unlikely(ts->state == CY_BL_STATE)) {
 		complete(&ts->bl_ready);
-	else {
-		/* process the touches */
-		retval = cyttsp_handle_tchdata(ts);
-
-		if (retval < 0) {
-			/*
-			 * TTSP device has reset back to bootloader mode.
-			 * Restore to operational mode.
-			 */
-			retval = cyttsp_exit_bl_mode(ts);
-			if (retval)
-				ts->power_state = CY_IDLE_STATE;
-			else
-				ts->power_state = CY_ACTIVE_STATE;
-			cyttsp_pr_state(ts);
+		goto out;
+	}
+
+	/* Get touch data from CYTTSP device */
+	error = ttsp_read_block_data(ts, CY_REG_BASE,
+				 sizeof(struct cyttsp_xydata), &ts->xy_data);
+	if (error)
+		goto out;
+
+	/* provide flow control handshake */
+	if (ts->pdata->use_hndshk) {
+		error = ttsp_send_command(ts,
+				ts->xy_data.hst_mode ^ CY_HNDSHK_BIT);
+		if (error)
+			goto out;
+	}
+
+	if (unlikely(ts->state == CY_IDLE_STATE))
+		goto out;
+
+	if (GET_BOOTLOADERMODE(ts->xy_data.tt_mode)) {
+		/*
+		 * TTSP device has reset back to bootloader mode.
+		 * Restore to operational mode.
+		 */
+		error = cyttsp_exit_bl_mode(ts);
+		if (error) {
+			dev_err(ts->dev,
+				"Could not return to operational mode, err: %d\n",
+				error);
+			ts->state = CY_IDLE_STATE;
 		}
+	} else {
+		cyttsp_report_tchdata(ts);
 	}
 
+out:
 	return IRQ_HANDLED;
 }
 
 static int cyttsp_power_on(struct cyttsp *ts)
 {
-	int retval = 0;
-
-	ts->power_state = CY_BL_STATE;
-	enable_irq(ts->irq);
+	int error;
 
-	retval = cyttsp_soft_reset(ts);
-	if (retval < 0)
-		return retval;
+	error = cyttsp_soft_reset(ts);
+	if (error)
+		return error;
 
-	retval = cyttsp_load_bl_regs(ts);
-	if (retval < 0)
-		return retval;
+	error = cyttsp_load_bl_regs(ts);
+	if (error)
+		return error;
 
 	if (GET_BOOTLOADERMODE(ts->bl_data.bl_status) &&
-	    IS_VALID_APP(ts->bl_data.bl_status))
-		retval = cyttsp_exit_bl_mode(ts);
-
-	if (retval < 0)
-		return retval;
-	else
-		ts->power_state = CY_IDLE_STATE;
+	    IS_VALID_APP(ts->bl_data.bl_status)) {
+		error = cyttsp_exit_bl_mode(ts);
+		if (error)
+			return error;
+	}
 
-	if (GET_HSTMODE(ts->bl_data.bl_file) == CY_OPERATE_MODE &&
-	    !IS_OPERATIONAL_ERR(ts->bl_data.bl_status)) {
-		retval = cyttsp_set_sysinfo_mode(ts);
-		if (retval < 0)
-			return retval;
+	if (GET_HSTMODE(ts->bl_data.bl_file) != CY_OPERATE_MODE ||
+	    IS_OPERATIONAL_ERR(ts->bl_data.bl_status)) {
+		return -ENODEV;
+	}
 
-		retval = cyttsp_set_sysinfo_regs(ts);
-		if (retval < 0)
-			return retval;
+	error = cyttsp_set_sysinfo_mode(ts);
+	if (error)
+		return error;
 
-		retval = cyttsp_set_operational_mode(ts);
-		if (retval < 0)
-			return retval;
+	error = cyttsp_set_sysinfo_regs(ts);
+	if (error)
+		return error;
 
-		/* init active distance */
-		retval = cyttsp_act_dist_setup(ts);
-		if (retval < 0)
-			return retval;
+	error = cyttsp_set_operational_mode(ts);
+	if (error)
+		return error;
 
-		ts->power_state = CY_ACTIVE_STATE;
+	/* init active distance */
+	error = cyttsp_act_dist_setup(ts);
+	if (error)
+		return error;
 
-		return 0;
-	}
+	ts->state = CY_ACTIVE_STATE;
 
-	return -ENODEV;
+	return 0;
 }
 
-static int __cyttsp_enable(struct cyttsp *ts)
+static int cyttsp_enable(struct cyttsp *ts)
 {
-	struct cyttsp_xydata xydata;
-	int retval = 0;
+	int error;
 
-	if (ts->power_state != CY_ACTIVE_STATE) {
+	// FIXME: Why do we need wakeup? The system is already woken up
+	// so I assume this is device wakeup. It should be generic, just
+	// like suspend is generic.
+	// Is there CY_FULL_POWER_MODE that is opposite to CY_LOW_POWER_MODE?
+	if (ts->pdata->wakeup) {
+		error = ts->pdata->wakeup();
+		if (error)
+			return error;
+	}
 
-		if (ts->pdata->wakeup)
-			retval = ts->pdata->wakeup();
+	error = ttsp_read_block_data(ts, CY_REG_BASE,
+				     sizeof(ts->xy_data), &ts->xy_data);
+	if (error)
+		return error;
 
-		if (retval == 0) {
-			retval = ttsp_read_block_data(ts, CY_REG_BASE,
-						      sizeof(xydata),
-						      &xydata);
-			if (retval == 0 &&
-			    !GET_HSTMODE(xydata.hst_mode)) {
-				ts->power_state = CY_ACTIVE_STATE;
-				enable_irq(ts->irq);
-			}
-		}
-	}
+	if (GET_HSTMODE(ts->xy_data.hst_mode))
+		return -EIO;
 
-	return retval;
+	enable_irq(ts->irq);
+
+	return 0;
 }
 
-static int __cyttsp_disable(struct cyttsp *ts)
+static int cyttsp_disable(struct cyttsp *ts)
 {
-	u8 cmd = CY_LOW_POWER_MODE;
-	int retval = 0;
+	int error;
 
-	if (ts->power_state == CY_ACTIVE_STATE) {
-		retval = ttsp_write_block_data(ts, CY_REG_BASE,
-					       sizeof(cmd), &cmd);
-		if (retval == 0) {
-			ts->power_state = CY_SLEEP_STATE;
-			disable_irq(ts->irq);
-		}
-	}
+	error = ttsp_send_command(ts, CY_LOW_POWER_MODE);
+	if (error)
+		return error;
 
-	return retval;
+	disable_irq(ts->irq);
+
+	return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
-static int cyttsp_resume(struct device *dev)
+static int cyttsp_suspend(struct device *dev)
 {
 	struct cyttsp *ts = dev_get_drvdata(dev);
 	int retval = 0;
 
 	mutex_lock(&ts->input->mutex);
 
-	if (ts->suspended)
-		retval = __cyttsp_enable(ts);
-
-	ts->suspended = false;
+	if (ts->input->users) {
+		retval = cyttsp_disable(ts);
+		if (retval == 0)
+			ts->suspended = true;
+	}
 
 	mutex_unlock(&ts->input->mutex);
 
 	return retval;
 }
 
-static int cyttsp_suspend(struct device *dev)
+static int cyttsp_resume(struct device *dev)
 {
 	struct cyttsp *ts = dev_get_drvdata(dev);
-	int retval = 0;
 
 	mutex_lock(&ts->input->mutex);
 
-	if (!ts->suspended)
-		retval = __cyttsp_disable(ts);
+	if (ts->input->users)
+		cyttsp_enable(ts);
 
-	ts->suspended = true;
+	ts->suspended = false;
 
 	mutex_unlock(&ts->input->mutex);
 
-	return retval;
+	return 0;
 }
+
 #endif
 
 SIMPLE_DEV_PM_OPS(cyttsp_pm_ops, cyttsp_suspend, cyttsp_resume);
@@ -550,18 +505,8 @@ static int cyttsp_open(struct input_dev *dev)
 	struct cyttsp *ts = input_get_drvdata(dev);
 	int retval = 0;
 
-	if (!ts->on) {
-		retval = cyttsp_power_on(ts);
-
-		if (retval) {
-			cyttsp_pr_state(ts);
-			return retval;
-		} else
-			ts->on = true;
-	}
-
 	if (!ts->suspended)
-		retval = __cyttsp_enable(ts);
+		retval = cyttsp_enable(ts);
 
 	return retval;
 }
@@ -571,7 +516,7 @@ static void cyttsp_close(struct input_dev *dev)
 	struct cyttsp *ts = input_get_drvdata(dev);
 
 	if (!ts->suspended)
-		__cyttsp_disable(ts);
+		cyttsp_disable(ts);
 }
 
 struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops,
@@ -599,8 +544,6 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops,
 	ts->pdata = dev->platform_data;
 	ts->bus_ops = bus_ops;
 	ts->irq = irq;
-	ts->suspended = false;
-	ts->on = false;
 
 	init_completion(&ts->bl_ready);
 	snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(dev));
@@ -642,6 +585,11 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops,
 			ts->irq, error);
 		goto err_platform_exit;
 	}
+
+	error = cyttsp_power_on(ts);
+	if (error)
+		goto err_free_irq;
+
 	disable_irq(ts->irq);
 
 	error = input_register_device(input_dev);
diff --git a/drivers/input/touchscreen/cyttsp_core.h b/drivers/input/touchscreen/cyttsp_core.h
index 866f5e2..560f959 100644
--- a/drivers/input/touchscreen/cyttsp_core.h
+++ b/drivers/input/touchscreen/cyttsp_core.h
@@ -115,6 +115,12 @@ struct cyttsp_bus_ops {
 	int (*read)(struct device *dev, u8 addr, u8 length, void *values);
 };
 
+enum cyttsp_state {
+	CY_IDLE_STATE,
+	CY_ACTIVE_STATE,
+	CY_BL_STATE,
+};
+
 struct cyttsp {
 	struct device *dev;
 	int irq;
@@ -124,10 +130,10 @@ struct cyttsp {
 	const struct cyttsp_bus_ops *bus_ops;
 	struct cyttsp_bootloader_data bl_data;
 	struct cyttsp_sysinfo_data sysinfo_data;
+	struct cyttsp_xydata xy_data;
 	struct completion bl_ready;
-	enum cyttsp_powerstate power_state;
+	enum cyttsp_state state;
 	bool suspended;
-	bool on;
 
 	u8 xfer_buf[] ____cacheline_aligned;
 };
diff --git a/drivers/input/touchscreen/cyttsp_i2c.c b/drivers/input/touchscreen/cyttsp_i2c.c
index cdbf61d..6394c8e 100644
--- a/drivers/input/touchscreen/cyttsp_i2c.c
+++ b/drivers/input/touchscreen/cyttsp_i2c.c
@@ -32,24 +32,33 @@
 #include <linux/i2c.h>
 #include <linux/input.h>
 
-#define CY_I2C_DATA_SIZE  128
+#define CY_I2C_DATA_SIZE	128
 
 static int cyttsp_i2c_read_block_data(struct device *dev,
 				      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_master_send(client, &addr, 1);
+	retval = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
 	if (retval < 0)
 		return retval;
 
-	retval = i2c_master_recv(client, values, length);
-
-	if (retval < 0)
-		return retval;
-
-	return (retval != length) ? -EIO : 0;
+	return retval != ARRAY_SIZE(msgs) ? -EIO : 0;
 }
 
 static int cyttsp_i2c_write_block_data(struct device *dev,
@@ -61,14 +70,15 @@ static int cyttsp_i2c_write_block_data(struct device *dev,
 
 	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;
+	return retval < 0 ? retval : 0;
 }
 
 static const struct cyttsp_bus_ops cyttsp_i2c_bus_ops = {
-	.bustype        = BUS_I2C,
-	.write          = cyttsp_i2c_write_block_data,
+	.bustype	= BUS_I2C,
+	.write		= cyttsp_i2c_write_block_data,
 	.read           = cyttsp_i2c_read_block_data,
 };
 
@@ -110,13 +120,13 @@ MODULE_DEVICE_TABLE(i2c, cyttsp_i2c_id);
 
 static struct i2c_driver cyttsp_i2c_driver = {
 	.driver = {
-		.name   = CY_I2C_NAME,
-		.owner  = THIS_MODULE,
-		.pm     = &cyttsp_pm_ops,
+		.name	= CY_I2C_NAME,
+		.owner	= THIS_MODULE,
+		.pm	= &cyttsp_pm_ops,
 	},
-	.probe          = cyttsp_i2c_probe,
-	.remove         = __devexit_p(cyttsp_i2c_remove),
-	.id_table       = cyttsp_i2c_id,
+	.probe		= cyttsp_i2c_probe,
+	.remove		= __devexit_p(cyttsp_i2c_remove),
+	.id_table	= cyttsp_i2c_id,
 };
 
 static int __init cyttsp_i2c_init(void)
diff --git a/drivers/input/touchscreen/cyttsp_spi.c b/drivers/input/touchscreen/cyttsp_spi.c
index 3238c7d..d404cd2 100644
--- a/drivers/input/touchscreen/cyttsp_spi.c
+++ b/drivers/input/touchscreen/cyttsp_spi.c
@@ -33,29 +33,30 @@
 #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_CMD_BYTES  4
-#define CY_SPI_SYNC_BYTE  2
-#define CY_SPI_SYNC_ACK1  0x62 /* from protocol v.2 */
-#define CY_SPI_SYNC_ACK2  0x9D /* from protocol v.2 */
-#define CY_SPI_DATA_SIZE  128
-#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(u8 op, struct spi_device *spi,
+#define CY_SPI_WR_OP		0x00 /* r/~w */
+#define CY_SPI_RD_OP		0x01
+#define CY_SPI_CMD_BYTES	4
+#define CY_SPI_SYNC_BYTE	2
+#define CY_SPI_SYNC_ACK1	0x62 /* from protocol v.2 */
+#define CY_SPI_SYNC_ACK2	0x9D /* from protocol v.2 */
+#define CY_SPI_DATA_SIZE	128
+#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(u8 op, struct device *dev,
 			   u8 reg, u8 *buf, int length)
 {
+	struct spi_device *spi = to_spi_device(dev);
 	struct cyttsp *ts = spi_get_drvdata(spi);
 	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];
 	int retval;
+	int i;
 
 	if (length > CY_SPI_DATA_SIZE) {
-		dev_dbg(&spi->dev, "%s: length %d is too big.\n",
-			__func__, length);
+		dev_err(dev, "%s: length %d is too big.\n", __func__, length);
 		return -EINVAL;
 	}
 
@@ -94,15 +95,13 @@ static int cyttsp_spi_xfer(u8 op, struct spi_device *spi,
 		break;
 
 	default:
-		dev_dbg(&spi->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(&spi->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);
 
 		/*
@@ -114,18 +113,17 @@ static int cyttsp_spi_xfer(u8 op, struct spi_device *spi,
 
 	if (rd_buf[CY_SPI_SYNC_BYTE] != CY_SPI_SYNC_ACK1 ||
 	    rd_buf[CY_SPI_SYNC_BYTE + 1] != CY_SPI_SYNC_ACK2) {
-		int i;
+
+		dev_dbg(dev, "%s: operation %d failed\n", __func__, op);
+
 		for (i = 0; i < CY_SPI_CMD_BYTES; i++)
-			dev_dbg(&spi->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(&spi->dev,
-				"%s: test buf[%d]:0x%02x\n",
+			dev_dbg(dev, "%s: test buf[%d]:0x%02x\n",
 				__func__, i, buf[i]);
 
-		/* signal ACK error so silent retry */
-		return 1;
+		return -EIO;
 	}
 
 	return 0;
@@ -134,51 +132,19 @@ static int cyttsp_spi_xfer(u8 op, struct spi_device *spi,
 static int cyttsp_spi_read_block_data(struct device *dev,
 				      u8 addr, u8 length, void *data)
 {
-	struct spi_device *spi = to_spi_device(dev);
-	int retval;
-
-	retval = cyttsp_spi_xfer(CY_SPI_RD_OP, spi, addr, data, length);
-	if (retval < 0)
-		dev_err(dev, "cyttsp_spi_read_block_data failed, err: %d\n",
-			retval);
-
-	/*
-	 * Do not print the above error if the data sync bytes were not found.
-	 * This is a normal condition for the bootloader loader startup and need
-	 * to retry until data sync bytes are found.
-	 */
-	if (retval > 0)
-		retval = -EIO;  /* now signal fail; so retry can be done */
-
-	return retval;
+	return cyttsp_spi_xfer(CY_SPI_RD_OP, dev, addr, data, length);
 }
 
 static int cyttsp_spi_write_block_data(struct device *dev,
 				       u8 addr, u8 length, const void *data)
 {
-	struct spi_device *spi = to_spi_device(dev);
-	int retval;
-
-	retval = cyttsp_spi_xfer(CY_SPI_WR_OP, spi, addr, (void *)data, length);
-	if (retval < 0)
-		dev_err(dev, "cyttsp_spi_write_block_data failed, err: %d\n",
-			retval);
-
-	/*
-	 * Do not print the above error if the data sync bytes were not found.
-	 * This is a normal condition for the bootloader loader startup and need
-	 * to retry until data sync bytes are found.
-	 */
-	if (retval > 0)
-		retval = -EIO;  /* now signal fail; so retry can be done */
-
-	return retval;
+	return cyttsp_spi_xfer(CY_SPI_WR_OP, dev, addr, (void *)data, length);
 }
 
 static const struct cyttsp_bus_ops cyttsp_spi_bus_ops = {
-	.bustype        = BUS_SPI,
-	.write          = cyttsp_spi_write_block_data,
-	.read           = cyttsp_spi_read_block_data,
+	.bustype	= BUS_SPI,
+	.write		= cyttsp_spi_write_block_data,
+	.read		= cyttsp_spi_read_block_data,
 };
 
 static int __devinit cyttsp_spi_probe(struct spi_device *spi)
@@ -208,7 +174,7 @@ static int __devinit cyttsp_spi_probe(struct spi_device *spi)
 
 static int __devexit cyttsp_spi_remove(struct spi_device *spi)
 {
-	struct cyttsp *ts = dev_get_drvdata(&spi->dev);
+	struct cyttsp *ts = spi_get_drvdata(spi);
 
 	cyttsp_remove(ts);
 
@@ -217,9 +183,9 @@ static int __devexit cyttsp_spi_remove(struct spi_device *spi)
 
 static struct spi_driver cyttsp_spi_driver = {
 	.driver = {
-		.name   = CY_SPI_NAME,
-		.owner  = THIS_MODULE,
-		.pm     = &cyttsp_pm_ops,
+		.name	= CY_SPI_NAME,
+		.owner	= THIS_MODULE,
+		.pm	= &cyttsp_pm_ops,
 	},
 	.probe  = cyttsp_spi_probe,
 	.remove = __devexit_p(cyttsp_spi_remove),
@@ -242,4 +208,3 @@ MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard Product (TTSP) SPI driver");
 MODULE_AUTHOR("Cypress");
 MODULE_ALIAS("spi:cyttsp");
-
diff --git a/include/linux/input/cyttsp.h b/include/linux/input/cyttsp.h
index f792603..3cdd574 100644
--- a/include/linux/input/cyttsp.h
+++ b/include/linux/input/cyttsp.h
@@ -40,15 +40,6 @@
 /* Active distance in pixels for a gesture to be reported */
 #define CY_ACT_DIST_DFLT 0xF8 /* pixels */
 
-enum cyttsp_powerstate {
-	CY_IDLE_STATE,
-	CY_ACTIVE_STATE,
-	CY_LOW_PWR_STATE,
-	CY_SLEEP_STATE,
-	CY_BL_STATE,
-	CY_INVALID_STATE	/* always last in the list */
-};
-
 struct cyttsp_platform_data {
 	u32 maxx;
 	u32 maxy;
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH v10 1/3] Input: cyttsp - Cypress TTSP capacitive multi-touch screen support
  2012-01-27  8:18       ` Dmitry Torokhov
@ 2012-01-27 15:57         ` Javier Martinez Canillas
  2012-01-27 18:18           ` Dmitry Torokhov
  0 siblings, 1 reply; 14+ messages in thread
From: Javier Martinez Canillas @ 2012-01-27 15:57 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Henrik Rydberg, Mohan Pallaka, Kevin McNeely, Shubhrajyoti Datta,
	linux-input

On Fri, Jan 27, 2012 at 9:18 AM, Dmitry Torokhov
<dmitry.torokhov@gmail.com> wrote:
> On Thu, Jan 26, 2012 at 01:12:50AM +0100, Javier Martinez Canillas wrote:
>> On Tue, Jan 24, 2012 at 8:54 AM, Dmitry Torokhov
>> <dmitry.torokhov@gmail.com> wrote:
>> > On Tue, Jan 24, 2012 at 08:26:39AM +0100, Javier Martinez Canillas wrote:
>> >> On Fri, Jan 20, 2012 at 1:57 AM, Javier Martinez Canillas
>> >> <javier@dowhile0.org> wrote:
>> >> > Cypress TrueTouch(tm) Standard Product controllers are found in
>> >> > a wide range of embedded devices. This driver add support for a
>> >> > variety of TTSP controllers.
>> >> >
>> >> > Since the hardware is capable of tracking identifiable contacts, multi-touch
>> >> > protocol type B (stateful) is used to report contact information.
>> >> >
>> >> > The driver is composed of a core driver that process the data sent by
>> >> > the contacts and a set of bus specific interface modules. This patch
>> >> > adds the base core TTSP driver.
>> >> >
>> >> > Signed-off-by: Javier Martinez Canillas <javier@dowhile0.org>
>> >> > ---
>> >> >
>> >> > Changes for v10: Fix issues called out by Dmitry Torokhov
>> >> >        - Remove use_sleep and put device to sleep unconditionally on suspend
>> >> >        - Cleanup cyttsp_power_on() and remove cyttsp_bl_app_valid() function
>> >> >
>> >> >  drivers/input/touchscreen/Kconfig       |   31 ++
>> >> >  drivers/input/touchscreen/Makefile      |    3 +
>> >> >  drivers/input/touchscreen/cyttsp_core.c |  682 +++++++++++++++++++++++++++++++
>> >> >  drivers/input/touchscreen/cyttsp_core.h |  141 +++++++
>> >> >  include/linux/input/cyttsp.h            |   68 +++
>> >> >  5 files changed, 925 insertions(+), 0 deletions(-)
>> >>
>> >> Hello Dmitry,
>> >>
>> >> Any comments on this version?
>> >
>> > Looking at it... If you do not hear from me by Wednesday please ping
>> > me again.
>> >
>> > Thanks.
>> >
>> > --
>> > Dmitry
>>
>> ping :)
>
> Is it still Wednesday by any chance? ;)
>

Hi Dmitry,

Thanks for the review and the cleanup patch!

> Anyway, the driver looks pretty good, still below are some changes that
> I'd like to get in as well:
>
> - do not return EAGAIN when operation times out, EIO I believe suits
>  better.
> - introduce ttsp_send_command() to replace host of custom functions.
> - reduce numver of states to 3 - IDLE, ACTIVE and BL mode.
>  Suspended/full power is already covered by "suspended" attribute.
> - streamline some functions.
>

Seems that your patch handlers all these issues.

> Please see the FIXME comment in cyttsp_enable() - is there a generic way
> to wake up the device, similarly to the way we put it to sleep?
>

I guess that CY_OPERATE_MODE works but I have to try it since I don't
have the hw data-sheet.

> Please tell me if the device still works with this patch.
>
> Thanks!
>
> --
> Dmitry
>

Strange enough, it doesn't apply cleanly on my tree...

with patch -p1 < your_patch

It should since only the files for this driver are modified and I've
only applied the v10 patches I sent to you.
Anyway I will manually do the changes, try it and resend to you.

Thanks a lot for your help and best regards,
Javier
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v10 1/3] Input: cyttsp - Cypress TTSP capacitive multi-touch screen support
  2012-01-27 15:57         ` Javier Martinez Canillas
@ 2012-01-27 18:18           ` Dmitry Torokhov
  2012-01-27 21:01             ` Javier Martinez Canillas
  0 siblings, 1 reply; 14+ messages in thread
From: Dmitry Torokhov @ 2012-01-27 18:18 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: Henrik Rydberg, Mohan Pallaka, Kevin McNeely, Shubhrajyoti Datta,
	linux-input

[-- Attachment #1: Type: text/plain, Size: 3855 bytes --]

On Fri, Jan 27, 2012 at 04:57:12PM +0100, Javier Martinez Canillas wrote:
> On Fri, Jan 27, 2012 at 9:18 AM, Dmitry Torokhov
> <dmitry.torokhov@gmail.com> wrote:
> > On Thu, Jan 26, 2012 at 01:12:50AM +0100, Javier Martinez Canillas wrote:
> >> On Tue, Jan 24, 2012 at 8:54 AM, Dmitry Torokhov
> >> <dmitry.torokhov@gmail.com> wrote:
> >> > On Tue, Jan 24, 2012 at 08:26:39AM +0100, Javier Martinez Canillas wrote:
> >> >> On Fri, Jan 20, 2012 at 1:57 AM, Javier Martinez Canillas
> >> >> <javier@dowhile0.org> wrote:
> >> >> > Cypress TrueTouch(tm) Standard Product controllers are found in
> >> >> > a wide range of embedded devices. This driver add support for a
> >> >> > variety of TTSP controllers.
> >> >> >
> >> >> > Since the hardware is capable of tracking identifiable contacts, multi-touch
> >> >> > protocol type B (stateful) is used to report contact information.
> >> >> >
> >> >> > The driver is composed of a core driver that process the data sent by
> >> >> > the contacts and a set of bus specific interface modules. This patch
> >> >> > adds the base core TTSP driver.
> >> >> >
> >> >> > Signed-off-by: Javier Martinez Canillas <javier@dowhile0.org>
> >> >> > ---
> >> >> >
> >> >> > Changes for v10: Fix issues called out by Dmitry Torokhov
> >> >> >        - Remove use_sleep and put device to sleep unconditionally on suspend
> >> >> >        - Cleanup cyttsp_power_on() and remove cyttsp_bl_app_valid() function
> >> >> >
> >> >> >  drivers/input/touchscreen/Kconfig       |   31 ++
> >> >> >  drivers/input/touchscreen/Makefile      |    3 +
> >> >> >  drivers/input/touchscreen/cyttsp_core.c |  682 +++++++++++++++++++++++++++++++
> >> >> >  drivers/input/touchscreen/cyttsp_core.h |  141 +++++++
> >> >> >  include/linux/input/cyttsp.h            |   68 +++
> >> >> >  5 files changed, 925 insertions(+), 0 deletions(-)
> >> >>
> >> >> Hello Dmitry,
> >> >>
> >> >> Any comments on this version?
> >> >
> >> > Looking at it... If you do not hear from me by Wednesday please ping
> >> > me again.
> >> >
> >> > Thanks.
> >> >
> >> > --
> >> > Dmitry
> >>
> >> ping :)
> >
> > Is it still Wednesday by any chance? ;)
> >
> 
> Hi Dmitry,
> 
> Thanks for the review and the cleanup patch!
> 
> > Anyway, the driver looks pretty good, still below are some changes that
> > I'd like to get in as well:
> >
> > - do not return EAGAIN when operation times out, EIO I believe suits
> >  better.
> > - introduce ttsp_send_command() to replace host of custom functions.
> > - reduce numver of states to 3 - IDLE, ACTIVE and BL mode.
> >  Suspended/full power is already covered by "suspended" attribute.
> > - streamline some functions.
> >
> 
> Seems that your patch handlers all these issues.
> 
> > Please see the FIXME comment in cyttsp_enable() - is there a generic way
> > to wake up the device, similarly to the way we put it to sleep?
> >
> 
> I guess that CY_OPERATE_MODE works but I have to try it since I don't
> have the hw data-sheet.
> 
> > Please tell me if the device still works with this patch.
> >
> > Thanks!
> >
> > --
> > Dmitry
> >
> 
> Strange enough, it doesn't apply cleanly on my tree...
> 
> with patch -p1 < your_patch
> 
> It should since only the files for this driver are modified and I've
> only applied the v10 patches I sent to you.
> Anyway I will manually do the changes, try it and resend to you.

Hmm, not sure why it gives you trouble, I tried not to change anything
when applying your v10 patches except for folding them all together.

I am attaching the version of the driver I've used as a base - maybe it
will save you some time instead of applying the changes manually.

Also, could you please send changes needed to make my patch work as
incremental patch so that I can apply on top of mime locally and fold
all 3 together? It will be easier to see what exactly changed.

Thanks!

-- 
Dmitry

[-- Attachment #2: input-cyttsp-cypress-ttsp-capacitive-multi-touch-screen-support.patch --]
[-- Type: text/plain, Size: 37423 bytes --]

Input: cyttsp - Cypress TTSP capacitive multi-touch screen support

From: Javier Martinez Canillas <javier@dowhile0.org>

Cypress TrueTouch(tm) Standard Product controllers are found in
a wide range of embedded devices. This driver add support for a
variety of TTSP controllers.

Since the hardware is capable of tracking identifiable contacts, multi-touch
protocol type B (stateful) is used to report contact information.

The driver is composed of a core driver that process the data sent by
the contacts and a set of bus specific interface modules. This patch
adds the base core TTSP driver.

Signed-off-by: Javier Martinez Canillas <javier@dowhile0.org>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
---

 drivers/input/touchscreen/Kconfig       |   32 +
 drivers/input/touchscreen/Makefile      |    5 
 drivers/input/touchscreen/cyttsp_core.c |  682 +++++++++++++++++++++++++++++++
 drivers/input/touchscreen/cyttsp_core.h |  141 ++++++
 drivers/input/touchscreen/cyttsp_i2c.c  |  137 ++++++
 drivers/input/touchscreen/cyttsp_spi.c  |  245 +++++++++++
 include/linux/input/cyttsp.h            |   68 +++
 7 files changed, 1308 insertions(+), 2 deletions(-)
 create mode 100644 drivers/input/touchscreen/cyttsp_core.c
 create mode 100644 drivers/input/touchscreen/cyttsp_core.h
 create mode 100644 drivers/input/touchscreen/cyttsp_i2c.c
 create mode 100644 drivers/input/touchscreen/cyttsp_spi.c
 create mode 100644 include/linux/input/cyttsp.h


diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 6caae44..29e126f 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -139,7 +139,6 @@ config TOUCHSCREEN_CY8CTMG110
 	tristate "cy8ctmg110 touchscreen"
 	depends on I2C
 	depends on GPIOLIB
-
 	help
 	  Say Y here if you have a cy8ctmg110 capacitive touchscreen on
 	  an AAVA device.
@@ -149,6 +148,37 @@ config TOUCHSCREEN_CY8CTMG110
 	  To compile this driver as a module, choose M here: the
 	  module will be called cy8ctmg110_ts.
 
+config TOUCHSCREEN_CYTTSP_CORE
+	tristate "Cypress TTSP touchscreen"
+	help
+	  Say Y here if you have a touchscreen using controller from
+	  the Cypress TrueTouch(tm) Standard Product family connected
+	  to your system. You will also need to select appropriate
+	  bus connection below.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called cyttsp_core.
+
+config TOUCHSCREEN_CYTTSP_I2C
+	tristate "support I2C bus connection"
+	depends on TOUCHSCREEN_CYTTSP_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 cyttsp_i2c.
+
+config TOUCHSCREEN_CYTTSP_SPI
+	tristate "support SPI bus connection"
+	depends on TOUCHSCREEN_CYTTSP_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 cyttsp_spi.
+
 config TOUCHSCREEN_DA9034
 	tristate "Touchscreen support for Dialog Semiconductor DA9034"
 	depends on PMIC_DA903X
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 6246e52..bc2b513 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -16,8 +16,11 @@ obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT)	+= atmel_mxt_ts.o
 obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC)	+= atmel_tsadcc.o
 obj-$(CONFIG_TOUCHSCREEN_AUO_PIXCIR)	+= auo-pixcir-ts.o
 obj-$(CONFIG_TOUCHSCREEN_BITSY)		+= h3600_ts_input.o
-obj-$(CONFIG_TOUCHSCREEN_BU21013)       += bu21013_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_SPI)	+= cyttsp_spi.o
 obj-$(CONFIG_TOUCHSCREEN_DA9034)	+= da9034-ts.o
 obj-$(CONFIG_TOUCHSCREEN_DA9052)	+= da9052_tsi.o
 obj-$(CONFIG_TOUCHSCREEN_DYNAPRO)	+= dynapro.o
diff --git a/drivers/input/touchscreen/cyttsp_core.c b/drivers/input/touchscreen/cyttsp_core.c
new file mode 100644
index 0000000..28d5ef0
--- /dev/null
+++ b/drivers/input/touchscreen/cyttsp_core.c
@@ -0,0 +1,682 @@
+/*
+ * Core Source for:
+ * Cypress TrueTouch(TM) Standard Product (TTSP) touchscreen drivers.
+ * For use with Cypress Txx3xx parts.
+ * Supported parts include:
+ * CY8CTST341
+ * CY8CTMA340
+ *
+ * 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.
+ *
+ * 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>
+ *
+ */
+
+#include "cyttsp_core.h"
+
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/input/mt.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+
+/* Bootloader number of command keys */
+#define CY_NUM_BL_KEYS    8
+
+/* helpers */
+#define GET_NUM_TOUCHES(x)          ((x) & 0x0F)
+#define IS_LARGE_AREA(x)            (((x) & 0x10) >> 4)
+#define IS_BAD_PKT(x)               ((x) & 0x20)
+#define IS_VALID_APP(x)             ((x) & 0x01)
+#define IS_OPERATIONAL_ERR(x)       ((x) & 0x3F)
+#define GET_HSTMODE(reg)            ((reg & 0x70) >> 4)
+#define GET_BOOTLOADERMODE(reg)     ((reg & 0x10) >> 4)
+
+#define CY_REG_BASE                 0x00
+#define CY_REG_ACT_DIST             0x1E
+#define CY_REG_ACT_INTRVL           0x1D
+#define CY_REG_TCH_TMOUT            (CY_REG_ACT_INTRVL+1)
+#define CY_REG_LP_INTRVL            (CY_REG_TCH_TMOUT+1)
+#define CY_MAXZ                     255
+#define CY_DELAY_DFLT               20 /* ms */
+#define CY_DELAY_MAX                500
+#define CY_ACT_DIST_DFLT            0xF8
+#define CY_HNDSHK_BIT               0x80
+/* device mode bits */
+#define CY_OPERATE_MODE             0x00
+#define CY_SYSINFO_MODE             0x10
+/* power mode select bits */
+#define CY_SOFT_RESET_MODE          0x01 /* return to Bootloader mode */
+#define CY_DEEP_SLEEP_MODE          0x02
+#define CY_LOW_POWER_MODE           0x04
+
+/* Slots management */
+#define CY_MAX_FINGER               4
+#define CY_MAX_ID                   16
+
+static const u8 bl_command[] = {
+	0x00,			/* file offset */
+	0xFF,			/* command */
+	0xA5,			/* exit bootloader command */
+	0, 1, 2, 3, 4, 5, 6, 7	/* default keys */
+};
+
+static int ttsp_read_block_data(struct cyttsp *ts, u8 command,
+	u8 length, void *buf)
+{
+	int retval = -1;
+	int tries;
+
+	if (!buf || !length)
+		return -EINVAL;
+
+	for (tries = 0; tries < CY_NUM_RETRY && (retval < 0); tries++) {
+		retval = ts->bus_ops->read(ts->dev, command, length, buf);
+		if (retval)
+			msleep(CY_DELAY_DFLT);
+	}
+
+	if (tries >= CY_NUM_RETRY)
+		return -EAGAIN;
+
+	return retval;
+}
+
+static int ttsp_write_block_data(struct cyttsp *ts, u8 command,
+	u8 length, void *buf)
+{
+	int retval = -1;
+	int tries;
+
+	if (!buf || !length)
+		return -EINVAL;
+
+	for (tries = 0; tries < CY_NUM_RETRY && (retval < 0); tries++) {
+		retval = ts->bus_ops->write(ts->dev, command, length, buf);
+		if (retval)
+			msleep(CY_DELAY_DFLT);
+	}
+
+	if (tries >= CY_NUM_RETRY)
+		return -EAGAIN;
+
+	return retval;
+}
+
+static int cyttsp_load_bl_regs(struct cyttsp *ts)
+{
+	memset(&(ts->bl_data), 0, sizeof(struct cyttsp_bootloader_data));
+
+	ts->bl_data.bl_status = 0x10;
+
+	return  ttsp_read_block_data(ts, CY_REG_BASE, sizeof(ts->bl_data),
+				     &ts->bl_data);
+}
+
+static int cyttsp_exit_bl_mode(struct cyttsp *ts)
+{
+	int retval;
+	u8 bl_cmd[sizeof(bl_command)];
+
+	memcpy(bl_cmd, bl_command, sizeof(bl_command));
+	if (ts->pdata->bl_keys)
+		memcpy(&bl_cmd[sizeof(bl_command) - CY_NUM_BL_KEYS],
+			ts->pdata->bl_keys, sizeof(bl_command));
+
+	retval = ttsp_write_block_data(ts, CY_REG_BASE,
+		sizeof(bl_cmd), (void *)bl_cmd);
+
+	if (retval < 0)
+		return retval;
+
+	/* wait for TTSP Device to complete the operation */
+	msleep(CY_DELAY_DFLT);
+	retval = cyttsp_load_bl_regs(ts);
+
+	if (retval || GET_BOOTLOADERMODE(ts->bl_data.bl_status))
+		return -ENODEV;
+
+	return retval;
+}
+
+static int cyttsp_set_operational_mode(struct cyttsp *ts)
+{
+	struct cyttsp_xydata xy_data;
+	int retval;
+	u8 cmd = CY_OPERATE_MODE;
+
+	retval = ttsp_write_block_data(ts, CY_REG_BASE, sizeof(cmd), &cmd);
+
+	if (retval < 0)
+		return retval;
+
+	/* wait for TTSP Device to complete switch to Operational mode */
+	retval = ttsp_read_block_data(ts, CY_REG_BASE,
+				      sizeof(xy_data), &(xy_data));
+
+	if (retval || xy_data.act_dist == CY_ACT_DIST_DFLT)
+		return -EAGAIN;
+
+	return retval;
+}
+
+static int cyttsp_set_sysinfo_mode(struct cyttsp *ts)
+{
+	int retval;
+	u8 cmd = CY_SYSINFO_MODE;
+
+	memset(&(ts->sysinfo_data), 0, sizeof(struct cyttsp_sysinfo_data));
+
+	/* switch to sysinfo mode */
+	retval = ttsp_write_block_data(ts, CY_REG_BASE, sizeof(cmd), &cmd);
+	if (retval < 0)
+		return retval;
+
+	/* read sysinfo registers */
+	msleep(CY_DELAY_DFLT);
+	retval = ttsp_read_block_data(ts, CY_REG_BASE, sizeof(ts->sysinfo_data),
+				      &ts->sysinfo_data);
+
+	if (retval || (!ts->sysinfo_data.tts_verh &&
+		       !ts->sysinfo_data.tts_verl))
+		return -EAGAIN;
+
+	return retval;
+}
+
+static int cyttsp_set_sysinfo_regs(struct cyttsp *ts)
+{
+	int retval = 0;
+
+	if (ts->pdata->act_intrvl != CY_ACT_INTRVL_DFLT ||
+		ts->pdata->tch_tmout != CY_TCH_TMOUT_DFLT ||
+		ts->pdata->lp_intrvl != CY_LP_INTRVL_DFLT) {
+
+		u8 intrvl_ray[3];
+
+		intrvl_ray[0] = ts->pdata->act_intrvl;
+		intrvl_ray[1] = ts->pdata->tch_tmout;
+		intrvl_ray[2] = ts->pdata->lp_intrvl;
+
+		/* set intrvl registers */
+		retval = ttsp_write_block_data(ts,
+				CY_REG_ACT_INTRVL,
+				sizeof(intrvl_ray), intrvl_ray);
+
+		msleep(CY_DELAY_DFLT);
+	}
+
+	return retval;
+}
+
+static int cyttsp_soft_reset(struct cyttsp *ts)
+{
+	int retval;
+	u8 cmd = CY_SOFT_RESET_MODE;
+	long wait_jiffies = msecs_to_jiffies(CY_DELAY_DFLT * CY_DELAY_MAX);
+	/* wait for interrupt to set ready completion */
+	INIT_COMPLETION(ts->bl_ready);
+
+	retval = ttsp_write_block_data(ts, CY_REG_BASE, sizeof(cmd), &cmd);
+	if (retval < 0)
+		return retval;
+
+	return wait_for_completion_timeout(&ts->bl_ready, wait_jiffies);
+}
+
+static int cyttsp_act_dist_setup(struct cyttsp *ts)
+{
+	int retval;
+	u8 act_dist_setup;
+
+	/* Init gesture; active distance setup */
+	act_dist_setup = ts->pdata->act_dist;
+	retval = ttsp_write_block_data(ts, CY_REG_ACT_DIST,
+		sizeof(act_dist_setup), &act_dist_setup);
+
+	return retval;
+}
+
+static int cyttsp_hndshk(struct cyttsp *ts, u8 hst_mode)
+{
+	u8 cmd;
+
+	cmd = hst_mode ^ CY_HNDSHK_BIT;
+
+	return ttsp_write_block_data(ts, CY_REG_BASE, sizeof(cmd), (u8 *)&cmd);
+}
+
+static void cyttsp_report_slot(struct input_dev *dev, int slot,
+			       int x, int y, int z)
+{
+	input_mt_slot(dev, slot);
+	input_mt_report_slot_state(dev, MT_TOOL_FINGER, true);
+	input_report_abs(dev, ABS_MT_POSITION_X, x);
+	input_report_abs(dev, ABS_MT_POSITION_Y, y);
+	input_report_abs(dev, ABS_MT_TOUCH_MAJOR, z);
+}
+
+static void cyttsp_report_slot_empty(struct input_dev *dev, int slot)
+{
+	input_mt_slot(dev, slot);
+	input_mt_report_slot_state(dev, MT_TOOL_FINGER, false);
+}
+
+static void cyttsp_extract_track_ids(struct cyttsp_xydata *xy_data, int *ids)
+{
+	ids[0] = xy_data->touch12_id >> 4;
+	ids[1] = xy_data->touch12_id & 0xF;
+	ids[2] = xy_data->touch34_id >> 4;
+	ids[3] = xy_data->touch34_id & 0xF;
+}
+
+static const struct cyttsp_tch *cyttsp_get_tch(struct cyttsp_xydata *xy_data,
+					       int idx)
+{
+	switch (idx) {
+	case 0:
+		return &xy_data->tch1;
+	case 1:
+		return &xy_data->tch2;
+	case 2:
+		return &xy_data->tch3;
+	case 3:
+		return  &xy_data->tch4;
+	default:
+		return NULL;
+	}
+}
+
+static int cyttsp_handle_tchdata(struct cyttsp *ts)
+{
+	struct cyttsp_xydata xy_data;
+	u8 num_cur_tch;
+	int i;
+	int ids[4];
+	const struct cyttsp_tch *tch = NULL;
+	int x, y, z;
+	int used = 0;
+
+	/* Get touch data from CYTTSP device */
+	if (ttsp_read_block_data(ts,
+		CY_REG_BASE, sizeof(struct cyttsp_xydata), &xy_data))
+		return 0;
+
+	/* provide flow control handshake */
+	if (ts->pdata->use_hndshk)
+		if (cyttsp_hndshk(ts, xy_data.hst_mode))
+			return 0;
+
+	/* determine number of currently active touches */
+	num_cur_tch = GET_NUM_TOUCHES(xy_data.tt_stat);
+
+	/* check for any error conditions */
+	if (ts->power_state == CY_IDLE_STATE)
+		return 0;
+	else if (GET_BOOTLOADERMODE(xy_data.tt_mode)) {
+		return -1;
+	} else if (IS_LARGE_AREA(xy_data.tt_stat) == 1) {
+		/* terminate all active tracks */
+		num_cur_tch = 0;
+		dev_dbg(ts->dev, "%s: Large area detected\n", __func__);
+	} else if (num_cur_tch > CY_MAX_FINGER) {
+		/* terminate all active tracks */
+		num_cur_tch = 0;
+		dev_dbg(ts->dev, "%s: Num touch error detected\n", __func__);
+	} else if (IS_BAD_PKT(xy_data.tt_mode)) {
+		/* terminate all active tracks */
+		num_cur_tch = 0;
+		dev_dbg(ts->dev, "%s: Invalid buffer detected\n", __func__);
+	}
+
+	cyttsp_extract_track_ids(&xy_data, ids);
+
+	for (i = 0; i < num_cur_tch; i++) {
+		used |= (1 << ids[i]);
+
+		tch = cyttsp_get_tch(&xy_data, i);
+
+		x = be16_to_cpu(tch->x);
+		y = be16_to_cpu(tch->y);
+		z = tch->z;
+
+		cyttsp_report_slot(ts->input, ids[i], x, y, z);
+	}
+
+	for (i = 0; i < CY_MAX_ID; i++)
+		if (!(used & (1 << i)))
+			cyttsp_report_slot_empty(ts->input, i);
+
+	input_sync(ts->input);
+
+	return 0;
+}
+
+static void cyttsp_pr_state(struct cyttsp *ts)
+{
+	static char *cyttsp_powerstate_string[] = {
+		"IDLE",
+		"ACTIVE",
+		"LOW_PWR",
+		"SLEEP",
+		"BOOTLOADER",
+		"INVALID"
+	};
+
+	dev_info(ts->dev, "%s: %s\n", __func__,
+		ts->power_state < CY_INVALID_STATE ?
+		cyttsp_powerstate_string[ts->power_state] :
+		"INVALID");
+}
+
+static irqreturn_t cyttsp_irq(int irq, void *handle)
+{
+	struct cyttsp *ts = handle;
+	int retval;
+
+	if (ts->power_state == CY_BL_STATE)
+		complete(&ts->bl_ready);
+	else {
+		/* process the touches */
+		retval = cyttsp_handle_tchdata(ts);
+
+		if (retval < 0) {
+			/*
+			 * TTSP device has reset back to bootloader mode.
+			 * Restore to operational mode.
+			 */
+			retval = cyttsp_exit_bl_mode(ts);
+			if (retval)
+				ts->power_state = CY_IDLE_STATE;
+			else
+				ts->power_state = CY_ACTIVE_STATE;
+			cyttsp_pr_state(ts);
+		}
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int cyttsp_power_on(struct cyttsp *ts)
+{
+	int retval = 0;
+
+	ts->power_state = CY_BL_STATE;
+	enable_irq(ts->irq);
+
+	retval = cyttsp_soft_reset(ts);
+	if (retval < 0)
+		return retval;
+
+	retval = cyttsp_load_bl_regs(ts);
+	if (retval < 0)
+		return retval;
+
+	if (GET_BOOTLOADERMODE(ts->bl_data.bl_status) &&
+	    IS_VALID_APP(ts->bl_data.bl_status))
+		retval = cyttsp_exit_bl_mode(ts);
+
+	if (retval < 0)
+		return retval;
+	else
+		ts->power_state = CY_IDLE_STATE;
+
+	if (GET_HSTMODE(ts->bl_data.bl_file) == CY_OPERATE_MODE &&
+	    !IS_OPERATIONAL_ERR(ts->bl_data.bl_status)) {
+		retval = cyttsp_set_sysinfo_mode(ts);
+		if (retval < 0)
+			return retval;
+
+		retval = cyttsp_set_sysinfo_regs(ts);
+		if (retval < 0)
+			return retval;
+
+		retval = cyttsp_set_operational_mode(ts);
+		if (retval < 0)
+			return retval;
+
+		/* init active distance */
+		retval = cyttsp_act_dist_setup(ts);
+		if (retval < 0)
+			return retval;
+
+		ts->power_state = CY_ACTIVE_STATE;
+
+		return 0;
+	}
+
+	return -ENODEV;
+}
+
+static int __cyttsp_enable(struct cyttsp *ts)
+{
+	struct cyttsp_xydata xydata;
+	int retval = 0;
+
+	if (ts->power_state != CY_ACTIVE_STATE) {
+
+		if (ts->pdata->wakeup)
+			retval = ts->pdata->wakeup();
+
+		if (retval == 0) {
+			retval = ttsp_read_block_data(ts, CY_REG_BASE,
+						      sizeof(xydata),
+						      &xydata);
+			if (retval == 0 &&
+			    !GET_HSTMODE(xydata.hst_mode)) {
+				ts->power_state = CY_ACTIVE_STATE;
+				enable_irq(ts->irq);
+			}
+		}
+	}
+
+	return retval;
+}
+
+static int __cyttsp_disable(struct cyttsp *ts)
+{
+	u8 cmd = CY_LOW_POWER_MODE;
+	int retval = 0;
+
+	if (ts->power_state == CY_ACTIVE_STATE) {
+		retval = ttsp_write_block_data(ts, CY_REG_BASE,
+					       sizeof(cmd), &cmd);
+		if (retval == 0) {
+			ts->power_state = CY_SLEEP_STATE;
+			disable_irq(ts->irq);
+		}
+	}
+
+	return retval;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int cyttsp_resume(struct device *dev)
+{
+	struct cyttsp *ts = dev_get_drvdata(dev);
+	int retval = 0;
+
+	mutex_lock(&ts->input->mutex);
+
+	if (ts->suspended)
+		retval = __cyttsp_enable(ts);
+
+	ts->suspended = false;
+
+	mutex_unlock(&ts->input->mutex);
+
+	return retval;
+}
+
+static int cyttsp_suspend(struct device *dev)
+{
+	struct cyttsp *ts = dev_get_drvdata(dev);
+	int retval = 0;
+
+	mutex_lock(&ts->input->mutex);
+
+	if (!ts->suspended)
+		retval = __cyttsp_disable(ts);
+
+	ts->suspended = true;
+
+	mutex_unlock(&ts->input->mutex);
+
+	return retval;
+}
+#endif
+
+SIMPLE_DEV_PM_OPS(cyttsp_pm_ops, cyttsp_suspend, cyttsp_resume);
+EXPORT_SYMBOL_GPL(cyttsp_pm_ops);
+
+static int cyttsp_open(struct input_dev *dev)
+{
+	struct cyttsp *ts = input_get_drvdata(dev);
+	int retval = 0;
+
+	if (!ts->on) {
+		retval = cyttsp_power_on(ts);
+
+		if (retval) {
+			cyttsp_pr_state(ts);
+			return retval;
+		} else
+			ts->on = true;
+	}
+
+	if (!ts->suspended)
+		retval = __cyttsp_enable(ts);
+
+	return retval;
+}
+
+static void cyttsp_close(struct input_dev *dev)
+{
+	struct cyttsp *ts = input_get_drvdata(dev);
+
+	if (!ts->suspended)
+		__cyttsp_disable(ts);
+}
+
+struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops,
+			    struct device *dev, int irq, size_t xfer_buf_size)
+{
+	const struct cyttsp_platform_data *pdata = dev->platform_data;
+	struct cyttsp *ts;
+	struct input_dev *input_dev;
+	int error;
+
+	if (!dev || !bus_ops || !pdata || !pdata->name || irq <= 0) {
+		error = -EINVAL;
+		goto err_out;
+	}
+
+	ts = kzalloc(sizeof(*ts) + xfer_buf_size, GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!ts || !input_dev) {
+		error = -ENOMEM;
+		goto err_free_mem;
+	}
+
+	ts->dev = dev;
+	ts->input = input_dev;
+	ts->pdata = dev->platform_data;
+	ts->bus_ops = bus_ops;
+	ts->irq = irq;
+	ts->suspended = false;
+	ts->on = false;
+
+	init_completion(&ts->bl_ready);
+	snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(dev));
+
+	if (pdata->init) {
+		error = pdata->init();
+		if (error) {
+			dev_err(ts->dev, "platform init failed, err: %d\n",
+				error);
+			goto err_free_mem;
+		}
+	}
+
+	input_dev->name = pdata->name;
+	input_dev->phys = ts->phys;
+	input_dev->id.bustype = bus_ops->bustype;
+	input_dev->dev.parent = ts->dev;
+
+	input_dev->open = cyttsp_open;
+	input_dev->close = cyttsp_close;
+
+	input_set_drvdata(input_dev, ts);
+
+	__set_bit(EV_ABS, input_dev->evbit);
+	input_set_abs_params(input_dev, ABS_MT_POSITION_X,
+			     0, pdata->maxx, 0, 0);
+	input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
+			     0, pdata->maxy, 0, 0);
+	input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
+			     0, CY_MAXZ, 0, 0);
+
+	input_mt_init_slots(input_dev, CY_MAX_ID);
+
+	error = request_threaded_irq(ts->irq, NULL, cyttsp_irq,
+				     IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+				     pdata->name, ts);
+	if (error) {
+		dev_err(ts->dev, "failed to request IRQ %d, err: %d\n",
+			ts->irq, error);
+		goto err_platform_exit;
+	}
+	disable_irq(ts->irq);
+
+	error = input_register_device(input_dev);
+	if (error) {
+		dev_err(ts->dev, "failed to register input device: %d\n",
+			error);
+		goto err_free_irq;
+	}
+
+	return ts;
+
+err_free_irq:
+	free_irq(ts->irq, ts);
+err_platform_exit:
+	if (pdata->exit)
+		pdata->exit();
+err_free_mem:
+	input_free_device(input_dev);
+	kfree(ts);
+err_out:
+	return ERR_PTR(error);
+}
+EXPORT_SYMBOL_GPL(cyttsp_probe);
+
+void cyttsp_remove(struct cyttsp *ts)
+{
+	free_irq(ts->irq, ts);
+	input_unregister_device(ts->input);
+	if (ts->pdata->exit)
+		ts->pdata->exit();
+	kfree(ts);
+}
+EXPORT_SYMBOL_GPL(cyttsp_remove);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard touchscreen driver core");
+MODULE_AUTHOR("Cypress");
+
diff --git a/drivers/input/touchscreen/cyttsp_core.h b/drivers/input/touchscreen/cyttsp_core.h
new file mode 100644
index 0000000..866f5e2
--- /dev/null
+++ b/drivers/input/touchscreen/cyttsp_core.h
@@ -0,0 +1,141 @@
+/*
+ * Header file for:
+ * Cypress TrueTouch(TM) Standard Product (TTSP) touchscreen drivers.
+ * For use with Cypress Txx3xx parts.
+ * Supported parts include:
+ * CY8CTST341
+ * CY8CTMA340
+ *
+ * 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.
+ *
+ * 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>
+ *
+ */
+
+
+#ifndef __CYTTSP_CORE_H__
+#define __CYTTSP_CORE_H__
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/input/cyttsp.h>
+
+#define CY_NUM_RETRY		16 /* max number of retries for read ops */
+
+struct cyttsp_tch {
+	__be16 x, y;
+	u8 z;
+} __packed;
+
+/* TrueTouch Standard Product Gen3 interface definition */
+struct cyttsp_xydata {
+	u8 hst_mode;
+	u8 tt_mode;
+	u8 tt_stat;
+	struct cyttsp_tch tch1;
+	u8 touch12_id;
+	struct cyttsp_tch tch2;
+	u8 gest_cnt;
+	u8 gest_id;
+	struct cyttsp_tch tch3;
+	u8 touch34_id;
+	struct cyttsp_tch tch4;
+	u8 tt_undef[3];
+	u8 act_dist;
+	u8 tt_reserved;
+} __packed;
+
+
+/* TTSP System Information interface definition */
+struct cyttsp_sysinfo_data {
+	u8 hst_mode;
+	u8 mfg_cmd;
+	u8 mfg_stat;
+	u8 cid[3];
+	u8 tt_undef1;
+	u8 uid[8];
+	u8 bl_verh;
+	u8 bl_verl;
+	u8 tts_verh;
+	u8 tts_verl;
+	u8 app_idh;
+	u8 app_idl;
+	u8 app_verh;
+	u8 app_verl;
+	u8 tt_undef[5];
+	u8 scn_typ;
+	u8 act_intrvl;
+	u8 tch_tmout;
+	u8 lp_intrvl;
+};
+
+/* TTSP Bootloader Register Map interface definition */
+#define CY_BL_CHKSUM_OK 0x01
+struct cyttsp_bootloader_data {
+	u8 bl_file;
+	u8 bl_status;
+	u8 bl_error;
+	u8 blver_hi;
+	u8 blver_lo;
+	u8 bld_blver_hi;
+	u8 bld_blver_lo;
+	u8 ttspver_hi;
+	u8 ttspver_lo;
+	u8 appid_hi;
+	u8 appid_lo;
+	u8 appver_hi;
+	u8 appver_lo;
+	u8 cid_0;
+	u8 cid_1;
+	u8 cid_2;
+};
+
+struct cyttsp_bus_ops {
+	u16 bustype;
+	int (*write)(struct device *dev,
+		     u8 addr, u8 length, const void *values);
+	int (*read)(struct device *dev, u8 addr, u8 length, void *values);
+};
+
+struct cyttsp {
+	struct device *dev;
+	int irq;
+	struct input_dev *input;
+	char phys[32];
+	const struct cyttsp_platform_data *pdata;
+	const struct cyttsp_bus_ops *bus_ops;
+	struct cyttsp_bootloader_data bl_data;
+	struct cyttsp_sysinfo_data sysinfo_data;
+	struct completion bl_ready;
+	enum cyttsp_powerstate power_state;
+	bool suspended;
+	bool on;
+
+	u8 xfer_buf[] ____cacheline_aligned;
+};
+
+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);
+
+extern const struct dev_pm_ops cyttsp_pm_ops;
+
+#endif /* __CYTTSP_CORE_H__ */
diff --git a/drivers/input/touchscreen/cyttsp_i2c.c b/drivers/input/touchscreen/cyttsp_i2c.c
new file mode 100644
index 0000000..cdbf61d
--- /dev/null
+++ b/drivers/input/touchscreen/cyttsp_i2c.c
@@ -0,0 +1,137 @@
+/*
+ * Source for:
+ * Cypress TrueTouch(TM) Standard Product (TTSP) I2C touchscreen driver.
+ * For use with Cypress Txx3xx parts.
+ * Supported parts include:
+ * CY8CTST341
+ * CY8CTMA340
+ *
+ * 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.
+ *
+ * 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>
+ *
+ */
+
+#include "cyttsp_core.h"
+
+#include <linux/i2c.h>
+#include <linux/input.h>
+
+#define CY_I2C_DATA_SIZE  128
+
+static int cyttsp_i2c_read_block_data(struct device *dev,
+				      u8 addr, u8 length, void *values)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	int retval;
+
+	retval = i2c_master_send(client, &addr, 1);
+	if (retval < 0)
+		return retval;
+
+	retval = i2c_master_recv(client, values, length);
+
+	if (retval < 0)
+		return retval;
+
+	return (retval != length) ? -EIO : 0;
+}
+
+static int cyttsp_i2c_write_block_data(struct device *dev,
+				       u8 addr, u8 length, const void *values)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct cyttsp *ts = i2c_get_clientdata(client);
+	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,
+	.read           = cyttsp_i2c_read_block_data,
+};
+
+static int __devinit cyttsp_i2c_probe(struct i2c_client *client,
+				      const struct i2c_device_id *id)
+{
+	struct cyttsp *ts;
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		dev_err(&client->dev, "I2C functionality not Supported\n");
+		return -EIO;
+	}
+
+	ts = cyttsp_probe(&cyttsp_i2c_bus_ops, &client->dev, client->irq,
+			  CY_I2C_DATA_SIZE);
+
+	if (IS_ERR(ts))
+		return PTR_ERR(ts);
+
+	i2c_set_clientdata(client, ts);
+
+	return 0;
+}
+
+static int __devexit cyttsp_i2c_remove(struct i2c_client *client)
+{
+	struct cyttsp *ts = i2c_get_clientdata(client);
+
+	cyttsp_remove(ts);
+
+	return 0;
+}
+
+static const struct i2c_device_id cyttsp_i2c_id[] = {
+	{ CY_I2C_NAME, 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, cyttsp_i2c_id);
+
+static struct i2c_driver cyttsp_i2c_driver = {
+	.driver = {
+		.name   = CY_I2C_NAME,
+		.owner  = THIS_MODULE,
+		.pm     = &cyttsp_pm_ops,
+	},
+	.probe          = cyttsp_i2c_probe,
+	.remove         = __devexit_p(cyttsp_i2c_remove),
+	.id_table       = cyttsp_i2c_id,
+};
+
+static int __init cyttsp_i2c_init(void)
+{
+	return i2c_add_driver(&cyttsp_i2c_driver);
+}
+module_init(cyttsp_i2c_init);
+
+static void __exit cyttsp_i2c_exit(void)
+{
+	return i2c_del_driver(&cyttsp_i2c_driver);
+}
+module_exit(cyttsp_i2c_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard Product (TTSP) I2C driver");
+MODULE_AUTHOR("Cypress");
+MODULE_ALIAS("i2c:cyttsp");
diff --git a/drivers/input/touchscreen/cyttsp_spi.c b/drivers/input/touchscreen/cyttsp_spi.c
new file mode 100644
index 0000000..3238c7d
--- /dev/null
+++ b/drivers/input/touchscreen/cyttsp_spi.c
@@ -0,0 +1,245 @@
+/*
+ * Source for:
+ * Cypress TrueTouch(TM) Standard Product (TTSP) SPI touchscreen driver.
+ * For use with Cypress Txx3xx parts.
+ * Supported parts include:
+ * CY8CTST341
+ * CY8CTMA340
+ *
+ * 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.
+ *
+ * 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>
+ *
+ */
+
+#include "cyttsp_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_CMD_BYTES  4
+#define CY_SPI_SYNC_BYTE  2
+#define CY_SPI_SYNC_ACK1  0x62 /* from protocol v.2 */
+#define CY_SPI_SYNC_ACK2  0x9D /* from protocol v.2 */
+#define CY_SPI_DATA_SIZE  128
+#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(u8 op, struct spi_device *spi,
+			   u8 reg, u8 *buf, int length)
+{
+	struct cyttsp *ts = spi_get_drvdata(spi);
+	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];
+	int retval;
+
+	if (length > CY_SPI_DATA_SIZE) {
+		dev_dbg(&spi->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_DATA_BUF_SIZE);
+
+	wr_buf[0] = 0x00; /* header byte 0 */
+	wr_buf[1] = 0xFF; /* header byte 1 */
+	wr_buf[2] = reg;  /* reg index */
+	wr_buf[3] = op;   /* r/~w */
+	if (op == CY_SPI_WR_OP)
+		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_CMD_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_dbg(&spi->dev,
+			"%s: bad operation code=%d\n", __func__, op);
+		return -EINVAL;
+	}
+
+	retval = spi_sync(spi, &msg);
+	if (retval < 0) {
+		dev_dbg(&spi->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_ACK1 ||
+	    rd_buf[CY_SPI_SYNC_BYTE + 1] != CY_SPI_SYNC_ACK2) {
+		int i;
+		for (i = 0; i < CY_SPI_CMD_BYTES; i++)
+			dev_dbg(&spi->dev,
+				"%s: test rd_buf[%d]:0x%02x\n",
+				__func__, i, rd_buf[i]);
+		for (i = 0; i < length; i++)
+			dev_dbg(&spi->dev,
+				"%s: test buf[%d]:0x%02x\n",
+				__func__, i, buf[i]);
+
+		/* signal ACK error so silent retry */
+		return 1;
+	}
+
+	return 0;
+}
+
+static int cyttsp_spi_read_block_data(struct device *dev,
+				      u8 addr, u8 length, void *data)
+{
+	struct spi_device *spi = to_spi_device(dev);
+	int retval;
+
+	retval = cyttsp_spi_xfer(CY_SPI_RD_OP, spi, addr, data, length);
+	if (retval < 0)
+		dev_err(dev, "cyttsp_spi_read_block_data failed, err: %d\n",
+			retval);
+
+	/*
+	 * Do not print the above error if the data sync bytes were not found.
+	 * This is a normal condition for the bootloader loader startup and need
+	 * to retry until data sync bytes are found.
+	 */
+	if (retval > 0)
+		retval = -EIO;  /* now signal fail; so retry can be done */
+
+	return retval;
+}
+
+static int cyttsp_spi_write_block_data(struct device *dev,
+				       u8 addr, u8 length, const void *data)
+{
+	struct spi_device *spi = to_spi_device(dev);
+	int retval;
+
+	retval = cyttsp_spi_xfer(CY_SPI_WR_OP, spi, addr, (void *)data, length);
+	if (retval < 0)
+		dev_err(dev, "cyttsp_spi_write_block_data failed, err: %d\n",
+			retval);
+
+	/*
+	 * Do not print the above error if the data sync bytes were not found.
+	 * This is a normal condition for the bootloader loader startup and need
+	 * to retry until data sync bytes are found.
+	 */
+	if (retval > 0)
+		retval = -EIO;  /* now signal fail; so retry can be done */
+
+	return retval;
+}
+
+static const struct cyttsp_bus_ops cyttsp_spi_bus_ops = {
+	.bustype        = BUS_SPI,
+	.write          = cyttsp_spi_write_block_data,
+	.read           = cyttsp_spi_read_block_data,
+};
+
+static int __devinit cyttsp_spi_probe(struct spi_device *spi)
+{
+	struct cyttsp *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 = cyttsp_probe(&cyttsp_spi_bus_ops, &spi->dev, spi->irq,
+			  CY_SPI_DATA_BUF_SIZE * 2);
+	if (IS_ERR(ts))
+		return PTR_ERR(ts);
+
+	spi_set_drvdata(spi, ts);
+
+	return 0;
+}
+
+static int __devexit cyttsp_spi_remove(struct spi_device *spi)
+{
+	struct cyttsp *ts = dev_get_drvdata(&spi->dev);
+
+	cyttsp_remove(ts);
+
+	return 0;
+}
+
+static struct spi_driver cyttsp_spi_driver = {
+	.driver = {
+		.name   = CY_SPI_NAME,
+		.owner  = THIS_MODULE,
+		.pm     = &cyttsp_pm_ops,
+	},
+	.probe  = cyttsp_spi_probe,
+	.remove = __devexit_p(cyttsp_spi_remove),
+};
+
+static int __init cyttsp_spi_init(void)
+{
+	return spi_register_driver(&cyttsp_spi_driver);
+}
+module_init(cyttsp_spi_init);
+
+static void __exit cyttsp_spi_exit(void)
+{
+	spi_unregister_driver(&cyttsp_spi_driver);
+}
+module_exit(cyttsp_spi_exit);
+
+MODULE_ALIAS("spi:cyttsp");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard Product (TTSP) SPI driver");
+MODULE_AUTHOR("Cypress");
+MODULE_ALIAS("spi:cyttsp");
+
diff --git a/include/linux/input/cyttsp.h b/include/linux/input/cyttsp.h
new file mode 100644
index 0000000..f792603
--- /dev/null
+++ b/include/linux/input/cyttsp.h
@@ -0,0 +1,68 @@
+/*
+ * Header file for:
+ * Cypress TrueTouch(TM) Standard Product (TTSP) touchscreen drivers.
+ * For use with Cypress Txx3xx parts.
+ * Supported parts include:
+ * CY8CTST341
+ * CY8CTMA340
+ *
+ * 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.
+ *
+ * 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)
+ *
+ */
+#ifndef _CYTTSP_H_
+#define _CYTTSP_H_
+
+#define CY_SPI_NAME "cyttsp-spi"
+#define CY_I2C_NAME "cyttsp-i2c"
+/* Active Power state scanning/processing refresh interval */
+#define CY_ACT_INTRVL_DFLT 0x00 /* ms */
+/* touch timeout for the Active power */
+#define CY_TCH_TMOUT_DFLT 0xFF /* ms */
+/* Low Power state scanning/processing refresh interval */
+#define CY_LP_INTRVL_DFLT 0x0A /* ms */
+/* Active distance in pixels for a gesture to be reported */
+#define CY_ACT_DIST_DFLT 0xF8 /* pixels */
+
+enum cyttsp_powerstate {
+	CY_IDLE_STATE,
+	CY_ACTIVE_STATE,
+	CY_LOW_PWR_STATE,
+	CY_SLEEP_STATE,
+	CY_BL_STATE,
+	CY_INVALID_STATE	/* always last in the list */
+};
+
+struct cyttsp_platform_data {
+	u32 maxx;
+	u32 maxy;
+	bool use_hndshk;
+	u8 act_dist;	/* Active distance */
+	u8 act_intrvl;  /* Active refresh interval; ms */
+	u8 tch_tmout;   /* Active touch timeout; ms */
+	u8 lp_intrvl;   /* Low power refresh interval; ms */
+	int (*wakeup)(void);
+	int (*init)(void);
+	void (*exit)(void);
+	char *name;
+	s16 irq_gpio;
+	u8 *bl_keys;
+};
+
+#endif /* _CYTTSP_H_ */

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH v10 1/3] Input: cyttsp - Cypress TTSP capacitive multi-touch screen support
  2012-01-27 18:18           ` Dmitry Torokhov
@ 2012-01-27 21:01             ` Javier Martinez Canillas
  2012-01-27 21:26               ` Dmitry Torokhov
  0 siblings, 1 reply; 14+ messages in thread
From: Javier Martinez Canillas @ 2012-01-27 21:01 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Henrik Rydberg, Mohan Pallaka, Kevin McNeely, Shubhrajyoti Datta,
	linux-input

On Fri, Jan 27, 2012 at 7:18 PM, Dmitry Torokhov
<dmitry.torokhov@gmail.com> wrote:
> On Fri, Jan 27, 2012 at 04:57:12PM +0100, Javier Martinez Canillas wrote:
>> On Fri, Jan 27, 2012 at 9:18 AM, Dmitry Torokhov
>> <dmitry.torokhov@gmail.com> wrote:
>> > On Thu, Jan 26, 2012 at 01:12:50AM +0100, Javier Martinez Canillas wrote:
>> >> On Tue, Jan 24, 2012 at 8:54 AM, Dmitry Torokhov
>> >> <dmitry.torokhov@gmail.com> wrote:
>> >> > On Tue, Jan 24, 2012 at 08:26:39AM +0100, Javier Martinez Canillas wrote:
>> >> >> On Fri, Jan 20, 2012 at 1:57 AM, Javier Martinez Canillas
>> >> >> <javier@dowhile0.org> wrote:
>> >> >> > Cypress TrueTouch(tm) Standard Product controllers are found in
>> >> >> > a wide range of embedded devices. This driver add support for a
>> >> >> > variety of TTSP controllers.
>> >> >> >
>> >> >> > Since the hardware is capable of tracking identifiable contacts, multi-touch
>> >> >> > protocol type B (stateful) is used to report contact information.
>> >> >> >
>> >> >> > The driver is composed of a core driver that process the data sent by
>> >> >> > the contacts and a set of bus specific interface modules. This patch
>> >> >> > adds the base core TTSP driver.
>> >> >> >
>> >> >> > Signed-off-by: Javier Martinez Canillas <javier@dowhile0.org>
>> >> >> > ---
>> >> >> >
>> >> >> > Changes for v10: Fix issues called out by Dmitry Torokhov
>> >> >> >        - Remove use_sleep and put device to sleep unconditionally on suspend
>> >> >> >        - Cleanup cyttsp_power_on() and remove cyttsp_bl_app_valid() function
>> >> >> >
>> >> >> >  drivers/input/touchscreen/Kconfig       |   31 ++
>> >> >> >  drivers/input/touchscreen/Makefile      |    3 +
>> >> >> >  drivers/input/touchscreen/cyttsp_core.c |  682 +++++++++++++++++++++++++++++++
>> >> >> >  drivers/input/touchscreen/cyttsp_core.h |  141 +++++++
>> >> >> >  include/linux/input/cyttsp.h            |   68 +++
>> >> >> >  5 files changed, 925 insertions(+), 0 deletions(-)
>> >> >>
>> >> >> Hello Dmitry,
>> >> >>
>> >> >> Any comments on this version?
>> >> >
>> >> > Looking at it... If you do not hear from me by Wednesday please ping
>> >> > me again.
>> >> >
>> >> > Thanks.
>> >> >
>> >> > --
>> >> > Dmitry
>> >>
>> >> ping :)
>> >
>> > Is it still Wednesday by any chance? ;)
>> >
>>
>> Hi Dmitry,
>>
>> Thanks for the review and the cleanup patch!
>>
>> > Anyway, the driver looks pretty good, still below are some changes that
>> > I'd like to get in as well:
>> >
>> > - do not return EAGAIN when operation times out, EIO I believe suits
>> >  better.
>> > - introduce ttsp_send_command() to replace host of custom functions.
>> > - reduce numver of states to 3 - IDLE, ACTIVE and BL mode.
>> >  Suspended/full power is already covered by "suspended" attribute.
>> > - streamline some functions.
>> >
>>
>> Seems that your patch handlers all these issues.
>>
>> > Please see the FIXME comment in cyttsp_enable() - is there a generic way
>> > to wake up the device, similarly to the way we put it to sleep?
>> >
>>
>> I guess that CY_OPERATE_MODE works but I have to try it since I don't
>> have the hw data-sheet.
>>
>> > Please tell me if the device still works with this patch.
>> >
>> > Thanks!
>> >
>> > --
>> > Dmitry
>> >
>>
>> Strange enough, it doesn't apply cleanly on my tree...
>>
>> with patch -p1 < your_patch
>>
>> It should since only the files for this driver are modified and I've
>> only applied the v10 patches I sent to you.
>> Anyway I will manually do the changes, try it and resend to you.
>
> Hmm, not sure why it gives you trouble, I tried not to change anything
> when applying your v10 patches except for folding them all together.
>
> I am attaching the version of the driver I've used as a base - maybe it
> will save you some time instead of applying the changes manually.
>
> Also, could you please send changes needed to make my patch work as
> incremental patch so that I can apply on top of mime locally and fold
> all 3 together? It will be easier to see what exactly changed.
>
> Thanks!
>
> --
> Dmitry

Hi Dmitry,

Using that merged patch as a base your patch applies cleanly (not sure
what happened with my branch)

Sadly the driver is not working with your modifications. I'll make it
work changing as less as possible what was in your patch. Only to make
the device work again and will send you as an incremental patch as you
suggested.

Just to be clear, do you want me to send as an incremental patch of my
series (v10) or as an incremental patch of your last patch?

Thanks a lot and best regards,
Javier
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v10 1/3] Input: cyttsp - Cypress TTSP capacitive multi-touch screen support
  2012-01-27 21:01             ` Javier Martinez Canillas
@ 2012-01-27 21:26               ` Dmitry Torokhov
  2012-01-29  6:08                 ` Javier Martinez Canillas
  0 siblings, 1 reply; 14+ messages in thread
From: Dmitry Torokhov @ 2012-01-27 21:26 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: Henrik Rydberg, Mohan Pallaka, Kevin McNeely, Shubhrajyoti Datta,
	linux-input

On Friday, January 27, 2012 10:01:22 PM Javier Martinez Canillas wrote:
> On Fri, Jan 27, 2012 at 7:18 PM, Dmitry Torokhov
> 
> <dmitry.torokhov@gmail.com> wrote:
> > On Fri, Jan 27, 2012 at 04:57:12PM +0100, Javier Martinez Canillas wrote:
> >> On Fri, Jan 27, 2012 at 9:18 AM, Dmitry Torokhov
> >> 
> >> <dmitry.torokhov@gmail.com> wrote:
> >> > On Thu, Jan 26, 2012 at 01:12:50AM +0100, Javier Martinez Canillas 
wrote:
> >> >> On Tue, Jan 24, 2012 at 8:54 AM, Dmitry Torokhov
> >> >> 
> >> >> <dmitry.torokhov@gmail.com> wrote:
> >> >> > On Tue, Jan 24, 2012 at 08:26:39AM +0100, Javier Martinez Canillas 
wrote:
> >> >> >> On Fri, Jan 20, 2012 at 1:57 AM, Javier Martinez Canillas
> >> >> >> 
> >> >> >> <javier@dowhile0.org> wrote:
> >> >> >> > Cypress TrueTouch(tm) Standard Product controllers are
> >> >> >> > found in
> >> >> >> > a wide range of embedded devices. This driver add
> >> >> >> > support for a
> >> >> >> > variety of TTSP controllers.
> >> >> >> > 
> >> >> >> > Since the hardware is capable of tracking identifiable
> >> >> >> > contacts, multi-touch protocol type B (stateful) is
> >> >> >> > used to report contact information.
> >> >> >> > 
> >> >> >> > The driver is composed of a core driver that process
> >> >> >> > the data sent by the contacts and a set of bus
> >> >> >> > specific interface modules. This patch adds the base
> >> >> >> > core TTSP driver.
> >> >> >> > 
> >> >> >> > Signed-off-by: Javier Martinez Canillas
> >> >> >> > <javier@dowhile0.org>
> >> >> >> > ---
> >> >> >> > 
> >> >> >> > Changes for v10: Fix issues called out by Dmitry
> >> >> >> > Torokhov
> >> >> >> >        - Remove use_sleep and put device to sleep
> >> >> >> > unconditionally on suspend - Cleanup
> >> >> >> > cyttsp_power_on() and remove cyttsp_bl_app_valid()
> >> >> >> > function
> >> >> >> > 
> >> >> >> >  drivers/input/touchscreen/Kconfig       |   31 ++
> >> >> >> >  drivers/input/touchscreen/Makefile      |    3 +
> >> >> >> >  drivers/input/touchscreen/cyttsp_core.c |  682
> >> >> >> > +++++++++++++++++++++++++++++++
> >> >> >> > drivers/input/touchscreen/cyttsp_core.h |  141
> >> >> >> > +++++++ include/linux/input/cyttsp.h            |  
> >> >> >> > 68 +++
> >> >> >> >  5 files changed, 925 insertions(+), 0 deletions(-)
> >> >> >> 
> >> >> >> Hello Dmitry,
> >> >> >> 
> >> >> >> Any comments on this version?
> >> >> > 
> >> >> > Looking at it... If you do not hear from me by Wednesday
> >> >> > please ping me again.
> >> >> > 
> >> >> > Thanks.
> >> >> > 
> >> >> > --
> >> >> > Dmitry
> >> >> 
> >> >> ping :)
> >> > 
> >> > Is it still Wednesday by any chance? ;)
> >> 
> >> Hi Dmitry,
> >> 
> >> Thanks for the review and the cleanup patch!
> >> 
> >> > Anyway, the driver looks pretty good, still below are some changes
> >> > that I'd like to get in as well:
> >> > 
> >> > - do not return EAGAIN when operation times out, EIO I believe
> >> > suits
> >> >  better.
> >> > - introduce ttsp_send_command() to replace host of custom
> >> > functions.
> >> > - reduce numver of states to 3 - IDLE, ACTIVE and BL mode.
> >> >  Suspended/full power is already covered by "suspended" attribute.
> >> > - streamline some functions.
> >> 
> >> Seems that your patch handlers all these issues.
> >> 
> >> > Please see the FIXME comment in cyttsp_enable() - is there a
> >> > generic way to wake up the device, similarly to the way we put it
> >> > to sleep?>> 
> >> I guess that CY_OPERATE_MODE works but I have to try it since I don't
> >> have the hw data-sheet.
> >> 
> >> > Please tell me if the device still works with this patch.
> >> > 
> >> > Thanks!
> >> > 
> >> > --
> >> > Dmitry
> >> 
> >> Strange enough, it doesn't apply cleanly on my tree...
> >> 
> >> with patch -p1 < your_patch
> >> 
> >> It should since only the files for this driver are modified and I've
> >> only applied the v10 patches I sent to you.
> >> Anyway I will manually do the changes, try it and resend to you.
> > 
> > Hmm, not sure why it gives you trouble, I tried not to change anything
> > when applying your v10 patches except for folding them all together.
> > 
> > I am attaching the version of the driver I've used as a base - maybe it
> > will save you some time instead of applying the changes manually.
> > 
> > Also, could you please send changes needed to make my patch work as
> > incremental patch so that I can apply on top of mime locally and fold
> > all 3 together? It will be easier to see what exactly changed.
> > 
> > Thanks!
> > 
> > --
> > Dmitry
> 
> Hi Dmitry,
> 
> Using that merged patch as a base your patch applies cleanly (not sure
> what happened with my branch)
> 
> Sadly the driver is not working with your modifications.

I was afraid it could happen - hazards of chaging the code without the way of 
testing it...  I'll try to double check and see what I might have done wrong. 
What device did you test - I2C or SPI? Or do they both fail?

> I'll make it
> work changing as less as possible what was in your patch. Only to make
> the device work again and will send you as an incremental patch as you
> suggested.

Thank you for your patience with me.

> 
> Just to be clear, do you want me to send as an incremental patch of my
> series (v10) or as an incremental patch of your last patch?
> 

Incremental to mine please - so in your working branch you should have the 
original change + my patch as a separate commit + your commit fixing my mess.

-- 
Dmitry

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v10 1/3] Input: cyttsp - Cypress TTSP capacitive multi-touch screen support
  2012-01-27 21:26               ` Dmitry Torokhov
@ 2012-01-29  6:08                 ` Javier Martinez Canillas
  0 siblings, 0 replies; 14+ messages in thread
From: Javier Martinez Canillas @ 2012-01-29  6:08 UTC (permalink / raw)
  To: Dmitry Torokhov, Kevin McNeely, linux-input, Henrik Rydberg

On Fri, Jan 27, 2012 at 10:26 PM, Dmitry Torokhov
<dmitry.torokhov@gmail.com> wrote:
> On Friday, January 27, 2012 10:01:22 PM Javier Martinez Canillas wrote:
>> On Fri, Jan 27, 2012 at 7:18 PM, Dmitry Torokhov
>>
>> <dmitry.torokhov@gmail.com> wrote:
>> > On Fri, Jan 27, 2012 at 04:57:12PM +0100, Javier Martinez Canillas wrote:
>> >> On Fri, Jan 27, 2012 at 9:18 AM, Dmitry Torokhov
>> >>
>> >> <dmitry.torokhov@gmail.com> wrote:
>> >> > On Thu, Jan 26, 2012 at 01:12:50AM +0100, Javier Martinez Canillas
> wrote:
>> >> >> On Tue, Jan 24, 2012 at 8:54 AM, Dmitry Torokhov
>> >> >>
>> >> >> <dmitry.torokhov@gmail.com> wrote:
>> >> >> > On Tue, Jan 24, 2012 at 08:26:39AM +0100, Javier Martinez Canillas
> wrote:
>> >> >> >> On Fri, Jan 20, 2012 at 1:57 AM, Javier Martinez Canillas
>> >> >> >>
>> >> >> >> <javier@dowhile0.org> wrote:
>> >> >> >> > Cypress TrueTouch(tm) Standard Product controllers are
>> >> >> >> > found in
>> >> >> >> > a wide range of embedded devices. This driver add
>> >> >> >> > support for a
>> >> >> >> > variety of TTSP controllers.
>> >> >> >> >
>> >> >> >> > Since the hardware is capable of tracking identifiable
>> >> >> >> > contacts, multi-touch protocol type B (stateful) is
>> >> >> >> > used to report contact information.
>> >> >> >> >
>> >> >> >> > The driver is composed of a core driver that process
>> >> >> >> > the data sent by the contacts and a set of bus
>> >> >> >> > specific interface modules. This patch adds the base
>> >> >> >> > core TTSP driver.
>> >> >> >> >
>> >> >> >> > Signed-off-by: Javier Martinez Canillas
>> >> >> >> > <javier@dowhile0.org>
>> >> >> >> > ---
>> >> >> >> >
>> >> >> >> > Changes for v10: Fix issues called out by Dmitry
>> >> >> >> > Torokhov
>> >> >> >> >        - Remove use_sleep and put device to sleep
>> >> >> >> > unconditionally on suspend - Cleanup
>> >> >> >> > cyttsp_power_on() and remove cyttsp_bl_app_valid()
>> >> >> >> > function
>> >> >> >> >
>> >> >> >> >  drivers/input/touchscreen/Kconfig       |   31 ++
>> >> >> >> >  drivers/input/touchscreen/Makefile      |    3 +
>> >> >> >> >  drivers/input/touchscreen/cyttsp_core.c |  682
>> >> >> >> > +++++++++++++++++++++++++++++++
>> >> >> >> > drivers/input/touchscreen/cyttsp_core.h |  141
>> >> >> >> > +++++++ include/linux/input/cyttsp.h            |
>> >> >> >> > 68 +++
>> >> >> >> >  5 files changed, 925 insertions(+), 0 deletions(-)
>> >> >> >>
>> >> >> >> Hello Dmitry,
>> >> >> >>
>> >> >> >> Any comments on this version?
>> >> >> >
>> >> >> > Looking at it... If you do not hear from me by Wednesday
>> >> >> > please ping me again.
>> >> >> >
>> >> >> > Thanks.
>> >> >> >
>> >> >> > --
>> >> >> > Dmitry
>> >> >>
>> >> >> ping :)
>> >> >
>> >> > Is it still Wednesday by any chance? ;)
>> >>
>> >> Hi Dmitry,
>> >>
>> >> Thanks for the review and the cleanup patch!
>> >>
>> >> > Anyway, the driver looks pretty good, still below are some changes
>> >> > that I'd like to get in as well:
>> >> >
>> >> > - do not return EAGAIN when operation times out, EIO I believe
>> >> > suits
>> >> >  better.
>> >> > - introduce ttsp_send_command() to replace host of custom
>> >> > functions.
>> >> > - reduce numver of states to 3 - IDLE, ACTIVE and BL mode.
>> >> >  Suspended/full power is already covered by "suspended" attribute.
>> >> > - streamline some functions.
>> >>
>> >> Seems that your patch handlers all these issues.
>> >>
>> >> > Please see the FIXME comment in cyttsp_enable() - is there a
>> >> > generic way to wake up the device, similarly to the way we put it
>> >> > to sleep?>>
>> >> I guess that CY_OPERATE_MODE works but I have to try it since I don't
>> >> have the hw data-sheet.
>> >>
>> >> > Please tell me if the device still works with this patch.
>> >> >
>> >> > Thanks!
>> >> >
>> >> > --
>> >> > Dmitry
>> >>
>> >> Strange enough, it doesn't apply cleanly on my tree...
>> >>
>> >> with patch -p1 < your_patch
>> >>
>> >> It should since only the files for this driver are modified and I've
>> >> only applied the v10 patches I sent to you.
>> >> Anyway I will manually do the changes, try it and resend to you.
>> >
>> > Hmm, not sure why it gives you trouble, I tried not to change anything
>> > when applying your v10 patches except for folding them all together.
>> >
>> > I am attaching the version of the driver I've used as a base - maybe it
>> > will save you some time instead of applying the changes manually.
>> >
>> > Also, could you please send changes needed to make my patch work as
>> > incremental patch so that I can apply on top of mime locally and fold
>> > all 3 together? It will be easier to see what exactly changed.
>> >
>> > Thanks!
>> >
>> > --
>> > Dmitry
>>
>> Hi Dmitry,
>>
>> Using that merged patch as a base your patch applies cleanly (not sure
>> what happened with my branch)
>>
>> Sadly the driver is not working with your modifications.
>
> I was afraid it could happen - hazards of chaging the code without the way of
> testing it...  I'll try to double check and see what I might have done wrong.
> What device did you test - I2C or SPI? Or do they both fail?
>

Hi Dmitry,

Just sent an email with the fix of the two bugs I found in your
clean-up patch. With those two fixes the device is working again.

Also I remove the wakeup() platform function. That function told me
Kevin that was in the original Android driver because the device can
be wakeup by flipping the direction of the GPIO ping connected to the
touchscreen IRQ line. But also the device wakes up when there is an
I2C or SPI slave memory address match and by reading one of the device
registers. So trying to read will fail if the device is in sleep mode
but it will wake up the device so the first retry will succeed. I
documented that hardware behavior in the driver to make it clear.

I have only an device connected through I2C device but Kevin has been
testing with a device using SPI.

>> I'll make it
>> work changing as less as possible what was in your patch. Only to make
>> the device work again and will send you as an incremental patch as you
>> suggested.
>
> Thank you for your patience with me.
>

Thank you for your patience and your reviews.

>>
>> Just to be clear, do you want me to send as an incremental patch of my
>> series (v10) or as an incremental patch of your last patch?
>>
>
> Incremental to mine please - so in your working branch you should have the
> original change + my patch as a separate commit + your commit fixing my mess.
>
> --
> Dmitry

Perfect, the patch I sent is an incremental one on top of my three
last patches (v10) + your clean-up patch.

Best regards,
Javier
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2012-01-29  6:08 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-01-20  0:57 [PATCH v10 1/3] Input: cyttsp - Cypress TTSP capacitive multi-touch screen support Javier Martinez Canillas
2012-01-20  0:57 ` [PATCH v10 2/3] Input: cyttsp - add support for Cypress TTSP touchscreen I2C bus interface Javier Martinez Canillas
2012-01-20  0:57 ` [PATCH v10 3/3] Input: cyttsp - add support for Cypress TTSP touchscreen SPI " Javier Martinez Canillas
2012-01-24  7:26 ` [PATCH v10 1/3] Input: cyttsp - Cypress TTSP capacitive multi-touch screen support Javier Martinez Canillas
2012-01-24  7:54   ` Dmitry Torokhov
2012-01-24  8:09     ` Javier Martinez Canillas
2012-01-26  0:12     ` Javier Martinez Canillas
2012-01-27  8:18       ` Dmitry Torokhov
2012-01-27 15:57         ` Javier Martinez Canillas
2012-01-27 18:18           ` Dmitry Torokhov
2012-01-27 21:01             ` Javier Martinez Canillas
2012-01-27 21:26               ` Dmitry Torokhov
2012-01-29  6:08                 ` Javier Martinez Canillas
2012-01-24  9:26   ` Henrik Rydberg

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).