mirror of
https://github.com/Ysurac/openmptcprouter.git
synced 2025-03-09 15:40:20 +00:00
180 lines
5.3 KiB
Diff
180 lines
5.3 KiB
Diff
From f15346d0f92c0d16f4e6f51f852c94bde42c6d1a Mon Sep 17 00:00:00 2001
|
|
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
|
|
Date: Mon, 30 Jan 2023 14:46:16 +0000
|
|
Subject: [PATCH 321/697] input: goodix: Add option to poll instead of relying
|
|
on IRQ line
|
|
|
|
The interrupt line from the touch controller is not necessarily
|
|
connected to the SoC, so add the option to poll for touch info.
|
|
|
|
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
|
|
|
|
input: goodix: Include I2C details in names for the devices
|
|
|
|
libinput uses the input device name alone. If you have two
|
|
identical input devices, then there is no way to differentiate
|
|
between them, and in the case of touchscreens that means no
|
|
way to associate them with the appropriate display device.
|
|
|
|
Add the I2C bus and address to the start of the input device
|
|
name so that the name is always unique within the system.
|
|
|
|
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
|
|
---
|
|
drivers/input/touchscreen/goodix.c | 75 +++++++++++++++++++++++++++---
|
|
drivers/input/touchscreen/goodix.h | 5 ++
|
|
2 files changed, 73 insertions(+), 7 deletions(-)
|
|
|
|
--- a/drivers/input/touchscreen/goodix.c
|
|
+++ b/drivers/input/touchscreen/goodix.c
|
|
@@ -48,6 +48,8 @@
|
|
#define MAX_CONTACTS_LOC 5
|
|
#define TRIGGER_LOC 6
|
|
|
|
+#define POLL_INTERVAL_MS 17 /* 17ms = 60fps */
|
|
+
|
|
/* Our special handling for GPIO accesses through ACPI is x86 specific */
|
|
#if defined CONFIG_X86 && defined CONFIG_ACPI
|
|
#define ACPI_GPIO_SUPPORT
|
|
@@ -513,16 +515,67 @@ static irqreturn_t goodix_ts_irq_handler
|
|
return IRQ_HANDLED;
|
|
}
|
|
|
|
+static void goodix_ts_irq_poll_timer(struct timer_list *t)
|
|
+{
|
|
+ struct goodix_ts_data *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 goodix_ts_work_i2c_poll(struct work_struct *work)
|
|
+{
|
|
+ struct goodix_ts_data *ts = container_of(work,
|
|
+ struct goodix_ts_data, work_i2c_poll);
|
|
+
|
|
+ goodix_process_events(ts);
|
|
+ goodix_i2c_write_u8(ts->client, GOODIX_READ_COOR_ADDR, 0);
|
|
+}
|
|
+
|
|
+static void goodix_enable_irq(struct goodix_ts_data *ts)
|
|
+{
|
|
+ if (ts->client->irq) {
|
|
+ enable_irq(ts->client->irq);
|
|
+ } else {
|
|
+ ts->timer.expires = jiffies + msecs_to_jiffies(POLL_INTERVAL_MS);
|
|
+ add_timer(&ts->timer);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void goodix_disable_irq(struct goodix_ts_data *ts)
|
|
+{
|
|
+ if (ts->client->irq) {
|
|
+ disable_irq(ts->client->irq);
|
|
+ } else {
|
|
+ del_timer(&ts->timer);
|
|
+ cancel_work_sync(&ts->work_i2c_poll);
|
|
+ }
|
|
+}
|
|
+
|
|
static void goodix_free_irq(struct goodix_ts_data *ts)
|
|
{
|
|
- devm_free_irq(&ts->client->dev, ts->client->irq, ts);
|
|
+ if (ts->client->irq) {
|
|
+ devm_free_irq(&ts->client->dev, ts->client->irq, ts);
|
|
+ } else {
|
|
+ del_timer(&ts->timer);
|
|
+ cancel_work_sync(&ts->work_i2c_poll);
|
|
+ }
|
|
}
|
|
|
|
static int goodix_request_irq(struct goodix_ts_data *ts)
|
|
{
|
|
- return devm_request_threaded_irq(&ts->client->dev, ts->client->irq,
|
|
- NULL, goodix_ts_irq_handler,
|
|
- ts->irq_flags, ts->client->name, ts);
|
|
+ if (ts->client->irq) {
|
|
+ return devm_request_threaded_irq(&ts->client->dev, ts->client->irq,
|
|
+ NULL, goodix_ts_irq_handler,
|
|
+ ts->irq_flags, ts->client->name, ts);
|
|
+ } else {
|
|
+ INIT_WORK(&ts->work_i2c_poll,
|
|
+ goodix_ts_work_i2c_poll);
|
|
+ timer_setup(&ts->timer, goodix_ts_irq_poll_timer, 0);
|
|
+ if (ts->irq_pin_access_method == IRQ_PIN_ACCESS_NONE)
|
|
+ goodix_enable_irq(ts);
|
|
+ return 0;
|
|
+ }
|
|
}
|
|
|
|
static int goodix_check_cfg_8(struct goodix_ts_data *ts, const u8 *cfg, int len)
|
|
@@ -1141,7 +1194,10 @@ static int goodix_configure_dev(struct g
|
|
return -ENOMEM;
|
|
}
|
|
|
|
- ts->input_dev->name = "Goodix Capacitive TouchScreen";
|
|
+ snprintf(ts->name, GOODIX_NAME_MAX_LEN, "%s Goodix Capacitive TouchScreen",
|
|
+ dev_name(&ts->client->dev));
|
|
+
|
|
+ ts->input_dev->name = ts->name;
|
|
ts->input_dev->phys = "input/ts";
|
|
ts->input_dev->id.bustype = BUS_I2C;
|
|
ts->input_dev->id.vendor = 0x0416;
|
|
@@ -1407,6 +1463,11 @@ static void goodix_ts_remove(struct i2c_
|
|
{
|
|
struct goodix_ts_data *ts = i2c_get_clientdata(client);
|
|
|
|
+ if (!client->irq) {
|
|
+ del_timer(&ts->timer);
|
|
+ cancel_work_sync(&ts->work_i2c_poll);
|
|
+ }
|
|
+
|
|
if (ts->load_cfg_from_disk)
|
|
wait_for_completion(&ts->firmware_loading_complete);
|
|
}
|
|
@@ -1422,7 +1483,7 @@ static int goodix_suspend(struct device
|
|
|
|
/* We need gpio pins to suspend/resume */
|
|
if (ts->irq_pin_access_method == IRQ_PIN_ACCESS_NONE) {
|
|
- disable_irq(client->irq);
|
|
+ goodix_disable_irq(ts);
|
|
return 0;
|
|
}
|
|
|
|
@@ -1466,7 +1527,7 @@ static int goodix_resume(struct device *
|
|
int error;
|
|
|
|
if (ts->irq_pin_access_method == IRQ_PIN_ACCESS_NONE) {
|
|
- enable_irq(client->irq);
|
|
+ goodix_enable_irq(ts);
|
|
return 0;
|
|
}
|
|
|
|
--- a/drivers/input/touchscreen/goodix.h
|
|
+++ b/drivers/input/touchscreen/goodix.h
|
|
@@ -57,6 +57,8 @@
|
|
#define GOODIX_CONFIG_MAX_LENGTH 240
|
|
#define GOODIX_MAX_KEYS 7
|
|
|
|
+#define GOODIX_NAME_MAX_LEN 38
|
|
+
|
|
enum goodix_irq_pin_access_method {
|
|
IRQ_PIN_ACCESS_NONE,
|
|
IRQ_PIN_ACCESS_GPIO,
|
|
@@ -91,6 +93,7 @@ struct goodix_ts_data {
|
|
enum gpiod_flags gpiod_rst_flags;
|
|
char id[GOODIX_ID_MAX_LEN + 1];
|
|
char cfg_name[64];
|
|
+ char name[GOODIX_NAME_MAX_LEN];
|
|
u16 version;
|
|
bool reset_controller_at_probe;
|
|
bool load_cfg_from_disk;
|
|
@@ -104,6 +107,8 @@ struct goodix_ts_data {
|
|
u8 main_clk[GOODIX_MAIN_CLK_LEN];
|
|
int bak_ref_len;
|
|
u8 *bak_ref;
|
|
+ struct timer_list timer;
|
|
+ struct work_struct work_i2c_poll;
|
|
};
|
|
|
|
int goodix_i2c_read(struct i2c_client *client, u16 reg, u8 *buf, int len);
|