Thread (5 messages) 5 messages, 3 authors, 2025-05-21

回复: [EXT] Re: [PATCH] input: goodix: add poll mode for goodix touchscreen

From: Joseph Guo <hidden>
Date: 2025-05-21 02:52:12
Also in: lkml

Hi Hans

Thanks for your comment. I already remove the unused variable in v2.

Best Regards.
Joseph

-----邮件原件-----
发件人: Hans de Goede [off-list ref] 
发送时间: Tuesday, May 20, 2025 12:15 AM
收件人: Joseph Guo [off-list ref]; Bastien Nocera [off-list ref]; Dmitry Torokhov [off-list ref]; open list:GOODIX TOUCHSCREEN [off-list ref]; open list [off-list ref]
主题: [EXT] Re: [PATCH] input: goodix: add poll mode for goodix touchscreen

[You don't often get email from hdegoede@redhat.com. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]

Caution: This is an external email. Please take care when clicking links or opening attachments. When in doubt, report the message using the 'Report this email' button


Hi,

On 19-May-25 10:57 AM, Joseph Guo wrote:
quoted hunk ↗ jump to hunk
goodix touchscreen only support interrupt mode by default.
Some panels like waveshare panel which is widely used on raspeberry pi 
don't have interrupt pins and only work on i2c poll mode.
The waveshare panel 7inch panel use goodix gt911 touchscreen chip.

Update goodix touchscreen to support both interrupt and poll mode.

Signed-off-by: Joseph Guo <redacted>
---
 drivers/input/touchscreen/goodix.c | 69 
+++++++++++++++++++++++++++---  drivers/input/touchscreen/goodix.h |  
4 ++
 2 files changed, 67 insertions(+), 6 deletions(-)
diff --git a/drivers/input/touchscreen/goodix.c 
b/drivers/input/touchscreen/goodix.c
index aaf79ac50004..87991b56494d 100644
--- a/drivers/input/touchscreen/goodix.c
+++ b/drivers/input/touchscreen/goodix.c
@@ -47,6 +47,7 @@
 #define RESOLUTION_LOC               1
 #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 @@ -497,6 
+498,23 @@ static void goodix_process_events(struct goodix_ts_data *ts)
      input_sync(ts->input_dev);
 }

+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); }
+
 /**
  * goodix_ts_irq_handler - The IRQ handler
  *
@@ -523,16 +541,50 @@ static irqreturn_t goodix_ts_irq_handler(int irq, void *dev_id)
      return IRQ_HANDLED;
 }

+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) @@ -1420,6 +1472,11 @@ static void 
goodix_ts_remove(struct i2c_client *client)  {
      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);
 }
@@ -1435,7 +1492,7 @@ static int goodix_suspend(struct device *dev)

      /* 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;
      }
@@ -1479,7 +1536,7 @@ static int goodix_resume(struct device *dev)
      int error;

      if (ts->irq_pin_access_method == IRQ_PIN_ACCESS_NONE) {
-             enable_irq(client->irq);
+             goodix_enable_irq(ts);
              return 0;
      }
diff --git a/drivers/input/touchscreen/goodix.h 
b/drivers/input/touchscreen/goodix.h
index 87797cc88b32..132e49d66324 100644
--- a/drivers/input/touchscreen/goodix.h
+++ b/drivers/input/touchscreen/goodix.h
@@ -56,6 +56,7 @@
 #define GOODIX_ID_MAX_LEN                    4
 #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,
@@ -91,6 +92,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];
This adding of the name variable, seems to be some leftover change from another patch?

Please drop this for v2.

Regards,

Hans


quoted hunk ↗ jump to hunk
      u16 version;
      bool reset_controller_at_probe;
      bool load_cfg_from_disk;
@@ -104,6 +106,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);
--
2.34.1
  
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help