diff --git a/Android.bp b/Android.bp new file mode 100644 index 0000000000..75d9b80723 --- /dev/null +++ b/Android.bp @@ -0,0 +1,7 @@ +cc_library_headers { + name: "qti_glink_touch_kernel_headers", + export_include_dirs: [ + "glink_interface_ts", + ], + vendor_available: true, +} diff --git a/Android.mk b/Android.mk index bd41ca7273..0a8b956d13 100644 --- a/Android.mk +++ b/Android.mk @@ -92,6 +92,17 @@ ifeq ($(TARGET_BOARD_PLATFORM), monaco) include $(DLKM_DIR)/Build_external_kernelmodule.mk ########################################################### + ########################################################### + include $(CLEAR_VARS) + LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/**/*) $(wildcard $(LOCAL_PATH)/*) + LOCAL_MODULE := glink_comm.ko + LOCAL_MODULE_KBUILD_NAME := glink_comm.ko + LOCAL_MODULE_TAGS := optional + #LOCAL_MODULE_DEBUG_ENABLE := true + LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT) + include $(DLKM_DIR)/Build_external_kernelmodule.mk + ########################################################### + ########################################################### include $(CLEAR_VARS) LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/**/*) $(wildcard $(LOCAL_PATH)/*) diff --git a/Kbuild b/Kbuild index 392d00f3df..298f4bf844 100644 --- a/Kbuild +++ b/Kbuild @@ -156,6 +156,15 @@ ifeq ($(CONFIG_TOUCHSCREEN_DUMMY), y) obj-$(CONFIG_MSM_TOUCH) += dummy_ts.o endif +ifeq ($(CONFIG_TOUCHSCREEN_MSM_GLINK), y) + + LINUXINCLUDE += -I$(TOUCH_ROOT)/glink_interface_ts + + glink_comm-y := ./glink_interface_ts/glink_interface.o + + obj-$(CONFIG_MSM_TOUCH) += glink_comm.o +endif + ifeq ($(CONFIG_TOUCHSCREEN_SYNAPTICS_TCM), y) synaptics_tcm_ts-y := \ ./synaptics_tcm/synaptics_tcm_core.o \ diff --git a/config/gki_monacotouch.conf b/config/gki_monacotouch.conf index 810b5c9c49..cfa8246980 100644 --- a/config/gki_monacotouch.conf +++ b/config/gki_monacotouch.conf @@ -4,3 +4,4 @@ export CONFIG_TOUCHSCREEN_PARADE_DEVICETREE_SUPPORT=y export CONFIG_TOUCHSCREEN_PARADE_I2C=y export CONFIG_TOUCHSCREEN_PARADE_DEVICE_ACCESS=y export CONFIG_TOUCHSCREEN_RM_TS=y +export CONFIG_TOUCHSCREEN_MSM_GLINK=y diff --git a/config/gki_monacotouchconf.h b/config/gki_monacotouchconf.h index 34f79b80d4..e940a0f454 100644 --- a/config/gki_monacotouchconf.h +++ b/config/gki_monacotouchconf.h @@ -5,3 +5,4 @@ #define CONFIG_TOUCHSCREEN_PARADE_BUTTON 1 #define CONFIG_TOUCHSCREEN_PARADE_PROXIMITY 1 #define CONFIG_TOUCHSCREEN_RM_TS 1 +#define CONFIG_TOUCHSCREEN_MSM_GLINK 1 diff --git a/glink_interface_ts/glink_interface.c b/glink_interface_ts/glink_interface.c new file mode 100644 index 0000000000..9281d17639 --- /dev/null +++ b/glink_interface_ts/glink_interface.c @@ -0,0 +1,121 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include + +static struct glink_touch_dev *touch_pdev = NULL; +struct touch_channel_ops touch_ops; + + +void glink_touch_channel_init(void (*fn1)(bool), void (*fn2)(void *data, int len)) +{ + touch_ops.glink_channel_state = fn1; + touch_ops.rx_msg = fn2; +} +EXPORT_SYMBOL(glink_touch_channel_init); + +int glink_touch_tx_msg(void *msg, size_t len) +{ + int ret = 0; + + if (touch_pdev == NULL || !touch_pdev->chnl_state) { + pr_err("pmsg_device is null, channel is closed\n"); + return -ENETRESET; + } + + touch_pdev->message = msg; + touch_pdev->message_length = len; + if (touch_pdev->message) { + ret = rpmsg_send(touch_pdev->channel, + touch_pdev->message, touch_pdev->message_length); + if (ret) + pr_err("rpmsg_send failed: %d\n", ret); + + } + + return ret; +} +EXPORT_SYMBOL(glink_touch_tx_msg); + +static int glink_touch_probe(struct rpmsg_device *touch_rpdev) +{ + int ret = 0; + void *msg = NULL; + + pr_info("%s Start of glink_touch_probe\n", __func__); + touch_pdev = devm_kzalloc(&touch_rpdev->dev, sizeof(*touch_pdev), GFP_KERNEL); + if (!touch_pdev) + return -ENOMEM; + + touch_pdev->channel = touch_rpdev->ept; + touch_pdev->dev = &touch_rpdev->dev; + if (touch_pdev->channel == NULL) + return -ENOMEM; + + touch_pdev->chnl_state = true; + dev_set_drvdata(&touch_rpdev->dev, touch_pdev); + + /* send a callback to slate-MSM touch driver*/ + touch_ops.glink_channel_state(true); + if (touch_pdev->message == NULL) + ret = glink_touch_tx_msg(msg, 0); + + pr_info("%s End of glink_touch_probe\n", __func__); + return 0; +} + +static void glink_touch_remove(struct rpmsg_device *touch_rpdev) +{ + touch_pdev->chnl_state = false; + touch_pdev->message = NULL; + dev_dbg(&touch_rpdev->dev, "rpmsg client driver is removed\n"); + touch_ops.glink_channel_state(false); + dev_set_drvdata(&touch_rpdev->dev, NULL); + +} + +static int glink_touch_cb(struct rpmsg_device *touch_rpdev, + void *data, int len, void *priv, u32 src) +{ + struct glink_touch_dev *touch_dev = + dev_get_drvdata(&touch_rpdev->dev); + + if (!touch_dev) + return -ENODEV; + touch_ops.rx_msg(data, len); + + return 0; +} + +static const struct rpmsg_device_id glink_touch_driver_id_table[] = { + { "touch-ctrl" }, + {}, +}; +MODULE_DEVICE_TABLE(rpmsg, glink_touch_driver_id_table); + +static const struct of_device_id glink_touch_driver_of_match[] = { + { .compatible = "qcom,slatetouch-rpmsg" }, + {}, +}; + +static struct rpmsg_driver glink_touch_client = { + .id_table = glink_touch_driver_id_table, + .probe = glink_touch_probe, + .callback = glink_touch_cb, + .remove = glink_touch_remove, + .drv = { + .name = "glink_interface", + .of_match_table = glink_touch_driver_of_match, + }, +}; +module_rpmsg_driver(glink_touch_client); + +MODULE_DESCRIPTION("Interface Driver for MSM TOUCH and RPMSG"); +MODULE_LICENSE("GPL v2"); diff --git a/glink_interface_ts/glink_interface.h b/glink_interface_ts/glink_interface.h new file mode 100644 index 0000000000..89031fae82 --- /dev/null +++ b/glink_interface_ts/glink_interface.h @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef GLINKINTERFACE_H +#define GLINKINTERFACE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define TOUCH_GLINK_INTENT_SIZE 0x0c +#define TOUCH_MSG_SIZE 0x08 +#define TIMEOUT_MS 2000 + +struct glink_touch_priv { + void *handle; + struct mutex glink_mutex; + struct mutex touch_state_mutex; + void *lhndl; + char rx_buf[TOUCH_GLINK_INTENT_SIZE]; + bool glink_touch_cmplt; + wait_queue_head_t link_state_wait; + bool msm_touch_rpmsg; +}; + +static void *glink_touch_drv; + +enum touch_slate_cmds { + TOUCH_ENTER_PREPARE = 0x1100, + TOUCH_ENTER, + TOUCH_EXIT_PREPARE, + TOUCH_EXIT +}; + +struct glink_touch_dev { + struct rpmsg_endpoint *channel; + struct device *dev; + bool chnl_state; + void *message; + size_t message_length; +}; + +struct touch_channel_ops { + void (*glink_channel_state)(bool state); + void (*rx_msg)(void *data, int len); +}; + +void glink_touch_channel_init(void (*fn1)(bool), void (*fn2)(void *, int)); + + + +#if IS_ENABLED(CONFIG_MSM_SLATERSB_RPMSG) +int glink_touch_tx_msg(void *msg, size_t len); +#else +static inline int glink_touch_tx_msg(void *msg, size_t len) +{ + return -EIO; +} +#endif + +#endif diff --git a/raydium/raydium_driver.c b/raydium/raydium_driver.c index 6d8ef874d5..5e2f4158aa 100644 --- a/raydium/raydium_driver.c +++ b/raydium/raydium_driver.c @@ -39,6 +39,8 @@ #include #include #include "raydium_driver.h" +#include +#include #if defined(CONFIG_FB) #include #include @@ -60,7 +62,6 @@ struct raydium_slot_status gst_slot_init = {0xFF, 0, 0}; static int raydium_enable_regulator(struct raydium_ts_data *cd, bool en); - #if (defined(CONFIG_RM_SYSFS_DEBUG)) const struct attribute_group raydium_attr_group; #endif /*end of CONFIG_RM_SYSFS_DEBUG*/ @@ -89,6 +90,7 @@ unsigned char g_u8_checkflag; #endif unsigned char g_u8_log_level; struct raydium_ts_data *g_raydium_ts; + /******************************************************************************* * Name: raydium_variable_init * Brief: @@ -1076,15 +1078,17 @@ static int raydium_touch_report(unsigned char *p_u8_buf, return 0; } + int raydium_read_touchdata(unsigned char *p_u8_tp_status, unsigned char *p_u8_buf) { + int i32_ret = 0; unsigned char u8_points_amount; static unsigned char u8_seq_no; unsigned char u8_retry; unsigned char u8_read_size; unsigned char u8_read_buf[MAX_REPORT_PACKET_SIZE]; - u8_retry = 3; + u8_retry = 100; mutex_lock(&g_raydium_ts->lock); while (u8_retry != 0) { @@ -2100,6 +2104,36 @@ static void raydium_input_set(struct input_dev *input_dev) gst_slot[i] = gst_slot_init; } + +void touch_notify_glink_channel_state(bool state) +{ + LOGD(LOG_INFO, "%s:[touch] channel state: %d\n", __func__, state); +} + +void glink_touch_rx_msg(void *data, int len) +{ + int rc = 0; + + LOGD(LOG_INFO, "%s:[touch]TOUCH_RX_MSG Start:\n", __func__); + + if (len > TOUCH_GLINK_INTENT_SIZE) { + LOGD(LOG_ERR, "Invalid TOUCH glink intent size\n"); + return; + } + + /* check SLATE response */ + slate_ack_resp = *(uint32_t *)&data[8]; + LOGD(LOG_INFO, "[touch]slate_ack_resp :%0x\n", slate_ack_resp); + if (slate_ack_resp == 0x01) { + LOGD(LOG_INFO,"Bad SLATE response\n"); + rc = -EINVAL; + goto err_ret; + } + LOGD(LOG_INFO, "%s:[touch]TOUCH_RX_MSG End:\n", __func__); +err_ret: +return; +} + static int raydium_set_resolution(void) { unsigned char u8_buf[4]; @@ -2370,6 +2404,9 @@ static int raydium_ts_probe(struct i2c_client *client, ret = -EPROBE_DEFER; goto exit_check_i2c; } + + glink_touch_channel_init(&touch_notify_glink_channel_state, &glink_touch_rx_msg); + #if defined(CONFIG_DRM) || defined(CONFIG_PANEL_NOTIFIER) /* Setup active dsi panel */ active_panel = pdata->active_panel; diff --git a/raydium/raydium_driver.h b/raydium/raydium_driver.h index 5a9d138f5a..574967d574 100644 --- a/raydium/raydium_driver.h +++ b/raydium/raydium_driver.h @@ -275,6 +275,7 @@ #include #endif +extern uint32_t slate_ack_resp; enum raydium_fb_state { FB_ON, diff --git a/raydium/raydium_sysfs.c b/raydium/raydium_sysfs.c index e61675457a..39df8b6a7f 100644 --- a/raydium/raydium_sysfs.c +++ b/raydium/raydium_sysfs.c @@ -25,8 +25,18 @@ #include #include #include +#include +#include #include #include "raydium_driver.h" +#include + + +static void raydium_ts_touch_entry(void); +static void raydium_ts_touch_exit(void); +static int raydium_ts_gpio_config(bool on); + +uint32_t slate_ack_resp; static ssize_t raydium_touch_calibration_show(struct device *dev, struct device_attribute *attr, @@ -221,6 +231,196 @@ static ssize_t raydium_palm_status_show(struct device *dev, u16_len = strlen(p_i8_buf); return u16_len + 1; } + + +static int raydium_ts_gpio_config(bool on) +{ + int i32_err = 0; + + if (on) { + if (gpio_is_valid(g_raydium_ts->irq_gpio)) { + i32_err = gpio_request(g_raydium_ts->irq_gpio, + "raydium_irq_gpio"); + if (i32_err) { + LOGD(LOG_ERR, "[touch]irq gpio request failed"); + goto err_irq_gpio_req; + } + + i32_err = gpio_direction_input(g_raydium_ts->irq_gpio); + if (i32_err) { + LOGD(LOG_ERR, "[touch]set_direction for irq gpio failed\n"); + goto err_irq_gpio_dir; + } + } + if (gpio_is_valid(g_raydium_ts->rst_gpio)) { + i32_err = gpio_request(g_raydium_ts->rst_gpio, + "raydium_rst_gpio"); + if (i32_err) { + LOGD(LOG_ERR, "[touch]rst gpio request failed"); + goto err_irq_gpio_req; + } + + i32_err = gpio_direction_output(g_raydium_ts->rst_gpio, 0); + msleep(RAYDIUM_RESET_INTERVAL_10MSEC); + if (i32_err) { + LOGD(LOG_ERR, + "[touch]set_direction for rst gpio failed\n"); + goto err_rst_gpio_dir; + } + + i32_err = gpio_direction_output(g_raydium_ts->rst_gpio, 1); + if (i32_err) { + LOGD(LOG_ERR, + "[touch]set_direction for irq gpio failed\n"); + goto err_rst_gpio_dir; + } + } + } else { + if (gpio_is_valid(g_raydium_ts->irq_gpio)) + gpio_free(g_raydium_ts->irq_gpio); + } + return 0; +err_rst_gpio_dir: + if (gpio_is_valid(g_raydium_ts->rst_gpio)) + gpio_free(g_raydium_ts->rst_gpio); + return i32_err; +err_irq_gpio_dir: + if (gpio_is_valid(g_raydium_ts->irq_gpio)) + gpio_free(g_raydium_ts->irq_gpio); +err_irq_gpio_req: + return i32_err; +} + +static void raydium_ts_touch_entry(void) +{ + void *glink_send_msg; + unsigned char u8_i = 0; + + int glink_touch_enter_prep = TOUCH_ENTER_PREPARE; + int glink_touch_enter = TOUCH_ENTER; + int rc = 0; + + LOGD(LOG_INFO, "%s[touch] raydium_ts_touch_entry Start\n", __func__); + + /*glink touch enter prepare cmd */ + glink_send_msg = &glink_touch_enter_prep; + LOGD(LOG_INFO, "[touch] glink_send_msg = %0x\n", glink_send_msg); + glink_touch_tx_msg(glink_send_msg, TOUCH_MSG_SIZE); + + if (slate_ack_resp != 0) { + rc = -EINVAL; + goto err_ret; + } + /*glink touch enter cmd */ + glink_send_msg = &glink_touch_enter; + LOGD(LOG_INFO, "[touch]glink_send_msg = %0x\n", glink_send_msg); + glink_touch_tx_msg(glink_send_msg, TOUCH_MSG_SIZE); + + if(slate_ack_resp == 0) { + //Release the gpio's + if (gpio_is_valid(g_raydium_ts->rst_gpio)) + gpio_free(g_raydium_ts->rst_gpio); + + if (gpio_is_valid(g_raydium_ts->irq_gpio)) + gpio_free(g_raydium_ts->irq_gpio); + + raydium_irq_control(DISABLE); + + if (!cancel_work_sync(&g_raydium_ts->work)) + LOGD(LOG_DEBUG, "[touch]workqueue is empty!\n"); + + /* release all touches */ + for (u8_i = 0; u8_i < g_raydium_ts->u8_max_touchs; u8_i++) { + pr_err("[touch]%s 1111\n", __func__); + input_mt_slot(g_raydium_ts->input_dev, u8_i); + input_mt_report_slot_state(g_raydium_ts->input_dev, + MT_TOOL_FINGER, + false); + } + + input_mt_report_pointer_emulation(g_raydium_ts->input_dev, false); + input_sync(g_raydium_ts->input_dev); + } + + LOGD(LOG_INFO, "%s[touch] raydium_ts_touch_entry Start End\n", __func__); +err_ret: + return; +} + + +static void raydium_ts_touch_exit(void) +{ + + int ret = 0, rc = 0; + void *glink_send_msg; + int glink_touch_exit_prep = TOUCH_EXIT_PREPARE; + int glink_touch_exit = TOUCH_EXIT; + + + LOGD(LOG_INFO, "%s[touch]raydium_ts_touch_exit Start\n", __func__); + + /*glink touch exit prepare cmd */ + glink_send_msg = &glink_touch_exit_prep; + LOGD(LOG_INFO, "[touch]glink_send_msg = %0x\n", glink_send_msg); + glink_touch_tx_msg(glink_send_msg, TOUCH_MSG_SIZE); + + if (slate_ack_resp != 0) { + rc = -EINVAL; + goto err_ret; + } + + else if(slate_ack_resp == 0) { + //Configure the gpio's + ret = raydium_ts_gpio_config(true); + if (ret < 0) { + LOGD(LOG_ERR, "[touch]failed to configure the gpios\n"); + goto err_ret; + } + } + + /*glink touch exit cmd */ + glink_send_msg = &glink_touch_exit; + LOGD(LOG_INFO, "[touch]glink_send_msg = %d\n", glink_send_msg); + glink_touch_tx_msg(glink_send_msg, TOUCH_MSG_SIZE); + + LOGD(LOG_INFO, "%s[touch] raydium_ts_touch_exit End\n", __func__); +err_ret: + return; + +} + +static ssize_t raydium_touch_offload_store(struct device *dev, + struct device_attribute *attr, + const char *p_i8_buf, size_t count) +{ + int i32_ret = 0; + unsigned char u8_mode; + + /* receive command line arguments string */ + if (count > 2) + return -EINVAL; + + i32_ret = kstrtou8(p_i8_buf, 16, &u8_mode); + if (i32_ret < 0) + return i32_ret; + + switch (u8_mode) { + case 0: /* Disable Touch offload */ + + LOGD(LOG_INFO, "[touch]RAD %s disable touch offload!!\n", __func__); + raydium_ts_touch_entry(); + break; + + case 1: /* Enable Touch offload */ + + LOGD(LOG_INFO, "[touch]RAD %s enable touch offload!!\n", __func__); + raydium_ts_touch_exit(); + break; + } + + return count; +} + static ssize_t raydium_touch_lock_store(struct device *dev, struct device_attribute *attr, const char *p_i8_buf, size_t count) @@ -1363,6 +1563,14 @@ static DEVICE_ATTR(raydium_i2c_touch_lock, 0644, NULL, raydium_touch_lock_store); +/* Touch Offload (W) + * example: echo 1 > raydium_touch_offload ==> enable touch offload + * echo 0 > raydium_touch_offload ==> disable touch offload + */ +static DEVICE_ATTR(raydium_touch_offload, 0644, + NULL, + raydium_touch_offload_store); + /* Log level (W) * example: echo 1 > raydium_log_level ==> modify log level */ @@ -1436,6 +1644,7 @@ struct attribute *raydium_attributes[] = { &dev_attr_raydium_i2c_pda2_page.attr, &dev_attr_raydium_i2c_raw_data.attr, &dev_attr_raydium_i2c_touch_lock.attr, + &dev_attr_raydium_touch_offload.attr, &dev_attr_raydium_fw_upgrade.attr, &dev_attr_raydium_check_fw_version.attr, &dev_attr_raydium_check_panel_version.attr, diff --git a/touch_driver_board.mk b/touch_driver_board.mk index 6e11fe5a85..71df480a7a 100644 --- a/touch_driver_board.mk +++ b/touch_driver_board.mk @@ -12,6 +12,7 @@ ifeq ($(TOUCH_DLKM_ENABLE), true) BOARD_VENDOR_KERNEL_MODULES += $(KERNEL_MODULES_OUT)/pt_ts.ko \ $(KERNEL_MODULES_OUT)/pt_i2c.ko \ $(KERNEL_MODULES_OUT)/pt_device_access.ko \ + $(KERNEL_MODULES_OUT)/glink_comm.ko \ $(KERNEL_MODULES_OUT)/raydium_ts.ko else ifeq ($(TARGET_BOARD_PLATFORM), kona) BOARD_VENDOR_KERNEL_MODULES += $(KERNEL_MODULES_OUT)/focaltech_fts.ko diff --git a/touch_driver_product.mk b/touch_driver_product.mk index 4d0876df58..0de0c14e2c 100644 --- a/touch_driver_product.mk +++ b/touch_driver_product.mk @@ -10,6 +10,7 @@ ifeq ($(TOUCH_DLKM_ENABLE), true) PRODUCT_PACKAGES += $(KERNEL_MODULES_OUT)/pt_ts.ko \ $(KERNEL_MODULES_OUT)/pt_i2c.ko \ $(KERNEL_MODULES_OUT)/pt_device_access.ko \ + $(KERNEL_MODULES_OUT)/glink_comm.ko \ $(KERNEL_MODULES_OUT)/raydium_ts.ko else ifeq ($(TARGET_BOARD_PLATFORM), kona) PRODUCT_PACKAGES += $(KERNEL_MODULES_OUT)/focaltech_fts.ko