Commit eb91ecc9 authored by Marek Vasut's avatar Marek Vasut Committed by Dmitry Torokhov

Input: ili210x - add ILI2117 support

Add support for ILI2117 touch controller. This controller is similar
to the ILI210x and ILI251x, except for the following differences:
- Reading out of touch data must happen at most 300 mS after the
  interrupt line was asserted. No command must be sent, the data
  are returned upon pure I2C read of 43 bytes long.
- Supports 10 simultaneous touch inputs.
- Touch data format is slightly different.
Signed-off-by: default avatarMarek Vasut <marex@denx.de>
Reviewed-by: Rob Herring <robh@kernel.org> # for DT binding
Tested-by: Adam Ford <aford173@gmail.com> #imx6q-logicpd
Tested-by: Sven Van Asbroeck <TheSven73@gmail.com> # ILI2118A variant
Signed-off-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
parent 4d856f72
Ilitek ILI210x/ILI251x touchscreen controller Ilitek ILI210x/ILI2117/ILI251x touchscreen controller
Required properties: Required properties:
- compatible: - compatible:
ilitek,ili210x for ILI210x ilitek,ili210x for ILI210x
ilitek,ili2117 for ILI2117
ilitek,ili251x for ILI251x ilitek,ili251x for ILI251x
- reg: The I2C address of the device - reg: The I2C address of the device
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <asm/unaligned.h> #include <asm/unaligned.h>
#define ILI210X_TOUCHES 2 #define ILI210X_TOUCHES 2
#define ILI211X_TOUCHES 10
#define ILI251X_TOUCHES 10 #define ILI251X_TOUCHES 10
#define DEFAULT_POLL_PERIOD 20 #define DEFAULT_POLL_PERIOD 20
...@@ -30,6 +31,7 @@ struct firmware_version { ...@@ -30,6 +31,7 @@ struct firmware_version {
enum ili2xxx_model { enum ili2xxx_model {
MODEL_ILI210X, MODEL_ILI210X,
MODEL_ILI211X,
MODEL_ILI251X, MODEL_ILI251X,
}; };
...@@ -118,6 +120,27 @@ static bool ili210x_touchdata_to_coords(struct ili210x *priv, u8 *touchdata, ...@@ -118,6 +120,27 @@ static bool ili210x_touchdata_to_coords(struct ili210x *priv, u8 *touchdata,
return true; return true;
} }
static bool ili211x_touchdata_to_coords(struct ili210x *priv, u8 *touchdata,
unsigned int finger,
unsigned int *x, unsigned int *y)
{
u32 data;
if (finger >= ILI211X_TOUCHES)
return false;
data = get_unaligned_be32(touchdata + 1 + (finger * 4) + 0);
if (data == 0xffffffff) /* Finger up */
return false;
*x = ((touchdata[1 + (finger * 4) + 0] & 0xf0) << 4) |
touchdata[1 + (finger * 4) + 1];
*y = ((touchdata[1 + (finger * 4) + 0] & 0x0f) << 8) |
touchdata[1 + (finger * 4) + 2];
return true;
}
static bool ili251x_touchdata_to_coords(struct ili210x *priv, u8 *touchdata, static bool ili251x_touchdata_to_coords(struct ili210x *priv, u8 *touchdata,
unsigned int finger, unsigned int finger,
unsigned int *x, unsigned int *y) unsigned int *x, unsigned int *y)
...@@ -146,6 +169,9 @@ static bool ili210x_report_events(struct ili210x *priv, u8 *touchdata) ...@@ -146,6 +169,9 @@ static bool ili210x_report_events(struct ili210x *priv, u8 *touchdata)
if (priv->model == MODEL_ILI210X) { if (priv->model == MODEL_ILI210X) {
touch = ili210x_touchdata_to_coords(priv, touchdata, touch = ili210x_touchdata_to_coords(priv, touchdata,
i, &x, &y); i, &x, &y);
} else if (priv->model == MODEL_ILI211X) {
touch = ili211x_touchdata_to_coords(priv, touchdata,
i, &x, &y);
} else if (priv->model == MODEL_ILI251X) { } else if (priv->model == MODEL_ILI251X) {
touch = ili251x_touchdata_to_coords(priv, touchdata, touch = ili251x_touchdata_to_coords(priv, touchdata,
i, &x, &y); i, &x, &y);
...@@ -176,12 +202,26 @@ static void ili210x_work(struct work_struct *work) ...@@ -176,12 +202,26 @@ static void ili210x_work(struct work_struct *work)
dwork.work); dwork.work);
struct i2c_client *client = priv->client; struct i2c_client *client = priv->client;
u8 touchdata[64] = { 0 }; u8 touchdata[64] = { 0 };
s16 sum = 0;
bool touch; bool touch;
int error = -EINVAL; int i, error = -EINVAL;
if (priv->model == MODEL_ILI210X) { if (priv->model == MODEL_ILI210X) {
error = ili210x_read_reg(client, REG_TOUCHDATA, error = ili210x_read_reg(client, REG_TOUCHDATA,
touchdata, sizeof(touchdata)); touchdata, sizeof(touchdata));
} else if (priv->model == MODEL_ILI211X) {
error = ili210x_read(client, touchdata, 43);
if (!error) {
/* This chip uses custom checksum at the end of data */
for (i = 0; i <= 41; i++)
sum = (sum + touchdata[i]) & 0xff;
if ((-sum & 0xff) != touchdata[42]) {
dev_err(&client->dev,
"CRC error (crc=0x%02x expected=0x%02x)\n",
sum, touchdata[42]);
return;
}
}
} else if (priv->model == MODEL_ILI251X) { } else if (priv->model == MODEL_ILI251X) {
error = ili210x_read_reg(client, REG_TOUCHDATA, error = ili210x_read_reg(client, REG_TOUCHDATA,
touchdata, 31); touchdata, 31);
...@@ -311,6 +351,8 @@ static int ili210x_i2c_probe(struct i2c_client *client, ...@@ -311,6 +351,8 @@ static int ili210x_i2c_probe(struct i2c_client *client,
priv->model = model; priv->model = model;
if (model == MODEL_ILI210X) if (model == MODEL_ILI210X)
priv->max_touches = ILI210X_TOUCHES; priv->max_touches = ILI210X_TOUCHES;
if (model == MODEL_ILI211X)
priv->max_touches = ILI211X_TOUCHES;
if (model == MODEL_ILI251X) if (model == MODEL_ILI251X)
priv->max_touches = ILI251X_TOUCHES; priv->max_touches = ILI251X_TOUCHES;
...@@ -395,6 +437,7 @@ static SIMPLE_DEV_PM_OPS(ili210x_i2c_pm, ...@@ -395,6 +437,7 @@ static SIMPLE_DEV_PM_OPS(ili210x_i2c_pm,
static const struct i2c_device_id ili210x_i2c_id[] = { static const struct i2c_device_id ili210x_i2c_id[] = {
{ "ili210x", MODEL_ILI210X }, { "ili210x", MODEL_ILI210X },
{ "ili2117", MODEL_ILI211X },
{ "ili251x", MODEL_ILI251X }, { "ili251x", MODEL_ILI251X },
{ } { }
}; };
...@@ -402,6 +445,7 @@ MODULE_DEVICE_TABLE(i2c, ili210x_i2c_id); ...@@ -402,6 +445,7 @@ MODULE_DEVICE_TABLE(i2c, ili210x_i2c_id);
static const struct of_device_id ili210x_dt_ids[] = { static const struct of_device_id ili210x_dt_ids[] = {
{ .compatible = "ilitek,ili210x", .data = (void *)MODEL_ILI210X }, { .compatible = "ilitek,ili210x", .data = (void *)MODEL_ILI210X },
{ .compatible = "ilitek,ili2117", .data = (void *)MODEL_ILI211X },
{ .compatible = "ilitek,ili251x", .data = (void *)MODEL_ILI251X }, { .compatible = "ilitek,ili251x", .data = (void *)MODEL_ILI251X },
{ }, { },
}; };
......
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