diff --git a/drivers/input/touchscreen/focaltech_0flash_mmi/Android.mk b/drivers/input/touchscreen/focaltech_0flash_mmi/Android.mk index f4a2244e17d0..b6ee6ac93b00 100644 --- a/drivers/input/touchscreen/focaltech_0flash_mmi/Android.mk +++ b/drivers/input/touchscreen/focaltech_0flash_mmi/Android.mk @@ -19,6 +19,10 @@ ifneq ($(BOARD_USES_PEN_NOTIFIER),) KERNEL_CFLAGS += CONFIG_INPUT_FOCALTECH_0FLASH_MMI_PEN_NOTIFIER=y endif +ifneq ($(findstring touchscreen_mmi.ko,$(BOARD_VENDOR_KERNEL_MODULES)),) + KERNEL_CFLAGS += CONFIG_INPUT_TOUCHSCREEN_MMI=y +endif + include $(CLEAR_VARS) LOCAL_MODULE := focaltech_0flash_mmi.ko LOCAL_MODULE_TAGS := optional diff --git a/drivers/input/touchscreen/focaltech_0flash_mmi/Kbuild b/drivers/input/touchscreen/focaltech_0flash_mmi/Kbuild index c0439bdc253e..8d3103c00771 100644 --- a/drivers/input/touchscreen/focaltech_0flash_mmi/Kbuild +++ b/drivers/input/touchscreen/focaltech_0flash_mmi/Kbuild @@ -40,6 +40,10 @@ ifneq ($(filter ft8009,$(CONFIG_INPUT_FOCALTECH_0FLASH_MMI_IC_NAME)),) focaltech_0flash_mmi-objs += focaltech_flash_ft8756.o focaltech_0flash_mmi-objs += focaltech_spi_v1_1_1.o endif +ifneq ($(filter m y,$(CONFIG_INPUT_TOUCHSCREEN_MMI)),) + EXTRA_CFLAGS += -DCONFIG_INPUT_TOUCHSCREEN_MMI + focaltech_0flash_mmi-objs += focaltech_ts_mmi.o +endif ifneq ($(filter m y,$(CONFIG_INPUT_FOCALTECH_0FLASH_MMI_ENABLE_DOUBLE_TAP)),) EXTRA_CFLAGS += -DFOCALTECH_SENSOR_EN endif diff --git a/drivers/input/touchscreen/focaltech_0flash_mmi/focaltech_core.c b/drivers/input/touchscreen/focaltech_0flash_mmi/focaltech_core.c index d6ec05a7b41c..7cad522eb86c 100755 --- a/drivers/input/touchscreen/focaltech_0flash_mmi/focaltech_core.c +++ b/drivers/input/touchscreen/focaltech_0flash_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 *****************************************************************************/ @@ -1259,7 +1264,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; @@ -1993,6 +1998,10 @@ static int fts_ts_probe_entry(struct fts_ts_data *ts_data) } #endif +#ifdef CONFIG_INPUT_TOUCHSCREEN_MMI + fts_mmi_dev_register(ts_data); +#endif + FTS_FUNC_EXIT(); return 0; @@ -2032,6 +2041,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_USB_DETECT_EN if (ts_data->charger_notif.notifier_call) power_supply_unreg_notifier(&ts_data->charger_notif); diff --git a/drivers/input/touchscreen/focaltech_0flash_mmi/focaltech_core.h b/drivers/input/touchscreen/focaltech_0flash_mmi/focaltech_core.h index afec1babf6e3..3f70c540151d 100755 --- a/drivers/input/touchscreen/focaltech_0flash_mmi/focaltech_core.h +++ b/drivers/input/touchscreen/focaltech_0flash_mmi/focaltech_core.h @@ -348,4 +348,6 @@ 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_0flash_mmi/focaltech_ex_fun.c b/drivers/input/touchscreen/focaltech_0flash_mmi/focaltech_ex_fun.c index b7196be90c69..d593be6e3a9b 100755 --- a/drivers/input/touchscreen/focaltech_0flash_mmi/focaltech_ex_fun.c +++ b/drivers/input/touchscreen/focaltech_0flash_mmi/focaltech_ex_fun.c @@ -1346,6 +1346,7 @@ static struct attribute_group fts_attribute_group = { .attrs = fts_attributes }; +#ifndef CONFIG_INPUT_TOUCHSCREEN_MMI #include #include @@ -1379,10 +1380,12 @@ static struct device_attribute touchscreen_attributes[] = { __ATTR_RO(vendor), __ATTR_NULL }; +#endif #define TSDEV_MINOR_BASE 128 #define TSDEV_MINOR_MAX 32 +#ifndef CONFIG_INPUT_TOUCHSCREEN_MMI static int fts_sysfs_class(void *_data, bool create) { struct fts_ts_data *data = _data; @@ -1447,6 +1450,7 @@ device_destroy: return -ENODEV; } +#endif int fts_create_sysfs(struct fts_ts_data *ts_data) { @@ -1458,6 +1462,7 @@ int fts_create_sysfs(struct fts_ts_data *ts_data) sysfs_remove_group(&ts_data->dev->kobj, &fts_attribute_group); return -ENOMEM; } +#ifndef CONFIG_INPUT_TOUCHSCREEN_MMI ret = fts_sysfs_class(ts_data, true); if (ret) { FTS_ERROR("[EX]: fts_sysfs_class() failed!!"); @@ -1465,6 +1470,7 @@ int fts_create_sysfs(struct fts_ts_data *ts_data) return -ENOMEM; } FTS_INFO("[EX]: sysfs_create_group() succeeded!!"); +#endif return ret; } @@ -1472,6 +1478,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 fts_sysfs_class(ts_data, false); +#endif return 0; } diff --git a/drivers/input/touchscreen/focaltech_0flash_mmi/focaltech_ts_mmi.c b/drivers/input/touchscreen/focaltech_0flash_mmi/focaltech_ts_mmi.c new file mode 100644 index 000000000000..af6aa77e46f5 --- /dev/null +++ b/drivers/input/touchscreen/focaltech_0flash_mmi/focaltech_ts_mmi.c @@ -0,0 +1,403 @@ +/* + * 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_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_fw_recovery(); + mutex_unlock(&input_dev->mutex); + + return 0; +} + +static int fts_mmi_panel_state(struct device *dev, + enum ts_mmi_pm_mode from, enum ts_mmi_pm_mode to) +{ + struct fts_ts_data *ts_data; + int ret = 0; + + GET_TS_DATA(dev); + +#ifdef FOCALTECH_SENSOR_EN + mutex_lock(&ts_data->state_mutex); +#endif + + switch (to) { + case TS_MMI_PM_DEEPSLEEP: + ret = fts_write_reg(FTS_REG_POWER_MODE, FTS_REG_POWER_MODE_SLEEP_VALUE); + if (ret < 0) + FTS_ERROR("set TP to sleep mode fail, ret=%d", ret); + + /* TP delay 50ms then lcd entery suspend*/ + mdelay(50); + 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; +#endif + } +#endif + break; + + case TS_MMI_PM_ACTIVE: + break; + default: + dev_warn(dev, "panel mode %d is invalid.\n", to); + ret = -EINVAL; + break; + } + +#ifdef FOCALTECH_SENSOR_EN + mutex_unlock(&ts_data->state_mutex); +#endif + return ret; + +} + +static int fts_mmi_pre_resume(struct device *dev) +{ + struct fts_ts_data *ts_data; + + GET_TS_DATA(dev); + +#ifdef FOCALTECH_SENSOR_EN + mutex_lock(&ts_data->state_mutex); +#endif + + FTS_FUNC_ENTER(); + + fts_release_all_finger(); + + FTS_FUNC_EXIT(); +#ifdef FOCALTECH_SENSOR_EN + mutex_unlock(&ts_data->state_mutex); +#endif + return 0; +} + +static int fts_mmi_post_resume(struct device *dev) +{ + struct fts_ts_data *ts_data; + + GET_TS_DATA(dev); + +#ifdef FOCALTECH_SENSOR_EN + mutex_lock(&ts_data->state_mutex); +#endif + 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 + +exit: + FTS_FUNC_EXIT(); + ts_data->suspended = false; +#ifdef FOCALTECH_SENSOR_EN + mutex_unlock(&ts_data->state_mutex); + ts_data->screen_state = SCREEN_ON; +#endif + return 0; +} + +static int fts_mmi_pre_suspend(struct device *dev) +{ + struct fts_ts_data *ts_data; + + GET_TS_DATA(dev); +#ifdef FOCALTECH_SENSOR_EN + mutex_lock(&ts_data->state_mutex); +#endif + FTS_FUNC_ENTER(); + +#if FTS_ESDCHECK_EN + FTS_INFO("fts_esdcheck_suspend"); + fts_esdcheck_suspend(); +#endif + + FTS_FUNC_EXIT(); +#ifdef FOCALTECH_SENSOR_EN + mutex_unlock(&ts_data->state_mutex); +#endif + return 0; +} + +static int fts_mmi_post_suspend(struct device *dev) +{ + struct fts_ts_data *ts_data; + + GET_TS_DATA(dev); + +#ifdef FOCALTECH_SENSOR_EN + mutex_lock(&ts_data->state_mutex); +#endif + FTS_FUNC_ENTER(); + +#ifdef FOCALTECH_SENSOR_EN + if (!ts_data->wakeable) { +#endif + if (!ts_data->pdata->always_on_vio) { + FTS_INFO("Set reset pin to 0 in suspend."); + gpio_direction_output(ts_data->pdata->reset_gpio, 0); + } + fts_release_all_finger(); + } + + ts_data->suspended = true; + FTS_FUNC_EXIT(); +#ifdef FOCALTECH_SENSOR_EN + ts_data->screen_state = SCREEN_OFF; + mutex_unlock(&ts_data->state_mutex); +#endif + return 0; +} + +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, + .drv_irq = fts_mmi_methods_drv_irq, +#if FTS_POWER_SOURCE_CUST_EN + .power = fts_mmi_methods_power, +#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; + } + + return 0; +} + +void fts_mmi_dev_unregister(struct fts_ts_data *ts_data) { + ts_mmi_dev_unregister(ts_data->dev); +} +