Register touchscreen class of synaptics

TP:
Access to synaptics touch through touchscreen unified interface

Change-Id: I353932ea46510a9f1d7357872238d073d1740ecc
Reviewed-on: https://gerrit.mot.com/1475154
SLTApproved: Slta Waiver
SME-Granted: SME Approvals Granted
Tested-by: Jira Key
Reviewed-by: Jialei Hao <haojl2@motorola.com>
Reviewed-by: Jianqi Yang <yangj@motorola.com>
Submit-Approved: Jira Key
This commit is contained in:
litong 2019-12-30 21:13:55 +08:00 • committed by litong20
commit 7a67d2b18b
8 changed files with 518 additions and 3 deletions

View file

@ -1,6 +1,10 @@
DLKM_DIR := motorola/kernel/modules
LOCAL_PATH := $(call my-dir)
ifneq ($(findstring touchscreen_mmi.ko,$(BOARD_VENDOR_KERNEL_MODULES)),)
KERNEL_CFLAGS += CONFIG_INPUT_TOUCHSCREEN_MMI=y
endif
ifeq ($(DLKM_INSTALL_TO_VENDOR_OUT),true)
SYNA_TCM_MODULE_PATH := $(TARGET_OUT_VENDOR)/lib/modules/
else

View file

@ -14,3 +14,7 @@ obj-m += synaptics_testing.o
obj-m += synaptics_zeroflash.o
synaptics_core_module-objs := synaptics_core.o synaptics_touch.o
ifneq ($(filter m y,$(CONFIG_INPUT_TOUCHSCREEN_MMI)),)
EXTRA_CFLAGS += -DCONFIG_INPUT_TOUCHSCREEN_MMI
synaptics_core_module-objs += synaptics_ts_mmi.o
endif

View file

@ -40,6 +40,11 @@
#include <linux/regulator/consumer.h>
#include "synaptics_core.h"
#ifdef CONFIG_INPUT_TOUCHSCREEN_MMI
extern int syna_ts_mmi_dev_register(struct syna_tcm_hcd *tcm_hcd);
extern void syna_ts_mmi_dev_unregister(struct syna_tcm_hcd *tcm_hcd);
#endif
/* #define RESET_ON_RESUME */
/* #define RESUME_EARLY_UNBLANK */
@ -3922,6 +3927,10 @@ prepare_modules:
mod_pool.queue_work = true;
queue_work(mod_pool.workqueue, &mod_pool.work);
#ifdef CONFIG_INPUT_TOUCHSCREEN_MMI
syna_ts_mmi_dev_register(tcm_hcd);
#endif
return 0;
err_enable_irq:
@ -4005,6 +4014,9 @@ static int syna_tcm_remove(struct platform_device *pdev)
struct syna_tcm_hcd *tcm_hcd = platform_get_drvdata(pdev);
const struct syna_tcm_board_data *bdata = tcm_hcd->hw_if->bdata;
#ifdef CONFIG_INPUT_TOUCHSCREEN_MMI
syna_ts_mmi_dev_unregister(tcm_hcd);
#endif
touch_remove(tcm_hcd);
mutex_lock(&mod_pool.mutex);

View file

