Commit 25309004 authored by Marcin Niestroj's avatar Marcin Niestroj Committed by Dmitry Torokhov

Input: goodix - support gt1151 touchpanel

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_genericSigned-off-by: default avatarMarcin Niestroj <m.niestroj@grinn-global.com>
Acked-by: default avatarRob Herring <robh@kernel.org>
Signed-off-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
parent 6a3eafe4
...@@ -2,7 +2,8 @@ Device tree bindings for Goodix GT9xx series touchscreen controller ...@@ -2,7 +2,8 @@ Device tree bindings for Goodix GT9xx series touchscreen controller
Required properties: Required properties:
- compatible : Should be "goodix,gt911" - compatible : Should be "goodix,gt1151"
or "goodix,gt911"
or "goodix,gt9110" or "goodix,gt9110"
or "goodix,gt912" or "goodix,gt912"
or "goodix,gt927" or "goodix,gt927"
......
...@@ -31,9 +31,18 @@ ...@@ -31,9 +31,18 @@
#include <linux/of.h> #include <linux/of.h>
#include <asm/unaligned.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 goodix_ts_data {
struct i2c_client *client; struct i2c_client *client;
struct input_dev *input_dev; struct input_dev *input_dev;
const struct goodix_chip_data *chip;
int abs_x_max; int abs_x_max;
int abs_y_max; int abs_y_max;
bool swapped_x_y; bool swapped_x_y;
...@@ -41,7 +50,6 @@ struct goodix_ts_data { ...@@ -41,7 +50,6 @@ struct goodix_ts_data {
bool inverted_y; bool inverted_y;
unsigned int max_touch_num; unsigned int max_touch_num;
unsigned int int_trigger_type; unsigned int int_trigger_type;
int cfg_len;
struct gpio_desc *gpiod_int; struct gpio_desc *gpiod_int;
struct gpio_desc *gpiod_rst; struct gpio_desc *gpiod_rst;
u16 id; u16 id;
...@@ -69,7 +77,8 @@ struct goodix_ts_data { ...@@ -69,7 +77,8 @@ struct goodix_ts_data {
#define GOODIX_CMD_SCREEN_OFF 0x05 #define GOODIX_CMD_SCREEN_OFF 0x05
#define GOODIX_READ_COOR_ADDR 0x814E #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_REG_ID 0x8140
#define GOODIX_BUFFER_STATUS_READY BIT(7) #define GOODIX_BUFFER_STATUS_READY BIT(7)
...@@ -79,6 +88,35 @@ struct goodix_ts_data { ...@@ -79,6 +88,35 @@ struct goodix_ts_data {
#define MAX_CONTACTS_LOC 5 #define MAX_CONTACTS_LOC 5
#define TRIGGER_LOC 6 #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[] = { static const unsigned long goodix_irq_flags[] = {
IRQ_TYPE_EDGE_RISING, IRQ_TYPE_EDGE_RISING,
IRQ_TYPE_EDGE_FALLING, IRQ_TYPE_EDGE_FALLING,
...@@ -177,22 +215,25 @@ static int goodix_i2c_write_u8(struct i2c_client *client, u16 reg, u8 value) ...@@ -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)); 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) { switch (id) {
case 1151:
return &gt1x_chip_data;
case 911: case 911:
case 9271: case 9271:
case 9110: case 9110:
case 927: case 927:
case 928: case 928:
return GOODIX_CONFIG_911_LENGTH; return &gt911_chip_data;
case 912: case 912:
case 967: case 967:
return GOODIX_CONFIG_967_LENGTH; return &gt967_chip_data;
default: default:
return GOODIX_CONFIG_MAX_LENGTH; return &gt9x_chip_data;
} }
} }
...@@ -332,25 +373,12 @@ static int goodix_request_irq(struct goodix_ts_data *ts) ...@@ -332,25 +373,12 @@ static int goodix_request_irq(struct goodix_ts_data *ts)
ts->irq_flags, ts->client->name, ts); ts->irq_flags, ts->client->name, ts);
} }
/** static int goodix_check_cfg_8(struct goodix_ts_data *ts,
* goodix_check_cfg - Checks if config fw is valid const struct firmware *cfg)
*
* @ts: goodix_ts_data pointer
* @cfg: firmware config data
*/
static int goodix_check_cfg(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; 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++) for (i = 0; i < raw_cfg_len; i++)
check_sum += cfg->data[i]; check_sum += cfg->data[i];
check_sum = (~check_sum) + 1; check_sum = (~check_sum) + 1;
...@@ -369,6 +397,48 @@ static int goodix_check_cfg(struct goodix_ts_data *ts, ...@@ -369,6 +397,48 @@ static int goodix_check_cfg(struct goodix_ts_data *ts,
return 0; 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 * goodix_send_cfg - Write fw config to device
* *
...@@ -384,7 +454,7 @@ static int goodix_send_cfg(struct goodix_ts_data *ts, ...@@ -384,7 +454,7 @@ static int goodix_send_cfg(struct goodix_ts_data *ts,
if (error) if (error)
return 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); cfg->size);
if (error) { if (error) {
dev_err(&ts->client->dev, "Failed to write config data: %d", 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) ...@@ -511,8 +581,8 @@ static void goodix_read_config(struct goodix_ts_data *ts)
u8 config[GOODIX_CONFIG_MAX_LENGTH]; u8 config[GOODIX_CONFIG_MAX_LENGTH];
int error; int error;
error = goodix_i2c_read(ts->client, GOODIX_REG_CONFIG_DATA, error = goodix_i2c_read(ts->client, ts->chip->config_addr,
config, ts->cfg_len); config, ts->chip->config_len);
if (error) { if (error) {
dev_warn(&ts->client->dev, dev_warn(&ts->client->dev,
"Error reading config (%d), using defaults\n", "Error reading config (%d), using defaults\n",
...@@ -592,7 +662,7 @@ static int goodix_i2c_test(struct i2c_client *client) ...@@ -592,7 +662,7 @@ static int goodix_i2c_test(struct i2c_client *client)
u8 test; u8 test;
while (retry++ < 2) { while (retry++ < 2) {
error = goodix_i2c_read(client, GOODIX_REG_CONFIG_DATA, error = goodix_i2c_read(client, GOODIX_REG_ID,
&test, 1); &test, 1);
if (!error) if (!error)
return 0; return 0;
...@@ -762,7 +832,7 @@ static int goodix_ts_probe(struct i2c_client *client, ...@@ -762,7 +832,7 @@ static int goodix_ts_probe(struct i2c_client *client,
return error; 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) { if (ts->gpiod_int && ts->gpiod_rst) {
/* update device config */ /* update device config */
...@@ -891,6 +961,7 @@ MODULE_DEVICE_TABLE(acpi, goodix_acpi_match); ...@@ -891,6 +961,7 @@ MODULE_DEVICE_TABLE(acpi, goodix_acpi_match);
#ifdef CONFIG_OF #ifdef CONFIG_OF
static const struct of_device_id goodix_of_match[] = { static const struct of_device_id goodix_of_match[] = {
{ .compatible = "goodix,gt1151" },
{ .compatible = "goodix,gt911" }, { .compatible = "goodix,gt911" },
{ .compatible = "goodix,gt9110" }, { .compatible = "goodix,gt9110" },
{ .compatible = "goodix,gt912" }, { .compatible = "goodix,gt912" },
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment