diff --git a/drivers/input/touchscreen/himax_v2_mmi/Android.mk b/drivers/input/touchscreen/himax_v2_mmi/Android.mk index 4dcfb0f9cb07..d7c262af4192 100644 --- a/drivers/input/touchscreen/himax_v2_mmi/Android.mk +++ b/drivers/input/touchscreen/himax_v2_mmi/Android.mk @@ -10,6 +10,9 @@ endif ifeq ($(HIMAX_V2_MMI_0FLASH),true) KERNEL_CFLAGS += CONFIG_INPUT_TOUCHSCREEN_HIMAX_V2_MMI_0FLASH=y endif +ifneq ($(BOARD_USES_TOUCH_PALM),) + KERNEL_CFLAGS += CONFIG_INPUT_TOUCHSCREEN_HIMAX_V2_MMI_ENABLE_PALM=y +endif include $(CLEAR_VARS) LOCAL_MODULE := himax_v2_mmi.ko diff --git a/drivers/input/touchscreen/himax_v2_mmi/Kbuild b/drivers/input/touchscreen/himax_v2_mmi/Kbuild index 28338a0674cb..450d609237c7 100644 --- a/drivers/input/touchscreen/himax_v2_mmi/Kbuild +++ b/drivers/input/touchscreen/himax_v2_mmi/Kbuild @@ -16,6 +16,10 @@ ifneq ($(filter hx83102,$(CONFIG_INPUT_HIMAX_V2_MMI_IC_NAME)),) EXTRA_CFLAGS += -D__HIMAX_HX83102_MOD__ endif +ifneq ($(filter m y,$(CONFIG_INPUT_TOUCHSCREEN_HIMAX_V2_MMI_ENABLE_PALM)),) + EXTRA_CFLAGS += -DHIMAX_PALM_SENSOR_EN +endif + obj-m := himax_v2_mmi.o ifneq ($(filter m y,$(CONFIG_INPUT_TOUCHSCREEN_HIMAX_V2_MMI_0FLASH)),) diff --git a/drivers/input/touchscreen/himax_v2_mmi/himax_common.c b/drivers/input/touchscreen/himax_v2_mmi/himax_common.c index c626f9cfd742..30b911fd21dc 100644 --- a/drivers/input/touchscreen/himax_v2_mmi/himax_common.c +++ b/drivers/input/touchscreen/himax_v2_mmi/himax_common.c @@ -42,6 +42,27 @@ uint8_t *wake_event_buffer; #endif +#ifdef HIMAX_PALM_SENSOR_EN +static struct sensors_classdev __maybe_unused palm_sensors_touch_cdev = { + .name = "palm-gesture", + .vendor = "Himax", + .version = 1, + .type = SENSOR_TYPE_MOTO_TOUCH_PALM, + .max_range = "5.0", + .resolution = "5.0", + .sensor_power = "1", + .min_delay = 0, + .max_delay = 0, + .fifo_reserved_event_count = 0, + .fifo_max_event_count = 0, + .enabled = 0, + .delay_msec = 200, + .sensors_enable = NULL, + .sensors_poll_delay = NULL, +}; +static void himax_palm_detect_func(struct himax_ts_data *ts, bool detected); +#endif + #define SUPPORT_FINGER_DATA_CHECKSUM 0x0F #define TS_WAKE_LOCK_TIMEOUT (5000) #define FRAME_COUNT 5 @@ -279,11 +300,24 @@ static int himax_palm_detect(uint8_t *buf) x = buf[base] << 8 | buf[base + 1]; y = (buf[base + 2] << 8 | buf[base + 3]); w = buf[(ts->nFinger_support * 4) + loop_i]; +#ifndef HIMAX_PALM_SENSOR_EN I(" %s HX_PALM_REPORT_loopi=%d,base=%x,X=%x,Y=%x,W=%x\n", __func__, loop_i, base, x, y, w); if ((!atomic_read(&ts->suspend_mode)) && (x == 0xFA5A) && (y == 0xFA5A) && (w == 0x00)) return PALM_REPORT; else return NOT_REPORT; +#else + if ((x == 0xFA5A) && (y == 0xFA5A)) { + I("%s: HX_PALM_REPORT loop_i=%d base=%x X=%x, Y=%x, W=%x\n", + __func__, loop_i, base, x, y, w); + return PALM_REPORT; + } else if ((x == 0xFC5C) && (y == 0xFC5C)) { + I("%s: HX_PALM_REPORT loop_i=%d base=%x X=%x, Y=%x, W=%x\n", + __func__, loop_i, base, x, y, w); + return PALM_LEAVE_REPORT; + } else + return NOT_REPORT; +#endif } #endif @@ -2611,6 +2645,20 @@ static void himax_finger_report(struct himax_ts_data *ts) I("%s:end\n", __func__); } + +#ifdef HIMAX_PALM_SENSOR_EN +static void himax_palm_detect_func(struct himax_ts_data *ts, bool detected) { + if (detected) { + I("palm detected\n"); + input_report_abs(ts->palm_sensor_pdata->input_sensor_dev, ABS_DISTANCE, 1); + } else { + I("palm leave\n"); + input_report_abs(ts->palm_sensor_pdata->input_sensor_dev, ABS_DISTANCE, 0); + } + input_sync(ts->palm_sensor_pdata->input_sensor_dev); +} +#endif + static void himax_finger_leave(struct himax_ts_data *ts) { #ifndef HX_PROTOCOL_A @@ -2619,6 +2667,8 @@ static void himax_finger_leave(struct himax_ts_data *ts) if (g_ts_dbg != 0) I("%s: start!\n", __func__); + +#ifndef HIMAX_PALM_SENSOR_EN #if defined(HX_PALM_REPORT) if (himax_palm_detect(hx_touch_data->hx_coord_buf) == PALM_REPORT) { I(" %s HX_PALM_REPORT KEY power event press\n", __func__); @@ -2631,6 +2681,7 @@ static void himax_finger_leave(struct himax_ts_data *ts) input_sync(ts->input_dev); return; } +#endif #endif hx_touch_data->finger_on = 0; @@ -2689,6 +2740,19 @@ static void himax_report_points(struct himax_ts_data *ts) if (g_ts_dbg != 0) I("%s: start!\n", __func__); +#if defined(HX_PALM_REPORT) && defined(HIMAX_PALM_SENSOR_EN) + if (ts->palm_detection_enabled) { + if (himax_palm_detect(hx_touch_data->hx_coord_buf) == PALM_REPORT) { + I(" %s HX_PALM_REPORT\n", __func__); + himax_palm_detect_func(ts, true); + return; + } else if (himax_palm_detect(hx_touch_data->hx_coord_buf) == PALM_LEAVE_REPORT) { + I(" %s HX_PALM_LEAVE_REPORT\n", __func__); + himax_palm_detect_func(ts, false); + return; + } + } +#endif if (ts->hx_point_num != 0) himax_finger_report(ts); else @@ -2757,6 +2821,91 @@ END_FUNCTION: return ts_status; } +#ifdef HIMAX_PALM_SENSOR_EN +static int himax_palm_detect_sensor_set_enable(struct sensors_classdev *sensors_cdev, + unsigned int enable) +{ + I("Gesture set enable %d!", enable); + if (enable == 1) { + g_core_fp.fp_palm_detection_function(1); + private_ts->palm_detection_enabled = true; + } else if (enable == 0) { + g_core_fp.fp_palm_detection_function(0); + private_ts->palm_detection_enabled = false; + } else + E("unknown enable symbol\n"); + + return 0; +} + +static int himax_palm_detect_sensor_init(struct himax_ts_data *data) +{ + struct himax_sensor_platform_data *sensor_pdata; + struct input_dev *sensor_input_dev; + int err; + + sensor_input_dev = input_allocate_device(); + if (!sensor_input_dev) { + E("Failed to allocate device"); + goto exit; + } + + sensor_pdata = devm_kzalloc(&sensor_input_dev->dev, + sizeof(struct himax_sensor_platform_data), + GFP_KERNEL); + if (!sensor_pdata) { + E("Failed to allocate memory"); + goto free_sensor_pdata; + } + data->palm_sensor_pdata = sensor_pdata; + + __set_bit(EV_ABS, sensor_input_dev->evbit); + __set_bit(EV_SYN, sensor_input_dev->evbit); + input_set_abs_params(sensor_input_dev, ABS_DISTANCE, + 0, 5, 0, 0); + sensor_input_dev->name = "palm_detect"; + data->palm_sensor_pdata->input_sensor_dev = sensor_input_dev; + + err = input_register_device(sensor_input_dev); + if (err) { + E("Unable to register device, err=%d", err); + goto free_sensor_input_dev; + } + + sensor_pdata->ps_cdev = palm_sensors_touch_cdev; + sensor_pdata->ps_cdev.sensors_enable = himax_palm_detect_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->palm_sensor_pdata->input_sensor_dev); +free_sensor_input_dev: + input_free_device(data->palm_sensor_pdata->input_sensor_dev); +free_sensor_pdata: + devm_kfree(&sensor_input_dev->dev, sensor_pdata); + data->palm_sensor_pdata= NULL; +exit: + return 1; +} + +int himax_palm_detect_sensor_remove(struct himax_ts_data *data) +{ + sensors_classdev_unregister(&data->palm_sensor_pdata->ps_cdev); + input_unregister_device(data->palm_sensor_pdata->input_sensor_dev); + devm_kfree(&data->palm_sensor_pdata->input_sensor_dev->dev, + data->palm_sensor_pdata); + data->palm_sensor_pdata = NULL; + data->palm_detection_enabled = false; + return 0; +} +#endif + void himax_ts_work(struct himax_ts_data *ts) { @@ -3334,6 +3483,14 @@ FW_force_upgrade: cable_detect_register_notifier(&himax_cable_status_handler); #endif + +#ifdef HIMAX_PALM_SENSOR_EN + if (himax_palm_detect_sensor_init(ts)) { + E(" %s: himax_palm_detect_sensor_init failed!\n", __func__); + goto err_create_palm_sensor_failed; + } +#endif + himax_ts_register_interrupt(); #ifdef CONFIG_TOUCHSCREEN_HIMAX_DEBUG @@ -3350,6 +3507,9 @@ FW_force_upgrade: g_hx_chip_inited = true; return 0; +#ifdef HIMAX_PALM_SENSOR_EN +err_create_palm_sensor_failed: +#endif err_creat_proc_file_failed: himax_report_data_deinit(); err_report_data_init_failed: @@ -3477,6 +3637,15 @@ int himax_chip_common_suspend(struct himax_ts_data *ts) I("%s: enter\n", __func__); } +#ifdef HIMAX_PALM_SENSOR_EN + if (ts->palm_detection_enabled) { + himax_report_all_leave_event(ts); + atomic_set(&ts->suspend_mode, 1); + I("[himax] %s: palm detect function enable, reject suspend\n", __func__); + goto END; + } +#endif + if (debug_data != NULL && debug_data->flash_dump_going == true) { I("[himax] %s: Flash dump is going, reject suspend\n", __func__); goto END; @@ -3554,6 +3723,12 @@ int himax_chip_common_resume(struct himax_ts_data *ts) #endif atomic_set(&ts->suspend_mode, 0); +#ifdef HIMAX_PALM_SENSOR_EN + if (ts->palm_detection_enabled) { + I("[himax] %s: palm detect function enable, skip resume\n", __func__); + goto END; + } +#endif if (ts->pdata) if (ts->pdata->powerOff3V3 && ts->pdata->power) diff --git a/drivers/input/touchscreen/himax_v2_mmi/himax_common.h b/drivers/input/touchscreen/himax_v2_mmi/himax_common.h index b51ec290dc99..cf8c1f9b31ba 100755 --- a/drivers/input/touchscreen/himax_v2_mmi/himax_common.h +++ b/drivers/input/touchscreen/himax_v2_mmi/himax_common.h @@ -39,6 +39,10 @@ #include #include "himax_platform.h" #include +#ifdef HIMAX_PALM_SENSOR_EN +#include +#define SENSOR_TYPE_MOTO_TOUCH_PALM (SENSOR_TYPE_DEVICE_PRIVATE_BASE + 31) +#endif #if defined(CONFIG_DRM) #include @@ -61,6 +65,17 @@ #define HX_TP_PROC_2T2R /*#define HX_TP_SELF_TEST_DRIVER*/ /*if enable, selftest works in driver*/ #endif + +#ifdef HIMAX_PALM_SENSOR_EN +struct himax_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 himax_ts_data *data; +}; +#endif + /*===========Himax Option function=============*/ #define HX_RST_PIN_FUNC #define HX_RESUME_SEND_CMD @@ -72,7 +87,11 @@ /*#define HX_SMART_WAKEUP*/ /*#define HX_GESTURE_TRACK*/ /*#define HX_HIGH_SENSE*/ +#ifdef HIMAX_PALM_SENSOR_EN +#define HX_PALM_REPORT +#else /*#define HX_PALM_REPORT*/ +#endif #define HX_USB_DETECT_GLOBAL /*#define HX_USB_DETECT_CALLBACK*/ /*#define HX_PROTOCOL_A*/ /* for MTK special platform.If turning on,it will report to system by using specific format. */ @@ -167,6 +186,7 @@ #if defined(HX_PALM_REPORT) #define PALM_REPORT 1 +#define PALM_LEAVE_REPORT 2 #define NOT_REPORT -1 #endif @@ -448,6 +468,10 @@ struct himax_ts_data { struct work_struct guest_info_work; #endif +#ifdef HIMAX_PALM_SENSOR_EN + bool palm_detection_enabled; + struct himax_sensor_platform_data *palm_sensor_pdata; +#endif }; diff --git a/drivers/input/touchscreen/himax_v2_mmi/himax_ic_core.h b/drivers/input/touchscreen/himax_v2_mmi/himax_ic_core.h index 111941178e23..e6db83a413fb 100644 --- a/drivers/input/touchscreen/himax_v2_mmi/himax_ic_core.h +++ b/drivers/input/touchscreen/himax_v2_mmi/himax_ic_core.h @@ -489,6 +489,12 @@ struct zf_info { }; #endif +#ifdef HIMAX_PALM_SENSOR_EN + #define palm_detection_register 0x10007FF4 + #define palm_detection_register_enable 0xA55AA55A + #define palm_detection_register_disable 0x00000000 +#endif + struct ic_operation { uint8_t addr_ahb_addr_byte_0[1]; uint8_t addr_ahb_rdata_byte_0[1]; @@ -520,6 +526,9 @@ struct fw_operation { uint8_t addr_smwp_enable[4]; #ifdef HX_EDGE_LIMIT uint8_t addr_edge_limit_enable[4]; +#endif +#ifdef HIMAX_PALM_SENSOR_EN + uint8_t addr_palm_detection_enable[4]; #endif uint8_t addr_program_reload_from[4]; uint8_t addr_program_reload_to[4]; @@ -945,6 +954,9 @@ struct himax_core_fp { #ifdef HX_CODE_OVERLAY int (*fp_0f_overlay)(int ovl_type, int mode); #endif +#ifdef HIMAX_PALM_SENSOR_EN + int (*fp_palm_detection_function)(int mode); +#endif #endif }; diff --git a/drivers/input/touchscreen/himax_v2_mmi/himax_ic_incell_core.c b/drivers/input/touchscreen/himax_v2_mmi/himax_ic_incell_core.c index aa67c4400e84..6cdc7c5e69c9 100755 --- a/drivers/input/touchscreen/himax_v2_mmi/himax_ic_incell_core.c +++ b/drivers/input/touchscreen/himax_v2_mmi/himax_ic_incell_core.c @@ -3313,6 +3313,26 @@ int himax_mcu_0f_overlay(int ovl_type, int mode) #endif + +#ifdef HIMAX_PALM_SENSOR_EN +int himax_mcu_palm_detection(int mode) +{ + uint8_t data_byte[DATA_LEN_4]; + uint8_t tmp_addr[4]; + I("%s: set palm detection mode to %d", __func__, mode); + if (mode) + himax_in_parse_assign_cmd(palm_detection_register_enable, data_byte, 4); + else + himax_in_parse_assign_cmd(palm_detection_register_disable, data_byte, 4); + + g_core_fp.fp_register_write(pfw_op->addr_palm_detection_enable, DATA_LEN_4, data_byte, 0); + g_core_fp.fp_register_read(pfw_op->addr_palm_detection_enable, DATA_LEN_4, tmp_addr, 0); + I("%s: reg=0x%02X%02X%02X%02X.", __func__, tmp_addr[0],tmp_addr[1],tmp_addr[2],tmp_addr[3]); + + return 0; +} +#endif + #ifdef CORE_INIT /* init start */ static void himax_mcu_fp_init(void) @@ -3444,6 +3464,9 @@ static void himax_mcu_fp_init(void) #ifdef HX_CODE_OVERLAY g_core_fp.fp_0f_overlay = himax_mcu_0f_overlay; #endif +#ifdef HIMAX_PALM_SENSOR_EN + g_core_fp.fp_palm_detection_function = himax_mcu_palm_detection; +#endif #endif } @@ -3614,6 +3637,10 @@ EXPORT_SYMBOL(himax_in_parse_assign_cmd); void himax_mcu_in_cmd_init(void) { I("%s: Entering!\n", __func__); + +#ifdef HIMAX_PALM_SENSOR_EN + himax_in_parse_assign_cmd(palm_detection_register, pfw_op->addr_palm_detection_enable, sizeof(pfw_op->addr_palm_detection_enable)); +#endif #ifdef CORE_IC himax_in_parse_assign_cmd(ic_adr_ahb_addr_byte_0, pic_op->addr_ahb_addr_byte_0, sizeof(pic_op->addr_ahb_addr_byte_0)); himax_in_parse_assign_cmd(ic_adr_ahb_rdata_byte_0, pic_op->addr_ahb_rdata_byte_0, sizeof(pic_op->addr_ahb_rdata_byte_0)); diff --git a/drivers/input/touchscreen/himax_v2_mmi/himax_platform_QCT_SPI.c b/drivers/input/touchscreen/himax_v2_mmi/himax_platform_QCT_SPI.c index af2de22e586c..008e1e85e07a 100755 --- a/drivers/input/touchscreen/himax_v2_mmi/himax_platform_QCT_SPI.c +++ b/drivers/input/touchscreen/himax_v2_mmi/himax_platform_QCT_SPI.c @@ -898,6 +898,12 @@ int drm_notifier_callback(struct notifier_block *self, if (!ts->initialized) return -ECANCELED; himax_common_suspend(ts->dev); +#ifdef HIMAX_PALM_SENSOR_EN + if (ts->palm_detection_enabled) { + I("%s: palm detection is enabled", __func__); + return 1; + } +#endif break; } } diff --git a/drivers/input/touchscreen/himax_v2_mmi/support_ic/himax_v2_mmi_hx83112/Android.mk b/drivers/input/touchscreen/himax_v2_mmi/support_ic/himax_v2_mmi_hx83112/Android.mk index 3727aa120cb8..21012b7ef06c 100644 --- a/drivers/input/touchscreen/himax_v2_mmi/support_ic/himax_v2_mmi_hx83112/Android.mk +++ b/drivers/input/touchscreen/himax_v2_mmi/support_ic/himax_v2_mmi_hx83112/Android.mk @@ -9,6 +9,10 @@ endif KERNEL_CFLAGS += CONFIG_INPUT_HIMAX_V2_MMI_IC_NAME=hx83112 +ifneq ($(BOARD_USES_TOUCH_PALM),) + KERNEL_CFLAGS += CONFIG_INPUT_TOUCHSCREEN_HIMAX_V2_MMI_ENABLE_PALM=y +endif + include $(CLEAR_VARS) LOCAL_MODULE := himax_v2_mmi_hx83112.ko LOCAL_MODULE_TAGS := optional diff --git a/drivers/input/touchscreen/himax_v2_mmi/support_ic/himax_v2_mmi_hx83112/Kbuild b/drivers/input/touchscreen/himax_v2_mmi/support_ic/himax_v2_mmi_hx83112/Kbuild index ec35e08ba6b6..52d075da4819 100644 --- a/drivers/input/touchscreen/himax_v2_mmi/support_ic/himax_v2_mmi_hx83112/Kbuild +++ b/drivers/input/touchscreen/himax_v2_mmi/support_ic/himax_v2_mmi_hx83112/Kbuild @@ -14,5 +14,9 @@ ifneq ($(filter hx83112,$(CONFIG_INPUT_HIMAX_V2_MMI_IC_NAME)),) EXTRA_CFLAGS += -D__HIMAX_HX83112_MOD__ endif +ifneq ($(filter m y,$(CONFIG_INPUT_TOUCHSCREEN_HIMAX_V2_MMI_ENABLE_PALM)),) + EXTRA_CFLAGS += -DHIMAX_PALM_SENSOR_EN +endif + obj-m := himax_v2_mmi_hx83112.o himax_v2_mmi_hx83112-objs += himax_ic_HX83112.o