Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 72995406 authored by Bingzhe Cai's avatar Bingzhe Cai
Browse files

input: touchscreen: add multiple config data support for GT9xx



Goodix GT9xx touchscreen driver supports up to six groups of config
data and uses hardware GPIO configuration to select which one will
be used. This change allows these six config groups to be loaded
from devicetree.

Change-Id: I9dfd698e7084164688dd964ed914d5eecc75ecd3
Signed-off-by: default avatarBingzhe Cai <bingzhec@codeaurora.org>
parent 179b553f
Loading
Loading
Loading
Loading
+38 −24
Original line number Diff line number Diff line
@@ -32,10 +32,24 @@ Optional properties:
 - goodix,no-force-update	: To specify force update is allowed.
 - goodix,button-map	: Button map of key codes. The number of key codes
				depend on panel.
 - goodix,cfg-data	: Touchpanel controller configuration data, ask vendor
				to provide that. Default configuration will be
				used if this property is not present.

 - goodix,cfg-data0	: Touch screen controller config data group 0. Ask vendor
				to provide that.
				Driver supports maximum six config groups. If more than one
				groups are defined, driver will select config group depending
				on hardware configuration. If only config group 0 is defined,
				it will be used for all hardware configurations.
				Touch screen controller will use its onchip default config data
				if this property is not present.
 - goodix,cfg-data1	: Touch screen controller config data group 1. Ask vendor
				to provide that.
 - goodix,cfg-data2	: Touch screen controller config data group 2. Ask vendor
				to provide that.
 - goodix,cfg-data3	: Touch screen controller config data group 3. Ask vendor
				to provide that.
 - goodix,cfg-data4	: Touch screen controller config data group 4. Ask vendor
				to provide that.
 - goodix,cfg-data5	: Touch screen controller config data group 5. Ask vendor
				to provide that.
Example:
i2c@f9927000 {
		goodix@5d {
@@ -50,7 +64,7 @@ i2c@f9927000 {
			goodix,display-coords = <0 0 720 1080>;
			goodix,button-map= <158 102 139>;
			goodix,product-id = "915";
			goodix,cfg-data = [
			goodix,cfg-data0 = [
				41 D0 02 00 05 0A 05 01 01 08
				12 58 50 41 03 05 00 00 00 00
				00 00 00 00 00 00 00 8C 2E 0E
+40 −20
Original line number Diff line number Diff line
@@ -61,13 +61,33 @@
			goodix,display-coords = <0 0 720 1080>;
			goodix,button-map= <158 102 139>;
			goodix,product-id = "915";
			goodix,cfg-data = [
			41 D0 02 00 05 0A 35 01 01 0F
			2D 08 55 32 03 04 00 00 00 00
			goodix,cfg-data0 = [
				41 D0 02 00 05 05 35 01 01 0F
				2D 06 50 32 03 05 00 00 00 00
				00 00 05 18 1A 1E 14 8C 0E 0E
				3F 3D 2A 09 00 00 00 99 04 1D
				00 00 00 00 00 00 00 00 00 00
				00 32 6E 94 D5 01 05 00 00 04
				CE 36 00 B5 3F 00 9E 4A 00 8B
				57 00 7C 65 00 7C 10 38 68 00
				56 50 35 66 66 27 00 00 00 00
				00 00 00 00 00 00 00 00 00 00
				00 00 00 00 00 00 00 00 00 00
				00 00 02 04 06 08 0A 0C 0E 10
				12 14 16 18 1A 1C 00 00 00 00
				00 00 00 00 00 00 00 00 00 00
				00 00 00 02 04 06 08 0A 0C 0F
				10 12 13 14 16 18 1C 1D 1E 1F
				20 21 22 24 26 28 29 2A 00 00
				00 FF FF FF FF FF FF FF FF FF
				FF FF FF FF A3 01];
			goodix,cfg-data1 = [
				41 D0 02 00 05 05 35 01 01 C3
				2D 06 55 32 03 03 00 00 00 00
				00 00 05 0A 0C 0F 0A 8C 0E 0E
			30 2E B8 08 00 00 00 83 03 1D
				30 2E B8 08 00 00 00 8F 03 1D
				00 00 00 00 00 00 00 00 00 00
			00 2D 62 94 C5 02 05 00 00 04
				00 2D 62 94 D5 02 05 00 00 04
				96 30 00 80 39 00 71 42 00 63
				4D 00 56 5A 00 56 10 38 68 00
				56 50 35 AA AA 27 00 00 00 00
@@ -80,7 +100,7 @@
				10 12 13 14 16 18 1C 1D 1E 1F
				20 21 22 24 26 28 29 2A FF FF
				FF FF FF FF FF FF FF FF FF FF
			FF FF FF FF 06 01];
				FF FF FF FF 3E 01];
		};
	};
};
+50 −64
Original line number Diff line number Diff line
@@ -73,6 +73,7 @@
#define RESET_DELAY_T4		20	/* T4: > 5ms */

#define PHY_BUF_SIZE		32
#define PROP_NAME_SIZE		24

#define GTP_MAX_TOUCH		5
#define GTP_ESD_CHECK_CIRCLE_MS	2000
@@ -871,22 +872,9 @@ static int gtp_init_panel(struct goodix_ts_data *ts)
	u8 opr_buf[16];
	u8 sensor_id = 0;

	u8 cfg_info_group1[] = CTP_CFG_GROUP1;
	u8 cfg_info_group2[] = CTP_CFG_GROUP2;
	u8 cfg_info_group3[] = CTP_CFG_GROUP3;
	u8 cfg_info_group4[] = CTP_CFG_GROUP4;
	u8 cfg_info_group5[] = CTP_CFG_GROUP5;
	u8 cfg_info_group6[] = CTP_CFG_GROUP6;
	u8 *send_cfg_buf[] = {cfg_info_group1, cfg_info_group2,
		cfg_info_group3, cfg_info_group4,
		cfg_info_group5, cfg_info_group6};

	u8 cfg_info_len[] = {CFG_GROUP_LEN(cfg_info_group1),
		CFG_GROUP_LEN(cfg_info_group2),
		CFG_GROUP_LEN(cfg_info_group3),
		CFG_GROUP_LEN(cfg_info_group4),
		CFG_GROUP_LEN(cfg_info_group5),
		CFG_GROUP_LEN(cfg_info_group6)};
	for (i = 0; i < GOODIX_MAX_CFG_GROUP; i++)
		dev_dbg(&client->dev, "Config Groups(%d) Lengths: %d",
			i, ts->pdata->config_data_len[i]);

	ret = gtp_i2c_read_dbl_check(ts->client, 0x41E4, opr_buf, 1);
	if (SUCCESS == ret) {
@@ -897,14 +885,18 @@ static int gtp_init_panel(struct goodix_ts_data *ts)
			return -EINVAL;
		}
	}
	if ((!cfg_info_len[1]) && (!cfg_info_len[2]) && (!cfg_info_len[3])
		&& (!cfg_info_len[4]) && (!cfg_info_len[5])) {

	for (i = 1; i < GOODIX_MAX_CFG_GROUP; i++) {
		if (ts->pdata->config_data_len[i])
			break;
	}
	if (i == GOODIX_MAX_CFG_GROUP) {
		sensor_id = 0;
	} else {
		ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_SENSOR_ID,
			&sensor_id, 1);
		if (SUCCESS == ret) {
			if (sensor_id >= 0x06) {
			if (sensor_id >= GOODIX_MAX_CFG_GROUP) {
				dev_err(&client->dev,
					"Invalid sensor_id(0x%02X), No Config Sent!",
					sensor_id);
@@ -916,22 +908,26 @@ static int gtp_init_panel(struct goodix_ts_data *ts)
			return -EINVAL;
		}
	}
	ts->gtp_cfg_len = cfg_info_len[sensor_id];

	if (ts->gtp_cfg_len < GTP_CONFIG_MIN_LENGTH) {
	dev_info(&client->dev, "Sensor ID selected: %d", sensor_id);

	if (ts->pdata->config_data_len[sensor_id] < GTP_CONFIG_MIN_LENGTH ||
		!ts->pdata->config_data[sensor_id]) {
		dev_err(&client->dev,
				"Sensor_ID(%d) matches with NULL or INVALID CONFIG GROUP! NO Config Sent! You need to check you header file CFG_GROUP section!\n",
				"Sensor_ID(%d) matches with NULL or invalid config group!\n",
				sensor_id);
		return -EINVAL;
	}

	ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_CONFIG_DATA,
		&opr_buf[0], 1);

	if (ret == SUCCESS) {
		if (opr_buf[0] < 90) {
			/* backup group config version */
			grp_cfg_version = send_cfg_buf[sensor_id][0];
			send_cfg_buf[sensor_id][0] = 0x00;
			grp_cfg_version =
			ts->pdata->config_data[sensor_id][GTP_ADDR_LENGTH];
			ts->pdata->config_data[sensor_id][GTP_ADDR_LENGTH] =
				0x00;
			ts->fixed_cfg = 0;
		} else {
			/* treated as fixed config, not send config */
@@ -946,27 +942,9 @@ static int gtp_init_panel(struct goodix_ts_data *ts)
		return -EINVAL;
	}

	if (ts->pdata->gtp_cfg_len) {
		config_data = ts->pdata->config_data;
		ts->config_data = ts->pdata->config_data;
		ts->gtp_cfg_len = ts->pdata->gtp_cfg_len;
	} else {
		config_data = devm_kzalloc(&client->dev,
			GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH,
				GFP_KERNEL);
		if (!config_data) {
			dev_err(&client->dev,
					"Not enough memory for panel config data\n");
			return -ENOMEM;
		}

		ts->config_data = config_data;
		config_data[0] = GTP_REG_CONFIG_DATA >> 8;
		config_data[1] = GTP_REG_CONFIG_DATA & 0xff;
		memset(&config_data[GTP_ADDR_LENGTH], 0, GTP_CONFIG_MAX_LENGTH);
		memcpy(&config_data[GTP_ADDR_LENGTH], send_cfg_buf[sensor_id],
				ts->gtp_cfg_len);
	}
	config_data = ts->pdata->config_data[sensor_id];
	ts->config_data = ts->pdata->config_data[sensor_id];
	ts->gtp_cfg_len = ts->pdata->config_data_len[sensor_id];

#if GTP_CUSTOM_CFG
	config_data[RESOLUTION_LOC] =
@@ -1547,6 +1525,8 @@ static int goodix_parse_dt(struct device *dev,
	struct property *prop;
	u32 temp_val, num_buttons;
	u32 button_map[MAX_BUTTONS];
	char prop_name[PROP_NAME_SIZE];
	int i, read_cfg_num;

	rc = goodix_ts_get_dt_coords(dev, "goodix,panel-coords", pdata);
	if (rc && (rc != -EINVAL))
@@ -1592,26 +1572,32 @@ static int goodix_parse_dt(struct device *dev,
		}
	}

	prop = of_find_property(np, "goodix,cfg-data", &pdata->gtp_cfg_len);
	if (prop && prop->value) {
		pdata->config_data = devm_kzalloc(dev,
			GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH, GFP_KERNEL);
		if (!pdata->config_data) {
			dev_err(dev, "Not enough memory for panel config data\n");
			return -ENOMEM;
	read_cfg_num = 0;
	for (i = 0; i < GOODIX_MAX_CFG_GROUP; i++) {
		snprintf(prop_name, sizeof(prop_name), "goodix,cfg-data%d", i);
		prop = of_find_property(np, prop_name,
			&pdata->config_data_len[i]);
		if (!prop || !prop->value) {
			pdata->config_data_len[i] = 0;
			pdata->config_data[i] = NULL;
			continue;
		}

		pdata->config_data[0] = GTP_REG_CONFIG_DATA >> 8;
		pdata->config_data[1] = GTP_REG_CONFIG_DATA & 0xff;
		memset(&pdata->config_data[GTP_ADDR_LENGTH], 0,
					GTP_CONFIG_MAX_LENGTH);
		memcpy(&pdata->config_data[GTP_ADDR_LENGTH],
				prop->value, pdata->gtp_cfg_len);
	} else {
		pdata->config_data[i] = devm_kzalloc(dev,
				GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH,
				GFP_KERNEL);
		if (!pdata->config_data[i]) {
			dev_err(dev,
			"Unable to get configure data, default will be used.\n");
		pdata->gtp_cfg_len = 0;
				"Not enough memory for panel config data %d\n",
				i);
			return -ENOMEM;
		}
		pdata->config_data[i][0] = GTP_REG_CONFIG_DATA >> 8;
		pdata->config_data[i][1] = GTP_REG_CONFIG_DATA & 0xff;
		memcpy(&pdata->config_data[i][GTP_ADDR_LENGTH],
				prop->value, pdata->config_data_len[i]);
		read_cfg_num++;
	}
	dev_dbg(dev, "%d config data read from device tree.\n", read_cfg_num);

	return 0;
}
+3 −50
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@
#define GOODIX_SUSPEND_LEVEL 1
#endif

#define GOODIX_MAX_CFG_GROUP	6
struct goodix_ts_platform_data {
	int irq_gpio;
	u32 irq_gpio_flags;
@@ -61,8 +62,8 @@ struct goodix_ts_platform_data {
	u32 panel_maxy;
	bool no_force_update;
	bool i2c_pull_up;
	int gtp_cfg_len;
	u8 *config_data;
	size_t config_data_len[GOODIX_MAX_CFG_GROUP];
	u8 *config_data[GOODIX_MAX_CFG_GROUP];
};
struct goodix_ts_data {
	spinlock_t irq_lock;
@@ -137,54 +138,6 @@ extern u16 total_len;
 *	VDDIO		NC/300K		4
 *	NC			NC/300K		5
*/
/* Define your own default or for Sensor_ID == 0 config here */
/* The predefined one is just a sample config,
 * which is not suitable for your tp in most cases. */
#define CTP_CFG_GROUP1 {\
	0x41, 0x1C, 0x02, 0xC0, 0x03, 0x0A, 0x05, 0x01, 0x01, 0x0F,\
	0x23, 0x0F, 0x5F, 0x41, 0x03, 0x05, 0x00, 0x00, 0x00, 0x00,\
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0x00, 0x0A,\
	0x28, 0x00, 0xB8, 0x0B, 0x00, 0x00, 0x00, 0x9A, 0x03, 0x25,\
	0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x64, 0x32, 0x00, 0x00,\
	0x00, 0x32, 0x8C, 0x94, 0x05, 0x01, 0x05, 0x00, 0x00, 0x96,\
	0x0C, 0x22, 0xD8, 0x0E, 0x23, 0x56, 0x11, 0x25, 0xFF, 0x13,\
	0x28, 0xA7, 0x15, 0x2E, 0x00, 0x00, 0x10, 0x30, 0x48, 0x00,\
	0x56, 0x4A, 0x3A, 0xFF, 0xFF, 0x16, 0x00, 0x00, 0x00, 0x00,\
	0x00, 0x01, 0x1B, 0x14, 0x0D, 0x19, 0x00, 0x00, 0x01, 0x00,\
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
	0x00, 0x00, 0x1A, 0x18, 0x16, 0x14, 0x12, 0x10, 0x0E, 0x0C,\
	0x0A, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\
	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\
	0xFF, 0xFF, 0x1D, 0x1E, 0x1F, 0x20, 0x22, 0x24, 0x28, 0x29,\
	0x0C, 0x0A, 0x08, 0x00, 0x02, 0x04, 0x05, 0x06, 0x0E, 0xFF,\
	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\
	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\
	0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0x01\
	}

/* Define your config for Sensor_ID == 1 here, if needed */
#define CTP_CFG_GROUP2 {\
	}

/* Define your config for Sensor_ID == 2 here, if needed */
#define CTP_CFG_GROUP3 {\
	}

/* Define your config for Sensor_ID == 3 here, if needed */
#define CTP_CFG_GROUP4 {\
	}

/* Define your config for Sensor_ID == 4 here, if needed */
#define CTP_CFG_GROUP5 {\
	}

/* Define your config for Sensor_ID == 5 here, if needed */
#define CTP_CFG_GROUP6 {\
	}

#define GTP_IRQ_TAB		{\
				IRQ_TYPE_EDGE_RISING,\