From 8e4468c6de5f11c7ed078599dee21171f8de17af Mon Sep 17 00:00:00 2001 From: Alan Date: Sat, 20 May 2023 14:44:07 +0800 Subject: [PATCH] Optimize: TSC2007 touchscreen add polling method --- drivers/input/touchscreen/tsc2007.h | 6 ++ drivers/input/touchscreen/tsc2007_core.c | 110 +++++++++++++++++++++-- 2 files changed, 108 insertions(+), 8 deletions(-) diff --git a/drivers/input/touchscreen/tsc2007.h b/drivers/input/touchscreen/tsc2007.h index 69b08dd6c8df..5252b6c6daeb 100644 --- a/drivers/input/touchscreen/tsc2007.h +++ b/drivers/input/touchscreen/tsc2007.h @@ -66,10 +66,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; @@ -81,6 +84,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 21916a30fb76..9e91df8c6bc0 100644 --- a/drivers/input/touchscreen/tsc2007_core.c +++ b/drivers/input/touchscreen/tsc2007_core.c @@ -28,6 +28,8 @@ #include #include "tsc2007.h" +#define POLL_INTERVAL_MS 17 /* 17ms = 60fps */ + int tsc2007_xfer(struct tsc2007 *tsc, u8 cmd) { s32 data; @@ -172,6 +174,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; @@ -216,11 +277,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 = from_timer(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 @@ -317,6 +399,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; @@ -362,14 +447,23 @@ static int tsc2007_probe(struct i2c_client *client) pdata->init_platform_hw(); } - err = devm_request_threaded_irq(&client->dev, ts->irq, - NULL, tsc2007_soft_irq, - IRQF_ONESHOT, - client->dev.driver->name, ts); - if (err) { - dev_err(&client->dev, "Failed to request irq %d: %d\n", - ts->irq, err); - return err; + if (ts->gpiod) { + err = devm_request_threaded_irq(&client->dev, ts->irq, + NULL, tsc2007_soft_irq, + IRQF_ONESHOT, + client->dev.driver->name, ts); + if (err) { + dev_err(&client->dev, "Failed to request irq %d: %d\n", + 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); -- 2.34.1