summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSuper Liu <supercjliu@google.com>2021-07-19 08:35:25 +0000
committerSuper Liu <supercjliu@google.com>2021-07-21 11:45:02 +0000
commitfe46d087fd6d4d9aa1e1bb366ea088aaa1622f6d (patch)
treed9df06a634fd4f30777dae0bcfb9df79a150e747
parentb98ede58197b6dc89c280457c5aaf3c3a9da5468 (diff)
downloadsec_touch-fe46d087fd6d4d9aa1e1bb366ea088aaa1622f6d.tar.gz
touch/sec: support FoD (Fingerprint on Display) event.
FW add FoD event for better HBM (High Brightness Mode) control on kernel side. Bug: 192988780 Test: check the functionality for STTW/LPTW and FoD. Signed-off-by: Super Liu <supercjliu@google.com> Change-Id: Ic978fdedccb4f838e1b27d8c256e0773444e7a4e
-rw-r--r--sec_ts.c108
-rw-r--r--sec_ts.h20
2 files changed, 124 insertions, 4 deletions
diff --git a/sec_ts.c b/sec_ts.c
index 712f691..9ec8ad0 100644
--- a/sec_ts.c
+++ b/sec_ts.c
@@ -2557,6 +2557,62 @@ static void sec_ts_offload_set_running(struct sec_ts_data *ts, bool running)
#endif /* CONFIG_TOUCHSCREEN_OFFLOAD */
+static void sec_ts_handle_fod_event(struct sec_ts_data *ts,
+ struct sec_ts_event_status *p_event_status)
+{
+ struct sec_ts_fod_event *p_fod =
+ (struct sec_ts_fod_event *)p_event_status;
+ int x = p_fod->x_b11_b8 << 8 | p_fod->x_b7_b0;
+ int y = p_fod->y_b11_b8 << 8 | p_fod->y_b7_b0;
+
+ if (test_bit(0, &ts->tid_touch_state)) {
+ input_info(true, &ts->client->dev,
+ "%s: slot 0 is in use!", __func__);
+ return;
+ }
+
+ if (!x || !y) {
+ input_info(true, &ts->client->dev,
+ "%s: one of coords is ZERO(%d, %d)!",
+ __func__, x, y);
+ x = ts->plat_data->fod_x;
+ y = ts->plat_data->fod_y;
+ }
+
+ input_info(true, &ts->client->dev,
+ "STATUS: FoD: %s, X,Y: %d, %d\n", p_fod->status ? "ON" : "OFF", x, y);
+
+ if (p_fod->status == false) {
+ mutex_lock(&ts->eventlock);
+ input_mt_slot(ts->input_dev, 0);
+ input_report_key(ts->input_dev, BTN_TOUCH, 1);
+ input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 1);
+ input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x);
+ input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y);
+ input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 140);
+ input_report_abs(ts->input_dev, ABS_MT_TOUCH_MINOR, 140);
+#ifndef SKIP_PRESSURE
+ input_report_abs(ts->input_dev, ABS_MT_PRESSURE, 1);
+#endif
+ input_sync(ts->input_dev);
+
+ /* Report MT_TOOL_PALM for canceling the touch event. */
+ input_mt_slot(ts->input_dev, 0);
+ input_report_key(ts->input_dev, BTN_TOUCH, 1);
+ input_mt_report_slot_state(ts->input_dev, MT_TOOL_PALM, 1);
+ input_sync(ts->input_dev);
+
+ /* Release slot 0. */
+ input_mt_slot(ts->input_dev, 0);
+ 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, 0);
+ input_sync(ts->input_dev);
+ mutex_unlock(&ts->eventlock);
+ }
+}
static void sec_ts_read_vendor_event(struct sec_ts_data *ts,
struct sec_ts_event_status *p_event_status)
@@ -2634,6 +2690,10 @@ static void sec_ts_read_vendor_event(struct sec_ts_data *ts,
status_data_1);
break;
+ case SEC_TS_EVENT_STATUS_ID_FOD:
+ sec_ts_handle_fod_event(ts, p_event_status);
+ break;
+
default:
break;
}
@@ -5321,6 +5381,7 @@ static void sec_ts_resume_work(struct work_struct *work)
{
struct sec_ts_data *ts = container_of(work, struct sec_ts_data,
resume_work);
+ u8 touch_mode[2] = {0};
int ret = 0;
input_info(true, &ts->client->dev, "%s\n", __func__);
@@ -5347,10 +5408,49 @@ static void sec_ts_resume_work(struct work_struct *work)
ts->power_status = SEC_TS_STATE_POWER_ON;
- ret = sec_ts_system_reset(ts, RESET_MODE_HW, false, false);
- if (ret < 0)
- input_err(true, &ts->client->dev,
- "%s: reset failed! ret %d\n", __func__, ret);
+ ret = ts->sec_ts_read(ts, SEC_TS_CMD_CHG_SYSMODE, touch_mode,
+ sizeof(touch_mode));
+ if (ret < 0) {
+ ret = sec_ts_system_reset(ts, RESET_MODE_HW, false, false);
+ if (ret < 0) {
+ input_err(true, &ts->client->dev,
+ "%s: reset failed! ret %d\n", __func__, ret);
+ }
+ } else {
+ u8 power_mode = 0;
+
+ input_info(true, &ts->client->dev, "%s: before resume: mode %#x, state %#x.",
+ __func__, touch_mode[0], touch_mode[1]);
+
+ if (touch_mode[0] == TOUCH_SYSTEM_MODE_LOWPOWER) {
+ ret = sec_ts_write(ts, SEC_TS_CMD_SET_POWER_MODE,
+ &power_mode, sizeof(power_mode));
+ if (ret < 0) {
+ input_err(true, &ts->client->dev,
+ "%s: set power mode failed(%d)\n",
+ __func__, ret);
+ }
+ sec_ts_delay(50);
+ ret = ts->sec_ts_read(ts, SEC_TS_CMD_CHG_SYSMODE, touch_mode,
+ sizeof(touch_mode));
+ if (ret < 0) {
+ input_err(true, &ts->client->dev,
+ "%s: set read touch mode failed(%d)\n",
+ __func__, ret);
+
+ } else {
+ input_info(true, &ts->client->dev,
+ "%s: after resume: mode %#x, state %#x",
+ __func__, touch_mode[0], touch_mode[1]);
+ }
+ } else {
+ ret = sec_ts_system_reset(ts, RESET_MODE_HW, false, false);
+ if (ret < 0) {
+ input_err(true, &ts->client->dev,
+ "%s: reset failed! ret %d\n", __func__, ret);
+ }
+ }
+ }
if (ts->plat_data->enable_sync)
ts->plat_data->enable_sync(true);
diff --git a/sec_ts.h b/sec_ts.h
index 20ca6d4..4d3cba7 100644
--- a/sec_ts.h
+++ b/sec_ts.h
@@ -773,9 +773,29 @@ struct sec_ts_gesture_status {
#define SEC_TS_EVENT_STATUS_ID_NOISE 0x64
#define SEC_TS_EVENT_STATUS_ID_WLC 0x66
#define SEC_TS_EVENT_STATUS_ID_GRIP 0x69
+#define SEC_TS_EVENT_STATUS_ID_FOD 0x6B
#define SEC_TS_EVENT_STATUS_ID_PALM 0x70
/* 8 byte */
+struct sec_ts_fod_event {
+ struct {
+ u8 type;
+ u8 id;
+ u8 status;
+ u8 x_b7_b0;
+ union {
+ struct {
+ u8 y_b11_b8:4;
+ u8 x_b11_b8:4;
+ };
+ u8 x_y_b11_b8;
+ };
+ u8 y_b7_b0;
+ u8 reserved[2];
+ };
+} __packed;
+
+/* 8 byte */
struct sec_ts_event_status {
union {
struct {