Input: goodix - support gt1151 touchpanel
authorMarcin Niestroj <m.niestroj@grinn-global.com>
Tue, 24 Oct 2017 18:06:41 +0000 (11:06 -0700)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Tue, 24 Oct 2017 18:58:19 +0000 (11:58 -0700)
Support was added based on Goodix GitHub repo [1]. There are two major
differences between gt1151 and currently supported devices (gt9x):
 * CONFIG_DATA register has 0x8050 address instead of 0x8047,
 * config data checksum has 16-bit width instead of 8-bit.

Also update goodix_i2c_test() function, so it reads ID register (which
has the same address for all devices) instead of CONFIG_DATA (because
its address is known only after reading ID of the device).

[1] https://github.com/goodix/gt1x_driver_generic

Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Documentation/devicetree/bindings/input/touchscreen/goodix.txt
drivers/input/touchscreen/goodix.c

index c98757a69110dbc6a997998d1e27753c205bdbdd..0c369d8ebcabdfebc04539f5905ee3b9f38d15de 100644 (file)
@@ -2,7 +2,8 @@ Device tree bindings for Goodix GT9xx series touchscreen controller
 
 Required properties:
 
- - compatible          : Should be "goodix,gt911"
+ - compatible          : Should be "goodix,gt1151"
+                                or "goodix,gt911"
                                 or "goodix,gt9110"
                                 or "goodix,gt912"
                                 or "goodix,gt927"
index b3bbad7d228296118f35a2d4bff7c295b5e9839c..69d0b8cbc71f8cab52d83a4ca411bd9b4eb1d670 100644 (file)
 #include <linux/of.h>
 #include <asm/unaligned.h>
 
