diff options
author | Wendly Li <wendlyli@google.com> | 2022-05-16 12:41:11 +0000 |
---|---|---|
committer | Wendly Li <wendlyli@google.com> | 2022-05-24 13:08:48 +0000 |
commit | aac08b5bc1260df075c1e5e177b5ea41d406ea6b (patch) | |
tree | d5109901e432d66596e195ee51a90eb337fe1236 | |
parent | 2066943eca0910f544389120ff8c4e503f2ccbc6 (diff) | |
download | goodix_touch-aac08b5bc1260df075c1e5e177b5ea41d406ea6b.tar.gz |
goodix: Support reading mutual and self sensing data
Bug: 214118837
Test: Check driver can read mutual and self sensing data
Change-Id: Id4afa4c902dc0bc3310467387fc6f7f4f2af4498
Signed-off-by: Wendly Li <wendlyli@google.com>
-rw-r--r-- | goodix_brl_hw.c | 212 | ||||
-rw-r--r-- | goodix_brl_spi.c | 65 | ||||
-rw-r--r-- | goodix_ts_core.c | 25 | ||||
-rw-r--r-- | goodix_ts_core.h | 83 | ||||
-rw-r--r-- | goodix_ts_proc.c | 13 | ||||
-rw-r--r-- | goodix_ts_utils.c | 38 |
6 files changed, 311 insertions, 125 deletions
diff --git a/goodix_brl_hw.c b/goodix_brl_hw.c index ac61fd5..a91db4e 100644 --- a/goodix_brl_hw.c +++ b/goodix_brl_hw.c @@ -358,6 +358,14 @@ static int brl_read(struct goodix_ts_core *cd, unsigned int addr, return bus->read(bus->dev, addr, data, len); } +static int brl_read_fast(struct goodix_ts_core *cd, unsigned int addr, + struct goodix_rx_package *package, unsigned int len) +{ + struct goodix_bus_interface *bus = cd->bus; + + return bus->read_fast(bus->dev, addr, package, len); +} + static int brl_write(struct goodix_ts_core *cd, unsigned int addr, unsigned char *data, unsigned int len) { @@ -881,6 +889,7 @@ static void print_ic_info(struct goodix_ic_info *ic_info) ts_info("stylus_rawdata_addr: 0x%04X, %d", misc->stylus_rawdata_addr, misc->stylus_rawdata_len); ts_info("esd_addr: 0x%04X", misc->esd_addr); + ts_info("frame_data_addr: 0x%04X", misc->frame_data_addr); } static int brl_get_ic_info( @@ -998,9 +1007,10 @@ static int point_struct_len; static void goodix_parse_finger( struct goodix_touch_data *touch_data, u8 *buf, int touch_num) { - unsigned int id = 0, x = 0, y = 0, w = 0; + unsigned int id = 0; u8 *coor_data; int i; + struct goodix_ts_coords *coord; coor_data = &buf[IRQ_EVENT_HEAD_LEN]; for (i = 0; i < touch_num; i++) { @@ -1010,23 +1020,18 @@ static void goodix_parse_finger( touch_data->touch_num = 0; return; } + coord = &touch_data->coords[id]; - touch_data->coords[id].status = TS_TOUCH; - x = le16_to_cpup((__le16 *)(coor_data + 2)); - y = le16_to_cpup((__le16 *)(coor_data + 4)); - w = le16_to_cpup((__le16 *)(coor_data + 6)); - touch_data->coords[id].x = x; - touch_data->coords[id].y = y; - touch_data->coords[id].w = w; + coord->status = TS_TOUCH; + coord->x = le16_to_cpup((__le16 *)(coor_data + 2)); + coord->y = le16_to_cpup((__le16 *)(coor_data + 4)); + coord->w = le16_to_cpup((__le16 *)(coor_data + 6)); if (point_struct_len > 8) { - touch_data->coords[id].p = coor_data[8]; - touch_data->coords[id].major = - le16_to_cpup((__le16 *)(coor_data + 9)); - touch_data->coords[id].minor = - le16_to_cpup((__le16 *)(coor_data + 11)); - touch_data->coords[id].angle = - (signed char)coor_data[13]; + coord->p = coor_data[8]; + coord->major = le16_to_cpup((__le16 *)(coor_data + 9)); + coord->minor = le16_to_cpup((__le16 *)(coor_data + 11)); + coord->angle = (signed char)coor_data[13]; } coor_data += point_struct_len; @@ -1071,16 +1076,35 @@ static void goodix_parse_pen( } } +static int goodix_update_heatmap(struct goodix_ts_core *cd, uint8_t *event_data) +{ + struct goodix_ic_info_misc *misc = &cd->ic_info.misc; + int tx = cd->ic_info.parm.drv_num; + int rx = cd->ic_info.parm.sen_num; + int mutual_len = sizeof(struct goodix_mutual_data) + tx * rx * 2; + struct goodix_mutual_data *mutual_data; + struct goodix_self_sensing_data *self_sensing_data; + uint8_t *mutual_head = event_data + misc->frame_data_addr - + misc->touch_data_addr + + misc->frame_data_head_len + misc->fw_attr_len + + misc->fw_log_len; + + mutual_data = (struct goodix_mutual_data *)mutual_head; + self_sensing_data = + (struct goodix_self_sensing_data *)(mutual_head + mutual_len); + goodix_rotate_abcd2cbad(tx, rx, mutual_data->data, cd->mutual_data); + memcpy(cd->self_sensing_data, self_sensing_data->data, (tx + rx) * 2); + + return 0; +} + static int goodix_touch_handler(struct goodix_ts_core *cd, - struct goodix_ts_event *ts_event, u8 *pre_buf, u32 pre_buf_len) + struct goodix_ts_event *ts_event, + struct goodix_ts_touch_event_data *event_data) { - struct goodix_ts_hw_ops *hw_ops = cd->hw_ops; struct goodix_ic_info_misc *misc = &cd->ic_info.misc; struct goodix_touch_data *touch_data = &ts_event->touch_data; struct goodix_pen_data *pen_data = &ts_event->pen_data; - static u8 buffer[IRQ_EVENT_HEAD_LEN + - BYTES_PER_POINT * GOODIX_MAX_TOUCH + 2]; - u8 touch_num = 0; int ret = 0; u8 point_type = 0; static u8 pre_finger_num; @@ -1088,85 +1112,74 @@ static int goodix_touch_handler(struct goodix_ts_core *cd, /* clean event buffer */ memset(ts_event, 0, sizeof(*ts_event)); - /* copy pre-data to buffer */ - memcpy(buffer, pre_buf, pre_buf_len); - touch_num = buffer[2] & 0x0F; - - if (touch_num > GOODIX_MAX_TOUCH) { - ts_debug("invalid touch num %d", touch_num); + if (event_data->touches > GOODIX_MAX_TOUCH) { + ts_debug("invalid touch num %d", event_data->touches); return -EINVAL; } - if (unlikely(touch_num > 2)) { - ret = hw_ops->read(cd, misc->touch_data_addr + pre_buf_len, - &buffer[pre_buf_len], - (touch_num - 2) * BYTES_PER_POINT); - if (ret) { - ts_debug("failed get touch data"); - return ret; - } - } - - /* read done */ - hw_ops->after_event_handler(cd); - - if (touch_num > 0) { - point_type = buffer[IRQ_EVENT_HEAD_LEN] & 0x0F; + if (event_data->touches > 0) { + point_type = event_data->data[0] & 0x0F; if (point_type == POINT_TYPE_STYLUS || point_type == POINT_TYPE_STYLUS_HOVER) { - ret = checksum_cmp(&buffer[IRQ_EVENT_HEAD_LEN], + ret = checksum_cmp(event_data->data, BYTES_PER_POINT * 2 + 2, CHECKSUM_MODE_U8_LE); if (ret) { ts_debug("touch data checksum error"); ts_debug("data:%*ph", BYTES_PER_POINT * 2 + 2, - &buffer[IRQ_EVENT_HEAD_LEN]); + event_data->data); return -EINVAL; } } else { point_struct_len = misc->point_struct_len; - ret = checksum_cmp(&buffer[IRQ_EVENT_HEAD_LEN], - touch_num * point_struct_len + 2, + ret = checksum_cmp(event_data->data, + event_data->touches * point_struct_len + 2, CHECKSUM_MODE_U8_LE); if (ret) { ts_debug("touch data checksum error"); ts_debug("data:%*ph", - touch_num * point_struct_len + 2, - &buffer[IRQ_EVENT_HEAD_LEN]); + event_data->touches * point_struct_len + + 2, + event_data->data); return -EINVAL; } } } - ts_event->fp_flag = pre_buf[0] & GOODIX_FP_EVENT; + goodix_update_heatmap(cd, (u8 *)event_data); - if (touch_num > 0 && (point_type == POINT_TYPE_STYLUS || - point_type == POINT_TYPE_STYLUS_HOVER)) { + ts_event->fp_flag = event_data->fp_flag; + + if (event_data->touches > 0 && + (point_type == POINT_TYPE_STYLUS || + point_type == POINT_TYPE_STYLUS_HOVER)) { /* stylus info */ if (pre_finger_num) { ts_event->event_type = EVENT_TOUCH; - goodix_parse_finger(touch_data, buffer, 0); + goodix_parse_finger(touch_data, (u8 *)event_data, 0); pre_finger_num = 0; } else { pre_pen_num = 1; ts_event->event_type = EVENT_PEN; - goodix_parse_pen(pen_data, buffer, touch_num); + goodix_parse_pen(pen_data, (u8 *)event_data, + event_data->touches); } } else { /* finger info */ if (pre_pen_num) { ts_event->event_type = EVENT_PEN; - goodix_parse_pen(pen_data, buffer, 0); + goodix_parse_pen(pen_data, (u8 *)event_data, 0); pre_pen_num = 0; } else { ts_event->event_type = EVENT_TOUCH; - goodix_parse_finger(touch_data, buffer, touch_num); - pre_finger_num = touch_num; + goodix_parse_finger(touch_data, (u8 *)event_data, + event_data->touches); + pre_finger_num = event_data->touches; } } /* process custom info */ - if (buffer[3] & 0x01) + if (event_data->custom_coor_info_flag) ts_debug("TODO add custom info process function"); return 0; @@ -1177,68 +1190,57 @@ 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[100]; - u8 event_status; - u32 mutual_addr; + struct goodix_ts_event_data *event_data; 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); + ret = hw_ops->read_fast(cd, misc->touch_data_addr, + cd->touch_frame_package, cd->touch_frame_size); if (ret) { ts_debug("failed get event head data"); return ret; } - if (pre_buf[0] == 0x00) { + event_data = + (struct goodix_ts_event_data *)cd->touch_frame_package->data; + if (event_data->type == 0x00) { ts_debug("invalid touch head"); return -EINVAL; } - if (checksum_cmp(pre_buf, IRQ_EVENT_HEAD_LEN, CHECKSUM_MODE_U8_LE)) { + if (checksum_cmp((u8 *)event_data, IRQ_EVENT_HEAD_LEN, + CHECKSUM_MODE_U8_LE)) { ts_debug("touch head checksum err[%*ph]", IRQ_EVENT_HEAD_LEN, - pre_buf); + event_data); return -EINVAL; } ts_event->event_type = EVENT_INVALID; - event_status = pre_buf[0]; - if (event_status & GOODIX_TOUCH_EVENT) - return goodix_touch_handler( - cd, ts_event, pre_buf, pre_read_len); + if (event_data->type & (GOODIX_TOUCH_EVENT >> 4)) + return goodix_touch_handler(cd, ts_event, + (struct goodix_ts_touch_event_data *)event_data); - if (event_status & GOODIX_REQUEST_EVENT) { + if (event_data->type & (GOODIX_REQUEST_EVENT >> 4)) { + struct goodix_ts_request_event_data *request = + (struct goodix_ts_request_event_data *)event_data; ts_event->event_type = EVENT_REQUEST; - if (pre_buf[2] == BRL_REQUEST_CODE_CONFIG) + if (request->request_type == BRL_REQUEST_CODE_CONFIG) ts_event->request_code = REQUEST_TYPE_CONFIG; - else if (pre_buf[2] == BRL_REQUEST_CODE_RESET) + else if (request->request_type == BRL_REQUEST_CODE_RESET) ts_event->request_code = REQUEST_TYPE_RESET; else - ts_debug("unsupported request code 0x%x", pre_buf[2]); + ts_debug("unsupported request code 0x%x", + request->request_type); } - if (event_status & GOODIX_GESTURE_EVENT) { + if (event_data->type & (GOODIX_GESTURE_EVENT >> 4)) { + struct goodix_ts_gesture_event_data *gesture = + (struct goodix_ts_gesture_event_data *)event_data; ts_event->event_type = EVENT_GESTURE; - ts_event->gesture_type = pre_buf[4]; - memcpy(ts_event->gesture_data, &pre_buf[8], + ts_event->gesture_type = gesture->gesture_type; + memcpy(ts_event->gesture_data, gesture->data, GOODIX_GESTURE_DATA_LEN); } - /* read done */ - hw_ops->after_event_handler(cd); return 0; } @@ -1343,7 +1345,7 @@ static int brld_get_cap_data( ts_err("brld get rawdata failed"); goto exit; } - goodix_rotate_abcd2cbad(tx, rx, &info->buff[info->used_size]); + goodix_rotate_abcd2cbad(tx, rx, &info->buff[info->used_size], NULL); info->used_size += size; temp_cmd.cmd = 0x90; @@ -1360,7 +1362,7 @@ static int brld_get_cap_data( ts_err("brld get diffdata failed"); goto exit; } - goodix_rotate_abcd2cbad(tx, rx, &info->buff[info->used_size]); + goodix_rotate_abcd2cbad(tx, rx, &info->buff[info->used_size], NULL); info->used_size += size; exit: @@ -1442,7 +1444,7 @@ static int brl_get_capacitance_data( ts_err("obtian raw_data failed, exit!"); goto exit; } - goodix_rotate_abcd2cbad(tx, rx, &info->buff[info->used_size]); + goodix_rotate_abcd2cbad(tx, rx, &info->buff[info->used_size], NULL); info->used_size += size; ret = brl_read(cd, diff_addr, (u8 *)&info->buff[info->used_size], @@ -1451,7 +1453,7 @@ static int brl_get_capacitance_data( ts_err("obtian diff_data failed, exit!"); goto exit; } - goodix_rotate_abcd2cbad(tx, rx, &info->buff[info->used_size]); + goodix_rotate_abcd2cbad(tx, rx, &info->buff[info->used_size], NULL); info->used_size += size; exit: @@ -1496,6 +1498,24 @@ int brl_set_continuously_report_enabled(struct goodix_ts_core *cd, bool enabled) return 0; } +#define GOODIX_CMD_SET_HEATMAP_ENABLED 0x90 +int brl_set_heatmap_enabled(struct goodix_ts_core *cd, bool enabled) +{ + struct goodix_ts_cmd cmd; + + cd->hw_ops->irq_enable(cd, false); + + cmd.cmd = GOODIX_CMD_SET_HEATMAP_ENABLED; + cmd.len = 5; + cmd.data[0] = enabled ? 2 : 0; + if (cd->hw_ops->send_cmd(cd, &cmd)) + ts_err("failed to set heatmap enabled: %s", + enabled ? "enabled" : "disabled"); + + cd->hw_ops->irq_enable(cd, true); + return 0; +} + static struct goodix_ts_hw_ops brl_hw_ops = { .power_on = brl_power_on, .resume = brl_resume, @@ -1504,6 +1524,7 @@ static struct goodix_ts_hw_ops brl_hw_ops = { .reset = brl_reset, .irq_enable = brl_irq_enable, .read = brl_read, + .read_fast = brl_read_fast, .write = brl_write, .send_cmd = brl_send_cmd, .send_config = brl_send_config, @@ -1517,6 +1538,7 @@ static struct goodix_ts_hw_ops brl_hw_ops = { .ping = brl_dev_confirm, .set_scan_mode = brl_set_scan_mode, .set_continuously_report_enabled = brl_set_continuously_report_enabled, + .set_heatmap_enabled = brl_set_heatmap_enabled, }; struct goodix_ts_hw_ops *goodix_get_hw_ops(void) diff --git a/goodix_brl_spi.c b/goodix_brl_spi.c index 09fc9aa..652383c 100644 --- a/goodix_brl_spi.c +++ b/goodix_brl_spi.c @@ -172,9 +172,65 @@ static int goodix_spi_read(struct device *dev, unsigned int addr, memcpy(data, &rx_buf[SPI_READ_PREFIX_LEN - 1], len); err_spi_transfer: + if (tx_buf != goodix_spi_bus.tx_buf) + kfree(tx_buf); +err_alloc_rx_buf: if (rx_buf != goodix_spi_bus.rx_buf) kfree(rx_buf); -err_alloc_rx_buf: + return ret; +} + +static int goodix_spi_read_fast(struct device *dev, unsigned int addr, + struct goodix_rx_package *package, unsigned int len) +{ + struct spi_device *spi = to_spi_device(dev); + u8 *tx_buf = NULL; + struct spi_transfer xfers; + struct spi_message spi_msg; + int ret = 0; + int buf_len = SPI_READ_PREFIX_LEN - 1 + len; + + if (buf_len >= 64) { + buf_len = ALIGN(buf_len, 4); + } + + if (buf_len <= SPI_PREALLOC_TX_BUF_SIZE) { + tx_buf = goodix_spi_bus.tx_buf; + } else { + tx_buf = kzalloc(buf_len, GFP_KERNEL); + if (!tx_buf) { + ts_err("alloc tx_buf failed, size:%d", buf_len); + return -ENOMEM; + } + } + + spi_message_init(&spi_msg); + memset(&xfers, 0, sizeof(xfers)); + + /*spi_read tx_buf format: 0xF1 + addr(4bytes) + data*/ + tx_buf[0] = SPI_READ_FLAG; + tx_buf[1] = (addr >> 24) & 0xFF; + tx_buf[2] = (addr >> 16) & 0xFF; + tx_buf[3] = (addr >> 8) & 0xFF; + tx_buf[4] = addr & 0xFF; + tx_buf[5] = 0xFF; + tx_buf[6] = 0xFF; + tx_buf[7] = 0xFF; + + xfers.tx_buf = tx_buf; + xfers.rx_buf = package->header; + xfers.len = buf_len; + xfers.cs_change = 0; + xfers.bits_per_word = buf_len >= 64 ? 32 : 8; + spi_message_add_tail(&xfers, &spi_msg); + + ret = spi_sync(spi, &spi_msg); + if (ret < 0) { + ts_err("spi transfer error:%d", ret); + goto err_spi_transfer; + } + +err_spi_transfer: if (tx_buf != goodix_spi_bus.tx_buf) kfree(tx_buf); return ret; @@ -250,6 +306,7 @@ static int goodix_spi_probe(struct spi_device *spi) /* init spi_device */ spi->mode = SPI_MODE_0; spi->bits_per_word = 8; + spi->rt = true; ret = spi_setup(spi); if (ret) { @@ -264,10 +321,12 @@ static int goodix_spi_probe(struct spi_device *spi) goodix_spi_bus.bus_type = GOODIX_BUS_TYPE_SPI; goodix_spi_bus.dev = &spi->dev; - if (goodix_spi_bus.ic_type == IC_TYPE_BERLIN_A) + if (goodix_spi_bus.ic_type == IC_TYPE_BERLIN_A) { goodix_spi_bus.read = goodix_spi_read_bra; - else + } else { goodix_spi_bus.read = goodix_spi_read; + goodix_spi_bus.read_fast = goodix_spi_read_fast; + } goodix_spi_bus.write = goodix_spi_write; goodix_spi_bus.rx_buf = kzalloc(SPI_PREALLOC_RX_BUF_SIZE, GFP_KERNEL); diff --git a/goodix_ts_core.c b/goodix_ts_core.c index 24a59da..5242201 100644 --- a/goodix_ts_core.c +++ b/goodix_ts_core.c @@ -1350,6 +1350,9 @@ static irqreturn_t goodix_ts_threadirq_func(int irq, void *data) } if (ts_event->event_type == EVENT_REQUEST) goodix_ts_request_handle(core_data, ts_event); + + /* read done */ + hw_ops->after_event_handler(core_data); } #if IS_ENABLED(CONFIG_TOUCHSCREEN_PM) @@ -1868,6 +1871,7 @@ static int goodix_ts_suspend(struct goodix_ts_core *core_data) atomic_set(&core_data->suspended, 1); /* disable irq */ hw_ops->irq_enable(core_data, false); + hw_ops->set_heatmap_enabled(core_data, false); /* * notify suspend event, inform the esd protector @@ -1997,6 +2001,8 @@ static int goodix_ts_resume(struct goodix_ts_core *core_data) } mutex_unlock(&goodix_modules.mutex); + hw_ops->set_heatmap_enabled(core_data, true); + out: /* enable irq */ hw_ops->irq_enable(core_data, true); @@ -2092,6 +2098,17 @@ static int goodix_generic_noti_callback( int goodix_ts_stage2_init(struct goodix_ts_core *cd) { int ret; + int tx = cd->ic_info.parm.drv_num; + int rx = cd->ic_info.parm.sen_num; + size_t mutual_size = tx * rx * sizeof(s16); + size_t self_sensing_size = (tx + rx) * sizeof(s16); + struct goodix_ic_info_misc *misc = &cd->ic_info.misc; + size_t touch_frame_size = + misc->frame_data_addr - misc->touch_data_addr + + misc->frame_data_head_len + misc->fw_attr_len + + misc->fw_log_len + sizeof(struct goodix_mutual_data) + + mutual_size + sizeof(struct goodix_self_sensing_data) + + self_sensing_size; /* alloc/config/register input device */ ret = goodix_ts_input_dev_config(cd); @@ -2188,6 +2205,14 @@ int goodix_ts_stage2_init(struct goodix_ts_core *cd) goto err_init_inspect; } + cd->touch_frame_size = touch_frame_size; + cd->touch_frame_package = + devm_kzalloc(&cd->pdev->dev, touch_frame_size + 8, GFP_KERNEL); + cd->mutual_data = devm_kzalloc(&cd->pdev->dev, mutual_size, GFP_KERNEL); + cd->self_sensing_data = + devm_kzalloc(&cd->pdev->dev, self_sensing_size, GFP_KERNEL); + cd->hw_ops->set_heatmap_enabled(cd, true); + /* request irq line */ ret = goodix_ts_irq_setup(cd); if (ret < 0) { diff --git a/goodix_ts_core.h b/goodix_ts_core.h index d5d1739..a7dddff 100644 --- a/goodix_ts_core.h +++ b/goodix_ts_core.h @@ -428,6 +428,77 @@ struct goodix_ts_event { struct goodix_pen_data pen_data; }; +struct goodix_ts_event_data { + u8 fp_flag : 4; + u8 type : 4; + u8 int_count; +}; + +struct goodix_ts_request_event_data { + u8 fp_flag : 4; + u8 type : 4; + u8 int_count; + u8 request_type; + u8 reserved1; + u8 reserved2; + u8 reserved3; + u16 checksum; +}; + +struct goodix_ts_touch_event_data { + u8 fp_flag : 4; + u8 type : 4; + u8 int_count; + u8 touches : 4; + u8 large_touch : 1; + u8 hover_approach_flag : 1; + u8 edge_flag : 1; + u8 reset_int : 1; + u8 custom_coor_info_flag : 1; + u8 reserved1 : 7; + u16 reserved2; + u16 checksum; + u8 data[0]; +}; + +struct goodix_ts_gesture_event_data { + u8 fp_flag : 4; + u8 type : 4; + u8 int_count; + u8 reserved1 : 4; + u8 large_touch : 1; + u8 hover_approach_flag : 1; + u8 edge_flag : 1; + u8 reset_int : 1; + u8 touches; + u8 gesture_type; + u8 reserved3; + u16 checksum; + u8 data[0]; +}; + +struct goodix_mutual_data { + uint16_t duration; + uint16_t tx1_freq; + uint16_t tx2_freq; + uint16_t res; + uint16_t data[0]; +}; + +struct goodix_self_sensing_data { + uint16_t tx_duration; + uint16_t rx_duration; + uint16_t tx_freq; + uint16_t rx_freq; + uint16_t res; + uint16_t data[0]; +}; + +struct goodix_rx_package { + uint8_t header[8]; + uint16_t data[0]; +}; + enum goodix_ic_bus_type { GOODIX_BUS_TYPE_I2C, GOODIX_BUS_TYPE_SPI, @@ -443,6 +514,8 @@ struct goodix_bus_interface { u8 *tx_buf; int (*read)(struct device *dev, unsigned int addr, unsigned char *data, unsigned int len); + int (*read_fast)(struct device *dev, unsigned int addr, + struct goodix_rx_package *package, unsigned int len); int (*write)(struct device *dev, unsigned int addr, unsigned char *data, unsigned int len); }; @@ -456,6 +529,8 @@ struct goodix_ts_hw_ops { int (*irq_enable)(struct goodix_ts_core *cd, bool enable); int (*read)(struct goodix_ts_core *cd, unsigned int addr, unsigned char *data, unsigned int len); + int (*read_fast)(struct goodix_ts_core *cd, unsigned int addr, + struct goodix_rx_package *package, unsigned int len); int (*write)(struct goodix_ts_core *cd, unsigned int addr, unsigned char *data, unsigned int len); int (*send_cmd)(struct goodix_ts_core *cd, struct goodix_ts_cmd *cmd); @@ -476,6 +551,7 @@ struct goodix_ts_hw_ops { int (*set_scan_mode)(struct goodix_ts_core *cd, int mdoe); int (*set_continuously_report_enabled)( struct goodix_ts_core *cd, bool enabled); + int (*set_heatmap_enabled)(struct goodix_ts_core *cd, bool enabled); }; /* @@ -523,7 +599,10 @@ struct goodix_ts_core { struct regulator *avdd; struct regulator *iovdd; unsigned char gesture_type; - s16 *heatmap_buffer; + struct goodix_rx_package *touch_frame_package; + size_t touch_frame_size; + uint16_t *mutual_data; + uint16_t *self_sensing_data; int power_on; int irq; @@ -701,7 +780,7 @@ u32 goodix_append_checksum(u8 *data, int len, int mode); int checksum_cmp(const u8 *data, int size, int mode); int is_risk_data(const u8 *data, int size); u32 goodix_get_file_config_id(u8 *ic_config); -void goodix_rotate_abcd2cbad(int tx, int rx, s16 *data); +void goodix_rotate_abcd2cbad(int tx, int rx, s16 *src, s16 *dest); int goodix_fw_update_init(struct goodix_ts_core *core_data); void goodix_fw_update_uninit(void); diff --git a/goodix_ts_proc.c b/goodix_ts_proc.c index c24fbe2..0418f3e 100644 --- a/goodix_ts_proc.c +++ b/goodix_ts_proc.c @@ -1702,7 +1702,7 @@ static int goodix_open_test(void) } cd->hw_ops->read(cd, raw_addr, tmp_buf, tx * rx * 2); - goodix_rotate_abcd2cbad(tx, rx, (s16 *)tmp_buf); + goodix_rotate_abcd2cbad(tx, rx, (s16 *)tmp_buf, NULL); memcpy((u8 *)ts_test->rawdata[i].data, tmp_buf, tx * rx * 2); } @@ -1861,7 +1861,7 @@ static int goodix_noise_test(void) } cd->hw_ops->read(cd, raw_addr, tmp_buf, tx * rx * 2); - goodix_rotate_abcd2cbad(tx, rx, (s16 *)tmp_buf); + goodix_rotate_abcd2cbad(tx, rx, (s16 *)tmp_buf, NULL); memcpy((u8 *)ts_test->noisedata[i].data, tmp_buf, tx * rx * 2); } @@ -1977,7 +1977,7 @@ static void goodix_auto_noise_test(u16 cnt, int threshold) } cd->hw_ops->read(cd, raw_addr, (u8 *)tmp_buf, tx * rx * 2); - goodix_rotate_abcd2cbad(tx, rx, tmp_buf); + goodix_rotate_abcd2cbad(tx, rx, tmp_buf, NULL); index += sprintf(&rbuf[index], "max:\n"); for (i = 0; i < tx * rx; i++) { tmp_val = tmp_buf[i]; @@ -2002,7 +2002,7 @@ static void goodix_auto_noise_test(u16 cnt, int threshold) goto exit; } cd->hw_ops->read(cd, raw_addr, (u8 *)tmp_buf, tx * rx * 2); - goodix_rotate_abcd2cbad(tx, rx, tmp_buf); + goodix_rotate_abcd2cbad(tx, rx, tmp_buf, NULL); index += sprintf(&rbuf[index], "min:\n"); for (i = 0; i < tx * rx; i++) { tmp_val = tmp_buf[i]; @@ -2114,7 +2114,7 @@ static int get_cap_data(uint8_t *type) ts_err("read frame data failed"); goto exit; } - goodix_rotate_abcd2cbad(tx, rx, (s16 *)frame_buf); + goodix_rotate_abcd2cbad(tx, rx, (s16 *)frame_buf, NULL); for (i = 0; i < tx * rx; i++) { index += sprintf( &rbuf[index], "%5d,", *((s16 *)frame_buf + i)); @@ -2558,14 +2558,11 @@ static void goodix_set_heatmap(int val) 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; diff --git a/goodix_ts_utils.c b/goodix_ts_utils.c index 1d24cea..7649759 100644 --- a/goodix_ts_utils.c +++ b/goodix_ts_utils.c @@ -124,30 +124,34 @@ u32 goodix_get_file_config_id(u8 *ic_config) } /* matrix transpose */ -void goodix_rotate_abcd2cbad(int tx, int rx, s16 *data) +void goodix_rotate_abcd2cbad(int tx, int rx, s16 *src, s16 *dest) { - s16 *temp_buf = NULL; + s16 *temp_buf = dest; int size = tx * rx; - int i; - int j; - int col; - - temp_buf = kcalloc(size, sizeof(s16), GFP_KERNEL); - if (!temp_buf) { - ts_err("malloc failed"); - return; + int x; + s16 *curr; + int index_org = 0; + + if (dest == NULL) { + temp_buf = kcalloc(size, sizeof(s16), GFP_KERNEL); + if (!temp_buf) { + ts_err("malloc failed"); + return; + } } - for (i = 0, j = 0, col = 0; i < size; i++) { - temp_buf[i] = data[j++ * rx + col]; - if (j == tx) { - j = 0; - col++; + curr = temp_buf; + for (x = 0; x < rx; x++) { + for (index_org = x; index_org < size; index_org += rx) { + *curr = src[index_org]; + curr++; } } - memcpy(data, temp_buf, size * sizeof(s16)); - kfree(temp_buf); + if (dest == NULL) { + memcpy(src, temp_buf, size * sizeof(s16)); + kfree(temp_buf); + } } /* get ic type */ |