From b2b3e5fa44d416b72490f5850529d8e480e2f612 Mon Sep 17 00:00:00 2001 From: Super Liu Date: Thu, 31 Mar 2022 11:38:45 +0800 Subject: touch/common: GTI support continuous reporting. Bug: 201610482 Signed-off-by: Super Liu Change-Id: Ic25eb25155d381835be4d26e6efc54d6509a59f3 --- goog_touch_interface.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++---- goog_touch_interface.h | 37 ++++++++++++++++++++++- 2 files changed, 109 insertions(+), 7 deletions(-) diff --git a/goog_touch_interface.c b/goog_touch_interface.c index 0a87083..2f02314 100644 --- a/goog_touch_interface.c +++ b/goog_touch_interface.c @@ -12,6 +12,67 @@ #include "goog_touch_interface.h" #include "../../../gs-google/drivers/soc/google/vh/kernel/systrace.h" +void goog_update_motion_filter(struct goog_touch_interface *gti, unsigned long slot_bit) +{ + const u32 mf_timeout_ms = 500; + unsigned long touches = hweight_long(slot_bit); + u32 next_state = gti->mf_state; + + switch (gti->mf_mode) { + case GTI_MF_MODE_AUTO_REPORT: + case GTI_MF_MODE_UNFILTER: + next_state = GTI_MF_STATE_UNFILTERED; + break; + case GTI_MF_MODE_FILTER: + next_state = GTI_MF_STATE_FILTERED; + break; + case GTI_MF_MODE_DYNAMIC: + default: + /* + * Determine the next filter state. The motion filter is enabled by + * default and it is disabled while a single finger is touching the + * screen. If another finger is touched down or if a timeout expires, + * the motion filter is reenabled and remains enabled until all fingers + * are lifted. + */ + switch (next_state) { + case GTI_MF_STATE_FILTERED: + if (touches == 1) { + next_state = GTI_MF_STATE_UNFILTERED; + gti->mf_downtime = ktime_get(); + } + break; + case GTI_MF_STATE_UNFILTERED: + if (touches == 0) { + next_state = GTI_MF_STATE_FILTERED; + } else if (touches > 1 || + ktime_after(ktime_get(), + ktime_add_ms(gti->mf_downtime, mf_timeout_ms))) { + next_state = GTI_MF_STATE_FILTERED_LOCKED; + } + break; + case GTI_MF_STATE_FILTERED_LOCKED: + if (touches == 0) + next_state = GTI_MF_STATE_FILTERED; + break; + } + break; + } + + /* Send command to setup continuous report. */ + if ((next_state == GTI_MF_STATE_UNFILTERED) != + (gti->mf_state == GTI_MF_STATE_UNFILTERED)) { + u32 enable = GTI_SUB_CMD_DISABLE; + + if (next_state == GTI_MF_STATE_UNFILTERED) + enable = GTI_SUB_CMD_ENABLE; + gti->vendor_cb(gti->vendor_private_data, + GTI_CMD_SET_CONTINUOUS_REPORT, enable, NULL, NULL); + } + + gti->mf_state = next_state; +} + bool goog_v4l2_read_frame_cb(struct v4l2_heatmap *v4l2) { struct goog_touch_interface *gti = container_of(v4l2, struct goog_touch_interface, v4l2); @@ -180,6 +241,7 @@ void goog_offload_input_report(void *handle, bool touch_down = 0; unsigned int tool_type = MT_TOOL_FINGER; int i; + unsigned long active_slot_bit = 0; ATRACE_BEGIN(__func__); @@ -199,6 +261,7 @@ void goog_offload_input_report(void *handle, tool_type = MT_TOOL_FINGER; break; } + __set_bit(i, &active_slot_bit); input_mt_slot(gti->input_dev, i); touch_down = 1; input_report_key(gti->input_dev, BTN_TOUCH, touch_down); @@ -214,6 +277,7 @@ void goog_offload_input_report(void *handle, input_report_abs(gti->input_dev, ABS_MT_PRESSURE, report->coords[i].pressure); } else { + __clear_bit(i, &active_slot_bit); input_mt_slot(gti->input_dev, i); input_report_abs(gti->input_dev, ABS_MT_PRESSURE, 0); input_mt_report_slot_state(gti->input_dev, MT_TOOL_FINGER, 0); @@ -227,9 +291,7 @@ void goog_offload_input_report(void *handle, if (touch_down) goog_v4l2_read(gti, report->timestamp); - /* - * TODO(b/201610482): Enable/disable continuous reporting. - */ + goog_update_motion_filter(gti, active_slot_bit); ATRACE_END(); } @@ -399,7 +461,7 @@ int goog_input_process(struct goog_touch_interface *gti) * Otherwise, heatmap will be handled for both offload and v4l2 * during goog_offload_populate_frame(). */ - if (!gti->offload.offload_running) { + if (!gti->offload.offload_running && gti->v4l2_enable) { int ret; u8 *buffer = NULL; u32 size = 0; @@ -410,6 +472,7 @@ int goog_input_process(struct goog_touch_interface *gti) if (ret == 0 && buffer && size) memcpy(gti->heatmap_buf, buffer, size); goog_v4l2_read(gti, gti->timestamp); + goog_update_motion_filter(gti, gti->active_slot_bit); } gti->coord_changed = false; @@ -486,10 +549,13 @@ void goog_input_mt_report_slot_state( input_mt_report_slot_state(dev, tool_type, active); if (tool_type == MT_TOOL_FINGER) { - if (active) + if (active) { gti->offload.coords[gti->slot].status = COORD_STATUS_FINGER; - else + __set_bit(gti->slot, >i->active_slot_bit); + } else { gti->offload.coords[gti->slot].status = COORD_STATUS_INACTIVE; + __clear_bit(gti->slot, >i->active_slot_bit); + } } } EXPORT_SYMBOL(goog_input_mt_report_slot_state); @@ -555,6 +621,7 @@ struct goog_touch_interface *goog_touch_interface_probe( gti->dev = dev; gti->input_dev = input_dev; gti->vendor_cb = vendor_cb; + gti->mf_mode = GTI_MF_MODE_DEFAULT; mutex_init(>i->input_lock); goog_offload_probe(gti); } diff --git a/goog_touch_interface.h b/goog_touch_interface.h index ab0113f..16c32b7 100644 --- a/goog_touch_interface.h +++ b/goog_touch_interface.h @@ -23,7 +23,6 @@ #define KTIME_RELEASE_ALL (ktime_set(0, 0)) - enum { /* * GTI_CMD_GET_SENSOR_DATA: @@ -64,6 +63,34 @@ enum { GTI_SUB_CMD_DRIVER_DEFAULT, }; +/** + * Motion filter finite state machine (FSM) state. + * GTI_MF_STATE_FILTERED: default coordinate filtering + * GTI_MF_STATE_UNFILTERED: coordinate unfiltering for single-touch. + * GTI_MF_STATE_FILTERED_LOCKED: filtered coordinates. Locked until + * touch is lifted or timeout. + */ +enum { + GTI_MF_STATE_FILTERED = 0, + GTI_MF_STATE_UNFILTERED, + GTI_MF_STATE_FILTERED_LOCKED, +}; + +/** + * Motion filter mode. + * GTI_MF_MODE_UNFILTER: enable unfilter by continuous reporting. + * GTI_MF_MODE_DYNAMIC: dynamic control for motion filter. + * GTI_MF_MODE_FILTER: only report touch if coord report changed. + * GTI_MF_MODE_AUTO: for development case. + */ +enum { + GTI_MF_MODE_UNFILTER = 0, + GTI_MF_MODE_DEFAULT, + GTI_MF_MODE_DYNAMIC = GTI_MF_MODE_DEFAULT, + GTI_MF_MODE_FILTER, + GTI_MF_MODE_AUTO_REPORT, +}; + /** * struct goog_touch_interfac - Google touch interface data for Pixel. * @vendor_private_data: the private data pointer that used by touch vendor driver. @@ -74,8 +101,11 @@ enum { * @offload_frame: reserved frame that used by touch offload. * @v4l2: struct that used by v4l2. * @timestamp: irq timestamp from touch vendor driver. + * @mf_downtime: timestamp for motion filter control. * @grip_setting: current grip setting. * @palm_setting: current palm setting. + * @mf_mode: current motion filter mode. + * @mf_state: current motion filter state. * @force_legacy_report: force to directly report input by kernel input API. * @offload_enable: touch offload is enabled or not. * @v4l2_enable: v4l2 is enabled or not. @@ -84,6 +114,7 @@ enum { * @heatmap_buf: heatmap buffer that used by v4l2. * @heatmap_buf_size: heatmap buffer size that used by v4l2. * @slot: slot id that current used by input report. + * @active_slot_bit: bitmap of active slot from legacy report. * @vendor_cb: touch vendor driver function callback. */ @@ -96,9 +127,12 @@ struct goog_touch_interface { struct touch_offload_frame *offload_frame; struct v4l2_heatmap v4l2; ktime_t timestamp; + ktime_t mf_downtime; u32 grip_setting; u32 palm_setting; + u32 mf_mode; + u32 mf_state; bool force_legacy_report; bool offload_enable; @@ -111,6 +145,7 @@ struct goog_touch_interface { u8 *heatmap_buf; u32 heatmap_buf_size; int slot; + unsigned long active_slot_bit; int (*vendor_cb)(void *vendor_private_data, u32 cmd, u32 sub_cmd, u8 **buffer, u32 *size); -- cgit v1.2.3