Files
BPI-CM9-Linux/build/patch/kernel/archive/sunxi-6.18/patches.armbian/drv-input-tsc2007-add-polling-method.patch
T

187 lines
4.6 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alan <Alan>
Date: Sat, 20 May 2023 14:44:07 +0800
Subject: Optimize: TSC2007 touchscreen add polling method
---
drivers/input/touchscreen/tsc2007.h | 6 +
drivers/input/touchscreen/tsc2007_core.c | 94 ++++++++++
2 files changed, 100 insertions(+)
diff --git a/drivers/input/touchscreen/tsc2007.h b/drivers/input/touchscreen/tsc2007.h
index 111111111111..222222222222 100644
--- a/drivers/input/touchscreen/tsc2007.h
+++ b/drivers/input/touchscreen/tsc2007.h
@@ -68,10 +68,13 @@ struct tsc2007 {
u16 model;
u16 x_plate_ohms;
u16 max_rt;
+ u16 rt_thr;
+ u8 touched;
unsigned long poll_period; /* in jiffies */
int fuzzx;
int fuzzy;
int fuzzz;
+ bool ignore_nak;
struct gpio_desc *gpiod;
int irq;
@@ -83,6 +86,9 @@ struct tsc2007 {
void (*clear_penirq)(void);
struct mutex mlock;
+
+ struct timer_list timer;
+ struct work_struct work_i2c_poll;
};
int tsc2007_xfer(struct tsc2007 *tsc, u8 cmd);
diff --git a/drivers/input/touchscreen/tsc2007_core.c b/drivers/input/touchscreen/tsc2007_core.c
index 111111111111..222222222222 100644
--- a/drivers/input/touchscreen/tsc2007_core.c
+++ b/drivers/input/touchscreen/tsc2007_core.c
@@ -29,6 +29,8 @@
#include <linux/platform_data/tsc2007.h>
#include "tsc2007.h"
+#define POLL_INTERVAL_MS 17 /* 17ms = 60fps */
+
int tsc2007_xfer(struct tsc2007 *tsc, u8 cmd)
{
s32 data;
@@ -174,6 +176,65 @@ static irqreturn_t tsc2007_soft_irq(int irq, void *handle)
return IRQ_HANDLED;
}
+static irqreturn_t tsc2007_soft_poll(int irq, void *handle)
+{
+ struct tsc2007 *ts = handle;
+ struct input_dev *input = ts->input;
+ struct ts_event tc;
+ u32 rt;
+
+ if(!ts->stopped) {
+
+ mutex_lock(&ts->mlock);
+ tsc2007_read_values(ts, &tc);
+ mutex_unlock(&ts->mlock);
+
+ 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;
+
+ 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);
+ 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;
+ }
+ }
+
+
+ }
+
+ return IRQ_HANDLED;
+}
+
static void tsc2007_stop(struct tsc2007 *ts)
{
ts->stopped = true;
@@ -220,11 +281,32 @@ static int tsc2007_get_pendown_state_gpio(struct device *dev)
return gpiod_get_value_cansleep(ts->gpiod);
}
+static void tsc2007_ts_irq_poll_timer(struct timer_list *t)
+{
+ struct tsc2007 *ts = timer_container_of(ts, t, timer);
+
+ schedule_work(&ts->work_i2c_poll);
+ mod_timer(&ts->timer, jiffies + msecs_to_jiffies(POLL_INTERVAL_MS));
+}
+
+static void tsc2007_ts_work_i2c_poll(struct work_struct *work)
+{
+ struct tsc2007 *ts = container_of(work,
+ struct tsc2007, work_i2c_poll);
+
+ tsc2007_soft_poll(0, ts);
+}
+
static int tsc2007_probe_properties(struct device *dev, struct tsc2007 *ts)
{
u32 val32;
u64 val64;
+ ts->ignore_nak = device_property_read_bool(dev, "i2c,ignore-nak");
+
+ if (!device_property_read_u32(dev, "ti,rt-thr", &val32))
+ ts->rt_thr = val32;
+
if (!device_property_read_u32(dev, "ti,max-rt", &val32))
ts->max_rt = val32;
else
@@ -321,6 +403,9 @@ static int tsc2007_probe(struct i2c_client *client)
if (!input_dev)
return -ENOMEM;
+ if (ts->ignore_nak)
+ client->flags |= I2C_M_IGNORE_NAK;
+
i2c_set_clientdata(client, ts);
ts->client = client;
@@ -367,6 +452,7 @@ static int tsc2007_probe(struct i2c_client *client)
}
if (ts->irq) {
+ if (ts->gpiod) {
err = devm_request_threaded_irq(&client->dev, ts->irq,
NULL, tsc2007_soft_irq,
IRQF_ONESHOT,
@@ -376,6 +462,14 @@ static int tsc2007_probe(struct i2c_client *client)
ts->irq, err);
return err;
}
+ } else {
+ 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);
+ add_timer(&ts->timer);
+ }
tsc2007_stop(ts);
}
--
Armbian