Linux Input/HID development
 help / color / mirror / Atom feed
* [PATCH 0/5] Input: s6sy761 - add support for ST FTS1BA90A
@ 2026-11-08  8:33 Nizat Mikayilli via B4 Relay
  2026-11-08  8:33 ` [PATCH 1/5] Input: s6sy761 - apply the touchscreen inversion and swap properties Nizat Mikayilli via B4 Relay
                   ` (4 more replies)
  0 siblings, 5 replies; 9+ messages in thread
From: Nizat Mikayilli via B4 Relay @ 2026-11-08  8:33 UTC (permalink / raw)
  To: Dmitry Torokhov, Henrik Rydberg, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Andi Shyti
  Cc: linux-input, linux-kernel, devicetree, David Heidelberg,
	Nizat Mikayilli

The ST FTS1BA90A in the Samsung Galaxy Tab S9 Wi-Fi speaks the S6SY761
protocol, so this series adds it to s6sy761. Patches 1 and 2 are
standalone fixes.

The touchscreen node for the tablet will be sent with its board series:
https://lore.kernel.org/r/20261022-gts9wifi-dts-v4-0-a361428fe59c@dxdmail.cc

I tested it on the tablet. I don't have a device with an S6SY761, so
for that chip it is only compile-tested.

Signed-off-by: Nizat Mikayilli <nacht@dxdmail.cc>
---
Nizat Mikayilli (5):
      Input: s6sy761 - apply the touchscreen inversion and swap properties
      Input: s6sy761 - check the multitouch axis ranges
      dt-bindings: input: samsung,s6sy761: Add ST FTS1BA90A
      Input: s6sy761 - move chip differences into per-chip data
      Input: s6sy761 - add support for ST FTS1BA90A

 .../input/touchscreen/samsung,s6sy761.yaml         |   6 +-
 drivers/input/touchscreen/Kconfig                  |   3 +-
 drivers/input/touchscreen/s6sy761.c                | 190 ++++++++++++++++-----
 3 files changed, 156 insertions(+), 43 deletions(-)
---
base-commit: f7a8b89bc067fa1cbcd3312539bc0d61810d3280
change-id: 20261108-b4-s6sy761-fts1ba90a-2ac94a78de25

Best regards,
-- 
Nizat Mikayilli <nacht@dxdmail.cc>



^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/5] Input: s6sy761 - apply the touchscreen inversion and swap properties
  2026-11-08  8:33 [PATCH 0/5] Input: s6sy761 - add support for ST FTS1BA90A Nizat Mikayilli via B4 Relay
@ 2026-11-08  8:33 ` Nizat Mikayilli via B4 Relay
  2026-11-08  8:38   ` sashiko-bot
  2026-11-08  8:33 ` [PATCH 2/5] Input: s6sy761 - check the multitouch axis ranges Nizat Mikayilli via B4 Relay
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 9+ messages in thread
From: Nizat Mikayilli via B4 Relay @ 2026-11-08  8:33 UTC (permalink / raw)
  To: Dmitry Torokhov, Henrik Rydberg, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Andi Shyti
  Cc: linux-input, linux-kernel, devicetree, David Heidelberg,
	Nizat Mikayilli

From: Nizat Mikayilli <nacht@dxdmail.cc>

The driver parses the touchscreen properties, which swaps the axis
ranges for touchscreen-swapped-x-y, but reports the raw coordinates, so
inverted and swapped axes do not work. Report them through
touchscreen_report_pos(). No in-tree device tree sets these properties
for this driver.

Fixes: 0145a7141e59 ("Input: add support for the Samsung S6SY761 touchscreen")
Signed-off-by: Nizat Mikayilli <nacht@dxdmail.cc>
---
 drivers/input/touchscreen/s6sy761.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/input/touchscreen/s6sy761.c b/drivers/input/touchscreen/s6sy761.c
index 1afa38850f12..967fd222f0d6 100644
--- a/drivers/input/touchscreen/s6sy761.c
+++ b/drivers/input/touchscreen/s6sy761.c
@@ -153,8 +153,7 @@ static void s6sy761_report_coordinates(struct s6sy761_data *sdata,
 	input_mt_slot(sdata->input, tid);
 
 	input_mt_report_slot_state(sdata->input, MT_TOOL_FINGER, true);
-	input_report_abs(sdata->input, ABS_MT_POSITION_X, x);
-	input_report_abs(sdata->input, ABS_MT_POSITION_Y, y);
+	touchscreen_report_pos(sdata->input, &sdata->prop, x, y, true);
 	input_report_abs(sdata->input, ABS_MT_TOUCH_MAJOR, major);
 	input_report_abs(sdata->input, ABS_MT_TOUCH_MINOR, minor);
 	input_report_abs(sdata->input, ABS_MT_PRESSURE, z);

-- 
2.56.0



^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/5] Input: s6sy761 - check the multitouch axis ranges
  2026-11-08  8:33 [PATCH 0/5] Input: s6sy761 - add support for ST FTS1BA90A Nizat Mikayilli via B4 Relay
  2026-11-08  8:33 ` [PATCH 1/5] Input: s6sy761 - apply the touchscreen inversion and swap properties Nizat Mikayilli via B4 Relay
