[Touch][A311D]support focaltech touch panel:focaltech FTS_5726

PD#SWPL-27361
Problem:
	support focaltech touch panel:focaltech FTS_5726

Solution:
	add focaltech FTS_5726 driver

Verify:
	on google newman platform

Signed-off-by: chunlong.cao <chunlong.cao@amlogic.com>
Change-Id: I79ff49e062233c3c7202796be03f79f7fc32e52f
This commit is contained in:
chunlong.cao
2020-06-09 17:08:53 +08:00
committed by Chris
parent c0e6f5cd63
commit cfc696f078
19 changed files with 8324 additions and 0 deletions

View File

@@ -1214,6 +1214,8 @@ config TOUCHSCREEN_ROHM_BU21023
To compile this driver as a module, choose M here: the
module will be called bu21023_ts.
source "drivers/input/touchscreen/focaltech_touch/Kconfig"
config TOUCHSCREEN_DWAV_USB_MT
tristate "D-WAV Scientific USB MultiTouch"
depends on USB_ARCH_HAS_HCD

View File

@@ -99,4 +99,5 @@ obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o
obj-$(CONFIG_TOUCHSCREEN_ZFORCE) += zforce_ts.o
obj-$(CONFIG_TOUCHSCREEN_COLIBRI_VF50) += colibri-vf50-ts.o
obj-$(CONFIG_TOUCHSCREEN_ROHM_BU21023) += rohm_bu21023.o
obj-$(CONFIG_TOUCHSCREEN_FTS_5726) += focaltech_touch/
obj-$(CONFIG_TOUCHSCREEN_DWAV_USB_MT) += dwav-usb-mt.o

View File

@@ -0,0 +1,73 @@
#
# Focaltech Touchscreen driver configuration
#
config TOUCHSCREEN_FTS_3427
bool "Focaltech Touchscreen FT3427"
depends on I2C
default n
help
Say Y here if you have Focaltech 3427 IC.
If unsure, say N.
config TOUCHSCREEN_FTS_5726
bool "Focaltech Touchscreen FT5726"
depends on I2C
default n
help
Say Y here if you have FocalTech 5726 IC.
If unsure, say N.
if TOUCHSCREEN_FTS_5726
config TOUCHSCREEN_FTS_5726_P1
bool "Focaltech Touchscreen FT5726 for P1 Build Only"
depends on I2C
default n
help
Say Y here if you have FocalTech 5726 IC for P1 build.
If unsure, say N.
config TOUCHSCREEN_FTS_5726_MP_POR
bool "Focaltech Touchscreen FT5726 for EVT Build Onwards"
depends on I2C
default n
help
Say Y here if you have FocalTech 5726 IC with the POR
touch configuration and HW. This should only be used
for devices from the EVT build onwards.
If unsure, say N.
config TOUCHSCREEN_FTS_5726_UPDATE_TOPTOUCH_FW
bool "Focaltech Touchscreen Update TopTouch FW"
depends on I2C
default n
help
Say Y here if you have FocalTech 5726 IC,
and want to update FW for a TopTouch panel.
If unsure, say N.
config TOUCHSCREEN_FTS_5726_UPDATE_TOPGROUP_FW
bool "Focaltech Touchscreen Update TopGroup FW"
depends on I2C
default n
help
Say Y here if you have FocalTech 5726 IC,
and want to update FW for a TopGroup panel.
If unsure, say N.
config TOUCHSCREEN_FTS_5726_UPDATE_LENSONE_FW
bool "Focaltech Touchscreen Update Lensone FW"
depends on I2C
default n
help
Say Y here if you have FocalTech 5726 IC,
and want to update FW for a Lensone panel.
If unsure, say N.
endif # TOUCHSCREEN_FTS_5726
config TOUCHSCREEN_FTS_DIRECTORY
string "Focaltech Touchscreen Directory"
default "focaltech_touch"
depends on TOUCHSCREEN_FTS_3427 || TOUCHSCREEN_FTS_5726

View File

@@ -0,0 +1,25 @@
#
# Makefile for the focaltech touchscreen drivers.
#
# Each configuration option enables a list of files.
obj-$(CONFIG_TOUCHSCREEN_FTS_3427) += focaltech_core.o
obj-$(CONFIG_TOUCHSCREEN_FTS_3427) += focaltech_ex_fun.o
obj-$(CONFIG_TOUCHSCREEN_FTS_3427) += focaltech_ex_mode.o
obj-$(CONFIG_TOUCHSCREEN_FTS_3427) += focaltech_flash.o
obj-$(CONFIG_TOUCHSCREEN_FTS_3427) += focaltech_gesture.o
obj-$(CONFIG_TOUCHSCREEN_FTS_3427) += focaltech_esdcheck.o
obj-$(CONFIG_TOUCHSCREEN_FTS_3427) += focaltech_i2c.o
obj-$(CONFIG_TOUCHSCREEN_FTS_3427) += focaltech_point_report_check.o
obj-$(CONFIG_TOUCHSCREEN_FTS_3427) += focaltech_flash/
obj-$(CONFIG_TOUCHSCREEN_FTS_5726) += focaltech_core.o
obj-$(CONFIG_TOUCHSCREEN_FTS_5726) += focaltech_ex_fun.o
obj-$(CONFIG_TOUCHSCREEN_FTS_5726) += focaltech_ex_mode.o
obj-$(CONFIG_TOUCHSCREEN_FTS_5726) += focaltech_flash.o
obj-$(CONFIG_TOUCHSCREEN_FTS_5726) += focaltech_gesture.o
obj-$(CONFIG_TOUCHSCREEN_FTS_5726) += focaltech_esdcheck.o
obj-$(CONFIG_TOUCHSCREEN_FTS_5726) += focaltech_i2c.o
obj-$(CONFIG_TOUCHSCREEN_FTS_5726) += focaltech_point_report_check.o
obj-$(CONFIG_TOUCHSCREEN_FTS_5726) += focaltech_flash/

View File

@@ -0,0 +1,168 @@
/*
*
* FocalTech fts TouchScreen driver.
*
* Copyright (c) 2010-2018, Focaltech Ltd. All rights reserved.
*
* 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.
*
*/
/*****************************************************************************
*
* File Name: focaltech_common.h
*
* Author: Focaltech Driver Team
*
* Created: 2016-08-16
*
* Abstract:
*
* Reference:
*
*****************************************************************************/
#ifndef __LINUX_FOCALTECH_COMMON_H__
#define __LINUX_FOCALTECH_COMMON_H__
#include "focaltech_config.h"
/*****************************************************************************
* Macro definitions using #define
*****************************************************************************/
#define FTS_DRIVER_VERSION "Focaltech V2.2 20180321"
#define BYTE_OFF_0(x) (u8)((x) & 0xFF)
#define BYTE_OFF_8(x) (u8)((x >> 8) & 0xFF)
#define BYTE_OFF_16(x) (u8)((x >> 16) & 0xFF)
#define BYTE_OFF_24(x) (u8)((x >> 24) & 0xFF)
#define FLAGBIT(x) (0x00000001 << (x))
#define FLAGBITS(x, y) ((0xFFFFFFFF >> (32 - (y) - 1)) << (x))
#define FLAG_ICSERIALS_LEN 8
#define FLAG_HID_BIT 10
#define FLAG_IDC_BIT 11
#define IC_SERIALS (FTS_CHIP_TYPE & FLAGBITS(0, FLAG_ICSERIALS_LEN-1))
#define IC_TO_SERIALS(x) ((x) & FLAGBITS(0, FLAG_ICSERIALS_LEN-1))
#define FTS_CHIP_IDC ((FTS_CHIP_TYPE & FLAGBIT(FLAG_IDC_BIT)) == FLAGBIT(FLAG_IDC_BIT))
#define FTS_HID_SUPPORTTED ((FTS_CHIP_TYPE & FLAGBIT(FLAG_HID_BIT)) == FLAGBIT(FLAG_HID_BIT))
#if defined(CONFIG_TOUCHSCREEN_FTS_3427) && !defined(CONFIG_TOUCHSCREEN_FTS_5726)
#define FTS_CHIP_TYPE_MAPPING { { 0x02, 0x54, 0x22, 0x54, 0x22, 0x00, 0x00, 0x54, 0x2C } }
#elif defined(CONFIG_TOUCHSCREEN_FTS_5726) && !defined(CONFIG_TOUCHSCREEN_FTS_3427)
#define FTS_CHIP_TYPE_MAPPING { { 0x01, 0x58, 0x22, 0x58, 0x22, 0x00, 0x00, 0x58, 0x2C } }
#endif
#define I2C_BUFFER_LENGTH_MAXINUM 256
#define FILE_NAME_LENGTH 128
#define ENABLE 1
#define DISABLE 0
#define VALID 1
#define INVALID 0
#define FTS_CMD_START1 0x55
#define FTS_CMD_START2 0xAA
#define FTS_CMD_START_DELAY 10
#define FTS_CMD_READ_ID 0x90
#define FTS_CMD_READ_ID_LEN 4
#define FTS_CMD_READ_ID_LEN_INCELL 1
/*register address*/
#define FTS_REG_INT_CNT 0x8F
#define FTS_REG_FLOW_WORK_CNT 0x91
#define FTS_REG_WORKMODE 0x00
#define FTS_REG_WORKMODE_FACTORY_VALUE 0x40
#define FTS_REG_WORKMODE_WORK_VALUE 0x00
#define FTS_REG_MAX_REPORT_RATE 0x88
#define FTS_REG_REPORT_RATE_60HZ 0x06
#define FTS_REG_ESDCHECK_DISABLE 0x8D
#define FTS_REG_CHIP_ID 0xA3
#define FTS_REG_CHIP_ID2 0x9F
#define FTS_REG_POWER_MODE 0xA5
#define FTS_REG_POWER_MODE_SLEEP_VALUE 0x03
#define FTS_REG_FW_VER 0xA6
#define FTS_REG_VENDOR_ID 0xA8
#define FTS_REG_PANEL_ID 0xAC
#define FTS_REG_LCD_BUSY_NUM 0xAB
#define FTS_REG_FACE_DEC_MODE_EN 0xB0
#define FTS_REG_FACE_DEC_MODE_STATUS 0x01
#define FTS_REG_IDE_PARA_VER_ID 0xB5
#define FTS_REG_IDE_PARA_STATUS 0xB6
#define FTS_REG_GLOVE_MODE_EN 0xC0
#define FTS_REG_COVER_MODE_EN 0xC1
#define FTS_REG_CHARGER_MODE_EN 0x8B
#define FTS_REG_GESTURE_EN 0xD0
#define FTS_REG_GESTURE_OUTPUT_ADDRESS 0xD3
#define FTS_REG_MODULE_ID 0xE3
#define FTS_REG_LIC_VER 0xE4
#define FTS_REG_ESD_SATURATE 0xED
#define FTS_SYSFS_ECHO_ON(buf) (buf[0] == '1')
#define FTS_SYSFS_ECHO_OFF(buf) (buf[0] == '0')
#define kfree_safe(pbuf) do { \
if (pbuf) { \
kfree(pbuf); \
pbuf = NULL; \
} \
} while (0)
/*****************************************************************************
* Alternative mode (When something goes wrong, the modules may be able to solve the problem.)
*****************************************************************************/
/*
* point report check
* default: disable
*/
#define FTS_POINT_REPORT_CHECK_EN 0
/*****************************************************************************
* Global variable or extern global variabls/functions
*****************************************************************************/
struct ft_chip_t {
u64 type;
u8 chip_idh;
u8 chip_idl;
u8 rom_idh;
u8 rom_idl;
u8 pb_idh;
u8 pb_idl;
u8 bl_idh;
u8 bl_idl;
};
struct ts_ic_info {
bool is_incell;
bool hid_supported;
struct ft_chip_t ids;
};
/*****************************************************************************
* DEBUG function define here
*****************************************************************************/
#if FTS_DEBUG_EN
#define FTS_DEBUG_LEVEL 1
#if (FTS_DEBUG_LEVEL == 2)
#define FTS_DEBUG(fmt, args...) printk("[FTS][%s]"fmt"\n", __func__, ##args)
#else
#define FTS_DEBUG(fmt, args...) printk("[FTS]"fmt"\n", ##args)
#endif
#define FTS_FUNC_ENTER() printk("[FTS]%s: Enter\n", __func__)
#define FTS_FUNC_EXIT() printk("[FTS]%s: Exit(%d)\n", __func__, __LINE__)
#else /* #if FTS_DEBUG_EN*/
#define FTS_DEBUG(fmt, args...)
#define FTS_FUNC_ENTER()
#define FTS_FUNC_EXIT()
#endif
#define FTS_INFO(fmt, args...) printk(KERN_INFO "[FTS][Info]"fmt"\n", ##args)
#define FTS_WARN(fmt, args...) printk(KERN_WARNING "[FTS][Warning]"fmt"\n", ##args)
#define FTS_ERROR(fmt, args...) printk(KERN_ERR "[FTS][Error]"fmt"\n", ##args)
#endif /* __LINUX_FOCALTECH_COMMON_H__ */

