From 5607ccab3192a2cc9d70c6072f83d9b9060295c8 Mon Sep 17 00:00:00 2001
From: JohnTheCoolingFan <ivan8215145640@gmail.com>
Date: Sat, 25 Jan 2025 12:54:16 +0000
Subject: Fix ghost touches on tsc2007 tft screen

Signed-off-by: JohnTheCoolingFan <ivan8215145640@gmail.com>
---
 .../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

