lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Message-Id: <20200615132533.3852637-1-john@metanate.com>
Date:   Mon, 15 Jun 2020 14:25:32 +0100
From:   John Keeping <john@...anate.com>
To:     Dmitry Torokhov <dmitry.torokhov@...il.com>
Cc:     John Keeping <john@...anate.com>,
        Martin Kepplinger <martink@...teo.de>,
        Dixit Parmar <dixitparmar19@...il.com>,
        linux-input@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: [PATCH] Input: st1232 - read resolution from touch panel

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@...anate.com>
---
 drivers/input/touchscreen/st1232.c | 55 +++++++++++++++++++++++++-----
 1 file changed, 46 insertions(+), 9 deletions(-)

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);
 
-- 
2.27.0

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