himax_v2_mmi: Add palm detection function

TP:
If palm detection option is enabled
Create a virtual sensor for moto app.

Change-Id: I8065fccc5da638dde3f2ece9c41470d28cc5c7c3
Signed-off-by: haojl2 <haojl2@motorola.com>
Reviewed-on: https://gerrit.mot.com/1405365
SLTApproved: Slta Waiver
SME-Granted: SME Approvals Granted
Tested-by: Jira Key
Reviewed-by: Jianqi Yang <yangj@motorola.com>
Submit-Approved: Jira Key
This commit is contained in:
haojl2 2019-08-20 11:28:02 +08:00 • committed by Jialei Hao
commit 2a04696a64
9 changed files with 259 additions and 0 deletions

View file

@ -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

View file

@ -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)),)

View file

@ -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)

View file

@ -39,6 +39,10 @@
#include <linux/proc_fs.h>
#include "himax_platform.h"
#include <linux/kallsyms.h>
#ifdef HIMAX_PALM_SENSOR_EN
#include <linux/sensors.h>
#define SENSOR_TYPE_MOTO_TOUCH_PALM (SENSOR_TYPE_DEVICE_PRIVATE_BASE + 31)
#endif
#if defined(CONFIG_DRM)
#include <linux/msm_drm_notify.h>
@ -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
};

View file

@ -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
};

View file

@ -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));

View file

@ -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;
}
}

View file

@ -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

View file

@ -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