diff mbox series

Input: st1232 - read resolution from touch panel

Message ID 20200615132533.3852637-1-john@metanate.com
State New
Headers show
Series Input: st1232 - read resolution from touch panel | expand

Commit Message

John Keeping June 15, 2020, 1:25 p.m. UTC
The ST1232 and ST1633 touch controllers have read/write registers for
the X and Y resolution and it seems that these can also be
pre-programmed so that the resolution is matched to that of the display
paired with the touch panel.

Instead of hard coding the resolution in the driver, read it from the
controller when probing.  This requires a delay after de-asserting reset
in order to ensure that the I2C communication succeeds.

I have tested this on ST1633 and the datasheet for ST1232 indicates that
the format of these registers is the same there (and at the same
address).

Signed-off-by: John Keeping <john@metanate.com>
---
 drivers/input/touchscreen/st1232.c | 55 +++++++++++++++++++++++++-----
 1 file changed, 46 insertions(+), 9 deletions(-)
diff mbox series

Patch

diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c
index 63b29c7279e2..4e032d3a3737 100644
--- a/drivers/input/touchscreen/st1232.c
+++ b/drivers/input/touchscreen/st1232.c
@@ -28,10 +28,10 @@ 
 
 #define ST_TS_MAX_FINGERS	10
 
+#define ST1232_RESOLUTION_REG	0x04
+
 struct st_chip_info {
 	bool	have_z;
-	u16	max_x;
-	u16	max_y;
 	u16	max_area;
 	u16	max_fingers;
 	u8	start_reg;
@@ -44,6 +44,8 @@  struct st1232_ts_data {
 	struct dev_pm_qos_request low_latency_req;
 	struct gpio_desc *reset_gpio;
 	const struct st_chip_info *chip_info;
+	u16 max_x;
+	u16 max_y;
 	int read_buf_len;
 	u8 *read_buf;
 };
@@ -117,6 +119,36 @@  static int st1232_ts_parse_and_report(struct st1232_ts_data *ts)
 	return n_contacts;
 }
 
+static int st1232_ts_read_resolution(struct st1232_ts_data *ts)
+{
+	struct i2c_client *client = ts->client;
+	u8 start_reg = ST1232_RESOLUTION_REG;
+	u8 buf[3];
+	struct i2c_msg msg[] = {
+		{
+			.addr	= client->addr,
+			.len	= sizeof(start_reg),
+			.buf	= &start_reg,
+		},
+		{
+			.addr	= client->addr,
+			.flags	= I2C_M_RD,
+			.len	= sizeof(buf),
+			.buf	= buf,
+		},
+	};
+	int ret;
+
+	ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
+	if (ret != ARRAY_SIZE(msg))
+		return ret < 0 ? ret : -EIO;
+
+	ts->max_x = (((buf[0] & 0xf0) << 4) | buf[1]) - 1;
+	ts->max_y = (((buf[0] & 0x0f) << 8) | buf[2]) - 1;
+
+	return 0;
+}
+
 static irqreturn_t st1232_ts_irq_handler(int irq, void *dev_id)
 {
 	struct st1232_ts_data *ts = dev_id;
@@ -146,8 +178,10 @@  static irqreturn_t st1232_ts_irq_handler(int irq, void *dev_id)
 
 static void st1232_ts_power(struct st1232_ts_data *ts, bool poweron)
 {
-	if (ts->reset_gpio)
+	if (ts->reset_gpio) {
 		gpiod_set_value_cansleep(ts->reset_gpio, !poweron);
+		msleep(100);
+	}
 }
 
 static void st1232_ts_power_off(void *data)
@@ -157,8 +191,6 @@  static void st1232_ts_power_off(void *data)
 
 static const struct st_chip_info st1232_chip_info = {
 	.have_z		= true,
-	.max_x		= 0x31f, /* 800 - 1 */
-	.max_y		= 0x1df, /* 480 -1 */
 	.max_area	= 0xff,
 	.max_fingers	= 2,
 	.start_reg	= 0x12,
@@ -166,8 +198,6 @@  static const struct st_chip_info st1232_chip_info = {
 
 static const struct st_chip_info st1633_chip_info = {
 	.have_z		= false,
-	.max_x		= 0x13f, /* 320 - 1 */
-	.max_y		= 0x1df, /* 480 -1 */
 	.max_area	= 0x00,
 	.max_fingers	= 5,
 	.start_reg	= 0x12,
@@ -236,6 +266,13 @@  static int st1232_ts_probe(struct i2c_client *client,
 		return error;
 	}
 
+	error = st1232_ts_read_resolution(ts);
+	if (error) {
+		dev_err(&client->dev,
+			"Failed to read touch panel resolution: %d\n", error);
+		return error;
+	}
+
 	input_dev->name = "st1232-touchscreen";
 	input_dev->id.bustype = BUS_I2C;
 
@@ -244,9 +281,9 @@  static int st1232_ts_probe(struct i2c_client *client,
 				     ts->chip_info->max_area, 0, 0);
 
 	input_set_abs_params(input_dev, ABS_MT_POSITION_X,
-			     0, ts->chip_info->max_x, 0, 0);
+			     0, ts->max_x, 0, 0);
 	input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
-			     0, ts->chip_info->max_y, 0, 0);
+			     0, ts->max_y, 0, 0);
 
 	touchscreen_parse_properties(input_dev, true, &ts->prop);