diff options
author | Roger Liao <rogerliao@google.com> | 2020-10-20 17:28:07 +0800 |
---|---|---|
committer | Roger Liao <rogerliao@google.com> | 2020-10-21 00:24:57 +0800 |
commit | ac9bb17e305323f1a6f66c33d3c39c11b91c95fe (patch) | |
tree | bfa0831edfd9a487773f97ba49e104948cded91d | |
parent | 274d04dda03882f326df59fe82c4ea81aa6c665b (diff) | |
parent | 6f2831fddffb0158b6af92e7c0b5cc369f883530 (diff) | |
download | sec_touch-ac9bb17e305323f1a6f66c33d3c39c11b91c95fe.tar.gz |
Merge branch 'android-msm-pixel-4.19-rvc-qpr1' into android-msm-barbet-4.19
Merge from build 6891367
Bug: 162288636
Signed-off-by: Roger Liao <rogerliao@google.com>
Change-Id: Icb9f7b23eb5453ac8b6d2e8223c593bbd6dad530
-rw-r--r-- | sec_ts.c | 590 | ||||
-rw-r--r-- | sec_ts.h | 8 | ||||
-rw-r--r-- | sec_ts_fn.c | 8 |
3 files changed, 558 insertions, 48 deletions
@@ -1413,7 +1413,7 @@ static bool read_heatmap_raw(struct v4l2_heatmap *v4l2) } ret = sec_ts_read(ts, - SEC_TS_CMD_MUTU_RAW_TYPE, &ts->frame_type, 1); + SEC_TS_CMD_MUTU_RAW_TYPE, &ts->ms_frame_type, 1); if (ret < 0) { input_err(true, &ts->client->dev, "%s: read rawdata type failed\n", @@ -1422,13 +1422,13 @@ static bool read_heatmap_raw(struct v4l2_heatmap *v4l2) } /* Check raw type is TYPE_SIGNAL_DATA */ - if (ts->frame_type != TYPE_SIGNAL_DATA) { + if (ts->ms_frame_type != TYPE_SIGNAL_DATA) { input_info(true, &ts->client->dev, - "%s: frame_type change from %#x\n", - __func__, ts->frame_type); + "%s: ms_frame_type change from %#x\n", + __func__, ts->ms_frame_type); /* Check raw type is TYPE_INVALID_DATA */ - if (ts->frame_type != TYPE_INVALID_DATA) { + if (ts->ms_frame_type != TYPE_INVALID_DATA) { type = TYPE_INVALID_DATA; ret = sec_ts_write(ts, SEC_TS_CMD_MUTU_RAW_TYPE, &type, 1); @@ -1438,7 +1438,7 @@ static bool read_heatmap_raw(struct v4l2_heatmap *v4l2) __func__); return false; } - ts->frame_type = type; + ts->ms_frame_type = type; } /* Set raw type to TYPE_SIGNAL_DATA */ @@ -1451,7 +1451,7 @@ static bool read_heatmap_raw(struct v4l2_heatmap *v4l2) __func__); return false; } - ts->frame_type = type; + ts->ms_frame_type = type; /* * If raw type change, need to wait 50 ms to read data @@ -1483,6 +1483,11 @@ static bool read_heatmap_raw(struct v4l2_heatmap *v4l2) #endif #ifdef SEC_TS_SUPPORT_CUSTOMLIB +/* WARNING: touch_offload does not currently support the custom library + * interface! + * TODO: when custom library support is enabled, ensure that the output is + * routed through touch_offload. + */ static void sec_ts_handle_lib_status_event(struct sec_ts_data *ts, struct sec_ts_event_status *p_event_status) { @@ -1590,6 +1595,14 @@ static void sec_ts_handle_coord_event(struct sec_ts_data *ts, if (ts->coord[t_id].z <= 0) ts->coord[t_id].z = 1; +#if IS_ENABLED(CONFIG_TOUCHSCREEN_OFFLOAD) + ts->offload.coords[t_id].x = ts->coord[t_id].x; + ts->offload.coords[t_id].y = ts->coord[t_id].y; + ts->offload.coords[t_id].major = ts->coord[t_id].major; + ts->offload.coords[t_id].minor = ts->coord[t_id].minor; + ts->offload.coords[t_id].pressure = ts->coord[t_id].z; +#endif + if ((ts->coord[t_id].ttype == SEC_TS_TOUCHTYPE_NORMAL) || (ts->coord[t_id].ttype == @@ -1613,6 +1626,21 @@ static void sec_ts_handle_coord_event(struct sec_ts_data *ts, (ts->time_released[t_id].tv_sec - ts->time_pressed[t_id].tv_sec); + if (ts->touch_count > 0) + ts->touch_count--; + if (ts->touch_count == 0 || + ts->tid_touch_state == 0) { + ts->check_multi = 0; + } + __clear_bit(t_id, &ts->tid_palm_state); + __clear_bit(t_id, &ts->tid_grip_state); + __clear_bit(t_id, &ts->tid_touch_state); + +#if IS_ENABLED(CONFIG_TOUCHSCREEN_OFFLOAD) + ts->offload.coords[t_id].status = + COORD_STATUS_INACTIVE; + if (!ts->offload.offload_running) { +#endif input_mt_slot(ts->input_dev, t_id); if (ts->plat_data->support_mt_pressure) input_report_abs(ts->input_dev, @@ -1620,25 +1648,26 @@ static void sec_ts_handle_coord_event(struct sec_ts_data *ts, input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 0); - if (ts->touch_count > 0) - ts->touch_count--; if (ts->touch_count == 0 || ts->tid_touch_state == 0) { input_report_key(ts->input_dev, BTN_TOUCH, 0); input_report_key(ts->input_dev, BTN_TOOL_FINGER, 0); - ts->check_multi = 0; } - __clear_bit(t_id, &ts->tid_palm_state); - __clear_bit(t_id, &ts->tid_grip_state); - __clear_bit(t_id, &ts->tid_touch_state); - +#if IS_ENABLED(CONFIG_TOUCHSCREEN_OFFLOAD) + } +#endif } else if (ts->coord[t_id].action == SEC_TS_COORDINATE_ACTION_PRESS) { do_gettimeofday(&ts->time_pressed[t_id]); ts->touch_count++; + if ((ts->touch_count > 4) && + (ts->check_multi == 0)) { + ts->check_multi = 1; + ts->multi_count++; + } ts->all_finger_count++; ts->max_z_value = max_t(unsigned int, @@ -1650,25 +1679,31 @@ static void sec_ts_handle_coord_event(struct sec_ts_data *ts, ts->sum_z_value += (unsigned int)ts->coord[t_id].z; - input_mt_slot(ts->input_dev, t_id); __set_bit(t_id, &ts->tid_touch_state); - if (ts->coord[t_id].palm) { + __clear_bit(t_id, &ts->tid_palm_state); + __clear_bit(t_id, &ts->tid_grip_state); + if (ts->coord[t_id].palm) + __set_bit(t_id, &ts->tid_palm_state); + else if (ts->coord[t_id].grip) + __set_bit(t_id, &ts->tid_grip_state); + +#if IS_ENABLED(CONFIG_TOUCHSCREEN_OFFLOAD) + ts->offload.coords[t_id].status = + COORD_STATUS_FINGER; + if (!ts->offload.offload_running) { +#endif + input_mt_slot(ts->input_dev, t_id); + if (ts->coord[t_id].palm) input_mt_report_slot_state( ts->input_dev, MT_TOOL_PALM, 1); - __set_bit(t_id, &ts->tid_palm_state); - __clear_bit(t_id, &ts->tid_grip_state); - } else if (ts->coord[t_id].grip) { + else if (ts->coord[t_id].grip) input_mt_report_slot_state( ts->input_dev, MT_TOOL_PALM, 1); - __clear_bit(t_id, &ts->tid_palm_state); - __set_bit(t_id, &ts->tid_grip_state); - } else { + else input_mt_report_slot_state( ts->input_dev, MT_TOOL_FINGER, 1); - __clear_bit(t_id, &ts->tid_palm_state); - __clear_bit(t_id, &ts->tid_grip_state); - } + input_report_key(ts->input_dev, BTN_TOUCH, 1); input_report_key(ts->input_dev, BTN_TOOL_FINGER, 1); @@ -1700,48 +1735,62 @@ static void sec_ts_handle_coord_event(struct sec_ts_data *ts, ABS_MT_PRESSURE, ts->coord[t_id].z); - if ((ts->touch_count > 4) && - (ts->check_multi == 0)) { - ts->check_multi = 1; - ts->multi_count++; +#if IS_ENABLED(CONFIG_TOUCHSCREEN_OFFLOAD) } - +#endif } else if (ts->coord[t_id].action == SEC_TS_COORDINATE_ACTION_MOVE) { + + ts->coord[t_id].mcount++; + #ifdef SW_GLOVE if ((ts->coord[t_id].ttype == SEC_TS_TOUCHTYPE_GLOVE) && !ts->touchkey_glove_mode_status) { ts->touchkey_glove_mode_status = true; + } else if ((ts->coord[t_id].ttype != + SEC_TS_TOUCHTYPE_GLOVE) && + ts->touchkey_glove_mode_status) { + ts->touchkey_glove_mode_status = false; + } +#endif + __set_bit(t_id, &ts->tid_touch_state); + __clear_bit(t_id, &ts->tid_palm_state); + __clear_bit(t_id, &ts->tid_grip_state); + if (ts->coord[t_id].palm) + __set_bit(t_id, &ts->tid_palm_state); + else if (ts->coord[t_id].grip) + __set_bit(t_id, &ts->tid_grip_state); +#if IS_ENABLED(CONFIG_TOUCHSCREEN_OFFLOAD) + ts->offload.coords[t_id].status = + COORD_STATUS_FINGER; + if (!ts->offload.offload_running) { +#endif +#ifdef SW_GLOVE + if ((ts->coord[t_id].ttype == + SEC_TS_TOUCHTYPE_GLOVE) && + !ts->touchkey_glove_mode_status) { input_report_switch(ts->input_dev, SW_GLOVE, 1); } else if ((ts->coord[t_id].ttype != SEC_TS_TOUCHTYPE_GLOVE) && ts->touchkey_glove_mode_status) { - ts->touchkey_glove_mode_status = false; input_report_switch(ts->input_dev, SW_GLOVE, 0); } #endif input_mt_slot(ts->input_dev, t_id); - __set_bit(t_id, &ts->tid_touch_state); - if (ts->coord[t_id].palm) { + if (ts->coord[t_id].palm) input_mt_report_slot_state( ts->input_dev, MT_TOOL_PALM, 1); - __set_bit(t_id, &ts->tid_palm_state); - __clear_bit(t_id, &ts->tid_grip_state); - } else if (ts->coord[t_id].grip) { + else if (ts->coord[t_id].grip) input_mt_report_slot_state( ts->input_dev, MT_TOOL_PALM, 1); - __clear_bit(t_id, &ts->tid_palm_state); - __set_bit(t_id, &ts->tid_grip_state); - } else { + else input_mt_report_slot_state( ts->input_dev, MT_TOOL_FINGER, 1); - __clear_bit(t_id, &ts->tid_palm_state); - __clear_bit(t_id, &ts->tid_grip_state); - } + input_report_key(ts->input_dev, BTN_TOUCH, 1); input_report_key(ts->input_dev, BTN_TOOL_FINGER, 1); @@ -1772,7 +1821,9 @@ static void sec_ts_handle_coord_event(struct sec_ts_data *ts, input_report_abs(ts->input_dev, ABS_MT_PRESSURE, ts->coord[t_id].z); - ts->coord[t_id].mcount++; +#if IS_ENABLED(CONFIG_TOUCHSCREEN_OFFLOAD) + } +#endif } else input_dbg(true, &ts->client->dev, "%s: do not support coordinate action(%d)\n", @@ -1848,6 +1899,308 @@ static void sec_ts_handle_gesture_event(struct sec_ts_data *ts, } #endif +#if IS_ENABLED(CONFIG_TOUCHSCREEN_OFFLOAD) + +static void sec_ts_populate_coordinate_channel(struct sec_ts_data *ts, + struct touch_offload_frame *frame, + int channel) +{ + int j; + + struct TouchOffloadDataCoord *dc = + (struct TouchOffloadDataCoord *)frame->channel_data[channel]; + memset(dc, 0, frame->channel_data_size[channel]); + dc->header.channel_type = TOUCH_DATA_TYPE_COORD; + dc->header.channel_size = TOUCH_OFFLOAD_FRAME_SIZE_COORD; + + for (j = 0; j < MAX_COORDS; j++) { + dc->coords[j].x = ts->offload.coords[j].x; + dc->coords[j].y = ts->offload.coords[j].y; + dc->coords[j].major = ts->offload.coords[j].major; + dc->coords[j].minor = ts->offload.coords[j].minor; + dc->coords[j].pressure = ts->offload.coords[j].pressure; + dc->coords[j].status = ts->offload.coords[j].status; + } +} + +static void sec_ts_populate_mutual_channel(struct sec_ts_data *ts, + struct touch_offload_frame *frame, + int channel) +{ + uint32_t frame_index = 0; + int32_t x, y; + uint16_t heatmap_value; + int ret = 0; + u8 target_data_type, type; + struct TouchOffloadData2d *mutual_strength = + (struct TouchOffloadData2d *)frame->channel_data[channel]; + + switch (frame->channel_type[channel] & ~TOUCH_SCAN_TYPE_MUTUAL) { + case TOUCH_DATA_TYPE_RAW: + target_data_type = TYPE_DECODED_DATA; + break; + case TOUCH_DATA_TYPE_FILTERED: + target_data_type = TYPE_REMV_AMB_DATA; + break; + case TOUCH_DATA_TYPE_STRENGTH: + target_data_type = TYPE_SIGNAL_DATA; + break; + case TOUCH_DATA_TYPE_BASELINE: + target_data_type = TYPE_AMBIENT_DATA; + break; + } + + mutual_strength->tx_size = ts->tx_count; + mutual_strength->rx_size = ts->rx_count; + mutual_strength->header.channel_type = frame->channel_type[channel]; + mutual_strength->header.channel_size = + TOUCH_OFFLOAD_FRAME_SIZE_2D(mutual_strength->rx_size, + mutual_strength->tx_size); + + ret = sec_ts_read(ts, + SEC_TS_CMD_MUTU_RAW_TYPE, &ts->ms_frame_type, 1); + if (ret < 0) { + input_err(true, &ts->client->dev, + "%s: read rawdata type failed\n", + __func__); + return; + } + + /* Check raw type is correct */ + if (ts->ms_frame_type != target_data_type) { + input_info(true, &ts->client->dev, + "%s: ms_frame_type change from %#x\n", + __func__, ts->ms_frame_type); + + /* Check raw type is TYPE_INVALID_DATA */ + if (ts->ms_frame_type != TYPE_INVALID_DATA) { + type = TYPE_INVALID_DATA; + ret = sec_ts_write(ts, + SEC_TS_CMD_MUTU_RAW_TYPE, &type, 1); + if (ret < 0) { + input_err(true, &ts->client->dev, + "%s: recover rawdata type failed\n", + __func__); + return; + } + ts->ms_frame_type = type; + } + + /* Set the targeted data type */ + ret = sec_ts_write(ts, SEC_TS_CMD_MUTU_RAW_TYPE, + &target_data_type, 1); + if (ret < 0) { + input_err(true, &ts->client->dev, + "%s: Set rawdata type failed\n", + __func__); + return; + } + ts->ms_frame_type = target_data_type; + + /* + * If raw type change, need to wait 50 ms to read data + * back. But, we don't wanto to wait here to cause + * overhead. Just drop this and wait for next reading. + */ + + return; + } + + ret = sec_ts_read_heap(ts, SEC_TS_READ_TOUCH_RAWDATA, + (u8 *)ts->heatmap_buff, + mutual_strength->header.channel_size); + if (ret < 0) { + input_err(true, &ts->client->dev, + "%s: Read mutual frame failed\n", __func__); + return; + } + + for (y = mutual_strength->rx_size - 1; y >= 0; y--) { + for (x = mutual_strength->tx_size - 1; x >= 0; x--) { + heatmap_value = + ts->heatmap_buff[x * mutual_strength->rx_size + y]; + ((uint16_t *) + mutual_strength->data)[frame_index++] = + be16_to_cpu(heatmap_value); + } + } +} + +static void sec_ts_populate_self_channel(struct sec_ts_data *ts, + struct touch_offload_frame *frame, + int channel) +{ + uint32_t frame_index = 0; + int32_t x, y; + uint16_t heatmap_value; + int ret = 0; + u8 target_data_type, type; + struct TouchOffloadData1d *self_strength = + (struct TouchOffloadData1d *)frame->channel_data[channel]; + + switch (frame->channel_type[channel] & ~TOUCH_SCAN_TYPE_SELF) { + case TOUCH_DATA_TYPE_RAW: + target_data_type = TYPE_DECODED_DATA; + break; + case TOUCH_DATA_TYPE_FILTERED: + target_data_type = TYPE_REMV_AMB_DATA; + break; + case TOUCH_DATA_TYPE_STRENGTH: + target_data_type = TYPE_SIGNAL_DATA; + break; + case TOUCH_DATA_TYPE_BASELINE: + target_data_type = TYPE_AMBIENT_DATA; + break; + } + + self_strength->tx_size = ts->tx_count; + self_strength->rx_size = ts->rx_count; + self_strength->header.channel_type = frame->channel_type[channel]; + self_strength->header.channel_size = + TOUCH_OFFLOAD_FRAME_SIZE_1D(self_strength->rx_size, + self_strength->tx_size); + + ret = sec_ts_read(ts, + SEC_TS_CMD_SELF_RAW_TYPE, &ts->ss_frame_type, 1); + if (ret < 0) { + input_err(true, &ts->client->dev, + "%s: read rawdata type failed\n", + __func__); + return; + } + + /* Check raw type is TYPE_SIGNAL_DATA */ + if (ts->ss_frame_type != target_data_type) { + input_info(true, &ts->client->dev, + "%s: ss_frame_type change from %#x\n", + __func__, ts->ss_frame_type); + + /* Check raw type is TYPE_INVALID_DATA */ + if (ts->ss_frame_type != TYPE_INVALID_DATA) { + type = TYPE_INVALID_DATA; + ret = sec_ts_write(ts, + SEC_TS_CMD_SELF_RAW_TYPE, &type, 1); + if (ret < 0) { + input_err(true, &ts->client->dev, + "%s: recover rawdata type failed\n", + __func__); + return; + } + ts->ss_frame_type = type; + } + + /* Set the targeted data type */ + ret = sec_ts_write(ts, SEC_TS_CMD_SELF_RAW_TYPE, + &target_data_type, 1); + if (ret < 0) { + input_err(true, &ts->client->dev, + "%s: Set rawdata type failed\n", + __func__); + return; + } + ts->ss_frame_type = target_data_type; + + /* + * If raw type change, need to wait 50 ms to read data + * back. But, we don't wanto to wait here to cause + * overhead. Just drop this and wait for next reading. + */ + + return; + } + + ret = sec_ts_read_heap(ts, SEC_TS_READ_TOUCH_SELF_RAWDATA, + (u8 *)ts->heatmap_buff, + self_strength->header.channel_size); + if (ret < 0) { + input_err(true, &ts->client->dev, + "%s: Read self frame failed\n", __func__); + return; + } + + for (x = self_strength->tx_size - 1; x >= 0; x--) { + heatmap_value = ts->heatmap_buff[x]; + ((uint16_t *) + self_strength->data)[frame_index++] = + be16_to_cpu(heatmap_value); + } + for (y = self_strength->rx_size - 1; y >= 0; y--) { + heatmap_value = ts->heatmap_buff[self_strength->tx_size + y]; + ((uint16_t *) + self_strength->data)[frame_index++] = + be16_to_cpu(heatmap_value); + } +} + +static void sec_ts_populate_frame(struct sec_ts_data *ts, + struct touch_offload_frame *frame) +{ + static u64 index; + int i; + + frame->header.index = index++; + frame->header.timestamp = ts->timestamp; + + if (!ts->heatmap_buff) { + ts->heatmap_buff = kmalloc( + ts->rx_count * ts->rx_count * 2, GFP_KERNEL); + } + + /* Populate all channels */ + for (i = 0; i < frame->num_channels; i++) { + if (frame->channel_type[i] == TOUCH_DATA_TYPE_COORD) + sec_ts_populate_coordinate_channel(ts, frame, i); + else if ((frame->channel_type[i] & TOUCH_SCAN_TYPE_MUTUAL) != 0) + sec_ts_populate_mutual_channel(ts, frame, i); + else if ((frame->channel_type[i] & TOUCH_SCAN_TYPE_SELF) != 0) + sec_ts_populate_self_channel(ts, frame, i); + } +} + +int sec_ts_enable_grip(struct sec_ts_data *ts, bool enable) +{ + u8 value = enable ? 1 : 0; + int ret; + int final_result = 0; + + /* Set grip */ + ret = ts->sec_ts_write(ts, SEC_TS_CMD_SET_GRIP_DETEC, &value, 1); + if (ret < 0) { + input_err(true, &ts->client->dev, + "%s: SEC_TS_CMD_SET_GRIP_DETEC failed with ret=%d\n", + __func__, ret); + final_result = ret; + } + + /* Set deadzone */ + value = enable ? 1 : 0; + ret = ts->sec_ts_write(ts, SEC_TS_CMD_EDGE_DEADZONE, &value, 1); + if (ret < 0) { + input_err(true, &ts->client->dev, + "%s: SEC_TS_CMD_EDGE_DEADZONE failed with ret=%d\n", + __func__, ret); + final_result = ret; + } + + return final_result; +} + +static void sec_ts_offload_set_running(struct sec_ts_data *ts, bool running) +{ + if (ts->offload.offload_running != running) { + ts->offload.offload_running = running; + if (running) { + pr_info("%s: disabling FW grip.\n", __func__); + sec_ts_enable_grip(ts, false); + } else { + pr_info("%s: enabling FW grip.\n", __func__); + sec_ts_enable_grip(ts, true); + } + } +} + +#endif /* CONFIG_TOUCHSCREEN_OFFLOAD */ + #define MAX_EVENT_COUNT 32 static void sec_ts_read_event(struct sec_ts_data *ts) { @@ -1864,6 +2217,9 @@ static void sec_ts_read_event(struct sec_ts_data *ts) bool processed_pointer_event = false; unsigned long last_tid_palm_state = ts->tid_palm_state; unsigned long last_tid_grip_state = ts->tid_grip_state; +#if IS_ENABLED(CONFIG_TOUCHSCREEN_OFFLOAD) + struct touch_offload_frame *frame = NULL; +#endif if (ts->power_status == SEC_TS_STATE_LPM) { @@ -2169,7 +2525,40 @@ static void sec_ts_read_event(struct sec_ts_data *ts) remain_event_count--; } while (remain_event_count >= 0); +#if IS_ENABLED(CONFIG_TOUCHSCREEN_OFFLOAD) + if (!ts->offload.offload_running) { +#endif + input_sync(ts->input_dev); + +#if IS_ENABLED(CONFIG_TOUCHSCREEN_OFFLOAD) + } + + if (processed_pointer_event) { + ret = touch_offload_reserve_frame(&ts->offload, &frame); + if (ret != 0) { + input_dbg(true, &ts->client->dev, + "Could not reserve a frame: ret=%d.\n", ret); + + /* Stop offload when there are no buffers available */ + sec_ts_offload_set_running(ts, false); + } else { + sec_ts_offload_set_running(ts, true); + + sec_ts_populate_frame(ts, frame); + + ret = touch_offload_queue_frame(&ts->offload, frame); + if (ret != 0) { + pr_err("%s: Failed to queue reserved frame: ret=%d.\n", + __func__, ret); + } + } + } +#endif + + /* TODO: If the mutual strength heatmap was already read into the touch + * offload interface, use it here instead of reading again. + */ #if IS_ENABLED(CONFIG_TOUCHSCREEN_HEATMAP) if (processed_pointer_event) { heatmap_read(&ts->v4l2, ktime_to_ns(ts->timestamp)); @@ -2226,7 +2615,9 @@ static irqreturn_t sec_ts_isr(int irq, void *handle) struct sec_ts_data *ts = (struct sec_ts_data *)handle; ts->timestamp = ktime_get(); +#if !IS_ENABLED(CONFIG_TOUCHSCREEN_OFFLOAD) input_set_timestamp(ts->input_dev, ts->timestamp); +#endif return IRQ_WAKE_THREAD; } @@ -2265,6 +2656,52 @@ static irqreturn_t sec_ts_irq_thread(int irq, void *ptr) return IRQ_HANDLED; } +#if IS_ENABLED(CONFIG_TOUCHSCREEN_OFFLOAD) +static void sec_ts_offload_report(void *handle, + struct TouchOffloadIocReport *report) +{ + struct sec_ts_data *ts = (struct sec_ts_data *)handle; + bool touch_down = 0; + int i; + + input_set_timestamp(ts->input_dev, report->timestamp); + + for (i = 0; i < MAX_COORDS; i++) { + if (report->coords[i].status == COORD_STATUS_FINGER) { + input_mt_slot(ts->input_dev, i); + touch_down = 1; + input_report_key(ts->input_dev, BTN_TOUCH, + touch_down); + input_mt_report_slot_state(ts->input_dev, + MT_TOOL_FINGER, 1); + input_report_abs(ts->input_dev, ABS_MT_POSITION_X, + report->coords[i].x); + input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, + report->coords[i].y); + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, + report->coords[i].major); + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MINOR, + report->coords[i].minor); +#ifndef SKIP_PRESSURE + input_report_abs(ts->input_dev, ABS_MT_PRESSURE, + report->coords[i].pressure); +#endif + } else { + input_mt_slot(ts->input_dev, i); + input_report_abs(ts->input_dev, ABS_MT_PRESSURE, 0); + input_mt_report_slot_state(ts->input_dev, + MT_TOOL_FINGER, 0); + input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, + -1); + } + } + + input_report_key(ts->input_dev, BTN_TOUCH, touch_down); + + input_sync(ts->input_dev); +} +#endif /* CONFIG_TOUCHSCREEN_OFFLOAD */ + int get_tsp_status(void) { return 0; @@ -3461,6 +3898,47 @@ static int sec_ts_probe(struct spi_device *client) goto err_heatmap; } +#if IS_ENABLED(CONFIG_TOUCHSCREEN_OFFLOAD) + ts->offload.caps.touch_offload_major_version = 1; + ts->offload.caps.touch_offload_minor_version = 0; + /* ID equivalent to the 4-byte, little-endian string: '00r3' */ + ts->offload.caps.device_id = + '3' << 24 | 'r' << 16 | '0' << 8 | '0' << 0; + ts->offload.caps.display_width = ts->plat_data->max_x + 1; + ts->offload.caps.display_height = ts->plat_data->max_y + 1; + ts->offload.caps.tx_size = ts->tx_count; + ts->offload.caps.rx_size = ts->rx_count; + ts->offload.caps.heatmap_size = HEATMAP_SIZE_FULL; +#ifdef I2C_INTERFACE + ts->offload.caps.bus_type = BUS_TYPE_I2C; + ts->offload.caps.bus_speed_hz = 1000000; +#else + ts->offload.caps.bus_type = BUS_TYPE_SPI; + ts->offload.caps.bus_speed_hz = client->max_speed_hz; +#endif + + /* Currently can only reliably read mutual and self strength heatmaps + * each frame. Cannot support other formats due to penalties associated + * with switching data types. + */ + ts->offload.caps.touch_data_types = + TOUCH_DATA_TYPE_COORD | TOUCH_DATA_TYPE_STRENGTH; + ts->offload.caps.touch_scan_types = + TOUCH_SCAN_TYPE_MUTUAL | TOUCH_SCAN_TYPE_SELF; + + ts->offload.caps.continuous_reporting = true; + ts->offload.caps.noise_reporting = false; + ts->offload.caps.cancel_reporting = false; + ts->offload.caps.size_reporting = true; + ts->offload.caps.filter_grip = true; + ts->offload.caps.filter_palm = true; + ts->offload.caps.num_sensitivity_settings = 1; + + ts->offload.hcallback = (void *)ts; + ts->offload.report_cb = sec_ts_offload_report; + touch_offload_init(&ts->offload); +#endif + ts->notifier = sec_ts_screen_nb; ret = drm_panel_notifier_register(pdata->panel, &ts->notifier); if (ret < 0) { @@ -3520,6 +3998,11 @@ static int sec_ts_probe(struct spi_device *client) **/ err_register_drm_client: free_irq(client->irq, ts); + +#if IS_ENABLED(CONFIG_TOUCHSCREEN_OFFLOAD) + touch_offload_cleanup(&ts->offload); +#endif + err_heatmap: #if IS_ENABLED(CONFIG_TOUCHSCREEN_HEATMAP) heatmap_remove(&ts->v4l2); @@ -3605,6 +4088,9 @@ void sec_ts_unlocked_release_all_finger(struct sec_ts_data *ts) SEC_TS_COORDINATE_ACTION_MOVE)) { ts->coord[i].action = SEC_TS_COORDINATE_ACTION_RELEASE; +#if IS_ENABLED(CONFIG_TOUCHSCREEN_OFFLOAD) + ts->offload.coords[i].status = COORD_STATUS_INACTIVE; +#endif input_info(true, &ts->client->dev, "%s: [RA] tID:%d mc:%d tc:%d v:%02X%02X cal:%02X(%02X) id(%d,%d) p:%d\n", __func__, i, @@ -3673,6 +4159,9 @@ void sec_ts_locked_release_all_finger(struct sec_ts_data *ts) SEC_TS_COORDINATE_ACTION_MOVE)) { ts->coord[i].action = SEC_TS_COORDINATE_ACTION_RELEASE; +#if IS_ENABLED(CONFIG_TOUCHSCREEN_OFFLOAD) + ts->offload.coords[i].status = COORD_STATUS_INACTIVE; +#endif input_info(true, &ts->client->dev, "%s: [RA] tID:%d mc: %d tc:%d, v:%02X%02X, cal:%X(%X|%X), id(%d,%d), p:%d\n", __func__, i, ts->coord[i].mcount, @@ -4076,6 +4565,10 @@ static int sec_ts_remove(struct spi_device *client) free_irq(ts->client->irq, ts); input_info(true, &ts->client->dev, "%s: irq disabled\n", __func__); +#if IS_ENABLED(CONFIG_TOUCHSCREEN_OFFLOAD) + touch_offload_cleanup(&ts->offload); +#endif + #if IS_ENABLED(CONFIG_TOUCHSCREEN_HEATMAP) heatmap_remove(&ts->v4l2); #endif @@ -4507,6 +5000,17 @@ static void sec_ts_resume_work(struct work_struct *work) input_err(true, &ts->client->dev, "%s: failed to write Sense_on.\n", __func__); +#if IS_ENABLED(CONFIG_TOUCHSCREEN_OFFLOAD) + /* Set touch_offload configuration */ + if (ts->offload.offload_running) { + input_info(true, &ts->client->dev, + "applying touch_offload settings.\n"); + + if (!ts->offload.config.filter_grip) + sec_ts_enable_grip(ts, false); + } +#endif + enable_irq(ts->client->irq); complete_all(&ts->bus_resumed); @@ -27,6 +27,7 @@ #include <linux/input/heatmap.h> #endif #include <linux/input/mt.h> +#include <linux/input/touch_offload.h> #include "sec_cmd.h" #include <linux/interrupt.h> #include <linux/io.h> @@ -872,12 +873,17 @@ struct sec_ts_data { ktime_t mf_downtime; u8 print_format; - u8 frame_type; + u8 ms_frame_type; + u8 ss_frame_type; #if IS_ENABLED(CONFIG_TOUCHSCREEN_HEATMAP) struct v4l2_heatmap v4l2; strength_t *heatmap_buff; #endif +#if IS_ENABLED(CONFIG_TOUCHSCREEN_OFFLOAD) + struct touch_offload_context offload; +#endif + #ifdef USE_POWER_RESET_WORK struct delayed_work reset_work; volatile bool reset_is_on_going; diff --git a/sec_ts_fn.c b/sec_ts_fn.c index 4d0eecf..bc5f2d2 100644 --- a/sec_ts_fn.c +++ b/sec_ts_fn.c @@ -1690,7 +1690,7 @@ static int sec_ts_read_frame(struct sec_ts_data *ts, u8 type, short *min, /* Set raw type to TYPE_INVALID_DATA if change before */ ret = ts->sec_ts_read(ts, - SEC_TS_CMD_MUTU_RAW_TYPE, &ts->frame_type, 1); + SEC_TS_CMD_MUTU_RAW_TYPE, &ts->ms_frame_type, 1); if (ret < 0) { input_err(true, &ts->client->dev, "%s: read rawdata type failed\n", @@ -1698,7 +1698,7 @@ static int sec_ts_read_frame(struct sec_ts_data *ts, u8 type, short *min, goto ErrorExit; } - if (ts->frame_type != TYPE_INVALID_DATA) { + if (ts->ms_frame_type != TYPE_INVALID_DATA) { ret = ts->sec_ts_write(ts, SEC_TS_CMD_MUTU_RAW_TYPE, &mode, 1); if (ret < 0) input_err(true, &ts->client->dev, @@ -1711,7 +1711,7 @@ static int sec_ts_read_frame(struct sec_ts_data *ts, u8 type, short *min, "%s: Set rawdata type failed\n", __func__); goto ErrorExit; } - ts->frame_type = w_type; + ts->ms_frame_type = w_type; sec_ts_delay(50); @@ -1874,7 +1874,7 @@ ErrorRelease: input_err(true, &ts->client->dev, "%s: Set rawdata type failed\n", __func__); else - ts->frame_type = mode; + ts->ms_frame_type = mode; ErrorExit: kfree(pRead); |