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_*/