input: ilitek_0flash_mmi: add support for single tap

ilitek_0flash_mmi:
Add support for single tap.
NO_PROP_NEEDED: this is new IC driver, don't need to pick to stable
line.

Change-Id: I7d3efeb71e0f0e309db7c06062c86c765f8d7e1e
Signed-off-by: wangyq13 <wangyq13@lenovo.com>
Reviewed-on: https://gerrit.mot.com/1647675
SLTApproved: Slta Waiver
SME-Granted: SME Approvals Granted
Tested-by: Jira Key
Reviewed-by: Jun Weng <wengjun1@motorola.com>
Reviewed-by: Huosheng Liao <liaohs@motorola.com>
Submit-Approved: Jira Key
This commit is contained in:
wangyq13 2020-06-28 11:27:21 +08:00 • committed by Yeqing Wang
commit ceba7f61ed
6 changed files with 315 additions and 0 deletions

View file

@ -1,6 +1,14 @@
DLKM_DIR := motorola/kernel/modules
LOCAL_PATH := $(call my-dir)
ifneq ($(BOARD_USES_DOUBLE_TAP),)
KERNEL_CFLAGS += CONFIG_INPUT_ILI_0FLASH_MMI_ENABLE_DOUBLE_TAP=y
endif
ifneq ($(BOARD_USES_PANEL_NOTIFICATIONS),)
KERNEL_CFLAGS += CONFIG_INPUT_ILI_PANEL_NOTIFICATIONS=y
endif
include $(CLEAR_VARS)
LOCAL_MODULE := ilitek_0flash_mmi.ko
LOCAL_MODULE_TAGS := optional

View file

@ -7,6 +7,13 @@ ifeq ($(filter m y, $(CONFIG_TOUCHSCREEN_ILITEK_CHIPSET)),)
obj-m += ilitek_0flash_mmi.o
endif
ifneq ($(filter m y,$(CONFIG_INPUT_ILI_0FLASH_MMI_ENABLE_DOUBLE_TAP)),)
EXTRA_CFLAGS += -DILI_SENSOR_EN
endif
ifneq ($(filter m y,$(CONFIG_INPUT_ILI_PANEL_NOTIFICATIONS)),)
EXTRA_CFLAGS += -DILI_CONFIG_PANEL_NOTIFICATIONS
endif
ilitek_0flash_mmi-objs += ilitek.o
ilitek_0flash_mmi-objs += ilitek_spi.o
ilitek_0flash_mmi-objs += ilitek_qcom.o

View file

@ -407,6 +407,18 @@ int ili_sleep_handler(int mode)
ILI_ERR("Check busy timeout during suspend\n");
}
#ifdef ILI_SENSOR_EN
if (ilits->should_enable_gesture) {
ili_switch_tp_mode(P5_X_FW_GESTURE_MODE);
enable_irq_wake(ilits->irq_num);
ili_irq_enable();
ilits->wakeable = true;
} else {
if (ili_ic_func_ctrl("sleep", SLEEP_IN) < 0)
ILI_ERR("Write sleep in cmd failed\n");
ilits->wakeable = false;
}
#else
if (ilits->gesture) {
ili_switch_tp_mode(P5_X_FW_GESTURE_MODE);
enable_irq_wake(ilits->irq_num);
@ -415,6 +427,7 @@ int ili_sleep_handler(int mode)
if (ili_ic_func_ctrl("sleep", SLEEP_IN) < 0)
ILI_ERR("Write sleep in cmd failed\n");
}
#endif
ILI_INFO("TP suspend end\n");
ilits->tp_suspend = true;
break;
@ -458,6 +471,13 @@ int ili_sleep_handler(int mode)
ili_wq_ctrl(WQ_ESD, ENABLE);
ili_wq_ctrl(WQ_BAT, ENABLE);
ilits->tp_suspend = false;
#ifdef ILI_SENSOR_EN
if (ilits->wakeable) {
disable_irq_wake(ilits->irq_num);
ilits->gesture_enabled = false;
ilits->wakeable = false;
}
#endif
ILI_INFO("TP resume end\n");
#endif
ili_irq_enable();

View file

