mirror of
https://github.com/hardkernel/linux.git
synced 2026-03-24 19:40:21 +09:00
[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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
73
drivers/input/touchscreen/focaltech_touch/Kconfig
Normal file
73
drivers/input/touchscreen/focaltech_touch/Kconfig
Normal 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
|
||||
25
drivers/input/touchscreen/focaltech_touch/Makefile
Normal file
25
drivers/input/touchscreen/focaltech_touch/Makefile
Normal 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/
|
||||
168
drivers/input/touchscreen/focaltech_touch/focaltech_common.h
Normal file
168
drivers/input/touchscreen/focaltech_touch/focaltech_common.h
Normal 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__ */
|
||||
232
drivers/input/touchscreen/focaltech_touch/focaltech_config.h
Normal file
232
drivers/input/touchscreen/focaltech_touch/focaltech_config.h
Normal 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_ */
|
||||
1841
drivers/input/touchscreen/focaltech_touch/focaltech_core.c
Executable file
1841
drivers/input/touchscreen/focaltech_touch/focaltech_core.c
Executable file
File diff suppressed because it is too large
Load Diff
258
drivers/input/touchscreen/focaltech_touch/focaltech_core.h
Normal file
258
drivers/input/touchscreen/focaltech_touch/focaltech_core.h
Normal 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__ */
|
||||
552
drivers/input/touchscreen/focaltech_touch/focaltech_esdcheck.c
Normal file
552
drivers/input/touchscreen/focaltech_touch/focaltech_esdcheck.c
Normal 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, ®_addr, 1, ®_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, ®_addr, 1, ®_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, ®_addr, 1, ®_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 */
|
||||
|
||||
1319
drivers/input/touchscreen/focaltech_touch/focaltech_ex_fun.c
Executable file
1319
drivers/input/touchscreen/focaltech_touch/focaltech_ex_fun.c
Executable file
File diff suppressed because it is too large
Load Diff
382
drivers/input/touchscreen/focaltech_touch/focaltech_ex_mode.c
Normal file
382
drivers/input/touchscreen/focaltech_touch/focaltech_ex_mode.c
Normal 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;
|
||||
}
|
||||
|
||||
2013
drivers/input/touchscreen/focaltech_touch/focaltech_flash.c
Executable file
2013
drivers/input/touchscreen/focaltech_touch/focaltech_flash.c
Executable file
File diff suppressed because it is too large
Load Diff
172
drivers/input/touchscreen/focaltech_touch/focaltech_flash.h
Normal file
172
drivers/input/touchscreen/focaltech_touch/focaltech_flash.h
Normal 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
|
||||
@@ -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
|
||||
@@ -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,
|
||||
};
|
||||
@@ -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,
|
||||
};
|
||||
591
drivers/input/touchscreen/focaltech_touch/focaltech_gesture.c
Normal file
591
drivers/input/touchscreen/focaltech_touch/focaltech_gesture.c
Normal 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
|
||||
243
drivers/input/touchscreen/focaltech_touch/focaltech_i2c.c
Normal file
243
drivers/input/touchscreen/focaltech_touch/focaltech_i2c.c
Normal 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, ®addr, 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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user