dlkm: bo: Support single tap feature for ili9882_mmi

- Add support single tap feature for ili9882_mmi.
- Resume will use workqueue.

Change-Id: I65c4685e09650fe0f2ba92526ea01a8acf4c0af7
Signed-off-by: wengjun1 <wengjun1@motorola.com>
Reviewed-on: https://gerrit.mot.com/1970382
SME-Granted: SME Approvals Granted
SLTApproved: Slta Waiver
Tested-by: Jira Key
Reviewed-by: Huosheng Liao <liaohs@motorola.com>
Submit-Approved: Jira Key
This commit is contained in:
wengjun1 2021-06-04 18:17:03 +08:00 • committed by Jun Weng
commit 55917fa672
7 changed files with 288 additions and 4 deletions

View file

@ -9,6 +9,10 @@ ifneq ($(BOARD_USES_PANEL_NOTIFICATIONS),)
KERNEL_CFLAGS += CONFIG_INPUT_ILI_PANEL_NOTIFICATIONS=y
endif
ifneq ($(MOTO_PANEL_CHECK_TOUCH_STATE),)
KERNEL_CFLAGS += CONFIG_INPUT_ILI_0FLASH_MMI_NOTIFY_TOUCH_STATE=y
endif
ifneq ($(DL_FW_BY_DISPLAY),)
KERNEL_CFLAGS += CONFIG_ILITEK_RESUME_BY_DDI=y
endif

View file

@ -10,7 +10,13 @@ endif
ifneq ($(filter m y,$(CONFIG_INPUT_ILI_0FLASH_MMI_ENABLE_DOUBLE_TAP)),)
EXTRA_CFLAGS += -DILI_SENSOR_EN
KBUILD_EXTRA_SYMBOLS += $(CURDIR)/$(KBUILD_EXTMOD)/../../../sensors/$(GKI_OBJ_MODULE_DIR)/Module.symvers
endif
ifneq ($(filter m y,$(CONFIG_INPUT_ILI_0FLASH_MMI_NOTIFY_TOUCH_STATE)),)
EXTRA_CFLAGS += -DILI_SET_TOUCH_STATE
endif
ifneq ($(filter m y,$(CONFIG_INPUT_ILI_PANEL_NOTIFICATIONS)),)
EXTRA_CFLAGS += -DILI_CONFIG_PANEL_NOTIFICATIONS
endif

View file

