summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--goodix_brl_hw.c212
-rw-r--r--goodix_brl_spi.c65
-rw-r--r--goodix_ts_core.c25
-rw-r--r--goodix_ts_core.h83
-rw-r--r--goodix_ts_proc.c13
-rw-r--r--goodix_ts_utils.c38
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 */