@ -106,6 +106,13 @@
#include <linux/msm_drm_notify.h>
#endif
#ifdef ILI_SENSOR_EN
#include <linux/sensors.h>
#endif
#ifdef ILI_CONFIG_PANEL_NOTIFICATIONS
#include <linux/panel_notifier.h>
#endif
#define DRIVER_VERSION "3.0.2.0.200512"
/* Options */
@ -128,7 +135,11 @@
#define MT_PRESSURE DISABLE
#define ENABLE_WQ_ESD DISABLE
#define ENABLE_WQ_BAT DISABLE
#ifdef ILI_SENSOR_EN
#define ENABLE_GESTURE ENABLE
#else
#define ENABLE_GESTURE DISABLE
#endif
#define REGULATOR_POWER DISABLE
#define TP_SUSPEND_PRIO ENABLE
#define RESUME_BY_DDI DISABLE
@ -732,6 +743,23 @@ struct gesture_symbol {
#define TDDI_CHIP_RESET_ADDR 0x40050
#define RAWDATA_NO_BK_SHIFT 8192
#ifdef ILI_SENSOR_EN
/* display state */
enum display_state {
SCREEN_UNKNOWN,
SCREEN_OFF,
SCREEN_ON,
};
struct ili_sensor_platform_data {
struct input_dev *input_sensor_dev;
struct sensors_classdev ps_cdev;
int sensor_opened;
char sensor_data; /* 0 near, 1 far */
struct ilitek_ts_data *data;
};
#define REPORT_MAX_COUNT 10000
#endif
struct ilitek_ts_data {
struct i2c_client *i2c;
struct spi_device *spi;
@ -752,6 +780,10 @@ struct ilitek_ts_data {
struct early_suspend early_suspend;
#endif
#ifdef ILI_CONFIG_PANEL_NOTIFICATIONS
struct notifier_block panel_notif;
#endif
struct mutex touch_mutex;
struct mutex debug_mutex;
struct mutex debug_read_mutex;
@ -870,6 +902,21 @@ struct ilitek_ts_data {
atomic_t cmd_int_check;
atomic_t esd_stat;
#ifdef ILI_SENSOR_EN
bool wakeable;
bool should_enable_gesture;
bool gesture_enabled;
uint32_t report_gesture_key;
enum display_state screen_state;
struct mutex state_mutex;
struct ili_sensor_platform_data *sensor_pdata;
#ifdef CONFIG_HAS_WAKELOCK
struct wake_lock gesture_wakelock;
#else
struct wakeup_source gesture_wakelock;
#endif
#endif
/* Event for driver test */
struct completion esd_done;

View file

@ -22,6 +22,45 @@
#include "ilitek.h"
#ifdef ILI_CONFIG_PANEL_NOTIFICATIONS
#define register_panel_notifier panel_register_notifier
#define unregister_panel_notifier panel_unregister_notifier
enum touch_state {
TOUCH_DEEP_SLEEP_STATE = 0,
TOUCH_LOW_POWER_STATE,
};
#else
#define register_panel_notifier(...) rc
#define unregister_panel_notifier(...) rc
#endif
#ifdef ILI_SENSOR_EN
static struct sensors_classdev __maybe_unused sensors_touch_cdev = {
.name = "dt-gesture",
.vendor = "ilitek",
.version = 1,
.type = SENSOR_TYPE_MOTO_DOUBLE_TAP,
.max_range = "5.0",
.resolution = "5.0",
.sensor_power = "1",
.min_delay = 0,
.max_delay = 0,
/* WAKE_UP & SPECIAL_REPORT */
.flags = 1 | 6,
.fifo_reserved_event_count = 0,
.fifo_max_event_count = 0,
.enabled = 0,
.delay_msec = 200,
.sensors_enable = NULL,
.sensors_poll_delay = NULL,
};
#endif
#ifdef ILI_CONFIG_PANEL_NOTIFICATIONS
static int ili_panel_notifier_callback(struct notifier_block *self, unsigned long event, void *data);
#endif
#define DTS_INT_GPIO "touch,irq-gpio"
#define DTS_RESET_GPIO "touch,reset-gpio"
#define DTS_OF_NAME "tchip,ilitek"
@ -546,6 +585,135 @@ static void ilitek_plat_late_resume(struct early_suspend *h)
}
#endif
#ifdef ILI_SENSOR_EN
static int ili_sensor_set_enable(struct sensors_classdev *sensors_cdev,
unsigned int enable)
{
ILI_INFO("Gesture set enable %d!", enable);
mutex_lock(&ilits->state_mutex);
if (enable == 1) {
ilits->should_enable_gesture = true;
} else if (enable == 0) {
ilits->should_enable_gesture = false;
} else {
ILI_INFO("unknown enable symbol\n");
}
mutex_unlock(&ilits->state_mutex);
return 0;
}
static int ili_sensor_init(struct ilitek_ts_data *data)
{
struct ili_sensor_platform_data *sensor_pdata;
struct input_dev *sensor_input_dev;
int err;
sensor_input_dev = input_allocate_device();
if (!sensor_input_dev) {
ILI_ERR("Failed to allocate device");
goto exit;
}
sensor_pdata = devm_kzalloc(&sensor_input_dev->dev,
sizeof(struct ili_sensor_platform_data),
GFP_KERNEL);
if (!sensor_pdata) {
ILI_ERR("Failed to allocate memory");
goto free_sensor_pdata;
}
data->sensor_pdata = sensor_pdata;
if (data->report_gesture_key) {
__set_bit(EV_KEY, sensor_input_dev->evbit);
__set_bit(KEY_F1, sensor_input_dev->keybit);
} else {
__set_bit(EV_ABS, sensor_input_dev->evbit);
input_set_abs_params(sensor_input_dev, ABS_DISTANCE,
0, REPORT_MAX_COUNT, 0, 0);
}
__set_bit(EV_SYN, sensor_input_dev->evbit);
sensor_input_dev->name = "double-tap";
data->sensor_pdata->input_sensor_dev = sensor_input_dev;
err = input_register_device(sensor_input_dev);
if (err) {
ILI_ERR("Unable to register device, err=%d", err);
goto free_sensor_input_dev;
}
sensor_pdata->ps_cdev = sensors_touch_cdev;
sensor_pdata->ps_cdev.sensors_enable = ili_sensor_set_enable;
sensor_pdata->data = data;
err = sensors_classdev_register(&sensor_input_dev->dev,
&sensor_pdata->ps_cdev);
if (err)
goto unregister_sensor_input_device;
return 0;
unregister_sensor_input_device:
input_unregister_device(data->sensor_pdata->input_sensor_dev);
free_sensor_input_dev:
input_free_device(data->sensor_pdata->input_sensor_dev);
free_sensor_pdata:
devm_kfree(&sensor_input_dev->dev, sensor_pdata);
data->sensor_pdata = NULL;
exit:
return 1;
}
int ili_sensor_remove(struct ilitek_ts_data *data)
{
sensors_classdev_unregister(&data->sensor_pdata->ps_cdev);
input_unregister_device(data->sensor_pdata->input_sensor_dev);
devm_kfree(&data->sensor_pdata->input_sensor_dev->dev,
data->sensor_pdata);
data->sensor_pdata = NULL;
data->wakeable = false;
data->should_enable_gesture = false;
return 0;
}
#endif
#ifdef ILI_CONFIG_PANEL_NOTIFICATIONS
static int ili_panel_notifier_callback(struct notifier_block *self, unsigned long event, void *data)
{
#ifdef ILI_SENSOR_EN
struct ilitek_ts_data *ts =
container_of(self, struct ilitek_ts_data, panel_notif);
#endif
switch (event) {
case PANEL_EVENT_PRE_DISPLAY_OFF:
ILI_INFO("event=%lu\n", event);
if (ili_sleep_handler(TP_SUSPEND) < 0)
ILI_ERR("TP suspend failed\n");
#ifdef ILI_SENSOR_EN
if (ts->should_enable_gesture) {
ILI_INFO("double tap gesture suspend\n");
touch_set_state(TOUCH_LOW_POWER_STATE, TOUCH_PANEL_IDX_PRIMARY);
} else {
touch_set_state(TOUCH_DEEP_SLEEP_STATE, TOUCH_PANEL_IDX_PRIMARY);
}
#endif
break;
case PANEL_EVENT_DISPLAY_ON:
ILI_INFO("event=%lu\n", event);
if (ili_sleep_handler(TP_RESUME) < 0)
ILI_ERR("TP resume failed\n");
break;
default: /* use DEV_TS here to avoid unused variable */
ILI_INFO("%s: function not implemented event %lu\n", __func__, event);
break;
}
return 0;
}
#endif
static void ilitek_plat_sleep_init(void)
{
int ret;
@ -576,6 +744,13 @@ static void ilitek_plat_sleep_init(void)
}
#endif
#endif/* CONFIG_DRM */
#ifdef ILI_CONFIG_PANEL_NOTIFICATIONS
ilits->panel_notif.notifier_call = ili_panel_notifier_callback;
ret = register_panel_notifier(&ilits->panel_notif);
if(ret) {
ILI_ERR("register panel_notifier failed. ret=%d\n", ret);
}
#endif
#if defined(CONFIG_HAS_EARLYSUSPEND)
ILI_ERR("Init eqarly_suspend struct\n");
ilits->early_suspend.suspend = ilitek_plat_early_suspend;
@ -607,6 +782,14 @@ static int ilitek_plat_gpio_register(void)
return err;
}
#endif
#endif
#ifdef ILI_SENSOR_EN
if (of_property_read_bool(dev_node, "ilitek,report_gesture_key")) {
ILI_INFO("ilitek,report_gesture_key set");
ilits->report_gesture_key = 1;
} else {
ilits->report_gesture_key = 0;
}
#endif
ilits->tp_int = of_get_named_gpio_flags(dev_node, DTS_INT_GPIO, 0, &flag);
ilits->tp_rst = of_get_named_gpio_flags(dev_node, DTS_RESET_GPIO, 0, &flag);
@ -653,6 +836,9 @@ out:
static int ilitek_plat_probe(void)
{
#ifdef ILI_SENSOR_EN
static bool initialized_sensor;
#endif
ILI_INFO("platform probe\n");
#if REGULATOR_POWER
@ -675,6 +861,20 @@ static int ilitek_plat_probe(void)
ilitek_plat_sleep_init();
ilits->pm_suspend = false;
init_completion(&ilits->pm_completion);
#ifdef ILI_SENSOR_EN
mutex_init(&ilits->state_mutex);
//unknown screen state
ilits->screen_state = SCREEN_UNKNOWN;
if (!initialized_sensor) {
#ifdef CONFIG_HAS_WAKELOCK
wake_lock_init(&(ilits->gesture_wakelock), WAKE_LOCK_SUSPEND, "dt-wake-lock");
#else
wakeup_source_init(&(ilits->gesture_wakelock), "dt-wake-lock");
#endif
if (!ili_sensor_init(ilits))
initialized_sensor = true;
}
#endif
ILI_INFO("ILITEK Driver loaded successfully!");
return 0;
}

View file

@ -1100,8 +1100,13 @@ void ili_report_gesture_mode(u8 *buf, int len)
int i, lu_x = 0, lu_y = 0, rd_x = 0, rd_y = 0, score = 0;
u8 ges[P5_X_GESTURE_INFO_LENGTH] = {0};
struct gesture_coordinate *gc = ilits->gcoord;
#ifndef ILI_SENSOR_EN
struct input_dev *input = ilits->input;
#endif
bool transfer = ilits->trans_xy;
#ifdef ILI_SENSOR_EN
static int report_cnt = 0;
#endif
for (i = 0; i < len; i++)
ges[i] = buf[i];
@ -1129,10 +1134,38 @@ void ili_report_gesture_mode(u8 *buf, int len)
switch (gc->code) {
case GESTURE_DOUBLECLICK:
ILI_INFO("Double Click key event\n");
#ifdef ILI_SENSOR_EN
if (!(ilits->wakeable && ilits->should_enable_gesture)) {
ILI_INFO("Gesture got but wakeable not set. Skip this gesture.");
return;
}
if (ilits->report_gesture_key) {
input_report_key(ilits->sensor_pdata->input_sensor_dev, KEY_F1, 1);
input_sync(ilits->sensor_pdata->input_sensor_dev);
input_report_key(ilits->sensor_pdata->input_sensor_dev, KEY_F1, 0);
input_sync(ilits->sensor_pdata->input_sensor_dev);
++report_cnt;
} else {
input_report_abs(ilits->sensor_pdata->input_sensor_dev,
ABS_DISTANCE,
++report_cnt);
input_sync(ilits->sensor_pdata->input_sensor_dev);
}
ILI_INFO("input report: %d", report_cnt);
if (report_cnt >= REPORT_MAX_COUNT) {
report_cnt = 0;
}
#ifdef CONFIG_HAS_WAKELOCK
wake_lock_timeout(&(ilits->gesture_wakelock), msecs_to_jiffies(5000));
#else
__pm_wakeup_event(&(ilits->gesture_wakelock), 5000);
#endif
#else
input_report_key(input, KEY_GESTURE_POWER, 1);
input_sync(input);
input_report_key(input, KEY_GESTURE_POWER, 0);
input_sync(input);
#endif
gc->type = GESTURE_DOUBLECLICK;
gc->clockwise = 1;
gc->pos_end.x = gc->pos_start.x;