Kiev: Add touchscreen class for focaltech

Access to focaltech touch driver through touchscreen class
unified interface.

NO_PROP_NEEDED: <Touch driver code is unified in bo branch>
Change-Id: I32874ac2cc55b7e6df6c01470d767963e2b45122
Reviewed-on: https://gerrit.mot.com/1664276
SLTApproved: Slta Waiver
SME-Granted: SME Approvals Granted
Tested-by: Jira Key
Reviewed-by: Jichao Zou <zoujc@motorola.com>
Reviewed-by: Jianqi Yang <yangj@motorola.com>
Submit-Approved: Jira Key
This commit is contained in:
litong 2020-07-06 16:13:11 +08:00 • committed by litong20
commit 49097bf12e
6 changed files with 435 additions and 1 deletions

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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__ */

View file

@ -1346,6 +1346,7 @@ static struct attribute_group fts_attribute_group = {
.attrs = fts_attributes
};
#ifndef CONFIG_INPUT_TOUCHSCREEN_MMI
#include <linux/major.h>
#include <linux/kdev_t.h>
@ -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;
}

View file

@ -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 <linux/gpio.h>
#include <linux/touchscreen_mmi.h>
#include <linux/regulator/consumer.h>
#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);
}