View File

@@ -0,0 +1,232 @@
/*
*
* FocalTech TouchScreen driver.
*
* Copyright (c) 2010-2018, FocalTech Systems, Ltd., all rights reserved.
*
* 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.
*
*/
/************************************************************************
*
* File Name: focaltech_config.h
*
* Author: Focaltech Driver Team
*
* Created: 2016-08-08
*
* Abstract: global configurations
*
* Version: v1.0
*
************************************************************************/
#ifndef _LINUX_FOCLATECH_CONFIG_H_
#define _LINUX_FOCLATECH_CONFIG_H_
/**************************************************/
/****** G: A, I: B, S: C, U: D ******************/
/****** chip type defines, do not modify *********/
#define _FT8716 0x87160805
#define _FT8736 0x87360806
#define _FT8006M 0x80060807
#define _FT7250 0x72500807
#define _FT8606 0x86060808
#define _FT8607 0x86070809
#define _FTE716 0xE716080A
#define _FT8006U 0x8006D80B
#define _FT8613 0x8613080C
#define _FT8719 0x8719080D
#define _FT8739 0x8739080E
#define _FT8615 0x8615080F
#define _FT8201 0x8201081
#define _FT5416 0x54160402
#define _FT5426 0x54260402
#define _FT5435 0x54350402
#define _FT5436 0x54360402
#define _FT5526 0x55260402
#define _FT5526I 0x5526B402
#define _FT5446 0x54460402
#define _FT5346 0x53460402
#define _FT5446I 0x5446B402
#define _FT5346I 0x5346B402
#define _FT7661 0x76610402
#define _FT7511 0x75110402
#define _FT7421 0x74210402
#define _FT7681 0x76810402
#define _FT3C47U 0x3C47D402
#define _FT3417 0x34170402
#define _FT3517 0x35170402
#define _FT3327 0x33270402
#define _FT3427 0x34270402
#define _FT7311 0x73110402
#define _FT5626 0x56260401
#define _FT5726 0x57260401
#define _FT5826B 0x5826B401
#define _FT5826S 0x5826C401
#define _FT7811 0x78110401
#define _FT3D47 0x3D470401
#define _FT3617 0x36170401
#define _FT3717 0x37170401
#define _FT3817B 0x3817B401
#define _FT3517U 0x3517D401
#define _FT6236U 0x6236D003
#define _FT6336G 0x6336A003
#define _FT6336U 0x6336D003
#define _FT6436U 0x6436D003
#define _FT3267 0x32670004
#define _FT3367 0x33670004
#define _FT5422U 0x5422D482
#define _FT3327DQQ_001 0x3327D482
#define _FT5446DQS_W01 0x5446D482
#define _FT5446DQS_W02 0x5446A482
#define _FT5446DQS_002 0x5446B482
#define _FT5446DQS_Q02 0x5446C482
#define _FT3518 0x35180481
#define _FT3558 0x35580481
/*************************************************/
/*
* choose your ic chip type of focaltech
*/
#if defined(CONFIG_TOUCHSCREEN_FTS_3427) && !defined(CONFIG_TOUCHSCREEN_FTS_5726)
#define FTS_CHIP_TYPE _FT3427
#elif defined(CONFIG_TOUCHSCREEN_FTS_5726) && !defined(CONFIG_TOUCHSCREEN_FTS_3427)
#define FTS_CHIP_TYPE _FT5726
#endif
/******************* Enables *********************/
/*********** 1 to enable, 0 to disable ***********/
/*
* show debug log info
* enable it for debug, disable it for release
*/
#define FTS_DEBUG_EN 0
/*
* Linux MultiTouch Protocol
* 1: Protocol B(default), 0: Protocol A
*/
#define FTS_MT_PROTOCOL_B_EN 1
/*
* Report Pressure in multitouch
* 1:enable(default),0:disable
*/
#define FTS_REPORT_PRESSURE_EN 1
/*
* Gesture function enable
* default: disable
*/
#define FTS_GESTURE_EN 0
/*
* ESD check & protection
* default: disable
*/
#define FTS_ESDCHECK_EN 0
/*
* Production test enable
* 1: enable, 0:disable(default)
*/
#define FTS_TEST_EN 0
/*
* Glove mode enable
* 1: enable, 0:disable(default)
*/
#define FTS_GLOVE_EN 0
/*
* cover enable
* 1: enable, 0:disable(default)
*/
#define FTS_COVER_EN 0
/*
* Charger enable
* 1: enable, 0:disable(default)
*/
#define FTS_CHARGER_EN 0
/*
* Nodes for tools, please keep enable
*/
#define FTS_SYSFS_NODE_EN 1
#define FTS_APK_NODE_EN 1
/*
* Pinctrl enable
* default: disable
*/
#define FTS_PINCTRL_EN 0
/*
* Customer power enable
* enable it when customer need control TP power
* default: disable
*/
#define FTS_POWER_SOURCE_CUST_EN 0
/****************************************************/
/********************** Upgrade ****************************/
/*
* auto upgrade, please keep enable
*/
#define FTS_AUTO_UPGRADE_EN 1
/*
* auto upgrade for lcd cfg
*/
#define FTS_AUTO_LIC_UPGRADE_EN 0
/*
* Vendor and Panel IDs
*/
#define FTS_VENDOR_ID_DEFAULT 0x0000
#define FTS_VENDOR_ID_TOPTOUCH 0x00A0
#define FTS_VENDOR_ID_LENSONE 0x006D
#define FTS_VENDOR_ID_TOPGROUP 0x003E
#define FTS_PANEL_ID_DEFAULT 0x0000
#define FTS_PANEL_ID_TOPTOUCH_7MM 0x00C0
#define FTS_PANEL_ID_TOPTOUCH_11MM 0x00C1
#define FTS_PANEL_ID_LENSONE_7MM 0x00C2
#define FTS_PANEL_ID_LENSONE_11MM 0x00C3
#define FTS_PANEL_ID_TOPGROUP_7MM 0x0050
#define FTS_PANEL_ID_TOPGROUP_11MM 0x0051
/*
* Firmware Update Files
*/
#define FTS_UPGRADE_FW_DEFAULT "firmware/fw_sample.i"
#define FTS_TOPTOUCH_NUM_FW 2
#define FTS_UPGRADE_FW_TOPTOUCH_7MM "firmware/7mm/TopTouch_7mm_0x0A.i"
#define FTS_UPGRADE_FW_TOPTOUCH_11MM "firmware/11mm/TopTouch_11mm_0x0F.i"
#define FTS_LENSONE_NUM_FW 2
#define FTS_UPGRADE_FW_LENSONE_7MM "firmware/7mm/LensOne_7mm_0x04.i"
#define FTS_UPGRADE_FW_LENSONE_11MM "firmware/11mm/LensOne_11mm_0x0D.i"
#define FTS_TOPGROUP_NUM_FW 2
#define FTS_UPGRADE_FW_TOPGROUP_7MM "firmware/7mm/TopGroup_7mm_0x06.i"
#define FTS_UPGRADE_FW_TOPGROUP_11MM "firmware/11mm/TopGroup_11mm_0x0B.i"
/*********************************************************/
#endif /* _LINUX_FOCLATECH_CONFIG_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,258 @@
/*
*
* FocalTech TouchScreen driver.
*
* Copyright (c) 2010-2017, Focaltech Ltd. All rights reserved.
*
* 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.
*
*/
/*****************************************************************************
*
* File Name: focaltech_core.h
* Author: Focaltech Driver Team
*
* Created: 2016-08-08
*
* Abstract:
*
* Reference:
*
*****************************************************************************/
#ifndef __LINUX_FOCALTECH_CORE_H__
#define __LINUX_FOCALTECH_CORE_H__
/*****************************************************************************
* Included header files
*****************************************************************************/
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/regulator/consumer.h>
#include <linux/firmware.h>
#include <linux/debugfs.h>
#include <linux/mutex.h>
#include <linux/wait.h>
#include <linux/time.h>
#include <linux/workqueue.h>
#include <linux/fs.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
#include <linux/version.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/kthread.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/mount.h>
#include <linux/netdevice.h>
#include <linux/unistd.h>
#include <linux/ioctl.h>
#include <linux/vmalloc.h>
#include "focaltech_common.h"
/*****************************************************************************
* Private constant and macro definitions using #define
*****************************************************************************/
#define FTS_MAX_POINTS_SUPPORT 10 /* constant value, can't be changed */
#define FTS_MAX_KEYS 4
#define FTS_KEY_WIDTH 50
#define FTS_ONE_TCH_LEN 6
#define FTS_MAX_ID 0x0A
#define FTS_TOUCH_X_H_POS 3
#define FTS_TOUCH_X_L_POS 4
#define FTS_TOUCH_Y_H_POS 5
#define FTS_TOUCH_Y_L_POS 6
#define FTS_TOUCH_PRE_POS 7
#define FTS_TOUCH_AREA_POS 8
#define FTS_TOUCH_POINT_NUM 2
#define FTS_TOUCH_EVENT_POS 3
#define FTS_TOUCH_ID_POS 5
#define FTS_COORDS_ARR_SIZE 4
#define FTS_TOUCH_DOWN 0
#define FTS_TOUCH_UP 1
#define FTS_TOUCH_CONTACT 2
#define EVENT_DOWN(flag) ((FTS_TOUCH_DOWN == flag) || (FTS_TOUCH_CONTACT == flag))
#define EVENT_UP(flag) (FTS_TOUCH_UP == flag)
#define EVENT_NO_DOWN(data) (!data->point_num)
#define KEY_EN(data) (data->pdata->have_key)
#define TOUCH_IS_KEY(y, key_y) (y == key_y)
#define TOUCH_IN_RANGE(val, key_val, half) ((val > (key_val - half)) && (val < (key_val + half)))
#define TOUCH_IN_KEY(x, key_x) TOUCH_IN_RANGE(x, key_x, FTS_KEY_WIDTH)
/*****************************************************************************
* Private enumerations, structures and unions using typedef
*****************************************************************************/
struct fts_ts_platform_data {
u32 irq_gpio;
u32 irq_gpio_flags;
u32 reset_gpio;
u32 reset_gpio_flags;
bool have_key;
u32 key_number;
u32 keys[FTS_MAX_KEYS];
u32 key_y_coord;
u32 key_x_coords[FTS_MAX_KEYS];
u32 x_max;
u32 y_max;
u32 x_min;
u32 y_min;
u32 max_touch_number;
u32 rotation;
};
struct ts_event {
int x; /*x coordinate */
int y; /*y coordinate */
int p; /* pressure */
int flag; /* touch event flag: 0 -- down; 1-- up; 2 -- contact */
int id; /*touch ID */
int area;
};
enum fts_panel_vendor {
FTS_PANEL_VENDOR_NONE = 0,
FTS_PANEL_VENDOR_BOE = 1,
FTS_PANEL_VENDOR_INX = 2
};
struct fts_ts_data {
struct i2c_client *client;
struct input_dev *input_dev;
struct fts_ts_platform_data *pdata;
struct ts_ic_info ic_info;
struct workqueue_struct *ts_workqueue;
struct work_struct fwupg_work;
struct delayed_work esdcheck_work;
struct delayed_work prc_work;
struct regulator *vdd;
struct regulator *vcc_i2c;
spinlock_t irq_lock;
struct mutex report_mutex;
int irq;
bool suspended;
bool fw_loading;
bool irq_disabled;
enum fts_panel_vendor panel_vendor;
#if FTS_POWER_SOURCE_CUST_EN
bool power_disabled;
#endif
/* multi-touch */
struct ts_event *events;
u8 *point_buf;
int pnt_buf_size;
int touchs;
bool key_down;
int touch_point;
int point_num;
struct proc_dir_entry *proc;
u8 proc_opmode;
#if FTS_PINCTRL_EN
struct pinctrl *pinctrl;
struct pinctrl_state *pins_active;
struct pinctrl_state *pins_suspend;
struct pinctrl_state *pins_release;
#endif
#if defined(CONFIG_FB)
struct notifier_block fb_notif;
#elif defined(CONFIG_HAS_EARLYSUSPEND)
struct early_suspend early_suspend;
#endif
};
/*****************************************************************************
* Global variable or extern global variabls/functions
*****************************************************************************/
extern struct fts_ts_data *fts_data;
/* i2c communication*/
int fts_i2c_write_reg(struct i2c_client *client, u8 regaddr, u8 regvalue);
int fts_i2c_read_reg(struct i2c_client *client, u8 regaddr, u8 *regvalue);
int fts_i2c_read(struct i2c_client *client, char *writebuf, int writelen, char *readbuf, int readlen);
int fts_i2c_write(struct i2c_client *client, char *writebuf, int writelen);
void fts_i2c_hid2std(struct i2c_client *client);
int fts_i2c_init(void);
int fts_i2c_exit(void);
/* Gesture functions */
#if FTS_GESTURE_EN
int fts_gesture_init(struct fts_ts_data *ts_data);
int fts_gesture_exit(struct i2c_client *client);
void fts_gesture_recovery(struct i2c_client *client);
int fts_gesture_readdata(struct fts_ts_data *ts_data);
int fts_gesture_suspend(struct i2c_client *i2c_client);
int fts_gesture_resume(struct i2c_client *client);
#endif
/* Apk and functions */
#if FTS_APK_NODE_EN
int fts_create_apk_debug_channel(struct fts_ts_data *);
void fts_release_apk_debug_channel(struct fts_ts_data *);
#endif
/* ADB functions */
#if FTS_SYSFS_NODE_EN
int fts_create_sysfs(struct i2c_client *client);
int fts_remove_sysfs(struct i2c_client *client);
#endif
/* ESD */
#if FTS_ESDCHECK_EN
int fts_esdcheck_init(struct fts_ts_data *ts_data);
int fts_esdcheck_exit(struct fts_ts_data *ts_data);
int fts_esdcheck_switch(bool enable);
int fts_esdcheck_proc_busy(bool proc_debug);
int fts_esdcheck_set_intr(bool intr);
int fts_esdcheck_suspend(void);
int fts_esdcheck_resume(void);
#endif
/* Production test */
#if FTS_TEST_EN
int fts_test_init(struct i2c_client *client);
int fts_test_exit(struct i2c_client *client);
#endif
/* Point Report Check*/
#if FTS_POINT_REPORT_CHECK_EN
int fts_point_report_check_init(struct fts_ts_data *ts_data);
int fts_point_report_check_exit(struct fts_ts_data *ts_data);
void fts_prc_queue_work(struct fts_ts_data *ts_data);
#endif
/* FW upgrade */
int fts_upgrade_bin(struct i2c_client *client, char *fw_name, bool force);
int fts_fwupg_init(struct fts_ts_data *ts_data);
int fts_fwupg_exit(struct fts_ts_data *ts_data);
/* Other */
int fts_reset_proc(int hdelayms);
int fts_wait_tp_to_valid(struct i2c_client *client);
void fts_tp_state_recovery(struct i2c_client *client);
int fts_ex_mode_init(struct i2c_client *client);
int fts_ex_mode_exit(struct i2c_client *client);
int fts_ex_mode_recovery(struct i2c_client *client);
void fts_irq_disable(void);
void fts_irq_enable(void);
#endif /* __LINUX_FOCALTECH_CORE_H__ */

