Skip to content

Commit 49db399

Browse files
jwrdegoededtor
authored andcommitted
Input: goodix - refactor IRQ pin GPIO accesses
Suspending Goodix touchscreens requires changing the interrupt pin to output before sending them a power-down command. Followed by wiggling the interrupt pin to wake the device up, after which it is put back in input mode. So far we have only effectively supported this on devices which use devicetree. On X86 ACPI platforms both looking up the pins; and using a pin as both IRQ and GPIO is a bit more complicated. E.g. on some devices we cannot directly access the IRQ pin as GPIO and we need to call ACPI methods to control it instead. This commit adds a new irq_pin_access_method field to the goodix_chip_data struct and adds goodix_irq_direction_output and goodix_irq_direction_input helpers which together abstract the GPIO accesses to the IRQ pin. This is a preparation patch for adding support for properly suspending the touchscreen on X86 ACPI platforms. BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=1786317 BugLink: nexus511/gpd-ubuntu-packages#10 BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=199207 Signed-off-by: Hans de Goede <[email protected]> Reviewed-by: Bastien Nocera <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Dmitry Torokhov <[email protected]>
1 parent 0617067 commit 49db399

File tree

1 file changed

+51
-11
lines changed

1 file changed

+51
-11
lines changed

drivers/input/touchscreen/goodix.c

Lines changed: 51 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@
3131

3232
struct goodix_ts_data;
3333

