alarm-tegra-x1 / reference/switchroot-mainline/0011-v0-stmfts-switch-support.patch

raw file 9352 bytes
From dc3ec8dee0a8a3ced5ea99aad092f1f927acd601 Mon Sep 17 00:00:00 2001
From: SwtcR <[email protected]>
Date: Sun, 11 Feb 2018 09:10:38 +0900
Subject: [PATCH 059/124] stmfts: support polled mode when there is no IRQ

---
 drivers/input/touchscreen/stmfts.c | 59 +++++++++++++++++++++++-------
 1 file changed, 46 insertions(+), 13 deletions(-)

diff --git a/drivers/input/touchscreen/stmfts.c b/drivers/input/touchscreen/stmfts.c
index 704e99046916..4cba504f046e 100644
--- a/drivers/input/touchscreen/stmfts.c
+++ b/drivers/input/touchscreen/stmfts.c
@@ -14,6 +14,7 @@
 #include <linux/module.h>
 #include <linux/pm_runtime.h>
 #include <linux/regulator/consumer.h>
+#include <linux/kthread.h>
 
 /* I2C commands */
 #define STMFTS_READ_INFO			0x80
@@ -104,6 +105,8 @@ struct stmfts_data {
 	bool led_status;
 	bool hover_enabled;
 	bool running;
+
+	struct task_struct *poll_thread;
 };
 
 static void stmfts_brightness_set(struct led_classdev *led_cdev,
@@ -313,6 +316,18 @@ static irqreturn_t stmfts_irq_handler(int irq, void *dev)
 	return IRQ_HANDLED;
 }
 
