diff --git a/drivers/input/touchscreen/goodix_berlin_mmi/Android.mk b/drivers/input/touchscreen/goodix_berlin_mmi/Android.mk index 06a0dd009eb6..9abbb250c8d4 100644 --- a/drivers/input/touchscreen/goodix_berlin_mmi/Android.mk +++ b/drivers/input/touchscreen/goodix_berlin_mmi/Android.mk @@ -49,6 +49,10 @@ ifeq ($(BOARD_USES_DOUBLE_TAP_CTRL),true) KBUILD_OPTIONS += CONFIG_BOARD_USES_DOUBLE_TAP_CTRL=y endif +ifneq ($(GTP_ENABLE_TOUCH_PALM),) + KBUILD_OPTIONS += CONFIG_INPUT_GOODIX_MMI_ENABLE_PALM=y +endif + include $(CLEAR_VARS) LOCAL_MODULE := goodix_brl_mmi.ko LOCAL_MODULE_TAGS := optional diff --git a/drivers/input/touchscreen/goodix_berlin_mmi/Kbuild b/drivers/input/touchscreen/goodix_berlin_mmi/Kbuild index 014e87f0f96a..b57c1851ba73 100644 --- a/drivers/input/touchscreen/goodix_berlin_mmi/Kbuild +++ b/drivers/input/touchscreen/goodix_berlin_mmi/Kbuild @@ -69,6 +69,10 @@ ifneq ($(filter m y, $(CONFIG_BOARD_USES_DOUBLE_TAP_CTRL)),) EXTRA_CFLAGS += -DCONFIG_BOARD_USES_DOUBLE_TAP_CTRL endif +ifneq ($(filter m y,$(CONFIG_INPUT_GOODIX_MMI_ENABLE_PALM)),) + EXTRA_CFLAGS += -DGOODIX_PALM_SENSOR_EN +endif + ifneq ($(findstring _factory,$(TARGET_PRODUCT)),) USE_TARGET_PRODUCT := $(strip $(subst _factory,, $(TARGET_PRODUCT))) else diff --git a/drivers/input/touchscreen/goodix_berlin_mmi/goodix_brl_hw.c b/drivers/input/touchscreen/goodix_berlin_mmi/goodix_brl_hw.c index e2d9d0eced36..892847fe2ae7 100644 --- a/drivers/input/touchscreen/goodix_berlin_mmi/goodix_brl_hw.c +++ b/drivers/input/touchscreen/goodix_berlin_mmi/goodix_brl_hw.c @@ -1103,6 +1103,9 @@ static int goodix_touch_handler(struct goodix_ts_core *cd, static int pre_flags = 0; #endif int underwater_flag = 0; +#ifdef GOODIX_PALM_SENSOR_EN + int palm_flag = 0; +#endif /* clean event buffer */ memset(ts_event, 0, sizeof(*ts_event)); /* copy pre-data to buffer */ @@ -1118,6 +1121,23 @@ static int goodix_touch_handler(struct goodix_ts_core *cd, } } +#ifdef GOODIX_PALM_SENSOR_EN + if (cd->set_mode.palm_detection) { + palm_flag = buffer[2] & GOODIX_GESTURE_PALM_DETECTION; + if (palm_flag) { + mod_timer(&cd->palm_release_timer, + jiffies + msecs_to_jiffies(cd->palm_release_delay_ms)); + } + if (atomic_read(&cd->palm_status) != palm_flag) { + atomic_set(&cd->palm_status, palm_flag); + /* call class method */ + if (cd->imports && cd->imports->report_palm) + cd->imports->report_palm(palm_flag); + ts_info("palm detection flag changed to: 0x%x\n", palm_flag); + } + } +#endif + touch_num = buffer[2] & 0x0F; if (touch_num > GOODIX_MAX_TOUCH) { diff --git a/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_core.c b/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_core.c index 30467a11c28f..e365eeed242e 100644 --- a/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_core.c +++ b/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_core.c @@ -2385,6 +2385,19 @@ static int goodix_start_later_init(struct goodix_ts_core *ts_core) return 0; } +#ifdef GOODIX_PALM_SENSOR_EN +static void goodix_palm_sensor_release_timer_handler(struct timer_list *t) +{ + struct goodix_ts_core *cd = from_timer(cd, t, palm_release_timer); + + if (cd->imports && cd->imports->report_palm && atomic_read(&cd->palm_status)) { + cd->imports->report_palm(false); + ts_info("palm report far"); + atomic_set(&cd->palm_status, 0); + } +} +#endif + /** * goodix_ts_probe - called by kernel when Goodix touch * platform driver is added. @@ -2527,6 +2540,11 @@ static int goodix_ts_probe(struct platform_device *pdev) goto err_register_gesture_wakelock; } +#ifdef GOODIX_PALM_SENSOR_EN + timer_setup(&core_data->palm_release_timer, goodix_palm_sensor_release_timer_handler, 0); + core_data->palm_release_delay_ms = GOODIX_PALM_RELEASE_DELAY_MS; +#endif + ts_info("goodix_ts_core probe success"); return 0; diff --git a/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_core.h b/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_core.h index e0afb2de8881..88d6b067d4a2 100644 --- a/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_core.h +++ b/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_core.h @@ -46,6 +46,8 @@ #define GOODIX_NORMAL_RESET_DELAY_MS 100 #define GOODIX_HOLD_CPU_RESET_DELAY_MS 5 +#define GOODIX_PALM_RELEASE_DELAY_MS 200 + #define GOODIX_RETRY_3 3 #define GOODIX_RETRY_5 5 @@ -64,6 +66,7 @@ #define GOODIX_GESTURE_FOD_DOWN 0x46 #define GOODIX_GESTURE_FOD_UP 0x55 #define GOODIX_GESTURE_UNDER_WATER 0x20 +#define GOODIX_GESTURE_PALM_DETECTION 0x40 enum GOODIX_GESTURE_TYP { GESTURE_SINGLE_TAP = (1 << 0), @@ -491,6 +494,9 @@ struct goodix_mode_info { int report_rate_mode; int edge_mode[2]; int liquid_detection; +#ifdef GOODIX_PALM_SENSOR_EN + int palm_detection; +#endif }; struct goodix_ts_core { @@ -520,6 +526,11 @@ struct goodix_ts_core { int irq; size_t irq_trig_cnt; int liquid_status; +#ifdef GOODIX_PALM_SENSOR_EN + atomic_t palm_status; + struct timer_list palm_release_timer; + unsigned int palm_release_delay_ms; +#endif atomic_t irq_enabled; atomic_t suspended; diff --git a/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_gesture.c b/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_gesture.c index bf8794fdfe74..5fd8f69dcc14 100644 --- a/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_gesture.c +++ b/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_gesture.c @@ -227,6 +227,9 @@ 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 ret; +#ifdef GOODIX_PALM_SENSOR_EN + int palm_flag = 0; +#endif if (atomic_read(&cd->suspended) == 0) return EVT_CONTINUE; @@ -257,6 +260,24 @@ static int gsx_gesture_ist(struct goodix_ts_core *cd, gs_event.gesture_type)) { gsx_gesture->gesture_data = gs_event.gesture_type; #if defined(CONFIG_INPUT_TOUCHSCREEN_MMI) +#ifdef GOODIX_PALM_SENSOR_EN + if (cd->set_mode.palm_detection) { + palm_flag = gs_event.gesture_report_info & GOODIX_GESTURE_PALM_DETECTION; + if (palm_flag) { + mod_timer(&cd->palm_release_timer, + jiffies + msecs_to_jiffies(cd->palm_release_delay_ms)); + } + if (atomic_read(&cd->palm_status) != palm_flag) { + atomic_set(&cd->palm_status, palm_flag); + /* call class method */ + if (cd->imports && cd->imports->report_palm) + cd->imports->report_palm(palm_flag); + ts_info("palm detection flag changed to: 0x%x\n", palm_flag); + } + goto gesture_ist_exit; + } +#endif + if (cd->imports && cd->imports->report_gesture) { struct gesture_event_data mmi_event; @@ -274,7 +295,7 @@ static int gsx_gesture_ist(struct goodix_ts_core *cd, PM_WAKEUP_EVENT(cd->gesture_wakelock, 3000); goto gesture_ist_exit; } -#endif +#else /* do resume routine */ ts_info("got valid gesture type 0x%x", gs_event.gesture_type); @@ -283,12 +304,18 @@ static int gsx_gesture_ist(struct goodix_ts_core *cd, input_report_key(cd->input_dev, KEY_POWER, 0); input_sync(cd->input_dev); goto gesture_ist_exit; +#endif } else { ts_info("unsupported gesture:%x", gs_event.gesture_type); } re_send_ges_cmd: +#if defined(CONFIG_BOARD_USES_DOUBLE_TAP_CTRL) + if (goodix_ts_send_cmd(cd, ENTER_GESTURE_MODE_CMD, 6, (cd->gesture_cmd) >> 8, + cd->gesture_cmd & 0xFF) < 0) +#else if (hw_ops->gesture(cd, 0)) +#endif ts_info("warning: failed re_send gesture cmd"); gesture_ist_exit: if (!cd->tools_ctrl_sync) diff --git a/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_mmi.c b/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_mmi.c index b9035a449586..ee21d44599c8 100644 --- a/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_mmi.c +++ b/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_mmi.c @@ -934,6 +934,14 @@ static int goodix_ts_mmi_panel_state(struct device *dev, if (core_data->imports && core_data->imports->get_gesture_type) { ret = core_data->imports->get_gesture_type(core_data->bus->dev, &gesture_type); } +#ifdef GOODIX_PALM_SENSOR_EN + if (gesture_type & TS_MMI_GESTURE_PALM) { + //override previous setting + gesture_cmd = 0xFFFF; + ts_info("enable palm gesture mode cmd 0x%04x\n", gesture_cmd); + goto palm_detection; + } +#endif if (gesture_type & TS_MMI_GESTURE_ZERO) { gesture_cmd &= ~(1 << 5); ts_info("enable zero gesture mode cmd 0x%04x\n", gesture_cmd); @@ -947,6 +955,9 @@ static int goodix_ts_mmi_panel_state(struct device *dev, ts_info("enable double gesture mode cmd 0x%04x\n", gesture_cmd); } +#ifdef GOODIX_PALM_SENSOR_EN +palm_detection: +#endif ret = goodix_ts_send_cmd(core_data, ENTER_GESTURE_MODE_CMD, 6, 0xFF, 0xFF); if (ret < 0) { ts_err("Failed to send enter gesture mode\n"); @@ -1100,6 +1111,18 @@ static int goodix_ts_mmi_post_resume(struct device *dev) { ts_info("Success to %d liquid detection mode\n", core_data->get_mode.liquid_detection); } } + +#ifdef GOODIX_PALM_SENSOR_EN + if (core_data->get_mode.palm_detection) { + ret = goodix_ts_send_cmd(core_data, PALM_DETECTION_SWITCH_CMD, 5, + core_data->get_mode.palm_detection, 0x00); + if (!ret) { + core_data->set_mode.palm_detection = core_data->get_mode.palm_detection; + msleep(20); + ts_info("Success to %d palm detection mode\n", core_data->get_mode.palm_detection); + } + } +#endif mutex_unlock(&core_data->mode_lock); #ifdef CONFIG_GTP_FOD if(core_data->zerotap_data[0]) { @@ -1120,6 +1143,12 @@ static int goodix_ts_mmi_pre_suspend(struct device *dev) { ts_info("Suspend start"); atomic_set(&core_data->suspended, 1); +#ifdef GOODIX_PALM_SENSOR_EN + if (core_data->set_mode.palm_detection) { + del_timer(&core_data->palm_release_timer); + } +#endif + if (core_data->board_data.stylus_mode_ctrl && core_data->set_mode.stylus_mode) { mutex_lock(&core_data->mode_lock); ret = goodix_stylus_mode(core_data, 0x00); @@ -1261,6 +1290,55 @@ static int goodix_ts_mmi_methods_get_active_region(struct device *dev, void *uid return 0; } +#ifdef GOODIX_PALM_SENSOR_EN +int goodix_ts_mmi_palm_set_enable(struct device *dev, unsigned int enable) +{ + int ret = 0; + struct platform_device *pdev; + struct goodix_ts_core *core_data; + + GET_GOODIX_DATA(dev); + + mutex_lock(&core_data->mode_lock); + core_data->get_mode.palm_detection= enable; + if (core_data->set_mode.palm_detection == enable) { + ts_info("The value = %d is same, so not to write", enable); + goto exit; + } + + if (core_data->power_on == 0) { + ts_info("The touch is in sleep state, restore the value when resume\n"); + goto exit; + } + + //clear palm status before enable detection + if (enable) + atomic_set(&core_data->palm_status, 0); + else { + if (core_data->imports && core_data->imports->report_palm) { + core_data->imports->report_palm(0); + ts_info("Disable palm detection, report far\n"); + } + del_timer(&core_data->palm_release_timer); + } + + ret = goodix_ts_send_cmd(core_data, PALM_DETECTION_SWITCH_CMD, 5, + core_data->get_mode.palm_detection, 0x00); + if (ret < 0) { + ts_err("failed to set palm detection, enable = %d", enable); + goto exit; + } + + core_data->set_mode.palm_detection = enable; + msleep(20); + ts_info("Success set palm detection to %d\n", enable); + +exit: + mutex_unlock(&core_data->mode_lock); + return ret; +} +#endif + static struct ts_mmi_methods goodix_ts_mmi_methods = { .get_vendor = goodix_ts_mmi_methods_get_vendor, .get_productinfo = goodix_ts_mmi_methods_get_productinfo, @@ -1280,6 +1358,9 @@ static struct ts_mmi_methods goodix_ts_mmi_methods = { .refresh_rate = goodix_ts_mmi_refresh_rate, .active_region = goodix_ts_mmi_active_region, .update_liquid_detect_mode = goodix_ts_mmi_update_liquid_detect_mode, +#ifdef GOODIX_PALM_SENSOR_EN + .palm_set_enable = goodix_ts_mmi_palm_set_enable, +#endif /* Firmware */ .firmware_update = goodix_ts_firmware_update, /* vendor specific attribute group */ diff --git a/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_mmi.h b/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_mmi.h index 1b2e95e288f6..6021e4b99d58 100644 --- a/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_mmi.h +++ b/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_mmi.h @@ -58,4 +58,5 @@ int goodix_ts_send_cmd(struct goodix_ts_core *core_data, #define SAMPLE_SWITCH_CMD 0xC2 #define ENTER_GESTURE_MODE_CMD 0xA6 #define LIQUID_DETECTION_SWITCH_CMD 0x33 +#define PALM_DETECTION_SWITCH_CMD 0x93 #endif diff --git a/drivers/input/touchscreen/touchscreen_mmi/touchscreen_mmi_gesture.c b/drivers/input/touchscreen/touchscreen_mmi/touchscreen_mmi_gesture.c index 4e6277bcc88f..e90d6fde32c5 100644 --- a/drivers/input/touchscreen/touchscreen_mmi/touchscreen_mmi_gesture.c +++ b/drivers/input/touchscreen/touchscreen_mmi/touchscreen_mmi_gesture.c @@ -452,14 +452,19 @@ static int ts_mmi_palm_set_enable(struct sensors_classdev *sensors_cdev, struct ts_mmi_dev *touch_cdev = sensor_pdata->touch_cdev; int ret = 0; + mutex_lock(&touch_cdev->extif_mutex); TRY_TO_CALL(palm_set_enable, enable); if (enable == 1) { + touch_cdev->gesture_mode_type |= 0x08; dev_info(DEV_TS, "%s: sensor ENABLE\n", __func__); } else if (enable == 0) { + touch_cdev->gesture_mode_type &= 0xF7; dev_info(DEV_TS, "%s: sensor DISABLE\n", __func__); } else { dev_err(DEV_TS, "%s: unknown enable symbol\n", __func__); } + mutex_unlock(&touch_cdev->extif_mutex); + return 0; } diff --git a/drivers/input/touchscreen/touchscreen_mmi/touchscreen_mmi_notif.c b/drivers/input/touchscreen/touchscreen_mmi/touchscreen_mmi_notif.c index 7de25f9fb981..f6f6892ddc1d 100644 --- a/drivers/input/touchscreen/touchscreen_mmi/touchscreen_mmi_notif.c +++ b/drivers/input/touchscreen/touchscreen_mmi/touchscreen_mmi_notif.c @@ -51,7 +51,7 @@ static int ts_mmi_panel_off(struct ts_mmi_dev *touch_cdev) { TRY_TO_CALL(pre_suspend); if (touch_cdev->pdata.gestures_enabled || touch_cdev->pdata.cli_gestures_enabled || - touch_cdev->pdata.support_liquid_detection) { + touch_cdev->pdata.support_liquid_detection || touch_cdev->pdata.palm_enabled) { #if defined(CONFIG_BOARD_USES_DOUBLE_TAP_CTRL) if(touch_cdev->gesture_mode_type != 0 || touch_cdev->pdata.support_liquid_detection != 0) { dev_info(DEV_MMI, "%s: try to enter Gesture mode\n", __func__); diff --git a/include/linux/touchscreen_mmi.h b/include/linux/touchscreen_mmi.h index c306fa61b5c7..e41028daafe1 100644 --- a/include/linux/touchscreen_mmi.h +++ b/include/linux/touchscreen_mmi.h @@ -333,6 +333,7 @@ enum ts_mmi_work { #define TS_MMI_GESTURE_ZERO 0x01 #define TS_MMI_GESTURE_SINGLE 0x02 #define TS_MMI_GESTURE_DOUBLE 0x04 +#define TS_MMI_GESTURE_PALM 0x08 /** * struct touchscreen_mmi_methods - hold vendor provided functions