drivers: input: gt911: Add support for multitouch events
The gt911 can recognize up to 5 touch points at a time. Add code to support these multi-touch events. Signed-off-by: Farah Fliss <farah.fliss@nxp.com> Signed-off-by: Phi Bang Nguyen <phibang.nguyen@nxp.com>
This commit is contained in:
parent
bd658642e1
commit
ad254b06c8
2 changed files with 74 additions and 30 deletions
|
|
@ -26,4 +26,11 @@ config INPUT_GT911_INTERRUPT
|
||||||
help
|
help
|
||||||
Enable interrupt support (requires GPIO).
|
Enable interrupt support (requires GPIO).
|
||||||
|
|
||||||
|
config INPUT_GT911_MAX_TOUCH_POINTS
|
||||||
|
int "Touch Number"
|
||||||
|
default 1
|
||||||
|
range 1 5
|
||||||
|
help
|
||||||
|
Maximum number of touch points to be handled.
|
||||||
|
Multitouch is ignored if equal to 1.
|
||||||
endif # INPUT_GT911
|
endif # INPUT_GT911
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@ LOG_MODULE_REGISTER(gt911, CONFIG_INPUT_LOG_LEVEL);
|
||||||
/* GT911 used registers */
|
/* GT911 used registers */
|
||||||
#define DEVICE_ID BSWAP_16(0x8140U)
|
#define DEVICE_ID BSWAP_16(0x8140U)
|
||||||
#define REG_STATUS BSWAP_16(0x814EU)
|
#define REG_STATUS BSWAP_16(0x814EU)
|
||||||
#define REG_FIRST_POINT BSWAP_16(0x814FU)
|
|
||||||
|
|
||||||
/* REG_TD_STATUS: Touch points. */
|
/* REG_TD_STATUS: Touch points. */
|
||||||
#define TOUCH_POINTS_MSK 0x0FU
|
#define TOUCH_POINTS_MSK 0x0FU
|
||||||
|
|
@ -30,9 +29,15 @@ LOG_MODULE_REGISTER(gt911, CONFIG_INPUT_LOG_LEVEL);
|
||||||
/* The GT911's config */
|
/* The GT911's config */
|
||||||
#define REG_GT911_CONFIG BSWAP_16(0x8047U)
|
#define REG_GT911_CONFIG BSWAP_16(0x8047U)
|
||||||
#define REG_CONFIG_VERSION REG_GT911_CONFIG
|
#define REG_CONFIG_VERSION REG_GT911_CONFIG
|
||||||
|
#define REG_CONFIG_TOUCH_NUM_OFFSET 0x5
|
||||||
#define REG_CONFIG_SIZE 186U
|
#define REG_CONFIG_SIZE 186U
|
||||||
#define GT911_PRODUCT_ID 0x00313139U
|
#define GT911_PRODUCT_ID 0x00313139U
|
||||||
|
|
||||||
|
/* Points registers */
|
||||||
|
#define REG_POINT_0 0x814F
|
||||||
|
#define POINT_OFFSET 0x8
|
||||||
|
#define REG_POINT_ADDR(n) BSWAP_16(REG_POINT_0 + POINT_OFFSET * n)
|
||||||
|
|
||||||
/** GT911 configuration (DT). */
|
/** GT911 configuration (DT). */
|
||||||
struct gt911_config {
|
struct gt911_config {
|
||||||
/** I2C bus. */
|
/** I2C bus. */
|
||||||
|
|
@ -101,27 +106,29 @@ static int gt911_process(const struct device *dev)
|
||||||
int r;
|
int r;
|
||||||
uint16_t reg_addr;
|
uint16_t reg_addr;
|
||||||
uint8_t status;
|
uint8_t status;
|
||||||
|
uint8_t i;
|
||||||
|
uint8_t j;
|
||||||
|
uint16_t row;
|
||||||
|
uint16_t col;
|
||||||
uint8_t points;
|
uint8_t points;
|
||||||
struct gt911_point_reg point_reg;
|
static uint8_t prev_points;
|
||||||
uint16_t row, col;
|
struct gt911_point_reg point_reg[CONFIG_INPUT_GT911_MAX_TOUCH_POINTS];
|
||||||
bool pressed;
|
static struct gt911_point_reg prev_point_reg[CONFIG_INPUT_GT911_MAX_TOUCH_POINTS];
|
||||||
|
|
||||||
/* obtain number of touch points (NOTE: multi-touch ignored) */
|
/* obtain number of touch points */
|
||||||
reg_addr = REG_STATUS;
|
reg_addr = REG_STATUS;
|
||||||
r = gt911_i2c_write_read(dev, ®_addr, sizeof(reg_addr), &status, sizeof(status));
|
r = gt911_i2c_write_read(dev, ®_addr, sizeof(reg_addr), &status, sizeof(status));
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
points = status & TOUCH_POINTS_MSK;
|
|
||||||
if (points != 0U && points != 1U && (0 != (status & TOUCH_STATUS_MSK))) {
|
|
||||||
points = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(status & TOUCH_STATUS_MSK)) {
|
if (!(status & TOUCH_STATUS_MSK)) {
|
||||||
/* Status bit not set, ignore this event */
|
/* Status bit not set, ignore this event */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
points = status & TOUCH_POINTS_MSK;
|
||||||
|
|
||||||
/* need to clear the status */
|
/* need to clear the status */
|
||||||
uint8_t clear_buffer[3] = {(uint8_t)REG_STATUS, (uint8_t)(REG_STATUS >> 8), 0};
|
uint8_t clear_buffer[3] = {(uint8_t)REG_STATUS, (uint8_t)(REG_STATUS >> 8), 0};
|
||||||
|
|
||||||
|
|
@ -130,28 +137,55 @@ static int gt911_process(const struct device *dev)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* obtain first point X, Y coordinates and event from:
|
/* current points array */
|
||||||
* REG_P1_XH, REG_P1_XL, REG_P1_YH, REG_P1_YL.
|
for (i = 0; i <= points; i++) {
|
||||||
*/
|
reg_addr = REG_POINT_ADDR(i);
|
||||||
reg_addr = REG_FIRST_POINT;
|
r = gt911_i2c_write_read(dev, ®_addr, sizeof(reg_addr), &point_reg[i],
|
||||||
r = gt911_i2c_write_read(dev, ®_addr, sizeof(reg_addr), &point_reg, sizeof(point_reg));
|
sizeof(point_reg[i]));
|
||||||
|
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pressed = (points == 1);
|
/* touch events */
|
||||||
row = ((point_reg.high_y) << 8U) | point_reg.low_y;
|
for (i = 0; i < points; i++) {
|
||||||
col = ((point_reg.high_x) << 8U) | point_reg.low_x;
|
if (CONFIG_INPUT_GT911_MAX_TOUCH_POINTS > 1) {
|
||||||
|
input_report_abs(dev, INPUT_ABS_MT_SLOT, point_reg[i].id, true, K_FOREVER);
|
||||||
|
}
|
||||||
|
|
||||||
LOG_DBG("pressed: %d, row: %d, col: %d", pressed, row, col);
|
row = ((point_reg[i].high_y) << 8U) | point_reg[i].low_y;
|
||||||
|
col = ((point_reg[i].high_x) << 8U) | point_reg[i].low_x;
|
||||||
|
|
||||||
if (pressed) {
|
|
||||||
input_report_abs(dev, INPUT_ABS_X, col, false, K_FOREVER);
|
input_report_abs(dev, INPUT_ABS_X, col, false, K_FOREVER);
|
||||||
input_report_abs(dev, INPUT_ABS_Y, row, false, K_FOREVER);
|
input_report_abs(dev, INPUT_ABS_Y, row, false, K_FOREVER);
|
||||||
input_report_key(dev, INPUT_BTN_TOUCH, 1, true, K_FOREVER);
|
input_report_key(dev, INPUT_BTN_TOUCH, 1, true, K_FOREVER);
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
/* release events */
|
||||||
|
for (i = 0; i < prev_points; i++) {
|
||||||
|
/* We look for the prev_point in the current points list */
|
||||||
|
for (j = 0; j < points; j++) {
|
||||||
|
if (prev_point_reg[i].id == point_reg[j].id) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j == points) {
|
||||||
|
if (CONFIG_INPUT_GT911_MAX_TOUCH_POINTS > 1) {
|
||||||
|
input_report_abs(dev, INPUT_ABS_MT_SLOT, prev_point_reg[i].id, true,
|
||||||
|
K_FOREVER);
|
||||||
|
}
|
||||||
|
row = ((prev_point_reg[i].high_y) << 8U) | prev_point_reg[i].low_y;
|
||||||
|
col = ((prev_point_reg[i].high_x) << 8U) | prev_point_reg[i].low_x;
|
||||||
|
input_report_abs(dev, INPUT_ABS_X, col, false, K_FOREVER);
|
||||||
|
input_report_abs(dev, INPUT_ABS_Y, row, false, K_FOREVER);
|
||||||
input_report_key(dev, INPUT_BTN_TOUCH, 0, true, K_FOREVER);
|
input_report_key(dev, INPUT_BTN_TOUCH, 0, true, K_FOREVER);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(prev_point_reg, point_reg, sizeof(point_reg));
|
||||||
|
prev_points = points;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -328,6 +362,9 @@ static int gt911_init(const struct device *dev)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gt911_config_firmware[REG_CONFIG_TOUCH_NUM_OFFSET + 2] =
|
||||||
|
CONFIG_INPUT_GT911_MAX_TOUCH_POINTS;
|
||||||
|
|
||||||
gt911_config_firmware[REG_CONFIG_SIZE] =
|
gt911_config_firmware[REG_CONFIG_SIZE] =
|
||||||
gt911_get_firmware_checksum(gt911_config_firmware + 2);
|
gt911_get_firmware_checksum(gt911_config_firmware + 2);
|
||||||
gt911_config_firmware[REG_CONFIG_SIZE + 1] = 1;
|
gt911_config_firmware[REG_CONFIG_SIZE + 1] = 1;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue