diff --git a/drivers/input/touchscreen/ili9882_mmi/Android.mk b/drivers/input/touchscreen/ili9882_mmi/Android.mk index f269c01061c8..53c3c2292172 100644 --- a/drivers/input/touchscreen/ili9882_mmi/Android.mk +++ b/drivers/input/touchscreen/ili9882_mmi/Android.mk @@ -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 diff --git a/drivers/input/touchscreen/ili9882_mmi/Kbuild b/drivers/input/touchscreen/ili9882_mmi/Kbuild index 5c32eee4a2e6..cd89d7a190e0 100644 --- a/drivers/input/touchscreen/ili9882_mmi/Kbuild +++ b/drivers/input/touchscreen/ili9882_mmi/Kbuild @@ -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 diff --git a/drivers/input/touchscreen/ili9882_mmi/ili9882.c b/drivers/input/touchscreen/ili9882_mmi/ili9882.c index 9c8b23539ff7..490453a9e0d9 100644 --- a/drivers/input/touchscreen/ili9882_mmi/ili9882.c +++ b/drivers/input/touchscreen/ili9882_mmi/ili9882.c @@ -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(); diff --git a/drivers/input/touchscreen/ili9882_mmi/ili9882.h b/drivers/input/touchscreen/ili9882_mmi/ili9882.h index e23818da9b53..49bb753d06a8 100755 --- a/drivers/input/touchscreen/ili9882_mmi/ili9882.h +++ b/drivers/input/touchscreen/ili9882_mmi/ili9882.h @@ -100,6 +100,10 @@ #include #endif +#ifdef ILI_SENSOR_EN +#include +#endif + #ifdef CONFIG_DRM #include #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) { diff --git a/drivers/input/touchscreen/ili9882_mmi/ili9882_qcom.c b/drivers/input/touchscreen/ili9882_mmi/ili9882_qcom.c index dee9275e6a0f..2421584ffef6 100755 --- a/drivers/input/touchscreen/ili9882_mmi/ili9882_qcom.c +++ b/drivers/input/touchscreen/ili9882_mmi/ili9882_qcom.c @@ -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; } diff --git a/drivers/input/touchscreen/ili9882_mmi/ili9882_spi.c b/drivers/input/touchscreen/ili9882_mmi/ili9882_spi.c index 6258de40b5d6..a907d75b46e7 100755 --- a/drivers/input/touchscreen/ili9882_mmi/ili9882_spi.c +++ b/drivers/input/touchscreen/ili9882_mmi/ili9882_spi.c @@ -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) { diff --git a/drivers/input/touchscreen/ili9882_mmi/ili9882_touch.c b/drivers/input/touchscreen/ili9882_mmi/ili9882_touch.c index 7fa99033547e..e65b578f72a4 100755 --- a/drivers/input/touchscreen/ili9882_mmi/ili9882_touch.c +++ b/drivers/input/touchscreen/ili9882_mmi/ili9882_touch.c @@ -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;