+struct goodix_ts_data;
+
+struct goodix_chip_data {
+       u16 config_addr;
+       int config_len;
+       int (*check_config)(struct goodix_ts_data *, const struct firmware *);
+};
+
 struct goodix_ts_data {
        struct i2c_client *client;
        struct input_dev *input_dev;
+       const struct goodix_chip_data *chip;
        int abs_x_max;
        int abs_y_max;
        bool swapped_x_y;
@@ -41,7 +50,6 @@ struct goodix_ts_data {
        bool inverted_y;
        unsigned int max_touch_num;
        unsigned int int_trigger_type;
-       int cfg_len;
        struct gpio_desc *gpiod_int;
        struct gpio_desc *gpiod_rst;
        u16 id;
@@ -69,7 +77,8 @@ struct goodix_ts_data {
 #define GOODIX_CMD_SCREEN_OFF          0x05
 
 #define GOODIX_READ_COOR_ADDR          0x814E
-#define GOODIX_REG_CONFIG_DATA         0x8047
+#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)
@@ -79,6 +88,35 @@ struct goodix_ts_data {
 #define MAX_CONTACTS_LOC       5
 #define TRIGGER_LOC            6
 
+static int goodix_check_cfg_8(struct goodix_ts_data *ts,
+                       const struct firmware *cfg);
+static int goodix_check_cfg_16(struct goodix_ts_data *ts,
+                       const struct firmware *cfg);
+
+static const struct goodix_chip_data gt1x_chip_data = {
+       .config_addr            = GOODIX_GT1X_REG_CONFIG_DATA,
+       .config_len             = GOODIX_CONFIG_MAX_LENGTH,
+       .check_config           = goodix_check_cfg_16,
+};
+
+static const struct goodix_chip_data gt911_chip_data = {
+       .config_addr            = GOODIX_GT9X_REG_CONFIG_DATA,
+       .config_len             = GOODIX_CONFIG_911_LENGTH,
+       .check_config           = goodix_check_cfg_8,
+};
+
+static const struct goodix_chip_data gt967_chip_data = {
+       .config_addr            = GOODIX_GT9X_REG_CONFIG_DATA,
+       .config_len             = GOODIX_CONFIG_967_LENGTH,
+       .check_config           = goodix_check_cfg_8,
+};
+
+static const struct goodix_chip_data gt9x_chip_data = {
+       .config_addr            = GOODIX_GT9X_REG_CONFIG_DATA,
+       .config_len             = GOODIX_CONFIG_MAX_LENGTH,
+       .check_config           = goodix_check_cfg_8,
+};
+
 static const unsigned long goodix_irq_flags[] = {
        IRQ_TYPE_EDGE_RISING,
        IRQ_TYPE_EDGE_FALLING,
@@ -177,22 +215,25 @@ static int goodix_i2c_write_u8(struct i2c_client *client, u16 reg, u8 value)
        return goodix_i2c_write(client, reg, &value, sizeof(value));
 }
 
-static int goodix_get_cfg_len(u16 id)
+static const struct goodix_chip_data *goodix_get_chip_data(u16 id)
 {
        switch (id) {
+       case 1151:
+               return &gt1x_chip_data;
+
        case 911:
        case 9271:
        case 9110:
        case 927:
        case 928:
-               return GOODIX_CONFIG_911_LENGTH;
+               return &gt911_chip_data;
 
        case 912:
        case 967:
-               return GOODIX_CONFIG_967_LENGTH;
+               return &gt967_chip_data;
 
        default:
-               return GOODIX_CONFIG_MAX_LENGTH;
+               return &gt9x_chip_data;
        }
 }
 
@@ -332,25 +373,12 @@ static int goodix_request_irq(struct goodix_ts_data *ts)
                                         ts->irq_flags, ts->client->name, ts);
 }
 
-/**
- * goodix_check_cfg - Checks if config fw is valid
- *
- * @ts: goodix_ts_data pointer
- * @cfg: firmware config data
- */
-static int goodix_check_cfg(struct goodix_ts_data *ts,
-                           const struct firmware *cfg)
+static int goodix_check_cfg_8(struct goodix_ts_data *ts,
+                       const struct firmware *cfg)
 {
-       int i, raw_cfg_len;
+       int i, raw_cfg_len = cfg->size - 2;
        u8 check_sum = 0;
 
-       if (cfg->size > GOODIX_CONFIG_MAX_LENGTH) {
-               dev_err(&ts->client->dev,
-                       "The length of the config fw is not correct");
-               return -EINVAL;
-       }
-
-       raw_cfg_len = cfg->size - 2;
        for (i = 0; i < raw_cfg_len; i++)
                check_sum += cfg->data[i];
        check_sum = (~check_sum) + 1;
@@ -369,6 +397,48 @@ static int goodix_check_cfg(struct goodix_ts_data *ts,
        return 0;
 }
 
+static int goodix_check_cfg_16(struct goodix_ts_data *ts,
+                       const struct firmware *cfg)
+{
+       int i, raw_cfg_len = cfg->size - 3;
+       u16 check_sum = 0;
+
+       for (i = 0; i < raw_cfg_len; i += 2)
+               check_sum += get_unaligned_be16(&cfg->data[i]);
+       check_sum = (~check_sum) + 1;
+       if (check_sum != get_unaligned_be16(&cfg->data[raw_cfg_len])) {
+               dev_err(&ts->client->dev,
+                       "The checksum of the config fw is not correct");
+               return -EINVAL;
+       }
+
+       if (cfg->data[raw_cfg_len + 2] != 1) {
+               dev_err(&ts->client->dev,
+                       "Config fw must have Config_Fresh register set");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/**
+ * goodix_check_cfg - Checks if config fw is valid
+ *
+ * @ts: goodix_ts_data pointer
+ * @cfg: firmware config data
+ */
+static int goodix_check_cfg(struct goodix_ts_data *ts,
+                           const struct firmware *cfg)
+{
+       if (cfg->size > GOODIX_CONFIG_MAX_LENGTH) {
+               dev_err(&ts->client->dev,
+                       "The length of the config fw is not correct");
+               return -EINVAL;
+       }
+
+       return ts->chip->check_config(ts, cfg);
+}
+
 /**
  * goodix_send_cfg - Write fw config to device
  *
@@ -384,7 +454,7 @@ static int goodix_send_cfg(struct goodix_ts_data *ts,
        if (error)
                return error;
 
-       error = goodix_i2c_write(ts->client, GOODIX_REG_CONFIG_DATA, cfg->data,
+       error = goodix_i2c_write(ts->client, ts->chip->config_addr, cfg->data,
                                 cfg->size);
        if (error) {
                dev_err(&ts->client->dev, "Failed to write config data: %d",
@@ -511,8 +581,8 @@ static void goodix_read_config(struct goodix_ts_data *ts)
        u8 config[GOODIX_CONFIG_MAX_LENGTH];
        int error;
 
-       error = goodix_i2c_read(ts->client, GOODIX_REG_CONFIG_DATA,
-                               config, ts->cfg_len);
+       error = goodix_i2c_read(ts->client, ts->chip->config_addr,
+                               config, ts->chip->config_len);
        if (error) {
                dev_warn(&ts->client->dev,
                         "Error reading config (%d), using defaults\n",
@@ -592,7 +662,7 @@ static int goodix_i2c_test(struct i2c_client *client)
        u8 test;
 
        while (retry++ < 2) {
-               error = goodix_i2c_read(client, GOODIX_REG_CONFIG_DATA,
+               error = goodix_i2c_read(client, GOODIX_REG_ID,
                                        &test, 1);
                if (!error)
                        return 0;
@@ -762,7 +832,7 @@ static int goodix_ts_probe(struct i2c_client *client,
                return error;
        }
 
-       ts->cfg_len = goodix_get_cfg_len(ts->id);
+       ts->chip = goodix_get_chip_data(ts->id);
 
        if (ts->gpiod_int && ts->gpiod_rst) {
                /* update device config */
@@ -891,6 +961,7 @@ MODULE_DEVICE_TABLE(acpi, goodix_acpi_match);
 
 #ifdef CONFIG_OF
 static const struct of_device_id goodix_of_match[] = {
+       { .compatible = "goodix,gt1151" },
        { .compatible = "goodix,gt911" },
        { .compatible = "goodix,gt9110" },
        { .compatible = "goodix,gt912" },