@ 2026-11-08  8:33 ` Nizat Mikayilli via B4 Relay
  2026-11-08  8:33 ` [PATCH 3/5] dt-bindings: input: samsung,s6sy761: Add ST FTS1BA90A Nizat Mikayilli via B4 Relay
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 9+ messages in thread
From: Nizat Mikayilli via B4 Relay @ 2026-11-08  8:33 UTC (permalink / raw)
  To: Dmitry Torokhov, Henrik Rydberg, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Andi Shyti
  Cc: linux-input, linux-kernel, devicetree, David Heidelberg,
	Nizat Mikayilli

From: Nizat Mikayilli <nacht@dxdmail.cc>

The axis check runs before input_mt_init_slots() copies the multitouch
ranges to ABS_X and ABS_Y, so it warns on every probe. Check
ABS_MT_POSITION_X and ABS_MT_POSITION_Y instead.

Fixes: 0145a7141e59 ("Input: add support for the Samsung S6SY761 touchscreen")
Signed-off-by: Nizat Mikayilli <nacht@dxdmail.cc>
---
 drivers/input/touchscreen/s6sy761.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/input/touchscreen/s6sy761.c b/drivers/input/touchscreen/s6sy761.c
index 967fd222f0d6..59166865d397 100644
--- a/drivers/input/touchscreen/s6sy761.c
+++ b/drivers/input/touchscreen/s6sy761.c
@@ -449,8 +449,8 @@ static int s6sy761_probe(struct i2c_client *client)
 
 	touchscreen_parse_properties(sdata->input, true, &sdata->prop);
 
-	if (!input_abs_get_max(sdata->input, ABS_X) ||
-	    !input_abs_get_max(sdata->input, ABS_Y)) {
+	if (!input_abs_get_max(sdata->input, ABS_MT_POSITION_X) ||
+	    !input_abs_get_max(sdata->input, ABS_MT_POSITION_Y)) {
 		dev_warn(&client->dev, "the axis have not been set\n");
 	}
 

-- 
2.56.0



^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 3/5] dt-bindings: input: samsung,s6sy761: Add ST FTS1BA90A
  2026-11-08  8:33 [PATCH 0/5] Input: s6sy761 - add support for ST FTS1BA90A Nizat Mikayilli via B4 Relay
  2026-11-08  8:33 ` [PATCH 1/5] Input: s6sy761 - apply the touchscreen inversion and swap properties Nizat Mikayilli via B4 Relay
  2026-11-08  8:33 ` [PATCH 2/5] Input: s6sy761 - check the multitouch axis ranges Nizat Mikayilli via B4 Relay
@ 2026-11-08  8:33 ` Nizat Mikayilli via B4 Relay
  2026-11-08  8:33 ` [PATCH 4/5] Input: s6sy761 - move chip differences into per-chip data Nizat Mikayilli via B4 Relay
  2026-11-08  8:33 ` [PATCH 5/5] Input: s6sy761 - add support for ST FTS1BA90A Nizat Mikayilli via B4 Relay
  4 siblings, 0 replies; 9+ messages in thread
From: Nizat Mikayilli via B4 Relay @ 2026-11-08  8:33 UTC (permalink / raw)
  To: Dmitry Torokhov, Henrik Rydberg, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Andi Shyti
  Cc: linux-input, linux-kernel, devicetree, David Heidelberg,
	Nizat Mikayilli

From: Nizat Mikayilli <nacht@dxdmail.cc>

The ST FTS1BA90A in the Samsung Galaxy Tab S9 Wi-Fi runs firmware that
speaks the S6SY761 protocol rather than the ones of st,stmfts and
st,stmfts5, and it has the same supplies as the S6SY761. Its event size
and some commands differ, so there is no fallback compatible.

Signed-off-by: Nizat Mikayilli <nacht@dxdmail.cc>
---
 .../devicetree/bindings/input/touchscreen/samsung,s6sy761.yaml      | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/input/touchscreen/samsung,s6sy761.yaml b/Documentation/devicetree/bindings/input/touchscreen/samsung,s6sy761.yaml
index 1ffd17af3c53..92d071852d71 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/samsung,s6sy761.yaml
+++ b/Documentation/devicetree/bindings/input/touchscreen/samsung,s6sy761.yaml
@@ -4,7 +4,7 @@
 $id: http://devicetree.org/schemas/input/touchscreen/samsung,s6sy761.yaml#
 $schema: http://devicetree.org/meta-schemas/core.yaml#
 
-title: Samsung S6SY761 touchscreen controller
+title: Samsung S6SY761 and ST FTS1BA90A touchscreen controllers
 
 maintainers:
   - Andi Shyti <andi.shyti@kernel.org>
@@ -14,7 +14,9 @@ allOf:
 
 properties:
   compatible:
-    const: samsung,s6sy761
+    enum:
+      - samsung,s6sy761
+      - st,fts1ba90a
 
   reg:
     maxItems: 1

-- 
2.56.0



^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 4/5] Input: s6sy761 - move chip differences into per-chip data
  2026-11-08  8:33 [PATCH 0/5] Input: s6sy761 - add support for ST FTS1BA90A Nizat Mikayilli via B4 Relay
                   ` (2 preceding siblings ...)
  2026-11-08  8:33 ` [PATCH 3/5] dt-bindings: input: samsung,s6sy761: Add ST FTS1BA90A Nizat Mikayilli via B4 Relay
@ 2026-11-08  8:33 ` Nizat Mikayilli via B4 Relay
  2026-11-08  8:42   ` sashiko-bot
  2026-11-08  8:33 ` [PATCH 5/5] Input: s6sy761 - add support for ST FTS1BA90A Nizat Mikayilli via B4 Relay
  4 siblings, 1 reply; 9+ messages in thread
