fogor: kernel: 2nd tongxingda ili9883c TP bringup

1. add 2nd ili9883c TP code
2. add TP build.

Change-Id: Iee5821d2b5f92be73c5184d5ac386afd559673e7
Signed-off-by: ontim52 <ontim52@motorola.com>
Reviewed-on: https://gerrit.mot.com/2647002
SME-Granted: SME Approvals Granted
SLTApproved: Slta Waiver
Tested-by: Jira Key
Reviewed-by: Jun Weng <wengjun1@motorola.com>
Reviewed-by: Huosheng Liao <liaohs@motorola.com>
Submit-Approved: Jira Key
This commit is contained in:
ontim52 2023-06-17 18:41:49 +08:00
commit d905a5eaca
21 changed files with 32137 additions and 0 deletions

View file

@ -22,6 +22,10 @@ ifneq ($(MOTO_PANEL_CHECK_TOUCH_STATE),)
KERNEL_CFLAGS += CONFIG_INPUT_CHIPONE_0FLASH_MMI_NOTIFY_TOUCH_STATE=y
endif
ifneq ($(findstring touchscreen_mmi.ko,$(BOARD_VENDOR_KERNEL_MODULES)),)
KBUILD_OPTIONS += CONFIG_INPUT_TOUCHSCREEN_MMI=y
endif
include $(CLEAR_VARS)
ifneq ($(BOARD_USES_DOUBLE_TAP),)
LOCAL_ADDITIONAL_DEPENDENCIES += $(KERNEL_MODULES_OUT)/sensors_class.ko
@ -29,4 +33,8 @@ endif
LOCAL_MODULE := chipone_tddi_v2_mmi.ko
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(CHIPONE_MMI_MODULE_PATH)
LOCAL_ADDITIONAL_DEPENDENCIES += $(KERNEL_MODULES_OUT)/mmi_info.ko
ifneq ($(findstring touchscreen_mmi.ko,$(BOARD_VENDOR_KERNEL_MODULES)),)
LOCAL_ADDITIONAL_DEPENDENCIES += $(KERNEL_MODULES_OUT)/touchscreen_mmi.ko
endif
include $(DLKM_DIR)/AndroidKernelModule.mk

View file

@ -21,6 +21,10 @@ ifneq ($(filter m y,$(CONFIG_INPUT_CHIPONE_PANEL_NOTIFICATIONS)),)
EXTRA_CFLAGS += -DCHIPONE_CONFIG_PANEL_NOTIFICATIONS
endif
ifneq ($(filter m y,$(CONFIG_INPUT_TOUCHSCREEN_MMI)),)
EXTRA_CFLAGS += -DCONFIG_INPUT_TOUCHSCREEN_MMI
endif
#obj-$(CONFIG_TOUCHSCREEN_CHIPONE) += chipone-tddi.o
obj-m += chipone_tddi_v2_mmi.o
@ -38,3 +42,5 @@ chipone_tddi_v2_mmi-objs += cts_tool.o
chipone_tddi_v2_mmi-objs += cts_sysfs.o
chipone_tddi_v2_mmi-objs += cts_strerror.o
chipone_tddi_v2_mmi-objs += cts_oem.o
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

@ -8,3 +8,6 @@ modules_install:
clean:
$(MAKE) -C $(KERNEL_SRC) M=$(PWD) clean
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