View File

@@ -0,0 +1,552 @@
/*
*
* FocalTech TouchScreen driver.
*
* Copyright (c) 2010-2017, FocalTech Systems, Ltd., all rights reserved.
*
* 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.
*
*/
/*****************************************************************************
*
* File Name: focaltech_esdcheck.c
*
* Author: Focaltech Driver Team
*
* Created: 2016-08-03
*
* Abstract: ESD check function
*
* Version: v1.0
*
* Revision History:
* v1.0:
* First release. By luougojin 2016-08-03
* v1.1: By luougojin 2017-02-15
* 1. Add LCD_ESD_PATCH to control idc_esdcheck_lcderror
*****************************************************************************/
/*****************************************************************************
* Included header files
*****************************************************************************/
#include "focaltech_core.h"
#if FTS_ESDCHECK_EN
/*****************************************************************************
* Private constant and macro definitions using #define
*****************************************************************************/
#define ESDCHECK_WAIT_TIME 1000 /* ms */
#define LCD_ESD_PATCH 0
/*****************************************************************************
* Private enumerations, structures and unions using typedef
*****************************************************************************/
struct fts_esdcheck_st {
u8 mode : 1; /* 1- need check esd 0- no esd check */
u8 suspend : 1;
u8 proc_debug : 1; /* apk or adb is accessing I2C */
u8 intr : 1; /* 1- Interrupt trigger */
u8 unused : 4;
u8 flow_work_hold_cnt; /* Flow Work Cnt(reg0x91) keep a same value for x times. >=5 times is ESD, need reset */
u8 flow_work_cnt_last; /* Save Flow Work Cnt(reg0x91) value */
u32 hardware_reset_cnt;
u32 i2c_nack_cnt;
u32 i2c_dataerror_cnt;
};
/*****************************************************************************
* Static variables
*****************************************************************************/
static struct fts_esdcheck_st fts_esdcheck_data;
/*****************************************************************************
* Global variable or extern global variabls/functions
*****************************************************************************/
/*****************************************************************************
* Static function prototypes
*****************************************************************************/
/*****************************************************************************
* functions body
*****************************************************************************/
#if LCD_ESD_PATCH
/*****************************************************************************
* Name: lcd_esdcheck
* Brief:
* Input:
* Output:
* Return:
*****************************************************************************/
int lcd_need_reset;
static int tp_need_recovery; /* LCD reset cause Tp reset */
int idc_esdcheck_lcderror(struct fts_ts_data *ts_data)
{
int ret = 0;
u8 val = 0;
struct i2c_client *client = ts_data->client;
FTS_DEBUG("[ESD]Check LCD ESD");
if ((tp_need_recovery == 1) && (lcd_need_reset == 0)) {
tp_need_recovery = 0;
/* LCD reset, need recover TP state */
fts_tp_state_recovery(client);
}
ret = fts_i2c_read_reg(client, FTS_REG_ESD_SATURATE, &val);
if (ret < 0) {
FTS_ERROR("[ESD]: Read ESD_SATURATE(0xED) failed ret=%d!", ret);
return -EIO;
}
if (val == 0xAA) {
/*
* 1. Set flag lcd_need_reset = 1;
* 2. LCD driver need reset(recovery) LCD and set lcd_need_reset to 0
* 3. recover TP state
*/
FTS_INFO("LCD ESD, Execute LCD reset!");
lcd_need_reset = 1;
tp_need_recovery = 1;
}
return 0;
}
#endif
/*****************************************************************************
* Name: fts_esdcheck_tp_reset
* Brief: esd check algorithm
* Input:
* Output:
* Return:
*****************************************************************************/
static int fts_esdcheck_tp_reset(struct fts_ts_data *ts_data)
{
FTS_FUNC_ENTER();
fts_esdcheck_data.flow_work_hold_cnt = 0;
fts_esdcheck_data.hardware_reset_cnt++;
fts_reset_proc(200);
fts_tp_state_recovery(ts_data->client);
FTS_FUNC_EXIT();
return 0;
}
/*****************************************************************************
* Name: get_chip_id
* Brief: Read Chip Id 3 times
* Input:
* Output:
* Return: 1 - Read Chip Id 3 times failed
* 0 - Read Chip Id pass
*****************************************************************************/
static bool get_chip_id(struct fts_ts_data *ts_data)
{
int ret = 0;
int i = 0;
u8 reg_value = 0;
u8 reg_addr = 0;
struct i2c_client *client = ts_data->client;
u8 chip_id = ts_data->ic_info.ids.chip_idh;
for (i = 0; i < 3; i++) {
reg_addr = FTS_REG_CHIP_ID;
ret = fts_i2c_read(client, &reg_addr, 1, &reg_value, 1);
if (ret < 0) {
FTS_ERROR("[ESD]: Read Reg 0xA3 failed ret = %d!!", ret);
fts_esdcheck_data.i2c_nack_cnt++;
} else {
if (reg_value == chip_id) {
break;
} else {
fts_esdcheck_data.i2c_dataerror_cnt++;
}
}
msleep(10);
}
/* if can't get correct data in 3 times, then need hardware reset */
if (i >= 3) {
FTS_ERROR("[ESD]: Read Chip id 3 times failed, need execute TP reset!!");
return 1;
}
return 0;
}
/*****************************************************************************
* Name: get_flow_cnt
* Brief: Read flow cnt(0x91)
* Input:
* Output:
* Return: 1 - Reg 0x91(flow cnt) abnormal: hold a value for 5 times
* 0 - Reg 0x91(flow cnt) normal
*****************************************************************************/
static bool get_flow_cnt(struct fts_ts_data *ts_data)
{
int ret = 0;
u8 reg_value = 0;
u8 reg_addr = 0;
struct i2c_client *client = ts_data->client;
reg_addr = FTS_REG_FLOW_WORK_CNT;
ret = fts_i2c_read(client, &reg_addr, 1, &reg_value, 1);
if (ret < 0) {
FTS_ERROR("[ESD]: Read Reg 0x91 failed ret = %d!!", ret);
fts_esdcheck_data.i2c_nack_cnt++;
} else {
if (reg_value == fts_esdcheck_data.flow_work_cnt_last) {
fts_esdcheck_data.flow_work_hold_cnt++;
} else {
fts_esdcheck_data.flow_work_hold_cnt = 0;
}
fts_esdcheck_data.flow_work_cnt_last = reg_value;
}
/* if read flow work cnt 5 times and the value are all the same, then need hardware_reset */
if (fts_esdcheck_data.flow_work_hold_cnt >= 5) {
FTS_DEBUG("[ESD]: Flow Work Cnt(reg0x91) keep a value for 5 times, need execute TP reset!!");
return 1;
}
return 0;
}
/*****************************************************************************
* Name: esdcheck_algorithm
* Brief: esd check algorithm
* Input:
* Output:
* Return:
*****************************************************************************/
static int esdcheck_algorithm(struct fts_ts_data *ts_data)
{
int ret = 0;
u8 reg_value = 0;
u8 reg_addr = 0;
bool hardware_reset = 0;
struct i2c_client *client = ts_data->client;
/* 1. esdcheck is interrupt, then return */
if (fts_esdcheck_data.intr == 1) {
FTS_DEBUG("[ESD]: In interrupt state, not check esd, return immediately!!");
return 0;
}
/* 2. check power state, if suspend, no need check esd */
if (fts_esdcheck_data.suspend == 1) {
FTS_DEBUG("[ESD]: In suspend, not check esd, return immediately!!");
/* because in suspend state, adb can be used, when upgrade FW, will active ESD check(active = 1)
* But in suspend, then will don't queue_delayed_work, when resume, don't check ESD again
*/
return 0;
}
/* 3. check fts_esdcheck_data.proc_debug state, if 1-proc busy, no need check esd*/
if (fts_esdcheck_data.proc_debug == 1) {
FTS_INFO("[ESD]: In apk or adb command mode, not check esd, return immediately!!");
return 0;
}
/* 4. In factory mode, can't check esd */
reg_addr = FTS_REG_WORKMODE;
ret = fts_i2c_read(client, &reg_addr, 1, &reg_value, 1);
if (ret < 0) {
fts_esdcheck_data.i2c_nack_cnt++;
} else if ((reg_value & 0x70) != FTS_REG_WORKMODE_WORK_VALUE) {
FTS_DEBUG("[ESD]: not in work mode, no check esd, return immediately!!");
return 0;
}
/* 5. IDC esd check lcd default:close */
#if LCD_ESD_PATCH
idc_esdcheck_lcderror(ts_data);
#endif
/* 6. Get Chip ID */
hardware_reset = get_chip_id(ts_data);
/* 7. get Flow work cnt: 0x91 If no change for 5 times, then ESD and reset */
if (!hardware_reset) {
hardware_reset = get_flow_cnt(ts_data);
}
/* 8. If need hardware reset, then handle it here */
if (hardware_reset == 1) {
fts_esdcheck_tp_reset(ts_data);
}
FTS_DEBUG("[ESD]: NoACK=%d, Error Data=%d, Hardware Reset=%d", fts_esdcheck_data.i2c_nack_cnt, fts_esdcheck_data.i2c_dataerror_cnt, fts_esdcheck_data.hardware_reset_cnt);
return 0;
}
/*****************************************************************************
* Name: fts_esdcheck_func
* Brief: fts_esdcheck_func
* Input:
* Output:
* Return:
*****************************************************************************/
static void esdcheck_func(struct work_struct *work)
{
u8 val = 0;
struct fts_ts_data *ts_data = container_of(work,
struct fts_ts_data, esdcheck_work.work);
FTS_FUNC_ENTER();
if (ENABLE == fts_esdcheck_data.mode) {
if (ts_data->ic_info.is_incell) {
fts_i2c_read_reg(ts_data->client, FTS_REG_ESDCHECK_DISABLE, &val);
if (0xA5 == val) {
fts_esdcheck_data.mode = DISABLE;
return;
}
}
esdcheck_algorithm(ts_data);
queue_delayed_work(ts_data->ts_workqueue, &ts_data->esdcheck_work,
msecs_to_jiffies(ESDCHECK_WAIT_TIME));
}
FTS_FUNC_EXIT();
}
/*****************************************************************************
* Name: fts_esdcheck_set_intr
* Brief: interrupt flag (main used in interrupt tp report)
* Input:
* Output:
* Return:
*****************************************************************************/
int fts_esdcheck_set_intr(bool intr)
{
/* interrupt don't add debug message */
fts_esdcheck_data.intr = intr;
return 0;
}
/*****************************************************************************
* Name: fts_esdcheck_get_status(void)
* Brief: get current status
* Input:
* Output:
* Return:
*****************************************************************************/
int fts_esdcheck_get_status(void)
{
/* interrupt don't add debug message */
return fts_esdcheck_data.mode;
}
/*****************************************************************************
* Name: fts_esdcheck_proc_busy
* Brief: When APK or ADB command access TP via driver, then need set proc_debug,
* then will not check ESD.
* Input:
* Output:
* Return:
*****************************************************************************/
int fts_esdcheck_proc_busy(bool proc_debug)
{
fts_esdcheck_data.proc_debug = proc_debug;
return 0;
}
/*****************************************************************************
* Name: fts_esdcheck_switch
* Brief: FTS esd check function switch.
* Input: enable: 1 - Enable esd check
* 0 - Disable esd check
* Output:
* Return:
*****************************************************************************/
int fts_esdcheck_switch(bool enable)
{
struct fts_ts_data *ts_data = fts_data;
FTS_FUNC_ENTER();
if (fts_esdcheck_data.mode == ENABLE) {
if (enable) {
FTS_DEBUG("[ESD]: ESD check start!!");
fts_esdcheck_data.flow_work_hold_cnt = 0;
fts_esdcheck_data.flow_work_cnt_last = 0;
queue_delayed_work(ts_data->ts_workqueue, &ts_data->esdcheck_work,
msecs_to_jiffies(ESDCHECK_WAIT_TIME));
} else {
FTS_DEBUG("[ESD]: ESD check stop!!");
cancel_delayed_work(&ts_data->esdcheck_work);
}
} else {
FTS_DEBUG("[ESD]: ESD should disable!!");
cancel_delayed_work(&ts_data->esdcheck_work);
}
FTS_FUNC_EXIT();
return 0;
}
EXPORT_SYMBOL(fts_esdcheck_switch);
/*****************************************************************************
* Name: fts_esdcheck_suspend
* Brief: Run when tp enter into suspend
* Input:
* Output:
* Return:
*****************************************************************************/
int fts_esdcheck_suspend(void)
{
FTS_FUNC_ENTER();
fts_esdcheck_switch(DISABLE);
fts_esdcheck_data.suspend = 1;
FTS_FUNC_EXIT();
return 0;
}
/*****************************************************************************
* Name: fts_esdcheck_resume
* Brief: Run when tp resume
* Input:
* Output:
* Return:
*****************************************************************************/
int fts_esdcheck_resume(void)
{
FTS_FUNC_ENTER();
fts_esdcheck_switch(ENABLE);
fts_esdcheck_data.suspend = 0;
FTS_FUNC_EXIT();
return 0;
}
/************************************************************************
* Name: fts_esdcheck_store
* Brief: no
* Input: device, device attribute, char buf, char count
* Output: no
* Return: EPERM
***********************************************************************/
static ssize_t fts_esdcheck_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct input_dev *input_dev = fts_data->input_dev;
mutex_lock(&input_dev->mutex);
if (FTS_SYSFS_ECHO_ON(buf)) {
FTS_DEBUG("enable esdcheck");
fts_esdcheck_data.mode = ENABLE;
fts_esdcheck_switch(ENABLE);
} else if (FTS_SYSFS_ECHO_OFF(buf)) {
FTS_DEBUG("disable esdcheck");
fts_esdcheck_data.mode = DISABLE;
fts_esdcheck_switch(DISABLE);
}
mutex_unlock(&input_dev->mutex);
return count;
}
/************************************************************************
* Name: fts_esdcheck_show
* Brief: no
* Input: device, device attribute, char buf
* Output: no
* Return: EPERM
***********************************************************************/
static ssize_t fts_esdcheck_show(struct device *dev, struct device_attribute *attr, char *buf)
{
int count;
struct input_dev *input_dev = fts_data->input_dev;
mutex_lock(&input_dev->mutex);
count = snprintf(buf, PAGE_SIZE, "Esd check: %s\n", fts_esdcheck_get_status() ? "On" : "Off");
mutex_unlock(&input_dev->mutex);
return count;
}
/* sysfs esd node
* read example: cat fts_esd_mode ---read esd mode
* write example:echo 01 > fts_esd_mode ---make esdcheck enable
*
*/
static DEVICE_ATTR (fts_esd_mode, S_IRUGO | S_IWUSR, fts_esdcheck_show, fts_esdcheck_store);
static struct attribute *fts_esd_mode_attrs[] = {
&dev_attr_fts_esd_mode.attr,
NULL,
};
static struct attribute_group fts_esd_group = {
.attrs = fts_esd_mode_attrs,
};
/*****************************************************************************
* Name: fts_create_gesture_sysfs
* Brief:
* Input:
* Output:
* Return: 0-success or others-error
*****************************************************************************/
int fts_create_esd_sysfs(struct i2c_client *client)
{
int ret = 0;
ret = sysfs_create_group(&client->dev.kobj, &fts_esd_group);
if (ret != 0) {
FTS_ERROR("fts_create_esd_sysfs(sysfs) create failed!");
sysfs_remove_group(&client->dev.kobj, &fts_esd_group);
return ret;
}
return 0;
}
/*****************************************************************************
* Name: fts_esdcheck_init
* Brief: Init and create a queue work to check esd
* Input:
* Output:
* Return: < 0: Fail to create esd check queue
*****************************************************************************/
int fts_esdcheck_init(struct fts_ts_data *ts_data)
{
FTS_FUNC_ENTER();
if (ts_data->ts_workqueue) {
INIT_DELAYED_WORK(&ts_data->esdcheck_work, esdcheck_func);
} else {
FTS_ERROR("fts workqueue is NULL, can't run esd check function");
return -EINVAL;
}
memset((u8 *)&fts_esdcheck_data, 0, sizeof(struct fts_esdcheck_st));
fts_esdcheck_data.mode = ENABLE;
fts_esdcheck_switch(ENABLE);
fts_create_esd_sysfs(ts_data->client);
FTS_FUNC_EXIT();
return 0;
}
/*****************************************************************************
* Name: fts_esdcheck_exit
* Brief: When FTS TP driver is removed, then call this function to destory work queue
* Input:
* Output:
* Return:
*****************************************************************************/
int fts_esdcheck_exit(struct fts_ts_data *ts_data)
{
FTS_FUNC_ENTER();
FTS_FUNC_EXIT();
return 0;
}
#endif /* FTS_ESDCHECK_EN */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,382 @@
/*
*
* FocalTech ftxxxx TouchScreen driver.
*
* Copyright (c) 2010-2017, Focaltech Ltd. All rights reserved.
*
* 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.
*
*/
/*****************************************************************************
*
* File Name: focaltech_ex_mode.c
*
* Author: Liu WeiGuang
*
* Created: 2016-08-31
*
* Abstract:
*
* Reference:
*
*****************************************************************************/
/*****************************************************************************
* 1.Included header files
*****************************************************************************/
#include "focaltech_core.h"
/*****************************************************************************
* 2.Private constant and macro definitions using #define
*****************************************************************************/
/*****************************************************************************
* 3.Private enumerations, structures and unions using typedef
*****************************************************************************/
struct fts_mode_flag {
int fts_glove_mode_flag;
int fts_cover_mode_flag;
int fts_charger_mode_flag;
};
struct fts_mode_flag g_fts_mode_flag;
/*****************************************************************************
* 4.Static variables
*****************************************************************************/
/*****************************************************************************
* 5.Global variable or extern global variabls/functions
*****************************************************************************/
int fts_enter_glove_mode(struct i2c_client *client, int mode);
int fts_enter_cover_mode(struct i2c_client *client, int mode);
int fts_enter_charger_mode(struct i2c_client *client, int mode);
/*****************************************************************************
* 6.Static function prototypes
*******************************************************************************/
#if FTS_GLOVE_EN
static ssize_t fts_touch_glove_show(struct device *dev, struct device_attribute *attr, char *buf)
{
int count;
u8 val;
struct input_dev *input_dev = fts_data->input_dev;
struct i2c_client *client = container_of(dev, struct i2c_client, dev);
mutex_lock(&input_dev->mutex);
fts_i2c_read_reg(client, FTS_REG_GLOVE_MODE_EN, &val);
count = snprintf(buf, PAGE_SIZE, "Glove Mode: %s\n", g_fts_mode_flag.fts_glove_mode_flag ? "On" : "Off");
count += snprintf(buf + count, PAGE_SIZE, "Glove Reg(0xC0) = %d\n", val);
mutex_unlock(&input_dev->mutex);
return count;
}
static ssize_t fts_touch_glove_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
int ret;
struct fts_ts_data *ts_data = fts_data;
struct i2c_client *client;
client = ts_data->client;
if (FTS_SYSFS_ECHO_ON(buf)) {
if (!g_fts_mode_flag.fts_glove_mode_flag) {
FTS_INFO("[Mode]enter glove mode");
ret = fts_enter_glove_mode(client, true);
if (ret >= 0) {
g_fts_mode_flag.fts_glove_mode_flag = true;
}
}
} else if (FTS_SYSFS_ECHO_OFF(buf)) {
if (g_fts_mode_flag.fts_glove_mode_flag) {
FTS_INFO("[Mode]exit glove mode");
ret = fts_enter_glove_mode(client, false);
if (ret >= 0) {
g_fts_mode_flag.fts_glove_mode_flag = false;
}
}
}
FTS_INFO("[Mode]glove mode status: %d", g_fts_mode_flag.fts_glove_mode_flag);
return count;
}
/************************************************************************
* Name: fts_enter_glove_mode
* Brief: change glove mode
* Input: glove mode
* Output: no
* Return: success >=0, otherwise failed
***********************************************************************/
int fts_enter_glove_mode(struct i2c_client *client, int mode)
{
int ret = 0;
static u8 buf_addr[2] = { 0 };
static u8 buf_value[2] = { 0 };
buf_addr[0] = FTS_REG_GLOVE_MODE_EN; /* glove control */
if (mode)
buf_value[0] = 0x01;
else
buf_value[0] = 0x00;
ret = fts_i2c_write_reg(client, buf_addr[0], buf_value[0]);
if (ret < 0) {
FTS_ERROR("[Mode]fts_enter_glove_mode write value fail");
}
return ret ;
}
/* read and write glove mode
* read example: cat fts_touch_glove_mode---read glove mode
* write example:echo 01 > fts_touch_glove_mode ---write glove mode to 01
*
*/
static DEVICE_ATTR (fts_glove_mode, S_IRUGO | S_IWUSR, fts_touch_glove_show, fts_touch_glove_store);
#endif
#if FTS_COVER_EN
static ssize_t fts_touch_cover_show(struct device *dev, struct device_attribute *attr, char *buf)
{
int count;
u8 val;
struct input_dev *input_dev = fts_data->input_dev;
struct i2c_client *client = container_of(dev, struct i2c_client, dev);
mutex_lock(&input_dev->mutex);
fts_i2c_read_reg(client, FTS_REG_COVER_MODE_EN, &val);
count = snprintf(buf, PAGE_SIZE, "Cover Mode: %s\n", g_fts_mode_flag.fts_cover_mode_flag ? "On" : "Off");
count += snprintf(buf + count, PAGE_SIZE, "Cover Reg(0xC1) = %d\n", val);
mutex_unlock(&input_dev->mutex);
return count;
}
static ssize_t fts_touch_cover_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
int ret;
struct fts_ts_data *ts_data = fts_data;
struct i2c_client *client;
client = ts_data->client;
if (FTS_SYSFS_ECHO_ON(buf)) {
if (!g_fts_mode_flag.fts_cover_mode_flag) {
FTS_INFO("[Mode]enter cover mode");
ret = fts_enter_cover_mode(client, true);
if (ret >= 0) {
g_fts_mode_flag.fts_cover_mode_flag = true;
}
}
} else if (FTS_SYSFS_ECHO_OFF(buf)) {
if (g_fts_mode_flag.fts_cover_mode_flag) {
FTS_INFO("[Mode]exit cover mode");
ret = fts_enter_cover_mode(client, false);
if (ret >= 0) {
g_fts_mode_flag.fts_cover_mode_flag = false;
}
}
}
FTS_INFO("[Mode]cover mode status: %d", g_fts_mode_flag.fts_cover_mode_flag);
return count;
}
/************************************************************************
* Name: fts_enter_cover_mode
* Brief: change cover mode
* Input: cover mode
* Output: no
* Return: success >=0, otherwise failed
***********************************************************************/
int fts_enter_cover_mode(struct i2c_client *client, int mode)
{
int ret = 0;
static u8 buf_addr[2] = { 0 };
static u8 buf_value[2] = { 0 };
buf_addr[0] = FTS_REG_COVER_MODE_EN; /* cover control */
if (mode)
buf_value[0] = 0x01;
else
buf_value[0] = 0x00;
ret = fts_i2c_write_reg(client, buf_addr[0], buf_value[0]);
if (ret < 0) {
FTS_ERROR("[Mode] fts_enter_cover_mode write value fail \n");
}
return ret ;
}
/* read and write cover mode
* read example: cat fts_touch_cover_mode---read cover mode
* write example:echo 01 > fts_touch_cover_mode ---write cover mode to 01
*
*/
static DEVICE_ATTR (fts_cover_mode, S_IRUGO | S_IWUSR, fts_touch_cover_show, fts_touch_cover_store);
#endif
#if FTS_CHARGER_EN
static ssize_t fts_touch_charger_show(struct device *dev, struct device_attribute *attr, char *buf)
{
int count;
u8 val;
struct input_dev *input_dev = fts_data->input_dev;
struct i2c_client *client = container_of(dev, struct i2c_client, dev);
mutex_lock(&input_dev->mutex);
fts_i2c_read_reg(client, FTS_REG_CHARGER_MODE_EN, &val);
count = snprintf(buf, PAGE_SIZE, "Charge Mode: %s\n", g_fts_mode_flag.fts_charger_mode_flag ? "On" : "Off");
count += snprintf(buf + count, PAGE_SIZE, "Charge Reg(0x8B) = %d\n", val);
mutex_unlock(&input_dev->mutex);
return count;
}
static ssize_t fts_touch_charger_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
int ret;
struct fts_ts_data *ts_data = fts_data;
struct i2c_client *client;
client = ts_data->client;
if (FTS_SYSFS_ECHO_ON(buf)) {
if (!g_fts_mode_flag.fts_charger_mode_flag) {
FTS_INFO("[Mode]enter charger mode");
ret = fts_enter_charger_mode(client, true);
if (ret >= 0) {
g_fts_mode_flag.fts_charger_mode_flag = true;
}
}
} else if (FTS_SYSFS_ECHO_OFF(buf)) {
if (g_fts_mode_flag.fts_charger_mode_flag) {
FTS_INFO("[Mode]exit charger mode");
ret = fts_enter_charger_mode(client, false);
if (ret >= 0) {
g_fts_mode_flag.fts_charger_mode_flag = false;
}
}
}
FTS_INFO("[Mode]charger mode status: %d", g_fts_mode_flag.fts_charger_mode_flag);
return count;
}
/************************************************************************
* Name: fts_enter_charger_mode
* Brief: change charger mode
* Input: charger mode
* Output: no
* Return: success >=0, otherwise failed
***********************************************************************/
int fts_enter_charger_mode(struct i2c_client *client, int mode)
{
int ret = 0;
static u8 buf_addr[2] = { 0 };
static u8 buf_value[2] = { 0 };
buf_addr[0] = FTS_REG_CHARGER_MODE_EN; /* charger control */
if (mode)
buf_value[0] = 0x01;
else
buf_value[0] = 0x00;
ret = fts_i2c_write_reg(client, buf_addr[0], buf_value[0]);
if (ret < 0) {
FTS_DEBUG("[Mode]fts_enter_charger_mode write value fail");
}
return ret ;
}
/* read and write charger mode
* read example: cat fts_touch_charger_mode---read charger mode
* write example:echo 01 > fts_touch_charger_mode ---write charger mode to 01
*
*/
static DEVICE_ATTR (fts_charger_mode, S_IRUGO | S_IWUSR, fts_touch_charger_show, fts_touch_charger_store);
#endif
static struct attribute *fts_touch_mode_attrs[] = {
#if FTS_GLOVE_EN
&dev_attr_fts_glove_mode.attr,
#endif
#if FTS_COVER_EN
&dev_attr_fts_cover_mode.attr,
#endif
#if FTS_CHARGER_EN
&dev_attr_fts_charger_mode.attr,
#endif
NULL,
};
static struct attribute_group fts_touch_mode_group = {
.attrs = fts_touch_mode_attrs,
};
int fts_ex_mode_init(struct i2c_client *client)
{
int err = 0;
g_fts_mode_flag.fts_glove_mode_flag = false;
g_fts_mode_flag.fts_cover_mode_flag = false;
g_fts_mode_flag.fts_charger_mode_flag = false;
err = sysfs_create_group(&client->dev.kobj, &fts_touch_mode_group);
if (0 != err) {
FTS_ERROR("[Mode]create sysfs failed.");
sysfs_remove_group(&client->dev.kobj, &fts_touch_mode_group);
return -EIO;
} else {
FTS_DEBUG("[Mode]create sysfs succeeded");
}
return err;
}
int fts_ex_mode_exit(struct i2c_client *client)
{
sysfs_remove_group(&client->dev.kobj, &fts_touch_mode_group);
return 0;
}
int fts_ex_mode_recovery(struct i2c_client *client)
{
int ret = 0;
#if FTS_GLOVE_EN
if (g_fts_mode_flag.fts_glove_mode_flag)
ret = fts_enter_glove_mode(client, true);
#endif
#if FTS_COVER_EN
if (g_fts_mode_flag.fts_cover_mode_flag)
ret = fts_enter_cover_mode(client, true);
#endif
#if FTS_CHARGER_EN
if (g_fts_mode_flag.fts_charger_mode_flag)
ret = fts_enter_charger_mode(client, true);
#endif
return ret;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,172 @@
/************************************************************************
* Copyright (C) 2010-2018, Focaltech Systems (R)£¬All Rights Reserved.
*
* File Name: focaltech_flash.h
*
* Author: fupeipei
*
* Created: 2016-08-07
*
* Abstract:
*
************************************************************************/
#ifndef __LINUX_FOCALTECH_FLASH_H__
#define __LINUX_FOCALTECH_FLASH_H__
/*****************************************************************************
* 1.Included header files
*****************************************************************************/
#include "focaltech_core.h"
/*****************************************************************************
* Private constant and macro definitions using #define
*****************************************************************************/
#define FTS_CMD_RESET 0x07
#define FTS_ROMBOOT_CMD_WRITE 0xAE
#define FTS_ROMBOOT_CMD_START_APP 0x08
#define FTS_DELAY_PRAMBOOT_START 10
#define FTS_ROMBOOT_CMD_ECC 0xCC
#define FTS_CMD_READ 0x03
#define FTS_CMD_READ_DELAY 1
#define FTS_CMD_READ_LEN 4
#define FTS_CMD_FLASH_TYPE 0x05
#define FTS_CMD_FLASH_MODE 0x09
#define FLASH_MODE_WRITE_FLASH_VALUE 0x0A
#define FLASH_MODE_UPGRADE_VALUE 0x0B
#define FLASH_MODE_LIC_VALUE 0x0C
#define FLASH_MODE_PARAM_VALUE 0x0D
#define FTS_CMD_ERASE_APP 0x61
#define FTS_REASE_APP_DELAY 1350
#define FTS_ERASE_SECTOR_DELAY 60
#define FTS_RETRIES_REASE 50
#define FTS_RETRIES_DELAY_REASE 200
#define FTS_CMD_FLASH_STATUS 0x6A
#define FTS_CMD_FLASH_STATUS_LEN 2
#define FTS_CMD_FLASH_STATUS_NOP 0x0000
#define FTS_CMD_FLASH_STATUS_ECC_OK 0xF055
#define FTS_CMD_FLASH_STATUS_ERASE_OK 0xF0AA
#define FTS_CMD_FLASH_STATUS_WRITE_OK 0x1000
#define FTS_CMD_ECC_INIT 0x64
#define FTS_CMD_ECC_CAL 0x65
#define FTS_CMD_ECC_CAL_LEN 6
#define FTS_RETRIES_ECC_CAL 10
#define FTS_RETRIES_DELAY_ECC_CAL 50
#define FTS_CMD_ECC_READ 0x66
#define FTS_CMD_DATA_LEN 0xB0
#define FTS_CMD_DATA_LEN_LEN 4
#define FTS_CMD_WRITE 0xBF
#define FTS_RETRIES_WRITE 100
#define FTS_RETRIES_DELAY_WRITE 1
#define FTS_CMD_WRITE_LEN 6
#define FTS_DELAY_READ_ID 20
#define FTS_DELAY_UPGRADE_RESET 80
#define PRAMBOOT_MIN_SIZE 0x120
#define PRAMBOOT_MAX_SIZE (64*1024)
#define FTS_FLASH_PACKET_LENGTH 32 /* max=128 */
#define FTS_MAX_LEN_ECC_CALC 0xFFFE /* must be even */
#define FTS_MIN_LEN 0x120
#define FTS_MAX_LEN_FILE (128 * 1024)
#define FTS_MAX_LEN_APP (64 * 1024)
#define FTS_MAX_LEN_SECTOR (4 * 1024)
#define FTS_CONIFG_VENDORID_OFF 0x04
#define FTS_CONIFG_MODULEID_OFF 0x1E
#define FTS_CONIFG_PROJECTID_OFF 0x20
#define FTS_APPINFO_OFF 0x100
#define FTS_APPINFO_APPLEN_OFF 0x00
#define FTS_APPINFO_APPLEN2_OFF 0x12
#define FTS_REG_UPGRADE 0xFC
#define FTS_UPGRADE_AA 0xAA
#define FTS_UPGRADE_55 0x55
#define FTS_DELAY_FC_AA 10
#define FTS_UPGRADE_LOOP 30
#define FTS_HEADER_LEN 32
#define FTS_FW_BIN_FILEPATH "/data/"
#define FTS_ROMBOOT_CMD_ECC_NEW_LEN 7
#define FTS_ROMBOOT_CMD_ECC_FINISH 0xCE
#define FTS_CMD_READ_ECC 0xCD
#define FTX_MAX_COMPATIBLE_TYPE 4
#define AL2_FCS_COEF ((1 << 15) + (1 << 10) + (1 << 3))
enum FW_STATUS {
FTS_RUN_IN_ERROR,
FTS_RUN_IN_APP,
FTS_RUN_IN_ROM,
FTS_RUN_IN_PRAM,
FTS_RUN_IN_BOOTLOADER,
};
enum FW_FLASH_MODE {
FLASH_MODE_APP,
FLASH_MODE_LIC,
FLASH_MODE_PARAM,
FLASH_MODE_ALL,
};
/*****************************************************************************
* Private enumerations, structures and unions using typedef
*****************************************************************************/
/* IC info */
struct upgrade_func {
u64 ctype[FTX_MAX_COMPATIBLE_TYPE];
int newmode;
u32 fwveroff;
u32 fwcfgoff;
u32 appoff;
u32 licoff;
u32 paramcfgoff;
u32 paramcfgveroff;
u32 paramcfg2off;
bool hid_supported;
bool pramboot_supported;
u8 *pramboot;
u32 pb_length;
int (*init)(void);
int (*upgrade)(struct i2c_client *, u8 *, u32);
int (*get_hlic_ver)(u8 *);
int (*lic_upgrade)(struct i2c_client *, u8 *, u32);
int (*param_upgrade)(struct i2c_client *, u8 *, u32);
int (*force_upgrade)(struct i2c_client *, u8 *, u32);
};
struct fts_upgrade {
u8 *fw;
u32 fw_length;
u8 *lic;
u32 lic_length;
struct upgrade_func *func;
};
struct upgrade_fw {
u16 vendor_id;
u16 panel_id;
u8 *fw_file;
u32 fw_len;
};
/*****************************************************************************
* Global variable or extern global variabls/functions
*****************************************************************************/
extern struct fts_upgrade *fwupgrade;
#if defined(CONFIG_TOUCHSCREEN_FTS_3427) && !defined(CONFIG_TOUCHSCREEN_FTS_5726)
extern struct upgrade_func upgrade_func_ft5x46;
#elif defined(CONFIG_TOUCHSCREEN_FTS_5726) && !defined(CONFIG_TOUCHSCREEN_FTS_3427)
extern struct upgrade_func upgrade_func_ft5822;
#endif
/*****************************************************************************
* Static function prototypes
*****************************************************************************/
bool fts_fwupg_check_fw_valid(struct i2c_client *client);
int fts_fwupg_get_boot_state(struct i2c_client *client, enum FW_STATUS *fw_sts);
bool fts_fwupg_check_state(struct i2c_client *client, enum FW_STATUS rstate);
int fts_fwupg_reset_in_boot(struct i2c_client *client);
int fts_fwupg_reset_to_boot(struct i2c_client *client);
int fts_fwupg_reset_to_romboot(struct i2c_client *client);
int fts_fwupg_enter_into_boot(struct i2c_client *client);
int fts_fwupg_erase(struct i2c_client *client, u32 delay);
int fts_fwupg_ecc_cal(struct i2c_client *client, u32 saddr, u32 len);
int fts_flash_write_buf(struct i2c_client *client, u32 saddr, u8 *buf, u32 len, u32 delay);
int fts_fwupg_upgrade(struct i2c_client *client, struct fts_upgrade *upg);
#endif

View File

@@ -0,0 +1,9 @@
#
# Makefile for the focaltech touchscreen drivers.
#
# Each configuration option enables a list of files.
obj-$(CONFIG_TOUCHSCREEN_FTS_3427) += focaltech_upgrade_ft3427.o
obj-$(CONFIG_TOUCHSCREEN_FTS_5726) += focaltech_upgrade_ft5726.o

View File

@@ -0,0 +1,162 @@
/*
*
* FocalTech fts TouchScreen driver.
*
* Copyright (c) 2010-2018, Focaltech Ltd. All rights reserved.
*
* 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.
*
*/
/*****************************************************************************
*
* File Name: focaltech_upgrade_ft5x46.c
*
* Author: Focaltech Driver Team
*
* Created: 2016-08-15
*
* Abstract:
*
* Reference:
*
*****************************************************************************/
/*****************************************************************************
* 1.Included header files
*****************************************************************************/
#include "../focaltech_core.h"
#include "../focaltech_flash.h"
/*****************************************************************************
* Static function prototypes
*****************************************************************************/
static int fts_ft5x46_init(void)
{
struct fts_upgrade *upg = fwupgrade;
if (NULL == upg) {
FTS_ERROR("upg is null");
return -EINVAL;
}
if (upg->fw_length < FTS_MIN_LEN) {
FTS_ERROR("fw length fail");
return -EINVAL;
}
upgrade_func_ft5x46.fwveroff = upg->fw_length - 2;
return 0;
}
/************************************************************************
* Name: fts_ft5x46_upgrade
* Brief:
* Input:
* Output:
* Return: return 0 if success, otherwise return error code
***********************************************************************/
static int fts_ft5x46_upgrade(struct i2c_client *client, u8 *buf, u32 len)
{
int ret = 0;
u32 start_addr = 0;
u8 cmd[4] = { 0 };
int ecc_in_host = 0;
int ecc_in_tp = 0;
if (NULL == buf) {
FTS_ERROR("fw buf is null");
return -EINVAL;
}
if ((len < FTS_MIN_LEN) || (len > (60 * 1024))) {
FTS_ERROR("fw buffer len(%x) fail", len);
return -EINVAL;
}
/* enter into upgrade environment */
ret = fts_fwupg_enter_into_boot(client);
if (ret < 0) {
FTS_ERROR("enter into pramboot/bootloader fail,ret=%d", ret);
goto fw_reset;
}
cmd[0] = FTS_CMD_FLASH_MODE;
cmd[1] = FLASH_MODE_UPGRADE_VALUE;
ret = fts_i2c_write(client, cmd, 2);
if (ret < 0) {
FTS_ERROR("upgrade mode(09) cmd write fail");
goto fw_reset;
}
cmd[0] = FTS_CMD_DATA_LEN;
cmd[1] = BYTE_OFF_16(len);
cmd[2] = BYTE_OFF_8(len);
cmd[3] = BYTE_OFF_0(len);
ret = fts_i2c_write(client, cmd, FTS_CMD_DATA_LEN_LEN);
if (ret < 0) {
FTS_ERROR("data len cmd write fail");
goto fw_reset;
}
ret = fts_fwupg_erase(client, FTS_REASE_APP_DELAY);
if (ret < 0) {
FTS_ERROR("erase cmd write fail");
goto fw_reset;
}
/* write app */
start_addr = upgrade_func_ft5x46.appoff;
ecc_in_host = fts_flash_write_buf(client, start_addr, buf, len, 1);
if (ecc_in_host < 0) {
FTS_ERROR("lcd initial code write fail");
goto fw_reset;
}
/* ecc */
ecc_in_tp = fts_fwupg_ecc_cal(client, start_addr, len);
if (ecc_in_tp < 0) {
FTS_ERROR("ecc read fail");
goto fw_reset;
}
FTS_INFO("ecc in tp:%x, host:%x", ecc_in_tp, ecc_in_host);
if (ecc_in_tp != ecc_in_host) {
FTS_ERROR("ecc check fail");
goto fw_reset;
}
FTS_INFO("upgrade success, reset to normal boot");
ret = fts_fwupg_reset_in_boot(client);
if (ret < 0) {
FTS_ERROR("reset to normal boot fail");
}
msleep(200);
return 0;
fw_reset:
FTS_INFO("upgrade fail, reset to normal boot");
ret = fts_fwupg_reset_in_boot(client);
if (ret < 0) {
FTS_ERROR("reset to normal boot fail");
}
return -EIO;
}
struct upgrade_func upgrade_func_ft5x46 = {
.ctype = {0x02},
.fwveroff = 0x0000,
.fwcfgoff = 0xD780,
.appoff = 0x0000,
.pramboot_supported = false,
.hid_supported = true,
.init = fts_ft5x46_init,
.upgrade = fts_ft5x46_upgrade,
};

View File

@@ -0,0 +1,145 @@
/*
*
* FocalTech fts TouchScreen driver.
*
* Copyright (c) 2012-2018, Focaltech Ltd. All rights reserved.
*
* 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.
*
*/
/*****************************************************************************
*
* File Name: focaltech_upgrade_ft5822.c
*
* Author: Focaltech Driver Team
*
* Created: 2016-08-15
*
* Abstract:
*
* Reference:
*
*****************************************************************************/
/*****************************************************************************
* 1.Included header files
*****************************************************************************/
#include "../focaltech_core.h"
#include "../focaltech_flash.h"
/*****************************************************************************
* Static function prototypes
*****************************************************************************/
/************************************************************************
* Name: fts_ft5822_upgrade
* Brief:
* Input:
* Output:
* Return: return 0 if success, otherwise return error code
***********************************************************************/
static int fts_ft5822_upgrade(struct i2c_client *client, u8 *buf, u32 len)
{
int ret = 0;
u32 start_addr = 0;
u8 cmd[4] = { 0 };
int ecc_in_host = 0;
int ecc_in_tp = 0;
if (NULL == buf) {
FTS_ERROR("fw buf is null");
return -EINVAL;
}
if ((len < FTS_MIN_LEN) || (len > (60 * 1024))) {
FTS_ERROR("fw buffer len(%x) fail", len);
return -EINVAL;
}
/* enter into upgrade environment */
ret = fts_fwupg_enter_into_boot(client);
if (ret < 0) {
FTS_ERROR("enter into pramboot/bootloader fail,ret=%d", ret);
goto fw_reset;
}
cmd[0] = FTS_CMD_FLASH_MODE;
cmd[1] = FLASH_MODE_UPGRADE_VALUE;
ret = fts_i2c_write(client, cmd, 2);
if (ret < 0) {
FTS_ERROR("upgrade mode(09) cmd write fail");
goto fw_reset;
}
cmd[0] = FTS_CMD_DATA_LEN;
cmd[1] = BYTE_OFF_16(len);
cmd[2] = BYTE_OFF_8(len);
cmd[3] = BYTE_OFF_0(len);
ret = fts_i2c_write(client, cmd, FTS_CMD_DATA_LEN_LEN);
if (ret < 0) {
FTS_ERROR("data len cmd write fail");
goto fw_reset;
}
ret = fts_fwupg_erase(client, FTS_REASE_APP_DELAY);
if (ret < 0) {
FTS_ERROR("erase cmd write fail");
goto fw_reset;
}
/* write app */
start_addr = upgrade_func_ft5822.appoff;
ecc_in_host = fts_flash_write_buf(client, start_addr, buf, len, 1);
if (ecc_in_host < 0) {
FTS_ERROR("lcd initial code write fail");
goto fw_reset;
}
/* ecc */
ecc_in_tp = fts_fwupg_ecc_cal(client, start_addr, len);
if (ecc_in_tp < 0) {
FTS_ERROR("ecc read fail");
goto fw_reset;
}
FTS_INFO("ecc in tp:%x, host:%x", ecc_in_tp, ecc_in_host);
if (ecc_in_tp != ecc_in_host) {
FTS_ERROR("ecc check fail");
goto fw_reset;
}
FTS_INFO("upgrade success, reset to normal boot");
ret = fts_fwupg_reset_in_boot(client);
if (ret < 0) {
FTS_ERROR("reset to normal boot fail");
}
msleep(200);
return 0;
fw_reset:
FTS_INFO("upgrade fail, reset to normal boot");
ret = fts_fwupg_reset_in_boot(client);
if (ret < 0) {
FTS_ERROR("reset to normal boot fail");
}
return -EIO;
}
struct upgrade_func upgrade_func_ft5822 = {
.ctype = {0x01},
.fwveroff = 0x10A,
.fwcfgoff = 0xFFB0,
.appoff = 0x0000,
.pramboot_supported = false,
.hid_supported = true,
.upgrade = fts_ft5822_upgrade,
};

View File

@@ -0,0 +1,591 @@
/*
*
* FocalTech TouchScreen driver.
*
* Copyright (c) 2010-2017, Focaltech Ltd. All rights reserved.
*
* 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.
*
*/
/*****************************************************************************
*
* File Name: focaltech_gestrue.c
*
* Author: Focaltech Driver Team
*
* Created: 2016-08-08
*
* Abstract:
*
* Reference:
*
*****************************************************************************/
/*****************************************************************************
* 1.Included header files
*****************************************************************************/
#include "focaltech_core.h"
#if FTS_GESTURE_EN
/******************************************************************************
* Private constant and macro definitions using #define
*****************************************************************************/
#define KEY_GESTURE_U KEY_U
#define KEY_GESTURE_UP KEY_UP
#define KEY_GESTURE_DOWN KEY_DOWN
#define KEY_GESTURE_LEFT KEY_LEFT
#define KEY_GESTURE_RIGHT KEY_RIGHT
#define KEY_GESTURE_O KEY_O
#define KEY_GESTURE_E KEY_E
#define KEY_GESTURE_M KEY_M
#define KEY_GESTURE_L KEY_L
#define KEY_GESTURE_W KEY_W
#define KEY_GESTURE_S KEY_S
#define KEY_GESTURE_V KEY_V
#define KEY_GESTURE_C KEY_C
#define KEY_GESTURE_Z KEY_Z
#define GESTURE_LEFT 0x20
#define GESTURE_RIGHT 0x21
#define GESTURE_UP 0x22
#define GESTURE_DOWN 0x23
#define GESTURE_DOUBLECLICK 0x24
#define GESTURE_O 0x30
#define GESTURE_W 0x31
#define GESTURE_M 0x32
#define GESTURE_E 0x33
#define GESTURE_L 0x44
#define GESTURE_S 0x46
#define GESTURE_V 0x54
#define GESTURE_Z 0x41
#define GESTURE_C 0x34
#define FTS_GESTRUE_POINTS 255
#define FTS_GESTRUE_POINTS_HEADER 8
/*****************************************************************************
* Private enumerations, structures and unions using typedef
*****************************************************************************/
/*
* header - byte0:gesture id
* byte1:pointnum
* byte2~7:reserved
* coordinate_x - All gesture point x coordinate
* coordinate_y - All gesture point y coordinate
* mode - 1:enable gesture function(default)
* - 0:disable
* active - 1:enter into gesture(suspend)
* 0:gesture disable or resume
*/
struct fts_gesture_st {
u8 header[FTS_GESTRUE_POINTS_HEADER];
u16 coordinate_x[FTS_GESTRUE_POINTS];
u16 coordinate_y[FTS_GESTRUE_POINTS];
u8 mode; /*host driver enable gesture flag*/
u8 active; /*gesture actutally work*/
};
/*****************************************************************************
* Static variables
*****************************************************************************/
static struct fts_gesture_st fts_gesture_data;
/*****************************************************************************
* Global variable or extern global variabls/functions
*****************************************************************************/
/*****************************************************************************
* Static function prototypes
*****************************************************************************/
static ssize_t fts_gesture_show(struct device *dev, struct device_attribute *attr, char *buf);
static ssize_t fts_gesture_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
static ssize_t fts_gesture_buf_show(struct device *dev, struct device_attribute *attr, char *buf);
static ssize_t fts_gesture_buf_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
/* sysfs gesture node
* read example: cat fts_gesture_mode ---read gesture mode
* write example:echo 01 > fts_gesture_mode ---write gesture mode to 01
*
*/
static DEVICE_ATTR (fts_gesture_mode, S_IRUGO | S_IWUSR, fts_gesture_show, fts_gesture_store);
/*
* read example: cat fts_gesture_buf ---read gesture buf
*/
static DEVICE_ATTR (fts_gesture_buf, S_IRUGO | S_IWUSR, fts_gesture_buf_show, fts_gesture_buf_store);
static struct attribute *fts_gesture_mode_attrs[] = {
&dev_attr_fts_gesture_mode.attr,
&dev_attr_fts_gesture_buf.attr,
NULL,
};
static struct attribute_group fts_gesture_group = {
.attrs = fts_gesture_mode_attrs,
};
/************************************************************************
* Name: fts_gesture_show
* Brief:
* Input: device, device attribute, char buf
* Output:
* Return:
***********************************************************************/
static ssize_t fts_gesture_show(struct device *dev, struct device_attribute *attr, char *buf)
{
int count;
u8 val;
struct input_dev *input_dev = fts_data->input_dev;
struct i2c_client *client = container_of(dev, struct i2c_client, dev);
mutex_lock(&input_dev->mutex);
fts_i2c_read_reg(client, FTS_REG_GESTURE_EN, &val);
count = snprintf(buf, PAGE_SIZE, "Gesture Mode: %s\n", fts_gesture_data.mode ? "On" : "Off");
count += snprintf(buf + count, PAGE_SIZE, "Reg(0xD0) = %d\n", val);
mutex_unlock(&input_dev->mutex);
return count;
}
/************************************************************************
* Name: fts_gesture_store
* Brief:
* Input: device, device attribute, char buf, char count
* Output:
* Return:
***********************************************************************/
static ssize_t fts_gesture_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct input_dev *input_dev = fts_data->input_dev;
mutex_lock(&input_dev->mutex);
if (FTS_SYSFS_ECHO_ON(buf)) {
FTS_INFO("[GESTURE]enable gesture");
fts_gesture_data.mode = ENABLE;
} else if (FTS_SYSFS_ECHO_OFF(buf)) {
FTS_INFO("[GESTURE]disable gesture");
fts_gesture_data.mode = DISABLE;
}
mutex_unlock(&input_dev->mutex);
return count;
}
/************************************************************************
* Name: fts_gesture_buf_show
* Brief:
* Input: device, device attribute, char buf
* Output:
* Return:
***********************************************************************/
static ssize_t fts_gesture_buf_show(struct device *dev, struct device_attribute *attr, char *buf)
{
int count;
int i = 0;
struct input_dev *input_dev = fts_data->input_dev;
mutex_lock(&input_dev->mutex);
count = snprintf(buf, PAGE_SIZE, "Gesture ID: 0x%x\n", fts_gesture_data.header[0]);
count += snprintf(buf + count, PAGE_SIZE, "Gesture PointNum: %d\n", fts_gesture_data.header[1]);
count += snprintf(buf + count, PAGE_SIZE, "Gesture Point Buf:\n");
for (i = 0; i < fts_gesture_data.header[1]; i++) {
count += snprintf(buf + count, PAGE_SIZE, "%3d(%4d,%4d) ", i, fts_gesture_data.coordinate_x[i], fts_gesture_data.coordinate_y[i]);
if ((i + 1) % 4 == 0)
count += snprintf(buf + count, PAGE_SIZE, "\n");
}
count += snprintf(buf + count, PAGE_SIZE, "\n");
mutex_unlock(&input_dev->mutex);
return count;
}
/************************************************************************
* Name: fts_gesture_buf_store
* Brief:
* Input: device, device attribute, char buf, char count
* Output:
* Return:
***********************************************************************/
static ssize_t fts_gesture_buf_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
/* place holder for future use */
return -EPERM;
}
/*****************************************************************************
* Name: fts_create_gesture_sysfs
* Brief:
* Input:
* Output:
* Return: 0-success or others-error
*****************************************************************************/
int fts_create_gesture_sysfs(struct i2c_client *client)
{
int ret = 0;
ret = sysfs_create_group(&client->dev.kobj, &fts_gesture_group);
if (ret != 0) {
FTS_ERROR("[GESTURE]fts_gesture_mode_group(sysfs) create failed!");
sysfs_remove_group(&client->dev.kobj, &fts_gesture_group);
return ret;
}
return 0;
}
/*****************************************************************************
* Name: fts_gesture_report
* Brief:
* Input:
* Output:
* Return:
*****************************************************************************/
static void fts_gesture_report(struct input_dev *input_dev, int gesture_id)
{
int gesture;
FTS_FUNC_ENTER();
FTS_INFO("fts gesture_id==0x%x ", gesture_id);
switch (gesture_id) {
case GESTURE_LEFT:
gesture = KEY_GESTURE_LEFT;
break;
case GESTURE_RIGHT:
gesture = KEY_GESTURE_RIGHT;
break;
case GESTURE_UP:
gesture = KEY_GESTURE_UP;
break;
case GESTURE_DOWN:
gesture = KEY_GESTURE_DOWN;
break;
case GESTURE_DOUBLECLICK:
gesture = KEY_GESTURE_U;
break;
case GESTURE_O:
gesture = KEY_GESTURE_O;
break;
case GESTURE_W:
gesture = KEY_GESTURE_W;
break;
case GESTURE_M:
gesture = KEY_GESTURE_M;
break;
case GESTURE_E:
gesture = KEY_GESTURE_E;
break;
case GESTURE_L:
gesture = KEY_GESTURE_L;
break;
case GESTURE_S:
gesture = KEY_GESTURE_S;
break;
case GESTURE_V:
gesture = KEY_GESTURE_V;
break;
case GESTURE_Z:
gesture = KEY_GESTURE_Z;
break;
case GESTURE_C:
gesture = KEY_GESTURE_C;
break;
default:
gesture = -1;
break;
}
/* report event key */
if (gesture != -1) {
FTS_DEBUG("Gesture Code=%d", gesture);
input_report_key(input_dev, gesture, 1);
input_sync(input_dev);
input_report_key(input_dev, gesture, 0);
input_sync(input_dev);
}
FTS_FUNC_EXIT();
}
/************************************************************************
* Name: fts_gesture_read_buffer
* Brief: read data from TP register
* Input:
* Output:
* Return: fail <0
***********************************************************************/
static int fts_gesture_read_buffer(struct i2c_client *client, u8 *buf, int read_bytes)
{
int remain_bytes;
int ret;
int i;
if (read_bytes <= I2C_BUFFER_LENGTH_MAXINUM) {
ret = fts_i2c_read(client, buf, 1, buf, read_bytes);
} else {
ret = fts_i2c_read(client, buf, 1, buf, I2C_BUFFER_LENGTH_MAXINUM);
remain_bytes = read_bytes - I2C_BUFFER_LENGTH_MAXINUM;
for (i = 1; remain_bytes > 0; i++) {
if (remain_bytes <= I2C_BUFFER_LENGTH_MAXINUM)
ret = fts_i2c_read(client, buf, 0, buf + I2C_BUFFER_LENGTH_MAXINUM * i, remain_bytes);
else
ret = fts_i2c_read(client, buf, 0, buf + I2C_BUFFER_LENGTH_MAXINUM * i, I2C_BUFFER_LENGTH_MAXINUM);
remain_bytes -= I2C_BUFFER_LENGTH_MAXINUM;
}
}
return ret;
}
/************************************************************************
* Name: fts_gesture_readdata
* Brief: read data from TP register
* Input:
* Output:
* Return: return 0 if succuss, otherwise reture error code
***********************************************************************/
int fts_gesture_readdata(struct fts_ts_data *ts_data)
{
u8 buf[FTS_GESTRUE_POINTS * 4] = { 0 };
int ret = 0;
int i = 0;
int gestrue_id = 0;
int read_bytes = 0;
u8 pointnum;
u8 state;
struct i2c_client *client = ts_data->client;
struct input_dev *input_dev = ts_data->input_dev;
if (!ts_data->suspended) {
return -EINVAL;
}
ret = fts_i2c_read_reg(client, FTS_REG_GESTURE_EN, &state);
if ((ret < 0) || (state != ENABLE)) {
FTS_DEBUG("gesture not enable, don't process gesture");
return -EIO;
}
/* init variable before read gesture point */
memset(fts_gesture_data.header, 0, FTS_GESTRUE_POINTS_HEADER);
memset(fts_gesture_data.coordinate_x, 0, FTS_GESTRUE_POINTS * sizeof(u16));
memset(fts_gesture_data.coordinate_y, 0, FTS_GESTRUE_POINTS * sizeof(u16));
buf[0] = FTS_REG_GESTURE_OUTPUT_ADDRESS;
ret = fts_i2c_read(client, buf, 1, buf, FTS_GESTRUE_POINTS_HEADER);
if (ret < 0) {
FTS_ERROR("[GESTURE]Read gesture header data failed!!");
FTS_FUNC_EXIT();
return ret;
}
memcpy(fts_gesture_data.header, buf, FTS_GESTRUE_POINTS_HEADER);
gestrue_id = buf[0];
pointnum = buf[1];
read_bytes = ((int)pointnum) * 4 + 2;
buf[0] = FTS_REG_GESTURE_OUTPUT_ADDRESS;
FTS_DEBUG("[GESTURE]PointNum=%d", pointnum);
ret = fts_gesture_read_buffer(client, buf, read_bytes);
if (ret < 0) {
FTS_ERROR("[GESTURE]Read gesture touch data failed!!");
FTS_FUNC_EXIT();
return ret;
}
fts_gesture_report(input_dev, gestrue_id);
for (i = 0; i < pointnum; i++) {
fts_gesture_data.coordinate_x[i] = (((s16) buf[0 + (4 * i + 2)]) & 0x0F) << 8
| (((s16) buf[1 + (4 * i + 2)]) & 0xFF);
fts_gesture_data.coordinate_y[i] = (((s16) buf[2 + (4 * i + 2)]) & 0x0F) << 8
| (((s16) buf[3 + (4 * i + 2)]) & 0xFF);
}
return 0;
}
/*****************************************************************************
* Name: fts_gesture_recovery
* Brief: recovery gesture state when reset or power on
* Input:
* Output:
* Return:
*****************************************************************************/
void fts_gesture_recovery(struct i2c_client *client)
{
if ((ENABLE == fts_gesture_data.mode) && (ENABLE == fts_gesture_data.active)) {
FTS_INFO("enter fts_gesture_recovery");
fts_i2c_write_reg(client, 0xD1, 0xff);
fts_i2c_write_reg(client, 0xD2, 0xff);
fts_i2c_write_reg(client, 0xD5, 0xff);
fts_i2c_write_reg(client, 0xD6, 0xff);
fts_i2c_write_reg(client, 0xD7, 0xff);
fts_i2c_write_reg(client, 0xD8, 0xff);
fts_i2c_write_reg(client, FTS_REG_GESTURE_EN, ENABLE);
}
}
/*****************************************************************************
* Name: fts_gesture_suspend
* Brief:
* Input:
* Output:
* Return: return 0 if succuss, otherwise return error code
*****************************************************************************/
int fts_gesture_suspend(struct i2c_client *client)
{
int ret;
int i;
u8 state;
FTS_INFO("gesture suspend...");
/* gesture not enable, return immediately */
if (fts_gesture_data.mode == DISABLE) {
FTS_INFO("gesture is disabled");
return -EINVAL;
}
for (i = 0; i < 5; i++) {
fts_i2c_write_reg(client, 0xd1, 0xff);
fts_i2c_write_reg(client, 0xd2, 0xff);
fts_i2c_write_reg(client, 0xd5, 0xff);
fts_i2c_write_reg(client, 0xd6, 0xff);
fts_i2c_write_reg(client, 0xd7, 0xff);
fts_i2c_write_reg(client, 0xd8, 0xff);
fts_i2c_write_reg(client, FTS_REG_GESTURE_EN, ENABLE);
msleep(1);
fts_i2c_read_reg(client, FTS_REG_GESTURE_EN, &state);
if (state == ENABLE)
break;
}
if (i >= 5) {
FTS_ERROR("[GESTURE]Enter into gesture(suspend) failed!\n");
fts_gesture_data.active = DISABLE;
return -EIO;
}
ret = enable_irq_wake(fts_data->irq);
if (ret) {
FTS_INFO("enable_irq_wake(irq:%d) failed", fts_data->irq);
}
fts_gesture_data.active = ENABLE;
FTS_INFO("[GESTURE]Enter into gesture(suspend) successfully!");
FTS_FUNC_EXIT();
return 0;
}
/*****************************************************************************
* Name: fts_gesture_resume
* Brief:
* Input:
* Output:
* Return: return 0 if succuss, otherwise return error code
*****************************************************************************/
int fts_gesture_resume(struct i2c_client *client)
{
int ret;
int i;
u8 state;
FTS_INFO("gesture resume...");
/* gesture not enable, return immediately */
if (fts_gesture_data.mode == DISABLE) {
FTS_DEBUG("gesture is disabled");
return -EINVAL;
}
if (fts_gesture_data.active == DISABLE) {
FTS_DEBUG("gesture in suspend is failed, no running fts_gesture_resume");
return -EINVAL;
}
for (i = 0; i < 5; i++) {
fts_i2c_write_reg(client, FTS_REG_GESTURE_EN, DISABLE);
msleep(1);
fts_i2c_read_reg(client, FTS_REG_GESTURE_EN, &state);
if (state == DISABLE)
break;
}
if (i >= 5) {
FTS_ERROR("[GESTURE]Clear gesture(resume) failed!\n");
return -EIO;
}
ret = disable_irq_wake(fts_data->irq);
if (ret) {
FTS_INFO("disable_irq_wake(irq:%d) failed", fts_data->irq);
}
FTS_INFO("[GESTURE]resume from gesture successfully!");
FTS_FUNC_EXIT();
return 0;
}
/*****************************************************************************
* Name: fts_gesture_init
* Brief:
* Input:
* Output:
* Return:
*****************************************************************************/
int fts_gesture_init(struct fts_ts_data *ts_data)
{
struct i2c_client *client = ts_data->client;
struct input_dev *input_dev = ts_data->input_dev;
FTS_FUNC_ENTER();
input_set_capability(input_dev, EV_KEY, KEY_POWER);
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_U);
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_UP);
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_DOWN);
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_LEFT);
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_RIGHT);
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_O);
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_E);
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_M);
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_L);
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_W);
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_S);
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_V);
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_Z);
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_C);
__set_bit(KEY_GESTURE_RIGHT, input_dev->keybit);
__set_bit(KEY_GESTURE_LEFT, input_dev->keybit);
__set_bit(KEY_GESTURE_UP, input_dev->keybit);
__set_bit(KEY_GESTURE_DOWN, input_dev->keybit);
__set_bit(KEY_GESTURE_U, input_dev->keybit);
__set_bit(KEY_GESTURE_O, input_dev->keybit);
__set_bit(KEY_GESTURE_E, input_dev->keybit);
__set_bit(KEY_GESTURE_M, input_dev->keybit);
__set_bit(KEY_GESTURE_W, input_dev->keybit);
__set_bit(KEY_GESTURE_L, input_dev->keybit);
__set_bit(KEY_GESTURE_S, input_dev->keybit);
__set_bit(KEY_GESTURE_V, input_dev->keybit);
__set_bit(KEY_GESTURE_C, input_dev->keybit);
__set_bit(KEY_GESTURE_Z, input_dev->keybit);
fts_create_gesture_sysfs(client);
fts_gesture_data.mode = ENABLE;
fts_gesture_data.active = DISABLE;
FTS_FUNC_EXIT();
return 0;
}
/************************************************************************
* Name: fts_gesture_exit
* Brief: call when driver removed
* Input:
* Output:
* Return:
***********************************************************************/
int fts_gesture_exit(struct i2c_client *client)
{
FTS_FUNC_ENTER();
sysfs_remove_group(&client->dev.kobj, &fts_gesture_group);
FTS_FUNC_EXIT();
return 0;
}
#endif

