summaryrefslogtreecommitdiff
path: root/drivers/input/touchscreen/goodix.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/touchscreen/goodix.c')
-rw-r--r--drivers/input/touchscreen/goodix.c150
1 files changed, 62 insertions, 88 deletions
diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c
index b77969a16986..3f5057dd9fc4 100644
--- a/drivers/input/touchscreen/goodix.c
+++ b/drivers/input/touchscreen/goodix.c
@@ -14,20 +14,15 @@
#include <linux/kernel.h>
#include <linux/dmi.h>
#include <linux/firmware.h>
-#include <linux/gpio/consumer.h>
-#include <linux/i2c.h>
-#include <linux/input.h>
-#include <linux/input/mt.h>
-#include <linux/input/touchscreen.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
-#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/acpi.h>
#include <linux/of.h>
#include <asm/unaligned.h>
+#include "goodix.h"
#define GOODIX_GPIO_INT_NAME "irq"
#define GOODIX_GPIO_RST_NAME "reset"
@@ -38,22 +33,11 @@
#define GOODIX_CONTACT_SIZE 8
#define GOODIX_MAX_CONTACT_SIZE 9
#define GOODIX_MAX_CONTACTS 10
-#define GOODIX_MAX_KEYS 7
#define GOODIX_CONFIG_MIN_LENGTH 186
#define GOODIX_CONFIG_911_LENGTH 186
#define GOODIX_CONFIG_967_LENGTH 228
#define GOODIX_CONFIG_GT9X_LENGTH 240
-#define GOODIX_CONFIG_MAX_LENGTH 240
-
-/* Register defines */
-#define GOODIX_REG_COMMAND 0x8040
-#define GOODIX_CMD_SCREEN_OFF 0x05
-
-#define GOODIX_READ_COOR_ADDR 0x814E
-#define GOODIX_GT1X_REG_CONFIG_DATA 0x8050
-#define GOODIX_GT9X_REG_CONFIG_DATA 0x8047
-#define GOODIX_REG_ID 0x8140
#define GOODIX_BUFFER_STATUS_READY BIT(7)
#define GOODIX_HAVE_KEY BIT(4)
@@ -68,55 +52,11 @@
#define ACPI_GPIO_SUPPORT
#endif
-struct goodix_ts_data;
-
-enum goodix_irq_pin_access_method {
- IRQ_PIN_ACCESS_NONE,
- IRQ_PIN_ACCESS_GPIO,
- IRQ_PIN_ACCESS_ACPI_GPIO,
- IRQ_PIN_ACCESS_ACPI_METHOD,
-};
-
-struct goodix_chip_data {
- u16 config_addr;
- int config_len;
- int (*check_config)(struct goodix_ts_data *ts, const u8 *cfg, int len);
- void (*calc_config_checksum)(struct goodix_ts_data *ts);
-};
-
struct goodix_chip_id {
const char *id;
const struct goodix_chip_data *data;
};
-#define GOODIX_ID_MAX_LEN 4
-
-struct goodix_ts_data {
- struct i2c_client *client;
- struct input_dev *input_dev;
- const struct goodix_chip_data *chip;
- struct touchscreen_properties prop;
- unsigned int max_touch_num;
- unsigned int int_trigger_type;
- struct regulator *avdd28;
- struct regulator *vddio;
- struct gpio_desc *gpiod_int;
- struct gpio_desc *gpiod_rst;
- int gpio_count;
- int gpio_int_idx;
- char id[GOODIX_ID_MAX_LEN + 1];
- u16 version;
- const char *cfg_name;
- bool reset_controller_at_probe;
- bool load_cfg_from_disk;
- struct completion firmware_loading_complete;
- unsigned long irq_flags;
- enum goodix_irq_pin_access_method irq_pin_access_method;
- unsigned int contact_size;
- u8 config[GOODIX_CONFIG_MAX_LENGTH];
- unsigned short keymap[GOODIX_MAX_KEYS];
-};
-
static int goodix_check_cfg_8(struct goodix_ts_data *ts,
const u8 *cfg, int len);
static int goodix_check_cfg_16(struct goodix_ts_data *ts,
@@ -216,8 +156,7 @@ static const struct dmi_system_id inverted_x_screen[] = {
* @buf: raw write data buffer.
* @len: length of the buffer to write
*/
-static int goodix_i2c_read(struct i2c_client *client,
- u16 reg, u8 *buf, int len)
+int goodix_i2c_read(struct i2c_client *client, u16 reg, u8 *buf, int len)
{
struct i2c_msg msgs[2];
__be16 wbuf = cpu_to_be16(reg);
@@ -245,8 +184,7 @@ static int goodix_i2c_read(struct i2c_client *client,
* @buf: raw data buffer to write.
* @len: length of the buffer to write
*/
-static int goodix_i2c_write(struct i2c_client *client, u16 reg, const u8 *buf,
- unsigned len)
+int goodix_i2c_write(struct i2c_client *client, u16 reg, const u8 *buf, int len)
{
u8 *addr_buf;
struct i2c_msg msg;
@@ -270,7 +208,7 @@ static int goodix_i2c_write(struct i2c_client *client, u16 reg, const u8 *buf,
return ret < 0 ? ret : (ret != 1 ? -EIO : 0);
}
-static int goodix_i2c_write_u8(struct i2c_client *client, u16 reg, u8 value)
+int goodix_i2c_write_u8(struct i2c_client *client, u16 reg, u8 value)
{
return goodix_i2c_write(client, reg, &value, sizeof(value));
}
@@ -563,7 +501,7 @@ static int goodix_check_cfg(struct goodix_ts_data *ts, const u8 *cfg, int len)
* @cfg: config firmware to write to device
* @len: config data length
*/
-static int goodix_send_cfg(struct goodix_ts_data *ts, const u8 *cfg, int len)
+int goodix_send_cfg(struct goodix_ts_data *ts, const u8 *cfg, int len)
{
int error;
@@ -661,62 +599,88 @@ static int goodix_irq_direction_input(struct goodix_ts_data *ts)
return -EINVAL; /* Never reached */
}
-static int goodix_int_sync(struct goodix_ts_data *ts)
+int goodix_int_sync(struct goodix_ts_data *ts)
{
int error;
error = goodix_irq_direction_output(ts, 0);
if (error)
- return error;
+ goto error;
msleep(50); /* T5: 50ms */
error = goodix_irq_direction_input(ts);
if (error)
- return error;
+ goto error;
return 0;
+
+error:
+ dev_err(&ts->client->dev, "Controller irq sync failed.\n");
+ return error;
}
/**
- * goodix_reset - Reset device during power on
+ * goodix_reset_no_int_sync - Reset device, leaving interrupt line in output mode
*
* @ts: goodix_ts_data pointer
*/
-static int goodix_reset(struct goodix_ts_data *ts)
+int goodix_reset_no_int_sync(struct goodix_ts_data *ts)
{
int error;
/* begin select I2C slave addr */
error = gpiod_direction_output(ts->gpiod_rst, 0);
if (error)
- return error;
+ goto error;
msleep(20); /* T2: > 10ms */
/* HIGH: 0x28/0x29, LOW: 0xBA/0xBB */
error = goodix_irq_direction_output(ts, ts->client->addr == 0x14);
if (error)
- return error;
+ goto error;
usleep_range(100, 2000); /* T3: > 100us */
error = gpiod_direction_output(ts->gpiod_rst, 1);
if (error)
- return error;
+ goto error;
usleep_range(6000, 10000); /* T4: > 5ms */
- /* end select I2C slave addr */
- error = gpiod_direction_input(ts->gpiod_rst);
- if (error)
- return error;
+ /*
+ * Put the reset pin back in to input / high-impedance mode to save
+ * power. Only do this in the non ACPI case since some ACPI boards
+ * don't have a pull-up, so there the reset pin must stay active-high.
+ */
+ if (ts->irq_pin_access_method == IRQ_PIN_ACCESS_GPIO) {
+ error = gpiod_direction_input(ts->gpiod_rst);
+ if (error)
+ goto error;
+ }
- error = goodix_int_sync(ts);
+ return 0;
+
+error:
+ dev_err(&ts->client->dev, "Controller reset failed.\n");
+ return error;
+}
+
+/**
+ * goodix_reset - Reset device during power on
+ *
+ * @ts: goodix_ts_data pointer
+ */
+static int goodix_reset(struct goodix_ts_data *ts)
+{
+ int error;
+
+ error = goodix_reset_no_int_sync(ts);
if (error)
return error;
- return 0;
+ return goodix_int_sync(ts);
}
#ifdef ACPI_GPIO_SUPPORT
@@ -828,6 +792,14 @@ static int goodix_add_acpi_gpio_mappings(struct goodix_ts_data *ts)
return -EINVAL;
}
+ /*
+ * Normally we put the reset pin in input / high-impedance mode to save
+ * power. But some x86/ACPI boards don't have a pull-up, so for the ACPI
+ * case, leave the pin as is. This results in the pin not being touched
+ * at all on x86/ACPI boards, except when needed for error-recover.
+ */
+ ts->gpiod_rst_flags = GPIOD_ASIS;
+
return devm_acpi_dev_add_driver_gpios(dev, gpio_mapping);
}
#else
@@ -853,6 +825,12 @@ static int goodix_get_gpio_config(struct goodix_ts_data *ts)
return -EINVAL;
dev = &ts->client->dev;
+ /*
+ * By default we request the reset pin as input, leaving it in
+ * high-impedance when not resetting the controller to save power.
+ */
+ ts->gpiod_rst_flags = GPIOD_IN;
+
ts->avdd28 = devm_regulator_get(dev, "AVDD28");
if (IS_ERR(ts->avdd28)) {
error = PTR_ERR(ts->avdd28);
@@ -890,7 +868,7 @@ retry_get_irq_gpio:
ts->gpiod_int = gpiod;
/* Get the reset line GPIO pin number */
- gpiod = devm_gpiod_get_optional(dev, GOODIX_GPIO_RST_NAME, GPIOD_IN);
+ gpiod = devm_gpiod_get_optional(dev, GOODIX_GPIO_RST_NAME, ts->gpiod_rst_flags);
if (IS_ERR(gpiod)) {
error = PTR_ERR(gpiod);
if (error != -EPROBE_DEFER)
@@ -1218,10 +1196,8 @@ reset:
if (ts->reset_controller_at_probe) {
/* reset the controller */
error = goodix_reset(ts);
- if (error) {
- dev_err(&client->dev, "Controller reset failed.\n");
+ if (error)
return error;
- }
}
error = goodix_i2c_test(client);
@@ -1363,10 +1339,8 @@ static int __maybe_unused goodix_resume(struct device *dev)
if (error != 0 || config_ver != ts->config[0]) {
error = goodix_reset(ts);
- if (error) {
- dev_err(dev, "Controller reset failed.\n");
+ if (error)
return error;
- }
if (ts->load_cfg_from_disk) {
error = goodix_send_cfg(ts, ts->config, ts->chip->config_len);