From 5607ccab3192a2cc9d70c6072f83d9b9060295c8 Mon Sep 17 00:00:00 2001 From: JohnTheCoolingFan Date: Sat, 25 Jan 2025 12:54:16 +0000 Subject: Fix ghost touches on tsc2007 tft screen Signed-off-by: JohnTheCoolingFan --- .../sun50i-h616-bigtreetech-cb1.dtsi | 1 + drivers/input/touchscreen/tsc2007.h | 1 + drivers/input/touchscreen/tsc2007_core.c | 96 +++++++++---------- include/linux/platform_data/tsc2007.h | 1 + 4 files changed, 49 insertions(+), 50 deletions(-) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616-bigtreetech-cb1.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h616-bigtreetech-cb1.dtsi index 2022990e4bc0..3b3a196eaa93 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h616-bigtreetech-cb1.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h616-bigtreetech-cb1.dtsi @@ -125,6 +125,7 @@ tft_tp: ns2009@48 { reg = <0x48>; status = "disabled"; ti,x-plate-ohms = <660>; + ti,y-plate-ohms = <660>; ti,rt-thr = <3000>; ti,fuzzx = <32>; ti,fuzzy = <16>; diff --git a/drivers/input/touchscreen/tsc2007.h b/drivers/input/touchscreen/tsc2007.h index 5252b6c6daeb..7411b8bce99c 100644 --- a/drivers/input/touchscreen/tsc2007.h +++ b/drivers/input/touchscreen/tsc2007.h @@ -65,6 +65,7 @@ struct tsc2007 { u16 model; u16 x_plate_ohms; + u16 y_plate_ohms; u16 max_rt; u16 rt_thr; u8 touched; diff --git a/drivers/input/touchscreen/tsc2007_core.c b/drivers/input/touchscreen/tsc2007_core.c index 08bbbafbbae1..1ae1b1a3e367 100644 --- a/drivers/input/touchscreen/tsc2007_core.c +++ b/drivers/input/touchscreen/tsc2007_core.c @@ -70,22 +70,20 @@ static void tsc2007_read_values(struct tsc2007 *tsc, struct ts_event *tc) u32 tsc2007_calculate_resistance(struct tsc2007 *tsc, struct ts_event *tc) { - u32 rt = 0; - - /* range filtering */ - if (tc->x == MAX_12BIT) + if (tc->x == MAX_12BIT){ tc->x = 0; + } - if (likely(tc->x && tc->z1)) { - /* compute touch resistance using equation #1 */ - rt = tc->z2 - tc->z1; - rt *= tc->x; - rt *= tsc->x_plate_ohms; - rt /= tc->z1; - rt = (rt + 2047) >> 12; + if (tc->y == MAX_12BIT){ + tc->y = 0; } - return rt; + + if (likely(tc->x && tc->y && tc->z1)) { + return (tsc->x_plate_ohms * tc->x / 4096) * ((4096 / tc->z1) - 1) - tsc->y_plate_ohms * (1 - tc->y / 4096); + } else{ + return 0; + } } bool tsc2007_is_pen_down(struct tsc2007 *ts) @@ -180,6 +178,7 @@ static irqreturn_t tsc2007_soft_poll(int irq, void *handle) struct input_dev *input = ts->input; struct ts_event tc; u32 rt; + bool skipSync = false; if(!ts->stopped) { @@ -189,45 +188,31 @@ static irqreturn_t tsc2007_soft_poll(int irq, void *handle) rt = tsc2007_calculate_resistance(ts, &tc); - if (rt == 0 || rt == 256) { - - /* - * Sample found inconsistent by debouncing or pressure is - * beyond the maximum. Don't report it to user space, - * repeat at least once more the measurement. - */ - dev_dbg(&ts->client->dev, "ignored pressure %d\n", rt); - - } else { - - if (rt < ts->rt_thr) { - - dev_dbg(&ts->client->dev, - "DOWN point(%4d,%4d), resistance (%4u)\n", - tc.x, tc.y, rt); - - rt = ts->max_rt - rt; + if (likely(rt)) { - input_report_key(input, BTN_TOUCH, 1); - input_report_abs(input, ABS_X, tc.y); - input_report_abs(input, ABS_Y, 4096 - tc.x); - input_report_abs(input, ABS_PRESSURE, rt); + /* range >= 0 && <= 4096 */ + if (rt > 0 && rt <= ts->max_rt) { + rt = ts->max_rt - rt; + input_report_key(input, BTN_TOUCH, 1); + input_report_abs(input, ABS_X, tc.y); + input_report_abs(input, ABS_Y, 4096 - tc.x); + input_report_abs(input, ABS_PRESSURE, rt); + input_sync(input); - input_sync(input); - ts->touched = 1; - - } else if (ts->touched == 1) { - - dev_dbg(&ts->client->dev, "UP\n"); - - input_report_key(input, BTN_TOUCH, 0); - input_report_abs(input, ABS_PRESSURE, 0); - input_sync(input); - ts->touched = 0; + } else { + //Discard Input Ghost or inconsistent + skipSync= true; } + }else{ + // No touch event or missing data for rt calculation + skipSync= true; } + } - + if(skipSync){ + input_report_key(input, BTN_TOUCH, 0); + input_report_abs(input, ABS_PRESSURE, 0); + input_sync(input); } return IRQ_HANDLED; @@ -329,6 +314,13 @@ static int tsc2007_probe_properties(struct device *dev, struct tsc2007 *ts) return -EINVAL; } + if (!device_property_read_u32(dev, "ti,y-plate-ohms", &val32)) { + ts->y_plate_ohms = val32; + } else { + dev_err(dev, "Missing ti,y-plate-ohms device property\n"); + return -EINVAL; + } + ts->gpiod = devm_gpiod_get_optional(dev, NULL, GPIOD_IN); if (IS_ERR(ts->gpiod)) return PTR_ERR(ts->gpiod); @@ -347,6 +339,7 @@ static int tsc2007_probe_pdev(struct device *dev, struct tsc2007 *ts, { ts->model = pdata->model; ts->x_plate_ohms = pdata->x_plate_ohms; + ts->y_plate_ohms = pdata->y_plate_ohms; ts->max_rt = pdata->max_rt ? : MAX_12BIT; ts->poll_period = msecs_to_jiffies(pdata->poll_period ? : 1); ts->get_pendown_state = pdata->get_pendown_state; @@ -360,6 +353,11 @@ static int tsc2007_probe_pdev(struct device *dev, struct tsc2007 *ts, return -EINVAL; } + if (pdata->y_plate_ohms == 0) { + dev_err(dev, "y_plate_ohms is not set up in platform data\n"); + return -EINVAL; + } + return 0; } @@ -458,11 +456,9 @@ static int tsc2007_probe(struct i2c_client *client) return err; } } else { - INIT_WORK(&ts->work_i2c_poll, - tsc2007_ts_work_i2c_poll); + INIT_WORK(&ts->work_i2c_poll, tsc2007_ts_work_i2c_poll); timer_setup(&ts->timer, tsc2007_ts_irq_poll_timer, 0); - ts->timer.expires = jiffies + - msecs_to_jiffies(POLL_INTERVAL_MS); + ts->timer.expires = jiffies + msecs_to_jiffies(POLL_INTERVAL_MS); add_timer(&ts->timer); } diff --git a/include/linux/platform_data/tsc2007.h b/include/linux/platform_data/tsc2007.h index a0ca52c41ccb..f88e580322f0 100644 --- a/include/linux/platform_data/tsc2007.h +++ b/include/linux/platform_data/tsc2007.h @@ -7,6 +7,7 @@ struct tsc2007_platform_data { u16 model; /* 2007. */ u16 x_plate_ohms; /* must be non-zero value */ + u16 y_plate_ohms; /* must be non-zero value */ u16 max_rt; /* max. resistance above which samples are ignored */ unsigned long poll_period; /* time (in ms) between samples */ int fuzzx; /* fuzz factor for X, Y and pressure axes */ -- 2.35.3