Commit 4065d1e7 authored by Javier Martinez Canillas's avatar Javier Martinez Canillas Committed by Dmitry Torokhov

Input: add Cypress TTSP capacitive multi-touch screen support

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: default avatarJavier Martinez Canillas <javier@dowhile0.org>
Reviewed-by: default avatarHenrik Rydberg <rydberg@euromail.se>
Signed-off-by: default avatarDmitry Torokhov <dtor@mail.ru>
parent 31175a83
......@@ -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
......
......@@ -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_DYNAPRO) += dynapro.o
obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += hampshire.o
......
This diff is collapsed.
/*
* 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;
struct cyttsp_bus_ops {
u16 bustype;
int (*write)(struct cyttsp *ts,
u8 addr, u8 length, const void *values);
int (*read)(struct cyttsp *ts, u8 addr, u8 length, void *values);
};
enum cyttsp_state {
CY_IDLE_STATE,
CY_ACTIVE_STATE,
CY_BL_STATE,
};
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 cyttsp_xydata xy_data;
struct completion bl_ready;
enum cyttsp_state state;
bool suspended;
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__ */
/*
* 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 cyttsp *ts,
u8 addr, u8 length, void *values)
{
struct i2c_client *client = to_i2c_client(ts->dev);
struct i2c_msg msgs[] = {
{
.addr = client->addr,
.flags = 0,
.len = 1,
.buf = &addr,
},
{
.addr = client->addr,
.flags = I2C_M_RD,
.len = length,
.buf = values,
},
};
int retval;
retval = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
if (retval < 0)
return retval;
return retval != ARRAY_SIZE(msgs) ? -EIO : 0;
}
static int cyttsp_i2c_write_block_data(struct cyttsp *ts,
u8 addr, u8 length, const void *values)
{
struct i2c_client *client = to_i2c_client(ts->dev);
int retval;
ts->xfer_buf[0] = addr;
memcpy(&ts->xfer_buf[1], values, length);
retval = i2c_master_send(client, ts->xfer_buf, length + 1);
return retval < 0 ? retval : 0;
}
static const struct cyttsp_bus_ops cyttsp_i2c_bus_ops = {
.bustype = BUS_I2C,
.write = cyttsp_i2c_write_block_data,
.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");
/*
* 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(struct cyttsp *ts,
u8 op, u8 reg, u8 *buf, int length)
{
struct spi_device *spi = to_spi_device(ts->dev);
struct spi_message msg;
struct spi_transfer xfer[2];
u8 *wr_buf = &ts->xfer_buf[0];
u8 *rd_buf = &ts->xfer_buf[CY_SPI_DATA_BUF_SIZE];
int retval;
int i;
if (length > CY_SPI_DATA_SIZE) {
dev_err(ts->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_err(ts->dev, "%s: bad operation code=%d\n", __func__, op);
return -EINVAL;
}
retval = spi_sync(spi, &msg);
if (retval < 0) {
dev_dbg(ts->dev, "%s: spi_sync() error %d, len=%d, op=%d\n",
__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) {
dev_dbg(ts->dev, "%s: operation %d failed\n", __func__, op);
for (i = 0; i < CY_SPI_CMD_BYTES; i++)
dev_dbg(ts->dev, "%s: test rd_buf[%d]:0x%02x\n",
__func__, i, rd_buf[i]);
for (i = 0; i < length; i++)
dev_dbg(ts->dev, "%s: test buf[%d]:0x%02x\n",
__func__, i, buf[i]);
return -EIO;
}
return 0;
}
static int cyttsp_spi_read_block_data(struct cyttsp *ts,
u8 addr, u8 length, void *data)
{
return cyttsp_spi_xfer(ts, CY_SPI_RD_OP, addr, data, length);
}
static int cyttsp_spi_write_block_data(struct cyttsp *ts,
u8 addr, u8 length, const void *data)
{
return cyttsp_spi_xfer(ts, CY_SPI_WR_OP, 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,
};
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 = spi_get_drvdata(spi);
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");
/*
* 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 */
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 (*init)(void);
void (*exit)(void);
char *name;
s16 irq_gpio;
u8 *bl_keys;
};
#endif /* _CYTTSP_H_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment