Commit a2f39dac authored by Marco Felsch's avatar Marco Felsch Committed by Dmitry Torokhov

Input: edt-ft5x06 - add support for Evervision FT5726

Evervision displays are using different Focaltech touchscreen
controllers. This commit adds the initial support for the ones using the
FT5726 controller. Receiving the touch data is the same as for the
GENERIC_FT but the x and y cooridnates are swapped. The main differences
are the register addresses where the GAIN and THRESHOLD parameters are
stored.
Signed-off-by: default avatarMarco Felsch <m.felsch@pengutronix.de>
Reviewed-by: default avatarRob Herring <robh@kernel.org>
Signed-off-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
parent 1eb7ea26
FocalTech EDT-FT5x06 Polytouch driver FocalTech EDT-FT5x06 Polytouch driver
===================================== =====================================
There are 3 variants of the chip for various touch panel sizes There are 5 variants of the chip for various touch panel sizes
FT5206GE1 2.8" .. 3.8" FT5206GE1 2.8" .. 3.8"
FT5306DE4 4.3" .. 7" FT5306DE4 4.3" .. 7"
FT5406EE8 7" .. 8.9" FT5406EE8 7" .. 8.9"
FT5506EEG 7" .. 8.9" FT5506EEG 7" .. 8.9"
FT5726NEI 5.7” .. 11.6"
The software interface is identical for all those chips, so that The software interface is identical for all those chips, so that
currently there is no need for the driver to distinguish between the currently there is no need for the driver to distinguish between the
...@@ -19,6 +20,7 @@ Required properties: ...@@ -19,6 +20,7 @@ Required properties:
or: "edt,edt-ft5306" or: "edt,edt-ft5306"
or: "edt,edt-ft5406" or: "edt,edt-ft5406"
or: "edt,edt-ft5506" or: "edt,edt-ft5506"
or: "evervision,ev-ft5726"
or: "focaltech,ft6236" or: "focaltech,ft6236"
- reg: I2C slave address of the chip (0x38) - reg: I2C slave address of the chip (0x38)
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/kernel.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
...@@ -53,6 +54,9 @@ ...@@ -53,6 +54,9 @@
#define M09_REGISTER_NUM_X 0x94 #define M09_REGISTER_NUM_X 0x94
#define M09_REGISTER_NUM_Y 0x95 #define M09_REGISTER_NUM_Y 0x95
#define EV_REGISTER_THRESHOLD 0x40
#define EV_REGISTER_GAIN 0x41
#define NO_REGISTER 0xff #define NO_REGISTER 0xff
#define WORK_REGISTER_OPMODE 0x3c #define WORK_REGISTER_OPMODE 0x3c
...@@ -73,6 +77,7 @@ enum edt_ver { ...@@ -73,6 +77,7 @@ enum edt_ver {
EDT_M06, EDT_M06,
EDT_M09, EDT_M09,
EDT_M12, EDT_M12,
EV_FT,
GENERIC_FT, GENERIC_FT,
}; };
...@@ -190,6 +195,7 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id) ...@@ -190,6 +195,7 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id)
case EDT_M09: case EDT_M09:
case EDT_M12: case EDT_M12:
case EV_FT:
case GENERIC_FT: case GENERIC_FT:
cmd = 0x0; cmd = 0x0;
offset = 3; offset = 3;
...@@ -242,6 +248,10 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id) ...@@ -242,6 +248,10 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id)
x = ((buf[0] << 8) | buf[1]) & 0x0fff; x = ((buf[0] << 8) | buf[1]) & 0x0fff;
y = ((buf[2] << 8) | buf[3]) & 0x0fff; y = ((buf[2] << 8) | buf[3]) & 0x0fff;
/* The FT5x26 send the y coordinate first */
if (tsdata->version == EV_FT)
swap(x, y);
id = (buf[2] >> 4) & 0x0f; id = (buf[2] >> 4) & 0x0f;
down = type != TOUCH_EVENT_UP; down = type != TOUCH_EVENT_UP;
...@@ -275,8 +285,10 @@ static int edt_ft5x06_register_write(struct edt_ft5x06_ts_data *tsdata, ...@@ -275,8 +285,10 @@ static int edt_ft5x06_register_write(struct edt_ft5x06_ts_data *tsdata,
wrbuf[3] = wrbuf[0] ^ wrbuf[1] ^ wrbuf[2]; wrbuf[3] = wrbuf[0] ^ wrbuf[1] ^ wrbuf[2];
return edt_ft5x06_ts_readwrite(tsdata->client, 4, return edt_ft5x06_ts_readwrite(tsdata->client, 4,
wrbuf, 0, NULL); wrbuf, 0, NULL);
/* fallthrough */
case EDT_M09: case EDT_M09:
case EDT_M12: case EDT_M12:
case EV_FT:
case GENERIC_FT: case GENERIC_FT:
wrbuf[0] = addr; wrbuf[0] = addr;
wrbuf[1] = value; wrbuf[1] = value;
...@@ -315,8 +327,10 @@ static int edt_ft5x06_register_read(struct edt_ft5x06_ts_data *tsdata, ...@@ -315,8 +327,10 @@ static int edt_ft5x06_register_read(struct edt_ft5x06_ts_data *tsdata,
} }
break; break;
/* fallthrough */
case EDT_M09: case EDT_M09:
case EDT_M12: case EDT_M12:
case EV_FT:
case GENERIC_FT: case GENERIC_FT:
wrbuf[0] = addr; wrbuf[0] = addr;
error = edt_ft5x06_ts_readwrite(tsdata->client, 1, error = edt_ft5x06_ts_readwrite(tsdata->client, 1,
...@@ -605,8 +619,9 @@ static int edt_ft5x06_work_mode(struct edt_ft5x06_ts_data *tsdata) ...@@ -605,8 +619,9 @@ static int edt_ft5x06_work_mode(struct edt_ft5x06_ts_data *tsdata)
tsdata->threshold); tsdata->threshold);
edt_ft5x06_register_write(tsdata, reg_addr->reg_gain, edt_ft5x06_register_write(tsdata, reg_addr->reg_gain,
tsdata->gain); tsdata->gain);
edt_ft5x06_register_write(tsdata, reg_addr->reg_offset, if (reg_addr->reg_offset != NO_REGISTER)
tsdata->offset); edt_ft5x06_register_write(tsdata, reg_addr->reg_offset,
tsdata->offset);
if (reg_addr->reg_report_rate != NO_REGISTER) if (reg_addr->reg_report_rate != NO_REGISTER)
edt_ft5x06_register_write(tsdata, reg_addr->reg_report_rate, edt_ft5x06_register_write(tsdata, reg_addr->reg_report_rate,
tsdata->report_rate); tsdata->report_rate);
...@@ -867,6 +882,16 @@ static int edt_ft5x06_ts_identify(struct i2c_client *client, ...@@ -867,6 +882,16 @@ static int edt_ft5x06_ts_identify(struct i2c_client *client,
case 0x5a: /* Solomon Goldentek Display */ case 0x5a: /* Solomon Goldentek Display */
snprintf(model_name, EDT_NAME_LEN, "GKTW50SCED1R0"); snprintf(model_name, EDT_NAME_LEN, "GKTW50SCED1R0");
break; break;
case 0x59: /* Evervision Display with FT5xx6 TS */
tsdata->version = EV_FT;
error = edt_ft5x06_ts_readwrite(client, 1, "\x53",
1, rdbuf);
if (error)
return error;
strlcpy(fw_version, rdbuf, 1);
snprintf(model_name, EDT_NAME_LEN,
"EVERVISION-FT5726NEi");
break;
default: default:
snprintf(model_name, EDT_NAME_LEN, snprintf(model_name, EDT_NAME_LEN,
"generic ft5x06 (%02x)", "generic ft5x06 (%02x)",
...@@ -912,7 +937,9 @@ edt_ft5x06_ts_get_parameters(struct edt_ft5x06_ts_data *tsdata) ...@@ -912,7 +937,9 @@ edt_ft5x06_ts_get_parameters(struct edt_ft5x06_ts_data *tsdata)
tsdata->threshold = edt_ft5x06_register_read(tsdata, tsdata->threshold = edt_ft5x06_register_read(tsdata,
reg_addr->reg_threshold); reg_addr->reg_threshold);
tsdata->gain = edt_ft5x06_register_read(tsdata, reg_addr->reg_gain); tsdata->gain = edt_ft5x06_register_read(tsdata, reg_addr->reg_gain);
tsdata->offset = edt_ft5x06_register_read(tsdata, reg_addr->reg_offset); if (reg_addr->reg_offset != NO_REGISTER)
tsdata->offset =
edt_ft5x06_register_read(tsdata, reg_addr->reg_offset);
if (reg_addr->reg_report_rate != NO_REGISTER) if (reg_addr->reg_report_rate != NO_REGISTER)
tsdata->report_rate = edt_ft5x06_register_read(tsdata, tsdata->report_rate = edt_ft5x06_register_read(tsdata,
reg_addr->reg_report_rate); reg_addr->reg_report_rate);
...@@ -954,6 +981,15 @@ edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata) ...@@ -954,6 +981,15 @@ edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata)
reg_addr->reg_num_y = M09_REGISTER_NUM_Y; reg_addr->reg_num_y = M09_REGISTER_NUM_Y;
break; break;
case EV_FT:
reg_addr->reg_threshold = EV_REGISTER_THRESHOLD;
reg_addr->reg_gain = EV_REGISTER_GAIN;
reg_addr->reg_offset = NO_REGISTER;
reg_addr->reg_num_x = NO_REGISTER;
reg_addr->reg_num_y = NO_REGISTER;
reg_addr->reg_report_rate = NO_REGISTER;
break;
case GENERIC_FT: case GENERIC_FT:
/* this is a guesswork */ /* this is a guesswork */
reg_addr->reg_threshold = M09_REGISTER_THRESHOLD; reg_addr->reg_threshold = M09_REGISTER_THRESHOLD;
...@@ -1155,6 +1191,7 @@ static const struct edt_i2c_chip_data edt_ft6236_data = { ...@@ -1155,6 +1191,7 @@ static const struct edt_i2c_chip_data edt_ft6236_data = {
static const struct i2c_device_id edt_ft5x06_ts_id[] = { static const struct i2c_device_id edt_ft5x06_ts_id[] = {
{ .name = "edt-ft5x06", .driver_data = (long)&edt_ft5x06_data }, { .name = "edt-ft5x06", .driver_data = (long)&edt_ft5x06_data },
{ .name = "edt-ft5506", .driver_data = (long)&edt_ft5506_data }, { .name = "edt-ft5506", .driver_data = (long)&edt_ft5506_data },
{ .name = "ev-ft5726", .driver_data = (long)&edt_ft5506_data },
/* Note no edt- prefix for compatibility with the ft6236.c driver */ /* Note no edt- prefix for compatibility with the ft6236.c driver */
{ .name = "ft6236", .driver_data = (long)&edt_ft6236_data }, { .name = "ft6236", .driver_data = (long)&edt_ft6236_data },
{ /* sentinel */ } { /* sentinel */ }
...@@ -1167,6 +1204,7 @@ static const struct of_device_id edt_ft5x06_of_match[] = { ...@@ -1167,6 +1204,7 @@ static const struct of_device_id edt_ft5x06_of_match[] = {
{ .compatible = "edt,edt-ft5306", .data = &edt_ft5x06_data }, { .compatible = "edt,edt-ft5306", .data = &edt_ft5x06_data },
{ .compatible = "edt,edt-ft5406", .data = &edt_ft5x06_data }, { .compatible = "edt,edt-ft5406", .data = &edt_ft5x06_data },
{ .compatible = "edt,edt-ft5506", .data = &edt_ft5506_data }, { .compatible = "edt,edt-ft5506", .data = &edt_ft5506_data },
{ .compatible = "evervision,ev-ft5726", .data = &edt_ft5506_data },
/* Note focaltech vendor prefix for compatibility with ft6236.c */ /* Note focaltech vendor prefix for compatibility with ft6236.c */
{ .compatible = "focaltech,ft6236", .data = &edt_ft6236_data }, { .compatible = "focaltech,ft6236", .data = &edt_ft6236_data },
{ /* sentinel */ } { /* sentinel */ }
......
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