input: goodix_v1510: enable single tap function

goodix_v1510:
Enable single tap function.

Change-Id: I783f8ca04efd73354f0b10c2e4e13add6721cc96
Signed-off-by: wangyq13 <wangyq13@lenovo.com>
Reviewed-on: https://gerrit.mot.com/2146428
SLTApproved: Slta Waiver
SME-Granted: SME Approvals Granted
Tested-by: Jira Key
Reviewed-by: Wei Deng <dengwei1@motorola.com>
Reviewed-by: Huosheng Liao <liaohs@motorola.com>
Submit-Approved: Jira Key
This commit is contained in:
wangyq13 2021-12-16 15:01:54 +08:00 • committed by Yeqing Wang
commit 28a097c665
8 changed files with 396 additions and 17 deletions

View file

@ -1,10 +1,18 @@
DLKM_DIR := motorola/kernel/modules
LOCAL_PATH := $(call my-dir)
ifeq ($(DRM_PANEL_NOTIFICATIONS),true)
KBUILD_OPTIONS += CONFIG_DRM_PANEL_NOTIFICATIONS=y
endif
include $(CLEAR_VARS)
LOCAL_MODULE := goodix_v1510_mmi.ko
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
LOCAL_ADDITIONAL_DEPENDENCIES += $(KERNEL_MODULES_OUT)/mmi_info.ko
ifneq ($(findstring touchscreen_mmi.ko,$(BOARD_VENDOR_KERNEL_MODULES)),)
KBUILD_OPTIONS += CONFIG_INPUT_TOUCHSCREEN_MMI=y
LOCAL_ADDITIONAL_DEPENDENCIES += $(KERNEL_MODULES_OUT)/touchscreen_mmi.ko
endif
KBUILD_OPTIONS_GKI += GKI_OBJ_MODULE_DIR=gki
include $(DLKM_DIR)/AndroidKernelModule.mk

View file

@ -4,6 +4,15 @@ EXTRA_CFLAGS += \
-I$(ANDROID_BUILD_TOP)/motorola/kernel/modules/include
obj-m := goodix_v1510_mmi.o
goodix_v1510_mmi-objs = goodix_ts_i2c.o goodix_ts_core.o goodix_ts_test.o goodix_cfg_bin.o goodix_gtx8_update.o
goodix_v1510_mmi-objs = goodix_ts_i2c.o goodix_ts_core.o goodix_ts_test.o goodix_cfg_bin.o goodix_gtx8_update.o goodix_ts_gesture.o
ifneq ($(filter m y,$(CONFIG_DRM_PANEL_NOTIFICATIONS)),)
EXTRA_CFLAGS += -DCONFIG_DRM_PANEL_NOTIFICATIONS
endif
ifneq ($(filter m y,$(CONFIG_INPUT_TOUCHSCREEN_MMI)),)
EXTRA_CFLAGS += -DCONFIG_INPUT_TOUCHSCREEN_MMI
goodix_v1510_mmi-objs += goodix_ts_mmi.o
endif
KBUILD_EXTRA_SYMBOLS += $(CURDIR)/$(KBUILD_EXTMOD)/../touchscreen_mmi/$(GKI_OBJ_MODULE_DIR)/Module.symvers
KBUILD_EXTRA_SYMBOLS += $(CURDIR)/$(KBUILD_EXTMOD)/../../../mmi_info/$(GKI_OBJ_MODULE_DIR)/Module.symvers

View file

@ -1,10 +1,17 @@
KERNEL_SRC ?= /lib/modules/$(shell uname -r)/build
all: modules
all:
$(MAKE) -C $(KERNEL_SRC) M=$(shell pwd) modules $(KBUILD_OPTIONS)
modules:
$(MAKE) -C $(KERNEL_SRC) M=$(M) modules $(KBUILD_OPTIONS)
modules_install:
$(MAKE) INSTALL_MOD_STRIP=1 -C $(KERNEL_SRC) M=$(shell pwd) modules_install
$(MAKE) INSTALL_MOD_STRIP=1 -C $(KERNEL_SRC) M=$(M) modules_install
%:
$(MAKE) -C $(KERNEL_SRC) M=$(M) $@ $(KBUILD_OPTIONS)
clean:
$(MAKE) -C $(KERNEL_SRC) M=$(PWD) clean
rm -f *.o *.ko *.mod.c *.mod.o *~ .*.cmd Module.symvers
rm -rf .tmp_versions
KBUILD_EXTRA_SYMBOLS += $(M)/../../../mmi_info/$(GKI_OBJ_MODULE_DIR)/Module.symvers
KBUILD_EXTRA_SYMBOLS += $(M)/../touchscreen_mmi/$(GKI_OBJ_MODULE_DIR)/Module.symvers