From: Nizat Mikayilli via B4 Relay @ 2026-11-08  8:33 UTC (permalink / raw)
  To: Dmitry Torokhov, Henrik Rydberg, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Andi Shyti
  Cc: linux-input, linux-kernel, devicetree, David Heidelberg,
	Nizat Mikayilli

From: Nizat Mikayilli <nacht@dxdmail.cc>

Put what differs between controllers speaking this protocol into
per-chip data, to prepare for adding the ST FTS1BA90A.

No functional change intended.

Signed-off-by: Nizat Mikayilli <nacht@dxdmail.cc>
---
 drivers/input/touchscreen/s6sy761.c | 133 +++++++++++++++++++++++++++---------
 1 file changed, 99 insertions(+), 34 deletions(-)

diff --git a/drivers/input/touchscreen/s6sy761.c b/drivers/input/touchscreen/s6sy761.c
index 59166865d397..f000ed0d7a9a 100644
--- a/drivers/input/touchscreen/s6sy761.c
+++ b/drivers/input/touchscreen/s6sy761.c
@@ -99,6 +99,7 @@ enum s6sy761_regulators {
 };
 
 struct s6sy761_data {
+	const struct s6sy761_chip_data *chip;
 	struct i2c_client *client;
 	struct regulator_bulk_data regulators[2];
 	struct input_dev *input;
@@ -112,6 +113,19 @@ struct s6sy761_data {
 	bool powered_up;
 };
 
+struct s6sy761_chip_data {
+	int (*boot)(struct s6sy761_data *sdata);
+	int (*set_sense)(struct s6sy761_data *sdata, bool enable);
+	u16 touch_function;
+	u8 event_size;
+	u8 first_tid;
+	u8 devid_cmd;
+	u8 devid_size;
+	u8 devid_offset;
+	bool has_fw_integrity;
+	bool has_app_mode;
+};
+
 /*
  * We can't simply use i2c_smbus_read_i2c_block_data because we
  * need to read more than 255 bytes
@@ -128,8 +142,8 @@ static int s6sy761_read_events(struct s6sy761_data *sdata, u16 n_events)
 		{
 			.addr	= sdata->client->addr,
 			.flags	= I2C_M_RD,
-			.len	= (n_events * S6SY761_EVENT_SIZE),
-			.buf	= sdata->data + S6SY761_EVENT_SIZE,
+			.len	= (n_events * sdata->chip->event_size),
+			.buf	= sdata->data + sdata->chip->event_size,
 		},
 	};
 	int ret;
@@ -175,10 +189,11 @@ static void s6sy761_handle_coordinates(struct s6sy761_data *sdata, u8 *event)
 	u8 tid;
 	u8 touch_state;
 
-	if (unlikely(!(event[0] & S6SY761_MASK_TID)))
+	tid = (event[0] & S6SY761_MASK_TID) >> 2;
+	if (unlikely(tid < sdata->chip->first_tid))
 		return;
 
-	tid = ((event[0] & S6SY761_MASK_TID) >> 2) - 1;
+	tid -= sdata->chip->first_tid;
 	touch_state = (event[0] & S6SY761_MASK_TOUCH_STATE) >> 6;
 
 	switch (touch_state) {
@@ -200,7 +215,7 @@ static void s6sy761_handle_events(struct s6sy761_data *sdata, u8 n_events)
 	int i;
 
 	for (i = 0; i < n_events; i++) {
-		u8 *event = &sdata->data[i * S6SY761_EVENT_SIZE];
+		u8 *event = &sdata->data[i * sdata->chip->event_size];
 		u8 event_id = event[0] & S6SY761_MASK_EID;
 
 		if (!event[0])
@@ -229,7 +244,7 @@ static irqreturn_t s6sy761_irq_handler(int irq, void *dev)
 
 	ret = i2c_smbus_read_i2c_block_data(sdata->client,
 					    S6SY761_READ_ONE_EVENT,
-					    S6SY761_EVENT_SIZE,
+					    sdata->chip->event_size,
 					    sdata->data);
 	if (ret < 0) {
 		dev_err(&sdata->client->dev, "failed to read events\n");
@@ -256,11 +271,18 @@ static irqreturn_t s6sy761_irq_handler(int irq, void *dev)
 	return IRQ_HANDLED;
 }
 
+static int s6sy761_set_sense(struct s6sy761_data *sdata, bool enable)
+{
+	u8 cmd = enable ? S6SY761_SENSE_ON : S6SY761_SENSE_OFF;
+
+	return i2c_smbus_write_byte(sdata->client, cmd);
+}
+
 static int s6sy761_input_open(struct input_dev *dev)
 {
 	struct s6sy761_data *sdata = input_get_drvdata(dev);
 
-	return i2c_smbus_write_byte(sdata->client, S6SY761_SENSE_ON);
+	return sdata->chip->set_sense(sdata, true);
 }
 
 static void s6sy761_input_close(struct input_dev *dev)
@@ -268,7 +290,7 @@ static void s6sy761_input_close(struct input_dev *dev)
 	struct s6sy761_data *sdata = input_get_drvdata(dev);
 	int ret;
 
-	ret = i2c_smbus_write_byte(sdata->client, S6SY761_SENSE_OFF);
+	ret = sdata->chip->set_sense(sdata, false);
 	if (ret)
 		dev_err(&sdata->client->dev, "failed to turn off sensing\n");
 }
@@ -289,50 +311,68 @@ static struct attribute *s6sy761_sysfs_attrs[] = {
 };
 ATTRIBUTE_GROUPS(s6sy761_sysfs);
 
-static int s6sy761_power_on(struct s6sy761_data *sdata)
+static int s6sy761_boot_complete(struct s6sy761_data *sdata)
 {
 	u8 buffer[S6SY761_EVENT_SIZE];
 	u8 event;
 	int ret;
 
-	ret = regulator_bulk_enable(ARRAY_SIZE(sdata->regulators),
-				    sdata->regulators);
-	if (ret)
-		return ret;
-
-	msleep(140);
-
-	/* double check whether the touch is functional */
 	ret = i2c_smbus_read_i2c_block_data(sdata->client,
 					    S6SY761_READ_ONE_EVENT,
-					    S6SY761_EVENT_SIZE,
+					    sdata->chip->event_size,
 					    buffer);
 	if (ret < 0)
-		goto err_disable_regulators;
+		return ret;
 
 	event = (buffer[0] >> 2) & 0xf;
 
 	if ((event != S6SY761_EVENT_INFO &&
 	     event != S6SY761_EVENT_VENDOR_INFO) ||
-	    buffer[1] != S6SY761_INFO_BOOT_COMPLETE) {
-		ret = -ENODEV;
-		goto err_disable_regulators;
-	}
+	    buffer[1] != S6SY761_INFO_BOOT_COMPLETE)
+		return -ENODEV;
+
+	return 0;
+}
+
+static int s6sy761_boot(struct s6sy761_data *sdata)
+{
+	int ret;
+
+	msleep(140);
+
+	/* double check whether the touch is functional */
+	ret = s6sy761_boot_complete(sdata);
+	if (ret)
+		return ret;
 
 	ret = i2c_smbus_read_byte_data(sdata->client, S6SY761_BOOT_STATUS);
 	if (ret < 0)
-		goto err_disable_regulators;
+		return ret;
 
 	/* for some reasons the device might be stuck in the bootloader */
-	if (ret != S6SY761_BS_APPLICATION) {
-		ret = -ENODEV;
+	if (ret != S6SY761_BS_APPLICATION)
+		return -ENODEV;
+
+	return 0;
+}
+
+static int s6sy761_power_on(struct s6sy761_data *sdata)
+{
+	int ret;
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(sdata->regulators),
+				    sdata->regulators);
+	if (ret)
+		return ret;
+
+	ret = sdata->chip->boot(sdata);
+	if (ret)
 		goto err_disable_regulators;
-	}
 
 	/* enable touch functionality */
 	ret = i2c_smbus_write_word_data(sdata->client,
 					S6SY761_TOUCH_FUNCTION,
-					S6SY761_MASK_TOUCH);
+					sdata->chip->touch_function);
 	if (ret)
 		goto err_disable_regulators;
 
