From 20aa1b7593bc957e9b6a5634bb368c36368ae992 Mon Sep 17 00:00:00 2001 From: cjh1249131356 Date: Sun, 22 Jan 2023 18:09:51 +0800 Subject: [PATCH] oplus_touchscreen: Forward port oos_edge_limit_support from OOS 12 driver * Stock OOS kernel still have these nodes available. Don't know why oplus deleted these codes from public source. It's useful for users who play games much. Let's add them back. Signed-off-by: cjh1249131356 Signed-off-by: engstk --- .../Samsung/S6SY771/sec_drivers_s6sy771.c | 615 ++++++++++++++++++ .../Samsung/S6SY771/sec_drivers_s6sy771.h | 6 + .../Samsung/S6SY791/sec_drivers_s6sy791.c | 615 ++++++++++++++++++ .../Samsung/S6SY791/sec_drivers_s6sy791.h | 6 + .../oplus_touchscreen/touchpanel_common.h | 11 + .../touchpanel_common_driver.c | 282 ++++++++ .../oplus_touchscreen/touchpanel_prevention.h | 459 +++++++++++++ 7 files changed, 1994 insertions(+) create mode 100644 drivers/input/touchscreen/oplus_touchscreen/touchpanel_prevention.h diff --git a/drivers/input/touchscreen/oplus_touchscreen/Samsung/S6SY771/sec_drivers_s6sy771.c b/drivers/input/touchscreen/oplus_touchscreen/Samsung/S6SY771/sec_drivers_s6sy771.c index 93e368690c..ad86e498cd 100644 --- a/drivers/input/touchscreen/oplus_touchscreen/Samsung/S6SY771/sec_drivers_s6sy771.c +++ b/drivers/input/touchscreen/oplus_touchscreen/Samsung/S6SY771/sec_drivers_s6sy771.c @@ -58,6 +58,19 @@ static int sec_power_control(void *chip_data, bool enable); static int sec_get_verify_result(struct chip_data_s6sy771 *chip_info); static int sec_read_mutual(struct chip_data_s6sy771 *chip_info, u8 type, char *data, int len); static bool check_calibration(struct chip_data_s6sy771 *chip_info); +static int ver_bottom_large_handle_func(struct grip_zone_area *grip_zone, bool enable); +static int hor_corner_large_handle_func(struct grip_zone_area *grip_zone, bool enable); +static int long_size_dead_zone_handle_func(struct grip_zone_area *grip_zone, bool enable); +static int short_size_dead_zone_handle_func(struct grip_zone_area *grip_zone, bool enable); +static int long_size_condtion_zone_handle_func(struct grip_zone_area *grip_zone, bool enable); +static int short_size_condtion_zone_handle_func(struct grip_zone_area *grip_zone, bool enable); +static int long_size_large_zone_handle_func(struct grip_zone_area *grip_zone, bool enable); +static int short_size_large_zone_handle_func(struct grip_zone_area *grip_zone, bool enable); +static int sec_set_large_corner_frame_limit(int frame_limit); +static int sec_set_no_handle_area(struct kernel_grip_info *grip_info); +static int sec_set_condition_frame_limit(int frame_limit); +static int sec_set_large_frame_limit(int frame_limit); +static void sec_set_grip_touch_direction(uint8_t dir); static void sec_calibrate(struct seq_file *s, void *chip_data); static bool sec_get_cal_status(struct seq_file *s, void *chip_data); @@ -65,6 +78,26 @@ static bool sec_get_cal_status(struct seq_file *s, void *chip_data); /*************************** start of global variable delcare****************************************/ static struct chip_data_s6sy771 *g_chip_info; +static struct sec_support_grip_zone sec_grip[] = { + {"ver_left_bottom_large", ver_bottom_large_handle_func}, + //{"ver_right_bottom_large", ver_bottom_large_handle_func}, + {"hor90_left_corner_large", hor_corner_large_handle_func}, + //{"hor90_right_corner_large", hor_corner_large_handle_func}, + //{"hor270_left_corner_large", hor_corner_large_handle_func}, + //{"hor270_right_corner_large", hor_corner_large_handle_func}, + {"ver_left_dead", long_size_dead_zone_handle_func}, + //{"ver_right_dead", long_size_dead_zone_handle_func}, + {"hor_left_dead", short_size_dead_zone_handle_func}, + //{"hor_right_dead", short_size_dead_zone_handle_func}, + {"ver_left_condtion", long_size_condtion_zone_handle_func}, + //{"ver_right_condtion", long_size_condtion_zone_handle_func}, + {"hor_left_condtion", short_size_condtion_zone_handle_func}, + //{"hor_right_condtion", short_size_condtion_zone_handle_func}, + {"ver_left_large", long_size_large_zone_handle_func}, + //{"ver_right_large", long_size_large_zone_handle_func}, + {"hor_left_large", short_size_large_zone_handle_func}, + //{"hor_right_large", short_size_large_zone_handle_func}, +}; /**************************** end of global variable delcare*****************************************/ /****** Start of other functions that work for oplus_touchpanel_operations callbacks***********/ @@ -275,6 +308,87 @@ static int sec_smooth_lv_set(void *chip_data, int level) } +static int sec_limit_switch_mode(struct chip_data_s6sy771 *chip_info, bool enable) +{ + int ret = -1; + unsigned char buf[5] = {0}; + unsigned char cmd[3] = {0}; + unsigned char extra_cmd[3] = {0}; + struct touchpanel_data *ts = i2c_get_clientdata(chip_info->client); + + if (ts == NULL) { + return ret; + } + + TPD_INFO("limit_switch is %d\n", ts->limit_switch); + if (ts->limit_switch == 1) { /*LANDSPACE*/ + cmd[0] = 0x01; + ret = touch_i2c_write_block(chip_info->client, SEC_CMD_GRIP_DIRECTION, 3, cmd); /*change mode*/ + } else if (ts->limit_switch == 2) { + cmd[0] = 0x02; + ret = touch_i2c_write_block(chip_info->client, SEC_CMD_GRIP_DIRECTION, 3, cmd); + } else { /*portrait*/ + cmd[0] = 0x00; + ret = touch_i2c_write_block(chip_info->client, SEC_CMD_GRIP_DIRECTION, 3, cmd); + } + /*dead zone type 1*/ + if ((ts->limit_switch == 1) || (ts->limit_switch == 2)) /*landscape*/ + buf[2] = ts->dead_zone_l; /*default x=15px*/ + else /*portrait*/ + buf[2] = ts->dead_zone_p; /*default x=15px*/ + + ret = touch_i2c_write_block(chip_info->client, SEC_CMD_GRIP_AREA, 5, buf); + /*dead zone type 2*/ + buf[0] = 0x01; + if ((ts->limit_switch == 1) || (ts->limit_switch == 2)) { /*landscape*/ + buf[2] = 0x50; /*x=80px*/ + buf[4] = 0x50; /*y=80px*/ + } else { /*portrait*/ + buf[2] = 0x1E; /*x=30px*/ + buf[4] = 0x82; /*y=130px*/ + } + ret = touch_i2c_write_block(chip_info->client, SEC_CMD_GRIP_AREA, 5, buf); + /*long press reject zone*/ + buf[0] = 0x02; + if (ts->project_info == 1) { /*19811*/ + buf[2] = 0x3C; /*x=60px*/ + buf[4] = 0x50; /*y=80px*/ + } else { + buf[2] = 0x1E; /*x=30px*/ + buf[4] = 0x32; /*y=50px*/ + } + ret = touch_i2c_write_block(chip_info->client, SEC_CMD_GRIP_AREA, 5, buf); + extra_cmd[0] = 0x02; + extra_cmd[1] = 0x14; + extra_cmd[2] = 0x46; + ret = touch_i2c_write_block(chip_info->client, SEC_CMD_GRIP_PARA, 3, extra_cmd); + /*large touch reject zone*/ + buf[0] = 0x03; + buf[2] = 0x64; /*x=100px*/ + buf[4] = 0x64; /*y=100px*/ + ret = touch_i2c_write_block(chip_info->client, SEC_CMD_GRIP_AREA, 5, buf); + extra_cmd[0] = 0x03; + extra_cmd[1] = 0x0F; + extra_cmd[2] = 0x28; + ret = touch_i2c_write_block(chip_info->client, SEC_CMD_GRIP_PARA, 3, extra_cmd); + /*corner long press reject zone*/ + buf[0] = 0x04; + if (ts->project_info == 1) { + buf[2] = 0x78; /*120px*/ + buf[4] = 0x78; /*120px*/ + } else { + buf[2] = 0x64; /*100px*/ + buf[4] = 0x64; /*100px*/ + } + ret = touch_i2c_write_block(chip_info->client, SEC_CMD_GRIP_AREA, 5, buf); + extra_cmd[0] = 0x04; + extra_cmd[1] = 0x32; + extra_cmd[2] = 0x00; + ret = touch_i2c_write_block(chip_info->client, SEC_CMD_GRIP_PARA, 3, extra_cmd); + + return ret; +} + void sec_mdelay(unsigned int ms) { if (ms < 20) @@ -1673,6 +1787,13 @@ static int sec_mode_switch(void *chip_data, work_mode mode, bool flag) } break; + case MODE_LIMIT_SWITCH: + ret = sec_limit_switch_mode(chip_info, flag); + if (ret < 0) { + TPD_INFO("%s: limit switch: %d failed\n", __func__, flag); + } + break; + default: TPD_INFO("%s: Wrong mode.\n", __func__); } @@ -1717,6 +1838,57 @@ static uint8_t sec_get_touch_direction(void *chip_data) return chip_info->touch_direction; } +static void sec_enable_kernel_grip(void *chip_data, struct kernel_grip_info *grip_info) +{ + struct list_head *pos = NULL; + struct grip_zone_area *grip_zone = NULL; + //struct chip_data_s6sy771 *chip_info = (struct chip_data_s6sy771 *)chip_data; + int i = 0; + + if (!grip_info || !grip_info->grip_handle_in_fw) { + return; + } + + list_for_each(pos, &grip_info->large_zone_list) { + grip_zone = (struct grip_zone_area *)pos; + for (i = 0 ; i < ARRAY_SIZE(sec_grip); i ++) { + if (!strncmp(grip_zone->name, sec_grip[i].name, GRIP_TAG_SIZE)) { + if (sec_grip[i].handle_func) { + sec_grip[i].handle_func(grip_zone, true); + } + } + } + } + + list_for_each(pos, &grip_info->dead_zone_list) { + grip_zone = (struct grip_zone_area *)pos; + for (i = 0 ; i < ARRAY_SIZE(sec_grip); i ++) { + if (!strncmp(grip_zone->name, sec_grip[i].name, GRIP_TAG_SIZE)) { + if (sec_grip[i].handle_func) { + sec_grip[i].handle_func(grip_zone, true); + } + } + } + } + + list_for_each(pos, &grip_info->condition_zone_list) { + grip_zone = (struct grip_zone_area *)pos; + for (i = 0 ; i < ARRAY_SIZE(sec_grip); i ++) { + if (!strncmp(grip_zone->name, sec_grip[i].name, GRIP_TAG_SIZE)) { + if (sec_grip[i].handle_func) { + sec_grip[i].handle_func(grip_zone, true); + } + } + } + } + + sec_set_no_handle_area(grip_info); + sec_set_condition_frame_limit(grip_info->condition_frame_limit); + sec_set_large_frame_limit(grip_info->large_frame_limit); + sec_set_large_corner_frame_limit(grip_info->large_corner_frame_limit); + sec_set_grip_touch_direction(grip_info->touch_dir); +} + static struct oplus_touchpanel_operations sec_ops = { .ftm_process = sec_ftm_process, .get_vendor = sec_get_vendor, @@ -1733,6 +1905,7 @@ static struct oplus_touchpanel_operations sec_ops = { // .get_wireless_state = sec_get_wireless_state, .set_touch_direction = sec_set_touch_direction, .get_touch_direction = sec_get_touch_direction, + .enable_kernel_grip = sec_enable_kernel_grip, .enable_fingerprint = sec_enable_fingerprint_mode, .screenon_fingerprint_info = sec_get_fingerprint_info, .enable_gesture_mask = sec_enable_gesture_mask, @@ -3114,6 +3287,441 @@ static bool sec_get_cal_status(struct seq_file *s, void *chip_data) return chip_info->cal_needed; } +static int ver_bottom_large_handle_func(struct grip_zone_area *grip_zone, bool enable) +{ + int ret = 0; + u8 area_size[5] = {CORNER_LONG_PRESS_ZONE, 0, 0, 0, 0}; + + if (!g_chip_info || !grip_zone || *g_chip_info->in_suspend) { + return -1; + } + + if (enable) { + if ((grip_zone->grip_side >> TYPE_LONG_CORNER_SIDE) & 0x01) { + area_size[1] = (grip_zone->x_width >> 8) & 0xFF; + area_size[2] = grip_zone->x_width & 0xFF; + area_size[3] = (grip_zone->y_width >> 8) & 0xFF; + area_size[4] = grip_zone->y_width & 0xFF; + } else if ((grip_zone->grip_side >> TYPE_SHORT_CORNER_SIDE) & 0x01) { + area_size[1] = (grip_zone->y_width >> 8) & 0xFF; + area_size[2] = grip_zone->y_width & 0xFF; + area_size[3] = (grip_zone->x_width >> 8) & 0xFF; + area_size[4] = grip_zone->x_width & 0xFF; + } else if ((grip_zone->grip_side >> TYPE_LONG_SIDE) & 0x01) { + area_size[1] = (grip_zone->x_width >> 8) & 0xFF; + area_size[2] = grip_zone->x_width & 0xFF; + } else if ((grip_zone->grip_side >> TYPE_SHORT_SIDE) & 0x01) { + area_size[1] = (grip_zone->y_width >> 8) & 0xFF; + area_size[2] = grip_zone->y_width & 0xFF; + } + } + + ret = touch_i2c_write_byte(g_chip_info->client, SEC_CMD_GRIP_DIRECTION, 0x00); + ret |= touch_i2c_write_block(g_chip_info->client, SEC_CMD_GRIP_AREA, sizeof(area_size), area_size); + ret |= touch_i2c_write_byte(g_chip_info->client, SEC_CMD_GRIP_DIRECTION, g_chip_info->touch_direction); + TPD_DETAIL("%s: cmd write is : 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x.\n", __func__, SEC_CMD_GRIP_AREA, + area_size[0], area_size[1], area_size[2], area_size[3], area_size[4]); + TPD_DETAIL("%s: %s area size is %s %s in fw : [%d, %d] [%d %d].\n", __func__, + grip_zone->name, ret < 0 ? "failed" : "success", enable ? "change" : "remove", grip_zone->start_x, grip_zone->start_y, + grip_zone->x_width, grip_zone->y_width); + + return ret; +} + +static int hor_corner_large_handle_func(struct grip_zone_area *grip_zone, bool enable) +{ + int ret = 0; + u8 area_size[5] = {CORNER_LONG_PRESS_ZONE, 0, 0, 0, 0}; + + if (!g_chip_info || !grip_zone || *g_chip_info->in_suspend) { + return -1; + } + + if (enable) { + if ((grip_zone->grip_side >> TYPE_LONG_CORNER_SIDE) & 0x01) { + area_size[1] = (grip_zone->x_width >> 8) & 0xFF; + area_size[2] = grip_zone->x_width & 0xFF; + area_size[3] = (grip_zone->y_width >> 8) & 0xFF; + area_size[4] = grip_zone->y_width & 0xFF; + } else if ((grip_zone->grip_side >> TYPE_SHORT_CORNER_SIDE) & 0x01) { + area_size[1] = (grip_zone->y_width >> 8) & 0xFF; + area_size[2] = grip_zone->y_width & 0xFF; + area_size[3] = (grip_zone->x_width >> 8) & 0xFF; + area_size[4] = grip_zone->x_width & 0xFF; + } else if ((grip_zone->grip_side >> TYPE_LONG_SIDE) & 0x01) { + area_size[1] = (grip_zone->x_width >> 8) & 0xFF; + area_size[2] = grip_zone->x_width & 0xFF; + } else if ((grip_zone->grip_side >> TYPE_SHORT_SIDE) & 0x01) { + area_size[1] = (grip_zone->y_width >> 8) & 0xFF; + area_size[2] = grip_zone->y_width & 0xFF; + } + } + + ret = touch_i2c_write_byte(g_chip_info->client, SEC_CMD_GRIP_DIRECTION, 0x01); + ret |= touch_i2c_write_block(g_chip_info->client, SEC_CMD_GRIP_AREA, sizeof(area_size), area_size); + ret |= touch_i2c_write_byte(g_chip_info->client, SEC_CMD_GRIP_DIRECTION, g_chip_info->touch_direction); + TPD_DETAIL("%s: cmd write is : 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x.\n", __func__, SEC_CMD_GRIP_AREA, + area_size[0], area_size[1], area_size[2], area_size[3], area_size[4]); + TPD_DETAIL("%s: %s area size is %s %s in fw : [%d, %d] [%d %d].\n", __func__, + grip_zone->name, ret < 0 ? "failed" : "success", enable ? "change" : "remove", grip_zone->start_x, grip_zone->start_y, + grip_zone->x_width, grip_zone->y_width); + + return ret; +} + +static int long_size_dead_zone_handle_func(struct grip_zone_area *grip_zone, bool enable) +{ + int ret = 0; + u8 area_size[5] = {DEAD_ZONE_TYPE_1, 0, 0, 0xFF, 0xFF}; + + if (!g_chip_info || !grip_zone || *g_chip_info->in_suspend) { + return -1; + } + + if (enable) { + if ((grip_zone->grip_side >> TYPE_LONG_SIDE) & 0x01) { + area_size[1] = (grip_zone->x_width >> 8) & 0xFF; + area_size[2] = grip_zone->x_width & 0xFF; + } else if ((grip_zone->grip_side >> TYPE_SHORT_SIDE) & 0x01) { + area_size[1] = (grip_zone->y_width >> 8) & 0xFF; + area_size[2] = grip_zone->y_width & 0xFF; + } + } + + ret = touch_i2c_write_block(g_chip_info->client, SEC_CMD_GRIP_AREA, sizeof(area_size), area_size); + TPD_DETAIL("%s: cmd write is : 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x.\n", __func__, SEC_CMD_GRIP_AREA, + area_size[0], area_size[1], area_size[2], area_size[3], area_size[4]); + TPD_DETAIL("%s: %s area size is %s %s in fw : [%d, %d] [%d %d].\n", __func__, + grip_zone->name, ret < 0 ? "failed" : "success", enable ? "change" : "remove", grip_zone->start_x, grip_zone->start_y, + grip_zone->x_width, grip_zone->y_width); + + return ret; +} + +static int short_size_dead_zone_handle_func(struct grip_zone_area *grip_zone, bool enable) +{ + int ret = 0; + u8 area_size[5] = {DEAD_ZONE_TYPE_1, 0xFF, 0xFF, 0, 0}; + + if (!g_chip_info || !grip_zone || *g_chip_info->in_suspend) { + return -1; + } + + if (enable) { + if ((grip_zone->grip_side >> TYPE_LONG_SIDE) & 0x01) { + area_size[3] = (grip_zone->x_width >> 8) & 0xFF; + area_size[4] = grip_zone->x_width & 0xFF; + } else if ((grip_zone->grip_side >> TYPE_SHORT_SIDE) & 0x01) { + area_size[3] = (grip_zone->y_width >> 8) & 0xFF; + area_size[4] = grip_zone->y_width & 0xFF; + } + } + + ret = touch_i2c_write_block(g_chip_info->client, SEC_CMD_GRIP_AREA, sizeof(area_size), area_size); + TPD_DETAIL("%s: cmd write is : 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x.\n", __func__, SEC_CMD_GRIP_AREA, + area_size[0], area_size[1], area_size[2], area_size[3], area_size[4]); + TPD_DETAIL("%s: %s area size is %s %s in fw : [%d, %d] [%d %d].\n", __func__, + grip_zone->name, ret < 0 ? "failed" : "success", enable ? "change" : "remove", grip_zone->start_x, grip_zone->start_y, + grip_zone->x_width, grip_zone->y_width); + + return ret; +} + +static int long_size_condtion_zone_handle_func(struct grip_zone_area *grip_zone, bool enable) +{ + int ret = 0; + u8 area_size[5] = {LONG_PRESS_ZONE, 0, 0, 0xFF, 0xFF}; + u8 exit_thd[3] = {LONG_PRESS_ZONE, 0xFF, 0}; + + if (!g_chip_info || !grip_zone || *g_chip_info->in_suspend) { + return -1; + } + + if (enable) { + if ((grip_zone->grip_side >> TYPE_LONG_SIDE) & 0x01) { + area_size[1] = (grip_zone->x_width >> 8) & 0xFF; + area_size[2] = grip_zone->x_width & 0xFF; + } else if ((grip_zone->grip_side >> TYPE_SHORT_SIDE) & 0x01) { + area_size[1] = (grip_zone->y_width >> 8) & 0xFF; + area_size[2] = grip_zone->y_width & 0xFF; + } + } + + ret = touch_i2c_write_block(g_chip_info->client, SEC_CMD_GRIP_AREA, sizeof(area_size), area_size); + TPD_DETAIL("%s: cmd write is : 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x.\n", __func__, SEC_CMD_GRIP_AREA, + area_size[0], area_size[1], area_size[2], area_size[3], area_size[4]); + TPD_DETAIL("%s: %s area size is %s %s in fw : [%d, %d] [%d %d].\n", __func__, + grip_zone->name, ret < 0 ? "failed" : "success", enable ? "change" : "remove", grip_zone->start_x, grip_zone->start_y, + grip_zone->x_width, grip_zone->y_width); + + if (enable) { + exit_thd[2] = grip_zone->exit_thd & 0xFF; + ret = touch_i2c_write_block(g_chip_info->client, SEC_CMD_GRIP_PARA, sizeof(exit_thd), exit_thd); + TPD_DETAIL("%s: cmd is : 0x%02x, 0x%02x, 0x%02x, 0x%02x.\n", __func__, SEC_CMD_GRIP_PARA, exit_thd[0], exit_thd[1], exit_thd[2]); + TPD_DETAIL("%s: %s exit thd is %s change in fw : %d.\n", __func__, + grip_zone->name, ret < 0 ? "failed" : "success", grip_zone->exit_thd); + } + + return ret; +} + +static int short_size_condtion_zone_handle_func(struct grip_zone_area *grip_zone, bool enable) +{ + int ret = 0; + u8 area_size[5] = {LONG_PRESS_ZONE, 0xFF, 0xFF, 0, 0,}; + + if (!g_chip_info || !grip_zone || *g_chip_info->in_suspend) { + return -1; + } + + if (enable) { + if ((grip_zone->grip_side >> TYPE_LONG_SIDE) & 0x01) { + area_size[3] = (grip_zone->x_width >> 8) & 0xFF; + area_size[4] = grip_zone->x_width & 0xFF; + } else if ((grip_zone->grip_side >> TYPE_SHORT_SIDE) & 0x01) { + area_size[3] = (grip_zone->y_width >> 8) & 0xFF; + area_size[4] = grip_zone->y_width & 0xFF; + } + } + + ret = touch_i2c_write_block(g_chip_info->client, SEC_CMD_GRIP_AREA, sizeof(area_size), area_size); + TPD_DETAIL("%s: cmd write is : 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x.\n", __func__, SEC_CMD_GRIP_AREA, + area_size[0], area_size[1], area_size[2], area_size[3], area_size[4]); + TPD_DETAIL("%s: %s area size is %s %s in fw : [%d, %d] [%d %d].\n", __func__, + grip_zone->name, ret < 0 ? "failed" : "success", enable ? "change" : "remove", grip_zone->start_x, grip_zone->start_y, + grip_zone->x_width, grip_zone->y_width); + + return ret; +} + +static int long_size_large_zone_handle_func(struct grip_zone_area *grip_zone, bool enable) +{ + int ret = 0; + u8 area_size[5] = {LARGE_TOUCH_REJECTION, 0, 0, 0xFF, 0xFF}; + + if (!g_chip_info || !grip_zone || *g_chip_info->in_suspend) { + return -1; + } + + if (enable) { + if ((grip_zone->grip_side >> TYPE_LONG_SIDE) & 0x01) { + area_size[1] = (grip_zone->x_width >> 8) & 0xFF; + area_size[2] = grip_zone->x_width & 0xFF; + } else if ((grip_zone->grip_side >> TYPE_SHORT_SIDE) & 0x01) { + area_size[1] = (grip_zone->y_width >> 8) & 0xFF; + area_size[2] = grip_zone->y_width & 0xFF; + } + } + + ret = touch_i2c_write_block(g_chip_info->client, SEC_CMD_GRIP_AREA, sizeof(area_size), area_size); + TPD_DETAIL("%s: cmd write is : 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x.\n", __func__, SEC_CMD_GRIP_AREA, + area_size[0], area_size[1], area_size[2], area_size[3], area_size[4]); + TPD_DETAIL("%s: %s area size is %s %s in fw : [%d, %d] [%d %d].\n", __func__, + grip_zone->name, ret < 0 ? "failed" : "success", enable ? "change" : "remove", grip_zone->start_x, grip_zone->start_y, + grip_zone->x_width, grip_zone->y_width); + + return ret; +} + +static int short_size_large_zone_handle_func(struct grip_zone_area *grip_zone, bool enable) +{ + int ret = 0; + u8 area_size[5] = {LARGE_TOUCH_REJECTION, 0xFF, 0xFF, 0, 0}; + + if (!g_chip_info || !grip_zone || *g_chip_info->in_suspend) { + return -1; + } + + if (enable) { + if ((grip_zone->grip_side >> TYPE_LONG_SIDE) & 0x01) { + area_size[3] = (grip_zone->x_width >> 8) & 0xFF; + area_size[4] = grip_zone->x_width & 0xFF; + } else if ((grip_zone->grip_side >> TYPE_SHORT_SIDE) & 0x01) { + area_size[3] = (grip_zone->y_width >> 8) & 0xFF; + area_size[4] = grip_zone->y_width & 0xFF; + } + } + + ret = touch_i2c_write_block(g_chip_info->client, SEC_CMD_GRIP_AREA, sizeof(area_size), area_size); + TPD_DETAIL("%s: cmd write is : 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x.\n", __func__, SEC_CMD_GRIP_AREA, + area_size[0], area_size[1], area_size[2], area_size[3], area_size[4]); + TPD_DETAIL("%s: %s area size is %s %s in fw : [%d, %d] [%d %d].\n", __func__, + grip_zone->name, ret < 0 ? "failed" : "success", enable ? "change" : "remove", grip_zone->start_x, grip_zone->start_y, + grip_zone->x_width, grip_zone->y_width); + + return ret; +} + +static int sec_set_fw_grip_area(struct grip_zone_area *grip_zone, bool enable) +{ + int ret = 0, i = 0; + + if (!g_chip_info || !grip_zone || *g_chip_info->in_suspend) { + return -1; + } + + for (i = 0 ; i < ARRAY_SIZE(sec_grip); i ++) { + if (!strncmp(grip_zone->name, sec_grip[i].name, GRIP_TAG_SIZE)) { + if (sec_grip[i].handle_func) { + sec_grip[i].handle_func(grip_zone, enable); + } + break; + } + } + + if (i == ARRAY_SIZE(sec_grip)) { + TPD_DETAIL("%s: %s is not support in fw.\n", __func__, grip_zone->name); + return 0; + } else { + TPD_INFO("%s: %s %s in fw : [%d, %d] [%d %d] %d %d %d.\n", __func__, + grip_zone->name, enable ? "modify" : "remove", grip_zone->start_x, grip_zone->start_y, + grip_zone->x_width, grip_zone->y_width, grip_zone->exit_thd, + grip_zone->support_dir, grip_zone->grip_side); + } + + return ret; +} + +static int sec_set_no_handle_area(struct kernel_grip_info *grip_info) +{ + int ret = 0; + u8 edge_range[4] = {0}; //edge sereen function setting, y1,y2,direction + + if (!g_chip_info || !grip_info || *g_chip_info->in_suspend) { + return -1; + } + + /* + edge_range[0] = (grip_info->no_handle_y1 >> 4) & 0xFF; + edge_range[1] = (grip_info->no_handle_y1 & 0x0F) << 4 | ((grip_info->no_handle_y2 >> 8) & 0x0F); + edge_range[2] = grip_info->no_handle_y2 & 0xFF; + if (!grip_info->no_handle_dir) { + edge_range[3] = 0x01; + } else { + edge_range[3] = 0x00; + } + */ + + ret = touch_i2c_write_block(g_chip_info->client, SEC_CMD_EDGE_SCREEN, sizeof(edge_range), edge_range); + TPD_DETAIL("%s: cmd write is : 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x.\n", __func__, SEC_CMD_EDGE_SCREEN, + edge_range[0], edge_range[1], edge_range[2], edge_range[3]); + TPD_DETAIL("%s: No handle area is %s change in fw : [%d, %d, %d].\n", __func__, ret < 0 ? "failed" : "success", + grip_info->no_handle_dir, grip_info->no_handle_y1, grip_info->no_handle_y2); + + return ret; +} + +static int sec_set_condition_frame_limit(int frame_limit) +{ + int ret = 0; + u8 press_time[3] = {LONG_PRESS_ZONE, 0, 0xFF}; + + if (!g_chip_info || *g_chip_info->in_suspend) { + return -1; + } + + press_time[1] = frame_limit; + + ret = touch_i2c_write_block(g_chip_info->client, SEC_CMD_GRIP_PARA, sizeof(press_time), press_time); + TPD_DETAIL("%s: cmd write is : 0x%02x, 0x%02x, 0x%02x, 0x%02x.\n", __func__, SEC_CMD_GRIP_PARA, + press_time[0], press_time[1], press_time[2]); + TPD_DETAIL("%s: Condition frame limit is %s change in fw : frame_limit = %d.\n", __func__, ret < 0 ? "failed" : "success", frame_limit); + + return ret; +} + +static int sec_set_large_frame_limit(int frame_limit) +{ + int ret = 0; + u8 press_time[3] = {LARGE_TOUCH_REJECTION, 0, 0xFF}; + + if (!g_chip_info || *g_chip_info->in_suspend) { + return -1; + } + + press_time[1] = frame_limit; + + ret = touch_i2c_write_block(g_chip_info->client, SEC_CMD_GRIP_PARA, sizeof(press_time), press_time); + TPD_DETAIL("%s: cmd write is : 0x%02x, 0x%02x, 0x%02x, 0x%02x.\n", __func__, SEC_CMD_GRIP_PARA, + press_time[0], press_time[1], press_time[2]); + TPD_DETAIL("%s: large frame limit is %s change in fw : frame_limit = %d.\n", __func__, ret < 0 ? "failed" : "success", frame_limit); + + return ret; +} + +static int sec_set_large_corner_frame_limit(int frame_limit) +{ + int ret = 0; + u8 press_time[3] = {CORNER_LONG_PRESS_ZONE, 0, 0xFF}; + + if (!g_chip_info || *g_chip_info->in_suspend) { + return -1; + } + + press_time[1] = frame_limit; + + ret = touch_i2c_write_block(g_chip_info->client, SEC_CMD_GRIP_PARA, sizeof(press_time), press_time); + TPD_DETAIL("%s: cmd write is : 0x%02x, 0x%02x, 0x%02x, 0x%02x.\n", __func__, SEC_CMD_GRIP_PARA, + press_time[0], press_time[1], press_time[2]); + TPD_DETAIL("%s: large corner frame limit is %s change in fw : frame_limit = %d.\n", __func__, ret < 0 ? "failed" : "success", frame_limit); + + return ret; +} + +static int sec_set_large_thd(int large_thd) +{ + int ret = 0; + u8 touch_size[3] = {LARGE_TOUCH_REJECTION, 0xFF, 0}; + + if (!g_chip_info || *g_chip_info->in_suspend) { + return -1; + } + + touch_size[2] = large_thd; + + ret = touch_i2c_write_block(g_chip_info->client, SEC_CMD_GRIP_PARA, sizeof(touch_size), touch_size); + TPD_DETAIL("%s: cmd write is : 0x%02x, 0x%02x, 0x%02x, 0x%02x.\n", __func__, SEC_CMD_GRIP_PARA, + touch_size[0], touch_size[1], touch_size[2]); + TPD_DETAIL("%s: large ver thd is %s change in fw : large_thd = %d.\n", __func__, ret < 0 ? "failed" : "success", large_thd); + + return ret; +} + +static void sec_set_grip_touch_direction(uint8_t dir) +{ + int ret = -1; + u8 buf = 0x00; //direction enable, landscape grip area + + if (!g_chip_info) { + return; + } + + g_chip_info->touch_direction = dir; + + if (*g_chip_info->in_suspend) { + TPD_INFO("%s: set touch_direction in suspend: %d!\n", __func__, g_chip_info->touch_direction); + return; + } + + buf = dir; + ret = touch_i2c_write_byte(g_chip_info->client, SEC_CMD_GRIP_DIRECTION, buf); + + //disable wet mode while changing to horizontal + ret |= touch_i2c_write_byte(g_chip_info->client, SEC_CMD_WET_SWITCH, !!g_chip_info->touch_direction); + + TPD_INFO("%s: set touch_direction: %d %s!\n", __func__, g_chip_info->touch_direction, ret < 0 ? "failed" : "success"); +} + +static struct fw_grip_operations sec_fw_grip_op = { + .set_fw_grip_area = sec_set_fw_grip_area, + .set_touch_direction = sec_set_grip_touch_direction, + .set_no_handle_area = sec_set_no_handle_area, + .set_condition_frame_limit = sec_set_condition_frame_limit, + .set_large_frame_limit = sec_set_large_frame_limit, + .set_large_corner_frame_limit = sec_set_large_corner_frame_limit, + .set_large_ver_thd = sec_set_large_thd, +}; + static struct sec_proc_operations sec_proc_ops = { .auto_test = sec_auto_test, .verify_calibration = sec_verify_calibration, @@ -3413,6 +4021,13 @@ static int sec_tp_probe(struct i2c_client *client, const struct i2c_device_id *i sec_raw_device_init(ts); sec_create_proc(ts, &sec_proc_ops); + /* 7. kernel grip interface init*/ + if (ts->grip_info) { + if (ts->grip_info->grip_handle_in_fw) { + ts->grip_info->fw_ops = &sec_fw_grip_op; + } + } + #ifdef CONFIG_OPLUS_TP_APK sec_init_oplus_apk_op(ts); #endif // end of CONFIG_OPLUS_TP_APK diff --git a/drivers/input/touchscreen/oplus_touchscreen/Samsung/S6SY771/sec_drivers_s6sy771.h b/drivers/input/touchscreen/oplus_touchscreen/Samsung/S6SY771/sec_drivers_s6sy771.h index a11045ccc3..3e32221c36 100644 --- a/drivers/input/touchscreen/oplus_touchscreen/Samsung/S6SY771/sec_drivers_s6sy771.h +++ b/drivers/input/touchscreen/oplus_touchscreen/Samsung/S6SY771/sec_drivers_s6sy771.h @@ -13,6 +13,7 @@ #include #endif #include "../sec_common.h" +#include "../../touchpanel_prevention.h" /*********PART2:Define Area**********************/ #define GESTURE_DOUBLECLICK 0x00 @@ -322,4 +323,9 @@ struct chip_data_s6sy771 { #endif //end of CONFIG_OPLUS_TP_APK }; +struct sec_support_grip_zone { + char name[GRIP_TAG_SIZE]; + int (*handle_func) (struct grip_zone_area *grip_zone, bool enable); +}; + #endif diff --git a/drivers/input/touchscreen/oplus_touchscreen/Samsung/S6SY791/sec_drivers_s6sy791.c b/drivers/input/touchscreen/oplus_touchscreen/Samsung/S6SY791/sec_drivers_s6sy791.c index 0f463c3efc..1413af443c 100644 --- a/drivers/input/touchscreen/oplus_touchscreen/Samsung/S6SY791/sec_drivers_s6sy791.c +++ b/drivers/input/touchscreen/oplus_touchscreen/Samsung/S6SY791/sec_drivers_s6sy791.c @@ -57,6 +57,19 @@ static int sec_power_control(void *chip_data, bool enable); static int sec_get_verify_result(struct chip_data_s6sy791 *chip_info); static int sec_read_mutual(struct chip_data_s6sy791 *chip_info, u8 type, char *data, int len); static bool check_calibration(struct chip_data_s6sy791 *chip_info); +static int ver_bottom_large_handle_func(struct grip_zone_area *grip_zone, bool enable); +static int hor_corner_large_handle_func(struct grip_zone_area *grip_zone, bool enable); +static int long_size_dead_zone_handle_func(struct grip_zone_area *grip_zone, bool enable); +static int short_size_dead_zone_handle_func(struct grip_zone_area *grip_zone, bool enable); +static int long_size_condtion_zone_handle_func(struct grip_zone_area *grip_zone, bool enable); +static int short_size_condtion_zone_handle_func(struct grip_zone_area *grip_zone, bool enable); +static int long_size_large_zone_handle_func(struct grip_zone_area *grip_zone, bool enable); +static int short_size_large_zone_handle_func(struct grip_zone_area *grip_zone, bool enable); +static int sec_set_large_corner_frame_limit(int frame_limit); +static int sec_set_no_handle_area(struct kernel_grip_info *grip_info); +static int sec_set_condition_frame_limit(int frame_limit); +static int sec_set_large_frame_limit(int frame_limit); +static void sec_set_grip_touch_direction(uint8_t dir); static void sec_calibrate(struct seq_file *s, void *chip_data); static bool sec_get_cal_status(struct seq_file *s, void *chip_data); @@ -64,6 +77,26 @@ static bool sec_get_cal_status(struct seq_file *s, void *chip_data); /*************************** start of global variable delcare****************************************/ static struct chip_data_s6sy791 *g_chip_info; +static struct sec_support_grip_zone sec_grip[] = { + {"ver_left_bottom_large", ver_bottom_large_handle_func}, + //{"ver_right_bottom_large", ver_bottom_large_handle_func}, + {"hor90_left_corner_large", hor_corner_large_handle_func}, + //{"hor90_right_corner_large", hor_corner_large_handle_func}, + //{"hor270_left_corner_large", hor_corner_large_handle_func}, + //{"hor270_right_corner_large", hor_corner_large_handle_func}, + {"ver_left_dead", long_size_dead_zone_handle_func}, + //{"ver_right_dead", long_size_dead_zone_handle_func}, + {"hor_left_dead", short_size_dead_zone_handle_func}, + //{"hor_right_dead", short_size_dead_zone_handle_func}, + {"ver_left_condtion", long_size_condtion_zone_handle_func}, + //{"ver_right_condtion", long_size_condtion_zone_handle_func}, + {"hor_left_condtion", short_size_condtion_zone_handle_func}, + //{"hor_right_condtion", short_size_condtion_zone_handle_func}, + {"ver_left_large", long_size_large_zone_handle_func}, + //{"ver_right_large", long_size_large_zone_handle_func}, + {"hor_left_large", short_size_large_zone_handle_func}, + //{"hor_right_large", short_size_large_zone_handle_func}, +}; /**************************** end of global variable delcare*****************************************/ @@ -244,6 +277,87 @@ static int sec_enable_headset_mode(struct chip_data_s6sy791 *chip_info, bool ena return ret; } +static int sec_limit_switch_mode(struct chip_data_s6sy791 *chip_info, bool enable) +{ + int ret = -1; + unsigned char buf[5] = {0}; + unsigned char cmd[3] = {0}; + unsigned char extra_cmd[3] = {0}; + struct touchpanel_data *ts = i2c_get_clientdata(chip_info->client); + + if (ts == NULL) { + return ret; + } + + TPD_INFO("limit_switch is %d\n", ts->limit_switch); + if (ts->limit_switch == 1) { /*LANDSPACE*/ + cmd[0] = 0x01; + ret = touch_i2c_write_block(chip_info->client, SEC_CMD_GRIP_DIRECTION, 3, cmd); /*change mode*/ + } else if (ts->limit_switch == 2) { + cmd[0] = 0x02; + ret = touch_i2c_write_block(chip_info->client, SEC_CMD_GRIP_DIRECTION, 3, cmd); + } else { /*portrait*/ + cmd[0] = 0x00; + ret = touch_i2c_write_block(chip_info->client, SEC_CMD_GRIP_DIRECTION, 3, cmd); + } + /*dead zone type 1*/ + if ((ts->limit_switch == 1) || (ts->limit_switch == 2)) /*landscape*/ + buf[2] = ts->dead_zone_l; /*default x=15px*/ + else /*portrait*/ + buf[2] = ts->dead_zone_p; /*default x=15px*/ + + ret = touch_i2c_write_block(chip_info->client, SEC_CMD_GRIP_AREA, 5, buf); + /*dead zone type 2*/ + buf[0] = 0x01; + if ((ts->limit_switch == 1) || (ts->limit_switch == 2)) { /*landscape*/ + buf[2] = 0x50; /*x=80px*/ + buf[4] = 0x50; /*y=80px*/ + } else { /*portrait*/ + buf[2] = 0x1E; /*x=30px*/ + buf[4] = 0x82; /*y=130px*/ + } + ret = touch_i2c_write_block(chip_info->client, SEC_CMD_GRIP_AREA, 5, buf); + /*long press reject zone*/ + buf[0] = 0x02; + if (ts->project_info == 1) { /*19811*/ + buf[2] = 0x3C; /*x=60px*/ + buf[4] = 0x50; /*y=80px*/ + } else { + buf[2] = 0x1E; /*x=30px*/ + buf[4] = 0x32; /*y=50px*/ + } + ret = touch_i2c_write_block(chip_info->client, SEC_CMD_GRIP_AREA, 5, buf); + extra_cmd[0] = 0x02; + extra_cmd[1] = 0x14; + extra_cmd[2] = 0x46; + ret = touch_i2c_write_block(chip_info->client, SEC_CMD_GRIP_PARA, 3, extra_cmd); + /*large touch reject zone*/ + buf[0] = 0x03; + buf[2] = 0x64; /*x=100px*/ + buf[4] = 0x64; /*y=100px*/ + ret = touch_i2c_write_block(chip_info->client, SEC_CMD_GRIP_AREA, 5, buf); + extra_cmd[0] = 0x03; + extra_cmd[1] = 0x0F; + extra_cmd[2] = 0x28; + ret = touch_i2c_write_block(chip_info->client, SEC_CMD_GRIP_PARA, 3, extra_cmd); + /*corner long press reject zone*/ + buf[0] = 0x04; + if (ts->project_info == 1) { + buf[2] = 0x78; /*120px*/ + buf[4] = 0x78; /*120px*/ + } else { + buf[2] = 0x64; /*100px*/ + buf[4] = 0x64; /*100px*/ + } + ret = touch_i2c_write_block(chip_info->client, SEC_CMD_GRIP_AREA, 5, buf); + extra_cmd[0] = 0x04; + extra_cmd[1] = 0x32; + extra_cmd[2] = 0x00; + ret = touch_i2c_write_block(chip_info->client, SEC_CMD_GRIP_PARA, 3, extra_cmd); + + return ret; +} + static void sec_mdelay(unsigned int ms) { if (ms < 20) @@ -1589,6 +1703,13 @@ static int sec_mode_switch(void *chip_data, work_mode mode, bool flag) } break; + case MODE_LIMIT_SWITCH: + ret = sec_limit_switch_mode(chip_info, flag); + if (ret < 0) { + TPD_INFO("%s: limit switch: %d failed\n", __func__, flag); + } + break; + default: TPD_INFO("%s: Wrong mode.\n", __func__); } @@ -1623,6 +1744,57 @@ static uint8_t sec_get_touch_direction(void *chip_data) return chip_info->touch_direction; } +static void sec_enable_kernel_grip(void *chip_data, struct kernel_grip_info *grip_info) +{ + struct list_head *pos = NULL; + struct grip_zone_area *grip_zone = NULL; + //struct chip_data_s6sy791 *chip_info = (struct chip_data_s6sy791 *)chip_data; + int i = 0; + + if (!grip_info || !grip_info->grip_handle_in_fw) { + return; + } + + list_for_each(pos, &grip_info->large_zone_list) { + grip_zone = (struct grip_zone_area *)pos; + for (i = 0 ; i < ARRAY_SIZE(sec_grip); i ++) { + if (!strncmp(grip_zone->name, sec_grip[i].name, GRIP_TAG_SIZE)) { + if (sec_grip[i].handle_func) { + sec_grip[i].handle_func(grip_zone, true); + } + } + } + } + + list_for_each(pos, &grip_info->dead_zone_list) { + grip_zone = (struct grip_zone_area *)pos; + for (i = 0 ; i < ARRAY_SIZE(sec_grip); i ++) { + if (!strncmp(grip_zone->name, sec_grip[i].name, GRIP_TAG_SIZE)) { + if (sec_grip[i].handle_func) { + sec_grip[i].handle_func(grip_zone, true); + } + } + } + } + + list_for_each(pos, &grip_info->condition_zone_list) { + grip_zone = (struct grip_zone_area *)pos; + for (i = 0 ; i < ARRAY_SIZE(sec_grip); i ++) { + if (!strncmp(grip_zone->name, sec_grip[i].name, GRIP_TAG_SIZE)) { + if (sec_grip[i].handle_func) { + sec_grip[i].handle_func(grip_zone, true); + } + } + } + } + + sec_set_no_handle_area(grip_info); + sec_set_condition_frame_limit(grip_info->condition_frame_limit); + sec_set_large_frame_limit(grip_info->large_frame_limit); + sec_set_large_corner_frame_limit(grip_info->large_corner_frame_limit); + sec_set_grip_touch_direction(grip_info->touch_dir); +} + static void sec_rate_white_list_ctrl(void *chip_data, int value) { struct chip_data_s6sy791 *chip_info = (struct chip_data_s6sy791 *)chip_data; @@ -1651,6 +1823,7 @@ static struct oplus_touchpanel_operations sec_ops = { // .get_usb_state = sec_get_usb_state, .set_touch_direction = sec_set_touch_direction, .get_touch_direction = sec_get_touch_direction, + .enable_kernel_grip = sec_enable_kernel_grip, .enable_fingerprint = sec_enable_fingerprint_mode, .screenon_fingerprint_info = sec_get_fingerprint_info, .enable_gesture_mask = sec_enable_gesture_mask, @@ -3011,6 +3184,441 @@ static bool sec_get_cal_status(struct seq_file *s, void *chip_data) return chip_info->cal_needed; } +static int ver_bottom_large_handle_func(struct grip_zone_area *grip_zone, bool enable) +{ + int ret = 0; + u8 area_size[5] = {CORNER_LONG_PRESS_ZONE, 0, 0, 0, 0}; + + if (!g_chip_info || !grip_zone || *g_chip_info->in_suspend) { + return -1; + } + + if (enable) { + if ((grip_zone->grip_side >> TYPE_LONG_CORNER_SIDE) & 0x01) { + area_size[1] = (grip_zone->x_width >> 8) & 0xFF; + area_size[2] = grip_zone->x_width & 0xFF; + area_size[3] = (grip_zone->y_width >> 8) & 0xFF; + area_size[4] = grip_zone->y_width & 0xFF; + } else if ((grip_zone->grip_side >> TYPE_SHORT_CORNER_SIDE) & 0x01) { + area_size[1] = (grip_zone->y_width >> 8) & 0xFF; + area_size[2] = grip_zone->y_width & 0xFF; + area_size[3] = (grip_zone->x_width >> 8) & 0xFF; + area_size[4] = grip_zone->x_width & 0xFF; + } else if ((grip_zone->grip_side >> TYPE_LONG_SIDE) & 0x01) { + area_size[1] = (grip_zone->x_width >> 8) & 0xFF; + area_size[2] = grip_zone->x_width & 0xFF; + } else if ((grip_zone->grip_side >> TYPE_SHORT_SIDE) & 0x01) { + area_size[1] = (grip_zone->y_width >> 8) & 0xFF; + area_size[2] = grip_zone->y_width & 0xFF; + } + } + + ret = touch_i2c_write_byte(g_chip_info->client, SEC_CMD_GRIP_DIRECTION, 0x00); + ret |= touch_i2c_write_block(g_chip_info->client, SEC_CMD_GRIP_AREA, sizeof(area_size), area_size); + ret |= touch_i2c_write_byte(g_chip_info->client, SEC_CMD_GRIP_DIRECTION, g_chip_info->touch_direction); + TPD_DETAIL("%s: cmd write is : 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x.\n", __func__, SEC_CMD_GRIP_AREA, + area_size[0], area_size[1], area_size[2], area_size[3], area_size[4]); + TPD_DETAIL("%s: %s area size is %s %s in fw : [%d, %d] [%d %d].\n", __func__, + grip_zone->name, ret < 0 ? "failed" : "success", enable ? "change" : "remove", grip_zone->start_x, grip_zone->start_y, + grip_zone->x_width, grip_zone->y_width); + + return ret; +} + +static int hor_corner_large_handle_func(struct grip_zone_area *grip_zone, bool enable) +{ + int ret = 0; + u8 area_size[5] = {CORNER_LONG_PRESS_ZONE, 0, 0, 0, 0}; + + if (!g_chip_info || !grip_zone || *g_chip_info->in_suspend) { + return -1; + } + + if (enable) { + if ((grip_zone->grip_side >> TYPE_LONG_CORNER_SIDE) & 0x01) { + area_size[1] = (grip_zone->x_width >> 8) & 0xFF; + area_size[2] = grip_zone->x_width & 0xFF; + area_size[3] = (grip_zone->y_width >> 8) & 0xFF; + area_size[4] = grip_zone->y_width & 0xFF; + } else if ((grip_zone->grip_side >> TYPE_SHORT_CORNER_SIDE) & 0x01) { + area_size[1] = (grip_zone->y_width >> 8) & 0xFF; + area_size[2] = grip_zone->y_width & 0xFF; + area_size[3] = (grip_zone->x_width >> 8) & 0xFF; + area_size[4] = grip_zone->x_width & 0xFF; + } else if ((grip_zone->grip_side >> TYPE_LONG_SIDE) & 0x01) { + area_size[1] = (grip_zone->x_width >> 8) & 0xFF; + area_size[2] = grip_zone->x_width & 0xFF; + } else if ((grip_zone->grip_side >> TYPE_SHORT_SIDE) & 0x01) { + area_size[1] = (grip_zone->y_width >> 8) & 0xFF; + area_size[2] = grip_zone->y_width & 0xFF; + } + } + + ret = touch_i2c_write_byte(g_chip_info->client, SEC_CMD_GRIP_DIRECTION, 0x01); + ret |= touch_i2c_write_block(g_chip_info->client, SEC_CMD_GRIP_AREA, sizeof(area_size), area_size); + ret |= touch_i2c_write_byte(g_chip_info->client, SEC_CMD_GRIP_DIRECTION, g_chip_info->touch_direction); + TPD_DETAIL("%s: cmd write is : 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x.\n", __func__, SEC_CMD_GRIP_AREA, + area_size[0], area_size[1], area_size[2], area_size[3], area_size[4]); + TPD_DETAIL("%s: %s area size is %s %s in fw : [%d, %d] [%d %d].\n", __func__, + grip_zone->name, ret < 0 ? "failed" : "success", enable ? "change" : "remove", grip_zone->start_x, grip_zone->start_y, + grip_zone->x_width, grip_zone->y_width); + + return ret; +} + +static int long_size_dead_zone_handle_func(struct grip_zone_area *grip_zone, bool enable) +{ + int ret = 0; + u8 area_size[5] = {DEAD_ZONE_TYPE_1, 0, 0, 0xFF, 0xFF}; + + if (!g_chip_info || !grip_zone || *g_chip_info->in_suspend) { + return -1; + } + + if (enable) { + if ((grip_zone->grip_side >> TYPE_LONG_SIDE) & 0x01) { + area_size[1] = (grip_zone->x_width >> 8) & 0xFF; + area_size[2] = grip_zone->x_width & 0xFF; + } else if ((grip_zone->grip_side >> TYPE_SHORT_SIDE) & 0x01) { + area_size[1] = (grip_zone->y_width >> 8) & 0xFF; + area_size[2] = grip_zone->y_width & 0xFF; + } + } + + ret = touch_i2c_write_block(g_chip_info->client, SEC_CMD_GRIP_AREA, sizeof(area_size), area_size); + TPD_DETAIL("%s: cmd write is : 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x.\n", __func__, SEC_CMD_GRIP_AREA, + area_size[0], area_size[1], area_size[2], area_size[3], area_size[4]); + TPD_DETAIL("%s: %s area size is %s %s in fw : [%d, %d] [%d %d].\n", __func__, + grip_zone->name, ret < 0 ? "failed" : "success", enable ? "change" : "remove", grip_zone->start_x, grip_zone->start_y, + grip_zone->x_width, grip_zone->y_width); + + return ret; +} + +static int short_size_dead_zone_handle_func(struct grip_zone_area *grip_zone, bool enable) +{ + int ret = 0; + u8 area_size[5] = {DEAD_ZONE_TYPE_1, 0xFF, 0xFF, 0, 0}; + + if (!g_chip_info || !grip_zone || *g_chip_info->in_suspend) { + return -1; + } + + if (enable) { + if ((grip_zone->grip_side >> TYPE_LONG_SIDE) & 0x01) { + area_size[3] = (grip_zone->x_width >> 8) & 0xFF; + area_size[4] = grip_zone->x_width & 0xFF; + } else if ((grip_zone->grip_side >> TYPE_SHORT_SIDE) & 0x01) { + area_size[3] = (grip_zone->y_width >> 8) & 0xFF; + area_size[4] = grip_zone->y_width & 0xFF; + } + } + + ret = touch_i2c_write_block(g_chip_info->client, SEC_CMD_GRIP_AREA, sizeof(area_size), area_size); + TPD_DETAIL("%s: cmd write is : 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x.\n", __func__, SEC_CMD_GRIP_AREA, + area_size[0], area_size[1], area_size[2], area_size[3], area_size[4]); + TPD_DETAIL("%s: %s area size is %s %s in fw : [%d, %d] [%d %d].\n", __func__, + grip_zone->name, ret < 0 ? "failed" : "success", enable ? "change" : "remove", grip_zone->start_x, grip_zone->start_y, + grip_zone->x_width, grip_zone->y_width); + + return ret; +} + +static int long_size_condtion_zone_handle_func(struct grip_zone_area *grip_zone, bool enable) +{ + int ret = 0; + u8 area_size[5] = {LONG_PRESS_ZONE, 0, 0, 0xFF, 0xFF}; + u8 exit_thd[3] = {LONG_PRESS_ZONE, 0xFF, 0}; + + if (!g_chip_info || !grip_zone || *g_chip_info->in_suspend) { + return -1; + } + + if (enable) { + if ((grip_zone->grip_side >> TYPE_LONG_SIDE) & 0x01) { + area_size[1] = (grip_zone->x_width >> 8) & 0xFF; + area_size[2] = grip_zone->x_width & 0xFF; + } else if ((grip_zone->grip_side >> TYPE_SHORT_SIDE) & 0x01) { + area_size[1] = (grip_zone->y_width >> 8) & 0xFF; + area_size[2] = grip_zone->y_width & 0xFF; + } + } + + ret = touch_i2c_write_block(g_chip_info->client, SEC_CMD_GRIP_AREA, sizeof(area_size), area_size); + TPD_DETAIL("%s: cmd write is : 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x.\n", __func__, SEC_CMD_GRIP_AREA, + area_size[0], area_size[1], area_size[2], area_size[3], area_size[4]); + TPD_DETAIL("%s: %s area size is %s %s in fw : [%d, %d] [%d %d].\n", __func__, + grip_zone->name, ret < 0 ? "failed" : "success", enable ? "change" : "remove", grip_zone->start_x, grip_zone->start_y, + grip_zone->x_width, grip_zone->y_width); + + if (enable) { + exit_thd[2] = grip_zone->exit_thd & 0xFF; + ret = touch_i2c_write_block(g_chip_info->client, SEC_CMD_GRIP_PARA, sizeof(exit_thd), exit_thd); + TPD_DETAIL("%s: cmd is : 0x%02x, 0x%02x, 0x%02x, 0x%02x.\n", __func__, SEC_CMD_GRIP_PARA, exit_thd[0], exit_thd[1], exit_thd[2]); + TPD_DETAIL("%s: %s exit thd is %s change in fw : %d.\n", __func__, + grip_zone->name, ret < 0 ? "failed" : "success", grip_zone->exit_thd); + } + + return ret; +} + +static int short_size_condtion_zone_handle_func(struct grip_zone_area *grip_zone, bool enable) +{ + int ret = 0; + u8 area_size[5] = {LONG_PRESS_ZONE, 0xFF, 0xFF, 0, 0,}; + + if (!g_chip_info || !grip_zone || *g_chip_info->in_suspend){ + return -1; + } + + if (enable) { + if ((grip_zone->grip_side >> TYPE_LONG_SIDE) & 0x01) { + area_size[3] = (grip_zone->x_width >> 8) & 0xFF; + area_size[4] = grip_zone->x_width & 0xFF; + } else if ((grip_zone->grip_side >> TYPE_SHORT_SIDE) & 0x01) { + area_size[3] = (grip_zone->y_width >> 8) & 0xFF; + area_size[4] = grip_zone->y_width & 0xFF; + } + } + + ret = touch_i2c_write_block(g_chip_info->client, SEC_CMD_GRIP_AREA, sizeof(area_size), area_size); + TPD_DETAIL("%s: cmd write is : 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x.\n", __func__, SEC_CMD_GRIP_AREA, + area_size[0], area_size[1], area_size[2], area_size[3], area_size[4]); + TPD_DETAIL("%s: %s area size is %s %s in fw : [%d, %d] [%d %d].\n", __func__, + grip_zone->name, ret < 0 ? "failed" : "success", enable ? "change" : "remove", grip_zone->start_x, grip_zone->start_y, + grip_zone->x_width, grip_zone->y_width); + + return ret; +} + +static int long_size_large_zone_handle_func(struct grip_zone_area *grip_zone, bool enable) +{ + int ret = 0; + u8 area_size[5] = {LARGE_TOUCH_REJECTION, 0, 0, 0xFF, 0xFF}; + + if (!g_chip_info || !grip_zone || *g_chip_info->in_suspend) { + return -1; + } + + if (enable) { + if ((grip_zone->grip_side >> TYPE_LONG_SIDE) & 0x01) { + area_size[1] = (grip_zone->x_width >> 8) & 0xFF; + area_size[2] = grip_zone->x_width & 0xFF; + } else if ((grip_zone->grip_side >> TYPE_SHORT_SIDE) & 0x01) { + area_size[1] = (grip_zone->y_width >> 8) & 0xFF; + area_size[2] = grip_zone->y_width & 0xFF; + } + } + + ret = touch_i2c_write_block(g_chip_info->client, SEC_CMD_GRIP_AREA, sizeof(area_size), area_size); + TPD_DETAIL("%s: cmd write is : 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x.\n", __func__, SEC_CMD_GRIP_AREA, + area_size[0], area_size[1], area_size[2], area_size[3], area_size[4]); + TPD_DETAIL("%s: %s area size is %s %s in fw : [%d, %d] [%d %d].\n", __func__, + grip_zone->name, ret < 0 ? "failed" : "success", enable ? "change" : "remove", grip_zone->start_x, grip_zone->start_y, + grip_zone->x_width, grip_zone->y_width); + + return ret; +} + +static int short_size_large_zone_handle_func(struct grip_zone_area *grip_zone, bool enable) +{ + int ret = 0; + u8 area_size[5] = {LARGE_TOUCH_REJECTION, 0xFF, 0xFF, 0, 0}; + + if (!g_chip_info || !grip_zone || *g_chip_info->in_suspend) { + return -1; + } + + if (enable) { + if ((grip_zone->grip_side >> TYPE_LONG_SIDE) & 0x01) { + area_size[3] = (grip_zone->x_width >> 8) & 0xFF; + area_size[4] = grip_zone->x_width & 0xFF; + } else if ((grip_zone->grip_side >> TYPE_SHORT_SIDE) & 0x01) { + area_size[3] = (grip_zone->y_width >> 8) & 0xFF; + area_size[4] = grip_zone->y_width & 0xFF; + } + } + + ret = touch_i2c_write_block(g_chip_info->client, SEC_CMD_GRIP_AREA, sizeof(area_size), area_size); + TPD_DETAIL("%s: cmd write is : 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x.\n", __func__, SEC_CMD_GRIP_AREA, + area_size[0], area_size[1], area_size[2], area_size[3], area_size[4]); + TPD_DETAIL("%s: %s area size is %s %s in fw : [%d, %d] [%d %d].\n", __func__, + grip_zone->name, ret < 0 ? "failed" : "success", enable ? "change" : "remove", grip_zone->start_x, grip_zone->start_y, + grip_zone->x_width, grip_zone->y_width); + + return ret; +} + +static int sec_set_fw_grip_area(struct grip_zone_area *grip_zone, bool enable) +{ + int ret = 0, i = 0; + + if (!g_chip_info || !grip_zone || *g_chip_info->in_suspend) { + return -1; + } + + for (i = 0 ; i < ARRAY_SIZE(sec_grip); i ++) { + if (!strncmp(grip_zone->name, sec_grip[i].name, GRIP_TAG_SIZE)) { + if (sec_grip[i].handle_func) { + sec_grip[i].handle_func(grip_zone, enable); + } + break; + } + } + + if (i == ARRAY_SIZE(sec_grip)) { + TPD_DETAIL("%s: %s is not support in fw.\n", __func__, grip_zone->name); + return 0; + } else { + TPD_INFO("%s: %s %s in fw : [%d, %d] [%d %d] %d %d %d.\n", __func__, + grip_zone->name, enable ? "modify" : "remove", grip_zone->start_x, grip_zone->start_y, + grip_zone->x_width, grip_zone->y_width, grip_zone->exit_thd, + grip_zone->support_dir, grip_zone->grip_side); + } + + return ret; +} + +static int sec_set_no_handle_area(struct kernel_grip_info *grip_info) +{ + int ret = 0; + u8 edge_range[4] = {0}; //edge sereen function setting, y1,y2,direction + + if (!g_chip_info || !grip_info || *g_chip_info->in_suspend) { + return -1; + } + + // only portrait mode need set this area + if (g_chip_info->touch_direction == 0) { + edge_range[0] = (grip_info->no_handle_y1 >> 4) & 0xFF; + edge_range[1] = (grip_info->no_handle_y1 & 0x0F) << 4 | ((grip_info->no_handle_y2 >> 8) & 0x0F); + edge_range[2] = grip_info->no_handle_y2 & 0xFF; + if (!grip_info->no_handle_dir) { + edge_range[3] = 0x01; + } else { + edge_range[3] = 0x00; + } + } + + ret = touch_i2c_write_block(g_chip_info->client, SEC_CMD_EDGE_SCREEN, sizeof(edge_range), edge_range); + TPD_DETAIL("%s: cmd write is : 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x.\n", __func__, SEC_CMD_EDGE_SCREEN, + edge_range[0], edge_range[1], edge_range[2], edge_range[3]); + TPD_DETAIL("%s: No handle area is %s change in fw : [%d, %d, %d].\n", __func__, ret < 0 ? "failed" : "success", + grip_info->no_handle_dir, grip_info->no_handle_y1, grip_info->no_handle_y2); + + return ret; +} + +static int sec_set_condition_frame_limit(int frame_limit) +{ + int ret = 0; + u8 press_time[3] = {LONG_PRESS_ZONE, 0, 0xFF}; + + if (!g_chip_info || *g_chip_info->in_suspend) { + return -1; + } + + press_time[1] = frame_limit; + + ret = touch_i2c_write_block(g_chip_info->client, SEC_CMD_GRIP_PARA, sizeof(press_time), press_time); + TPD_DETAIL("%s: cmd write is : 0x%02x, 0x%02x, 0x%02x, 0x%02x.\n", __func__, SEC_CMD_GRIP_PARA, + press_time[0], press_time[1], press_time[2]); + TPD_DETAIL("%s: Condition frame limit is %s change in fw : frame_limit = %d.\n", __func__, ret < 0 ? "failed" : "success", frame_limit); + + return ret; +} + +static int sec_set_large_frame_limit(int frame_limit) +{ + int ret = 0; + u8 press_time[3] = {LARGE_TOUCH_REJECTION, 0, 0xFF}; + + if (!g_chip_info || *g_chip_info->in_suspend) { + return -1; + } + + press_time[1] = frame_limit; + + ret = touch_i2c_write_block(g_chip_info->client, SEC_CMD_GRIP_PARA, sizeof(press_time), press_time); + TPD_DETAIL("%s: cmd write is : 0x%02x, 0x%02x, 0x%02x, 0x%02x.\n", __func__, SEC_CMD_GRIP_PARA, + press_time[0], press_time[1], press_time[2]); + TPD_DETAIL("%s: large frame limit is %s change in fw : frame_limit = %d.\n", __func__, ret < 0 ? "failed" : "success", frame_limit); + + return ret; +} + +static int sec_set_large_corner_frame_limit(int frame_limit) +{ + int ret = 0; + u8 press_time[3] = {CORNER_LONG_PRESS_ZONE, 0, 0xFF}; + + if (!g_chip_info || *g_chip_info->in_suspend) { + return -1; + } + + press_time[1] = frame_limit; + + ret = touch_i2c_write_block(g_chip_info->client, SEC_CMD_GRIP_PARA, sizeof(press_time), press_time); + TPD_DETAIL("%s: cmd write is : 0x%02x, 0x%02x, 0x%02x, 0x%02x.\n", __func__, SEC_CMD_GRIP_PARA, + press_time[0], press_time[1], press_time[2]); + TPD_DETAIL("%s: large corner frame limit is %s change in fw : frame_limit = %d.\n", __func__, ret < 0 ? "failed" : "success", frame_limit); + + return ret; +} + +static int sec_set_large_thd(int large_thd) +{ + int ret = 0; + u8 touch_size[3] = {LARGE_TOUCH_REJECTION, 0xFF, 0}; + + if (!g_chip_info || *g_chip_info->in_suspend) { + return -1; + } + + touch_size[2] = large_thd; + + ret = touch_i2c_write_block(g_chip_info->client, SEC_CMD_GRIP_PARA, sizeof(touch_size), touch_size); + TPD_DETAIL("%s: cmd write is : 0x%02x, 0x%02x, 0x%02x, 0x%02x.\n", __func__, SEC_CMD_GRIP_PARA, + touch_size[0], touch_size[1], touch_size[2]); + TPD_DETAIL("%s: large ver thd is %s change in fw : large_thd = %d.\n", __func__, ret < 0 ? "failed" : "success", large_thd); + + return ret; +} + +static void sec_set_grip_touch_direction(uint8_t dir) +{ + int ret = -1; + u8 buf = 0x00; //direction enable, landscape grip area + + if (!g_chip_info) { + return; + } + + g_chip_info->touch_direction = dir; + + if (*g_chip_info->in_suspend) { + TPD_INFO("%s: set touch_direction in suspend: %d!\n", __func__, g_chip_info->touch_direction); + return; + } + + buf = dir; + ret = touch_i2c_write_byte(g_chip_info->client, SEC_CMD_GRIP_DIRECTION, buf); + + //disable wet mode while changing to horizontal + ret |= touch_i2c_write_byte(g_chip_info->client, SEC_CMD_WET_SWITCH, !!g_chip_info->touch_direction); + + TPD_INFO("%s: set touch_direction: %d %s!\n", __func__, g_chip_info->touch_direction, ret < 0 ? "failed" : "success"); +} + +static struct fw_grip_operations sec_fw_grip_op = { + .set_fw_grip_area = sec_set_fw_grip_area, + .set_touch_direction = sec_set_grip_touch_direction, + .set_no_handle_area = sec_set_no_handle_area, + .set_condition_frame_limit = sec_set_condition_frame_limit, + .set_large_frame_limit = sec_set_large_frame_limit, + .set_large_corner_frame_limit = sec_set_large_corner_frame_limit, + .set_large_ver_thd = sec_set_large_thd, +}; static struct sec_proc_operations sec_proc_ops = { .auto_test = sec_auto_test, @@ -3316,6 +3924,13 @@ static int sec_tp_probe(struct i2c_client *client, const struct i2c_device_id *i sec_raw_device_init(ts); sec_create_proc(ts, &sec_proc_ops); + /* 7. kernel grip interface init*/ + if (ts->grip_info) { + if (ts->grip_info->grip_handle_in_fw) { + ts->grip_info->fw_ops = &sec_fw_grip_op; + } + } + #ifdef CONFIG_OPLUS_TP_APK sec_init_oplus_apk_op(ts); #endif // end of CONFIG_OPLUS_TP_APK diff --git a/drivers/input/touchscreen/oplus_touchscreen/Samsung/S6SY791/sec_drivers_s6sy791.h b/drivers/input/touchscreen/oplus_touchscreen/Samsung/S6SY791/sec_drivers_s6sy791.h index 0d9dcea089..a7a105e3b8 100644 --- a/drivers/input/touchscreen/oplus_touchscreen/Samsung/S6SY791/sec_drivers_s6sy791.h +++ b/drivers/input/touchscreen/oplus_touchscreen/Samsung/S6SY791/sec_drivers_s6sy791.h @@ -13,6 +13,7 @@ #include #endif #include "../sec_common.h" +#include "../../touchpanel_prevention.h" /*********PART2:Define Area**********************/ #define GESTURE_DOUBLECLICK 0x00 @@ -312,4 +313,9 @@ struct chip_data_s6sy791 { #endif //end of CONFIG_OPLUS_TP_APK }; +struct sec_support_grip_zone { + char name[GRIP_TAG_SIZE]; + int (*handle_func) (struct grip_zone_area *grip_zone, bool enable); +}; + #endif diff --git a/drivers/input/touchscreen/oplus_touchscreen/touchpanel_common.h b/drivers/input/touchscreen/oplus_touchscreen/touchpanel_common.h index 07f132fcb2..67138d3e4a 100644 --- a/drivers/input/touchscreen/oplus_touchscreen/touchpanel_common.h +++ b/drivers/input/touchscreen/oplus_touchscreen/touchpanel_common.h @@ -191,6 +191,7 @@ typedef enum { MODE_FACE_DETECT, MODE_HEADSET, MODE_WIRELESS_CHARGE, + MODE_LIMIT_SWITCH, MODE_PEN_SCAN, } work_mode; @@ -1020,6 +1021,16 @@ struct touchpanel_data { u64 irq_interval;/*Record the interruption time to calculate the reporting rate*/ u64 irq_handle_time;/*Record the interruption handle time*/ int high_frame_value; + + u8 limit_switch; + int dead_zone_l; /*landscape dead zone*/ + int dead_zone_p; /*portrait dead zone*/ + int corner_dead_zone_xl; + int corner_dead_zone_yl; + int corner_dead_zone_xp; + int corner_dead_zone_yp; + bool project_info; /*different project using different parameter*/ + bool oos_edge_limit_support; /*oos system edge_limit support feature*/ }; #ifdef CONFIG_OPLUS_TP_APK diff --git a/drivers/input/touchscreen/oplus_touchscreen/touchpanel_common_driver.c b/drivers/input/touchscreen/oplus_touchscreen/touchpanel_common_driver.c index ec039d4e6d..4aa9a448b1 100644 --- a/drivers/input/touchscreen/oplus_touchscreen/touchpanel_common_driver.c +++ b/drivers/input/touchscreen/oplus_touchscreen/touchpanel_common_driver.c @@ -269,6 +269,10 @@ void operate_mode_switch(struct touchpanel_data *ts) ts->ts_ops->tp_refresh_switch(ts->chip_data, ts->lcd_fps); } + if (ts->oos_edge_limit_support) { + ts->ts_ops->mode_switch(ts->chip_data, MODE_LIMIT_SWITCH, ts->limit_switch); + } + ts->ts_ops->mode_switch(ts->chip_data, MODE_NORMAL, true); } } @@ -2710,6 +2714,226 @@ static const struct file_operations proc_limit_area_ops = { .owner = THIS_MODULE, }; +static ssize_t proc_limit_switch_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) +{ + int value = 0; + char buf[4] = {0}; + struct touchpanel_data *ts = PDE_DATA(file_inode(file)); + + if (count > 4) { + TPD_INFO("%s:count > 4\n", __func__); + return count; + } + + if (!ts) { + TPD_INFO("%s: ts is NULL\n", __func__); + return count; + } + + if (copy_from_user(buf, buffer, count)) { + TPD_INFO("%s: read proc input error.\n", __func__); + return count; + } + sscanf(buf, "%d", &value); + ts->limit_switch = value; + + TPD_DEBUG("%s: ts->limit_switch = %d\n", __func__, value); + if (ts->is_suspended == 0) { + mutex_lock(&ts->mutex); + ts->ts_ops->mode_switch(ts->chip_data, MODE_LIMIT_SWITCH, ts->limit_switch); + mutex_unlock(&ts->mutex); + } + return count; +} + +static ssize_t proc_limit_switch_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) +{ + int ret = 0; + char page[4] = {0}; + struct touchpanel_data *ts = PDE_DATA(file_inode(file)); + + if (!ts) { + sprintf(page, "%d\n", -1); /*no support*/ + } else { + sprintf(page, "%d\n", ts->limit_switch); /*support*/ + } + ret = simple_read_from_buffer(user_buf, count, ppos, page, strlen(page)); + return ret; +} + +static ssize_t proc_dead_zone_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) +{ + char buf[8] = {0}; + int data[6] = {0}; + int ret = -1; + struct touchpanel_data *ts = PDE_DATA(file_inode(file)); + + if (!ts) { + TPD_INFO("%s: ts is NULL\n", __func__); + return count; + } + + ret = copy_from_user(buf, buffer, count); + if (ret) { + TPD_INFO("%s: read proc input error.\n", __func__); + return count; + } + + if (sscanf(buf, "%d,%d", &data[0], &data[1]) == 2) { + if (data[0] > 50 || data[1] > 50) { + TPD_INFO("data not allow\n"); + return count; + } + ts->dead_zone_l = data[0]; + ts->dead_zone_p = data[1]; + } + TPD_INFO("data[0] is %d, data[1] is %d\n", data[0], data[1]); + + if (ts->is_suspended == 0) { + mutex_lock(&ts->mutex); + ts->ts_ops->mode_switch(ts->chip_data, MODE_LIMIT_SWITCH, ts->limit_switch); + mutex_unlock(&ts->mutex); + } + return count; +} + +static ssize_t proc_dead_zone_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) +{ + int ret = 0; + char page[9] = {0}; + struct touchpanel_data *ts = PDE_DATA(file_inode(file)); + + if (!ts) { + sprintf(page, "%d\n", -1); /*no support*/ + } else { + sprintf(page, "%d,%d\n", ts->dead_zone_l, ts->dead_zone_p); + } + ret = simple_read_from_buffer(user_buf, count, ppos, page, strlen(page)); + return ret; +} + +static const struct file_operations proc_limit_switch_fops = { + .write = proc_limit_switch_write, + .read = proc_limit_switch_read, + .open = simple_open, + .owner = THIS_MODULE, +}; + +static const struct file_operations proc_tp_dead_zone_fops = { + .write = proc_dead_zone_write, + .read = proc_dead_zone_read, + .open = simple_open, + .owner = THIS_MODULE, +}; + +static ssize_t proc_corner_dead_zone_l_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) +{ + char buf[8] = {0}; + int data[6] = {0}; + int ret = -1; + struct touchpanel_data *ts = PDE_DATA(file_inode(file)); + + if (!ts) { + TPD_INFO("%s: ts is NULL\n", __func__); + return count; + } + + ret = copy_from_user(buf, buffer, count); + if (ret) { + TPD_INFO("%s: read proc input error.\n", __func__); + return count; + } + + if (sscanf(buf, "%d,%d", &data[0], &data[1]) == 2) { + ts->corner_dead_zone_xl = data[0]; + ts->corner_dead_zone_yl = data[1]; + } + TPD_INFO("data[0] is %d, data[1] is %d\n", data[0], data[1]); + + if (ts->is_suspended == 0) { + mutex_lock(&ts->mutex); + ts->ts_ops->mode_switch(ts->chip_data, MODE_LIMIT_SWITCH, ts->limit_switch); + mutex_unlock(&ts->mutex); + } + return count; +} + +static ssize_t proc_corner_dead_zone_l_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) +{ + int ret = 0; + char page[9] = {0}; + struct touchpanel_data *ts = PDE_DATA(file_inode(file)); + + if (!ts) { + sprintf(page, "%d\n", -1); + } else { + sprintf(page, "%d,%d\n", ts->corner_dead_zone_xl, ts->corner_dead_zone_yl); + } + ret = simple_read_from_buffer(user_buf, count, ppos, page, strlen(page)); + return ret; +} + +static const struct file_operations proc_tp_corner_dead_zone_l_fops = { + .write = proc_corner_dead_zone_l_write, + .read = proc_corner_dead_zone_l_read, + .open = simple_open, + .owner = THIS_MODULE, +}; + +static ssize_t proc_corner_dead_zone_p_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) +{ + char buf[8] = {0}; + int data[6] = {0}; + int ret = -1; + struct touchpanel_data *ts = PDE_DATA(file_inode(file)); + + if (!ts) { + TPD_INFO("%s: ts is NULL\n", __func__); + return count; + } + + ret = copy_from_user(buf, buffer, count); + if (ret) { + TPD_INFO("%s: read proc input error.\n", __func__); + return count; + } + + if (sscanf(buf, "%d,%d", &data[0], &data[1]) == 2) { + ts->corner_dead_zone_xp = data[0]; + ts->corner_dead_zone_yp = data[1]; + } + TPD_INFO("data[0] is %d, data[1] is %d\n", data[0], data[1]); + + if (ts->is_suspended == 0) { + mutex_lock(&ts->mutex); + ts->ts_ops->mode_switch(ts->chip_data, MODE_LIMIT_SWITCH, ts->limit_switch); + mutex_unlock(&ts->mutex); + } + return count; +} + +static ssize_t proc_corner_dead_zone_p_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) +{ + int ret = 0; + char page[9] = {0}; + struct touchpanel_data *ts = PDE_DATA(file_inode(file)); + + if (!ts) { + sprintf(page, "%d\n", -1); + } else { + sprintf(page, "%d,%d\n", ts->corner_dead_zone_xp, ts->corner_dead_zone_yp); + } + ret = simple_read_from_buffer(user_buf, count, ppos, page, strlen(page)); + return ret; +} + +static const struct file_operations proc_tp_corner_dead_zone_p_fops = { + .write = proc_corner_dead_zone_p_write, + .read = proc_corner_dead_zone_p_read, + .open = simple_open, + .owner = THIS_MODULE, +}; + static ssize_t proc_limit_control_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { ssize_t ret = 0; @@ -2865,6 +3089,15 @@ static ssize_t proc_dir_control_write(struct file *file, const char __user *buff ts->edge_limit.limit_area, ts->edge_limit.left_y1, ts->edge_limit.right_y1, ts->edge_limit.left_y2, ts->edge_limit.right_y2, ts->edge_limit.left_y3, ts->edge_limit.right_y3); } + if (ts->oos_edge_limit_support) { + ts->limit_switch = temp; + + TPD_INFO("%s: ts->limit_switch = %d\n", __func__, temp); + if (ts->is_suspended == 0) { + ts->ts_ops->mode_switch(ts->chip_data, MODE_LIMIT_SWITCH, ts->limit_switch); + } + } + mutex_unlock(&ts->mutex); return count; @@ -4656,6 +4889,38 @@ static int init_touchpanel_proc(struct touchpanel_data *ts) } } + if (ts->oos_edge_limit_support) { + prEntry_tmp = proc_create_data("tpedge_limit_enable", 0666, prEntry_tp, &proc_limit_switch_fops, ts); + if (prEntry_tmp == NULL) { + ret = -ENOMEM; + TPD_INFO("%s: Couldn't create proc entry, %d\n", __func__, __LINE__); + } + + prEntry_tmp = proc_create_data("tp_switch_dead_zone", 0666, prEntry_tp, &proc_tp_dead_zone_fops, ts); + if (prEntry_tmp == NULL) { + ret = -ENOMEM; + TPD_INFO("%s: Couldn't create proc entry, %d\n", __func__, __LINE__); + } + + prEntry_tmp = proc_create_data("tp_switch_corner_dead_l_zone", 0666, prEntry_tp, &proc_tp_corner_dead_zone_l_fops, ts); + if (prEntry_tmp == NULL) { + ret = -ENOMEM; + TPD_INFO("%s: Couldn't create proc entry, %d\n", __func__, __LINE__); + } + + prEntry_tmp = proc_create_data("tp_switch_corner_dead_p_zone", 0666, prEntry_tp, &proc_tp_corner_dead_zone_p_fops, ts); + if (prEntry_tmp == NULL) { + ret = -ENOMEM; + TPD_INFO("%s: Couldn't create proc entry, %d\n", __func__, __LINE__); + } + + prEntry_tmp = proc_create_data("oplus_tp_direction", 0666, prEntry_tp, &touch_dir_proc_fops, ts); + if (prEntry_tmp == NULL) { + ret = -ENOMEM; + TPD_INFO("%s: Couldn't create proc entry, %d\n", __func__, __LINE__); + } + } + //proc files-step2-4:/proc/touchpanel/double_tap_enable (black gesture related interface) if (ts->black_gesture_support) { prEntry_tmp = proc_create_data("double_tap_enable", 0666, prEntry_tp, &proc_gesture_control_fops, ts); @@ -6431,6 +6696,7 @@ static int init_parse_dts(struct device *dev, struct touchpanel_data *ts) } ts->register_is_16bit = of_property_read_bool(np, "register-is-16bit"); ts->edge_limit_support = of_property_read_bool(np, "edge_limit_support"); + ts->oos_edge_limit_support = of_property_read_bool(np, "oos_edge_limit_support"); ts->fw_edge_limit_support = of_property_read_bool(np, "fw_edge_limit_support"); ts->drlimit_remove_support = of_property_read_bool(np, "drlimit_remove_support"); ts->glove_mode_support = of_property_read_bool(np, "glove_mode_support"); @@ -6474,6 +6740,7 @@ static int init_parse_dts(struct device *dev, struct touchpanel_data *ts) ts->report_rate_white_list_support = of_property_read_bool(np, "report_rate_white_list_support"); ts->lcd_tp_refresh_support = of_property_read_bool(np, "lcd_tp_refresh_support"); ts->smooth_level_support = of_property_read_bool(np, "smooth_level_support"); + ts->project_info = of_property_read_bool(np, "project_info"); ts->pen_support = of_property_read_bool(np, "pen_support"); ts->exception_upload_support = of_property_read_bool(np, "exception_upload_support"); /*set disable suspend irq handler parameter, for of_property_read_bool return 1 when success and return 0 when item is not exist*/ @@ -7634,6 +7901,21 @@ int register_common_touch_device(struct touchpanel_data *pdata) } else { ts->irq = ts->client->irq; } + if (ts->project_info == 1) { + ts->dead_zone_l = 25; + ts->dead_zone_p = 25; + } else { + ts->dead_zone_l = 20; + ts->dead_zone_p = 20; + } + if (ts->int_mode == UNBANNABLE) { + ts->dead_zone_l = 10; + ts->dead_zone_p = 10; + ts->corner_dead_zone_xl = 0x88; + ts->corner_dead_zone_yl = 0x44; + ts->corner_dead_zone_xp = 0x24; + ts->corner_dead_zone_yp = 0xF5; + } tp_register_times++; g_tp = ts; complete(&ts->pm_complete); diff --git a/drivers/input/touchscreen/oplus_touchscreen/touchpanel_prevention.h b/drivers/input/touchscreen/oplus_touchscreen/touchpanel_prevention.h new file mode 100644 index 0000000000..f557a114d5 --- /dev/null +++ b/drivers/input/touchscreen/oplus_touchscreen/touchpanel_prevention.h @@ -0,0 +1,459 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2018-2020 Oplus. All rights reserved. + */ + +#ifndef _TOUCHPANEL_PREVENTION_H_ +#define _TOUCHPANEL_PREVENTION_H_ + +#include +#include +#include +#include + +#define TOUCH_MAX_NUM (10) +#define GRIP_TAG_SIZE (64) +#define MAX_STRING_CNT (15) +#define MAX_AREA_PARAMETER (10) +#define UP2CANCEL_PRESSURE_VALUE (0xFF) + +typedef enum edge_grip_side { + TYPE_UNKNOW, + TYPE_LONG_SIDE, + TYPE_SHORT_SIDE, + TYPE_LONG_CORNER_SIDE, + TYPE_SHORT_CORNER_SIDE, +} grip_side; + +/*shows a rectangle +* x start at @start_x and end at @start_x+@x_width +* y start at @start_y and end at @start_y+@y_width +* @area_list: list used for connected with other area +* @start_x: original x coordinate +* @start_y: original y coordinate +* @x_width: witdh in x axis +* @y_width: witdh in y axis +*/ +struct grip_zone_area { + struct list_head area_list; + /*must be the first member to easy get the pointer of grip_zone_area*/ + uint16_t start_x; + uint16_t start_y; + uint16_t x_width; + uint16_t y_width; + uint16_t exit_thd; + uint16_t exit_tx_er; + uint16_t exit_rx_er; + uint16_t support_dir; + uint16_t grip_side; + char name[GRIP_TAG_SIZE]; +}; + +struct coord_buffer { + uint16_t x; + uint16_t y; + uint16_t weight; +}; + +enum large_judge_status { + JUDGE_LARGE_CONTINUE, + JUDGE_LARGE_TIMEOUT, + JUDGE_LARGE_OK, +}; + +enum large_reject_type { + TYPE_REJECT_NONE, + TYPE_REJECT_HOLD, + TYPE_REJECT_DONE, +}; + +enum large_finger_status { + TYPE_NORMAL_FINGER, + TYPE_HOLD_FINGER, + TYPE_EDGE_FINGER, + TYPE_PALM_SHORT_SIZE, + TYPE_PALM_LONG_SIZE, + TYPE_SMALL_PALM_CORNER, + TYPE_PALM_CORNER, + TYPE_LARGE_PALM_CORNER, + + TYPE_LONG_AROUND_TOUCH, + TYPE_LONG_FINGER_HOLD, + TYPE_LONG_EDGE_FINGER, + TYPE_LONG_CENTER_DOWN, + TYPE_SHORT_AROUND_TOUCH, + TYPE_SHORT_FINGER_HOLD, + TYPE_SHORT_EDGE_FINGER, + TYPE_SHORT_CENTER_DOWN, + TYPE_CORNER_SHAPE_SIZE, + TYPE_CORNER_LARGE_SIZE, + TYPE_CORNER_EDGE_FINGER, + TYPE_CORNER_CENTER_DOWN, + TYPE_CORNER_SHORT_MOVE, + TYPE_CORNER_MISTOUCH_AGAIN, + TYPE_TOP_LONG_PRESS, + TYPE_ALL_SHORT_CLICK, + TYPE_LONG_EDGE_TOUCH, + TYPE_SHORT_EDGE_TOUCH, + TYPE_TOP_SHORT_MOVE, +}; + +enum large_point_status { + UP_POINT, + DOWN_POINT, + DOWN_POINT_NEED_MAKEUP, +}; + +enum grip_diable_level { + GRIP_DISABLE_LARGE, + GRIP_DISABLE_ELI, + GRIP_DISABLE_UP2CANCEL, +}; + +typedef enum grip_operate_cmd { + OPERATE_UNKNOW, + OPERATE_ADD, + OPERATE_DELTE, + OPERATE_MODIFY, +} operate_cmd; + +typedef enum grip_operate_object { + OBJECT_UNKNOW, + OBJECT_PARAMETER, + OBJECT_PARAMETER_V2, + OBJECT_LONG_CURVED_PARAMETER, /* for modify curved srceen judge para for long side */ + OBJECT_SHORT_CURVED_PARAMETER, /* for modify curved srceen judge para for short side */ + OBJECT_CONDITION_AREA, /* for modify condition area */ + OBJECT_LARGE_AREA, /* for modify large judge area */ + OBJECT_ELI_AREA, /* for modify elimination area */ + OBJECT_DEAD_AREA, /* for modify dead area */ + OBJECT_SKIP_HANDLE, /* for modify no handle setting */ + OBJECT_EDGE_LIMIT, +} operate_oject; + +enum grip_position { + POS_UNDEFINE = 0, + POS_CENTER_INNER = 1, + POS_LONG_LEFT, + POS_LONG_RIGHT, + POS_SHORT_LEFT, + POS_SHORT_RIGHT, + POS_VERTICAL_LEFT_CORNER, + POS_VERTICAL_RIGHT_CORNER, + POS_VERTICAL_LEFT_TOP, + POS_VERTICAL_RIGHT_TOP, + POS_HORIZON_B_LEFT_CORNER, + POS_HORIZON_B_RIGHT_CORNER, + POS_HORIZON_T_LEFT_CORNER, + POS_HORIZON_T_RIGHT_CORNER, + POS_HORIZON_B_LEFT_TOP, + POS_HORIZON_B_RIGHT_TOP, + POS_HORIZON_T_LEFT_TOP, + POS_HORIZON_T_RIGHT_TOP, +}; + +struct grip_point_info { + uint16_t x; + uint16_t y; + uint8_t tx_press; + uint8_t rx_press; + uint8_t tx_er; + uint8_t rx_er; + s64 time_ms; /* record the point first down time */ +}; + +struct curved_judge_para { + uint16_t edge_finger_thd; + uint16_t hold_finger_thd; + uint16_t normal_finger_thd_1; + uint16_t normal_finger_thd_2; + uint16_t normal_finger_thd_3; + uint16_t large_palm_thd_1; + uint16_t large_palm_thd_2; + uint16_t palm_thd_1; + uint16_t palm_thd_2; + uint16_t small_palm_thd_1; + uint16_t small_palm_thd_2; +}; + +typedef enum point_info_type { + TYPE_START_POINT = 1, /* for record first frame point */ + TYPE_SECOND_POINT, /* for record second frame point */ + TYPE_LAST_POINT, /* for record last frame points */ + TYPE_LATEST_POINT, /* for record latest points */ + TYPE_MAX_TX_POINT, /* for record max tx frame points */ + TYPE_MAX_RX_POINT, /* for record max rx frame points */ + TYPE_INIT_TX_POINT, /* for record init rx points */ + TYPE_INIT_RX_POINT, /* for record init rx points */ + TYPE_RX_CHANGED_POINT, /* for record rx changed frame points */ + TYPE_TX_CHANGED_POINT, /* for record tx changed frame points */ +} point_info_type; + +enum center_down_status { + STATUS_CENTER_UNKNOW = 0, + STATUS_CENTER_UP, + STATUS_CENTER_DOWN, +}; + +enum corner_judge_shape { + CORNER_SHAPE_NONE = 0, + CORNER_SHAPE_LARGE, + CORNER_SHAPE_RATIO, +}; + +struct key_addr { + char name[64]; + uint16_t *addr; +}; + +#define MAKEUP_REAL_POINT (0xFF) +#define POINT_DIFF_CNT 10 +struct kernel_grip_info { + int + touch_dir; /*shows touchpanel direction*/ + uint32_t + max_x; /*touchpanel width*/ + uint32_t + max_y; /*touchpanel height*/ + int + tx_num; /*touchpanel tx num*/ + int + rx_num; /*touchpanel rx num*/ + struct mutex + grip_mutex; /*using for protect grip parameter working*/ + uint32_t + no_handle_y1; /*min y of no grip handle*/ + uint32_t + no_handle_y2; /*max y of no grip handle*/ + uint8_t + no_handle_dir; /*show which side no grip handle*/ + uint8_t + grip_disable_level; /*show whether if do grip handle*/ + uint8_t + record_total_cnt; /*remember total count*/ + + struct grip_point_info + first_point[TOUCH_MAX_NUM]; /*store the fist frame point of each ID*/ + struct grip_point_info + second_point[TOUCH_MAX_NUM]; /*store the second frame point of each ID*/ + struct grip_point_info + latest_points[TOUCH_MAX_NUM][POINT_DIFF_CNT]; /*store the latest different 5 points of each ID*/ + bool + sync_up_makeup[TOUCH_MAX_NUM]; /*shows this point need make up while report up*/ + bool + dead_out_status[TOUCH_MAX_NUM]; /*show if exit the dead grip*/ + struct list_head + dead_zone_list; /*list all area using dead grip strategy*/ + + uint16_t frame_cnt[TOUCH_MAX_NUM]; /*show down frame of each id*/ + int obj_prev_bit; /*show last frame obj attention*/ + int obj_bit_rcd; /*show current frame obj attention for record*/ + int obj_prced_bit_rcd; /*show current frame processed obj attention for record*/ + uint16_t coord_filter_cnt; /*cnt of make up points*/ + struct coord_buffer + *coord_buf; /*store point and its weight to do filter*/ + bool + large_out_status[TOUCH_MAX_NUM]; /*show if exit the large area grip*/ + uint8_t + large_reject[TOUCH_MAX_NUM]; /*show if rejected state*/ + uint8_t + large_finger_status[TOUCH_MAX_NUM]; /*show large area finger status for grip strategy*/ + uint8_t + large_point_status[TOUCH_MAX_NUM]; /*parameter for judge if ponits in large area need make up or not*/ + uint16_t + large_detect_time_ms; /*large area detection time limit in ms*/ + struct list_head + large_zone_list; /*list all area using large area grip strategy*/ + struct list_head + condition_zone_list; /*list all area using conditional grip strategy*/ + bool + condition_out_status[TOUCH_MAX_NUM]; /*show if exit the conditional rejection*/ + uint8_t + makeup_cnt[TOUCH_MAX_NUM]; /*show makeup count of each id*/ + uint16_t + large_frame_limit; /*max time to judge big area*/ + uint16_t + large_ver_thd; /*threshold to determine large area size in vetical*/ + uint16_t + large_hor_thd; /*threshold to determine large area size in horizon*/ + uint16_t + large_corner_frame_limit; /*max time to judge big area in corner area*/ + uint16_t + large_ver_corner_thd; /*threshold to determine large area size in vetical corner*/ + uint16_t + large_hor_corner_thd; /*threshold to determine large area size in horizon corner*/ + uint16_t + large_ver_corner_width; /*threshold to determine should be judged in vertical corner way*/ + uint16_t + large_hor_corner_width; /*threshold to determine should be judged in horizon corner way*/ + uint16_t + large_corner_distance; /*threshold to judge move from edge*/ + + struct curved_judge_para + curved_long_side_para; /*parameter for curved touchscreen long side judge*/ + struct curved_judge_para + curved_short_side_para; /*parameter for curved touchscreen short side judge*/ + bool + is_curved_screen; /*curved screen judge flag*/ + s64 + lastest_down_time_ms; /*record the lastest down time out of large judged*/ + s64 + down_delta_time_ms; /*threshold to judge whether need to make up point*/ + bool point_unmoved[TOUCH_MAX_NUM]; /*show point have already moved*/ + uint8_t condition_frame_limit; /*keep rejeected while beyond this time*/ + unsigned long condition_updelay_ms; /*time after to report touch up*/ + struct kfifo up_fifo; /*store up touch id according to the sequence*/ + struct hrtimer grip_up_timer[TOUCH_MAX_NUM]; /*using for report touch up event*/ + bool grip_hold_status[TOUCH_MAX_NUM]; /*show if this id is in hold status*/ + struct work_struct grip_up_work[TOUCH_MAX_NUM]; /*using for report touch up*/ + struct workqueue_struct *grip_up_handle_wq; /*just for handle report up event*/ + + bool eli_out_status[TOUCH_MAX_NUM]; /*store cross range status of each id*/ + bool eli_reject_status[TOUCH_MAX_NUM]; /*show reject status if each id*/ + struct list_head elimination_zone_list; + /*list all area using elimination strategy*/ + + bool grip_handle_in_fw; /*show whether we should handle prevention in fw*/ + bool dir_change_set_grip; + struct fw_grip_operations *fw_ops; /*fw grip setting func call back*/ + struct touchpanel_data *p_ts; /*record the ts address*/ + int work_id; + bool + is_curved_screen_V2; /*curved screen judge flag using new grip function*/ + uint8_t + exit_match_times[TOUCH_MAX_NUM]; /*record actual match the exit condition times*/ + struct grip_point_info + txMax_frame_point[TOUCH_MAX_NUM]; /*record the max tx frame point info*/ + struct grip_point_info + rxMax_frame_point[TOUCH_MAX_NUM]; /*record the max rx frame point info*/ + struct grip_point_info + last_frame_point[TOUCH_MAX_NUM]; /*record the last frame point info*/ + struct grip_point_info + rxChanged_frame_point[TOUCH_MAX_NUM]; /*record the rx changed frame point info*/ + struct grip_point_info + txChanged_frame_point[TOUCH_MAX_NUM]; /*record the tx changed frame point info*/ + uint32_t + fsr_stable_time[TOUCH_MAX_NUM]; /*record fsr stable time under detect period*/ + uint8_t + points_pos[TOUCH_MAX_NUM]; /*record point area distribution*/ + uint8_t + points_center_down[TOUCH_MAX_NUM]; /*record whether points down after center point down*/ + uint8_t + last_large_reject[TOUCH_MAX_NUM]; /*show last touch rejected state*/ + uint8_t + last_points_pos[TOUCH_MAX_NUM]; /*show last touch point position*/ + uint16_t + large_corner_exit_distance; /*large corner distance exit condition*/ + uint16_t + large_corner_detect_time_ms; /*large corner judge detect time*/ + uint16_t + large_corner_debounce_ms; /*large corner judge center down debounce time interval*/ + uint16_t + large_corner_width; /*large corner width*/ + uint16_t + large_corner_height; /*large corner height*/ + uint16_t + xfsr_corner_exit_thd; /*corner exit fsr threshold of x direction*/ + uint16_t + yfsr_corner_exit_thd; /*corner exit fsr threshold of y direction*/ + uint16_t + exit_match_thd; /*exit match times threshold*/ + uint16_t + rx_reject_thd; /*rx reject threshold*/ + uint16_t + tx_reject_thd; /*tx reject threshold*/ + uint16_t + trx_reject_thd; /*tx and rx reject threshold*/ + uint16_t + fsr_stable_time_thd; /*fsr stable time threshold*/ + uint16_t + single_channel_x_len; /*single channel x coordinate*/ + uint16_t + single_channel_y_len; /*single channel y coordinate*/ + uint16_t + normal_tap_min_time_ms; /*normal touch min time interval*/ + uint16_t + normal_tap_max_time_ms; /*normal touch max time interval*/ + uint16_t + long_start_coupling_thd; /*long start threshold of rx_er*rx_press*/ + uint16_t + long_stable_coupling_thd; /*long stable threshold of rx_er*rx_press*/ + uint16_t + long_detect_time_ms; /*long detect time threshold*/ + uint16_t + long_hold_changed_thd; /*long stable rx_er changed threshold*/ + uint16_t + long_hold_maxfsr_gap; /*long hold fsr gap max setting*/ + uint16_t + long_hold_divided_factor; /*long hold neighbouring range setting, default 6*/ + uint16_t + long_hold_debounce_time_ms; /*long hold debounce time of judge*/ + uint16_t + xfsr_normal_exit_thd; /*normal exit fsr of x direction*/ + uint16_t + yfsr_normal_exit_thd; /*normal exit fsr of y direction*/ + uint16_t + xfsr_hold_exit_thd; /*finger hold exit fsr of x direction*/ + uint16_t + yfsr_hold_exit_thd; /*finger hold exit fsr of y direction*/ + uint16_t + large_reject_debounce_time_ms; /*landed in large reject down or up debounce time will be rejected also*/ + uint16_t + report_updelay_ms; /*time after to report touch up*/ + uint16_t + short_start_coupling_thd; /*short start threshold of tx_er*tx_press*/ + uint16_t + short_stable_coupling_thd; /*short stable threshold of tx_er*tx_press*/ + uint16_t + short_hold_changed_thd; /*short stable tx_er changed threshold*/ + uint16_t + short_hold_maxfsr_gap; /*short hold fsr gap max setting*/ + uint16_t + large_top_width; /*large top corner width*/ + uint16_t + large_top_height; /*large top corner height*/ + uint16_t + large_top_exit_distance; /*large top corner exit distance*/ + uint16_t + edge_swipe_narrow_witdh; /*normal edge swipe width limit*/ + uint16_t + edge_swipe_exit_distance; /*normal edge swipe distance threshold*/ + uint16_t + long_strict_start_coupling_thd; /*long side strict start coupling threshold*/ + uint16_t + long_strict_stable_coupling_thd; /*long side strict stable coupling threshold*/ + uint16_t + rx_strict_reject_thd; /*long side strict rx reject threshold*/ + uint16_t + tx_strict_reject_thd; /*short side strict tx reject threshold*/ + uint16_t + trx_strict_reject_thd; /*tx and rx add strict reject threshold**/ + uint16_t + short_strict_start_coupling_thd; /*short side strict start coupling threshold*/ + uint16_t + short_strict_stable_coupling_thd; /*short side strict stable coupling threshold*/ + uint16_t + xfsr_strict_exit_thd; /*strict exit fsr of x direction*/ + uint16_t + yfsr_strict_exit_thd; /*strict exit fsr of y direction*/ + uint16_t + corner_move_rejected; /*flag to show whether we need to do corner move reject*/ +}; + +struct fw_grip_operations { + int (*set_fw_grip_area)(struct grip_zone_area *grip_zone, bool enable); /*set the fw grip area*/ + void (*set_touch_direction)(uint8_t dir); /*set touch direction in fw*/ + int (*set_no_handle_area)(struct kernel_grip_info *grip_info); /*set no handle area in fw*/ + int (*set_condition_frame_limit)(int frame); /*set condition frame limit in fw*/ + int (*set_large_frame_limit)(int frame); /*set large frame limit in fw*/ + int (*set_large_corner_frame_limit)(int frame); /*set large condition frame limit in fw*/ + int (*set_large_ver_thd)(int thd); /*set large ver thd in fw*/ +}; + +struct kernel_grip_info *kernel_grip_init(struct device *dev); +void init_kernel_grip_proc(struct proc_dir_entry *prEntry_tp, struct kernel_grip_info *grip_info); +void grip_status_reset(struct kernel_grip_info *grip_info, uint8_t index); +void kernel_grip_reset(struct kernel_grip_info *grip_info); +int kernel_grip_print_func(struct seq_file *s, struct kernel_grip_info *grip_info); + +#endif /*_TOUCHPANEL_PREVENTION_H_*/