View file

@ -47,6 +47,10 @@ int goodix_start_later_init(struct goodix_ts_core *ts_core);
void goodix_ts_dev_release(void);
int goodix_fw_update_init(struct goodix_ts_core *core_data);
void goodix_fw_update_uninit(void);
extern int goodix_ts_mmi_dev_register(struct platform_device *ts_device);
extern void goodix_ts_mmi_dev_unregister(struct platform_device *ts_device);
extern int __init goodix_gsx_gesture_init(void);
extern void __exit goodix_gsx_gesture_exit(void);
struct goodix_module goodix_modules;
@ -2246,7 +2250,8 @@ static int goodix_ts_probe(struct platform_device *pdev)
return -ENODEV;
}
core_data = kzalloc(sizeof(struct goodix_ts_core), GFP_KERNEL);
core_data = devm_kzalloc(&pdev->dev, sizeof(struct goodix_ts_core),
GFP_KERNEL);
if (!core_data) {
ts_err("Failed to allocate memory for core data");
core_module_prob_sate = CORE_MODULE_PROB_FAILED;
@ -2304,6 +2309,22 @@ static int goodix_ts_probe(struct platform_device *pdev)
ts_err("failed init fwupdate module, %d", r);
goto gpio_err;
}
#ifdef CONFIG_INPUT_TOUCHSCREEN_MMI
ts_info("%s:goodix_ts_mmi_dev_register",__func__);
r = goodix_ts_mmi_dev_register(pdev);
if (r) {
ts_err("Failed register touchscreen mmi.");
goto fw_update_init_err;
}
#endif
r = goodix_gsx_gesture_init();
if (r) {
ts_err("Failed goodix_gsx_gesture_init.");
goto ts_mmi_dev_err;
}
/* Try start a thread to get config-bin info */
r = goodix_start_later_init(core_data);
if (r) {
@ -2313,8 +2334,13 @@ static int goodix_ts_probe(struct platform_device *pdev)
complete_all(&goodix_modules.core_comp);
ts_info("goodix_ts_core probe success");
return 0;
later_thread_err:
goodix_gsx_gesture_exit();
ts_mmi_dev_err:
#ifdef CONFIG_INPUT_TOUCHSCREEN_MMI
goodix_ts_mmi_dev_unregister(pdev);
fw_update_init_err:
#endif
goodix_fw_update_uninit();
gpio_err:
goodix_ts_power_off(core_data);

View file

@ -62,6 +62,7 @@
#define GOODIX_VID_MAX_LEN 8
#define GOODIX_DEFAULT_CFG_NAME "goodix_config.cfg"
#define GOODIX_TP_IC_TYPE "GTx8"
#define IC_TYPE_NONE 0
#define IC_TYPE_NORMANDY 1
@ -468,6 +469,8 @@ struct goodix_ts_core {
#elif defined(CONFIG_HAS_EARLYSUSPEND)
struct early_suspend early_suspend;
#endif
/* touchscreen_mmi */
struct ts_mmi_class_methods *imports;
};
/* external module structures */

View file

@ -26,6 +26,7 @@
#include <linux/delay.h>
#include <linux/atomic.h>
#include "goodix_ts_core.h"
#include <linux/touchscreen_mmi.h>
#define GSX_GESTURE_CMD 0x08
@ -345,6 +346,19 @@ static int gsx_gesture_ist(struct goodix_ts_core *core_data,
input_report_key(core_data->input_dev, KEY_POWER, 0);
input_sync(core_data->input_dev);
goto gesture_ist_exit;
#if defined(CONFIG_INPUT_TOUCHSCREEN_MMI)
} else if (gsx_type == 0x4C) {
if (core_data->imports && core_data->imports->report_gesture) {
struct gesture_event_data mmi_event;
ts_info("invoke imported report gesture function\n");
mmi_event.evcode = 1;
/* call class method */
ret = core_data->imports->report_gesture(&mmi_event);
goto gesture_ist_exit;
}
#endif
} else {
ts_info("Unsupported gesture:%x", temp_data[2]);
}
@ -387,6 +401,26 @@ static int gsx_gesture_before_suspend(struct goodix_ts_core *core_data,
return EVT_CANCEL_SUSPEND;
}
int gsx_gesture_before_suspend_mmi(struct goodix_ts_core *core_data)
{
int ret;
const struct goodix_ts_hw_ops *hw_ops = core_data->ts_dev->hw_ops;
if (!core_data->gesture_enable || !hw_ops)
return EVT_CONTINUE;
atomic_set(&core_data->suspended, 1);
ret = gsx_enter_gesture_mode(core_data->ts_dev);
if (ret != 0)
ts_err("failed enter gesture mode");
else
ts_err("Set IC in gesture mode");
enable_irq_wake(core_data->irq);
return EVT_CANCEL_SUSPEND;
}
static struct goodix_ext_module_funcs gsx_gesture_funcs = {
.irq_event = gsx_gesture_ist,
.init = gsx_gesture_init,
@ -394,7 +428,7 @@ static struct goodix_ext_module_funcs gsx_gesture_funcs = {
.before_suspend = gsx_gesture_before_suspend
};
static int __init goodix_gsx_gesture_init(void)
int __init goodix_gsx_gesture_init(void)
{
/* initialize core_data->ts_dev->gesture_cmd */
int result;
@ -416,7 +450,7 @@ static int __init goodix_gsx_gesture_init(void)
return result;
}
static void __exit goodix_gsx_gesture_exit(void)
void __exit goodix_gsx_gesture_exit(void)
{
int i, ret;
ts_info("gesture module exit");
@ -434,10 +468,3 @@ static void __exit goodix_gsx_gesture_exit(void)
kfree(gsx_gesture);
}
late_initcall(goodix_gsx_gesture_init);
module_exit(goodix_gsx_gesture_exit);
MODULE_DESCRIPTION("Goodix gsx Touchscreen Gesture Module");
MODULE_AUTHOR("Goodix, Inc.");
MODULE_LICENSE("GPL v2");

View file

@ -1922,6 +1922,8 @@ static int goodix_i2c_probe(struct i2c_client *client,
if (!goodix_pdev)
return -ENOMEM;
i2c_set_clientdata(client, goodix_pdev);
goodix_pdev->name = GOODIX_CORE_DRIVER_NAME;
goodix_pdev->id = 0;
goodix_pdev->num_resources = 0;
@ -1947,6 +1949,7 @@ static int goodix_i2c_probe(struct i2c_client *client,
err_pdev:
kfree(goodix_pdev);
goodix_pdev = NULL;
i2c_set_clientdata(client, NULL);
ts_info("i2c probe out, %d", r);
return r;
}

View file

@ -0,0 +1,296 @@
/*
* 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/touchscreen_mmi.h>
#include "goodix_ts_core.h"
#include <linux/delay.h>
#define GET_GOODIX_DATA(dev) { \
pdev = dev_get_drvdata(dev); \
if (!pdev) { \
ts_err("Failed to get platform device"); \
return -ENODEV; \
} \
core_data = platform_get_drvdata(pdev); \
if (!core_data) { \
ts_err("Failed to get driver data"); \
return -ENODEV; \
} \
}
extern int gsx_gesture_before_suspend_mmi(struct goodix_ts_core *core_data);
static int goodix_ts_mmi_methods_get_vendor(struct device *dev, void *cdata) {
return scnprintf(TO_CHARP(cdata), TS_MMI_MAX_VENDOR_LEN, "%s", "goodix");
}
static int goodix_ts_mmi_methods_get_productinfo(struct device *dev, void *cdata) {
return scnprintf(TO_CHARP(cdata), TS_MMI_MAX_INFO_LEN, "%s", GOODIX_TP_IC_TYPE);
}
static int goodix_ts_mmi_methods_get_build_id(struct device *dev, void *cdata) {
int ret;
struct goodix_ts_version fw_ver;
struct goodix_ts_device *ts_dev;
struct goodix_ts_core *core_data;
struct platform_device *pdev;
GET_GOODIX_DATA(dev);
ts_dev = core_data->ts_dev;
if (!ts_dev) {
ts_err("Failed to get platform data");
return -ENODEV;
}
ret = ts_dev->hw_ops->read_version(ts_dev, &fw_ver);
if (!ret && fw_ver.valid) {
ret = scnprintf(TO_CHARP(cdata), TS_MMI_MAX_ID_LEN, "%02x", fw_ver.vid[0]);
ts_info("get config id:%d ", fw_ver.vid[0]);
return ret;
} else
return -ENODEV;
}
/*return firmware version*/
static int goodix_ts_mmi_methods_get_config_id(struct device *dev, void *cdata) {
int ret;
struct goodix_ts_version fw_ver;
struct goodix_ts_device *ts_dev;
struct goodix_ts_core *core_data;
struct platform_device *pdev;
GET_GOODIX_DATA(dev);
ts_dev = core_data->ts_dev;
if (!ts_dev) {
ts_err("Failed to get platform data");
return -ENODEV;
}
ret = ts_dev->hw_ops->read_version(ts_dev, &fw_ver);
if (!ret && fw_ver.valid) {
ret = scnprintf(TO_CHARP(cdata), TS_MMI_MAX_ID_LEN, "%02x", fw_ver.vid[3]);
ts_info("get build id:%d ", fw_ver.vid[3]);
return ret;
} else
return -ENODEV;
}
static int goodix_ts_mmi_methods_get_bus_type(struct device *dev, void *idata) {
TO_INT(idata) = TOUCHSCREEN_MMI_BUS_TYPE_I2C;
return 0;
}
static int goodix_ts_mmi_methods_get_irq_status(struct device *dev, void *idata) {
struct goodix_ts_board_data *ts_bdata;
struct goodix_ts_core *core_data;
struct platform_device *pdev;
GET_GOODIX_DATA(dev);
ts_bdata = board_data(core_data);
if (!ts_bdata) {
ts_err("Failed to get ts board data");
return -ENODEV;
}
TO_INT(idata) = gpio_get_value(ts_bdata->irq_gpio);
return 0;
}
static int goodix_ts_mmi_methods_get_drv_irq(struct device *dev, void *idata) {
struct goodix_ts_core *core_data;
struct platform_device *pdev;
GET_GOODIX_DATA(dev);
TO_INT(idata) = atomic_read(&core_data->irq_enabled);
return 0;
}
static int goodix_ts_mmi_methods_get_poweron(struct device *dev, void *idata) {
struct goodix_ts_core *core_data;
struct platform_device *pdev;
GET_GOODIX_DATA(dev);
TO_INT(idata) = core_data->power_on;
return 0;
}
static int goodix_ts_mmi_methods_drv_irq(struct device *dev, int state) {
struct goodix_ts_core *core_data;
struct platform_device *pdev;
GET_GOODIX_DATA(dev);
goodix_ts_irq_enable(core_data, !(!state));
return 0;
}
/* reset chip
* type:can control software reset and hardware reset,
* but GOODIX has no software reset,
* so the type parameter is not used here.
*/
static int goodix_ts_mmi_methods_reset(struct device *dev, int type) {
int ret = -ENODEV;
struct goodix_ts_device *ts_dev;
struct goodix_ts_core *core_data;
struct platform_device *pdev;
GET_GOODIX_DATA(dev);
ts_dev = core_data->ts_dev;
if (ts_dev->hw_ops->reset)
ret = ts_dev->hw_ops->reset(ts_dev);
return ret;
}
static int goodix_ts_mmi_methods_power(struct device *dev, int on) {
struct goodix_ts_core *core_data;
struct platform_device *pdev;
GET_GOODIX_DATA(dev);
if (on == TS_MMI_POWER_ON)
return goodix_ts_power_on(core_data);
else if(on == TS_MMI_POWER_OFF)
return goodix_ts_power_off(core_data);
else {
ts_err("Invalid power parameter %d.\n", on);
return -EINVAL;
}
}
#define CHARGER_MODE_CMD 0xAF
static int goodix_ts_mmi_charger_mode(struct device *dev, int mode)
{
return 0;
}
static int goodix_ts_mmi_panel_state(struct device *dev,
enum ts_mmi_pm_mode from, enum ts_mmi_pm_mode to)
{
struct goodix_ts_device *ts_dev;
struct goodix_ts_core *core_data;
struct platform_device *pdev;
GET_GOODIX_DATA(dev);
ts_dev = core_data->ts_dev;
switch (to) {
case TS_MMI_PM_GESTURE:
gsx_gesture_before_suspend_mmi(core_data);
msleep(16);
enable_irq_wake(core_data->irq);
core_data->gesture_enable = true;
break;
case TS_MMI_PM_DEEPSLEEP:
/* enter sleep mode or power off */
if (ts_dev && ts_dev->hw_ops->suspend)
ts_dev->hw_ops->suspend(ts_dev);
core_data->gesture_enable = false;
break;
case TS_MMI_PM_ACTIVE:
if (ts_dev && ts_dev->hw_ops->resume)
ts_dev->hw_ops->resume(ts_dev);
core_data->gesture_enable = false;
break;
default:
ts_err("Invalid power state parameter %d.\n", to);
return -EINVAL;
}
return 0;
}
static int goodix_ts_mmi_pre_resume(struct device *dev)
{
struct goodix_ts_device *ts_dev;
struct goodix_ts_core *core_data;
struct platform_device *pdev;
GET_GOODIX_DATA(dev);
ts_dev = core_data->ts_dev;
atomic_set(&core_data->suspended, 0);
if (core_data->gesture_enable)
disable_irq_wake(core_data->irq);
return 0;
}
static int goodix_ts_mmi_post_resume(struct device *dev)
{
return 0;
}
static int goodix_ts_mmi_pre_suspend(struct device *dev)
{
struct goodix_ts_core *core_data;
struct platform_device *pdev;
GET_GOODIX_DATA(dev);
ts_info("Suspend start");
atomic_set(&core_data->suspended, 1);
return 0;
}
static int goodix_ts_mmi_post_suspend(struct device *dev)
{
ts_info("Suspend end");
return 0;
}
static struct ts_mmi_methods goodix_ts_mmi_methods = {
.get_vendor = goodix_ts_mmi_methods_get_vendor,
.get_productinfo = goodix_ts_mmi_methods_get_productinfo,
.get_build_id = goodix_ts_mmi_methods_get_build_id,
.get_config_id = goodix_ts_mmi_methods_get_config_id,
.get_bus_type = goodix_ts_mmi_methods_get_bus_type,
.get_irq_status = goodix_ts_mmi_methods_get_irq_status,
.get_drv_irq = goodix_ts_mmi_methods_get_drv_irq,
.get_poweron = goodix_ts_mmi_methods_get_poweron,
/* SET methods */
.reset = goodix_ts_mmi_methods_reset,
.drv_irq = goodix_ts_mmi_methods_drv_irq,
.power = goodix_ts_mmi_methods_power,
.charger_mode = goodix_ts_mmi_charger_mode,
/* PM callback */
.panel_state = goodix_ts_mmi_panel_state,
.pre_resume = goodix_ts_mmi_pre_resume,
.post_resume = goodix_ts_mmi_post_resume,
.pre_suspend = goodix_ts_mmi_pre_suspend,
.post_suspend = goodix_ts_mmi_post_suspend,
};
int goodix_ts_mmi_dev_register(struct platform_device *pdev) {
int ret;
struct goodix_ts_core *core_data;
core_data = platform_get_drvdata(pdev);
if (!core_data) {
ts_err("Failed to get driver data");
return -ENODEV;
}
ret = ts_mmi_dev_register(core_data->ts_dev->dev, &goodix_ts_mmi_methods);
if (ret) {
dev_err(&pdev->dev, "Failed to register ts mmi\n");
return ret;
}
core_data->imports = &goodix_ts_mmi_methods.exports;
return 0;
}
void goodix_ts_mmi_dev_unregister(struct platform_device *pdev) {
struct goodix_ts_core *core_data;
core_data = platform_get_drvdata(pdev);
if (!core_data)
ts_err("Failed to get driver data");
ts_mmi_dev_unregister(&pdev->dev);
}