34+
enum goodix_irq_pin_access_method {
35+
IRQ_PIN_ACCESS_NONE,
36+
IRQ_PIN_ACCESS_GPIO,
37+
};
38+
3439
struct goodix_chip_data {
3540
u16 config_addr;
3641
int config_len;
@@ -53,6 +58,7 @@ struct goodix_ts_data {
5358
const char *cfg_name;
5459
struct completion firmware_loading_complete;
5560
unsigned long irq_flags;
61+
enum goodix_irq_pin_access_method irq_pin_access_method;
5662
unsigned int contact_size;
5763
};
5864

@@ -518,17 +524,48 @@ static int goodix_send_cfg(struct goodix_ts_data *ts,
518524
return 0;
519525
}
520526

527+
static int goodix_irq_direction_output(struct goodix_ts_data *ts,
528+
int value)
529+
{
530+
switch (ts->irq_pin_access_method) {
531+
case IRQ_PIN_ACCESS_NONE:
532+
dev_err(&ts->client->dev,
533+
"%s called without an irq_pin_access_method set\n",
534+
__func__);
535+
return -EINVAL;
536+
case IRQ_PIN_ACCESS_GPIO:
537+
return gpiod_direction_output(ts->gpiod_int, value);
538+
}
539+
540+
return -EINVAL; /* Never reached */
541+
}
542+
543+
static int goodix_irq_direction_input(struct goodix_ts_data *ts)
544+
{
545+
switch (ts->irq_pin_access_method) {
546+
case IRQ_PIN_ACCESS_NONE:
547+
dev_err(&ts->client->dev,
548+
"%s called without an irq_pin_access_method set\n",
549+
__func__);
550+
return -EINVAL;
551+
case IRQ_PIN_ACCESS_GPIO:
552+
return gpiod_direction_input(ts->gpiod_int);
553+
}
554+
555+
return -EINVAL; /* Never reached */
556+
}
557+
521558
static int goodix_int_sync(struct goodix_ts_data *ts)
522559
{
523560
int error;
524561

525-
error = gpiod_direction_output(ts->gpiod_int, 0);
562+
error = goodix_irq_direction_output(ts, 0);
526563
if (error)
527564
return error;
528565

529566
msleep(50); /* T5: 50ms */
530567

531-
error = gpiod_direction_input(ts->gpiod_int);
568+
error = goodix_irq_direction_input(ts);
532569
if (error)
533570
return error;
534571

@@ -552,7 +589,7 @@ static int goodix_reset(struct goodix_ts_data *ts)
552589
msleep(20); /* T2: > 10ms */
553590

554591
/* HIGH: 0x28/0x29, LOW: 0xBA/0xBB */
555-
error = gpiod_direction_output(ts->gpiod_int, ts->client->addr == 0x14);
592+
error = goodix_irq_direction_output(ts, ts->client->addr == 0x14);
556593
if (error)
557594
return error;
558595

@@ -633,6 +670,9 @@ static int goodix_get_gpio_config(struct goodix_ts_data *ts)
633670

634671
ts->gpiod_rst = gpiod;
635672

673+
if (ts->gpiod_int && ts->gpiod_rst)
674+
ts->irq_pin_access_method = IRQ_PIN_ACCESS_GPIO;
675+
636676
return 0;
637677
}
638678

@@ -911,7 +951,7 @@ static int goodix_ts_probe(struct i2c_client *client,
911951
if (error)
912952
return error;
913953

914-
if (ts->gpiod_int && ts->gpiod_rst) {
954+
if (ts->irq_pin_access_method == IRQ_PIN_ACCESS_GPIO) {
915955
/* reset the controller */
916956
error = goodix_reset(ts);
917957
if (error) {
@@ -934,7 +974,7 @@ static int goodix_ts_probe(struct i2c_client *client,
934974

935975
ts->chip = goodix_get_chip_data(ts->id);
936976

937-
if (ts->gpiod_int && ts->gpiod_rst) {
977+
if (ts->irq_pin_access_method == IRQ_PIN_ACCESS_GPIO) {
938978
/* update device config */
939979
ts->cfg_name = devm_kasprintf(&client->dev, GFP_KERNEL,
940980
"goodix_%d_cfg.bin", ts->id);
@@ -965,7 +1005,7 @@ static int goodix_ts_remove(struct i2c_client *client)
9651005
{
9661006
struct goodix_ts_data *ts = i2c_get_clientdata(client);
9671007

968-
if (ts->gpiod_int && ts->gpiod_rst)
1008+
if (ts->irq_pin_access_method == IRQ_PIN_ACCESS_GPIO)
9691009
wait_for_completion(&ts->firmware_loading_complete);
9701010

9711011
return 0;
@@ -978,7 +1018,7 @@ static int __maybe_unused goodix_suspend(struct device *dev)
9781018
int error;
9791019

9801020
/* We need gpio pins to suspend/resume */
981-
if (!ts->gpiod_int || !ts->gpiod_rst) {
1021+
if (ts->irq_pin_access_method == IRQ_PIN_ACCESS_NONE) {
9821022
disable_irq(client->irq);
9831023
return 0;
9841024
}
@@ -989,7 +1029,7 @@ static int __maybe_unused goodix_suspend(struct device *dev)
9891029
goodix_free_irq(ts);
9901030

9911031
/* Output LOW on the INT pin for 5 ms */
992-
error = gpiod_direction_output(ts->gpiod_int, 0);
1032+
error = goodix_irq_direction_output(ts, 0);
9931033
if (error) {
9941034
goodix_request_irq(ts);
9951035
return error;
@@ -1001,7 +1041,7 @@ static int __maybe_unused goodix_suspend(struct device *dev)
10011041
GOODIX_CMD_SCREEN_OFF);
10021042
if (error) {
10031043
dev_err(&ts->client->dev, "Screen off command failed\n");
1004-
gpiod_direction_input(ts->gpiod_int);
1044+
goodix_irq_direction_input(ts);
10051045
goodix_request_irq(ts);
10061046
return -EAGAIN;
10071047
}
@@ -1021,7 +1061,7 @@ static int __maybe_unused goodix_resume(struct device *dev)
10211061
struct goodix_ts_data *ts = i2c_get_clientdata(client);
10221062
int error;
10231063

1024-
if (!ts->gpiod_int || !ts->gpiod_rst) {
1064+
if (ts->irq_pin_access_method == IRQ_PIN_ACCESS_NONE) {
10251065
enable_irq(client->irq);
10261066
return 0;
10271067
}
@@ -1030,7 +1070,7 @@ static int __maybe_unused goodix_resume(struct device *dev)
10301070
* Exit sleep mode by outputting HIGH level to INT pin
10311071
* for 2ms~5ms.
10321072
*/
1033-
error = gpiod_direction_output(ts->gpiod_int, 1);
1073+
error = goodix_irq_direction_output(ts, 1);
10341074
if (error)
10351075
return error;
10361076

0 commit comments

Comments
 (0)