@ -516,6 +516,9 @@ struct syna_tcm_hcd {
struct syna_tcm_buffer *output);
void (*report_touch)(void);
void (*update_watchdog)(struct syna_tcm_hcd *tcm_hcd, bool en);
int (*do_fw_update)(void);
int (*set_fw_name)(const char* fw_name);
};
struct syna_tcm_module_cb {

View file

@ -430,6 +430,8 @@ static int syna_tcm_i2c_probe(struct i2c_client *i2c,
return -ENOMEM;
}
i2c_set_clientdata(i2c, syna_tcm_i2c_device);
#ifdef CONFIG_OF
hw_if.bdata = devm_kzalloc(&i2c->dev, sizeof(*hw_if.bdata), GFP_KERNEL);
if (!hw_if.bdata) {

View file

@ -1178,7 +1178,7 @@ static int recovery_init(struct syna_tcm_hcd *tcm_hcd)
return -ENOMEM;
}
recovery_hcd->ihex_buf = vmalloc(IHEX_BUF_SIZE);
recovery_hcd->ihex_buf = vzalloc(IHEX_BUF_SIZE);
if (!recovery_hcd->ihex_buf) {
LOGE(tcm_hcd->pdev->dev.parent,
"Failed to allocate memory for recovery_hcd->ihex_buf\n");

View file

@ -198,6 +198,7 @@ struct reflash_hcd {
struct syna_tcm_buffer resp;
struct syna_tcm_buffer read;
struct syna_tcm_hcd *tcm_hcd;
char fw_name[64];
};
DECLARE_COMPLETION(reflash_remove_complete);
@ -310,6 +311,34 @@ static struct bin_attribute bin_attrs[] = {
},
};
static int syna_ts_set_fwname(const char* fw_name) {
if (fw_name != NULL) {
strlcpy(reflash_hcd->fw_name, fw_name,
sizeof(reflash_hcd->fw_name));
return 0;
}
LOGI(reflash_hcd->tcm_hcd->pdev->dev.parent,
"set fw name = %s", reflash_hcd->fw_name);
return -EINVAL;
}
static int syna_ts_do_reflash(void)
{
int retval;
struct syna_tcm_hcd *tcm_hcd = reflash_hcd->tcm_hcd;
mutex_lock(&reflash_hcd->reflash_mutex);
reflash_hcd->force_update = true;
retval = reflash_do_reflash();
if (retval < 0) {
LOGE(tcm_hcd->pdev->dev.parent, "Failed to do reflash\n");
}
reflash_hcd->force_update = FORCE_REFLASH;
mutex_unlock(&reflash_hcd->reflash_mutex);
return retval;
}
static ssize_t reflash_sysfs_reflash_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
@ -860,8 +889,16 @@ static int reflash_get_fw_image(void)
struct syna_tcm_hcd *tcm_hcd = reflash_hcd->tcm_hcd;
if (reflash_hcd->image == NULL) {
if (reflash_hcd->reflash_by_manual == false) {
if (reflash_hcd->fw_name[0] != 0) {
LOGN(tcm_hcd->pdev->dev.parent, "Request firmware %s\n", reflash_hcd->fw_name);
retval = request_firmware(&reflash_hcd->fw_entry,
reflash_hcd->fw_name, tcm_hcd->pdev->dev.parent);
if (retval < 0) {
LOGE(tcm_hcd->pdev->dev.parent, "Failed to request %s\n", reflash_hcd->fw_name);
return retval;
}
} else if (reflash_hcd->reflash_by_manual == false) {
retval = request_firmware(&reflash_hcd->fw_entry,
FW_IMAGE_NAME, tcm_hcd->pdev->dev.parent);
if (retval < 0) {
@ -2388,7 +2425,7 @@ static int reflash_init(struct syna_tcm_hcd *tcm_hcd)
if (tcm_hcd->in_hdl_mode)
return 0;
reflash_hcd = vmalloc(sizeof(*reflash_hcd));
reflash_hcd = vzalloc(sizeof(*reflash_hcd));
if (!reflash_hcd) {
LOGE(tcm_hcd->pdev->dev.parent,
"Failed to allocate memory for reflash_hcd\n");
@ -2405,6 +2442,8 @@ static int reflash_init(struct syna_tcm_hcd *tcm_hcd)
reflash_hcd->tcm_hcd = tcm_hcd;
reflash_hcd->force_update = FORCE_REFLASH;
tcm_hcd->set_fw_name = syna_ts_set_fwname;
tcm_hcd->do_fw_update = syna_ts_do_reflash;
mutex_init(&reflash_hcd->reflash_mutex);

View file

@ -0,0 +1,451 @@
/*
* 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 "synaptics_core.h"
static int syna_ts_mmi_methods_get_vendor(struct device *dev, void *cdata)
{
return scnprintf(TO_CHARP(cdata), TS_MMI_MAX_VENDOR_LEN, "%s", "synaptics");
}
static int syna_ts_mmi_methods_get_productinfo(struct device *dev, void *cdata)
{
struct syna_tcm_hcd *tcm_hcd;
struct platform_device *pdev = dev_get_drvdata(dev);
if (!pdev) {
LOGE(dev, "Failed to get platform device");
return -ENODEV;
}
tcm_hcd = platform_get_drvdata(pdev);
if (!tcm_hcd) {
LOGE(dev, "Failed to get driver data");
return -ENODEV;
}
return scnprintf(TO_CHARP(cdata), 6, "%s", tcm_hcd->id_info.part_number);
}
static int syna_ts_mmi_methods_get_config_id(struct device *dev, void *cdata)
{
struct syna_tcm_hcd *tcm_hcd;
struct platform_device *pdev = dev_get_drvdata(dev);
unsigned int buildid;
if (!pdev) {
LOGE(dev, "Failed to get platform device");
return -ENODEV;
}
tcm_hcd = platform_get_drvdata(pdev);
if (!tcm_hcd) {
LOGE(dev, "Failed to get driver data");
return -ENODEV;
}
buildid = tcm_hcd->packrat_number;
return scnprintf(TO_CHARP(cdata), TS_MMI_MAX_ID_LEN, "%d", buildid);
}
/*return firmware version*/
static int syna_ts_mmi_methods_get_build_id(struct device *dev, void *cdata)
{
struct syna_tcm_hcd *tcm_hcd;
struct platform_device *pdev = dev_get_drvdata(dev);
if (!pdev) {
LOGE(dev, "Failed to get platform device");
return -ENODEV;
}
tcm_hcd = platform_get_drvdata(pdev);
if (!tcm_hcd) {
LOGE(dev, "Failed to get driver data");
return -ENODEV;
}
return scnprintf(TO_CHARP(cdata), TS_MMI_MAX_ID_LEN, "%s", tcm_hcd->app_info.customer_config_id);
}
static int syna_ts_mmi_methods_get_bus_type(struct device *dev, void *idata)
{
const struct syna_tcm_hw_interface *hw_if;
struct syna_tcm_hcd *tcm_hcd;
struct platform_device *pdev = dev_get_drvdata(dev);
if (!pdev) {
LOGE(dev, "Failed to get platform device");
return -ENODEV;
}
tcm_hcd = platform_get_drvdata(pdev);
if (!tcm_hcd) {
LOGE(dev, "Failed to get driver data");
return -ENODEV;
}
hw_if = tcm_hcd->hw_if;
if (!hw_if) {
LOGE(dev, "Hardware interface not found\n");
return -ENODEV;
}
TO_INT(idata) = hw_if->bus_io->type;
return 0;
}
static int syna_ts_mmi_methods_get_irq_status(struct device *dev, void *idata)
{
const struct syna_tcm_hw_interface *hw_if;
struct syna_tcm_board_data *bdata;
struct syna_tcm_hcd *tcm_hcd;
struct platform_device *pdev = dev_get_drvdata(dev);
if (!pdev) {
LOGE(dev, "Failed to get platform device");
return -ENODEV;
}
tcm_hcd = platform_get_drvdata(pdev);
if (!tcm_hcd) {
LOGE(dev, "Failed to get driver data");
return -ENODEV;
}
hw_if = tcm_hcd->hw_if;
if (!hw_if) {
LOGE(dev, "Hardware interface not found\n");
return -ENODEV;
}
bdata = hw_if->bdata;
if (!bdata) {
LOGE(dev, "Failed to get ts board data");
return -ENODEV;
}
TO_INT(idata) = gpio_get_value(bdata->irq_gpio);
return 0;
}
static int syna_ts_mmi_methods_get_drv_irq(struct device *dev, void *idata)
{
struct syna_tcm_board_data *bdata;
struct syna_tcm_hcd *tcm_hcd;
struct platform_device *pdev = dev_get_drvdata(dev);
if (!pdev) {
LOGE(dev, "Failed to get platform device");
return -ENODEV;
}
tcm_hcd = platform_get_drvdata(pdev);
if (!tcm_hcd) {
LOGE(dev, "Failed to get driver data");
return -ENODEV;
}
bdata = tcm_hcd->hw_if->bdata;
if (!bdata) {
LOGE(dev, "Failed to get ts board data");
return -ENODEV;
}
TO_INT(idata) = tcm_hcd->irq_enabled ? 1 : 0;
return 0;
}
static int syna_ts_mmi_methods_get_poweron(struct device *dev, void *idata)
{
struct syna_tcm_hcd *tcm_hcd;
struct platform_device *pdev = dev_get_drvdata(dev);
if (!pdev) {
LOGE(dev, "Failed to get platform device");
return -ENODEV;
}
tcm_hcd = platform_get_drvdata(pdev);
if (!tcm_hcd) {
LOGE(dev, "Failed to get driver data");
return -ENODEV;
}
TO_INT(idata) = tcm_hcd->in_suspend == 0 ? 1 : 0;
return 0;
}
static int syna_ts_mmi_methods_get_flashprog(struct device *dev, void *idata)
{
struct syna_tcm_hcd *tcm_hcd;
struct platform_device *pdev = dev_get_drvdata(dev);
if (!pdev) {
LOGE(dev, "Failed to get platform device");
return -ENODEV;
}
tcm_hcd = platform_get_drvdata(pdev);
if (!tcm_hcd) {
LOGE(dev, "Failed to get driver data");
return -ENODEV;
}
if (IS_NOT_FW_MODE(tcm_hcd->id_info.mode) ||
tcm_hcd->app_status != APP_STATUS_OK)
TO_INT(idata) = 1;
else
TO_INT(idata) = 0;
return 0;
}
static int syna_ts_mmi_methods_drv_irq(struct device *dev, int state)
{
int retval;
struct syna_tcm_hcd *tcm_hcd;
struct platform_device *pdev = dev_get_drvdata(dev);
if (!pdev) {
LOGE(dev, "Failed to get platform device");
return -ENODEV;
}
tcm_hcd = platform_get_drvdata(pdev);
if (!tcm_hcd) {
LOGE(dev, "Failed to get driver data");
return -ENODEV;
}
mutex_lock(&tcm_hcd->extif_mutex);
if (state == 0) {
retval = tcm_hcd->enable_irq(tcm_hcd, false, true);
if (retval < 0) {
LOGE(tcm_hcd->pdev->dev.parent,
"Failed to disable interrupt\n");
goto exit;
}
} else if (state == 1) {
retval = tcm_hcd->enable_irq(tcm_hcd, true, NULL);
if (retval < 0) {
LOGE(tcm_hcd->pdev->dev.parent,
"Failed to enable interrupt\n");
goto exit;
}
} else {
retval = -EINVAL;
goto exit;
}
exit:
mutex_unlock(&tcm_hcd->extif_mutex);
return retval;
}
static int syna_ts_mmi_methods_reset(struct device *dev, int type)
{
bool hw_reset = !!type;
struct syna_tcm_hcd *tcm_hcd;
struct platform_device *pdev = dev_get_drvdata(dev);
if (!pdev) {
LOGE(dev, "Failed to get platform device");
return -ENODEV;
}
tcm_hcd = platform_get_drvdata(pdev);
if (!tcm_hcd) {
LOGE(dev, "Failed to get driver data");
return -ENODEV;
}
if (tcm_hcd->reset)
return tcm_hcd->reset_n_reinit(tcm_hcd, hw_reset, true);
return -EFAULT;
}
static int syna_ts_firmware_update(struct device *dev, char *fwname) {
struct syna_tcm_hcd *tcm_hcd;
struct platform_device *pdev = dev_get_drvdata(dev);
if (!pdev) {
LOGE(dev, "Failed to get platform device");
return -ENODEV;
}
tcm_hcd = platform_get_drvdata(pdev);
if (!tcm_hcd) {
LOGE(dev, "Failed to get driver data");
return -ENODEV;
}
LOGI(dev, "HW request update fw");
/* set firmware image name */
if (tcm_hcd->set_fw_name)
tcm_hcd->set_fw_name(fwname);
else {
LOGE(dev, "fw update handler not ready, can't set fw_name");
return -EFAULT;
}
if (tcm_hcd->do_fw_update) {
tcm_hcd->do_fw_update();
} else {
LOGE(dev, "fw update handler not ready.");
return -EFAULT;
}
return 0;
}
static int syna_ts_mmi_methods_power(struct device *dev, int on)
{
int retval;
const struct syna_tcm_board_data *bdata;
struct syna_tcm_hcd *tcm_hcd;
struct platform_device *pdev = dev_get_drvdata(dev);
if (!pdev) {
LOGE(dev, "Failed to get platform device");
return -ENODEV;
}
tcm_hcd = platform_get_drvdata(pdev);
if (!tcm_hcd) {
LOGE(dev, "Failed to get driver data");
return -ENODEV;
}
bdata = tcm_hcd->hw_if->bdata;
if (!bdata) {
LOGE(dev, "Failed to get ts board data");
return -ENODEV;
}
if (!on) {
retval = 0;
goto disable_pwr_reg;
}
if (tcm_hcd->bus_reg) {
retval = regulator_enable(tcm_hcd->bus_reg);
if (retval < 0) {
LOGE(dev, "Failed to enable bus regulator\n");
goto exit;
}
}
if (tcm_hcd->pwr_reg) {
retval = regulator_enable(tcm_hcd->pwr_reg);
if (retval < 0) {
LOGE(dev, "Failed to enable power regulator\n");
goto disable_bus_reg;
}
msleep(bdata->power_delay_ms);
}
return 0;
disable_pwr_reg:
if (tcm_hcd->pwr_reg)
regulator_disable(tcm_hcd->pwr_reg);
disable_bus_reg:
if (tcm_hcd->bus_reg)
regulator_disable(tcm_hcd->bus_reg);
exit:
return retval;
}
static int syna_ts_mmi_pre_resume(struct device *dev)
{
int retval;
struct syna_tcm_hcd *tcm_hcd;
struct platform_device *pdev = dev_get_drvdata(dev);
if (!pdev) {
LOGE(dev, "Failed to get platform device");
return -ENODEV;
}
tcm_hcd = platform_get_drvdata(pdev);
if (!tcm_hcd) {
LOGE(dev, "Failed to get driver data");
return -ENODEV;
}
if (!tcm_hcd->in_suspend)
return 0;
retval = tcm_hcd->sleep(tcm_hcd, false);
if (retval < 0) {
LOGE(tcm_hcd->pdev->dev.parent,
"Failed to exit deep sleep\n");
goto exit;
}
touch_resume(tcm_hcd);
retval = 0;
exit:
tcm_hcd->in_suspend = false;
return retval;
}
static int syna_ts_mmi_post_suspend(struct device *dev)
{
struct syna_tcm_hcd *tcm_hcd;
struct platform_device *pdev = dev_get_drvdata(dev);
if (!pdev) {
LOGE(dev, "Failed to get platform device");
return -ENODEV;
}
tcm_hcd = platform_get_drvdata(pdev);
if (!tcm_hcd) {
LOGE(dev, "Failed to get driver data");
return -ENODEV;
}
if (tcm_hcd->in_suspend)
return 0;
touch_suspend(tcm_hcd);
tcm_hcd->in_suspend = true;
return 0;
}
static int syna_ts_mmi_pre_suspend(struct device *dev)
{
struct syna_tcm_hcd *tcm_hcd;
struct platform_device *pdev = dev_get_drvdata(dev);
if (!pdev) {
LOGE(dev, "Failed to get platform device");
return -ENODEV;
}
tcm_hcd = platform_get_drvdata(pdev);
if (!tcm_hcd) {
LOGE(dev, "Failed to get driver data");
return -ENODEV;
}
if (tcm_hcd->in_suspend)
return 0;
touch_early_suspend(tcm_hcd);
return 0;
}
static struct ts_mmi_methods syna_ts_mmi_methods = {
.get_vendor = syna_ts_mmi_methods_get_vendor,
.get_productinfo = syna_ts_mmi_methods_get_productinfo,
.get_build_id = syna_ts_mmi_methods_get_build_id,
.get_config_id = syna_ts_mmi_methods_get_config_id,
.get_bus_type = syna_ts_mmi_methods_get_bus_type,
.get_irq_status = syna_ts_mmi_methods_get_irq_status,
.get_drv_irq = syna_ts_mmi_methods_get_drv_irq,
.get_flashprog = syna_ts_mmi_methods_get_flashprog,
.get_poweron = syna_ts_mmi_methods_get_poweron,
/* SET methods */
.reset = syna_ts_mmi_methods_reset,
.drv_irq = syna_ts_mmi_methods_drv_irq,
.power = syna_ts_mmi_methods_power,
/* Firmware */
.firmware_update = syna_ts_firmware_update,
/* PM callback */
.pre_resume = syna_ts_mmi_pre_resume,
.pre_suspend = syna_ts_mmi_pre_suspend,
.post_suspend = syna_ts_mmi_post_suspend,
};
int syna_ts_mmi_dev_register(struct syna_tcm_hcd *tcm_hcd) {
int ret;
ret = ts_mmi_dev_register(tcm_hcd->pdev->dev.parent, &syna_ts_mmi_methods);
if (ret) {
dev_err(tcm_hcd->pdev->dev.parent, "Failed to register ts mmi\n");
return ret;
}
return 0;
}
void syna_ts_mmi_dev_unregister(struct syna_tcm_hcd *tcm_hcd) {
ts_mmi_dev_unregister(tcm_hcd->pdev->dev.parent);
}