Browse Source

touch: goodix: enable TUI using QTS on kalama

Add changes to enable secure touch on goodix through
QTS framework.

Change-Id: I403bd9bc296b40ad97f6a0d066958d48b53d701e
Signed-off-by: Raviteja Tamatam <[email protected]>
Raviteja Tamatam 3 years ago
parent
commit
0e0d02e94c

+ 4 - 1
Kbuild

@@ -88,6 +88,8 @@ endif
 
 ifeq ($(CONFIG_TOUCHSCREEN_GOODIX_BRL), y)
 	LINUX_INC += -include $(TOUCH_ROOT)/goodix_berlin_driver/goodix_ts_core.h
+	LINUX_INC += -include $(TOUCH_ROOT)/qts/qts_core.h
+	LINUX_INC += -include $(TOUCH_ROOT)/qts/qts_core_common.h
 
 	goodix_ts-y := \
 		 ./goodix_berlin_driver/goodix_ts_core.o \
@@ -99,7 +101,8 @@ ifeq ($(CONFIG_TOUCHSCREEN_GOODIX_BRL), y)
 		 ./goodix_berlin_driver/goodix_ts_gesture.o \
 		 ./goodix_berlin_driver/goodix_ts_inspect.o \
 		 ./goodix_berlin_driver/goodix_brl_spi.o \
-		 ./goodix_berlin_driver/goodix_brl_i2c.o
+		 ./goodix_berlin_driver/goodix_brl_i2c.o \
+		 ./qts/qts_core.o
 
 	obj-$(CONFIG_MSM_TOUCH) += goodix_ts.o
 endif

+ 3 - 0
goodix_berlin_driver/goodix_brl_i2c.c

@@ -167,9 +167,12 @@ static int goodix_i2c_probe(struct i2c_client *client,
 	int ret = 0;
 
 	ts_info("goodix i2c probe in");
+
+#ifndef CONFIG_ARCH_QTI_VM
 	ret = i2c_check_functionality(client->adapter, I2C_FUNC_I2C);
 	if (!ret)
 		return -EIO;
+#endif
 
 	/* get ic type */
 	ret = goodix_get_ic_type(client->dev.of_node);

+ 211 - 7
goodix_berlin_driver/goodix_ts_core.c

@@ -35,6 +35,7 @@
 static struct drm_panel *active_panel;
 static void goodix_panel_notifier_callback(enum panel_event_notifier_tag tag,
 		 struct panel_event_notification *event, void *client_data);
+static irqreturn_t  goodix_irq_handler(int irq, void *data);
 
 static void goodix_register_for_panel_events(struct device_node *dp,
 					struct goodix_ts_core *cd)
@@ -1023,6 +1024,7 @@ static int goodix_parse_dt(struct device_node *node,
 		board_data->iovdd_gpio = r;
 	}
 
+#ifndef CONFIG_ARCH_QTI_VM
 	r = of_get_named_gpio(node, "goodix,reset-gpio", 0);
 	if (r < 0) {
 		ts_err("invalid reset-gpio in dt: %d", r);
@@ -1045,6 +1047,7 @@ static int goodix_parse_dt(struct device_node *node,
 		ts_err("invalid irq-flags");
 		return -EINVAL;
 	}
+#endif
 
 	memset(board_data->avdd_name, 0, sizeof(board_data->avdd_name));
 	r = of_property_read_string(node, "goodix,avdd-name", &name_tmp);
@@ -1294,7 +1297,7 @@ static int goodix_ts_irq_setup(struct goodix_ts_core *core_data)
 	ts_info("IRQ:%u,flags:%d", core_data->irq, (int)ts_bdata->irq_flags);
 	ret = devm_request_threaded_irq(&core_data->pdev->dev,
 					core_data->irq, NULL,
-					goodix_ts_threadirq_func,
+					goodix_irq_handler,
 					ts_bdata->irq_flags | IRQF_ONESHOT,
 					GOODIX_CORE_DRIVER_NAME,
 					core_data);
@@ -2012,6 +2015,9 @@ int goodix_ts_stage2_init(struct goodix_ts_core *cd)
 			goto err_finger;
 		}
 	}
