diff options
author | Super Liu <supercjliu@google.com> | 2021-07-19 08:35:25 +0000 |
---|---|---|
committer | Super Liu <supercjliu@google.com> | 2021-07-21 11:45:02 +0000 |
commit | fe46d087fd6d4d9aa1e1bb366ea088aaa1622f6d (patch) | |
tree | d9df06a634fd4f30777dae0bcfb9df79a150e747 | |
parent | b98ede58197b6dc89c280457c5aaf3c3a9da5468 (diff) | |
download | sec_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.c | 108 | ||||
-rw-r--r-- | sec_ts.h | 20 |
2 files changed, 124 insertions, 4 deletions
@@ -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); @@ -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 { |