Browse Source

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>
pull/77305/head
Farah Fliss 1 year ago committed by Anas Nashif
parent
commit
ad254b06c8
  1. 7
      drivers/input/Kconfig.gt911
  2. 97
      drivers/input/input_gt911.c

7
drivers/input/Kconfig.gt911

@ -26,4 +26,11 @@ config INPUT_GT911_INTERRUPT @@ -26,4 +26,11 @@ config INPUT_GT911_INTERRUPT
help
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

97
drivers/input/input_gt911.c

@ -17,9 +17,8 @@ @@ -17,9 +17,8 @@
LOG_MODULE_REGISTER(gt911, CONFIG_INPUT_LOG_LEVEL);
/* GT911 used registers */
#define DEVICE_ID BSWAP_16(0x8140U)
#define REG_STATUS BSWAP_16(0x814EU)
#define REG_FIRST_POINT BSWAP_16(0x814FU)
#define DEVICE_ID BSWAP_16(0x8140U)
#define REG_STATUS BSWAP_16(0x814EU)
/* REG_TD_STATUS: Touch points. */
#define TOUCH_POINTS_MSK 0x0FU
@ -28,10 +27,16 @@ LOG_MODULE_REGISTER(gt911, CONFIG_INPUT_LOG_LEVEL); @@ -28,10 +27,16 @@ LOG_MODULE_REGISTER(gt911, CONFIG_INPUT_LOG_LEVEL);
#define TOUCH_STATUS_MSK (1 << 7U)
/* The GT911's config */
#define REG_GT911_CONFIG BSWAP_16(0x8047U)
#define REG_CONFIG_VERSION REG_GT911_CONFIG
#define REG_CONFIG_SIZE 186U
#define GT911_PRODUCT_ID 0x00313139U
#define REG_GT911_CONFIG BSWAP_16(0x8047U)
#define REG_CONFIG_VERSION REG_GT911_CONFIG
#define REG_CONFIG_TOUCH_NUM_OFFSET 0x5
#define REG_CONFIG_SIZE 186U
#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). */
struct gt911_config {
@ -101,27 +106,29 @@ static int gt911_process(const struct device *dev) @@ -101,27 +106,29 @@ static int gt911_process(const struct device *dev)
int r;
uint16_t reg_addr;
uint8_t status;
uint8_t i;
uint8_t j;
uint16_t row;
uint16_t col;
uint8_t points;
struct gt911_point_reg point_reg;
uint16_t row, col;
bool pressed;
static uint8_t prev_points;
struct gt911_point_reg point_reg[CONFIG_INPUT_GT911_MAX_TOUCH_POINTS];
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;
r = gt911_i2c_write_read(dev, &reg_addr, sizeof(reg_addr), &status, sizeof(status));
if (r < 0) {
return r;
}
points = status & TOUCH_POINTS_MSK;
if (points != 0U && points != 1U && (0 != (status & TOUCH_STATUS_MSK))) {
points = 1;
}
if (!(status & TOUCH_STATUS_MSK)) {
/* Status bit not set, ignore this event */
return 0;
}
points = status & TOUCH_POINTS_MSK;
/* need to clear the status */
uint8_t clear_buffer[3] = {(uint8_t)REG_STATUS, (uint8_t)(REG_STATUS >> 8), 0};
@ -130,29 +137,56 @@ static int gt911_process(const struct device *dev) @@ -130,29 +137,56 @@ static int gt911_process(const struct device *dev)
return r;
}
/* obtain first point X, Y coordinates and event from:
* REG_P1_XH, REG_P1_XL, REG_P1_YH, REG_P1_YL.
*/
reg_addr = REG_FIRST_POINT;
r = gt911_i2c_write_read(dev, &reg_addr, sizeof(reg_addr), &point_reg, sizeof(point_reg));
if (r < 0) {
return r;
/* current points array */
for (i = 0; i <= points; i++) {
reg_addr = REG_POINT_ADDR(i);
r = gt911_i2c_write_read(dev, &reg_addr, sizeof(reg_addr), &point_reg[i],
sizeof(point_reg[i]));
if (r < 0) {
return r;
}
}
pressed = (points == 1);
row = ((point_reg.high_y) << 8U) | point_reg.low_y;
col = ((point_reg.high_x) << 8U) | point_reg.low_x;
/* touch events */
for (i = 0; i < points; i++) {
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_Y, row, false, K_FOREVER);
input_report_key(dev, INPUT_BTN_TOUCH, 1, true, K_FOREVER);
} else {
input_report_key(dev, INPUT_BTN_TOUCH, 0, true, K_FOREVER);
}
/* 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);
}
}
memcpy(prev_point_reg, point_reg, sizeof(point_reg));
prev_points = points;
return 0;
}
@ -328,6 +362,9 @@ static int gt911_init(const struct device *dev) @@ -328,6 +362,9 @@ static int gt911_init(const struct device *dev)
return -ENODEV;
}
gt911_config_firmware[REG_CONFIG_TOUCH_NUM_OFFSET + 2] =
CONFIG_INPUT_GT911_MAX_TOUCH_POINTS;
gt911_config_firmware[REG_CONFIG_SIZE] =
gt911_get_firmware_checksum(gt911_config_firmware + 2);
gt911_config_firmware[REG_CONFIG_SIZE + 1] = 1;

Loading…
Cancel
Save