input: touchscreen: goodix_berlin_driver: Implement gestures via xiaomi touch

Change-Id: I64ffe8fd3131bb7428b187c503908d73195e15a7
This commit is contained in:
Arian 2024-10-13 18:45:22 +02:00 committed by Jens Reidel
parent 614b119f31
commit fa989c6913
No known key found for this signature in database
GPG Key ID: 23C1E5F512C12303
4 changed files with 97 additions and 33 deletions

View File

@ -342,8 +342,9 @@ int brl_gesture(struct goodix_ts_core *cd, int gesture_type)
cmd.cmd = GOODIX_GESTURE_CMD_BA;
else
cmd.cmd = GOODIX_GESTURE_CMD;
cmd.len = 5;
cmd.data[0] = gesture_type;
cmd.len = 6;
cmd.data[0] = (gesture_type >> 0) & 0x01;
cmd.data[1] = (gesture_type >> 1) & 0x01;
if (cd->hw_ops->send_cmd(cd, &cmd))
ts_err("failed send gesture cmd");

View File

@ -1903,6 +1903,8 @@ static int goodix_ts_resume(struct goodix_ts_core *core_data)
atomic_set(&core_data->suspended, 0);
hw_ops->irq_enable(core_data, false);
cancel_delayed_work_sync(&core_data->gesture_work);
mutex_lock(&goodix_modules.mutex);
if (!list_empty(&goodix_modules.head)) {
list_for_each_entry_safe(ext_module, next,
@ -1962,6 +1964,45 @@ static void goodix_resume_work(struct work_struct *work)
goodix_ts_resume(core_data);
}
static void goodix_set_gesture_work(struct work_struct *work)
{
struct delayed_work *dwork = to_delayed_work(work);
struct goodix_ts_core *core_data = container_of(dwork, struct goodix_ts_core, gesture_work);
struct goodix_ts_hw_ops *hw_ops = core_data->hw_ops;
unsigned int target_gesture_type;
int res;
if (!atomic_read(&core_data->suspended)) {
ts_debug("touch is not suspended, skip re-wake");
return;
}
pm_stay_awake(core_data->bus->dev);
target_gesture_type = core_data->nonui_enabled ? 0 : core_data->gesture_type;
if (target_gesture_type == 0) {
disable_irq_wake(core_data->irq);
hw_ops->irq_enable(core_data, false);
hw_ops->gesture(core_data, 0);
goto exit;
}
hw_ops->reset(core_data, GOODIX_NORMAL_RESET_DELAY_MS);
res = hw_ops->gesture(core_data, target_gesture_type);
if (res) {
ts_err("failed enter gesture mode");
goto exit;
} else {
ts_err("enter gesture mode");
}
hw_ops->irq_enable(core_data, true);
enable_irq_wake(core_data->irq);
exit:
pm_relax(core_data->bus->dev);
}
static int goodix_set_cur_value(int mode, int value)
{
ts_debug("mode: %d, value: %d", mode, value);
@ -1969,11 +2010,34 @@ static int goodix_set_cur_value(int mode, int value)
if (!ts_core || value < 0) return 0;
switch (mode) {
case Touch_Doubletap_Mode:
if (value)
ts_core->gesture_type |= GESTURE_DOUBLE_TAP;
else
ts_core->gesture_type &= ~GESTURE_DOUBLE_TAP;
break;
case Touch_Singletap_Gesture:
if (value)
ts_core->gesture_type |= GESTURE_SINGLE_TAP;
else
ts_core->gesture_type &= ~GESTURE_SINGLE_TAP;
break;
case Touch_Fod_Longpress_Gesture:
if (value)
ts_core->gesture_type |= GESTURE_FOD_PRESS;
else
ts_core->gesture_type &= ~GESTURE_FOD_PRESS;
break;
case Touch_Nonui_Mode:
ts_core->nonui_enabled = value != 0;
break;
default:
ts_err("handler got mode %d with value %d, not implemented", mode, value);
return 0;
}
queue_delayed_work(ts_core->gesture_wq, &ts_core->gesture_work, msecs_to_jiffies(GOODIX_NORMAL_GESTURE_DELAY_MS));
return 0;
}
@ -1984,6 +2048,14 @@ static int goodix_get_mode_value(int mode, int value_type)
if (!ts_core) return -1;
switch (mode) {
case Touch_Doubletap_Mode:
return (ts_core->gesture_type & GESTURE_DOUBLE_TAP) != 0;
case Touch_Singletap_Gesture:
return (ts_core->gesture_type & GESTURE_SINGLE_TAP) != 0;
case Touch_Fod_Longpress_Gesture:
return (ts_core->gesture_type & GESTURE_FOD_PRESS) != 0;
case Touch_Nonui_Mode:
return ts_core->nonui_enabled ? 2 : 0;
default:
ts_err("handler got mode %d with value_type %d, not implemented", mode, value_type);
return -1;
@ -2168,6 +2240,15 @@ int goodix_ts_stage2_init(struct goodix_ts_core *cd)
INIT_WORK(&cd->resume_work, goodix_resume_work);
INIT_WORK(&cd->suspend_work, goodix_suspend_work);
cd->gesture_wq =
alloc_workqueue("gtp-gesture-queue",
WQ_UNBOUND | WQ_HIGHPRI | WQ_CPU_INTENSIVE, 1);
if (!cd->gesture_wq) {
ts_err("cannot create gesture work thread");
ret = -ENOMEM;
goto exit;
}
INIT_DELAYED_WORK(&cd->gesture_work, goodix_set_gesture_work);
#if defined(CONFIG_DRM)
if (active_panel)
goodix_register_for_panel_events(cd->bus->dev->of_node, cd);

View File

@ -56,6 +56,7 @@
#define GOODIX_GESTURE_DATA_LEN 16
#define GOODIX_NORMAL_RESET_DELAY_MS 100
#define GOODIX_NORMAL_GESTURE_DELAY_MS 300
#define GOODIX_HOLD_CPU_RESET_DELAY_MS 5
#define GOODIX_RETRY_3 3
@ -552,6 +553,11 @@ struct goodix_ts_core {
struct workqueue_struct *power_wq;
struct work_struct resume_work;
struct work_struct suspend_work;
struct workqueue_struct *gesture_wq;
struct delayed_work gesture_work;
bool nonui_enabled;
};
/* external module structures */

View File

@ -236,10 +236,11 @@ static int gsx_gesture_ist(struct goodix_ts_core *cd,
{
struct goodix_ts_hw_ops *hw_ops = cd->hw_ops;
struct goodix_ts_event gs_event = {0};
int fodx, fody, overlay_area;
int ret;
if (atomic_read(&cd->suspended) == 0 || cd->gesture_type == 0)
ts_debug("gsx_gesture_ist called, gesture type is %d, nonui enabled is %d", cd->gesture_type, cd->nonui_enabled);
if (atomic_read(&cd->suspended) == 0 || cd->gesture_type == 0 || cd->nonui_enabled)
return EVT_CONTINUE;
ret = hw_ops->event_handler(cd, &gs_event);
@ -258,12 +259,7 @@ static int gsx_gesture_ist(struct goodix_ts_core *cd,
case GOODIX_GESTURE_SINGLE_TAP:
if (cd->gesture_type & GESTURE_SINGLE_TAP) {
ts_info("get SINGLE-TAP gesture");
input_report_key(cd->input_dev, KEY_WAKEUP, 1);
// input_report_key(cd->input_dev, KEY_GOTO, 1);
input_sync(cd->input_dev);
input_report_key(cd->input_dev, KEY_WAKEUP, 0);
// input_report_key(cd->input_dev, KEY_GOTO, 0);
input_sync(cd->input_dev);
notify_gesture_single_tap();
} else {
ts_debug("not enable SINGLE-TAP");
}
@ -271,10 +267,7 @@ static int gsx_gesture_ist(struct goodix_ts_core *cd,
case GOODIX_GESTURE_DOUBLE_TAP:
if (cd->gesture_type & GESTURE_DOUBLE_TAP) {
ts_info("get DOUBLE-TAP gesture");
input_report_key(cd->input_dev, KEY_WAKEUP, 1);
input_sync(cd->input_dev);
input_report_key(cd->input_dev, KEY_WAKEUP, 0);
input_sync(cd->input_dev);
notify_gesture_double_tap();
} else {
ts_debug("not enable DOUBLE-TAP");
}
@ -282,17 +275,7 @@ static int gsx_gesture_ist(struct goodix_ts_core *cd,
case GOODIX_GESTURE_FOD_DOWN:
if (cd->gesture_type & GESTURE_FOD_PRESS) {
ts_info("get FOD-DOWN gesture");
fodx = le16_to_cpup((__le16 *)gs_event.gesture_data);
fody = le16_to_cpup((__le16 *)(gs_event.gesture_data + 2));
overlay_area = gs_event.gesture_data[4];
ts_debug("fodx:%d fody:%d overlay_area:%d", fodx, fody, overlay_area);
input_report_key(cd->input_dev, BTN_TOUCH, 1);
input_mt_slot(cd->input_dev, 0);
input_mt_report_slot_state(cd->input_dev, MT_TOOL_FINGER, 1);
input_report_abs(cd->input_dev, ABS_MT_POSITION_X, fodx);
input_report_abs(cd->input_dev, ABS_MT_POSITION_Y, fody);
input_report_abs(cd->input_dev, ABS_MT_WIDTH_MAJOR, overlay_area);
input_sync(cd->input_dev);
update_fod_press_status(1);
} else {
ts_debug("not enable FOD-DOWN");
}
@ -300,14 +283,7 @@ static int gsx_gesture_ist(struct goodix_ts_core *cd,
case GOODIX_GESTURE_FOD_UP:
if (cd->gesture_type & GESTURE_FOD_PRESS) {
ts_info("get FOD-UP gesture");
fodx = le16_to_cpup((__le16 *)gs_event.gesture_data);
fody = le16_to_cpup((__le16 *)(gs_event.gesture_data + 2));
overlay_area = gs_event.gesture_data[4];
input_report_key(cd->input_dev, BTN_TOUCH, 0);
input_mt_slot(cd->input_dev, 0);
input_mt_report_slot_state(cd->input_dev,
MT_TOOL_FINGER, 0);
input_sync(cd->input_dev);
update_fod_press_status(0);
} else {
ts_debug("not enable FOD-UP");
}