@ -40,8 +40,16 @@ static void ilitek_resume_by_ddi_work(struct work_struct *work)
{
mutex_lock(&ilits->touch_mutex);
#ifdef ILI_SENSOR_EN
if (ilits->wakeable) {
disable_irq_wake(ilits->irq_num);
ilits->gesture_enabled = false;
ilits->wakeable = false;
}
#else
if (ilits->gesture)
disable_irq_wake(ilits->irq_num);
#endif
/* Set tp as demo mode and reload code if it's iram. */
ilits->actual_tp_mode = P5_X_FW_AP_MODE;
@ -491,6 +499,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", DEEP_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);
@ -500,6 +520,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;
@ -512,12 +533,14 @@ int ili_sleep_handler(int mode)
if (ili_ic_check_busy(50, 20) < 0)
ILI_ERR("Check busy timeout during deep suspend\n");
}
#ifndef ILI_SENSOR_EN
if (ilits->gesture) {
ili_switch_tp_mode(P5_X_FW_GESTURE_MODE);
enable_irq_wake(ilits->irq_num);
ili_irq_enable();
} else {
} else
#endif
{
ili_pinctrl_select_suspend(ilits);
if (ili_ic_func_ctrl("sleep", DEEP_SLEEP_IN) < 0)
ILI_ERR("Write deep sleep in cmd failed\n");
@ -547,6 +570,13 @@ int ili_sleep_handler(int mode)
ili_wq_ctrl(WQ_ESD, ENABLE);
ili_wq_ctrl(WQ_BAT, ENABLE);
#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");
#else
ili_resume_by_ddi();

View file

@ -100,6 +100,10 @@
#include <linux/msm_drm_notify.h>
#endif
#ifdef ILI_SENSOR_EN
#include <linux/sensors.h>
#endif
#ifdef CONFIG_DRM
#include <drm/drm_panel.h>
#endif
@ -137,7 +141,7 @@
#define ENABLE_WQ_ESD DISABLE
#endif
#define ENABLE_WQ_BAT DISABLE
#if defined(ILI_CONFIG_GESTURE) || defined(ILI_CONFIG_PANEL_GESTURE)
#if defined(ILI_CONFIG_GESTURE) || defined(ILI_CONFIG_PANEL_GESTURE) || defined(ILI_SENSOR_EN)
#define ENABLE_GESTURE ENABLE
#else
#define ENABLE_GESTURE DISABLE
@ -786,6 +790,31 @@ struct report_info_block {
#define TDDI_CHIP_RESET_ADDR 0x40050
#define RAWDATA_NO_BK_SHIFT 8192
#ifdef ILI_SET_TOUCH_STATE
#define MAX_PANEL_IDX 2
enum touch_panel_id {
TOUCH_PANEL_IDX_PRIMARY = 0,
TOUCH_PANEL_MAX_IDX,
};
#endif
#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;
@ -935,6 +964,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;
@ -1149,6 +1193,11 @@ extern int ili_get_tp_recore_data(void);
extern void ili_demo_debug_info_mode(u8 *buf, size_t rlen);
extern void ili_demo_debug_info_id0(u8 *buf, size_t len);
#ifdef ILI_SET_TOUCH_STATE
int touch_set_state(int state, int panel_idx);
int check_touch_state(int *state, int panel_idx);
#endif
static inline void ipio_kfree(void **mem)
{
if (*mem != NULL) {

View file

@ -30,6 +30,30 @@ enum touch_state {
TOUCH_LOW_POWER_STATE,
};
#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
void ili_tp_reset(void)
{
ILI_INFO("edge delay = %d\n", ilits->rst_edge_delay);
@ -422,6 +446,10 @@ static int ilitek_plat_notifier_fb(struct notifier_block *self, unsigned long ev
{
int *blank;
struct drm_panel_notifier *evdata = data;
#if defined(ILI_SENSOR_EN) && defined(ILI_SET_TOUCH_STATE)
struct ilitek_ts_data *ts =
container_of(self, struct ilitek_ts_data, notifier_fb);
#endif
ILI_INFO("Notifier's event = %ld\n", event);
@ -457,6 +485,17 @@ static int ilitek_plat_notifier_fb(struct notifier_block *self, unsigned long ev
else
ILI_INFO("TP in deep sleep!\n");
}
#elif defined(ILI_SENSOR_EN) && defined(ILI_SET_TOUCH_STATE)
if (ts->should_enable_gesture) {
ILI_INFO("double tap gesture suspend\n");
if (ili_sleep_handler(TP_SUSPEND) < 0)
ILI_ERR("TP suspend failed\n");
touch_set_state(TOUCH_LOW_POWER_STATE, TOUCH_PANEL_IDX_PRIMARY);
} else {
if (ili_sleep_handler(TP_DEEP_SLEEP) < 0)
ILI_ERR("TP deep sleep in failed\n");
touch_set_state(TOUCH_DEEP_SLEEP_STATE, TOUCH_PANEL_IDX_PRIMARY);
}
#else
if (ilits->tp_module == MODEL_TM) {
if (ili_sleep_handler(TP_DEEP_SLEEP) < 0)
@ -584,6 +623,98 @@ static void ilitek_plat_late_resume(struct early_suspend *h)
#endif
#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
static void ilitek_plat_sleep_init(void)
{
ILI_INFO("Init notifier_fb struct\n");
@ -693,6 +824,9 @@ void ilitek_plat_charger_init(void)
#endif
static int ilitek_plat_probe(void)
{
#ifdef ILI_SENSOR_EN
static bool initialized_sensor;
#endif
ILI_INFO("platform probe\n");
#if REGULATOR_POWER
@ -725,6 +859,26 @@ static int ilitek_plat_probe(void)
/* add_for_charger_end */
#endif
#endif
#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
PM_WAKEUP_REGISTER(ilits->dev, ilits->gesture_wakelock, "dt-wake-lock");
if (!ilits->gesture_wakelock) {
ILI_ERR("ILITEK Driver failed to load. wakeup_source_init failed.");
return -ENOMEM;
}
#endif
if (!ili_sensor_init(ilits))
initialized_sensor = true;
}
#endif
ILI_INFO("ILITEK Driver loaded successfully!");
return 0;
}

View file

@ -551,6 +551,15 @@ static int parse_dt(struct device_node *np)
{
int32_t ret = 0;
#ifdef ILI_SENSOR_EN
if (of_property_read_bool(np, "ilitek,report_gesture_key")) {
ILI_INFO("ilitek,report_gesture_key set");
ilits->report_gesture_key = 1;
} else {
ilits->report_gesture_key = 0;
}
#endif
#ifdef ILI_CONFIG_PANEL_GESTURE
//parse gesture by panel config
if (active_panel_name) {

View file

@ -1101,9 +1101,13 @@ void ili_report_gesture_mode(u8 *buf, int len)
int 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
ipio_memcpy(ges, buf, len, P5_X_GESTURE_INFO_LENGTH);
memset(gc, 0x0, sizeof(struct gesture_coordinate));
@ -1129,10 +1133,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;