@ -1,3 +1,16 @@
/*
* Copyright (C) 2023 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.
*/
#ifdef CONFIG_CTS_I2C_HOST
#define LOG_TAG "I2CDrv"
#else
@ -11,6 +24,9 @@
#include "cts_charger_detect.h"
#include "cts_earjack_detect.h"
#include "cts_oem.h"
#if defined(CONFIG_INPUT_TOUCHSCREEN_MMI)
#include <linux/mmi_device.h>
#endif
static void cts_resume_work_func(struct work_struct *work);
#ifdef CFG_CTS_DRM_NOTIFIER
@ -356,6 +372,12 @@ static int cts_driver_probe(struct spi_device *client)
{
struct device_node *dp = client->dev.of_node;
#if defined(CONFIG_INPUT_TOUCHSCREEN_MMI)
if (client->dev.of_node && !mmi_device_is_available(client->dev.of_node)) {
cts_err("%s : mmi: device not supported\n", __func__);
return -ENODEV;
}
#endif
if (check_dt(dp)) {
if (!check_default_tp(dp, "qcom,i2c-touch-active"))
ret = -EPROBE_DEFER;

View file

@ -0,0 +1,65 @@
DLKM_DIR := motorola/kernel/modules
LOCAL_PATH := $(call my-dir)
ifneq ($(BOARD_USES_DOUBLE_TAP),)
KERNEL_CFLAGS += CONFIG_INPUT_ILI_ENABLE_DOUBLE_TAP=y
endif
ifeq ($(BOARD_USES_DOUBLE_TAP_CTRL),true)
KERNEL_CFLAGS += CONFIG_BOARD_USES_DOUBLE_TAP_CTRL=y
endif
ifneq ($(CONFIG_INPUT_SET_TOUCH_STATE),)
KERNEL_CFLAGS += CONFIG_INPUT_ILI_SET_TOUCH_STATE=y
endif
ifneq ($(BOARD_USES_PANEL_NOTIFICATIONS),)
KERNEL_CFLAGS += CONFIG_INPUT_ILI_PANEL_NOTIFICATIONS=y
endif
ifneq ($(BOARD_USES_MTK_CHECK_PANEL),)
KERNEL_CFLAGS += CONFIG_ILITEK_MTK_CHECK_PANEL=y
endif
ifeq ($(ILITEK_MULTI_TP_MODULE),true)
KERNEL_CFLAGS += CONFIG_ILITEK_MULTI_TP_MODULE=y
endif
ifneq ($(ILITEK_RESUME_BY_DDI),)
KERNEL_CFLAGS += CONFIG_ILITEK_RESUME_BY_DDI=y
endif
ifeq ($(CONFIG_INPUT_CHARGER_DETECTION),true)
KERNEL_CFLAGS += CONFIG_ILITEK_CHARGER=y
endif
ifeq ($(ILITEK_ESD),true)
KERNEL_CFLAGS += CONFIG_ILITEK_ESD=y
endif
ifeq ($(ILITEK_GESTURE),true)
KERNEL_CFLAGS += CONFIG_ILITEK_GESTURE=y
endif
ifeq ($(TOUCHSCREEN_LAST_TIME),true)
KERNEL_CFLAGS += CONFIG_ILI_TOUCH_LAST_TIME=y
endif
ifneq ($(findstring touchscreen_mmi.ko,$(BOARD_VENDOR_KERNEL_MODULES)),)
KBUILD_OPTIONS += CONFIG_INPUT_TOUCHSCREEN_MMI=y
endif
include $(CLEAR_VARS)
ifneq ($(BOARD_USES_DOUBLE_TAP),)
LOCAL_ADDITIONAL_DEPENDENCIES += $(KERNEL_MODULES_OUT)/sensors_class.ko
LOCAL_REQUIRED_MODULES := sensors_class.ko
endif
LOCAL_MODULE := ilitek_v3_mmi.ko
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
KBUILD_OPTIONS_GKI += GKI_OBJ_MODULE_DIR=gki
LOCAL_ADDITIONAL_DEPENDENCIES += $(KERNEL_MODULES_OUT)/mmi_info.ko
ifneq ($(findstring touchscreen_mmi.ko,$(BOARD_VENDOR_KERNEL_MODULES)),)
LOCAL_ADDITIONAL_DEPENDENCIES += $(KERNEL_MODULES_OUT)/touchscreen_mmi.ko
endif
include $(DLKM_DIR)/AndroidKernelModule.mk

View file

@ -0,0 +1,63 @@
# add -Wall to try to catch everything we can.
EXTRA_CFLAGS += -Wall
EXTRA_CFLAGS += -I$(ANDROID_BUILD_TOP)/motorola/kernel/modules/include \
-I$(ANDROID_BUILD_TOP)/motorola/kernel/modules/drivers/input/touchscreen/ilitek_v3_mmi \
-I$(ANDROID_BUILD_TOP)/motorola/kernel/modules/drivers/input/touchscreen/ilitek_v3_mmi/firmware
ifeq ($(filter m y, $(CONFIG_TOUCHSCREEN_ILITEK_CHIPSET)),)
obj-m += ilitek_v3_mmi.o
endif
ifneq ($(filter m y,$(CONFIG_INPUT_ILI_ENABLE_DOUBLE_TAP)),)
EXTRA_CFLAGS += -DILI_SENSOR_EN
KBUILD_EXTRA_SYMBOLS += $(CURDIR)/$(KBUILD_EXTMOD)/../../../sensors/$(GKI_OBJ_MODULE_DIR)/Module.symvers
endif
ifneq ($(filter m y, $(CONFIG_BOARD_USES_DOUBLE_TAP_CTRL)),)
EXTRA_CFLAGS += -DILI_DOUBLE_TAP_CTRL
EXTRA_CFLAGS += -DILI_PRIMARY_NODE
endif
ifneq ($(filter m y,$(CONFIG_INPUT_ILI_SET_TOUCH_STATE)),)
EXTRA_CFLAGS += -DILI_SET_TOUCH_STATE
endif
ifneq ($(filter m y,$(CONFIG_INPUT_ILI_PANEL_NOTIFICATIONS)),)
EXTRA_CFLAGS += -DILI_CONFIG_PANEL_NOTIFICATIONS
endif
ifneq ($(filter m y,$(CONFIG_ILITEK_RESUME_BY_DDI)),)
EXTRA_CFLAGS += -DILI_CONFIG_RESUME_BY_DDI
endif
ifneq ($(filter m y,$(CONFIG_ILITEK_CHARGER)),)
EXTRA_CFLAGS += -DILI_CONFIG_MTK_CHARGER
endif
ifneq ($(filter m y,$(CONFIG_ILITEK_ESD)),)
EXTRA_CFLAGS += -DILI_CONFIG_ESD
endif
ifneq ($(filter m y,$(CONFIG_ILITEK_MTK_CHECK_PANEL)),)
EXTRA_CFLAGS += -DILI_MTK_CHECK_PANEL
endif
ifneq ($(filter m y,$(CONFIG_ILITEK_MULTI_TP_MODULE)),)
EXTRA_CFLAGS += -DILI_TP_MODULE_EN
endif
ifneq ($(filter m y,$(CONFIG_ILI_TOUCH_LAST_TIME)),)
EXTRA_CFLAGS += -DILI_TOUCH_LAST_TIME
endif
ifneq ($(filter m y,$(CONFIG_INPUT_TOUCHSCREEN_MMI)),)
EXTRA_CFLAGS += -DCONFIG_INPUT_TOUCHSCREEN_MMI
endif
ilitek_v3_mmi-objs += ilitek_v3.o
ilitek_v3_mmi-objs += ilitek_v3_spi.o
ilitek_v3_mmi-objs += ilitek_v3_qcom.o
ilitek_v3_mmi-objs += ilitek_v3_ic.o
ilitek_v3_mmi-objs += ilitek_v3_touch.o
ilitek_v3_mmi-objs += ilitek_v3_mp.o
ilitek_v3_mmi-objs += ilitek_v3_hostdl.o
ilitek_v3_mmi-objs += ilitek_v3_node.o
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

@ -0,0 +1,13 @@
KERNEL_SRC ?= /lib/modules/$(shell uname -r)/build
all:
$(MAKE) -C $(KERNEL_SRC) M=$(shell pwd) modules $(KBUILD_OPTIONS)
modules_install:
$(MAKE) INSTALL_MOD_STRIP=1 -C $(KERNEL_SRC) M=$(shell pwd) modules_install
clean:
$(MAKE) -C $(KERNEL_SRC) M=$(PWD) clean
KBUILD_EXTRA_SYMBOLS += $(M)/../../../mmi_info/$(GKI_OBJ_MODULE_DIR)/Module.symvers
KBUILD_EXTRA_SYMBOLS += $(M)/../touchscreen_mmi/$(GKI_OBJ_MODULE_DIR)/Module.symvers

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,91 @@
/*
* ILITEK Touch IC driver
*
* Copyright (C) 2011 ILI Technology Corporation.
*
* Author: Dicky Chiang <dicky_chiang@ilitek.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __ILITEK_V3_FW_H
#define __ILITEK_V3_FW_H
/* define names and paths for the variety of tp modules */
#define DEF_INI_NAME_PATH "/sdcard/mp.ini"
#define DEF_FW_FILP_PATH "/sdcard/ILITEK_FW"
#define DEF_INI_REQUEST_PATH "mp.ini"
#define DEF_FW_REQUEST_PATH "ILITEK_FW"
static unsigned char CTPM_FW_DEF[] = {
#include "FW_TDDI_TRUNK_FB.ili"
};
#define CSOT_INI_NAME_PATH "/sdcard/mp_csot.ini"
#define CSOT_FW_FILP_PATH "/sdcard/ILITEK_FW_CSOT"
#define CSOT_INI_REQUEST_PATH "mp_csot.ini"
#define CSOT_FW_REQUEST_PATH "ILITEK_FW_CSOT"
static unsigned char CTPM_FW_CSOT[] = {
0xFF,
};
#define AUO_INI_NAME_PATH "/sdcard/mp_auo.ini"
#define AUO_FW_FILP_PATH "/sdcard/ILITEK_FW_AUO"
#define AUO_INI_REQUEST_PATH "mp_auo.ini"
#define AUO_FW_REQUEST_PATH "ILITEK_FW_AUO"
static unsigned char CTPM_FW_AUO[] = {
0xFF,
};
#define BOE_INI_NAME_PATH "/sdcard/mp_boe.ini"
#define BOE_FW_FILP_PATH "/sdcard/ILITEK_FW_BOE"
#define BOE_INI_REQUEST_PATH "mp_boe.ini"
#define BOE_FW_REQUEST_PATH "ILITEK_FW_BOE"
static unsigned char CTPM_FW_BOE[] = {
0xFF,
};
#define INX_INI_NAME_PATH "/sdcard/mp_inx.ini"
#define INX_FW_FILP_PATH "/sdcard/ILITEK_FW_INX"
#define INX_INI_REQUEST_PATH "mp_inx.ini"
#define INX_FW_REQUEST_PATH "ILITEK_FW_INX"
static unsigned char CTPM_FW_INX[] = {
0xFF,
};
#define DJ_INI_NAME_PATH "/sdcard/mp_dj.ini"
#define DJ_FW_FILP_PATH "/sdcard/ILITEK_FW_DJ"
#define DJ_INI_REQUEST_PATH "mp_dj.ini"
#define DJ_FW_REQUEST_PATH "ILITEK_FW_DJ"
static unsigned char CTPM_FW_DJ[] = {
0xFF,
};
#define TXD_INI_NAME_PATH "/sdcard/mp_txd.ini"
#define TXD_FW_FILP_PATH "/sdcard/ILITEK_FW_TXD"
#define TXD_INI_REQUEST_PATH "mp_txd.ini"
#define TXD_FW_REQUEST_PATH "ILITEK_FW_TXD"
static unsigned char CTPM_FW_TXD[] = {
0xFF,
};
#define TM_INI_NAME_PATH "/sdcard/mp_tm.ini"
#define TM_FW_FILP_PATH "/sdcard/ILITEK_FW_TM"
#define TM_INI_REQUEST_PATH "mp_tm.ini"
#define TM_FW_REQUEST_PATH "ILITEK_FW_TM"
static unsigned char CTPM_FW_TM[] = {
0xFF,
};
#endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,504 @@
/*
* ILITEK Touch IC driver
*
* Copyright (C) 2011 ILI Technology Corporation.
*
* Author: Dicky Chiang <dicky_chiang@ilitek.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "ilitek_v3.h"
struct touch_bus_info {
struct i2c_driver bus_driver;
struct ilitek_hwif_info *hwif;
};
struct ilitek_ts_data *ilits;
#define RW_SYNC 0
#define R_ONLY 1
#define W_ONLY 2
#if I2C_DMA_TRANSFER
static unsigned char *ilitek_dma_va;
static dma_addr_t ilitek_dma_pa;
#define DMA_VA_BUFFER 4096
static int dma_i2c_alloc(struct i2c_client *client)
{
if (client != NULL) {
client->dev.coherent_dma_mask = DMA_BIT_MASK(32);
ilitek_dma_va = (u8 *)dmam_alloc_coherent(client->dev, DMA_VA_BUFFER, &ilitek_dma_pa, GFP_KERNEL);
if (ERR_ALLOC_MEM(ilitek_dma_va)) {
ILI_ERR("Allocate DMA I2C Buffer failed\n");
return -ENOMEM;
}
memset(ilitek_dma_va, 0, DMA_VA_BUFFER);
client->ext_flag |= I2C_DMA_FLAG;
return 0;
}
ILI_ERR("client is NULL, allocated dma i2c failed\n");
return -ENODEV;
}
#endif
static int core_i2c_write(void *buf, int len)
{
int ret = 0;
u8 *txbuf = (u8 *)buf;
u8 check_sum = 0;
u8 *mpbuf = NULL;
struct i2c_msg msgs[] = {
{
.addr = ilits->i2c->addr,
.flags = 0, /* write flag. */
.len = len,
.buf = txbuf,
},
};
#if I2C_DMA_TRANSFER
if (len > 8) {
msgs[0].addr = (ilits->i2c->addr & I2C_MASK_FLAG);
msgs[0].ext_flag = (ilits->i2c->ext_flag | I2C_ENEXT_FLAG | I2C_DMA_FLAG);
memcpy(ilitek_dma_va, txbuf, len);
msgs[0].buf = (u8 *)ilitek_dma_pa;
}
#endif
/*
* NOTE: If TP driver is doing MP test and commanding 0xF1 to FW, we add a checksum
* to the last index and plus 1 with size.
*/
if (atomic_read(&ilits->mp_stat) && txbuf[0] == P5_X_SET_CDC_INIT) {
check_sum = ili_calc_packet_checksum(txbuf, len);
mpbuf = kcalloc(len + 1, sizeof(u8), GFP_KERNEL);
if (ERR_ALLOC_MEM(mpbuf)) {
ILI_ERR("Failed to allocate mpbuf mem\n");
return -ENOMEM;
}
ipio_memcpy(mpbuf, txbuf, len, msgs[0].len);
mpbuf[len] = check_sum;
msgs[0].buf = mpbuf;
ili_dump_data(mpbuf, 8, len+1, 0, "mp cdc cmd");
msgs[0].len = len + 1;
}
if (i2c_transfer(ilits->i2c->adapter, msgs, 1) != 1)
ret = -1;
if (!atomic_read(&ilits->ice_stat))
mdelay(1);
ipio_kfree((void **)&mpbuf);
return ret;
}
static int core_i2c_read(void *buf, int len)
{
int ret;
u8 *rxbuf = (u8 *)buf;
struct i2c_msg msgs[] = {
{
.addr = ilits->i2c->addr,
.flags = I2C_M_RD, /* read flag. */
.len = len,
.buf = rxbuf,
},
};
#if I2C_DMA_TRANSFER
if (len > 8) {
msgs[0].addr = (ilits->i2c->addr & I2C_MASK_FLAG);
msgs[0].ext_flag = (ilits->i2c->ext_flag | I2C_ENEXT_FLAG | I2C_DMA_FLAG);
msgs[0].buf = (u8 *)ilitek_dma_pa;
} else {
msgs[0].buf = rxbuf;
}
#endif
ret = i2c_transfer(ilits->i2c->adapter, msgs, 1);
#if I2C_DMA_TRANSFER
if (len > 8)
memcpy(rxbuf, ilitek_dma_va, len);
#endif
/*
* If i2c_transfer is ok (must return 1 because only sends one msg),
* return #bytes transferred, else error code.
*/
return (ret == 1) ? len : ret;
}
static int ilitek_i2c_write(void *buf, int len)
{
int ret = 0;
if (len == 0) {
ILI_ERR("i2c write len is invalid\n");
return -EINVAL;
}
ret = core_i2c_write(buf, len);
if (ret < 0) {
if (atomic_read(&ilits->tp_reset) == START) {
ret = 0;
goto out;
}
ILI_ERR("i2c write error, ret = %d\n", ret);
}
out:
return ret;
}
static int ilitek_i2c_read(void *buf, int len)
{
int ret = 0;
if (len == 0) {
ILI_ERR("i2c read len is invalid\n");
return -EINVAL;
}
ret = core_i2c_read(buf, len);
if (ret < 0) {
if (atomic_read(&ilits->tp_reset) == START) {
ret = 0;
goto out;
}
ILI_ERR("i2c read error, ret = %d\n", ret);
}
out:
return ret;
}
static int ili_i2c_pll_clk_wakeup(void)
{
int ret = 0;
u8 wakeup = 0xA3;
#if (PLL_CLK_WAKEUP_TP_RESUME == ENABLE)
if (ilits->pll_clk_wakeup == true) {
#else
if ((ilits->pll_clk_wakeup == true) && (ilits->tp_suspend == true)) {
#endif
ret = ilitek_i2c_write(&wakeup, sizeof(wakeup));
if (ret < 0)
ILI_ERR("i2c write dummy cmd error\n");
}
return ret;
}
static int ili_i2c_wrapper(u8 *txbuf, u32 wlen, u8 *rxbuf, u32 rlen, bool spi_irq, bool i2c_irq)
{
int ret = 0, operate = -1;
if (wlen > 0) {
if (ERR_ALLOC_MEM(txbuf)) {
ILI_ERR("txbuf is null\n");
return -ENOMEM;
}
}
if (rlen > 0) {
if (ERR_ALLOC_MEM(rxbuf)) {
ILI_ERR("rxbuf is null\n");
return -ENOMEM;
}
}
#if ENABLE_CASCADE
if (ilits->i2c_addr_change == SLAVE) {
ilits->i2c->addr = TDDI_I2C_SLAVE_ADDR;
} else {
ilits->i2c->addr = TDDI_I2C_ADDR;
}
#endif
if (wlen > 0 && rlen > 0)
operate = RW_SYNC;
else if (wlen > 0 && !rlen)
operate = W_ONLY;
else
operate = R_ONLY;
if (ilits->int_pulse)
ilits->detect_int_stat = ili_ic_check_int_pulse;
else
ilits->detect_int_stat = ili_ic_check_int_level;
if (i2c_irq)
atomic_set(&ilits->cmd_int_check, ENABLE);
switch (operate) {
case RW_SYNC:
ret = ili_i2c_pll_clk_wakeup();
if (ret < 0) {
ILI_ERR("i2c-wrapper dummy cmd write error\n");
}
ret = ilitek_i2c_write(txbuf, wlen);
if (ret < 0) {
ILI_ERR("i2c-wrapper write error\n");
break;
}
if (i2c_irq) {
if (ilits->detect_int_stat(false) < 0) {
ILI_ERR("ERROR! Check INT timeout\n");
ret = -ETIME;
break;
}
} else {
msleep(1);
}
ret = ilitek_i2c_read(rxbuf, rlen);
if (ret < 0) {
ILI_ERR("i2c-wrapper read error\n");
break;
}
break;
case W_ONLY:
ret = ili_i2c_pll_clk_wakeup();
if (ret < 0) {
ILI_ERR("i2c-wrapper dummy cmd write error\n");
}
ret = ilitek_i2c_write(txbuf, wlen);
if (ret < 0) {
ILI_ERR("i2c-wrapper write error\n");
break;
}
break;
case R_ONLY:
if (i2c_irq) {
if (ilits->detect_int_stat(false) < 0) {
ILI_ERR("ERROR! Check INT timeout\n");
ret = -ETIME;
break;
}
}
ret = ilitek_i2c_read(rxbuf, rlen);
if (ret < 0) {
ILI_ERR("i2c-wrapper read error\n");
break;
}
break;
default:
ILI_ERR("Unknown ts-i2c operation\n");
ret = -EINVAL;
break;
}
if (i2c_irq)
atomic_set(&ilits->cmd_int_check, DISABLE);
return ret;
}
int ili_core_spi_setup(int num)
{
ILI_ERR("Not support this interface\n");
return 0;
}
static int ilitek_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
{
struct touch_bus_info *info =
container_of(to_i2c_driver(i2c->dev.driver),
struct touch_bus_info, bus_driver);
ILI_INFO("ilitek i2c probe\n");
if (!i2c) {
ILI_ERR("i2c client is NULL\n");
return -ENODEV;
}
if (i2c->addr != TDDI_I2C_ADDR) {
i2c->addr = TDDI_I2C_ADDR;
ILI_INFO("i2c addr doesn't be set up, use default : 0x%x\n", i2c->addr);
}
if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C)) {
ILI_ERR("i2c functions are not supported!\n");
return -ENODEV;
}
ilits = devm_kzalloc(&i2c->dev, sizeof(struct ilitek_ts_data), GFP_KERNEL);
if (ERR_ALLOC_MEM(ilits)) {
ILI_ERR("Failed to allocate ts memory, %ld\n", PTR_ERR(ilits));
return -ENOMEM;
}
/* Used for receiving touch data only, do not mix up with others. */
ilits->tr_buf = kzalloc(TR_BUF_SIZE, GFP_ATOMIC);
if (ERR_ALLOC_MEM(ilits->tr_buf)) {
ILI_ERR("failed to allocate touch report buffer\n");
return -ENOMEM;
}
ilits->gcoord = kzalloc(sizeof(struct gesture_coordinate), GFP_KERNEL);
if (ERR_ALLOC_MEM(ilits->gcoord)) {
ILI_ERR("Failed to allocate gresture coordinate buffer\n");
return -ENOMEM;
}
ilits->i2c = i2c;
ilits->spi = NULL;
ilits->dev = &i2c->dev;
ilits->hwif = info->hwif;
ilits->phys = "I2C";
ilits->wrapper = ili_i2c_wrapper;
ilits->detect_int_stat = ili_ic_check_int_pulse;
ilits->int_pulse = true;
ilits->mp_retry = false;
#if I2C_DMA_TRANSFER
if (dma_i2c_alloc(ilits->i2c) < 0)
ILI_ERR("Failed to alllocate DMA mem %ld\n", PTR_ERR(ilits->i2c));
#endif
ilits->actual_tp_mode = P5_X_FW_AP_MODE;
ilits->tp_data_mode = AP_MODE;
if (TDDI_RST_BIND)
ilits->reset = TP_IC_WHOLE_RST_WITH_FLASH;
else
ilits->reset = TP_HW_RST_ONLY;
#if ENABLE_CASCADE
ilits->rst_edge_delay = 60;
#else
ilits->rst_edge_delay = 40;
#endif
#if GENERIC_KERNEL_IMAGE
ilits->fw_open = REQUEST_FIRMWARE;
#else
ilits->fw_open = FILP_OPEN;
#endif
ilits->fw_upgrade_mode = UPGRADE_FLASH;
ilits->mp_move_code = ili_move_mp_code_flash;
ilits->gesture_move_code = ili_move_gesture_code_flash;
ilits->esd_recover = ili_wq_esd_i2c_check;
ilits->esd_func_ctrl = ENABLE_WQ_ESD;
ilits->ges_recover = ili_touch_esd_gesture_flash;
ilits->gesture_mode = DATA_FORMAT_GESTURE_INFO;
ilits->gesture_demo_ctrl = DISABLE;
ilits->wtd_ctrl = OFF;
ilits->report = ENABLE;
ilits->dnp = DISABLE;
ilits->dlnp = DISABLE;
ilits->irq_tirgger_type = IRQF_TRIGGER_RISING;
ilits->info_from_hex = DISABLE;
ilits->wait_int_timeout = AP_INT_TIMEOUT;
ilits->ice_flash_cs_ctrl = ENABLE;
ilits->compress_disable = ENABLE;
ilits->compress_handonly_disable = ENABLE;
ilits->compress_penonly_disable = ENABLE;
#if MULTI_REPORT_RATE
ilits->current_report_rate_mode = DDI60_TP120; /*Default report mode*/
#endif
#if ENABLE_GESTURE
ilits->gesture = DISABLE;
ilits->ges_sym.double_tap = DOUBLE_TAP;
ilits->ges_sym.alphabet_line_2_top = ALPHABET_LINE_2_TOP;
ilits->ges_sym.alphabet_line_2_bottom = ALPHABET_LINE_2_BOTTOM;
ilits->ges_sym.alphabet_line_2_left = ALPHABET_LINE_2_LEFT;
ilits->ges_sym.alphabet_line_2_right = ALPHABET_LINE_2_RIGHT;
ilits->ges_sym.alphabet_m = ALPHABET_M;
ilits->ges_sym.alphabet_w = ALPHABET_W;
ilits->ges_sym.alphabet_c = ALPHABET_C;
ilits->ges_sym.alphabet_E = ALPHABET_E;
ilits->ges_sym.alphabet_V = ALPHABET_V;
ilits->ges_sym.alphabet_O = ALPHABET_O;
ilits->ges_sym.alphabet_S = ALPHABET_S;
ilits->ges_sym.alphabet_Z = ALPHABET_Z;
ilits->ges_sym.alphabet_V_down = ALPHABET_V_DOWN;
ilits->ges_sym.alphabet_V_left = ALPHABET_V_LEFT;
ilits->ges_sym.alphabet_V_right = ALPHABET_V_RIGHT;
ilits->ges_sym.alphabet_two_line_2_bottom = ALPHABET_TWO_LINE_2_BOTTOM;
ilits->ges_sym.alphabet_F = ALPHABET_F;
ilits->ges_sym.alphabet_AT = ALPHABET_AT;
#endif
return info->hwif->plat_probe();
}
static int ilitek_i2c_remove(struct i2c_client *i2c)
{
ILI_INFO();
return 0;
}
static const struct i2c_device_id tp_i2c_id[] = {
{TDDI_DEV_ID, 0},
{},
};
int ili_interface_dev_init(struct ilitek_hwif_info *hwif)
{
struct touch_bus_info *info;
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info) {
ILI_ERR("faied to allocate i2c_driver\n");
return -ENOMEM;
}
if (hwif->bus_type != BUS_I2C) {
ILI_ERR("Not I2C dev\n");
ipio_kfree((void **)&info);
return -EINVAL;
}
hwif->info = info;
info->bus_driver.driver.name = hwif->name;
info->bus_driver.driver.owner = hwif->owner;
info->bus_driver.driver.of_match_table = hwif->of_match_table;
info->bus_driver.driver.pm = hwif->pm;
info->bus_driver.probe = ilitek_i2c_probe;
info->bus_driver.remove = ilitek_i2c_remove;
info->bus_driver.id_table = tp_i2c_id;
info->hwif = hwif;
return i2c_add_driver(&info->bus_driver);
}
void ili_interface_dev_exit(struct ilitek_ts_data *ts, bool flag)
{
struct touch_bus_info *info = (struct touch_bus_info *)ilits->hwif->info;
ILI_INFO("remove i2c dev\n");
if (flag == ENABLE) {
i2c_del_driver(&info->bus_driver);
ipio_kfree((void **)&info);
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,518 @@
/*
* ILITEK Touch IC driver
*
* Copyright (C) 2011 ILI Technology Corporation.
*
* Author: Dicky Chiang <dicky_chiang@ilitek.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "ilitek_v3.h"
#include "tpd.h"
#define DTS_INT_GPIO "touch,irq-gpio"
#define DTS_RESET_GPIO "touch,reset-gpio"
#define DTS_OF_NAME "mediatek,cap_touch"
#define MTK_RST_GPIO GTP_RST_PORT
#define MTK_INT_GPIO GTP_INT_PORT
extern struct tpd_device *tpd;
void ili_tp_reset(void)
{
ILI_INFO("edge delay = %d\n", ilits->rst_edge_delay);
/* Need accurate power sequence, do not change it to msleep */
tpd_gpio_output(ilits->tp_rst, 1);
mdelay(1);
tpd_gpio_output(ilits->tp_rst, 0);
mdelay(5);
tpd_gpio_output(ilits->tp_rst, 1);
mdelay(ilits->rst_edge_delay);
}
void ili_input_register(void)
{
int i;
ilits->input = tpd->dev;
if (tpd_dts_data.use_tpd_button) {
for (i = 0; i < tpd_dts_data.tpd_key_num; i++)
input_set_capability(ilits->input, EV_KEY, tpd_dts_data.tpd_key_local[i]);
}
/* set the supported event type for input device */
set_bit(EV_ABS, ilits->input->evbit);
set_bit(EV_SYN, ilits->input->evbit);
set_bit(EV_KEY, ilits->input->evbit);
set_bit(BTN_TOUCH, ilits->input->keybit);
set_bit(BTN_TOOL_FINGER, ilits->input->keybit);
set_bit(INPUT_PROP_DIRECT, ilits->input->propbit);
if (MT_PRESSURE)
input_set_abs_params(ilits->input, ABS_MT_PRESSURE, 0, MAX_PRESSURE, 0, 0);
if (MT_B_TYPE) {
#if KERNEL_VERSION(3, 7, 0) <= LINUX_VERSION_CODE
input_mt_init_slots(ilits->input, MAX_TOUCH_NUM, INPUT_MT_DIRECT);
#else
input_mt_init_slots(ilits->input, MAX_TOUCH_NUM);
#endif /* LINUX_VERSION_CODE */
} else {
input_set_abs_params(ilits->input, ABS_MT_TRACKING_ID, 0, MAX_TOUCH_NUM, 0, 0);
}
input_set_abs_params(ilits->input, ABS_MT_POSITION_X, TOUCH_SCREEN_X_MIN, ilits->panel_wid - 1, 0, 0);
input_set_abs_params(ilits->input, ABS_MT_POSITION_Y, TOUCH_SCREEN_Y_MIN, ilits->panel_hei - 1, 0, 0);
/* Gesture keys register */
input_set_capability(ilits->input, EV_KEY, KEY_POWER);
input_set_capability(ilits->input, EV_KEY, KEY_GESTURE_UP);
input_set_capability(ilits->input, EV_KEY, KEY_GESTURE_DOWN);
input_set_capability(ilits->input, EV_KEY, KEY_GESTURE_LEFT);
input_set_capability(ilits->input, EV_KEY, KEY_GESTURE_RIGHT);
input_set_capability(ilits->input, EV_KEY, KEY_GESTURE_O);
input_set_capability(ilits->input, EV_KEY, KEY_GESTURE_E);
input_set_capability(ilits->input, EV_KEY, KEY_GESTURE_M);
input_set_capability(ilits->input, EV_KEY, KEY_GESTURE_W);
input_set_capability(ilits->input, EV_KEY, KEY_GESTURE_S);
input_set_capability(ilits->input, EV_KEY, KEY_GESTURE_V);
input_set_capability(ilits->input, EV_KEY, KEY_GESTURE_Z);
input_set_capability(ilits->input, EV_KEY, KEY_GESTURE_C);
input_set_capability(ilits->input, EV_KEY, KEY_GESTURE_F);
__set_bit(KEY_GESTURE_POWER, ilits->input->keybit);
__set_bit(KEY_GESTURE_UP, ilits->input->keybit);
__set_bit(KEY_GESTURE_DOWN, ilits->input->keybit);
__set_bit(KEY_GESTURE_LEFT, ilits->input->keybit);
__set_bit(KEY_GESTURE_RIGHT, ilits->input->keybit);
__set_bit(KEY_GESTURE_O, ilits->input->keybit);
__set_bit(KEY_GESTURE_E, ilits->input->keybit);
__set_bit(KEY_GESTURE_M, ilits->input->keybit);
__set_bit(KEY_GESTURE_W, ilits->input->keybit);
__set_bit(KEY_GESTURE_S, ilits->input->keybit);
__set_bit(KEY_GESTURE_V, ilits->input->keybit);
__set_bit(KEY_GESTURE_Z, ilits->input->keybit);
__set_bit(KEY_GESTURE_C, ilits->input->keybit);
__set_bit(KEY_GESTURE_F, ilits->input->keybit);
}
void ili_input_pen_register(void)
{
ilits->input_pen = input_allocate_device();
if (ERR_ALLOC_MEM(ilits->input_pen)) {
ILI_ERR("Failed to allocate touch input device\n");
input_free_device(ilits->input_pen);
return;
}
ilits->input_pen->name = PEN_INPUT_DEVICE;
ilits->input_pen->phys = ilits->phys;
ilits->input_pen->dev.parent = ilits->dev;
ilits->input_pen->id.bustype = ilits->hwif->bus_type;
/* set the supported event type for input device */
set_bit(EV_ABS, ilits->input_pen->evbit);
set_bit(EV_SYN, ilits->input_pen->evbit);
set_bit(EV_KEY, ilits->input_pen->evbit);
set_bit(BTN_TOUCH, ilits->input_pen->keybit);
set_bit(BTN_TOOL_PEN, ilits->input_pen->keybit);
set_bit(BTN_STYLUS, ilits->input_pen->keybit);
set_bit(BTN_STYLUS2, ilits->input_pen->keybit);
set_bit(INPUT_PROP_DIRECT, ilits->input_pen->propbit);
input_set_abs_params(ilits->input_pen, ABS_X, 0, ilits->panel_wid, 0, 0);
input_set_abs_params(ilits->input_pen, ABS_Y, 0, ilits->panel_hei, 0, 0);
input_set_abs_params(ilits->input_pen, ABS_PRESSURE, 0, MAX_PRESSURE, 0, 0);
input_set_abs_params(ilits->input_pen, ABS_TILT_X, -60, 60, 0, 0);
input_set_abs_params(ilits->input_pen, ABS_TILT_Y, -60, 60, 0, 0);
input_set_abs_params(ilits->input_pen, ABS_DISTANCE, 0, 1, 0, 0);
/* register the input device to input sub-system */
if (input_register_device(ilits->input_pen) < 0) {
ILI_ERR("Failed to register touch input device\n");
input_unregister_device(ilits->input_pen);
input_free_device(ilits->input_pen);
}
ILI_INFO("Input Pen device for Single Touch\n");
}
#if REGULATOR_POWER
void ili_plat_regulator_power_on(bool status)
{
ILI_INFO("%s\n", status ? "POWER ON" : "POWER OFF");
if (status) {
if (ilits->vdd) {
if (regulator_enable(ilits->vdd) < 0)
ILI_ERR("regulator_enable VDD fail\n");
}
if (ilits->vcc) {
if (regulator_enable(ilits->vcc) < 0)
ILI_ERR("regulator_enable VCC fail\n");
}
} else {
if (ilits->vdd) {
if (regulator_disable(ilits->vdd) < 0)
ILI_ERR("regulator_enable VDD fail\n");
}
if (ilits->vcc) {
if (regulator_disable(ilits->vcc) < 0)
ILI_ERR("regulator_enable VCC fail\n");
}
}
atomic_set(&ilits->ice_stat, DISABLE);
mdelay(5);
}
static void ilitek_plat_regulator_power_init(void)
{
const char *vdd_name = "vdd";
const char *vcc_name = "vcc";
ilits->vdd = regulator_get(tpd->tpd_dev, vdd_name);
if (ERR_ALLOC_MEM(ilits->vdd)) {
ILI_ERR("regulator_get VDD fail\n");
ilits->vdd = NULL;
}
tpd->reg = ilits->vdd;
if (regulator_set_voltage(ilits->vdd, VDD_VOLTAGE, VDD_VOLTAGE) < 0)
ILI_ERR("Failed to set VDD %d\n", VDD_VOLTAGE);
ilits->vcc = regulator_get(ilits->dev, vcc_name);
if (ERR_ALLOC_MEM(ilits->vcc)) {
ILI_ERR("regulator_get VCC fail.\n");
ilits->vcc = NULL;
}
if (regulator_set_voltage(ilits->vcc, VCC_VOLTAGE, VCC_VOLTAGE) < 0)
ILI_ERR("Failed to set VCC %d\n", VCC_VOLTAGE);
ili_plat_regulator_power_on(true);
}
#endif
static int ilitek_plat_gpio_register(void)
{
int ret = 0;
ilits->tp_int = MTK_INT_GPIO;
ilits->tp_rst = MTK_RST_GPIO;
ILI_INFO("TP INT: %d\n", ilits->tp_int);
ILI_INFO("TP RESET: %d\n", ilits->tp_rst);
if (!gpio_is_valid(ilits->tp_int)) {
ILI_ERR("Invalid INT gpio: %d\n", ilits->tp_int);
return -EBADR;
}
if (!gpio_is_valid(ilits->tp_rst)) {
ILI_ERR("Invalid RESET gpio: %d\n", ilits->tp_rst);
return -EBADR;
}
gpio_direction_input(ilits->tp_int);
return ret;
}
void ili_irq_disable(void)
{
unsigned long flag;
spin_lock_irqsave(&ilits->irq_spin, flag);
if (atomic_read(&ilits->irq_stat) == DISABLE)
goto out;
if (!ilits->irq_num) {
ILI_ERR("gpio_to_irq (%d) is incorrect\n", ilits->irq_num);
goto out;
}
disable_irq_nosync(ilits->irq_num);
atomic_set(&ilits->irq_stat, DISABLE);
ILI_DBG("Disable irq success\n");
out:
spin_unlock_irqrestore(&ilits->irq_spin, flag);
}
void ili_irq_enable(void)
{
unsigned long flag;
spin_lock_irqsave(&ilits->irq_spin, flag);
if (atomic_read(&ilits->irq_stat) == ENABLE)
goto out;
if (!ilits->irq_num) {
ILI_ERR("gpio_to_irq (%d) is incorrect\n", ilits->irq_num);
goto out;
}
enable_irq(ilits->irq_num);
atomic_set(&ilits->irq_stat, ENABLE);
ILI_DBG("Enable irq success\n");
out:
spin_unlock_irqrestore(&ilits->irq_spin, flag);
}
static irqreturn_t ilitek_plat_isr_top_half(int irq, void *dev_id)
{
if (irq != ilits->irq_num) {
ILI_ERR("Incorrect irq number (%d)\n", irq);
return IRQ_NONE;
}
if (atomic_read(&ilits->cmd_int_check) == ENABLE) {
atomic_set(&ilits->cmd_int_check, DISABLE);
ILI_DBG("CMD INT detected, ignore\n");
wake_up(&(ilits->inq));
return IRQ_HANDLED;
}
if (ilits->prox_near) {
ILI_INFO("Proximity event, ignore interrupt!\n");
return IRQ_HANDLED;
}
ILI_DBG("report: %d, rst: %d, fw: %d, switch: %d, mp: %d, sleep: %d, esd: %d, igr:%d\n",
ilits->report,
atomic_read(&ilits->tp_reset),
atomic_read(&ilits->fw_stat),
atomic_read(&ilits->tp_sw_mode),
atomic_read(&ilits->mp_stat),
atomic_read(&ilits->tp_sleep),
atomic_read(&ilits->esd_stat),
atomic_read(&ilits->ignore_report));
if (!ilits->report || atomic_read(&ilits->tp_reset) || atomic_read(&ilits->ignore_report) ||
atomic_read(&ilits->fw_stat) || atomic_read(&ilits->tp_sw_mode) ||
atomic_read(&ilits->mp_stat) || atomic_read(&ilits->tp_sleep) ||
atomic_read(&ilits->esd_stat)) {
ILI_DBG("ignore interrupt !\n");
return IRQ_HANDLED;
}
return IRQ_WAKE_THREAD;
}
static irqreturn_t ilitek_plat_isr_bottom_half(int irq, void *dev_id)
{
if (mutex_is_locked(&ilits->touch_mutex)) {
ILI_DBG("touch is locked, ignore\n");
return IRQ_HANDLED;
}
mutex_lock(&ilits->touch_mutex);
ili_report_handler();
mutex_unlock(&ilits->touch_mutex);
return IRQ_HANDLED;
}
void ili_irq_unregister(void)
{
devm_free_irq(ilits->dev, ilits->irq_num, NULL);
}
int ili_irq_register(int type)
{
int ret = 0;
static bool get_irq_pin;
struct device_node *node;
atomic_set(&ilits->irq_stat, DISABLE);
if (get_irq_pin == false) {
node = of_find_matching_node(NULL, touch_of_match);
if (node)
ilits->irq_num = irq_of_parse_and_map(node, 0);
ILI_INFO("ilits->irq_num = %d\n", ilits->irq_num);
get_irq_pin = true;
}
ret = devm_request_threaded_irq(ilits->dev, ilits->irq_num,
ilitek_plat_isr_top_half,
ilitek_plat_isr_bottom_half,
type | IRQF_ONESHOT, "ilitek", NULL);
if (type == IRQF_TRIGGER_FALLING)
ILI_INFO("IRQ TYPE = IRQF_TRIGGER_FALLING\n");
if (type == IRQF_TRIGGER_RISING)
ILI_INFO("IRQ TYPE = IRQF_TRIGGER_RISING\n");
if (ret != 0)
ILI_ERR("Failed to register irq handler, irq = %d, ret = %d\n", ilits->irq_num, ret);
atomic_set(&ilits->irq_stat, ENABLE);
return ret;
}
static void tpd_resume(struct device *h)
{
if (ili_sleep_handler(TP_RESUME) < 0)
ILI_ERR("TP resume failed\n");
}
static void tpd_suspend(struct device *h)
{
if (ili_sleep_handler(TP_DEEP_SLEEP) < 0)
ILI_ERR("TP suspend failed\n");
}
static int ilitek_tp_pm_suspend(struct device *dev)
{
ILI_INFO("CALL BACK TP PM SUSPEND");
ilits->pm_suspend = true;
reinit_completion(&ilits->pm_completion);
return 0;
}
static int ilitek_tp_pm_resume(struct device *dev)
{
ILI_INFO("CALL BACK TP PM RESUME");
ilits->pm_suspend = false;
complete(&ilits->pm_completion);
return 0;
}
static int ilitek_plat_probe(void)
{
ILI_INFO("platform probe\n");
#if REGULATOR_POWER
ilitek_plat_regulator_power_init();
#endif
if (ilitek_plat_gpio_register() < 0)
ILI_ERR("Register gpio failed\n");
ili_irq_register(ilits->irq_tirgger_type);
if (ili_tddi_init() < 0) {
ILI_ERR("ILITEK Driver probe failed\n");
ili_irq_unregister();
ili_dev_remove(DISABLE);
return -ENODEV;
}
tpd_load_status = 1;
ilits->pm_suspend = false;
init_completion(&ilits->pm_completion);
#if CHARGER_NOTIFIER_CALLBACK
#if KERNEL_VERSION(4, 1, 0) <= LINUX_VERSION_CODE
/* add_for_charger_start */
ilitek_plat_charger_init();
/* add_for_charger_end */
#endif
#endif
ILI_INFO("ILITEK Driver loaded successfully!#");
return 0;
}
static int ilitek_plat_remove(void)
{
ILI_INFO("remove plat dev\n");
ili_dev_remove(ENABLE);
return 0;
}
static const struct dev_pm_ops tp_pm_ops = {
.suspend = ilitek_tp_pm_suspend,
.resume = ilitek_tp_pm_resume,
};
static const struct of_device_id tp_match_table[] = {
{.compatible = DTS_OF_NAME},
{},
};
#ifdef ROI
struct ts_device_ops ilitek_ops = {
.chip_roi_rawdata = ili_knuckle_roi_rawdata,
.chip_roi_switch = ili_knuckle_roi_switch,
};
#endif
static struct ilitek_hwif_info hwif = {
.bus_type = TDDI_INTERFACE,
.plat_type = TP_PLAT_MTK,
.owner = THIS_MODULE,
.name = TDDI_DEV_ID,
.of_match_table = of_match_ptr(tp_match_table),
.plat_probe = ilitek_plat_probe,
.plat_remove = ilitek_plat_remove,
.pm = &tp_pm_ops,
};
static int tpd_local_init(void)
{
ILI_INFO("TPD init device driver\n");
if (ili_dev_init(&hwif) < 0) {
ILI_ERR("Failed to register i2c/spi bus driver\n");
return -ENODEV;
}
if (tpd_load_status == 0) {
ILI_ERR("Add error touch panel driver\n");
return -1;
}
if (tpd_dts_data.use_tpd_button) {
tpd_button_setting(tpd_dts_data.tpd_key_num, tpd_dts_data.tpd_key_local,
tpd_dts_data.tpd_key_dim_local);
}
tpd_type_cap = 1;
return 0;
}
static struct tpd_driver_t tpd_device_driver = {
.tpd_device_name = TDDI_DEV_ID,
.tpd_local_init = tpd_local_init,
.suspend = tpd_suspend,
.resume = tpd_resume,
};
static int __init ilitek_plat_dev_init(void)
{
int ret = 0;
ILI_INFO("ILITEK TP driver init for MTK\n");
tpd_get_dts_info();
ret = tpd_driver_add(&tpd_device_driver);
if (ret < 0) {
ILI_ERR("ILITEK add TP driver failed\n");
tpd_driver_remove(&tpd_device_driver);
return -ENODEV;
}
return 0;
}
static void __exit ilitek_plat_dev_exit(void)
{
ILI_INFO("ilitek driver has been removed\n");
tpd_driver_remove(&tpd_device_driver);
}
module_init(ilitek_plat_dev_init);
module_exit(ilitek_plat_dev_exit);
MODULE_AUTHOR("ILITEK");
MODULE_LICENSE("GPL");

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,910 @@
/*
* ILITEK Touch IC driver
*
* Copyright (C) 2011 ILI Technology Corporation.
*
* Author: Dicky Chiang <dicky_chiang@ilitek.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "ilitek_v3.h"
struct touch_bus_info {
struct spi_driver bus_driver;
struct ilitek_hwif_info *hwif;
};
struct ilitek_ts_data *ilits;
#if defined(ILI_MTK_CHECK_PANEL) || defined(ILI_TP_MODULE_EN)
const char *active_panel_name;
#endif
#if SPI_DMA_TRANSFER_SPLIT
#if SPI_DMA_TRANSFER_SPLIT_OLD
#define DMA_TRANSFER_MAX_CHUNK 64 /* number of chunks to be transferred. */
#define DMA_TRANSFER_MAX_LEN 1024 /* length of a chunk. */
int ili_spi_write_then_read_split(struct spi_device *spi,
const void *txbuf, unsigned n_tx,
void *rxbuf, unsigned n_rx)
{
int status = -1, duplex_len = 0;
int xfercnt = 0, xferlen = 0, xferloop = 0;
int offset = 0;
u8 cmd = 0;
struct spi_message message;
struct spi_transfer *xfer;
xfer = kzalloc(DMA_TRANSFER_MAX_CHUNK * sizeof(struct spi_transfer), GFP_KERNEL);
if (n_rx > SPI_RX_BUF_SIZE) {
ILI_ERR("Rx length is greater than spi local buf, abort\n");
status = -ENOMEM;
goto out;
}
spi_message_init(&message);
memset(ilits->spi_tx, 0x0, SPI_TX_BUF_SIZE);
memset(ilits->spi_rx, 0x0, SPI_RX_BUF_SIZE);
if ((n_tx > 0) && (n_rx > 0))
cmd = SPI_READ;
else
cmd = SPI_WRITE;
switch (cmd) {
case SPI_WRITE:
if (n_tx % DMA_TRANSFER_MAX_LEN)
xferloop = (n_tx / DMA_TRANSFER_MAX_LEN) + 1;
else
xferloop = n_tx / DMA_TRANSFER_MAX_LEN;
xferlen = n_tx;
memcpy(ilits->spi_tx, (u8 *)txbuf, xferlen);
for (xfercnt = 0; xfercnt < xferloop; xfercnt++) {
if (xferlen > DMA_TRANSFER_MAX_LEN)
xferlen = DMA_TRANSFER_MAX_LEN;
xfer[xfercnt].len = xferlen;
xfer[xfercnt].tx_buf = ilits->spi_tx + xfercnt * DMA_TRANSFER_MAX_LEN;
spi_message_add_tail(&xfer[xfercnt], &message);
xferlen = n_tx - (xfercnt+1) * DMA_TRANSFER_MAX_LEN;
}
status = spi_sync(spi, &message);
break;
case SPI_READ:
if (n_tx > DMA_TRANSFER_MAX_LEN) {
ILI_ERR("Tx length must be lower than dma length (%d).\n", DMA_TRANSFER_MAX_LEN);
status = -EINVAL;
break;
}
if (!atomic_read(&ilits->ice_stat))
offset = 2;
memcpy(ilits->spi_tx, txbuf, n_tx);
duplex_len = n_tx + n_rx + offset;
if (duplex_len % DMA_TRANSFER_MAX_LEN)
xferloop = (duplex_len / DMA_TRANSFER_MAX_LEN) + 1;
else
xferloop = duplex_len / DMA_TRANSFER_MAX_LEN;
xferlen = duplex_len;
for (xfercnt = 0; xfercnt < xferloop; xfercnt++) {
if (xferlen > DMA_TRANSFER_MAX_LEN)
xferlen = DMA_TRANSFER_MAX_LEN;
xfer[xfercnt].len = xferlen;
xfer[xfercnt].tx_buf = ilits->spi_tx;
xfer[xfercnt].rx_buf = ilits->spi_rx + xfercnt * DMA_TRANSFER_MAX_LEN;
spi_message_add_tail(&xfer[xfercnt], &message);
xferlen = duplex_len - (xfercnt + 1) * DMA_TRANSFER_MAX_LEN;
}
status = spi_sync(spi, &message);
if (status == 0) {
if (ilits->spi_rx[1] != SPI_ACK && !atomic_read(&ilits->ice_stat)) {
status = DO_SPI_RECOVER;
ILI_ERR("Do spi recovery: rxbuf[1] = 0x%x, ice = %d\n", ilits->spi_rx[1], atomic_read(&ilits->ice_stat));
break;
}
memcpy((u8 *)rxbuf, ilits->spi_rx + offset + 1, n_rx);
} else {
ILI_ERR("spi read fail, status = %d\n", status);
}
break;
default:
ILI_INFO("Unknown command 0x%x\n", cmd);
break;
}
out:
ipio_kfree((void **)&xfer);
return status;
}
#else
#define DMA_TRANSFER_MAX_CHUNK 4 /* number of chunks to be transferred. */
#define DMA_TRANSFER_MAX_LEN 4096 /* length of a chunk. */
int ili_spi_write_then_read_split(struct spi_device *spi,
const void *txbuf, unsigned n_tx,
void *rxbuf, unsigned n_rx)
{
int status = -1, duplex_len = 0;
int xfercnt = 0, xferlen = 0, xferloop = 0;
int offset = 0;
u8 cmd = 0;
struct spi_message message;
struct spi_transfer xfer[DMA_TRANSFER_MAX_CHUNK];
if (n_rx > SPI_RX_BUF_SIZE) {
ILI_ERR("Rx length is greater than spi local buf, abort\n");
status = -ENOMEM;
goto out;
}
spi_message_init(&message);
memset(xfer, 0, sizeof(xfer));
memset(ilits->spi_tx, 0x0, SPI_TX_BUF_SIZE);
memset(ilits->spi_rx, 0x0, SPI_RX_BUF_SIZE);
if ((n_tx > 0) && (n_rx > 0))
cmd = SPI_READ;
else
cmd = SPI_WRITE;
switch (cmd) {
case SPI_WRITE:
if (n_tx % DMA_TRANSFER_MAX_LEN)
xferloop = (n_tx / DMA_TRANSFER_MAX_LEN) + 1;
else
xferloop = n_tx / DMA_TRANSFER_MAX_LEN;
if (xferloop > DMA_TRANSFER_MAX_CHUNK) {
ILI_ERR("xferloop = %d > %d\n", xferloop, DMA_TRANSFER_MAX_CHUNK);
status = -EINVAL;
break;
}
xferlen = n_tx;
memcpy(ilits->spi_tx, (u8 *)txbuf, xferlen);
for (xfercnt = 0; xfercnt < xferloop; xfercnt++) {
if (xferlen > DMA_TRANSFER_MAX_LEN)
xferlen = DMA_TRANSFER_MAX_LEN;
xfer[xfercnt].len = xferlen;
xfer[xfercnt].tx_buf = ilits->spi_tx + xfercnt * DMA_TRANSFER_MAX_LEN;
spi_message_add_tail(&xfer[xfercnt], &message);
xferlen = n_tx - (xfercnt+1) * DMA_TRANSFER_MAX_LEN;
}
status = spi_sync(spi, &message);
break;
case SPI_READ:
if (n_tx > DMA_TRANSFER_MAX_LEN) {
ILI_ERR("Tx length must be lower than dma length (%d).\n", DMA_TRANSFER_MAX_LEN);
status = -EINVAL;
break;
}
if (!atomic_read(&ilits->ice_stat))
offset = 2;
memcpy(ilits->spi_tx, txbuf, n_tx);
duplex_len = n_tx + n_rx + offset;
if (duplex_len % DMA_TRANSFER_MAX_LEN)
xferloop = (duplex_len / DMA_TRANSFER_MAX_LEN) + 1;
else
xferloop = duplex_len / DMA_TRANSFER_MAX_LEN;
if (xferloop > DMA_TRANSFER_MAX_CHUNK) {
ILI_ERR("xferloop = %d > %d\n", xferloop, DMA_TRANSFER_MAX_CHUNK);
status = -EINVAL;
break;
}
xferlen = duplex_len;
for (xfercnt = 0; xfercnt < xferloop; xfercnt++) {
if (xferlen > DMA_TRANSFER_MAX_LEN)
xferlen = DMA_TRANSFER_MAX_LEN;
xfer[xfercnt].len = xferlen;
xfer[xfercnt].tx_buf = ilits->spi_tx;
xfer[xfercnt].rx_buf = ilits->spi_rx + xfercnt * DMA_TRANSFER_MAX_LEN;
spi_message_add_tail(&xfer[xfercnt], &message);
xferlen = duplex_len - (xfercnt + 1) * DMA_TRANSFER_MAX_LEN;
}
status = spi_sync(spi, &message);
if (status == 0) {
if (ilits->spi_rx[1] != SPI_ACK && !atomic_read(&ilits->ice_stat)) {
status = DO_SPI_RECOVER;
ILI_ERR("Do spi recovery: rxbuf[1] = 0x%x, ice = %d\n", ilits->spi_rx[1], atomic_read(&ilits->ice_stat));
break;
}
memcpy((u8 *)rxbuf, ilits->spi_rx + offset + 1, n_rx);
} else {
ILI_ERR("spi read fail, status = %d\n", status);
}
break;
default:
ILI_INFO("Unknown command 0x%x\n", cmd);
break;
}
out:
return status;
}
#endif
#else
int ili_spi_write_then_read_direct(struct spi_device *spi,
const void *txbuf, unsigned n_tx,
void *rxbuf, unsigned n_rx)
{
int status = -1, duplex_len = 0;
int offset = 0;
u8 cmd;
struct spi_message message;
struct spi_transfer xfer;
if (n_rx > SPI_RX_BUF_SIZE) {
ILI_ERR("Rx length is greater than spi local buf, abort\n");
status = -ENOMEM;
goto out;
}
spi_message_init(&message);
memset(&xfer, 0, sizeof(xfer));
if ((n_tx > 0) && (n_rx > 0))
cmd = SPI_READ;
else
cmd = SPI_WRITE;
switch (cmd) {
case SPI_WRITE:
xfer.len = n_tx;
xfer.tx_buf = txbuf;
spi_message_add_tail(&xfer, &message);
status = spi_sync(spi, &message);
break;
case SPI_READ:
if (!atomic_read(&ilits->ice_stat))
offset = 2;
duplex_len = n_tx + n_rx + offset;
if ((duplex_len > SPI_TX_BUF_SIZE) ||
(duplex_len > SPI_RX_BUF_SIZE)) {
ILI_ERR("duplex_len is over than dma buf, abort\n");
status = -ENOMEM;
break;
}
memset(ilits->spi_tx, 0x0, SPI_TX_BUF_SIZE);
memset(ilits->spi_rx, 0x0, SPI_RX_BUF_SIZE);
xfer.len = duplex_len;
memcpy(ilits->spi_tx, txbuf, n_tx);
xfer.tx_buf = ilits->spi_tx;
xfer.rx_buf = ilits->spi_rx;
spi_message_add_tail(&xfer, &message);
status = spi_sync(spi, &message);
if (status == 0) {
if (ilits->spi_rx[1] != SPI_ACK && !atomic_read(&ilits->ice_stat)) {
status = DO_SPI_RECOVER;
ILI_ERR("Do spi recovery: rxbuf[1] = 0x%x, ice = %d\n", ilits->spi_rx[1], atomic_read(&ilits->ice_stat));
break;
}
memcpy((u8 *)rxbuf, ilits->spi_rx + offset + 1, n_rx);
} else {
ILI_ERR("spi read fail, status = %d\n", status);
}
break;
default:
ILI_INFO("Unknown command 0x%x\n", cmd);
break;
}
out:
return status;
}
#endif
static int ili_spi_mp_pre_cmd(u8 cdc)
{
u8 pre[5] = {0};
if (!atomic_read(&ilits->mp_stat) || cdc != P5_X_SET_CDC_INIT ||
ilits->chip->core_ver >= CORE_VER_1430)
return 0;
ILI_DBG("mp test with pre commands\n");
pre[0] = SPI_WRITE;
pre[1] = 0x0;/* dummy byte */
pre[2] = 0x2;/* Write len byte */
pre[3] = P5_X_READ_DATA_CTRL;
pre[4] = P5_X_GET_CDC_DATA;
if (ilits->spi_write_then_read(ilits->spi, pre, 5, NULL, 0) < 0) {
ILI_ERR("Failed to write pre commands\n");
return -1;
}
pre[0] = SPI_WRITE;
pre[1] = 0x0;/* dummy byte */
pre[2] = 0x1;/* Write len byte*/
pre[3] = P5_X_GET_CDC_DATA;
if (ilits->spi_write_then_read(ilits->spi, pre, 4, NULL, 0) < 0) {
ILI_ERR("Failed to write pre commands\n");
return -1;
}
return 0;
}
static int ili_spi_pll_clk_wakeup(void)
{
int index = 0;
u8 wdata[32] = {0};
u8 wakeup[9] = {0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3};
u32 wlen = sizeof(wakeup);
wdata[0] = SPI_WRITE;
wdata[1] = wlen >> 8;
wdata[2] = wlen & 0xff;
index = 3;
ipio_memcpy(&wdata[index], wakeup, wlen, wlen);
wlen += index;
ILI_INFO("Write dummy to wake up spi pll clk\n");
if (ilits->spi_write_then_read(ilits->spi, wdata, wlen, NULL, 0) < 0) {
ILI_INFO("spi slave write error\n");
return -1;
}
mdelay(1);
return 0;
}
static int ili_spi_wrapper(u8 *txbuf, u32 wlen, u8 *rxbuf, u32 rlen, bool spi_irq, bool i2c_irq)
{
int ret = 0;
int mode = 0, index = 0;
u8 wdata[128] = {0};
u8 checksum = 0;
bool ice = atomic_read(&ilits->ice_stat);
if (wlen > 0) {
if (!txbuf) {
ILI_ERR("txbuf is null\n");
return -ENOMEM;
}
/* 3 bytes data consist of length and header */
if ((wlen + 4) > sizeof(wdata)) {
ILI_ERR("WARNING! wlen(%d) > wdata(%d), using wdata length to transfer\n", wlen, (int)sizeof(wdata));
wlen = sizeof(wdata) - 4;
}
}
if (rlen > 0) {
if (!rxbuf) {
ILI_ERR("rxbuf is null\n");
return -ENOMEM;
}
}
if (rlen > 0 && !wlen)
mode = SPI_READ;
else
mode = SPI_WRITE;
if (ilits->int_pulse)
ilits->detect_int_stat = ili_ic_check_int_pulse;
else
ilits->detect_int_stat = ili_ic_check_int_level;
if (spi_irq)
atomic_set(&ilits->cmd_int_check, ENABLE);
switch (mode) {
case SPI_WRITE:
atomic_set(&ilits->ignore_report, START);
#if (PLL_CLK_WAKEUP_TP_RESUME == ENABLE)
if (ilits->pll_clk_wakeup == true) {
#else
if ((ilits->pll_clk_wakeup == true) && (ilits->tp_suspend == true)) {
#endif
ret = ili_spi_pll_clk_wakeup();
if (ret < 0) {
ILI_ERR("Wakeup pll clk error\n");
break;
}
}
if (ice) {
wdata[0] = SPI_WRITE;
index = 1;
} else {
wdata[0] = SPI_WRITE;
wdata[1] = wlen >> 8;
wdata[2] = wlen & 0xff;
index = 3;
}
ipio_memcpy(&wdata[index], txbuf, wlen, wlen);
wlen += index;
/*
* NOTE: If TP driver is doing MP test and commanding 0xF1 to FW, we add a checksum
* to the last index and plus 1 with size.
*/
if (atomic_read(&ilits->mp_stat) && wdata[index] == P5_X_SET_CDC_INIT) {
checksum = ili_calc_packet_checksum(&wdata[index], wlen - index);
wdata[wlen] = checksum;
wlen++;
wdata[1] = (wlen - index) >> 8;
wdata[2] = (wlen - index) & 0xff;
ili_dump_data(wdata, 8, wlen, 0, "mp cdc cmd with checksum");
}
ret = ilits->spi_write_then_read(ilits->spi, wdata, wlen, txbuf, 0);
if (!ice) {
ILI_DBG("send cmd delay 1ms\n");
mdelay(1);
}
if (ret < 0) {
ILI_INFO("spi-wrapper write error\n");
break;
}
/* Won't break if it needs to read data following with writing. */
if (!rlen)
break;
#if 0 /* if warning: this statement may fall through modify 0 to 1 */
else {
if (!ice && spi_irq) {
/* Check INT triggered by FW when sending cmds. */
if (ilits->detect_int_stat(false) < 0) {
ILI_ERR("ERROR! Check INT timeout\n");
ret = -ETIME;
break;
}
}
ret = ili_spi_mp_pre_cmd(wdata[3]);
if (ret < 0)
ILI_ERR("spi-wrapper mp pre cmd error\n");
wdata[0] = SPI_READ;
ret = ilits->spi_write_then_read(ilits->spi, wdata, 1, rxbuf, rlen);
if (ret < 0)
ILI_ERR("spi-wrapper read error\n");
break;
}
#endif
case SPI_READ:
if (!ice && spi_irq) {
/* Check INT triggered by FW when sending cmds. */
if (ilits->detect_int_stat(false) < 0) {
ILI_ERR("ERROR! Check INT timeout\n");
ret = -ETIME;
break;
}
}
ret = ili_spi_mp_pre_cmd(wdata[3]);
if (ret < 0)
ILI_ERR("spi-wrapper mp pre cmd error\n");
wdata[0] = SPI_READ;
ret = ilits->spi_write_then_read(ilits->spi, wdata, 1, rxbuf, rlen);
if (ret < 0)
ILI_ERR("spi-wrapper read error\n");
break;
default:
ILI_ERR("Unknown spi mode (%d)\n", mode);
ret = -EINVAL;
break;
}
atomic_set(&ilits->ignore_report, END);
if (spi_irq)
atomic_set(&ilits->cmd_int_check, DISABLE);
return ret;
}
int ili_core_spi_setup(int num)
{
u32 freq[] = {
TP_SPI_CLK_1M,
TP_SPI_CLK_2M,
TP_SPI_CLK_3M,
TP_SPI_CLK_4M,
TP_SPI_CLK_5M,
TP_SPI_CLK_6M,
TP_SPI_CLK_7M,
TP_SPI_CLK_8M,
TP_SPI_CLK_9M,
TP_SPI_CLK_10M,
TP_SPI_CLK_11M,
TP_SPI_CLK_12M,
TP_SPI_CLK_13M,
TP_SPI_CLK_14M,
TP_SPI_CLK_15M
};
if (num >= ARRAY_SIZE(freq)) {
ILI_ERR("Invaild clk freq, set default clk freq\n");
num = 7;
}
ILI_INFO("spi clock = %d\n", freq[num]);
ilits->spi->mode = SPI_MODE_0;
ilits->spi->bits_per_word = 8;
ilits->spi->max_speed_hz = freq[num];
ilits->spi->chip_select = 0;
if (spi_setup(ilits->spi) < 0) {
ILI_ERR("Failed to setup spi device\n");
return -ENODEV;
}
ILI_INFO("name = %s, bus_num = %d,cs = %d, mode = %d, speed = %d\n",
ilits->spi->modalias,
ilits->spi->master->bus_num,
ilits->spi->chip_select,
ilits->spi->mode,
ilits->spi->max_speed_hz);
return 0;
}
void ili_parse_tp_module(void)
{
int tp_module = 0;
#ifdef ILI_TP_MODULE_EN
if(active_panel_name) {
if (strstr(active_panel_name, "tm") || strstr(active_panel_name, "tianma")) {
tp_module = MODEL_TM;
}
else if (strstr(active_panel_name, "djn")) {
tp_module = MODEL_DJ;
}
else if (strstr(active_panel_name, "txd")) {
tp_module = MODEL_TXD;
}
else if (strstr(active_panel_name, "csot")) {
tp_module = MODEL_CSOT;
}
else if (strstr(active_panel_name, "boe")) {
tp_module = MODEL_BOE;
}
else if (strstr(active_panel_name, "auo")) {
tp_module = MODEL_AUO;
}
else
ILI_INFO("MODEL for panel:%s to be added!\n", active_panel_name);
if (tp_module)
ILI_INFO("get tp_module:%d\n", tp_module);
}
else
ILI_INFO("active_panel NULL\n");
#endif
ilits->tp_module = tp_module;
}
static int parse_dt(struct device_node *np)
{
int32_t ret = 0;
#ifdef ILI_DOUBLE_TAP_CTRL
uint32_t value;
if (!of_property_read_u32(np, "ilitek,supported_gesture_type", &value)) {
ilits->supported_gesture_type = (uint8_t)value;
ILI_INFO("supported_gesture_type=%d\n", ilits->supported_gesture_type);
}
else
ILI_INFO("warn: supported_gesture_type not set\n");
#endif //ILI_DOUBLE_TAP_CTRL
#ifdef ILI_SENSOR_EN
if (of_property_read_bool(np, "ilitek,report_gesture_key")) {
ILI_INFO("ilitek,report_gesture_key set");
ilits->report_gesture_key = 1;
} else {
ilits->report_gesture_key = 0;
}
#endif
#if CHARGER_NOTIFIER_CALLBACK
ret = of_property_read_string(np, "touch,psy-name", &ilits->psy_name);
if (ilits->psy_name)
ILI_INFO("%s: get psy_name:%s", __func__, ilits->psy_name);
#endif
return ret;
}
#ifdef ILI_MTK_CHECK_PANEL
static void ili_get_active_panel(void)
{
int rc;
struct device_node *chosen = of_find_node_by_name(NULL, "chosen");
if(chosen) {
rc = of_property_read_string(chosen, "mmi,panel_name", (const char **)&active_panel_name);
if (rc)
ILI_INFO("mmi,panel_name null\n");
else
ILI_DBG("active_panel_name=%s\n", active_panel_name);
}
else
ILI_INFO("chosen node null\n");
}
static int ili_check_panel(void)
{
ILI_DBG("enter");
ili_get_active_panel();
if (!active_panel_name)
ILI_INFO("active_panel NULL\n");
else if(strstr(active_panel_name, "ili78") || strstr(active_panel_name, "ili98") || strstr(active_panel_name, "il77"))
{
ILI_INFO("matched active_panel:%s ", active_panel_name);
return 0;
}
else
ILI_DBG("not macthed active_panel:%s\n", active_panel_name);
return -1;
}
#endif
static int ilitek_spi_probe(struct spi_device *spi)
{
struct touch_bus_info *info =
container_of(to_spi_driver(spi->dev.driver),
struct touch_bus_info, bus_driver);
#ifdef ILI_MTK_CHECK_PANEL
int ret;
#endif
ILI_INFO("ilitek spi probe\n");
if (!spi) {
ILI_ERR("spi device is NULL\n");
return -ENODEV;
}
#ifdef ILI_MTK_CHECK_PANEL
ret = ili_check_panel();
if (ret) {
ILI_INFO("check panel error\n");
return ret;
}
#endif
ilits = devm_kzalloc(&spi->dev, sizeof(struct ilitek_ts_data), GFP_KERNEL);
if (ERR_ALLOC_MEM(ilits)) {
ILI_ERR("Failed to allocate ts memory, %ld\n", PTR_ERR(ilits));
return -ENOMEM;
}
if (spi->master->flags & SPI_MASTER_HALF_DUPLEX) {
ILI_ERR("Full duplex not supported by master\n");
return -EIO;
}
ilits->update_buf = kzalloc(MAX_HEX_FILE_SIZE, GFP_KERNEL | GFP_DMA);
if (ERR_ALLOC_MEM(ilits->update_buf)) {
ILI_ERR("fw kzalloc error\n");
return -ENOMEM;
}
/* Used for receiving touch data only, do not mix up with others. */
ilits->tr_buf = kzalloc(TR_BUF_SIZE, GFP_ATOMIC);
if (ERR_ALLOC_MEM(ilits->tr_buf)) {
ILI_ERR("failed to allocate touch report buffer\n");
return -ENOMEM;
}
ilits->spi_tx = kzalloc(SPI_TX_BUF_SIZE, GFP_KERNEL | GFP_DMA);
if (ERR_ALLOC_MEM(ilits->spi_tx)) {
ILI_ERR("Failed to allocate spi tx buffer\n");
return -ENOMEM;
}
ilits->spi_rx = kzalloc(SPI_RX_BUF_SIZE, GFP_KERNEL | GFP_DMA);
if (ERR_ALLOC_MEM(ilits->spi_rx)) {
ILI_ERR("Failed to allocate spi rx buffer\n");
return -ENOMEM;
}
ilits->gcoord = kzalloc(sizeof(struct gesture_coordinate), GFP_KERNEL);
if (ERR_ALLOC_MEM(ilits->gcoord)) {
ILI_ERR("Failed to allocate gresture coordinate buffer\n");
return -ENOMEM;
}
ilits->i2c = NULL;
ilits->spi = spi;
ilits->dev = &spi->dev;
ilits->hwif = info->hwif;
ilits->phys = "SPI";
ilits->wrapper = ili_spi_wrapper;
ilits->detect_int_stat = ili_ic_check_int_pulse;
ilits->int_pulse = true;
ilits->mp_retry = false;
#if SPI_DMA_TRANSFER_SPLIT
ilits->spi_write_then_read = ili_spi_write_then_read_split;
#else
ilits->spi_write_then_read = ili_spi_write_then_read_direct;
#endif
ilits->actual_tp_mode = P5_X_FW_AP_MODE;
ilits->tp_data_format = DATA_FORMAT_DEMO;
ilits->tp_data_len = P5_X_DEMO_MODE_PACKET_LEN;
ilits->tp_data_mode = AP_MODE;
if (TDDI_RST_BIND)
ilits->reset = TP_IC_WHOLE_RST_WITH_FLASH;
else
ilits->reset = TP_HW_RST_ONLY;
ilits->rst_edge_delay = 10;
ilits->fw_open = REQUEST_FIRMWARE;
ilits->fw_upgrade_mode = UPGRADE_IRAM;
ilits->mp_move_code = ili_move_mp_code_iram;
ilits->gesture_move_code = ili_move_gesture_code_iram;
ilits->esd_recover = ili_wq_esd_spi_check;
ilits->esd_func_ctrl = ENABLE_WQ_ESD;
ilits->ges_recover = ili_touch_esd_gesture_iram;
ilits->gesture_mode = DATA_FORMAT_GESTURE_INFO;
ilits->gesture_demo_ctrl = DISABLE;
ilits->wtd_ctrl = OFF;
ilits->report = ENABLE;
ilits->dnp = DISABLE;
ilits->dlnp = DISABLE;
ilits->irq_tirgger_type = IRQF_TRIGGER_FALLING;
ilits->info_from_hex = ENABLE;
ilits->wait_int_timeout = AP_INT_TIMEOUT;
ilits->ice_flash_cs_ctrl = ENABLE;
ilits->compress_disable = ENABLE;
ilits->compress_handonly_disable = ENABLE;
ilits->compress_penonly_disable = ENABLE;
#if MULTI_REPORT_RATE
ilits->current_report_rate_mode = DDI60_TP120; /*Default report mode*/
#endif
//---parse dts---
parse_dt(spi->dev.of_node);
//---parse tp module---
ili_parse_tp_module();
#if ENABLE_GESTURE
ilits->gesture = ENABLE;
ilits->ges_sym.double_tap = DOUBLE_TAP;
ilits->ges_sym.alphabet_line_2_top = ALPHABET_LINE_2_TOP;
ilits->ges_sym.alphabet_line_2_bottom = ALPHABET_LINE_2_BOTTOM;
ilits->ges_sym.alphabet_line_2_left = ALPHABET_LINE_2_LEFT;
ilits->ges_sym.alphabet_line_2_right = ALPHABET_LINE_2_RIGHT;
ilits->ges_sym.alphabet_m = ALPHABET_M;
ilits->ges_sym.alphabet_w = ALPHABET_W;
ilits->ges_sym.alphabet_c = ALPHABET_C;
ilits->ges_sym.alphabet_E = ALPHABET_E;
ilits->ges_sym.alphabet_V = ALPHABET_V;
ilits->ges_sym.alphabet_O = ALPHABET_O;
ilits->ges_sym.alphabet_S = ALPHABET_S;
ilits->ges_sym.alphabet_Z = ALPHABET_Z;
ilits->ges_sym.alphabet_V_down = ALPHABET_V_DOWN;
ilits->ges_sym.alphabet_V_left = ALPHABET_V_LEFT;
ilits->ges_sym.alphabet_V_right = ALPHABET_V_RIGHT;
ilits->ges_sym.alphabet_two_line_2_bottom = ALPHABET_TWO_LINE_2_BOTTOM;
ilits->ges_sym.alphabet_F = ALPHABET_F;
ilits->ges_sym.alphabet_AT = ALPHABET_AT;
ILI_INFO("gesture eanble:%d\n", ilits->gesture);
#endif
if (ili_core_spi_setup(SPI_CLK) < 0)
return -EINVAL;
return info->hwif->plat_probe();
}
static int ilitek_spi_remove(struct spi_device *spi)
{
ILI_INFO();
return 0;
}
static struct spi_device_id tp_spi_id[] = {
{TDDI_DEV_ID, 0},
{},
};
int ili_interface_dev_init(struct ilitek_hwif_info *hwif)
{
struct touch_bus_info *info;
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info) {
ILI_ERR("faied to allocate spi_driver\n");
return -ENOMEM;
}
if (hwif->bus_type != BUS_SPI) {
ILI_ERR("Not SPI dev\n");
ipio_kfree((void **)&info);
return -EINVAL;
}
hwif->info = info;
info->bus_driver.driver.name = hwif->name;
info->bus_driver.driver.owner = hwif->owner;
info->bus_driver.driver.of_match_table = hwif->of_match_table;
info->bus_driver.driver.pm = hwif->pm;
info->bus_driver.probe = ilitek_spi_probe;
info->bus_driver.remove = ilitek_spi_remove;
info->bus_driver.id_table = tp_spi_id;
info->hwif = hwif;
return spi_register_driver(&info->bus_driver);
}
void ili_interface_dev_exit(struct ilitek_ts_data *ts, bool flag)
{
struct touch_bus_info *info = (struct touch_bus_info *)ilits->hwif->info;
ILI_INFO("remove spi dev\n");
kfree(ilits->update_buf);
kfree(ilits->spi_tx);
kfree(ilits->spi_rx);
if (flag == ENABLE) {
spi_unregister_driver(&info->bus_driver);
ipio_kfree((void **)&info);
}
}

File diff suppressed because it is too large Load diff