+static int stmfts_poll_thread(void *data)
+{
+	printk("poll_thread starting\n");
+	while (!kthread_should_stop()) {
+		stmfts_irq_handler(0, data);
+		msleep(2);
+	}
+	printk("poll_thread exiting\n");
+	return 0;
+}
+
+
 static int stmfts_command(struct stmfts_data *sdata, const u8 cmd)
 {
 	int err;
@@ -546,18 +561,26 @@ static int stmfts_power_on(struct stmfts_data *sdata)
 	sdata->fw_ver = be16_to_cpup((__be16 *)&reg[2]);
 	sdata->config_id = reg[4];
 	sdata->config_ver = reg[5];
-
-	enable_irq(sdata->client->irq);
+	
+	if (sdata->client->irq)
+		enable_irq(sdata->client->irq);
 
 	msleep(50);
 
+	if (!sdata->client->irq) {
+		sdata->poll_thread = kthread_run(stmfts_poll_thread, sdata, "stmfts_poll");
+		if (IS_ERR(sdata->poll_thread))
+			return -EIO;
+	}
+
 	err = stmfts_command(sdata, STMFTS_SYSTEM_RESET);
 	if (err)
-		return err;
+		goto stop_thread;
 
 	err = stmfts_command(sdata, STMFTS_SLEEP_OUT);
 	if (err)
-		return err;
+		dev_warn(&sdata->client->dev,
+			 "failed to perform sleep_out: %d\n", err);
 
 	/* optional tuning */
 	err = stmfts_command(sdata, STMFTS_MS_CX_TUNING);
@@ -573,7 +596,7 @@ static int stmfts_power_on(struct stmfts_data *sdata)
 
 	err = stmfts_command(sdata, STMFTS_FULL_FORCE_CALIBRATION);
 	if (err)
-		return err;
+		goto stop_thread;
 
 	/*
 	 * At this point no one is using the touchscreen
@@ -582,13 +605,21 @@ static int stmfts_power_on(struct stmfts_data *sdata)
 	(void) i2c_smbus_write_byte(sdata->client, STMFTS_SLEEP_IN);
 
 	return 0;
+
+stop_thread:
+	if (!sdata->client->irq)
+		kthread_stop(sdata->poll_thread);
+	return err;
 }
 
 static void stmfts_power_off(void *data)
 {
 	struct stmfts_data *sdata = data;
 
-	disable_irq(sdata->client->irq);
+	if (!sdata->client->irq)
+		kthread_stop(sdata->poll_thread);
+	else
+		disable_irq(sdata->client->irq);
 	regulator_bulk_disable(ARRAY_SIZE(sdata->regulators),
 						sdata->regulators);
 }
@@ -689,13 +720,15 @@ static int stmfts_probe(struct i2c_client *client,
 	 * interrupts. To be on the safe side it's better to not enable
 	 * the interrupts during their request.
 	 */
-	irq_set_status_flags(client->irq, IRQ_NOAUTOEN);
-	err = devm_request_threaded_irq(&client->dev, client->irq,
-					NULL, stmfts_irq_handler,
-					IRQF_ONESHOT,
-					"stmfts_irq", sdata);
-	if (err)
-		return err;
+	if (client->irq) {
+		irq_set_status_flags(client->irq, IRQ_NOAUTOEN);
+		err = devm_request_threaded_irq(&client->dev, client->irq,
+						NULL, stmfts_irq_handler,
+						IRQF_ONESHOT,
+						"stmfts_irq", sdata);
+		if (err)
+			return err;
+	}
 
 	dev_dbg(&client->dev, "initializing ST-Microelectronics FTS...\n");
 
-- 
2.20.1

From 7690882eba261d8bceb176b5a2109db2bc43c278 Mon Sep 17 00:00:00 2001
From: SwtcR <[email protected]>
Date: Mon, 12 Feb 2018 19:11:58 +0900
Subject: [PATCH 060/124] stmfts: hack to support Switch data format

---
 drivers/input/touchscreen/stmfts.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/input/touchscreen/stmfts.c b/drivers/input/touchscreen/stmfts.c
index 4cba504f046e..003aa7befe62 100644
--- a/drivers/input/touchscreen/stmfts.c
+++ b/drivers/input/touchscreen/stmfts.c
@@ -172,6 +172,7 @@ static int stmfts_read_events(struct stmfts_data *sdata)
 static void stmfts_report_contact_event(struct stmfts_data *sdata,
 					const u8 event[])
 {
+#if 0
 	u8 slot_id = (event[0] & STMFTS_MASK_TOUCH_ID) >> 4;
 	u16 x = event[1] | ((event[2] & STMFTS_MASK_X_MSB) << 8);
 	u16 y = (event[2] >> 4) | (event[3] << 4);
@@ -179,7 +180,17 @@ static void stmfts_report_contact_event(struct stmfts_data *sdata,
 	u8 min = event[5];
 	u8 orientation = event[6];
 	u8 area = event[7];
+#else
+	u8 slot_id = (event[0] & STMFTS_MASK_TOUCH_ID) >> 4;
+	u16 x = (event[1] << 4) | ((event[3] & 0xf0) >> 4);
+	u16 y = (event[2] << 4) | (event[3] & 0x0f);
 
+	u8 maj = event[4] | (event[5] << 8);
+	u8 min = maj;
+	// these two are not quite right but meh
+	u8 orientation = event[6];
+	u8 area = event[7];
+#endif
 	input_mt_slot(sdata->input, slot_id);
 
 	input_mt_report_slot_state(sdata->input, MT_TOOL_FINGER, true);
-- 
2.20.1

From 107b486493d8da5ea4c2aeb182bf80cc6fc38fea Mon Sep 17 00:00:00 2001
From: SwtcR <[email protected]>
Date: Thu, 22 Feb 2018 01:40:29 +0900
Subject: [PATCH 061/124] stmfts: support configurable IRQ enable register

---
 drivers/input/touchscreen/stmfts.c | 66 ++++++++++++++++++++++++++----
 1 file changed, 59 insertions(+), 7 deletions(-)

diff --git a/drivers/input/touchscreen/stmfts.c b/drivers/input/touchscreen/stmfts.c
index 003aa7befe62..797c2048a293 100644
--- a/drivers/input/touchscreen/stmfts.c
+++ b/drivers/input/touchscreen/stmfts.c
@@ -35,6 +35,7 @@
 #define STMFTS_FULL_FORCE_CALIBRATION		0xa2
 #define STMFTS_MS_CX_TUNING			0xa3
 #define STMFTS_SS_CX_TUNING			0xa4
+#define STMFTS_WRITE_REGISTER			0xb6
 
 /* events */
 #define STMFTS_EV_NO_EVENT			0x00
@@ -105,6 +106,8 @@ struct stmfts_data {
 	bool led_status;
 	bool hover_enabled;
 	bool running;
+	int irq_enable_reg;
+	u8 irq_enable_data;
 
 	struct task_struct *poll_thread;
 };
@@ -329,12 +332,10 @@ static irqreturn_t stmfts_irq_handler(int irq, void *dev)
 
 static int stmfts_poll_thread(void *data)
 {
-	printk("poll_thread starting\n");
 	while (!kthread_should_stop()) {
 		stmfts_irq_handler(0, data);
 		msleep(2);
 	}
-	printk("poll_thread exiting\n");
 	return 0;
 }
 
@@ -356,6 +357,18 @@ static int stmfts_command(struct stmfts_data *sdata, const u8 cmd)
 	return 0;
 }
 
+static int stmfts_write_register(struct stmfts_data *sdata, const u16 reg, const u8 value)
+{
+	u8 buf[3];
+
+	buf[0] = reg >> 8;
+	buf[1] = reg & 0xff;
+	buf[2] = value;
+
+	return i2c_smbus_write_i2c_block_data(sdata->client,
+					      STMFTS_WRITE_REGISTER, 3, buf);
+}
+
 static int stmfts_input_open(struct input_dev *dev)
 {
 	struct stmfts_data *sdata = input_get_drvdata(dev);
@@ -584,9 +597,33 @@ static int stmfts_power_on(struct stmfts_data *sdata)
 			return -EIO;
 	}
 
-	err = stmfts_command(sdata, STMFTS_SYSTEM_RESET);
+	/*
+	 * IRQs may be disabled on startup, so we need to reset the chip, then
+	 * immediately issue the command to enable IRQs. This will trigger
+	 * the completion for the reset command's queued status message.
+	 */
+	reinit_completion(&sdata->cmd_done);
+
+	err = i2c_smbus_write_byte(sdata->client, STMFTS_SYSTEM_RESET);
 	if (err)
-		goto stop_thread;
+		goto cleanup_irq;
+
+	msleep(10);
+
+	if (sdata->client->irq && sdata->irq_enable_reg != -1) {
+		err = stmfts_write_register(sdata, sdata->irq_enable_reg,
+					    sdata->irq_enable_data);
+		if (err)
+			goto cleanup_irq;
+	}
+
+	if (!wait_for_completion_timeout(&sdata->cmd_done,
+					 msecs_to_jiffies(1000))) {
+		err = -ETIMEDOUT;
+		dev_err(&sdata->client->dev,
+			 "reset did not complete: %d\n", err);
+		goto cleanup_irq;
+	}
 
 	err = stmfts_command(sdata, STMFTS_SLEEP_OUT);
 	if (err)
@@ -606,8 +643,11 @@ static int stmfts_power_on(struct stmfts_data *sdata)
 			 "failed to perform self auto tune: %d\n", err);
 
 	err = stmfts_command(sdata, STMFTS_FULL_FORCE_CALIBRATION);
-	if (err)
-		goto stop_thread;
+	if (err) {
+		dev_err(&sdata->client->dev,
+			 "failed to perform calibration: %d\n", err);
+		goto cleanup_irq;
+	}
 
 	/*
 	 * At this point no one is using the touchscreen
@@ -617,9 +657,11 @@ static int stmfts_power_on(struct stmfts_data *sdata)
 
 	return 0;
 
-stop_thread:
+cleanup_irq:
 	if (!sdata->client->irq)
 		kthread_stop(sdata->poll_thread);
+	else
+		disable_irq(sdata->client->irq);
 	return err;
 }
 
@@ -667,6 +709,7 @@ static int stmfts_probe(struct i2c_client *client,
 {
 	int err;
 	struct stmfts_data *sdata;
+	u32 prop[2];
 
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C |
 						I2C_FUNC_SMBUS_BYTE_DATA |
@@ -712,6 +755,15 @@ static int stmfts_probe(struct i2c_client *client,
 
 	sdata->use_key = device_property_read_bool(&client->dev,
 						   "touch-key-connected");
+	
+	if (!device_property_read_u32_array(&client->dev,
+		"interrupt-enable-reg", prop, 2)) {
+		sdata->irq_enable_reg = prop[0] & 0xffff;
+		sdata->irq_enable_data = prop[1] & 0xff;
+	} else {
+		sdata->irq_enable_reg = -1;
+	}
+	
 	if (sdata->use_key) {
 		input_set_capability(sdata->input, EV_KEY, KEY_MENU);
 		input_set_capability(sdata->input, EV_KEY, KEY_BACK);
-- 
2.20.1