View File

@@ -0,0 +1,243 @@
/*
*
* FocalTech TouchScreen driver.
*
* Copyright (c) 2010-2018, FocalTech Systems, Ltd., all rights reserved.
*
* 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.
*
*/
/************************************************************************
*
* File Name: focaltech_i2c.c
*
* Author: fupeipei
*
* Created: 2016-08-04
*
* Abstract: i2c communication with TP
*
* Version: v1.0
*
* Revision History:
* v1.0:
* First release. By fupeipei 2016-08-04
************************************************************************/
/*****************************************************************************
* Included header files
*****************************************************************************/
#include "focaltech_core.h"
/*****************************************************************************
* Private constant and macro definitions using #define
*****************************************************************************/
#define I2C_RETRY_NUMBER 3
/*****************************************************************************
* Private enumerations, structures and unions using typedef
*****************************************************************************/
/*****************************************************************************
* Static variables
*****************************************************************************/
static DEFINE_MUTEX(i2c_rw_access);
/*****************************************************************************
* Global variable or extern global variabls/functions
*****************************************************************************/
/*****************************************************************************
* Static function prototypes
*****************************************************************************/
/*****************************************************************************
* functions body
*****************************************************************************/
/************************************************************************
* Name: fts_i2c_read
* Brief: i2c read
* Input: i2c info, write buf, write len, read buf, read len
* Output: get data in the 3rd buf
* Return: fail <0
***********************************************************************/
int fts_i2c_read(struct i2c_client *client, char *writebuf, int writelen, char *readbuf, int readlen)
{
int ret = 0;
int i = 0;
mutex_lock(&i2c_rw_access);
if (readlen > 0) {
if (writelen > 0) {
struct i2c_msg msgs[] = {
{
.addr = client->addr,
.flags = 0,
.len = writelen,
.buf = writebuf,
},
{
.addr = client->addr,
.flags = I2C_M_RD,
.len = readlen,
.buf = readbuf,
},
};
for (i = 0; i < I2C_RETRY_NUMBER; i++) {
ret = i2c_transfer(client->adapter, msgs, 2);
if (ret < 0) {
FTS_ERROR("[IIC]: i2c_transfer(write) error, ret=%d!!", ret);
} else
break;
}
} else {
struct i2c_msg msgs[] = {
{
.addr = client->addr,
.flags = I2C_M_RD,
.len = readlen,
.buf = readbuf,
},
};
for (i = 0; i < I2C_RETRY_NUMBER; i++) {
ret = i2c_transfer(client->adapter, msgs, 1);
if (ret < 0) {
FTS_ERROR("[IIC]: i2c_transfer(read) error, ret=%d!!", ret);
} else
break;
}
}
}
mutex_unlock(&i2c_rw_access);
return ret;
}
EXPORT_SYMBOL(fts_i2c_read);
/************************************************************************
* Name: fts_i2c_write
* Brief: i2c write
* Input: i2c info, write buf, write len
* Output: no
* Return: fail <0
***********************************************************************/
int fts_i2c_write(struct i2c_client *client, char *writebuf, int writelen)
{
int ret = 0;
int i = 0;
mutex_lock(&i2c_rw_access);
if (writelen > 0) {
struct i2c_msg msgs[] = {
{
.addr = client->addr,
.flags = 0,
.len = writelen,
.buf = writebuf,
},
};
for (i = 0; i < I2C_RETRY_NUMBER; i++) {
ret = i2c_transfer(client->adapter, msgs, 1);
if (ret < 0) {
FTS_ERROR("%s: i2c_transfer(write) error, ret=%d", __func__, ret);
} else
break;
}
}
mutex_unlock(&i2c_rw_access);
return ret;
}
EXPORT_SYMBOL(fts_i2c_write);
/************************************************************************
* Name: fts_i2c_write_reg
* Brief: write register
* Input: i2c info, reg address, reg value
* Output: no
* Return: fail <0
***********************************************************************/
int fts_i2c_write_reg(struct i2c_client *client, u8 regaddr, u8 regvalue)
{
u8 buf[2] = {0};
buf[0] = regaddr;
buf[1] = regvalue;
return fts_i2c_write(client, buf, sizeof(buf));
}
/************************************************************************
* Name: fts_i2c_read_reg
* Brief: read register
* Input: i2c info, reg address, reg value
* Output: get reg value
* Return: fail <0
***********************************************************************/
int fts_i2c_read_reg(struct i2c_client *client, u8 regaddr, u8 *regvalue)
{
return fts_i2c_read(client, &regaddr, 1, regvalue, 1);
}
/************************************************************************
* HID to standard I2C
***********************************************************************/
void fts_i2c_hid2std(struct i2c_client *client)
{
int ret = 0;
u8 buf[3] = {0xeb, 0xaa, 0x09};
ret = fts_i2c_write(client, buf, 3);
if (ret < 0)
FTS_ERROR("hid2std cmd write fail");
else {
msleep(10);
buf[0] = buf[1] = buf[2] = 0;
ret = fts_i2c_read(client, NULL, 0, buf, 3);
if (ret < 0)
FTS_ERROR("hid2std cmd read fail");
else if ((0xeb == buf[0]) && (0xaa == buf[1]) && (0x08 == buf[2])) {
FTS_DEBUG("hidi2c change to stdi2c successful");
} else {
FTS_ERROR("hidi2c change to stdi2c fail");
}
}
}
/************************************************************************
* Name: fts_i2c_init
* Brief: fts i2c init
* Input:
* Output:
* Return:
***********************************************************************/
int fts_i2c_init(void)
{
FTS_FUNC_ENTER();
FTS_FUNC_EXIT();
return 0;
}
/************************************************************************
* Name: fts_i2c_exit
* Brief: fts i2c exit
* Input:
* Output:
* Return:
***********************************************************************/
int fts_i2c_exit(void)
{
FTS_FUNC_ENTER();
FTS_FUNC_EXIT();
return 0;
}

