mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-08 12:58:12 -04:00
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:
parent
60f7e4400e
commit
ceba7f61ed
6 changed files with 315 additions and 0 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in a new issue