summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/input/touchscreen/goodix.c62
1 files changed, 51 insertions, 11 deletions
diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c
index 37b35ab97beb..f5e2e0956d74 100644
--- a/drivers/input/touchscreen/goodix.c
+++ b/drivers/input/touchscreen/goodix.c
@@ -31,6 +31,11 @@
struct goodix_ts_data;
+enum goodix_irq_pin_access_method {
+ IRQ_PIN_ACCESS_NONE,
+ IRQ_PIN_ACCESS_GPIO,
+};
+
struct goodix_chip_data {
u16 config_addr;
int config_len;
@@ -53,6 +58,7 @@ struct goodix_ts_data {
const char *cfg_name;
struct completion firmware_loading_complete;
unsigned long irq_flags;
+ enum goodix_irq_pin_access_method irq_pin_access_method;
unsigned int contact_size;
};
@@ -518,17 +524,48 @@ static int goodix_send_cfg(struct goodix_ts_data *ts,
return 0;
}
+static int goodix_irq_direction_output(struct goodix_ts_data *ts,
+ int value)
+{
+ switch (ts->irq_pin_access_method) {
+ case IRQ_PIN_ACCESS_NONE:
+ dev_err(&ts->client->dev,
+ "%s called without an irq_pin_access_method set\n",
+ __func__);
+ return -EINVAL;
+ case IRQ_PIN_ACCESS_GPIO:
+ return gpiod_direction_output(ts->gpiod_int, value);
+ }
+
+ return -EINVAL; /* Never reached */
+}
+
+static int goodix_irq_direction_input(struct goodix_ts_data *ts)
+{
+ switch (ts->irq_pin_access_method) {
+ case IRQ_PIN_ACCESS_NONE:
+ dev_err(&ts->client->dev,
+ "%s called without an irq_pin_access_method set\n",
+ __func__);
+ return -EINVAL;
+ case IRQ_PIN_ACCESS_GPIO:
+ return gpiod_direction_input(ts->gpiod_int);
+ }
+
+ return -EINVAL; /* Never reached */
+}
+
static int goodix_int_sync(struct goodix_ts_data *ts)
{
int error;
- error = gpiod_direction_output(ts->gpiod_int, 0);
+ error = goodix_irq_direction_output(ts, 0);
if (error)
return error;
msleep(50); /* T5: 50ms */
- error = gpiod_direction_input(ts->gpiod_int);
+ error = goodix_irq_direction_input(ts);
if (error)
return error;
@@ -552,7 +589,7 @@ static int goodix_reset(struct goodix_ts_data *ts)
msleep(20); /* T2: > 10ms */
/* HIGH: 0x28/0x29, LOW: 0xBA/0xBB */
- error = gpiod_direction_output(ts->gpiod_int, ts->client->addr == 0x14);
+ error = goodix_irq_direction_output(ts, ts->client->addr == 0x14);
if (error)
return error;
@@ -633,6 +670,9 @@ static int goodix_get_gpio_config(struct goodix_ts_data *ts)
ts->gpiod_rst = gpiod;
+ if (ts->gpiod_int && ts->gpiod_rst)
+ ts->irq_pin_access_method = IRQ_PIN_ACCESS_GPIO;
+
return 0;
}
@@ -911,7 +951,7 @@ static int goodix_ts_probe(struct i2c_client *client,
if (error)
return error;
- if (ts->gpiod_int && ts->gpiod_rst) {
+ if (ts->irq_pin_access_method == IRQ_PIN_ACCESS_GPIO) {
/* reset the controller */
error = goodix_reset(ts);
if (error) {
@@ -934,7 +974,7 @@ static int goodix_ts_probe(struct i2c_client *client,
ts->chip = goodix_get_chip_data(ts->id);
- if (ts->gpiod_int && ts->gpiod_rst) {
+ if (ts->irq_pin_access_method == IRQ_PIN_ACCESS_GPIO) {
/* update device config */
ts->cfg_name = devm_kasprintf(&client->dev, GFP_KERNEL,
"goodix_%d_cfg.bin", ts->id);
@@ -965,7 +1005,7 @@ static int goodix_ts_remove(struct i2c_client *client)
{
struct goodix_ts_data *ts = i2c_get_clientdata(client);
- if (ts->gpiod_int && ts->gpiod_rst)
+ if (ts->irq_pin_access_method == IRQ_PIN_ACCESS_GPIO)
wait_for_completion(&ts->firmware_loading_complete);
return 0;
@@ -978,7 +1018,7 @@ static int __maybe_unused goodix_suspend(struct device *dev)
int error;
/* We need gpio pins to suspend/resume */
- if (!ts->gpiod_int || !ts->gpiod_rst) {
+ if (ts->irq_pin_access_method == IRQ_PIN_ACCESS_NONE) {
disable_irq(client->irq);
return 0;
}
@@ -989,7 +1029,7 @@ static int __maybe_unused goodix_suspend(struct device *dev)
goodix_free_irq(ts);
/* Output LOW on the INT pin for 5 ms */
- error = gpiod_direction_output(ts->gpiod_int, 0);
+ error = goodix_irq_direction_output(ts, 0);
if (error) {
goodix_request_irq(ts);
return error;
@@ -1001,7 +1041,7 @@ static int __maybe_unused goodix_suspend(struct device *dev)
GOODIX_CMD_SCREEN_OFF);
if (error) {
dev_err(&ts->client->dev, "Screen off command failed\n");
- gpiod_direction_input(ts->gpiod_int);
+ goodix_irq_direction_input(ts);
goodix_request_irq(ts);
return -EAGAIN;
}
@@ -1021,7 +1061,7 @@ static int __maybe_unused goodix_resume(struct device *dev)
struct goodix_ts_data *ts = i2c_get_clientdata(client);
int error;
- if (!ts->gpiod_int || !ts->gpiod_rst) {
+ if (ts->irq_pin_access_method == IRQ_PIN_ACCESS_NONE) {
enable_irq(client->irq);
return 0;
}
@@ -1030,7 +1070,7 @@ static int __maybe_unused goodix_resume(struct device *dev)
* Exit sleep mode by outputting HIGH level to INT pin
* for 2ms~5ms.
*/
- error = gpiod_direction_output(ts->gpiod_int, 1);
+ error = goodix_irq_direction_output(ts, 1);
if (error)
return error;