View File

@@ -0,0 +1,136 @@
/*
*
* FocalTech TouchScreen driver.
*
* Copyright (c) 2010-2018, FocalTech Systems, Ltd., all rights reserved.
*
* 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.
*
*/
/*****************************************************************************
*
* File Name: focaltech_point_report_check.c
*
* Author: WangTao
*
* Created: 2016-11-16
*
* Abstract: point report check function
*
* Version: v1.0
*
* Revision History:
* v1.0:
* First release. By WangTao 2016-11-16
*****************************************************************************/
/*****************************************************************************
* Included header files
*****************************************************************************/
#include "focaltech_core.h"
#if FTS_POINT_REPORT_CHECK_EN
/*****************************************************************************
* Private constant and macro definitions using #define
*****************************************************************************/
#define POINT_REPORT_CHECK_WAIT_TIME 200 /* unit:ms */
/*****************************************************************************
* functions body
*****************************************************************************/
/*****************************************************************************
* Name: fts_prc_func
* Brief: fts point report check work func, report whole up of points
* Input:
* Output:
* Return:
*****************************************************************************/
static void fts_prc_func(struct work_struct *work)
{
struct fts_ts_data *ts_data = container_of(work,
struct fts_ts_data, prc_work.work);
struct input_dev *input_dev = ts_data->input_dev;
#if FTS_MT_PROTOCOL_B_EN
u32 finger_count = 0;
#endif
FTS_FUNC_ENTER();
mutex_lock(&ts_data->report_mutex);
#if FTS_MT_PROTOCOL_B_EN
for (finger_count = 0; finger_count < ts_data->pdata->max_touch_number; finger_count++) {
input_mt_slot(input_dev, finger_count);
input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, false);
}
#else
input_mt_sync(input_dev);
#endif
input_report_key(input_dev, BTN_TOUCH, 0);
input_sync(input_dev);
mutex_unlock(&ts_data->report_mutex);
FTS_FUNC_EXIT();
}
/*****************************************************************************
* Name: fts_prc_queue_work
* Brief: fts point report check queue work, call it when interrupt comes
* Input:
* Output:
* Return:
*****************************************************************************/
void fts_prc_queue_work(struct fts_ts_data *ts_data)
{
cancel_delayed_work(&ts_data->prc_work);
queue_delayed_work(ts_data->ts_workqueue, &ts_data->prc_work,
msecs_to_jiffies(POINT_REPORT_CHECK_WAIT_TIME));
}
/*****************************************************************************
* Name: fts_point_report_check_init
* Brief:
* Input:
* Output:
* Return: < 0: Fail to create esd check queue
*****************************************************************************/
int fts_point_report_check_init(struct fts_ts_data *ts_data)
{
FTS_FUNC_ENTER();
if (ts_data->ts_workqueue) {
INIT_DELAYED_WORK(&ts_data->prc_work, fts_prc_func);
} else {
FTS_ERROR("fts workqueue is NULL, can't run point report check function");
return -EINVAL;
}
FTS_FUNC_EXIT();
return 0;
}
/*****************************************************************************
* Name: fts_point_report_check_exit
* Brief:
* Input:
* Output:
* Return:
*****************************************************************************/
int fts_point_report_check_exit(struct fts_ts_data *ts_data)
{
FTS_FUNC_ENTER();
FTS_FUNC_EXIT();
return 0;
}
#endif /* FTS_POINT_REPORT_CHECK_EN */