+#ifdef CONFIG_ARCH_QTI_VM
+		goto skip_goodix_ts_irq_setup;
+#endif
 	/* request irq line */
 	ret = goodix_ts_irq_setup(cd);
 	if (ret < 0) {
@@ -2028,6 +2034,10 @@ int goodix_ts_stage2_init(struct goodix_ts_core *cd)
 	cd->fb_notifier.notifier_call = goodix_ts_fb_notifier_callback;
 	if (fb_register_client(&cd->fb_notifier))
 		ts_err("Failed to register fb notifier client:%d", ret);
+#endif
+
+#ifdef CONFIG_ARCH_QTI_VM
+skip_goodix_ts_irq_setup:
 #endif
 	/* create sysfs files */
 	goodix_ts_sysfs_init(cd);
@@ -2093,6 +2103,10 @@ static int goodix_later_init_thread(void *data)
 	struct goodix_ts_core *cd = data;
 	struct goodix_ts_hw_ops *hw_ops = cd->hw_ops;
 
+#ifdef CONFIG_ARCH_QTI_VM
+	goto skip_to_stage2_init;
+#endif
+
 	/* step 1: read version */
 	ret = cd->hw_ops->read_version(cd, &cd->fw_version);
 	if (ret < 0) {
@@ -2142,7 +2156,9 @@ upgrade:
 	 * if not we will send config with interactive mode
 	 */
 	goodix_send_ic_config(cd, CONFIG_TYPE_NORMAL);
-
+#ifdef CONFIG_ARCH_QTI_VM
+skip_to_stage2_init:
+#endif
 	/* init other resources */
 	ret = goodix_ts_stage2_init(cd);
 	if (ret) {
@@ -2250,6 +2266,165 @@ out:
 }
 
 #endif
+
+static int goodix_ts_suspend_helper(void *data)
+{
+	struct goodix_ts_core *core_data = data;
+
+	return goodix_ts_suspend(core_data);
+}
+
+static int goodix_ts_resume_helper(void *data)
+{
+	struct goodix_ts_core *core_data = data;
+
+	return goodix_ts_resume(core_data);
+}
+
+static int goodix_ts_enable_touch_irq(void *data, bool enable)
+{
+	struct goodix_ts_core *core_data = data;
+	struct goodix_ts_hw_ops *hw_ops = core_data->hw_ops;
+
+	hw_ops->irq_enable(core_data, enable);
+	return 0;
+}
+
+static int goodix_ts_pre_la_tui_enable(void *data)
+{
+	struct goodix_ts_core *core_data = data;
+	struct goodix_ts_esd *ts_esd = &core_data->ts_esd;
+
+	mutex_lock(&core_data->tui_transition_lock);
+	atomic_set(&ts_esd->esd_on, 0);
+
+	return 0;
+}
+
+static int goodix_ts_post_la_tui_enable(void *data)
+{
+	struct goodix_ts_core *core_data = data;
+
+	goodix_ts_release_connects(core_data);
+	mutex_unlock(&core_data->tui_transition_lock);
+	return 0;
+}
+
+static int goodix_ts_post_la_tui_disable(void *data)
+{
+	struct goodix_ts_core *core_data = data;
+	struct goodix_ts_esd *ts_esd = &core_data->ts_esd;
+
+	atomic_set(&ts_esd->esd_on, 1);
+	return 0;
+}
+
+static int goodix_ts_post_le_tui_enable(void *data)
+{
+	int ret;
+	struct goodix_ts_core *cd = data;
+	struct goodix_ts_hw_ops *hw_ops = cd->hw_ops;
+
+	ret = hw_ops->read_version(cd, &cd->fw_version);
+	if (ret) {
+		ts_err("invalid fw version, abort");
+		return -EINVAL;
+	}
+	ret = hw_ops->get_ic_info(cd, &cd->ic_info);
+	if (ret) {
+		ts_err("invalid ic info, abort");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int goodix_ts_post_le_tui_disable(void *data)
+{
+	struct goodix_ts_core *core_data = data;
+
+	goodix_ts_release_connects(core_data);
+	return 0;
+}
+
+static int goodix_ts_get_irq_num(void *data)
+{
+	struct goodix_ts_core *core_data = data;
+
+	return core_data->irq;
+}
+
+static irqreturn_t  goodix_irq_handler(int irq, void *data)
+{
+	struct goodix_ts_core *core_data = data;
+
+	if (!mutex_trylock(&core_data->tui_transition_lock))
+		return IRQ_HANDLED;
+
+	goodix_ts_threadirq_func(irq, data);
+	mutex_unlock(&core_data->tui_transition_lock);
+
+	return IRQ_HANDLED;
+}
+
+static void goodix_ts_fill_qts_vendor_data(struct qts_vendor_data *qts_vendor_data,
+		 struct goodix_ts_core *core_data)
+{
+	struct goodix_bus_interface *bus_interface;
+	struct device_node *node;
+	const char *touch_type;
+	int rc = 0;
+
+	bus_interface = core_data->bus;
+	node = bus_interface->dev->of_node;
+
+	rc = of_property_read_string(node, "goodix,touch-type", &touch_type);
+	if (rc) {
+		ts_err("No touch type\n");
+		return;
+	}
+
+	if (!strcmp(touch_type, "primary"))
+		qts_vendor_data->client_type = QTS_CLIENT_PRIMARY_TOUCH;
+	else
+		qts_vendor_data->client_type = QTS_CLIENT_SECONDARY_TOUCH;
+
+	switch (bus_interface->bus_type) {
+	case GOODIX_BUS_TYPE_I2C:
+		qts_vendor_data->client = to_i2c_client(bus_interface->dev);
+		qts_vendor_data->spi = NULL;
+		qts_vendor_data->bus_type = QTS_BUS_TYPE_I2C;
+		break;
+
+	case GOODIX_BUS_TYPE_SPI:
+		qts_vendor_data->client = NULL;
+		qts_vendor_data->spi = to_spi_device(bus_interface->dev);
+		qts_vendor_data->bus_type = QTS_BUS_TYPE_SPI;
+		break;
+
+	default:
+		ts_err("Invalid bus type :%d\n",
+				bus_interface->bus_type);
+		break;
+	}
+
+	qts_vendor_data->vendor_data = core_data;
+	qts_vendor_data->schedule_suspend = false;
+	qts_vendor_data->schedule_resume = false;
+	qts_vendor_data->qts_vendor_ops.suspend = goodix_ts_suspend_helper;
+	qts_vendor_data->qts_vendor_ops.resume = goodix_ts_resume_helper;
+	qts_vendor_data->qts_vendor_ops.enable_touch_irq = goodix_ts_enable_touch_irq;
+	qts_vendor_data->qts_vendor_ops.get_irq_num = goodix_ts_get_irq_num;
+	qts_vendor_data->qts_vendor_ops.pre_la_tui_enable = goodix_ts_pre_la_tui_enable;
+	qts_vendor_data->qts_vendor_ops.post_la_tui_enable = goodix_ts_post_la_tui_enable;
+	qts_vendor_data->qts_vendor_ops.pre_la_tui_disable = NULL;
+	qts_vendor_data->qts_vendor_ops.post_la_tui_disable = goodix_ts_post_la_tui_disable;
+	qts_vendor_data->qts_vendor_ops.pre_le_tui_enable = NULL;
+	qts_vendor_data->qts_vendor_ops.post_le_tui_enable = goodix_ts_post_le_tui_enable;
+	qts_vendor_data->qts_vendor_ops.pre_le_tui_disable = NULL;
+	qts_vendor_data->qts_vendor_ops.post_le_tui_disable = goodix_ts_post_le_tui_disable;
+	qts_vendor_data->qts_vendor_ops.irq_handler = goodix_irq_handler;
+}
+
 /**
  * goodix_ts_probe - called by kernel when Goodix touch
  *  platform driver is added.
@@ -2260,6 +2435,8 @@ static int goodix_ts_probe(struct platform_device *pdev)
 	struct goodix_bus_interface *bus_interface;
 	int ret;
 	struct device_node *node;
+	bool qts_en = false;
+	struct qts_vendor_data qts_vendor_data;
 
 	ts_info("goodix_ts_probe IN");
 
@@ -2293,12 +2470,27 @@ static int goodix_ts_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	}
 
+	core_data->bus = bus_interface;
+	qts_en = of_property_read_bool(node, "goodix,qts_en");
+	if (qts_en) {
+		mutex_init(&core_data->tui_transition_lock);
+		goodix_ts_fill_qts_vendor_data(&qts_vendor_data, core_data);
+
+		ret = qts_client_register(qts_vendor_data);
+		if (ret) {
+			pr_err("qts client register failed, rc %d\n", ret);
+			goto err_out;
+		}
+		core_data->qts_en = qts_en;
+	}
+
 	if (IS_ENABLED(CONFIG_OF) && bus_interface->dev->of_node) {
 		/* parse devicetree property */
 		ret = goodix_parse_dt(node, &core_data->board_data);
 		if (ret) {
 			ts_err("failed parse device info form dts, %d", ret);
-			return -EINVAL;
+			ret = -EINVAL;
+			goto err_out;
 		}
 #if defined(CONFIG_DRM)
 		of_property_read_string(node, "qcom,touch-environment",
@@ -2306,22 +2498,25 @@ static int goodix_ts_probe(struct platform_device *pdev)
 #endif
 	} else {
 		ts_err("no valid device tree node found");
-		return -ENODEV;
+		ret = -ENODEV;
+		goto err_out;
 	}
 
 	core_data->hw_ops = goodix_get_hw_ops();
 	if (!core_data->hw_ops) {
 		ts_err("hw ops is NULL");
-		core_module_prob_sate = CORE_MODULE_PROB_FAILED;
-		return -EINVAL;
+		ret = -EINVAL;
+		goto err_out;
 	}
 	goodix_core_module_init();
 	/* touch core layer is a platform driver */
 	core_data->pdev = pdev;
-	core_data->bus = bus_interface;
 	platform_set_drvdata(pdev, core_data);
 
 	/* get GPIO resource */
+#ifdef CONFIG_ARCH_QTI_VM
+	goto skip_to_power_gpio_setup;
+#endif
 	ret = goodix_ts_gpio_setup(core_data);
 	if (ret) {
 		ts_err("failed init gpio");
@@ -2340,6 +2535,10 @@ static int goodix_ts_probe(struct platform_device *pdev)
 		goto err_out;
 	}
 
+#ifdef CONFIG_ARCH_QTI_VM
+skip_to_power_gpio_setup:
+#endif
+
 	/* generic notifier callback */
 	core_data->ts_notifier.notifier_call = goodix_generic_noti_callback;
 	goodix_ts_register_notifier(&core_data->ts_notifier);
@@ -2358,6 +2557,7 @@ static int goodix_ts_probe(struct platform_device *pdev)
 	return 0;
 
 err_out:
+	devm_kfree(&pdev->dev, core_data);
 	core_data->init_stage = CORE_INIT_FAIL;
 	core_module_prob_sate = CORE_MODULE_PROB_FAILED;
 	ts_err("goodix_ts_core failed, ret:%d", ret);
@@ -2453,7 +2653,11 @@ static void __exit goodix_ts_core_exit(void)
 	goodix_i2c_bus_exit();
 }
 
+#ifdef CONFIG_ARCH_QTI_VM
+module_init(goodix_ts_core_init);
+#else
 late_initcall(goodix_ts_core_init);
+#endif
 module_exit(goodix_ts_core_exit);
 
 MODULE_DESCRIPTION("Goodix Touchscreen Core Module");

+ 5 - 0
goodix_berlin_driver/goodix_ts_core.h

@@ -39,6 +39,9 @@
 #include <linux/notifier.h>
 #include <linux/fb.h>
 #endif
+#include <linux/i2c.h>
+#include <linux/spi/spi.h>
+#include "../qts/qts_core_common.h"
 
 #define GOODIX_CORE_DRIVER_NAME			"goodix_ts"
 #define GOODIX_PEN_DRIVER_NAME			"goodix_ts,pen"
@@ -524,6 +527,8 @@ struct goodix_ts_core {
 	atomic_t delayed_vm_probe_pending;
 	atomic_t trusted_touch_mode;
 #endif
+	bool qts_en;
+	struct mutex tui_transition_lock;
 };
 
 /* external module structures */

+ 2 - 1
nt36xxx/nt36xxx_mp_ctrlram.c

@@ -72,6 +72,7 @@ static int32_t *RawData_FW_CC = NULL;
 static struct proc_dir_entry *NVT_proc_selftest_entry = NULL;
 static int8_t nvt_mp_test_result_printed = 0;
 static uint8_t fw_ver = 0;
+unsigned char mpcriteria[PAGE_SIZE]; //novatek-mp-criteria-default
 
 extern void nvt_change_mode(uint8_t mode);
 extern uint8_t nvt_get_fw_pipe(void);
@@ -1054,8 +1055,8 @@ return:
 static int32_t nvt_selftest_open(struct inode *inode, struct file *file)
 {
 	struct device_node *np = ts->client->dev.of_node;
-	unsigned char mpcriteria[PAGE_SIZE] = {0};	//novatek-mp-criteria-default
 
+	memset(mpcriteria, 0, PAGE_SIZE * sizeof(mpcriteria[0]));
 	TestResult_Short = 0;
 	TestResult_Open = 0;
 	TestResult_FW_Rawdata = 0;