diff --git a/drivers/input/touchscreen/focaltech_v3_mmi/Android.mk b/drivers/input/touchscreen/focaltech_v3_mmi/Android.mk index 146ccea8d94c..ea69db58f654 100644 --- a/drivers/input/touchscreen/focaltech_v3_mmi/Android.mk +++ b/drivers/input/touchscreen/focaltech_v3_mmi/Android.mk @@ -11,6 +11,10 @@ ifneq ($(BOARD_USES_DOUBLE_TAP),) KERNEL_CFLAGS += CONFIG_INPUT_FOCALTECH_MMI_ENABLE_DOUBLE_TAP=y endif +ifneq ($(findstring touchscreen_mmi.ko,$(BOARD_VENDOR_KERNEL_MODULES)),) + KERNEL_CFLAGS += CONFIG_INPUT_TOUCHSCREEN_MMI=y +endif + ifneq ($(FOCALTECH_TOUCH_TEST_SUPPORT),) KERNEL_CFLAGS += CONFIG_INPUT_FTS_TEST_SUPPORT=y endif @@ -19,4 +23,9 @@ include $(CLEAR_VARS) LOCAL_MODULE := focaltech_v3_mmi.ko LOCAL_MODULE_TAGS := optional LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT) + +ifneq ($(findstring touchscreen_mmi.ko,$(BOARD_VENDOR_KERNEL_MODULES)),) + LOCAL_ADDITIONAL_DEPENDENCIES += $(KERNEL_MODULES_OUT)/touchscreen_mmi.ko +endif + include $(DLKM_DIR)/AndroidKernelModule.mk diff --git a/drivers/input/touchscreen/focaltech_v3_mmi/Kbuild b/drivers/input/touchscreen/focaltech_v3_mmi/Kbuild index 254457f2610b..31f5d2c5329a 100644 --- a/drivers/input/touchscreen/focaltech_v3_mmi/Kbuild +++ b/drivers/input/touchscreen/focaltech_v3_mmi/Kbuild @@ -24,6 +24,12 @@ ifneq ($(filter ft3518u,$(CONFIG_INPUT_FOCALTECH_MMI_IC_NAME)),) focaltech_v3_mmi-objs += focaltech_flash/focaltech_upgrade_ft3518u.o endif +ifneq ($(filter m y,$(CONFIG_INPUT_TOUCHSCREEN_MMI)),) + KBUILD_EXTRA_SYMBOLS += $(CURDIR)/$(KBUILD_EXTMOD)/../touchscreen_mmi/$(GKI_OBJ_MODULE_DIR)/Module.symvers + EXTRA_CFLAGS += -DCONFIG_INPUT_TOUCHSCREEN_MMI + focaltech_v3_mmi-objs += focaltech_ts_mmi.o +endif + ifneq ($(filter m y,$(CONFIG_INPUT_FOCALTECH_MMI_ENABLE_DOUBLE_TAP)),) EXTRA_CFLAGS += -DFOCALTECH_SENSOR_EN endif diff --git a/drivers/input/touchscreen/focaltech_v3_mmi/focaltech_common.h b/drivers/input/touchscreen/focaltech_v3_mmi/focaltech_common.h index f6dba4072c82..c791890faeea 100644 --- a/drivers/input/touchscreen/focaltech_v3_mmi/focaltech_common.h +++ b/drivers/input/touchscreen/focaltech_v3_mmi/focaltech_common.h @@ -56,9 +56,11 @@ #define FTS_MAX_CHIP_IDS 8 +#if defined(CONFIG_FTS_IC_NAME_FT3519) #define FTS_CHIP_TYPE_MAPPING {{0x89, 0x54, 0x52, 0x54, 0x52, 0x54, 0x5B, 0x54, 0x5E}} - - +#else +#define FTS_CHIP_TYPE_MAPPING {{0x81, 0x54, 0x52, 0x54, 0x52, 0x00, 0x00, 0x54, 0x5C}} +#endif #define FILE_NAME_LENGTH 128 #define ENABLE 1 diff --git a/drivers/input/touchscreen/focaltech_v3_mmi/focaltech_config.h b/drivers/input/touchscreen/focaltech_v3_mmi/focaltech_config.h index 7f352a970476..079664319b45 100644 --- a/drivers/input/touchscreen/focaltech_v3_mmi/focaltech_config.h +++ b/drivers/input/touchscreen/focaltech_v3_mmi/focaltech_config.h @@ -253,7 +253,9 @@ /* * auto upgrade */ -#define FTS_AUTO_UPGRADE_EN 1 +#define FTS_AUTO_UPGRADE_EN 0 + +#define FTS_FW_FILE_I_INCELL_CHECK 1 /* * auto upgrade for lcd cfg @@ -265,6 +267,11 @@ */ #define FTS_GET_MODULE_NUM 0 +/* + * Usb detect support + */ +#define FTS_USB_DETECT_EN 0 + /* * module_id: mean vendor_id generally, also maybe gpio or lcm_id... * If means vendor_id, the FTS_MODULE_ID = PANEL_ID << 8 + VENDOR_ID diff --git a/drivers/input/touchscreen/focaltech_v3_mmi/focaltech_core.c b/drivers/input/touchscreen/focaltech_v3_mmi/focaltech_core.c index 30e2fa13671d..ca880eb050b0 100644 --- a/drivers/input/touchscreen/focaltech_v3_mmi/focaltech_core.c +++ b/drivers/input/touchscreen/focaltech_v3_mmi/focaltech_core.c @@ -52,6 +52,11 @@ #endif #include "focaltech_core.h" +#ifdef CONFIG_INPUT_TOUCHSCREEN_MMI +extern int fts_mmi_dev_register(struct fts_ts_data *ts_data); +extern void fts_mmi_dev_unregister(struct fts_ts_data *ts_data); +#endif + /***************************************************************************** * Private constant and macro definitions using #define *****************************************************************************/ @@ -74,8 +79,10 @@ struct fts_ts_data *fts_data; /***************************************************************************** * Static function prototypes *****************************************************************************/ +#ifndef CONFIG_INPUT_TOUCHSCREEN_MMI static int fts_ts_suspend(struct device *dev); static int fts_ts_resume(struct device *dev); +#endif int fts_check_cid(struct fts_ts_data *ts_data, u8 id_h) { @@ -1144,7 +1151,7 @@ static int fts_pinctrl_select_release(struct fts_ts_data *ts) } #endif /* FTS_PINCTRL_EN */ -static int fts_power_source_ctrl(struct fts_ts_data *ts_data, int enable) +int fts_power_source_ctrl(struct fts_ts_data *ts_data, int enable) { int ret = 0; @@ -1278,6 +1285,7 @@ static int fts_power_source_exit(struct fts_ts_data *ts_data) return 0; } +#ifndef CONFIG_INPUT_TOUCHSCREEN_MMI static int fts_power_source_suspend(struct fts_ts_data *ts_data) { int ret = 0; @@ -1309,6 +1317,7 @@ static int fts_power_source_resume(struct fts_ts_data *ts_data) return ret; } +#endif //CONFIG_INPUT_TOUCHSCREEN_MMI #endif /* FTS_POWER_SOURCE_CUST_EN */ static int fts_gpio_configure(struct fts_ts_data *data) @@ -1488,6 +1497,7 @@ static int fts_parse_dt(struct device *dev, struct fts_ts_platform_data *pdata) return 0; } +#ifndef CONFIG_INPUT_TOUCHSCREEN_MMI static void fts_resume_work(struct work_struct *work) { struct fts_ts_data *ts_data = container_of(work, struct fts_ts_data, @@ -1680,6 +1690,7 @@ static void fts_ts_late_resume(struct early_suspend *handler) queue_work(fts_data->ts_workqueue, &fts_data->resume_work); } #endif +#endif //CONFIG_INPUT_TOUCHSCREEN_MMI static int fts_ts_probe_entry(struct fts_ts_data *ts_data) { @@ -1699,14 +1710,15 @@ static int fts_ts_probe_entry(struct fts_ts_data *ts_data) if (ret) FTS_ERROR("device-tree parse fail"); -#if defined(CONFIG_FB) -#elif defined(CONFIG_DRM) +#ifndef CONFIG_INPUT_TOUCHSCREEN_MMI +#if defined(CONFIG_DRM) #if defined(CONFIG_DRM_PANEL) ret = drm_check_dt(ts_data->dev->of_node); if (ret) { FTS_ERROR("parse drm-panel fail"); } #endif +#endif #endif } else { if (ts_data->dev->platform_data) { @@ -1821,15 +1833,18 @@ static int fts_ts_probe_entry(struct fts_ts_data *ts_data) FTS_ERROR("init fw upgrade fail"); } +#ifndef CONFIG_INPUT_TOUCHSCREEN_MMI if (ts_data->ts_workqueue) { INIT_WORK(&ts_data->resume_work, fts_resume_work); } +#endif #if defined(CONFIG_PM) && FTS_PATCH_COMERR_PM init_completion(&ts_data->pm_completion); ts_data->pm_suspend = false; #endif +#ifndef CONFIG_INPUT_TOUCHSCREEN_MMI #if defined(CONFIG_FB) ts_data->fb_notif.notifier_call = fb_notifier_callback; ret = fb_register_client(&ts_data->fb_notif); @@ -1856,6 +1871,11 @@ static int fts_ts_probe_entry(struct fts_ts_data *ts_data) ts_data->early_suspend.resume = fts_ts_late_resume; register_early_suspend(&ts_data->early_suspend); #endif +#endif + +#ifdef CONFIG_INPUT_TOUCHSCREEN_MMI + fts_mmi_dev_register(ts_data); +#endif FTS_FUNC_EXIT(); return 0; @@ -1893,6 +1913,10 @@ static int fts_ts_remove_entry(struct fts_ts_data *ts_data) { FTS_FUNC_ENTER(); +#ifdef CONFIG_INPUT_TOUCHSCREEN_MMI + fts_mmi_dev_unregister(ts_data); +#endif + #if FTS_POINT_REPORT_CHECK_EN fts_point_report_check_exit(ts_data); #endif @@ -1923,6 +1947,7 @@ static int fts_ts_remove_entry(struct fts_ts_data *ts_data) if (ts_data->ts_workqueue) destroy_workqueue(ts_data->ts_workqueue); +#ifndef CONFIG_INPUT_TOUCHSCREEN_MMI #if defined(CONFIG_FB) if (fb_unregister_client(&ts_data->fb_notif)) FTS_ERROR("[FB]Error occurred while unregistering fb_notifier."); @@ -1936,6 +1961,7 @@ static int fts_ts_remove_entry(struct fts_ts_data *ts_data) #endif #elif defined(CONFIG_HAS_EARLYSUSPEND) unregister_early_suspend(&ts_data->early_suspend); +#endif #endif if (gpio_is_valid(ts_data->pdata->reset_gpio)) @@ -1959,6 +1985,7 @@ static int fts_ts_remove_entry(struct fts_ts_data *ts_data) return 0; } +#ifndef CONFIG_INPUT_TOUCHSCREEN_MMI static int fts_ts_suspend(struct device *dev) { int ret = 0; @@ -2041,6 +2068,7 @@ static int fts_ts_resume(struct device *dev) FTS_FUNC_EXIT(); return 0; } +#endif #if defined(CONFIG_PM) && FTS_PATCH_COMERR_PM static int fts_pm_suspend(struct device *dev) diff --git a/drivers/input/touchscreen/focaltech_v3_mmi/focaltech_core.h b/drivers/input/touchscreen/focaltech_v3_mmi/focaltech_core.h index 48f3951de7a4..bef9faf57ee0 100644 --- a/drivers/input/touchscreen/focaltech_v3_mmi/focaltech_core.h +++ b/drivers/input/touchscreen/focaltech_v3_mmi/focaltech_core.h @@ -62,6 +62,9 @@ #include #include #include "focaltech_common.h" +#if defined(CONFIG_INPUT_TOUCHSCREEN_MMI) +#include +#endif /***************************************************************************** * Private constant and macro definitions using #define @@ -192,6 +195,7 @@ struct fts_ts_data { #endif bool suspended; bool fw_loading; + bool force_reflash; bool irq_disabled; bool power_disabled; bool glove_mode; @@ -225,6 +229,10 @@ struct fts_ts_data { #elif defined(CONFIG_HAS_EARLYSUSPEND) struct early_suspend early_suspend; #endif + +#if defined(CONFIG_INPUT_TOUCHSCREEN_MMI) + struct ts_mmi_class_methods *imports; +#endif }; enum _FTS_BUS_TYPE { @@ -292,7 +300,9 @@ void fts_prc_queue_work(struct fts_ts_data *ts_data); int fts_fwupg_init(struct fts_ts_data *ts_data); int fts_fwupg_exit(struct fts_ts_data *ts_data); int fts_upgrade_bin(char *fw_name, bool force); +void fts_fwupg_bin(void); int fts_enter_test_environment(bool test_state); +int fts_fw_update_vendor_name(const char* name); /* Other */ int fts_reset_proc(int hdelayms); @@ -306,4 +316,5 @@ int fts_ex_mode_recovery(struct fts_ts_data *ts_data); void fts_irq_disable(void); void fts_irq_enable(void); +int fts_power_source_ctrl(struct fts_ts_data *ts_data, int enable); #endif /* __LINUX_FOCALTECH_CORE_H__ */ diff --git a/drivers/input/touchscreen/focaltech_v3_mmi/focaltech_ex_fun.c b/drivers/input/touchscreen/focaltech_v3_mmi/focaltech_ex_fun.c index 26318203b01c..c0a27df59278 100644 --- a/drivers/input/touchscreen/focaltech_v3_mmi/focaltech_ex_fun.c +++ b/drivers/input/touchscreen/focaltech_v3_mmi/focaltech_ex_fun.c @@ -1266,6 +1266,7 @@ static struct attribute_group fts_attribute_group = { .attrs = fts_attributes }; +#ifndef CONFIG_INPUT_TOUCHSCREEN_MMI #include #include @@ -1381,6 +1382,7 @@ device_destroy: return -ENODEV; } +#endif int fts_create_sysfs(struct fts_ts_data *ts_data) { @@ -1395,12 +1397,14 @@ int fts_create_sysfs(struct fts_ts_data *ts_data) FTS_INFO("[EX]: sysfs_create_group() succeeded!!"); } +#ifndef CONFIG_INPUT_TOUCHSCREEN_MMI ret = ft_ts_sysfs_class(ts_data, true); if (ret) { FTS_ERROR("[EX]: fts_sysfs_class() failed!!"); sysfs_remove_group(&ts_data->dev->kobj, &fts_attribute_group); return -ENOMEM; } +#endif return ret; } @@ -1408,6 +1412,8 @@ int fts_create_sysfs(struct fts_ts_data *ts_data) int fts_remove_sysfs(struct fts_ts_data *ts_data) { sysfs_remove_group(&ts_data->dev->kobj, &fts_attribute_group); +#ifndef CONFIG_INPUT_TOUCHSCREEN_MMI ft_ts_sysfs_class(ts_data, false); +#endif return 0; } diff --git a/drivers/input/touchscreen/focaltech_v3_mmi/focaltech_flash.c b/drivers/input/touchscreen/focaltech_v3_mmi/focaltech_flash.c index ff177d7dd1d8..e235bc555c3d 100644 --- a/drivers/input/touchscreen/focaltech_v3_mmi/focaltech_flash.c +++ b/drivers/input/touchscreen/focaltech_v3_mmi/focaltech_flash.c @@ -40,11 +40,25 @@ *****************************************************************************/ #define FTS_FW_REQUEST_SUPPORT 1 /* Example: focaltech_ts_fw_tianma.bin */ +#ifdef CONFIG_INPUT_TOUCHSCREEN_MMI +#define FTS_FW_NAME_PREX_WITH_REQUEST "" +#else #define FTS_FW_NAME_PREX_WITH_REQUEST "focaltech_ts_fw_" +#endif /***************************************************************************** * Global variable or extern global variabls/functions *****************************************************************************/ +#ifdef CONFIG_INPUT_TOUCHSCREEN_MMI +u8 fw_file[] = { +}; + +u8 fw_file2[] = { +}; + +u8 fw_file3[] = { +}; +#else u8 fw_file[] = { #include FTS_UPGRADE_FW_FILE }; @@ -56,6 +70,7 @@ u8 fw_file2[] = { u8 fw_file3[] = { #include FTS_UPGRADE_FW3_FILE }; +#endif struct upgrade_module module_list[] = { {FTS_MODULE_ID, FTS_MODULE_NAME, fw_file, sizeof(fw_file)}, @@ -1858,6 +1873,33 @@ static int fts_fwupg_get_module_info(struct fts_upgrade *upg) return 0; } +int fts_fw_update_vendor_name(const char* name) { + struct fts_upgrade *upg = fwupgrade; + char* pos; + int len; + + fts_fwupg_get_module_info(fwupgrade); + + if (!upg || !upg->module_info) { + FTS_ERROR("upgrade struct not init"); + return -EINVAL; + } + + len = strlen(name); + if (len > FILE_NAME_LENGTH) { + FTS_ERROR("vendor name is too long"); + return -EINVAL; + } + pos = strstr(name, ".bin"); + if (pos == NULL) + snprintf(upg->module_info->vendor_name, FILE_NAME_LENGTH, "%s", name); + else { + len = len - strlen(".bin"); + snprintf(upg->module_info->vendor_name, len + 1, "%s", name); + } + return 0; +} + static int fts_get_fw_file_via_request_firmware(struct fts_upgrade *upg) { int ret = 0; @@ -1865,11 +1907,13 @@ static int fts_get_fw_file_via_request_firmware(struct fts_upgrade *upg) u8 *tmpbuf = NULL; char fwname[FILE_NAME_LENGTH] = { 0 }; + FTS_FUNC_ENTER(); if (!upg || !upg->ts_data || !upg->ts_data->dev) { FTS_ERROR("upg/ts_data/dev is null"); return -EINVAL; } +#ifndef CONFIG_INPUT_TOUCHSCREEN_MMI if (fts_data->panel_supplier) { FTS_INFO("fts_data->panel_supplier=%s\n", fts_data->panel_supplier); snprintf(fwname, FILE_NAME_LENGTH, "%s%s.bin", \ @@ -1877,6 +1921,7 @@ static int fts_get_fw_file_via_request_firmware(struct fts_upgrade *upg) fts_data->panel_supplier); } else +#endif snprintf(fwname, FILE_NAME_LENGTH, "%s%s.bin", \ FTS_FW_NAME_PREX_WITH_REQUEST, \ upg->module_info->vendor_name); @@ -1908,6 +1953,7 @@ static int fts_get_fw_file_via_request_firmware(struct fts_upgrade *upg) static int fts_get_fw_file_via_i(struct fts_upgrade *upg) { + FTS_FUNC_ENTER(); upg->fw = upg->module_info->fw_file; upg->fw_length = upg->module_info->fw_len; upg->fw_from_request = 0; @@ -1951,7 +1997,13 @@ static int fts_fwupg_get_fw_file(struct fts_upgrade *upg) if (FTS_FW_REQUEST_SUPPORT) { ret = fts_get_fw_file_via_request_firmware(upg); +#if FTS_FW_FILE_I_INCELL_CHECK + FTS_INFO("ret=%d, is_incell=%d",ret, upg->ts_data->ic_info.is_incell); + //only try get fw file i for non incell IC when load FW fail + if ((ret != 0) && upg->ts_data->ic_info.is_incell) { +#else if (ret != 0) { +#endif get_fw_i_flag = true; } } else { @@ -1971,6 +2023,7 @@ static int fts_fwupg_get_fw_file(struct fts_upgrade *upg) return -ENODATA; } + FTS_INFO("return ret:%d", ret); return ret; } @@ -1981,6 +2034,41 @@ static void fts_fwupg_init_ic_detail(struct fts_upgrade *upg) } } +void fts_fwupg_bin(void) +{ + int ret = 0; + struct fts_upgrade *upg = fwupgrade; + + FTS_INFO("fw upgrade bin function"); + if (!upg || !upg->ts_data) { + FTS_ERROR("upg/ts_data is null"); + return ; + } + + upg->ts_data->fw_loading = 1; + fts_irq_disable(); +#if FTS_ESDCHECK_EN + fts_esdcheck_switch(DISABLE); +#endif + + /* get fw */ + ret = fts_fwupg_get_fw_file(upg); + if (ret < 0) { + FTS_ERROR("get file fail, can't upgrade"); + } else { + /* ic init if have */ + fts_fwupg_init_ic_detail(upg); + /* run auto upgrade */ + fts_fwupg_auto_upgrade(upg); + } + +#if FTS_ESDCHECK_EN + fts_esdcheck_switch(ENABLE); +#endif + fts_irq_enable(); + upg->ts_data->fw_loading = 0; +} + /***************************************************************************** * Name: fts_fwupg_work * Brief: 1. get fw image/file diff --git a/drivers/input/touchscreen/focaltech_v3_mmi/focaltech_ts_mmi.c b/drivers/input/touchscreen/focaltech_v3_mmi/focaltech_ts_mmi.c new file mode 100644 index 000000000000..d81f832323dd --- /dev/null +++ b/drivers/input/touchscreen/focaltech_v3_mmi/focaltech_ts_mmi.c @@ -0,0 +1,421 @@ +/* + * Copyright (C) 2019 Motorola Mobility LLC + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include "focaltech_core.h" + +#define GET_TS_DATA(dev) { \ + ts_data = dev_get_drvdata(dev); \ + if (!ts_data) { \ + FTS_ERROR("Failed to get driver data"); \ + return -ENODEV; \ + } \ +} +static int fts_mmi_methods_get_vendor(struct device *dev, void *cdata) +{ + return scnprintf(TO_CHARP(cdata), TS_MMI_MAX_VENDOR_LEN, "%s", "focaltech"); +} + +static int fts_mmi_methods_get_productinfo(struct device *dev, void *cdata) +{ + return scnprintf(TO_CHARP(cdata), TS_MMI_MAX_INFO_LEN, "%s", FTS_CHIP_NAME); +} + +static int fts_mmi_methods_get_build_id(struct device *dev, void *cdata) +{ + struct fts_ts_data *ts_data; + struct input_dev *input_dev; + ssize_t num_read_chars = 0; + u8 fwver = 0; + + GET_TS_DATA(dev); + input_dev = ts_data->input_dev; + mutex_lock(&input_dev->mutex); + +#if FTS_ESDCHECK_EN + fts_esdcheck_proc_busy(1); +#endif + fts_read_reg(FTS_REG_FW_VER, &fwver); +#if FTS_ESDCHECK_EN + fts_esdcheck_proc_busy(0); +#endif + num_read_chars = scnprintf(TO_CHARP(cdata), TS_MMI_MAX_ID_LEN, "%02x", fwver); + + mutex_unlock(&input_dev->mutex); + return num_read_chars; +} + +/*return firmware version*/ +static int fts_mmi_methods_get_config_id(struct device *dev, void *cdata) +{ + return scnprintf(TO_CHARP(cdata), TS_MMI_MAX_ID_LEN, "%04x", 0); +} + +static int fts_mmi_methods_get_bus_type(struct device *dev, void *idata) +{ + struct fts_ts_data *ts_data; + struct input_dev *input_dev; + + GET_TS_DATA(dev); + input_dev = ts_data->input_dev; + TO_INT(idata) = input_dev->id.bustype == BUS_SPI ? + TOUCHSCREEN_MMI_BUS_TYPE_SPI : TOUCHSCREEN_MMI_BUS_TYPE_I2C; + return 0; +} + +static int fts_mmi_methods_get_irq_status(struct device *dev, void *idata) +{ + struct fts_ts_platform_data *pdata; + struct fts_ts_data *ts_data; + + GET_TS_DATA(dev); + pdata = ts_data->pdata; + + TO_INT(idata) = gpio_get_value(pdata->irq_gpio); + return 0; +} + +static int fts_mmi_methods_get_drv_irq(struct device *dev, void *idata) +{ + struct fts_ts_data *ts_data; + + GET_TS_DATA(dev); + TO_INT(idata) = ts_data->irq_disabled ? 0 : 1; + return 0; +} + +static int fts_mmi_methods_get_poweron(struct device *dev, void *idata) +{ + struct fts_ts_data *ts_data; + struct input_dev *input_dev; + + GET_TS_DATA(dev); + input_dev = ts_data->input_dev; + + mutex_lock(&input_dev->mutex); + TO_INT(idata) = ts_data->power_disabled == false ? 1 : 0; + mutex_unlock(&input_dev->mutex); + + return 0; +} + +static int fts_mmi_methods_get_flashprog(struct device *dev, void *idata) +{ + struct fts_ts_data *ts_data; + + GET_TS_DATA(dev); + TO_INT(idata) = (ts_data->fw_loading) ? 1 : 0; + + return 0; +} + +static int fts_mmi_methods_drv_irq(struct device *dev, int state) +{ + struct fts_ts_data *ts_data; + struct input_dev *input_dev; + int ret = 0; + + GET_TS_DATA(dev); + input_dev = ts_data->input_dev; + + mutex_lock(&input_dev->mutex); + + if (state == 1) { + FTS_INFO("enable irq"); + fts_irq_enable(); + } else if (state == 0) { + FTS_INFO("disable irq"); + fts_irq_disable(); + } else { + dev_err(dev, "%s: invalid value\n", __func__); + ret = -EINVAL; + } + + mutex_unlock(&input_dev->mutex); + return ret; +} + +#if FTS_POWER_SOURCE_CUST_EN +static int fts_mmi_methods_power(struct device *dev, int state) +{ + struct fts_ts_data *ts_data; + + GET_TS_DATA(dev); + + return fts_power_source_ctrl(ts_data, state); +} +#endif + +static int fts_mmi_methods_reset(struct device *dev, int type) +{ + struct fts_ts_data *ts_data; + struct input_dev *input_dev; + + GET_TS_DATA(dev); + input_dev = ts_data->input_dev; + + mutex_lock(&input_dev->mutex); + fts_reset_proc(0); + mutex_unlock(&input_dev->mutex); + + return 0; +} + +static int fts_mmi_methods_pinctrl(struct device *dev, int on) +{ + struct fts_ts_data *ts_data; + struct input_dev *input_dev; + + GET_TS_DATA(dev); + input_dev = ts_data->input_dev; + + if (on == TS_MMI_PINCTL_ON) { + mutex_lock(&input_dev->mutex); + fts_reset_proc(150); + mutex_unlock(&input_dev->mutex); + } + + return 0; +} + +static int fts_mmi_firmware_update(struct device *dev, char *fwname) +{ + struct fts_ts_data *ts_data; + struct input_dev *input_dev; + + GET_TS_DATA(dev); + input_dev = ts_data->input_dev; + + ts_data->force_reflash = true; + + mutex_lock(&input_dev->mutex); + fts_fw_update_vendor_name(fwname); + fts_fwupg_bin(); + mutex_unlock(&input_dev->mutex); + + return 0; +} + +#if FTS_USB_DETECT_EN +static int fts_mmi_charger_mode(struct device *dev, int mode) +{ + struct fts_ts_data *ts_data; + + GET_TS_DATA(dev); + ts_data->usb_detect_flag = !!mode; + + return 0; +} +#endif + +static int fts_mmi_panel_state(struct device *dev, + enum ts_mmi_pm_mode from, enum ts_mmi_pm_mode to) +{ + struct fts_ts_platform_data *pdata; + struct fts_ts_data *ts_data; + int ret = 0; + + GET_TS_DATA(dev); + pdata = ts_data->pdata; + + switch (to) { + case TS_MMI_PM_DEEPSLEEP: + ret = fts_write_reg(FTS_REG_POWER_MODE, FTS_REG_POWER_MODE_SLEEP); + ts_data->gesture_mode = false; + if (ret < 0) + FTS_ERROR("set TP to sleep mode fail, ret=%d", ret); + break; + + case TS_MMI_PM_GESTURE: +#if FTS_GESTURE_EN + if (fts_gesture_suspend(ts_data) == 0) { + /* Enter into gesture mode(suspend) */ +#ifdef FOCALTECH_SENSOR_EN + ts_data->wakeable = true; + ts_data->gesture_mode = true; +#endif + } +#endif + break; + + case TS_MMI_PM_ACTIVE: + break; + default: + dev_warn(dev, "panel mode %d is invalid.\n", to); + ret = -EINVAL; + break; + } + + return ret; + +} + +static int fts_mmi_pre_resume(struct device *dev) +{ + struct fts_ts_data *ts_data; + + GET_TS_DATA(dev); + + FTS_FUNC_ENTER(); + + fts_release_all_finger(); + + FTS_FUNC_EXIT(); + return 0; +} + +static int fts_mmi_post_resume(struct device *dev) +{ + struct fts_ts_data *ts_data; + + GET_TS_DATA(dev); + +/* if (!ts_data->pdata->always_on_vio) { + FTS_INFO("Reset IC in resume"); + fts_reset_proc(200); + }*/ + + fts_tp_state_recovery(ts_data); + +#if FTS_ESDCHECK_EN + fts_esdcheck_resume(); +#endif + +#if FTS_GESTURE_EN +#ifdef FOCALTECH_SENSOR_EN + if (ts_data->wakeable) { +#endif + if (fts_gesture_resume(ts_data) == 0) { +#ifdef FOCALTECH_SENSOR_EN + ts_data->wakeable = false; + FTS_INFO("Exit from gesture suspend mode."); +#endif + goto exit; + } +#ifdef FOCALTECH_SENSOR_EN + } +#endif +#endif + +#if FTS_GESTURE_EN +exit: +#endif + FTS_FUNC_EXIT(); + ts_data->suspended = false; + + return 0; +} + +static int fts_mmi_pre_suspend(struct device *dev) +{ + struct fts_ts_data *ts_data; + + GET_TS_DATA(dev); + + FTS_FUNC_ENTER(); + +#if FTS_ESDCHECK_EN + FTS_INFO("fts_esdcheck_suspend"); + fts_esdcheck_suspend(); +#endif + + FTS_FUNC_EXIT(); + + return 0; +} + +static int fts_mmi_post_suspend(struct device *dev) +{ + struct fts_ts_data *ts_data; + + GET_TS_DATA(dev); + + FTS_FUNC_ENTER(); + +#ifdef FOCALTECH_SENSOR_EN + if (!ts_data->wakeable) { +#endif + fts_release_all_finger(); +#ifdef FOCALTECH_SENSOR_EN + } +#endif + + ts_data->suspended = true; + FTS_FUNC_EXIT(); + + return 0; +} + +#ifdef FOCALTECH_PALM_SENSOR_EN +int fts_mmi_palm_set_enable(struct device *dev, unsigned int enable) +{ + fts_palm_sensor_set_enable(enable); + return 0; +} +#endif + +static struct ts_mmi_methods fts_mmi_methods = { + .get_vendor = fts_mmi_methods_get_vendor, + .get_productinfo = fts_mmi_methods_get_productinfo, + .get_build_id = fts_mmi_methods_get_build_id, + .get_config_id = fts_mmi_methods_get_config_id, + .get_bus_type = fts_mmi_methods_get_bus_type, + .get_irq_status = fts_mmi_methods_get_irq_status, + .get_drv_irq = fts_mmi_methods_get_drv_irq, + .get_flashprog = fts_mmi_methods_get_flashprog, + .get_poweron = fts_mmi_methods_get_poweron, + /* SET methods */ + .reset = fts_mmi_methods_reset, + .pinctrl = fts_mmi_methods_pinctrl, + .drv_irq = fts_mmi_methods_drv_irq, +#if FTS_POWER_SOURCE_CUST_EN + .power = fts_mmi_methods_power, +#endif +#if FTS_USB_DETECT_EN + .charger_mode = fts_mmi_charger_mode, +#endif +#ifdef FOCALTECH_PALM_SENSOR_EN + .palm_set_enable = fts_mmi_palm_set_enable, +#endif + /* Firmware */ + .firmware_update = fts_mmi_firmware_update, + /* PM callback */ + .panel_state = fts_mmi_panel_state, + .pre_resume = fts_mmi_pre_resume, + .post_resume = fts_mmi_post_resume, + .pre_suspend = fts_mmi_pre_suspend, + .post_suspend = fts_mmi_post_suspend, + +}; + +int fts_mmi_dev_register(struct fts_ts_data *ts_data) { + int ret; + + ret = ts_mmi_dev_register(ts_data->dev, &fts_mmi_methods); + if (ret) { + dev_err(ts_data->dev, "Failed to register ts mmi\n"); + return ret; + } + + /* initialize class imported methods */ + ts_data->imports = &fts_mmi_methods.exports; + + return 0; +} + +void fts_mmi_dev_unregister(struct fts_ts_data *ts_data) { + ts_mmi_dev_unregister(ts_data->dev); +} +