| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 |
- From 13a9614267e7d8d4075144a7bf4dbebfcc565367 Mon Sep 17 00:00:00 2001
- From: Dave Stevenson <[email protected]>
- Date: Mon, 30 Jan 2023 14:46:16 +0000
- Subject: [PATCH] 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 <[email protected]>
- ---
- drivers/input/touchscreen/goodix.c | 70 +++++++++++++++++++++++++++---
- drivers/input/touchscreen/goodix.h | 2 +
- 2 files changed, 66 insertions(+), 6 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)
- @@ -1425,6 +1478,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);
- }
- @@ -1440,7 +1498,7 @@ static int __maybe_unused goodix_suspend
-
- /* 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;
- }
-
- @@ -1484,7 +1542,7 @@ static int __maybe_unused goodix_resume(
- 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
- @@ -104,6 +104,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);
|