@@ -356,13 +396,13 @@ static int s6sy761_hw_init(struct s6sy761_data *sdata,
 		return ret;
 
 	ret = i2c_smbus_read_i2c_block_data(sdata->client,
-					    S6SY761_DEVICE_ID,
-					    S6SY761_DEVID_SIZE,
+					    sdata->chip->devid_cmd,
+					    sdata->chip->devid_size,
 					    buffer);
 	if (ret < 0)
 		return ret;
 
-	sdata->devid = get_unaligned_be16(buffer + 1);
+	sdata->devid = get_unaligned_be16(buffer + sdata->chip->devid_offset);
 
 	ret = i2c_smbus_read_i2c_block_data(sdata->client,
 					    S6SY761_PANEL_INFO,
@@ -377,6 +417,9 @@ static int s6sy761_hw_init(struct s6sy761_data *sdata,
 	/* if no tx channels defined, at least keep one */
 	sdata->tx_channel = max_t(u8, buffer[8], 1);
 
+	if (!sdata->chip->has_fw_integrity)
+		return 0;
+
 	ret = i2c_smbus_read_byte_data(sdata->client,
 				       S6SY761_FIRMWARE_INTEGRITY);
 	if (ret < 0)
@@ -415,6 +458,9 @@ static int s6sy761_probe(struct i2c_client *client)
 
 	i2c_set_clientdata(client, sdata);
 	sdata->client = client;
+	sdata->chip = i2c_get_match_data(client);
+	if (!sdata->chip)
+		return -EINVAL;
 
 	sdata->regulators[S6SY761_REGULATOR_VDD].supply = "vdd";
 	sdata->regulators[S6SY761_REGULATOR_AVDD].supply = "avdd";
@@ -486,6 +532,9 @@ static int s6sy761_runtime_suspend(struct device *dev)
 {
 	struct s6sy761_data *sdata = dev_get_drvdata(dev);
 
+	if (!sdata->chip->has_app_mode)
+		return 0;
+
 	return i2c_smbus_write_byte_data(sdata->client,
 				S6SY761_APPLICATION_MODE, S6SY761_APP_SLEEP);
 }
@@ -494,6 +543,9 @@ static int s6sy761_runtime_resume(struct device *dev)
 {
 	struct s6sy761_data *sdata = dev_get_drvdata(dev);
 
+	if (!sdata->chip->has_app_mode)
+		return 0;
+
 	return i2c_smbus_write_byte_data(sdata->client,
 				S6SY761_APPLICATION_MODE, S6SY761_APP_NORMAL);
 }
@@ -517,7 +569,7 @@ static int s6sy761_restore_sense(struct s6sy761_data *sdata)
 	if (!input_device_enabled(sdata->input))
 		return 0;
 
-	return i2c_smbus_write_byte(sdata->client, S6SY761_SENSE_ON);
+	return sdata->chip->set_sense(sdata, true);
 }
 
 static int s6sy761_resume(struct device *dev)
@@ -547,16 +599,29 @@ static const struct dev_pm_ops s6sy761_pm_ops = {
 	RUNTIME_PM_OPS(s6sy761_runtime_suspend, s6sy761_runtime_resume, NULL)
 };
 
+static const struct s6sy761_chip_data s6sy761_chip = {
+	.boot		= s6sy761_boot,
+	.set_sense	= s6sy761_set_sense,
+	.touch_function	= S6SY761_MASK_TOUCH,
+	.event_size	= S6SY761_EVENT_SIZE,
+	.first_tid	= 1,
+	.devid_cmd	= S6SY761_DEVICE_ID,
+	.devid_size	= S6SY761_DEVID_SIZE,
+	.devid_offset	= 1,
+	.has_fw_integrity = true,
+	.has_app_mode	= true,
+};
+
 #ifdef CONFIG_OF
 static const struct of_device_id s6sy761_of_match[] = {
-	{ .compatible = "samsung,s6sy761", },
+	{ .compatible = "samsung,s6sy761", .data = &s6sy761_chip },
 	{ },
 };
 MODULE_DEVICE_TABLE(of, s6sy761_of_match);
 #endif
 
 static const struct i2c_device_id s6sy761_id[] = {
-	{ .name = "s6sy761" },
+	{ .name = "s6sy761", .driver_data = (kernel_ulong_t)&s6sy761_chip },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, s6sy761_id);

-- 
2.56.0



^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 5/5] Input: s6sy761 - add support for ST FTS1BA90A
  2026-11-08  8:33 [PATCH 0/5] Input: s6sy761 - add support for ST FTS1BA90A Nizat Mikayilli via B4 Relay
                   ` (3 preceding siblings ...)
  2026-11-08  8:33 ` [PATCH 4/5] Input: s6sy761 - move chip differences into per-chip data Nizat Mikayilli via B4 Relay
@ 2026-11-08  8:33 ` Nizat Mikayilli via B4 Relay
  4 siblings, 0 replies; 9+ messages in thread
From: Nizat Mikayilli via B4 Relay @ 2026-11-08  8:33 UTC (permalink / raw)
  To: Dmitry Torokhov, Henrik Rydberg, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Andi Shyti
  Cc: linux-input, linux-kernel, devicetree, David Heidelberg,
	Nizat Mikayilli

From: Nizat Mikayilli <nacht@dxdmail.cc>

Add the ST FTS1BA90A, the touchscreen controller of the Samsung Galaxy
Tab S9 Wi-Fi (SM-X710). Samsung's GPL driver for the tablet shows that
its firmware speaks the S6SY761 protocol, with 16-byte events, touch IDs
from 0 and its own reset, device ID and scan commands. That driver never
sends the firmware integrity or application mode command, so neither is
used here and runtime PM does nothing. Like Samsung's driver, this
enables palm and wet detection and reports palms as fingers. Firmware
update, calibration and gestures are left out.

Signed-off-by: Nizat Mikayilli <nacht@dxdmail.cc>
---
 drivers/input/touchscreen/Kconfig   |  3 ++-
 drivers/input/touchscreen/s6sy761.c | 50 +++++++++++++++++++++++++++++++++++--
 2 files changed, 50 insertions(+), 3 deletions(-)

diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 9b9ae8ac3f7f..c24a8b13a4a4 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -531,7 +531,8 @@ config TOUCHSCREEN_S6SY761
 	tristate "Samsung S6SY761 Touchscreen driver"
 	depends on I2C
 	help
-	  Say Y if you have the Samsung S6SY761 driver
+	  Say Y if you have a Samsung S6SY761 or ST FTS1BA90A touchscreen
+	  controller.
 
 	  If unsure, say N
 
diff --git a/drivers/input/touchscreen/s6sy761.c b/drivers/input/touchscreen/s6sy761.c
index f000ed0d7a9a..5e3838a64588 100644
--- a/drivers/input/touchscreen/s6sy761.c
+++ b/drivers/input/touchscreen/s6sy761.c
@@ -10,6 +10,7 @@
 #include <linux/input/mt.h>
 #include <linux/input/touchscreen.h>
 #include <linux/interrupt.h>
+#include <linux/iopoll.h>
 #include <linux/irq.h>
 #include <linux/module.h>
 #include <linux/pm_runtime.h>
@@ -27,6 +28,8 @@
 #define S6SY761_READ_ALL_EVENT		0x61
 #define S6SY761_CLEAR_EVENT_STACK	0x62
 #define S6SY761_APPLICATION_MODE	0xe4
+#define FTS1BA90A_DEVICE_ID		0x22
+#define FTS1BA90A_SET_SCAN_MODE		0xa0
 
 /* events */
 #define S6SY761_EVENT_INFO		0x02
@@ -90,6 +93,10 @@
 #define S6SY761_PANEL_ID_SIZE		11
 #define S6SY761_TS_STATUS_SIZE		5
 #define S6SY761_MAX_FINGERS		10
+#define FTS1BA90A_EVENT_SIZE		16
+#define FTS1BA90A_DEVID_SIZE		5
+#define FTS1BA90A_SCAN_MS_SS		BIT(0)
+#define S6SY761_MAX_EVENT_SIZE		FTS1BA90A_EVENT_SIZE
 
 #define S6SY761_DEV_NAME	"s6sy761"
 
@@ -105,7 +112,7 @@ struct s6sy761_data {
 	struct input_dev *input;
 	struct touchscreen_properties prop;
 
-	u8 data[S6SY761_EVENT_SIZE * S6SY761_EVENT_COUNT];
+	u8 data[S6SY761_MAX_EVENT_SIZE * S6SY761_EVENT_COUNT];
 
 	u16 devid;
 	u8 tx_channel;
@@ -278,6 +285,15 @@ static int s6sy761_set_sense(struct s6sy761_data *sdata, bool enable)
 	return i2c_smbus_write_byte(sdata->client, cmd);
 }
 
+static int fts1ba90a_set_sense(struct s6sy761_data *sdata, bool enable)
+{
+	u8 scan_mode[] = { 0x00, enable ? FTS1BA90A_SCAN_MS_SS : 0x00 };
+
+	return i2c_smbus_write_i2c_block_data(sdata->client,
+					      FTS1BA90A_SET_SCAN_MODE,
+					      sizeof(scan_mode), scan_mode);
+}
+
 static int s6sy761_input_open(struct input_dev *dev)
 {
 	struct s6sy761_data *sdata = input_get_drvdata(dev);
@@ -313,7 +329,7 @@ ATTRIBUTE_GROUPS(s6sy761_sysfs);
 
 static int s6sy761_boot_complete(struct s6sy761_data *sdata)
 {
-	u8 buffer[S6SY761_EVENT_SIZE];
+	u8 buffer[S6SY761_MAX_EVENT_SIZE];
 	u8 event;
 	int ret;
 
@@ -356,6 +372,23 @@ static int s6sy761_boot(struct s6sy761_data *sdata)
 	return 0;
 }
 
+static int fts1ba90a_boot(struct s6sy761_data *sdata)
+{
+	static const u8 system_reset[] = { 0xfa, 0x20, 0x00, 0x00, 0x24, 0x81 };
+	int ret;
+
+	ret = i2c_master_send(sdata->client, system_reset,
+			      sizeof(system_reset));
+	if (ret != sizeof(system_reset))
+		return ret < 0 ? ret : -EIO;
+
+	usleep_range(10000, 11000);
+
+	return read_poll_timeout(s6sy761_boot_complete, ret, !ret,
+				 20 * USEC_PER_MSEC, 3 * USEC_PER_SEC, false,
+				 sdata);
+}
+
 static int s6sy761_power_on(struct s6sy761_data *sdata)
 {
 	int ret;
@@ -612,9 +645,21 @@ static const struct s6sy761_chip_data s6sy761_chip = {
 	.has_app_mode	= true,
 };
 
+static const struct s6sy761_chip_data fts1ba90a_chip = {
+	.boot		= fts1ba90a_boot,
+	.set_sense	= fts1ba90a_set_sense,
+	.touch_function	= S6SY761_MASK_TOUCH | S6SY761_MASK_PALM |
+			  S6SY761_MASK_WET,
+	.event_size	= FTS1BA90A_EVENT_SIZE,
+	.devid_cmd	= FTS1BA90A_DEVICE_ID,
+	.devid_size	= FTS1BA90A_DEVID_SIZE,
+	.devid_offset	= 2,
+};
+
 #ifdef CONFIG_OF
 static const struct of_device_id s6sy761_of_match[] = {
 	{ .compatible = "samsung,s6sy761", .data = &s6sy761_chip },
+	{ .compatible = "st,fts1ba90a", .data = &fts1ba90a_chip },
 	{ },
 };
 MODULE_DEVICE_TABLE(of, s6sy761_of_match);
@@ -622,6 +667,7 @@ MODULE_DEVICE_TABLE(of, s6sy761_of_match);
 
 static const struct i2c_device_id s6sy761_id[] = {
 	{ .name = "s6sy761", .driver_data = (kernel_ulong_t)&s6sy761_chip },
+	{ .name = "fts1ba90a", .driver_data = (kernel_ulong_t)&fts1ba90a_chip },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, s6sy761_id);

-- 
2.56.0



^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/5] Input: s6sy761 - apply the touchscreen inversion and swap properties
  2026-11-08  8:33 ` [PATCH 1/5] Input: s6sy761 - apply the touchscreen inversion and swap properties Nizat Mikayilli via B4 Relay
@ 2026-11-08  8:38   ` sashiko-bot
  2026-11-08 21:31     ` Dmitry Torokhov
  0 siblings, 1 reply; 9+ messages in thread
From: sashiko-bot @ 2026-11-08  8:38 UTC (permalink / raw)
  To: Nizat Mikayilli; +Cc: linux-input, devicetree, robh, conor+dt, dmitry.torokhov

Thank you for your contribution! Sashiko AI review found no new issues
in this patch, but noticed 1 related pre-existing issue it does not
introduce:
- [High] Input: s6sy761 - premature input_sync() in
  s6sy761_report_coordinates() [1]
--

commit a5e7ac4e0cb3d02e12af7f249f64b3074df9f280
Author: Nizat Mikayilli <nacht@dxdmail.cc>

Input: s6sy761 - apply the touchscreen inversion and swap properties

This commit replaces raw X and Y coordinate reporting with
touchscreen_report_pos() so touchscreen inversion and axis swap properties
take effect.

> diff --git a/drivers/input/touchscreen/s6sy761.c b/drivers/input/touchscreen/s6sy761.c
> index 1afa38850f12f..967fd222f0d62 100644
> --- a/drivers/input/touchscreen/s6sy761.c
> +++ b/drivers/input/touchscreen/s6sy761.c
> @@ -153,8 +153,7 @@ static void s6sy761_report_coordinates(struct s6sy761_data *sdata,
>  	input_mt_slot(sdata->input, tid);
>  
>  	input_mt_report_slot_state(sdata->input, MT_TOOL_FINGER, true);
> -	input_report_abs(sdata->input, ABS_MT_POSITION_X, x);
> -	input_report_abs(sdata->input, ABS_MT_POSITION_Y, y);
> +	touchscreen_report_pos(sdata->input, &sdata->prop, x, y, true);
>  	input_report_abs(sdata->input, ABS_MT_TOUCH_MAJOR, major);
>  	input_report_abs(sdata->input, ABS_MT_TOUCH_MINOR, minor);
>  	input_report_abs(sdata->input, ABS_MT_PRESSURE, z);

[Severity: High]
This problem wasn't introduced by this patch, but does calling
input_sync() at the end of s6sy761_report_coordinates() and
s6sy761_report_release() fragment multi-finger updates [1]?

drivers/input/touchscreen/s6sy761.c:s6sy761_report_coordinates() {
	...
	input_report_abs(sdata->input, ABS_MT_PRESSURE, z);

	input_sync(sdata->input);
}

When s6sy761_irq_handler() loops over batched events, emitting SYN_REPORT
inside each per-slot helper splits a single multi-finger hardware update
into multiple torn frames for userspace.

[1] https://sashiko.dev/#/bug/linux-c1c813ff-e5e5-43df-a3c3-af15e2a7dad5

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261108-b4-s6sy761-fts1ba90a-v1-0-999b3cfaf82d@dxdmail.cc?part=1

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 4/5] Input: s6sy761 - move chip differences into per-chip data
  2026-11-08  8:33 ` [PATCH 4/5] Input: s6sy761 - move chip differences into per-chip data Nizat Mikayilli via B4 Relay
@ 2026-11-08  8:42   ` sashiko-bot
  0 siblings, 0 replies; 9+ messages in thread
From: sashiko-bot @ 2026-11-08  8:42 UTC (permalink / raw)
  To: Nizat Mikayilli; +Cc: linux-input, devicetree, robh, conor+dt, dmitry.torokhov

Thank you for your contribution! Sashiko AI review found no new issues
in this patch, but noticed 1 related pre-existing issue it does not
introduce:
- [High] Input: s6sy761 - interrupt storm on I2C error in
  s6sy761_irq_handler() [1]
--

commit a2e70885f2393c600cd0947a2d064a0c055020a7
Author: Nizat Mikayilli <nacht@dxdmail.cc>

Input: s6sy761 - move chip differences into per-chip data

This commit moves controller-specific parameters and callbacks into a
per-chip data structure to prepare for adding support for the ST FTS1BA90A
controller.

> diff --git a/drivers/input/touchscreen/s6sy761.c b/drivers/input/touchscreen/s6sy761.c
> index 59166865d397c..f000ed0d7a9a4 100644
> --- a/drivers/input/touchscreen/s6sy761.c
> +++ b/drivers/input/touchscreen/s6sy761.c

> @@ -229,7 +244,7 @@ static irqreturn_t s6sy761_irq_handler(int irq, void *dev)
>  
>  	ret = i2c_smbus_read_i2c_block_data(sdata->client,
>  					    S6SY761_READ_ONE_EVENT,
> -					    S6SY761_EVENT_SIZE,
> +					    sdata->chip->event_size,
>  					    sdata->data);
>  	if (ret < 0) {
>  		dev_err(&sdata->client->dev, "failed to read events\n");

[Severity: High]
This problem wasn't introduced by this patch, but can returning IRQ_HANDLED
when i2c_smbus_read_i2c_block_data() or s6sy761_read_events() fails cause
an interrupt storm [1]?

The IRQ is registered with IRQF_TRIGGER_LOW.  When an I2C read fails, the
pending event is not drained from the controller, so the level-triggered
interrupt line stays asserted and immediately re-fires once unmasked, while
returning IRQ_HANDLED instead of IRQ_NONE prevents the spurious interrupt
detector from disabling the IRQ.

[1] https://sashiko.dev/#/bug/linux-d31827dd-6777-4c33-8908-c3b4fbd062c3

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261108-b4-s6sy761-fts1ba90a-v1-0-999b3cfaf82d@dxdmail.cc?part=4

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/5] Input: s6sy761 - apply the touchscreen inversion and swap properties
  2026-11-08  8:38   ` sashiko-bot
@ 2026-11-08 21:31     ` Dmitry Torokhov
  0 siblings, 0 replies; 9+ messages in thread
From: Dmitry Torokhov @ 2026-11-08 21:31 UTC (permalink / raw)
  To: sashiko-reviews; +Cc: Nizat Mikayilli, linux-input, devicetree, robh, conor+dt

On Sun, Nov 08, 2026 at 08:38:24AM +0000, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found no new issues
> in this patch, but noticed 1 related pre-existing issue it does not
> introduce:
> - [High] Input: s6sy761 - premature input_sync() in
>   s6sy761_report_coordinates() [1]
> --
> 
> commit a5e7ac4e0cb3d02e12af7f249f64b3074df9f280
> Author: Nizat Mikayilli <nacht@dxdmail.cc>
> 
> Input: s6sy761 - apply the touchscreen inversion and swap properties
> 
> This commit replaces raw X and Y coordinate reporting with
> touchscreen_report_pos() so touchscreen inversion and axis swap properties
> take effect.
> 
> > diff --git a/drivers/input/touchscreen/s6sy761.c b/drivers/input/touchscreen/s6sy761.c
> > index 1afa38850f12f..967fd222f0d62 100644
> > --- a/drivers/input/touchscreen/s6sy761.c
> > +++ b/drivers/input/touchscreen/s6sy761.c
> > @@ -153,8 +153,7 @@ static void s6sy761_report_coordinates(struct s6sy761_data *sdata,
> >  	input_mt_slot(sdata->input, tid);
> >  
> >  	input_mt_report_slot_state(sdata->input, MT_TOOL_FINGER, true);
> > -	input_report_abs(sdata->input, ABS_MT_POSITION_X, x);
> > -	input_report_abs(sdata->input, ABS_MT_POSITION_Y, y);
> > +	touchscreen_report_pos(sdata->input, &sdata->prop, x, y, true);
> >  	input_report_abs(sdata->input, ABS_MT_TOUCH_MAJOR, major);
> >  	input_report_abs(sdata->input, ABS_MT_TOUCH_MINOR, minor);
> >  	input_report_abs(sdata->input, ABS_MT_PRESSURE, z);
> 
> [Severity: High]
> This problem wasn't introduced by this patch, but does calling
> input_sync() at the end of s6sy761_report_coordinates() and
> s6sy761_report_release() fragment multi-finger updates [1]?
> 
> drivers/input/touchscreen/s6sy761.c:s6sy761_report_coordinates() {
> 	...
> 	input_report_abs(sdata->input, ABS_MT_PRESSURE, z);
> 
> 	input_sync(sdata->input);
> }
> 
> When s6sy761_irq_handler() loops over batched events, emitting SYN_REPORT
> inside each per-slot helper splits a single multi-finger hardware update
> into multiple torn frames for userspace.
> 
> [1] https://sashiko.dev/#/bug/linux-c1c813ff-e5e5-43df-a3c3-af15e2a7dad5

The driver does not use INPUT_MT_DROP_UNUSED so it is OK to emit
SYN_REPORT per contact. 

Thanks.

-- 
Dmitry

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2026-11-08 21:31 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-08  8:33 [PATCH 0/5] Input: s6sy761 - add support for ST FTS1BA90A Nizat Mikayilli via B4 Relay
2026-11-08  8:33 ` [PATCH 1/5] Input: s6sy761 - apply the touchscreen inversion and swap properties Nizat Mikayilli via B4 Relay
2026-11-08  8:38   ` sashiko-bot
2026-11-08 21:31     ` Dmitry Torokhov
2026-11-08  8:33 ` [PATCH 2/5] Input: s6sy761 - check the multitouch axis ranges Nizat Mikayilli via B4 Relay
2026-11-08  8:33 ` [PATCH 3/5] dt-bindings: input: samsung,s6sy761: Add ST FTS1BA90A Nizat Mikayilli via B4 Relay
2026-11-08  8:33 ` [PATCH 4/5] Input: s6sy761 - move chip differences into per-chip data Nizat Mikayilli via B4 Relay
2026-11-08  8:42   ` sashiko-bot
2026-11-08  8:33 ` [PATCH 5/5] Input: s6sy761 - add support for ST FTS1BA90A Nizat Mikayilli via B4 Relay

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox