diff options
-rw-r--r-- | goodix_brl_hw.c | 56 | ||||
-rw-r--r-- | goodix_ts_core.h | 3 | ||||
-rw-r--r-- | goodix_ts_gesture.c | 2 | ||||
-rw-r--r-- | goodix_ts_proc.c | 323 |
4 files changed, 332 insertions, 52 deletions
diff --git a/goodix_brl_hw.c b/goodix_brl_hw.c index 34675bf..e22ce0d 100644 --- a/goodix_brl_hw.c +++ b/goodix_brl_hw.c @@ -265,9 +265,26 @@ int brl_resume(struct goodix_ts_core *cd) { u32 cmd_reg = cd->ic_info.misc.cmd_addr; u8 cmd_buf[] = { 0x00, 0x00, 0x05, 0xC4, 0x00, 0xC9, 0x00 }; + int retry = 20; + u8 rcv_buf[2]; + + cd->hw_ops->write(cd, cmd_reg, cmd_buf, sizeof(cmd_buf)); + + while (retry--) { + usleep_range(5000, 5100); + cd->hw_ops->read(cd, cmd_reg, rcv_buf, sizeof(rcv_buf)); + if (rcv_buf[0] == 0x80 && rcv_buf[1] == 0x80) + break; + } + if (retry < 0) { + ts_err("failed to exit sleep mode, status[%X] ack[%X]", + rcv_buf[0], rcv_buf[1]); + return -EINVAL; + } else { + ts_info("Secceed to exit sleep mode with retry: %d", 19 - retry); + } - return cd->hw_ops->write(cd, cmd_reg, cmd_buf, sizeof(cmd_buf)); - // return cd->hw_ops->reset(cd, GOODIX_NORMAL_RESET_DELAY_MS); + return 0; } #define GOODIX_GESTURE_CMD_BA 0x12 @@ -275,12 +292,18 @@ int brl_resume(struct goodix_ts_core *cd) int brl_gesture(struct goodix_ts_core *cd, int gesture_type) { struct goodix_ts_cmd cmd; - u8 val = 0xff; + u8 val; - if (cd->gesture_type & GESTURE_SINGLE_TAP) - val &= ~(0x01 << 0); - if (cd->gesture_type & GESTURE_FOD_PRESS) - val &= ~(0x01 << 1); + if ((cd->gesture_type & GESTURE_SINGLE_TAP) && + (cd->gesture_type & GESTURE_FOD_PRESS)) { + val = 0x0F; + } else if (cd->gesture_type & GESTURE_SINGLE_TAP) { + val = 0x2F; + } else if (cd->gesture_type & GESTURE_FOD_PRESS) { + val = 0x1F; + } else { + val = 0xFF; + } if (cd->bus->ic_type == IC_TYPE_BERLIN_A) cmd.cmd = GOODIX_GESTURE_CMD_BA; @@ -323,7 +346,7 @@ static int brl_irq_enable(struct goodix_ts_core *cd, bool enable) ts_debug("Irq disabled"); return 0; } - ts_info("warnning: irq deepth inbalance!"); + // ts_info("warnning: irq deepth inbalance!"); return 0; } @@ -382,8 +405,6 @@ static int brl_send_cmd(struct goodix_ts_core *cd, struct goodix_ts_cmd *cmd) ts_debug("cmd ack data %*ph", (int)sizeof(cmd_ack), cmd_ack.buf); if (cmd_ack.ack == CMD_ACK_OK) { - // msleep(40); // wait for cmd response - usleep_range(6000, 6100); return 0; } if (cmd_ack.ack == CMD_ACK_BUSY || @@ -1155,10 +1176,23 @@ static int brl_event_handler( struct goodix_ts_hw_ops *hw_ops = cd->hw_ops; struct goodix_ic_info_misc *misc = &cd->ic_info.misc; int pre_read_len; + int tx = cd->ic_info.parm.drv_num; + int rx = cd->ic_info.parm.sen_num; u8 pre_buf[38]; u8 event_status; + u32 mutual_addr; int ret; + if (cd->heatmap_buffer) { + mutual_addr = cd->ic_info.misc.frame_data_addr + + cd->ic_info.misc.frame_data_head_len + + cd->ic_info.misc.fw_attr_len + + cd->ic_info.misc.fw_log_len + 8; + brl_read( + cd, mutual_addr, (u8 *)cd->heatmap_buffer, tx * rx * 2); + goodix_rotate_abcd2cbad(tx, rx, cd->heatmap_buffer); + } + pre_read_len = IRQ_EVENT_HEAD_LEN + BYTES_PER_POINT * 2 + COOR_DATA_CHECKSUM_SIZE + 4; ret = hw_ops->read(cd, misc->touch_data_addr, pre_buf, pre_read_len); @@ -1178,6 +1212,8 @@ static int brl_event_handler( return -EINVAL; } + ts_event->event_type = EVENT_INVALID; + event_status = pre_buf[0]; if (event_status & GOODIX_TOUCH_EVENT) return goodix_touch_handler( diff --git a/goodix_ts_core.h b/goodix_ts_core.h index 70afaa7..e28738a 100644 --- a/goodix_ts_core.h +++ b/goodix_ts_core.h @@ -49,7 +49,7 @@ #define GOODIX_CORE_DRIVER_NAME "goodix_ts" #define GOODIX_PEN_DRIVER_NAME "goodix_ts,pen" -#define GOODIX_DRIVER_VERSION "v1.0.5" +#define GOODIX_DRIVER_VERSION "v1.0.6" #define GOODIX_MAX_TOUCH 10 #define GOODIX_PEN_MAX_PRESSURE 4096 #define GOODIX_MAX_PEN_KEY 2 @@ -523,6 +523,7 @@ struct goodix_ts_core { struct regulator *avdd; struct regulator *iovdd; unsigned char gesture_type; + s16 *heatmap_buffer; int power_on; int irq; diff --git a/goodix_ts_gesture.c b/goodix_ts_gesture.c index 837b9a4..394a32e 100644 --- a/goodix_ts_gesture.c +++ b/goodix_ts_gesture.c @@ -317,8 +317,6 @@ static int gsx_gesture_ist( } re_send_ges_cmd: - if (hw_ops->gesture(cd, 0)) - ts_info("warning: failed re_send gesture cmd"); return EVT_CANCEL_IRQEVT; } diff --git a/goodix_ts_proc.c b/goodix_ts_proc.c index 5e8f4ae..777eb3d 100644 --- a/goodix_ts_proc.c +++ b/goodix_ts_proc.c @@ -22,6 +22,7 @@ #define CMD_SET_DOUBLE_TAP "set_double_tap" #define CMD_SET_SINGLE_TAP "set_single_tap" #define CMD_SET_LONG_PRESS "set_long_press" +#define CMD_SET_GESTURE_PARAM "set_gesture_param" #define CMD_SET_CHARGE_MODE "set_charge_mode" #define CMD_SET_IRQ_ENABLE "set_irq_enable" #define CMD_SET_ESD_ENABLE "set_esd_enable" @@ -32,7 +33,7 @@ #define CMD_GET_CHANNEL_NUM "get_channel_num" #define CMD_GET_TX_FREQ "get_tx_freq" #define CMD_RESET "reset" -#define CMD_SET_SENSE_ENABLE "set_sense_enable" +#define CMD_SET_SENSE_MODE "set_sense_mode" #define CMD_GET_CONFIG "get_config" #define CMD_GET_FW_STATUS "get_fw_status" #define CMD_SET_HIGHSENSE_MODE "set_highsense_mode" @@ -40,18 +41,20 @@ #define CMD_SET_PALM_MODE "set_palm_mode" #define CMD_SET_NOISE_MODE "set_noise_mode" #define CMD_SET_WATER_MODE "set_water_mode" +#define CMD_SET_HEATMAP "set_heatmap" char *cmd_list[] = { CMD_FW_UPDATE, CMD_AUTO_TEST, CMD_OPEN_TEST, CMD_SELF_OPEN_TEST, CMD_NOISE_TEST, CMD_AUTO_NOISE_TEST, CMD_SHORT_TEST, CMD_GET_PACKAGE_ID, CMD_GET_VERSION, CMD_GET_RAWDATA, CMD_GET_DIFFDATA, CMD_GET_BASEDATA, CMD_GET_SELF_RAWDATA, CMD_GET_SELF_DIFFDATA, CMD_GET_SELF_BASEDATA, CMD_SET_DOUBLE_TAP, CMD_SET_SINGLE_TAP, - CMD_SET_LONG_PRESS, CMD_SET_CHARGE_MODE, CMD_SET_IRQ_ENABLE, - CMD_SET_ESD_ENABLE, CMD_SET_DEBUG_LOG, CMD_SET_SCAN_MODE, - CMD_GET_SCAN_MODE, CMD_SET_CONTINUE_MODE, CMD_GET_CHANNEL_NUM, - CMD_GET_TX_FREQ, CMD_RESET, CMD_SET_SENSE_ENABLE, CMD_GET_CONFIG, - CMD_GET_FW_STATUS, CMD_SET_HIGHSENSE_MODE, CMD_SET_GRIP_DATA, - CMD_SET_PALM_MODE, CMD_SET_NOISE_MODE, CMD_SET_WATER_MODE, NULL }; + CMD_SET_LONG_PRESS, CMD_SET_GESTURE_PARAM, CMD_SET_CHARGE_MODE, + CMD_SET_IRQ_ENABLE, CMD_SET_ESD_ENABLE, CMD_SET_DEBUG_LOG, + CMD_SET_SCAN_MODE, CMD_GET_SCAN_MODE, CMD_SET_CONTINUE_MODE, + CMD_GET_CHANNEL_NUM, CMD_GET_TX_FREQ, CMD_RESET, CMD_SET_SENSE_MODE, + CMD_GET_CONFIG, CMD_GET_FW_STATUS, CMD_SET_HIGHSENSE_MODE, + CMD_SET_GRIP_DATA, CMD_SET_PALM_MODE, CMD_SET_NOISE_MODE, + CMD_SET_WATER_MODE, CMD_SET_HEATMAP, NULL }; /* test limits keyword */ #define CSV_TP_SPECIAL_RAW_MIN "special_raw_min" @@ -68,7 +71,7 @@ char *cmd_list[] = { CMD_FW_UPDATE, CMD_AUTO_TEST, CMD_OPEN_TEST, #define NOISE_FUNC 1 #define WATER_FUNC 2 -#define SHORT_SIZE 100 +#define SHORT_SIZE 150 #define LARGE_SIZE 4096 #define MAX_FRAME_CNT 50 #define HUGE_SIZE MAX_FRAME_CNT * 20 * 1024 @@ -97,6 +100,40 @@ static uint32_t index; #define MAX_SEN_NUM 35 #define MAX_SHORT_NUM 15 +typedef union __attribute__((packed)) { + struct { + u16 length; + u16 st_min_x; + u16 st_max_x; + u16 st_min_y; + u16 st_max_y; + u16 st_min_count; + u16 st_max_count; + u16 st_motion_tolerance; + u16 st_max_size; + u16 lp_min_x; + u16 lp_max_x; + u16 lp_min_y; + u16 lp_max_y; + u16 lp_min_count; + u16 lp_max_size; + u16 lp_marginal_min_x; + u16 lp_marginal_max_x; + u16 lp_marginal_min_y; + u16 lp_marginal_max_y; + u8 lp_monitor_chan_min_tx; + u8 lp_monitor_chan_max_tx; + u8 lp_monitor_chan_min_rx; + u8 lp_monitor_chan_max_rx; + u16 lp_min_node_count; + u16 lp_motion_tolerance_inner; + u16 lp_motion_tolerance_outer; + u16 checksum; + }; + u8 buf[50]; +} gesture_param_t; +static gesture_param_t gesture_param; + typedef struct __attribute__((packed)) { u8 result; u8 drv_drv_num; @@ -2097,27 +2134,36 @@ exit: return ret; } -static void goodix_set_sense_enable(bool on) +static void goodix_set_sense_mode(u8 val) { - static bool flag = true; + struct goodix_ts_cmd temp_cmd; - if (on && !flag) { - flag = true; + temp_cmd.len = 4; + temp_cmd.cmd = 0xA7; + + if (val == 1) { + /* normal mode */ + index = sprintf(rbuf, "switch to coordinate mode\n"); cd->hw_ops->resume(cd); - cd->hw_ops->irq_enable(cd, true); + cd->hw_ops->send_cmd(cd, &temp_cmd); goodix_ts_blocking_notify(NOTIFY_ESD_ON, NULL); - ts_info("set sense ON"); - return; - } else if (!on && flag) { - flag = false; + cd->hw_ops->irq_enable(cd, true); + atomic_set(&cd->suspended, 0); + } else if (val == 2) { + /* gesture mode */ + index = sprintf(rbuf, "switch to gesture mode\n"); + goodix_ts_blocking_notify(NOTIFY_ESD_OFF, NULL); + cd->hw_ops->resume(cd); + cd->hw_ops->gesture(cd, 0); + cd->hw_ops->irq_enable(cd, true); + atomic_set(&cd->suspended, 1); + } else { + /* sleep mode */ + index = sprintf(rbuf, "switch to sleep mode\n"); goodix_ts_blocking_notify(NOTIFY_ESD_OFF, NULL); cd->hw_ops->irq_enable(cd, false); cd->hw_ops->suspend(cd); - ts_info("set sense OFF"); - return; } - - ts_info("have already %s", on ? "ON" : "OFF"); } static void goodix_set_scan_mode(u8 val) @@ -2125,6 +2171,10 @@ static void goodix_set_scan_mode(u8 val) struct goodix_ts_cmd temp_cmd; if (val == 0) { + temp_cmd.len = 5; + temp_cmd.cmd = 0x9F; + temp_cmd.data[0] = 0; + cd->hw_ops->send_cmd(cd, &temp_cmd); temp_cmd.len = 6; temp_cmd.cmd = 0x25; temp_cmd.data[0] = 0; @@ -2211,8 +2261,9 @@ static void goodix_set_continue_mode(u8 val) static void goodix_read_config(void) { int ret; - int i; u8 cfg_buf[2500]; + u32 cfg_id; + u8 cfg_ver; ret = cd->hw_ops->read_config(cd, cfg_buf, sizeof(cfg_buf)); if (ret < 0) { @@ -2220,11 +2271,10 @@ static void goodix_read_config(void) return; } - for (i = 0; i < 200; i++) { // only print 200 bytes - index += sprintf(&rbuf[index], "%02x,", cfg_buf[i]); - if ((i + 1) % 20 == 0) - index += sprintf(&rbuf[index], "\n"); - } + cfg_id = le32_to_cpup((__le32 *)&cfg_buf[30]); + cfg_ver = cfg_buf[34]; + index = sprintf( + rbuf, "config_id:0x%X config_ver:0x%02X\n", cfg_id, cfg_ver); } static void goodix_get_fw_status(void) @@ -2348,6 +2398,173 @@ static void goodix_set_custom_mode(u8 type, u8 val) cd->hw_ops->send_cmd(cd, &temp_cmd); } +static int obtain_param(char **buf) +{ + char *token; + int val; + + token = strsep(buf, ","); + if (!token) { + if (kstrtos32(*buf, 10, &val)) + return -EINVAL; + } else { + if (kstrtos32(token, 10, &val)) + return -EINVAL; + } + + return val; +} + +static int goodix_parse_gesture_param(char **buf) +{ + gesture_param.length = 50; + gesture_param.st_min_x = obtain_param(buf); + gesture_param.st_max_x = obtain_param(buf); + gesture_param.st_min_y = obtain_param(buf); + gesture_param.st_max_y = obtain_param(buf); + gesture_param.st_min_count = obtain_param(buf); + gesture_param.st_max_count = obtain_param(buf); + gesture_param.st_motion_tolerance = obtain_param(buf); + gesture_param.st_max_size = obtain_param(buf); + gesture_param.lp_min_x = obtain_param(buf); + gesture_param.lp_max_x = obtain_param(buf); + gesture_param.lp_min_y = obtain_param(buf); + gesture_param.lp_max_y = obtain_param(buf); + gesture_param.lp_min_count = obtain_param(buf); + gesture_param.lp_max_size = obtain_param(buf); + gesture_param.lp_marginal_min_x = obtain_param(buf); + gesture_param.lp_marginal_max_x = obtain_param(buf); + gesture_param.lp_marginal_min_y = obtain_param(buf); + gesture_param.lp_marginal_max_y = obtain_param(buf); + gesture_param.lp_monitor_chan_min_tx = obtain_param(buf); + gesture_param.lp_monitor_chan_max_tx = obtain_param(buf); + gesture_param.lp_monitor_chan_min_rx = obtain_param(buf); + gesture_param.lp_monitor_chan_max_rx = obtain_param(buf); + gesture_param.lp_min_node_count = obtain_param(buf); + gesture_param.lp_motion_tolerance_inner = obtain_param(buf); + gesture_param.lp_motion_tolerance_outer = obtain_param(buf); + goodix_append_checksum(gesture_param.buf, 48, CHECKSUM_MODE_U8_LE); + + ts_info("st_min_x: %d", gesture_param.st_min_x); + ts_info("st_max_x: %d", gesture_param.st_max_x); + ts_info("st_min_y: %d", gesture_param.st_min_y); + ts_info("st_max_y: %d", gesture_param.st_max_y); + ts_info("st_min_count: %d", gesture_param.st_min_count); + ts_info("st_max_count: %d", gesture_param.st_max_count); + ts_info("st_motion_tolerance: %d", + gesture_param.st_motion_tolerance); + ts_info("st_max_size: %d", gesture_param.st_max_size); + ts_info("lp_min_x: %d", gesture_param.lp_min_x); + ts_info("lp_max_x: %d", gesture_param.lp_max_x); + ts_info("lp_min_y: %d", gesture_param.lp_min_y); + ts_info("lp_max_y: %d", gesture_param.lp_max_y); + ts_info("lp_min_count: %d", gesture_param.lp_min_count); + ts_info("lp_max_size: %d", gesture_param.lp_max_size); + ts_info("lp_marginal_min_x: %d", + gesture_param.lp_marginal_min_x); + ts_info("lp_marginal_max_x: %d", + gesture_param.lp_marginal_max_x); + ts_info("lp_marginal_min_y: %d", + gesture_param.lp_marginal_min_y); + ts_info("lp_marginal_max_y: %d", + gesture_param.lp_marginal_max_y); + ts_info("lp_monitor_chan_min_tx: %d", + gesture_param.lp_monitor_chan_min_tx); + ts_info("lp_monitor_chan_max_tx: %d", + gesture_param.lp_monitor_chan_max_tx); + ts_info("lp_monitor_chan_min_rx: %d", + gesture_param.lp_monitor_chan_min_rx); + ts_info("lp_monitor_chan_max_rx: %d", + gesture_param.lp_monitor_chan_max_rx); + ts_info("lp_min_node_count: %d", + gesture_param.lp_min_node_count); + ts_info("lp_motion_tolerance_inner: %d", + gesture_param.lp_motion_tolerance_inner); + ts_info("lp_motion_tolerance_outer: %d", + gesture_param.lp_motion_tolerance_outer); + + return 0; +} + +static void goodix_set_gesture_param(void) +{ + struct goodix_ts_cmd temp_cmd; + u32 cmd_reg = cd->ic_info.misc.cmd_addr; + int retry; + u8 status; + + ts_info("param:%*ph", 50, gesture_param.buf); + + temp_cmd.len = 4; + temp_cmd.cmd = 0xC8; + cd->hw_ops->send_cmd(cd, &temp_cmd); + retry = 20; + while (retry--) { + usleep_range(5000, 5100); + cd->hw_ops->read(cd, cmd_reg, &status, 1); + if (status == 0x80) + break; + } + if (retry < 0) { + ts_err("failed to start write gesture param, status[%x]", + status); + goto exit; + } + cd->hw_ops->write( + cd, 0x13D80, gesture_param.buf, sizeof(gesture_param)); + + temp_cmd.len = 4; + temp_cmd.cmd = 0x05; + cd->hw_ops->send_cmd(cd, &temp_cmd); + retry = 20; + while (retry--) { + usleep_range(5000, 5100); + cd->hw_ops->read(cd, cmd_reg, &status, 1); + if (status == 0x80 || status == 0x03) + break; + } + if (retry < 0) { + ts_err("failed to update gesture param, status[%x]", status); + goto exit; + } + + if (status == 0x80) { + ts_info("update gesture param OK"); + index = sprintf(rbuf, "update gesture param OK\n"); + } else { + ts_info("update gesture param FAIL"); + index = sprintf(rbuf, "update gesture param FAIL\n"); + } + +exit: + temp_cmd.len = 4; + temp_cmd.cmd = 0x06; + cd->hw_ops->send_cmd(cd, &temp_cmd); +} + +static void goodix_set_heatmap(int val) +{ + struct goodix_ts_cmd temp_cmd; + + cd->hw_ops->irq_enable(cd, false); + if (val == 0) { + index = sprintf(rbuf, "disable heatmap\n"); + kfree(cd->heatmap_buffer); + cd->heatmap_buffer = NULL; + temp_cmd.len = 5; + temp_cmd.cmd = 0x90; + temp_cmd.data[0] = 0; + } else { + index = sprintf(rbuf, "enable heatmap\n"); + cd->heatmap_buffer = kcalloc(1000, sizeof(s16), GFP_KERNEL); + temp_cmd.len = 5; + temp_cmd.cmd = 0x90; + temp_cmd.data[0] = 2; + } + cd->hw_ops->send_cmd(cd, &temp_cmd); + cd->hw_ops->irq_enable(cd, true); +} + static ssize_t driver_test_write( struct file *file, const char __user *buf, size_t count, loff_t *pos) { @@ -2528,12 +2745,12 @@ static ssize_t driver_test_write( cd->gesture_type &= ~GESTURE_FOD_PRESS; index = sprintf( rbuf, "%s: disable OK\n", CMD_SET_LONG_PRESS); - ts_info("disable single tap"); + ts_info("disable long press"); } else { cd->gesture_type |= GESTURE_FOD_PRESS; index = sprintf( rbuf, "%s: enable OK\n", CMD_SET_LONG_PRESS); - ts_info("enable single tap"); + ts_info("enable long press"); } goto exit; } @@ -2653,27 +2870,25 @@ static ssize_t driver_test_write( goto exit; } - if (!strncmp(p, CMD_SET_SENSE_ENABLE, strlen(CMD_SET_SENSE_ENABLE))) { + if (!strncmp(p, CMD_SET_SENSE_MODE, strlen(CMD_SET_SENSE_MODE))) { rbuf = kzalloc(SHORT_SIZE, GFP_KERNEL); token = strsep(&p, ","); if (!token || !p) { index = sprintf(rbuf, "%s: invalid cmd param\n", - CMD_SET_SENSE_ENABLE); + CMD_SET_SENSE_MODE); goto exit; } if (kstrtos32(p, 10, &cmd_val)) { index = sprintf(rbuf, "%s: invalid cmd param\n", - CMD_SET_SENSE_ENABLE); + CMD_SET_SENSE_MODE); goto exit; } - if (cmd_val == 0) { - goodix_set_sense_enable(false); - index = sprintf( - rbuf, "%s: OFF\n", CMD_SET_SENSE_ENABLE); - } else { - goodix_set_sense_enable(true); - index = sprintf(rbuf, "%s: ON\n", CMD_SET_SENSE_ENABLE); + if (cmd_val > 2 || cmd_val < 0) { + index = sprintf(rbuf, "%s: invalid cmd param\n", + CMD_SET_SENSE_MODE); + goto exit; } + goodix_set_sense_mode(cmd_val); goto exit; } @@ -2952,6 +3167,36 @@ static ssize_t driver_test_write( goto exit; } + if (!strncmp(p, CMD_SET_GESTURE_PARAM, strlen(CMD_SET_GESTURE_PARAM))) { + rbuf = kzalloc(SHORT_SIZE, GFP_KERNEL); + token = strsep(&p, ","); + if (!token || !p) { + index = sprintf(rbuf, "%s: invalid cmd param\n", + CMD_SET_GESTURE_PARAM); + goto exit; + } + goodix_parse_gesture_param(&p); + goodix_set_gesture_param(); + goto exit; + } + + if (!strncmp(p, CMD_SET_HEATMAP, strlen(CMD_SET_HEATMAP))) { + rbuf = kzalloc(SHORT_SIZE, GFP_KERNEL); + token = strsep(&p, ","); + if (!token || !p) { + index = sprintf(rbuf, "%s: invalid cmd param\n", + CMD_SET_HEATMAP); + goto exit; + } + if (kstrtos32(p, 10, &cmd_val)) { + index = sprintf(rbuf, "%s: invalid cmd param\n", + CMD_SET_HEATMAP); + goto exit; + } + goodix_set_heatmap(cmd_val); + goto exit; + } + rbuf = kzalloc(SHORT_SIZE, GFP_KERNEL); index = sprintf(rbuf, "not support cmd %s\n", p); ts_err("not support cmd[%s]", p); |