PD#158972: touchscreen: focaltech ft3x27 driver support

Change-Id: I5e1de4a6074a75c288d52fd388323978415610bd
Signed-off-by: Sunny Luo <sunny.luo@amlogic.com>
This commit is contained in:
Sunny Luo
2018-01-18 14:08:22 +08:00
committed by Jianxin Pan
parent 6c8ce66989
commit 4f75f1bd8b
27 changed files with 8843 additions and 0 deletions

View File

@@ -0,0 +1,28 @@
* Focaltech FT3x27 series touchscreen controller
Required properties:
- compatible: Should be "focaltech,fts"
- reg: I2C address of the chip. Should be 0x38
- irq-gpio: GPIO pin used for IRQ
- reset-gpio: GPIO pin used for reset
- x_max: horizontal resolution
- y_max: vertical resolution
- max-touch-number: the max touch fingers support
Example:
i2c1: i2c@1e000 {
/* ... */
focaltech_ts@0x38 {
compatible = "focaltech,fts";
status = "okay";
reg = <0x38>;
reset-gpio = <&gpio GPIOZ_2 0x00>;
irq-gpio = <&gpio GPIOZ_3 0x00>;
x_max = <600>;
y_max = <1024>;
max-touch-number = <10>;
};
/* ... */
};

View File

@@ -14250,3 +14250,9 @@ AMLOGIC LEDRING DRIVER IOCTL
M: Renjun Xu <renjun.xu@amlogic.com>
F: drivers/amlogic/ledring/aml-is31fl32xx.c
F: drivers/amlogic/ledring/aml-pca9557.c
AMLOGIC TOUCHSCREEN DRIVER
M: Sunny Luo <sunny.luo@amlogic.com>
F: Documentation/devicetree/bindings/input/touchscreen/amlogic-ts.txt
F: drivers/amlogic/input/touchscreen/*
F: drivers/amlogic/input/touchscreen/focaltech_touch/*

View File

@@ -234,6 +234,8 @@ CONFIG_AMLOGIC_ADC_KEYPADS=y
CONFIG_AMLOGIC_GPIO_KEY=y
CONFIG_AMLOGIC_REMOTE=y
CONFIG_AMLOGIC_MESON_REMOTE=y
CONFIG_AMLOGIC_TOUCHSCREEN=y
CONFIG_AMLOGIC_TOUCHSCREEN_FTS=y
CONFIG_AMLOGIC_EFUSE=y
CONFIG_AMLOGIC_REBOOT=y
CONFIG_AMLOGIC_GX_REBOOT=y

View File

@@ -13,5 +13,7 @@ if AMLOGIC_INPUT
source "drivers/amlogic/input/keyboard/Kconfig"
source "drivers/amlogic/input/remote/Kconfig"
source "drivers/amlogic/input/touchscreen/Kconfig"
endif

View File

@@ -7,3 +7,5 @@
obj-$(CONFIG_AMLOGIC_INPUT_KEYBOARD) += keyboard/
obj-$(CONFIG_AMLOGIC_REMOTE) += remote/
obj-$(CONFIG_AMLOGIC_TOUCHSCREEN) += touchscreen/

View File

@@ -0,0 +1,22 @@
#
# touchscreen drivers
#
menuconfig AMLOGIC_TOUCHSCREEN
bool "amlogic touchscreen"
default n
help
Say Y here, and a list of supported touchscreen driver will be displayed.
This option doesn't affect the kernel.
if AMLOGIC_TOUCHSCREEN
config AMLOGIC_TOUCHSCREEN_FTS
tristate "facaltech FT_xx touch driver support"
depends on I2C
default n
help
Say Y here if you want to use facaltech FT_xx.
endif

View File

@@ -0,0 +1,7 @@
#
# Makefile for touchscreen drivers.
#
# Each configuration option enables a list of files.
obj-$(CONFIG_AMLOGIC_TOUCHSCREEN_FTS) += focaltech_touch/

View File

@@ -0,0 +1,17 @@
#
# Focaltech Touchscreen driver configuration
#
config AMLOGIC_TOUCHSCREEN_FTS
bool "Focaltech Touchscreen"
depends on I2C
default n
help
Say Y here if you have Focaltech touch panel.
If unsure, say N.
config AMLOGIC_TOUCHSCREEN_FTS_DIRECTORY
string "Focaltech ts directory name"
default "focaltech_touch"
depends on AMLOGIC_TOUCHSCREEN_FTS

View File

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

View File

@@ -0,0 +1,196 @@
/*
*
* FocalTech fts 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_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 V1.4 20170630"
#define FLAGBIT(x) (0x00000001 << (x))
#define FLAGBITS(x, y) ((0xFFFFFFFF >> (32 - (y) - 1)) << (x))
#define FLAG_ICSERIALS_LEN 5
#define FLAG_IDC_BIT 11
#define IC_SERIALS (FTS_CHIP_TYPE & FLAGBITS(0, FLAG_ICSERIALS_LEN-1))
#define FTS_CHIP_IDC ((FTS_CHIP_TYPE & FLAGBIT(FLAG_IDC_BIT)) == FLAGBIT(FLAG_IDC_BIT))
#define FTS_CHIP_TYPE_MAPPING {{0x07,0x80, 0x06, 0x80, 0x06, 0x80, 0xC6, 0x80, 0xB6}}
#define I2C_BUFFER_LENGTH_MAXINUM 256
#define FILE_NAME_LENGTH 128
#define ENABLE 1
#define DISABLE 0
/*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_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_LCD_BUSY_NUM 0xAB
#define FTS_REG_FACE_DEC_MODE_EN 0xB0
#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_ESD_SATURATE 0xED
/*****************************************************************************
* 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
{
unsigned long type;
unsigned char chip_idh;
unsigned char chip_idl;
unsigned char rom_idh;
unsigned char rom_idl;
unsigned char pramboot_idh;
unsigned char pramboot_idl;
unsigned char bootloader_idh;
unsigned char bootloader_idl;
};
/* 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);
int fts_i2c_init(void);
int fts_i2c_exit(void);
/* Gesture functions */
#if FTS_GESTURE_EN
int fts_gesture_init(struct input_dev *input_dev, struct i2c_client *client);
int fts_gesture_exit(struct i2c_client *client);
void fts_gesture_recovery(struct i2c_client *client);
int fts_gesture_readdata(struct i2c_client *client);
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 i2c_client * client);
void fts_release_apk_debug_channel(void);
#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(void);
int fts_esdcheck_exit(void);
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);
int fts_esdcheck_get_status(void);
#endif
/* Point Report Check*/
#if FTS_POINT_REPORT_CHECK_EN
int fts_point_report_check_init(void);
int fts_point_report_check_exit(void);
void fts_point_report_check_queue_work(void);
#endif
/* Other */
extern int g_show_log;
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);
/*****************************************************************************
* DEBUG function define here
*****************************************************************************/
#if FTS_DEBUG_EN
#define FTS_DEBUG_LEVEL 1
#if (FTS_DEBUG_LEVEL == 2)
#define FTS_DEBUG(fmt, args...) printk(KERN_ERR "[FTS][%s]"fmt"\n", __func__, ##args)
#else
#define FTS_DEBUG(fmt, args...) printk(KERN_ERR "[FTS]"fmt"\n", ##args)
#endif
#define FTS_FUNC_ENTER() printk(KERN_ERR "[FTS]%s: Enter\n", __func__)
#define FTS_FUNC_EXIT() printk(KERN_ERR "[FTS]%s: Exit(%d)\n", __func__, __LINE__)
#else
#define FTS_DEBUG(fmt, args...)
#define FTS_FUNC_ENTER()
#define FTS_FUNC_EXIT()
#endif
#define FTS_INFO(fmt, args...) do { \
if (g_show_log) {printk(KERN_ERR "[FTS][Info]"fmt"\n", ##args);} \
} while (0)
#define FTS_ERROR(fmt, args...) do { \
if (g_show_log) {printk(KERN_ERR "[FTS][Error]"fmt"\n", ##args);} \
} while (0)
#endif /* __LINUX_FOCALTECH_COMMON_H__ */

View File

@@ -0,0 +1,228 @@
/*
*
* 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_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 _FT7250 0x72500807
#define _FT8606 0x86060808
#define _FT8607 0x86070809
#define _FTE716 0xE716080a
#define _FT5416 0x54160002
#define _FT5426 0x54260002
#define _FT5435 0x54350002
#define _FT5436 0x54360002
#define _FT5526 0x55260002
#define _FT5526I 0x5526B002
#define _FT5446 0x54460002
#define _FT5346 0x53460002
#define _FT5446I 0x5446B002
#define _FT5346I 0x5346B002
#define _FT7661 0x76610002
#define _FT7511 0x75110002
#define _FT7421 0x74210002
#define _FT7681 0x76810002
#define _FT3C47U 0x3C47D002
#define _FT3417 0x34170002
#define _FT3517 0x35170002
#define _FT3327 0x33270002
#define _FT3427 0x34270002
#define _FT5626 0x56260001
#define _FT5726 0x57260001
#define _FT5826B 0x5826B001
#define _FT5826S 0x5826C001
#define _FT7811 0x78110001
#define _FT3D47 0x3D470001
#define _FT3617 0x36170001
#define _FT3717 0x37170001
#define _FT3817B 0x3817B001
#define _FT6236U 0x6236D003
#define _FT6336G 0x6336A003
#define _FT6336U 0x6336D003
#define _FT6436U 0x6436D003
#define _FT3267 0x32670004
#define _FT3367 0x33670004
/*************************************************/
/*
* choose your ic chip type of focaltech
*/
#define FTS_CHIP_TYPE _FT7250
/******************* 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
/*
* 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
/*
* Proximity sensor
* default: disable
*/
#define FTS_PSENSOR_EN 0
/*
* Nodes for tools, please keep enable
*/
#define FTS_SYSFS_NODE_EN 1
#define FTS_APK_NODE_EN 1
/*
* 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
* default: 0
*/
#define FTS_AUTO_UPGRADE_FOR_LCD_CFG_EN 1
/* auto cb check
* default: disable
*/
#define FTS_AUTO_CLB_EN 0
/*
* Check vendor_id number
* 0:No check vendor_id (default)
* 1/2/3: Check vendor_id for vendor compatibility
*/
#define FTS_GET_VENDOR_ID_NUM 0
/*
* vendor_id(s) for vendor(s) to be compatible with.
* a confirmation of vendor_id(s) is recommended.
* FTS_GET_VENDOR_ID_NUM == 0, no check vendor id, you may ignore them
* FTS_GET_VENDOR_ID_NUM >= 1, compatible with FTS_VENDOR_1_ID
* FTS_GET_VENDOR_ID_NUM >= 2, compatible with FTS_VENDOR_2_ID
* FTS_GET_VENDOR_ID_NUM == 3, compatible with FTS_VENDOR_3_ID
*/
#define FTS_VENDOR_1_ID 0x00
#define FTS_VENDOR_2_ID 0x00
#define FTS_VENDOR_3_ID 0x00
/*
* FW_APP.i file for auto upgrade, you must replace it with your own
* define your own fw_app, the sample one to be replaced is invalid
* NOTE: if FTS_GET_VENDOR_ID_NUM >= 1, it's the fw corresponding with FTS_VENDOR_1_ID
*/
#define FTS_UPGRADE_FW_APP "include/firmware/FT8716_app_sample.i"
/*
* if FTS_GET_VENDOR_ID_NUM >= 2, fw corrsponding with FTS_VENDOR_2_ID
* define your own fw_app, the sample one is invalid
*/
#define FTS_UPGRADE_FW2_APP "include/firmware/FT8716_app_sample.i"
/*
* if FTS_GET_VENDOR_ID_NUM == 3, fw corrsponding with FTS_VENDOR_3_ID
* define your own fw_app, the sample one is invalid
*/
#define FTS_UPGRADE_FW3_APP "include/firmware/FT8716_app_sample.i"
/*
* upgrade stress test for debug
* enable it for upgrade debug if needed
* default: disable
*/
#define FTS_UPGRADE_STRESS_TEST 0
/* stress test times, default: 1000 */
#define FTS_UPGRADE_TEST_NUMBER 1000
/*********************************************************/
#endif /* _LINUX_FOCLATECH_CONFIG_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,194 @@
/*
*
* 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 "focaltech_common.h"
#include "focaltech_flash.h"
#if FTS_PSENSOR_EN
#include <linux/sensors.h>
#endif
/*****************************************************************************
* Private constant and macro definitions using #define
*****************************************************************************/
#define LEN_FLASH_ECC_MAX 0xFFFE
#define FTS_WORKQUEUE_NAME "fts_wq"
#define FTS_MAX_POINTS 10
#define FTS_KEY_WIDTH 50
#define FTS_ONE_TCH_LEN 6
#define POINT_READ_BUF (3 + FTS_ONE_TCH_LEN * FTS_MAX_POINTS)
#define FTS_MAX_ID 0x0F
#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 FTS_SYSFS_ECHO_ON(buf) ((strncmp(buf, "1", 1) == 0) || \
(strncmp(buf, "on", 2) == 0))
#define FTS_SYSFS_ECHO_OFF(buf) ((strncmp(buf, "0", 1) == 0) || \
(strncmp(buf, "off", 3) == 0))
/*****************************************************************************
* 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[4];
u32 key_y_coord;
u32 key_x_coords[4];
u32 x_max;
u32 y_max;
u32 x_min;
u32 y_min;
u32 max_touch_number;
};
struct ts_event
{
u16 au16_x[FTS_MAX_POINTS]; /*x coordinate */
u16 au16_y[FTS_MAX_POINTS]; /*y coordinate */
u16 pressure[FTS_MAX_POINTS];
u8 au8_touch_event[FTS_MAX_POINTS]; /* touch event: 0 -- down; 1-- up; 2 -- contact */
u8 au8_finger_id[FTS_MAX_POINTS]; /*touch ID */
u8 area[FTS_MAX_POINTS];
u8 touch_point;
u8 point_num;
};
struct fts_ts_data
{
struct i2c_client *client;
struct input_dev *input_dev;
struct ts_event event;
const struct fts_ts_platform_data *pdata;
#if FTS_PSENSOR_EN
struct fts_psensor_platform_data *psensor_pdata;
#endif
struct work_struct touch_event_work;
struct workqueue_struct *ts_workqueue;
struct regulator *vdd;
struct regulator *vcc_i2c;
spinlock_t irq_lock;
struct mutex report_mutex;
u16 addr;
bool suspended;
u8 fw_ver[3];
u8 fw_vendor_id;
int touchs;
int irq_disable;
#if defined(CONFIG_FB)
struct notifier_block fb_notif;
#elif defined(CONFIG_HAS_EARLYSUSPEND)
struct early_suspend early_suspend;
#endif
};
#if FTS_PSENSOR_EN
struct fts_psensor_platform_data
{
struct input_dev *input_psensor_dev;
struct sensors_classdev ps_cdev;
int tp_psensor_opened;
char tp_psensor_data; /* 0 near, 1 far */
struct fts_ts_data *data;
};
int fts_sensor_init(struct fts_ts_data *data);
int fts_sensor_read_data(struct fts_ts_data *data);
int fts_sensor_suspend(struct fts_ts_data *data);
int fts_sensor_resume(struct fts_ts_data *data);
int fts_sensor_remove(struct fts_ts_data *data);
#endif
/*****************************************************************************
* Static variables
*****************************************************************************/
extern struct i2c_client *fts_i2c_client;
extern struct fts_ts_data *fts_wq_data;
extern struct input_dev *fts_input_dev;
#endif /* __LINUX_FOCALTECH_CORE_H__ */

View File

@@ -0,0 +1,491 @@
/*
*
* 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: luoguojin
*
* 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 active : 1; /* 1- esd check active, 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 delayed_work fts_esdcheck_work;
static struct workqueue_struct *fts_esdcheck_workqueue = NULL;
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(void)
{
u8 val;
int ret;
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(fts_i2c_client);
}
ret = fts_i2c_read_reg(fts_i2c_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( void )
{
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(fts_i2c_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( void )
{
int err = 0;
int i = 0;
u8 reg_value = 0;
u8 reg_addr = 0;
for (i = 0; i < 3; i++)
{
reg_addr = FTS_REG_CHIP_ID;
err = fts_i2c_read(fts_i2c_client, &reg_addr, 1, &reg_value, 1);
if ( err < 0 )
{
FTS_ERROR("[ESD]: Read Reg 0xA3 failed ret = %d!!", err);
fts_esdcheck_data.i2c_nack_cnt++;
}
else
{
if ( (reg_value == chip_types.chip_idh) || (reg_value == 0xEF) ) /* Upgrade sometimes can't detect */
{
break;
}
else
{
fts_esdcheck_data.i2c_dataerror_cnt++;
}
}
}
/* 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( void )
{
int err = 0;
u8 reg_value = 0;
u8 reg_addr = 0;
reg_addr = FTS_REG_FLOW_WORK_CNT;
err = fts_i2c_read(fts_i2c_client, &reg_addr, 1, &reg_value, 1);
if (err < 0)
{
FTS_ERROR("[ESD]: Read Reg 0x91 failed ret = %d!!", err);
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(void)
{
int err = 0;
u8 reg_value = 0;
u8 reg_addr = 0;
bool hardware_reset = 0;
/* 1. esdcheck is interrupt, then return */
if (fts_esdcheck_data.intr == 1)
{
FTS_INFO("[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_INFO("[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
*/
fts_esdcheck_data.active = 0;
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;
err = fts_i2c_read(fts_i2c_client, &reg_addr, 1, &reg_value, 1);
if ( err < 0 )
{
fts_esdcheck_data.i2c_nack_cnt++;
}
else if ( (reg_value & 0x70) == FTS_REG_WORKMODE_FACTORY_VALUE)
{
FTS_INFO("[ESD]: In factory mode, not check esd, return immediately!!");
return 0;
}
/* 5. IDC esd check lcd default:close */
#if LCD_ESD_PATCH
idc_esdcheck_lcderror();
#endif
/* 6. Get Chip ID */
hardware_reset = get_chip_id();
/* 7. get Flow work cnt: 0x91 If no change for 5 times, then ESD and reset */
if (!hardware_reset)
{
hardware_reset = get_flow_cnt();
}
/* 8. If need hardware reset, then handle it here */
if ( hardware_reset == 1)
{
fts_esdcheck_tp_reset();
}
FTS_INFO("[ESD]: NoACK=%d, Error Data=%d, Hardware Reset=%d\n", 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)
{
FTS_FUNC_ENTER();
esdcheck_algorithm();
if ( fts_esdcheck_data.suspend == 0 )
{
queue_delayed_work(fts_esdcheck_workqueue, &fts_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.active;
}
/*****************************************************************************
* 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)
{
FTS_FUNC_ENTER();
if (enable == 1)
{
if (fts_esdcheck_data.active == 0)
{
FTS_INFO("[ESD]: ESD check start!!");
fts_esdcheck_data.active = 1;
queue_delayed_work(fts_esdcheck_workqueue, &fts_esdcheck_work, msecs_to_jiffies(ESDCHECK_WAIT_TIME));
}
}
else
{
if (fts_esdcheck_data.active == 1)
{
FTS_INFO("[ESD]: ESD check stop!!");
fts_esdcheck_data.active = 0;
cancel_delayed_work_sync(&fts_esdcheck_work);
}
}
FTS_FUNC_EXIT();
return 0;
}
/*****************************************************************************
* 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_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(void)
{
FTS_FUNC_ENTER();
INIT_DELAYED_WORK(&fts_esdcheck_work, esdcheck_func);
fts_esdcheck_workqueue = create_workqueue("fts_esdcheck_wq");
if (fts_esdcheck_workqueue == NULL)
{
FTS_INFO("[ESD]: Failed to create esd work queue!!");
}
memset((u8 *)&fts_esdcheck_data, 0, sizeof(struct fts_esdcheck_st));
fts_esdcheck_switch(ENABLE);
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(void)
{
FTS_FUNC_ENTER();
destroy_workqueue(fts_esdcheck_workqueue);
FTS_FUNC_EXIT();
return 0;
}
#endif /* FTS_ESDCHECK_EN */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,376 @@
/*
*
* 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_glove_init(struct i2c_client *client);
int fts_glove_exit(struct i2c_client *client);
int fts_enter_cover_mode(struct i2c_client *client, int mode );
int fts_cover_init(struct i2c_client *client);
int fts_cover_exit(struct i2c_client *client);
int fts_enter_charger_mode(struct i2c_client *client, int mode );
int fts_charger_init(struct i2c_client *client);
int fts_charger_exit(struct i2c_client *client);
/*****************************************************************************
* 6.Static function prototypes
*******************************************************************************/
#if FTS_GLOVE_EN
static ssize_t fts_touch_glove_show(struct device *dev, struct device_attribute *attr, char *buf)
{
return snprintf(buf, PAGE_SIZE, "Glove: %s\n", g_fts_mode_flag.fts_glove_mode_flag ? "On" : "Off");
}
static ssize_t fts_touch_glove_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
int ret;
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(fts_i2c_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(fts_i2c_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)
{
return snprintf(buf, PAGE_SIZE, "Cover: %s\n", g_fts_mode_flag.fts_cover_mode_flag ? "On" : "Off");
}
static ssize_t fts_touch_cover_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
int ret;
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(fts_i2c_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(fts_i2c_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)
{
return snprintf(buf, PAGE_SIZE, "Charger: %s\n", g_fts_mode_flag.fts_charger_mode_flag ? "On" : "Off");
}
static ssize_t fts_touch_charger_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
int ret;
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(fts_i2c_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(fts_i2c_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;
}

View File

@@ -0,0 +1,860 @@
/*
*
* FocalTech fts 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_flash.c
*
* Author: fupeipei
*
* Created: 2016-08-08
*
* Abstract:
*
* Reference:
*
*****************************************************************************/
/*****************************************************************************
* 1.Included header files
*****************************************************************************/
#include "focaltech_core.h"
#include "focaltech_flash.h"
/*****************************************************************************
* Static variables
*****************************************************************************/
struct ft_chip_t chip_types;
/*****************************************************************************
* Global variable or extern global variabls/functions
*****************************************************************************/
/* Upgrade FW/PRAMBOOT/LCD CFG */
u8 CTPM_FW[] =
{
//#include FTS_UPGRADE_FW_APP
"include/firmware/FT8716_app_sample.i"
};
#if (FTS_GET_VENDOR_ID_NUM >= 2)
u8 CTPM_FW2[] =
{
#include FTS_UPGRADE_FW2_APP
};
#endif
#if (FTS_GET_VENDOR_ID_NUM >= 3)
u8 CTPM_FW3[] =
{
#include FTS_UPGRADE_FW3_APP
};
#endif
u8 aucFW_PRAM_BOOT[] =
{
#ifdef FTS_UPGRADE_PRAMBOOT
#include FTS_UPGRADE_PRAMBOOT
#endif
};
struct fts_upgrade_fun fts_updatefun_curr;
struct workqueue_struct *touch_wq;
struct work_struct fw_update_work;
u8 *g_fw_file;
int g_fw_len;
/*****************************************************************************
* Static function prototypes
*****************************************************************************/
/************************************************************************
* Name: fts_ctpm_upgrade_delay
* Brief: 0
* Input: 0
* Output: 0
* Return: 0
***********************************************************************/
void fts_ctpm_upgrade_delay(u32 i)
{
do
{
i--;
}
while (i>0);
}
/************************************************************************
* Name: fts_ctpm_i2c_hid2std
* Brief: HID to I2C
* Input: i2c info
* Output: no
* Return: fail =0
***********************************************************************/
int fts_ctpm_i2c_hid2std(struct i2c_client *client)
{
#if (FTS_CHIP_IDC)
return 0;
#else
u8 buf[5] = {0};
int bRet = 0;
buf[0] = 0xeb;
buf[1] = 0xaa;
buf[2] = 0x09;
bRet =fts_i2c_write(client, buf, 3);
msleep(10);
buf[0] = buf[1] = buf[2] = 0;
fts_i2c_read(client, buf, 0, buf, 3);
if ((0xeb == buf[0]) && (0xaa == buf[1]) && (0x08 == buf[2]))
{
FTS_DEBUG("hidi2c change to stdi2c successful!!");
bRet = 1;
}
else
{
FTS_ERROR("hidi2c change to stdi2c error!!");
bRet = 0;
}
return bRet;
#endif
}
/************************************************************************
* Name: fts_get_chip_types
* Brief: get correct chip information
* Input:
* Output:
* Return:
***********************************************************************/
void fts_get_chip_types(void)
{
struct ft_chip_t ctype[] = FTS_CHIP_TYPE_MAPPING;
int ic_type = 0;
if (sizeof(ctype) != sizeof(struct ft_chip_t)) /* only one array */
ic_type = IC_SERIALS - 1;
chip_types = ctype[ic_type];
FTS_INFO("CHIP TYPE ID = 0x%02x%02x", chip_types.chip_idh, chip_types.chip_idl);
}
/************************************************************************
* Name: fts_ctpm_get_upgrade_array
* Brief: decide which ic
* Input: no
* Output: get ic info in fts_updateinfo_curr
* Return: no
***********************************************************************/
void fts_ctpm_get_upgrade_array(void)
{
FTS_FUNC_ENTER();
fts_get_chip_types();
fts_ctpm_i2c_hid2std(fts_i2c_client);
/* Get functin pointer */
memcpy(&fts_updatefun_curr, &fts_updatefun, sizeof(struct fts_upgrade_fun));
FTS_FUNC_EXIT();
}
/************************************************************************
* Name: fts_ctpm_rom_or_pram_reset
* Brief: RST CMD(07), reset to romboot(maybe->bootloader)
* Input:
* Output:
* Return:
***********************************************************************/
void fts_ctpm_rom_or_pram_reset(struct i2c_client *client)
{
u8 rst_cmd = FTS_REG_RESET_FW;
FTS_INFO("[UPGRADE]******Reset to romboot/bootloader******");
fts_i2c_write(client, &rst_cmd, 1);
/* The delay can't be changed */
msleep(300);
}
/************************************************************************
* Name: fts_ctpm_auto_clb
* Brief: auto calibration
* Input: i2c info
* Output: no
* Return: 0
***********************************************************************/
int fts_ctpm_auto_clb(struct i2c_client *client)
{
#if FTS_AUTO_CLB_EN
u8 uc_temp = 0x00;
u8 i = 0;
/*start auto CLB */
msleep(200);
fts_i2c_write_reg(client, 0, FTS_REG_WORKMODE_FACTORY_VALUE);
/*make sure already enter factory mode */
msleep(100);
/*write command to start calibration */
fts_i2c_write_reg(client, 2, 0x4);
msleep(300);
if ((chip_types.chip_idh==0x11) ||(chip_types.chip_idh==0x12) ||(chip_types.chip_idh==0x13) ||(chip_types.chip_idh==0x14)) //5x36,5x36i
{
for (i=0; i<100; i++)
{
fts_i2c_read_reg(client, 0x02, &uc_temp);
if (0x02 == uc_temp ||
0xFF == uc_temp)
{
break;
}
msleep(20);
}
}
else
{
for (i=0; i<100; i++)
{
fts_i2c_read_reg(client, 0, &uc_temp);
if (0x0 == ((uc_temp&0x70)>>4))
{
break;
}
msleep(20);
}
}
fts_i2c_write_reg(client, 0, 0x40);
msleep(200);
fts_i2c_write_reg(client, 2, 0x5);
msleep(300);
fts_i2c_write_reg(client, 0, FTS_REG_WORKMODE_WORK_VALUE);
msleep(300);
#endif
return 0;
}
/************************************************************************
* Name: fts_GetFirmwareSize
* Brief: get file size
* Input: file name
* Output: no
* Return: file size
***********************************************************************/
int fts_GetFirmwareSize(char *firmware_name)
{
struct file *pfile = NULL;
struct inode *inode;
unsigned long magic;
off_t fsize = 0;
char filepath[FILE_NAME_LENGTH];
memset(filepath, 0, sizeof(filepath));
sprintf(filepath, "%s%s", FTXXXX_INI_FILEPATH_CONFIG, firmware_name);
if (NULL == pfile)
{
pfile = filp_open(filepath, O_RDONLY, 0);
}
if (IS_ERR(pfile))
{
FTS_ERROR("error occured while opening file %s", filepath);
return -EIO;
}
inode = pfile->f_path.dentry->d_inode;
magic = inode->i_sb->s_magic;
fsize = inode->i_size;
filp_close(pfile, NULL);
return fsize;
}
/************************************************************************
* Name: fts_ReadFirmware
* Brief: read firmware buf for .bin file.
* Input: file name, data buf
* Output: data buf
* Return: 0
***********************************************************************/
int fts_ReadFirmware(char *firmware_name,u8 *firmware_buf)
{
struct file *pfile = NULL;
struct inode *inode;
unsigned long magic;
off_t fsize;
char filepath[FILE_NAME_LENGTH];
loff_t pos;
mm_segment_t old_fs;
memset(filepath, 0, sizeof(filepath));
sprintf(filepath, "%s%s", FTXXXX_INI_FILEPATH_CONFIG, firmware_name);
if (NULL == pfile)
{
pfile = filp_open(filepath, O_RDONLY, 0);
}
if (IS_ERR(pfile))
{
FTS_ERROR("[UPGRADE] Error occured while opening file %s.\n", filepath);
return -EIO;
}
inode = pfile->f_path.dentry->d_inode;
magic = inode->i_sb->s_magic;
fsize = inode->i_size;
old_fs = get_fs();
set_fs(KERNEL_DS);
pos = 0;
vfs_read(pfile, firmware_buf, fsize, &pos);
filp_close(pfile, NULL);
set_fs(old_fs);
return 0;
}
/************************************************************************
* Name: fts_getsize
* Brief: Get different file's size
* Input:
* Output:
* Return: file's size
***********************************************************************/
u32 fts_getsize(u8 fw_type)
{
int fw_len = 0;
if (fw_type == FW_SIZE)
fw_len = sizeof(CTPM_FW);
#if (FTS_GET_VENDOR_ID_NUM >= 2)
else if (fw_type == FW2_SIZE)
fw_len = sizeof(CTPM_FW2);
#endif
#if (FTS_GET_VENDOR_ID_NUM >= 3)
else if (fw_type == FW3_SIZE)
fw_len = sizeof(CTPM_FW3);
#endif
#if FTS_CHIP_IDC
else if (fw_type == PRAMBOOT_SIZE)
fw_len = sizeof(aucFW_PRAM_BOOT);
#endif
return fw_len;
}
/************************************************************************
* Name: fts_ctpm_get_pram_or_rom_id
* Brief: 0
* Input: 0
* Output: 0
* Return: 0
***********************************************************************/
enum FW_STATUS fts_ctpm_get_pram_or_rom_id(struct i2c_client *client)
{
u8 buf[4];
u8 reg_val[2] = {0};
enum FW_STATUS inRomBoot = FTS_RUN_IN_ERROR;
fts_ctpm_i2c_hid2std(client);
/*Enter upgrade mode*/
/*send 0x55 in time windows*/
buf[0] = FTS_UPGRADE_55;
buf[1] = FTS_UPGRADE_AA;
fts_i2c_write(client, buf, 2);
msleep(20);
buf[0] = 0x90;
buf[1] = buf[2] = buf[3] =0x00;
fts_i2c_read(client, buf, 4, reg_val, 2);
FTS_DEBUG("[UPGRADE] Read ROM/PRAM/Bootloader id:0x%02x%02x", reg_val[0], reg_val[1]);
if ((reg_val[0] == 0x00) || (reg_val[0] == 0xFF))
{
inRomBoot = FTS_RUN_IN_ERROR;
}
else if (reg_val[0] == chip_types.pramboot_idh && reg_val[1] == chip_types.pramboot_idl)
{
inRomBoot = FTS_RUN_IN_PRAM;
}
else if (reg_val[0] == chip_types.rom_idh && reg_val[1] == chip_types.rom_idl)
{
inRomBoot = FTS_RUN_IN_ROM;
}
else if (reg_val[0] == chip_types.bootloader_idh && reg_val[1] == chip_types.bootloader_idl)
{
inRomBoot = FTS_RUN_IN_BOOTLOADER;
}
return inRomBoot;
}
/************************************************************************
* Name: fts_ctpm_get_app_file
* Brief: get app file by Vendor ID
* Input:
* Output:
* Return: <0: vendor id not correct,not upgrade
***********************************************************************/
int fts_ctpm_get_i_file(struct i2c_client *client, int fw_valid)
{
int ret;
if (fts_updatefun_curr.get_i_file)
ret = fts_updatefun_curr.get_i_file(client, fw_valid);
else
ret = -EIO;
return ret;
}
/************************************************************************
* Name: fts_ctpm_get_app_ver
* Brief: get app file version
* Input:
* Output:
* Return: fw version
***********************************************************************/
int fts_ctpm_get_app_ver(void)
{
int i_ret = 0;
if (fts_updatefun_curr.get_app_i_file_ver)
i_ret = fts_updatefun_curr.get_app_i_file_ver();
return i_ret;
}
/************************************************************************
* Name: fts_ctpm_fw_upgrade
* Brief: fw upgrade entry funciotn
* Input:
* Output:
* Return: 0 - upgrade successfully
* <0 - upgrade failed
***********************************************************************/
int fts_ctpm_fw_upgrade(struct i2c_client *client)
{
int i_ret = 0;
if (fts_updatefun_curr.upgrade_with_app_i_file)
i_ret = fts_updatefun_curr.upgrade_with_app_i_file(client);
return i_ret;
}
/************************************************************************
* Name: fts_ctpm_fw_upgrade
* Brief: fw upgrade entry funciotn
* Input:
* Output:
* Return: 0 - upgrade successfully
* <0 - upgrade failed
***********************************************************************/
int fts_ctpm_lcd_cfg_upgrade(struct i2c_client *client)
{
int i_ret = 0;
if (fts_updatefun_curr.upgrade_with_lcd_cfg_i_file)
i_ret = fts_updatefun_curr.upgrade_with_lcd_cfg_i_file(client);
return i_ret;
}
bool fts_check_fw_valid(struct i2c_client *client)
{
int i = 0;
u8 chip_id = 0;
for (i = 0; i < 3; i++)
{
fts_i2c_read_reg(client, FTS_REG_CHIP_ID, &chip_id);
if(chip_id == chip_types.chip_idh)
return true;
}
return false;
}
#if (!(FTS_UPGRADE_STRESS_TEST))
/************************************************************************
* Name: fts_ctpm_check_fw_status
* Brief: Check App is valid or not
* Input:
* Output:
* Return: -EIO - I2C communication error
* FTS_RUN_IN_APP - APP valid
* 0 - APP invalid
***********************************************************************/
static int fts_ctpm_check_fw_status(struct i2c_client *client)
{
u8 chip_id1 = 0;
u8 chip_id2 = 0;
int fw_status = FTS_RUN_IN_ERROR;
int i = 0;
int ret = 0;
int i2c_noack_retry = 0;
for (i = 0; i < 5; i++)
{
ret = fts_i2c_read_reg(client, FTS_REG_CHIP_ID, &chip_id1);
if (ret < 0)
{
i2c_noack_retry++;
continue;
}
ret = fts_i2c_read_reg(client, FTS_REG_CHIP_ID2, &chip_id2);
if (ret < 0)
{
i2c_noack_retry++;
continue;
}
if ((chip_id1 == chip_types.chip_idh)
#if FTS_CHIP_IDC
&& (chip_id2 == chip_types.chip_idl)
#endif
)
{
fw_status = FTS_RUN_IN_APP;
break;
}
}
FTS_DEBUG("[UPGRADE]: chip_id = %02x%02x, chip_types.chip_idh = %02x%02x",
chip_id1, chip_id2, chip_types.chip_idh, chip_types.chip_idl);
/* I2C No ACK 5 times, then return -EIO */
if (i2c_noack_retry >= 5)
return -EIO;
/* I2C communication ok, but not get correct ID, need check pram/rom/bootloader */
if (i >= 5)
{
fw_status = fts_ctpm_get_pram_or_rom_id(client);
}
return fw_status;
}
/************************************************************************
* Name: fts_ctpm_check_fw_ver
* Brief: Check vendor id is valid or not
* Input:
* Output:
* Return: 1 - vendor id valid
* 0 - vendor id invalid
***********************************************************************/
static int fts_ctpm_check_fw_ver(struct i2c_client *client)
{
u8 uc_tp_fm_ver;
u8 uc_host_fm_ver = 0;
fts_i2c_read_reg(client, FTS_REG_FW_VER, &uc_tp_fm_ver);
uc_host_fm_ver = fts_ctpm_get_app_ver();
FTS_DEBUG("[UPGRADE]: uc_tp_fm_ver = 0x%x, uc_host_fm_ver = 0x%x!!", uc_tp_fm_ver, uc_host_fm_ver);
if (uc_tp_fm_ver < uc_host_fm_ver )
{
return 1;
}
else
{
return 0;
}
}
/************************************************************************
* Name: fts_ctpm_check_need_upgrade
* Brief:
* Input:
* Output:
* Return: 1 - Need upgrade
* 0 - No upgrade
***********************************************************************/
static int fts_ctpm_check_need_upgrade(struct i2c_client *client)
{
int fw_status = 0;
int bUpgradeFlag = false;
FTS_FUNC_ENTER();
/* 1. veriry FW APP is valid or not */
fw_status = fts_ctpm_check_fw_status(client);
FTS_DEBUG( "[UPGRADE]: fw_status = %d!!", fw_status);
if (fw_status < 0)
{
/* I2C no ACK, return immediately */
FTS_ERROR("[UPGRADE]******I2C NO ACK,exit upgrade******");
return -EIO;
}
else if (fw_status == FTS_RUN_IN_ERROR)
{
FTS_ERROR("[UPGRADE]******IC Type Fail******");
}
else if (fw_status == FTS_RUN_IN_APP)
{
FTS_INFO("[UPGRADE]**********FW APP valid**********");
if (fts_ctpm_get_i_file(client, 1) != 0)
{
FTS_DEBUG("[UPGRADE]******Get upgrade file(fw) fail******");
return -EIO;
}
if (fts_ctpm_check_fw_ver(client) == 1)
{
FTS_DEBUG("[UPGRADE]**********need upgrade fw**********");
bUpgradeFlag = true;
}
else
{
FTS_DEBUG("[UPGRADE]**********Don't need upgrade fw**********");
bUpgradeFlag = false;
}
}
else
{
/* if app is invalid, reset to run ROM */
FTS_INFO("[UPGRADE]**********FW APP invalid**********");
fts_ctpm_rom_or_pram_reset(client);
if (fts_ctpm_get_i_file(client, 0) != 0)
{
FTS_DEBUG("[UPGRADE]******Get upgrade file(flash) fail******");
fts_ctpm_rom_or_pram_reset(client);
return -EIO;
}
fts_ctpm_rom_or_pram_reset(client);
bUpgradeFlag = true;
}
FTS_FUNC_EXIT();
return bUpgradeFlag;
}
/************************************************************************
* Name: fts_ctpm_auto_upgrade
* Brief: auto upgrade
* Input:
* Output:
* Return: 0 - no upgrade
***********************************************************************/
int fts_ctpm_auto_upgrade(struct i2c_client *client)
{
u8 uc_tp_fm_ver;
int i_ret = 0;
int bUpgradeFlag = false;
u8 uc_upgrade_times = 0;
FTS_DEBUG("[UPGRADE]********************check upgrade need or not********************");
bUpgradeFlag = fts_ctpm_check_need_upgrade(client);
FTS_DEBUG("[UPGRADE]**********bUpgradeFlag = 0x%x**********", bUpgradeFlag);
if (bUpgradeFlag <= 0)
{
FTS_DEBUG("[UPGRADE]**********No Upgrade, exit**********");
return 0;
}
else
{
/* FW Upgrade */
do
{
uc_upgrade_times++;
FTS_DEBUG("[UPGRADE]********************star upgrade(%d)********************", uc_upgrade_times);
i_ret = fts_ctpm_fw_upgrade(client);
if (i_ret == 0)
{
/* upgrade success */
fts_i2c_read_reg(client, FTS_REG_FW_VER, &uc_tp_fm_ver);
FTS_DEBUG("[UPGRADE]********************Success upgrade to new fw version 0x%x********************", uc_tp_fm_ver);
fts_ctpm_auto_clb(client);
break;
}
else
{
/* upgrade fail, reset to run ROM BOOT..
* if app in flash is ok, TP will work success
*/
FTS_ERROR("[UPGRADE]********************upgrade fail, reset now********************");
fts_ctpm_rom_or_pram_reset(client);
}
}
while (uc_upgrade_times < 2); /* if upgrade fail, upgrade again. then return */
}
return i_ret;
}
#endif
#if FTS_AUTO_UPGRADE_FOR_LCD_CFG_EN
int fts_get_host_lic_ver(u8* ver)
{
int i_ret = 0;
if (fts_updatefun_curr.get_hlic_ver)
i_ret = fts_updatefun_curr.get_hlic_ver();
if (i_ret > 0)
*ver = i_ret;
return i_ret;
}
/* check if lcd init code need upgrade
* true-need false-no need
*/
static bool fts_lic_need_upgrade(struct i2c_client *client)
{
int ret = 0;
u8 initcode_ver_in_tp = 0;
u8 initcode_ver_in_host = 0;
bool fwvalid = false;
fwvalid = fts_check_fw_valid(client);
if( !fwvalid) {
FTS_INFO("fw is invalid, no upgrade lcd init code");
return false;
}
ret = fts_get_host_lic_ver(&initcode_ver_in_host);
if(ret < 0)
{
FTS_ERROR("init code in host invalid");
return false;
}
ret = fts_i2c_read_reg(client, 0xE4, &initcode_ver_in_tp);
if (ret < 0) {
FTS_ERROR("read reg0xE4 fail");
return false;
}
FTS_DEBUG("tp init ver:%x, fw init ver:%x", initcode_ver_in_tp, initcode_ver_in_host);
if(0xA5 == initcode_ver_in_tp) {
FTS_INFO("lcd init code ver is 0xA5, don't upgade init code");
return false;
}
else if(0xFF == initcode_ver_in_tp) {
FTS_DEBUG("lcd init code in tp is invalid, need upgrade init code");
return true;
}
else if(initcode_ver_in_tp < initcode_ver_in_host)
return true;
else
return false;
}
int fts_lic_upgrade(struct i2c_client *client)
{
int ret = 0;
bool hlic_upgrade = false;
int upgrade_count = 0;
hlic_upgrade = fts_lic_need_upgrade(client);
FTS_INFO("lcd init code upgrade flag:%d", hlic_upgrade);
if(hlic_upgrade) {
FTS_INFO("lcd init code upgrade...");
do {
upgrade_count++;
ret = fts_ctpm_lcd_cfg_upgrade(client);
if(0 == ret) {
FTS_INFO("lcd init code upgrade succussfully");
break;
}
else {
fts_ctpm_rom_or_pram_reset(client);
}
}while (upgrade_count < 2);
}
return ret;
}
#endif /* FTS_AUTO_UPGRADE_FOR_LCD_CFG_EN */
#if FTS_AUTO_UPGRADE_EN
static void fts_ctpm_update_work_func(struct work_struct *work)
{
int i_ret = 0;
FTS_DEBUG( "[UPGRADE]******************************FTS enter upgrade******************************");
fts_irq_disable();
/* esd check */
#if FTS_ESDCHECK_EN
fts_esdcheck_switch(DISABLE);
#endif
i_ret = fts_ctpm_auto_upgrade(fts_i2c_client);
if (i_ret < 0)
FTS_ERROR("[UPGRADE]**********TP FW upgrade failed**********");
#if FTS_AUTO_UPGRADE_FOR_LCD_CFG_EN
i_ret = fts_lic_upgrade(fts_i2c_client);
if (i_ret < 0)
FTS_ERROR("**********lcd init code upgrade failed**********");
#endif
#if FTS_ESDCHECK_EN
fts_esdcheck_switch(ENABLE);
#endif
fts_irq_enable();
FTS_DEBUG( "[UPGRADE]******************************FTS exit upgrade******************************");
}
/*****************************************************************************
* Name: fts_ctpm_upgrade_init
* Brief:
* Input:
* Output:
* Return:
*****************************************************************************/
void fts_ctpm_upgrade_init(void)
{
FTS_FUNC_ENTER();
touch_wq = create_singlethread_workqueue("touch_wq");
if (touch_wq)
{
INIT_WORK(&fw_update_work, fts_ctpm_update_work_func);
queue_work(touch_wq, &fw_update_work);
}
else
{
FTS_ERROR("[UPGRADE]create_singlethread_workqueue failed\n");
}
FTS_FUNC_EXIT();
}
/*****************************************************************************
* Name: fts_ctpm_upgrade_exit
* Brief:
* Input:
* Output:
* Return:
*****************************************************************************/
void fts_ctpm_upgrade_exit(void)
{
FTS_FUNC_ENTER();
destroy_workqueue(touch_wq);
FTS_FUNC_EXIT();
}
#endif /* #if FTS_AUTO_UPGRADE_EN */

View File

@@ -0,0 +1,120 @@
/************************************************************************
* Copyright (C) 2010-2017, 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_flash/focaltech_upgrade_common.h"
/*****************************************************************************
* Private constant and macro definitions using #define
*****************************************************************************/
#define FTS_REG_ECC 0xCC
#define FTS_RST_CMD_REG2 0xBC
#define FTS_READ_ID_REG 0x90
#define FTS_ERASE_APP_REG 0x61
#define FTS_ERASE_PARAMS_CMD 0x63
#define FTS_FW_WRITE_CMD 0xBF
#define FTS_REG_RESET_FW 0x07
#define FTS_RST_CMD_REG1 0xFC
#define LEN_FLASH_ECC_MAX 0xFFFE
#define FTS_PACKET_LENGTH 128
#define FTS_SETTING_BUF_LEN 128
#define FTS_UPGRADE_LOOP 30
#define AUTO_CLB_NEED 1
#define AUTO_CLB_NONEED 0
#define FTS_UPGRADE_AA 0xAA
#define FTS_UPGRADE_55 0x55
#define FTXXXX_INI_FILEPATH_CONFIG "/sdcard/"
enum FW_STATUS
{
FTS_RUN_IN_ERROR,
FTS_RUN_IN_APP,
FTS_RUN_IN_ROM,
FTS_RUN_IN_PRAM,
FTS_RUN_IN_BOOTLOADER
};
enum FILE_SIZE_TYPE
{
FW_SIZE,
FW2_SIZE,
FW3_SIZE,
PRAMBOOT_SIZE,
};
/*****************************************************************************
* Private enumerations, structures and unions using typedef
*****************************************************************************/
/* IC info */
struct fts_upgrade_fun
{
int (*get_i_file)(struct i2c_client *, int);
int (*get_app_bin_file_ver)(char *);
int (*get_app_i_file_ver)(void);
int (*upgrade_with_app_i_file)(struct i2c_client *);
int (*upgrade_with_app_bin_file)(struct i2c_client *, char *);
int (*get_hlic_ver)(void);
int (*upgrade_with_lcd_cfg_i_file)(struct i2c_client *);
int (*upgrade_with_lcd_cfg_bin_file)(struct i2c_client *, char *);
};
extern struct fts_upgrade_fun fts_updatefun;
/*****************************************************************************
* Static variables
*****************************************************************************/
/*****************************************************************************
* Global variable or extern global variabls/functions
*****************************************************************************/
extern u8 CTPM_FW[];
extern u8 CTPM_FW2[];
extern u8 CTPM_FW3[];
extern u8 aucFW_PRAM_BOOT[];
extern u8 CTPM_LCD_CFG[];
extern u8 *g_fw_file;
extern int g_fw_len;
extern struct fts_upgrade_fun fts_updatefun_curr;
extern struct ft_chip_t chip_types;
#if FTS_AUTO_UPGRADE_EN
extern struct workqueue_struct *touch_wq;
extern struct work_struct fw_update_work;
#endif
void fts_ctpm_upgrade_init(void);
void fts_ctpm_upgrade_exit(void);
void fts_ctpm_upgrade_delay(u32 i);
void fts_ctpm_get_upgrade_array(void);
int fts_ctpm_auto_upgrade(struct i2c_client *client);
int fts_fw_upgrade(struct device *dev, bool force);
int fts_ctpm_auto_clb(struct i2c_client *client);
/*****************************************************************************
* Static function prototypes
*****************************************************************************/
u32 fts_getsize(u8 fw_type);
int fts_GetFirmwareSize(char *firmware_name);
int fts_ctpm_i2c_hid2std(struct i2c_client *client);
int fts_ReadFirmware(char *firmware_name,u8 *firmware_buf);
void fts_ctpm_rom_or_pram_reset(struct i2c_client *client);
enum FW_STATUS fts_ctpm_get_pram_or_rom_id(struct i2c_client *client);
#endif

View File

@@ -0,0 +1,10 @@
#
# Makefile for the focaltech touchscreen drivers.
#
# Each configuration option enables a list of files.
obj-$(CONFIG_AMLOGIC_TOUCHSCREEN_FTS) += focaltech_upgrade_idc.o
obj-$(CONFIG_AMLOGIC_TOUCHSCREEN_FTS) += focaltech_upgrade_ft7250.o
obj-$(CONFIG_AMLOGIC_TOUCHSCREEN_FTS) += focaltech_upgrade_test.o

View File

@@ -0,0 +1,56 @@
/************************************************************************
* Copyright (C) 2010-2017, Focaltech Systems (R)£¬All Rights Reserved.
*
* File Name: focaltech_upgrade_common.h
*
* Author: fupeipei
*
* Created: 2016-08-16
*
* Abstract:
*
************************************************************************/
#ifndef __LINUX_FOCALTECH_UPGRADE_COMMON_H__
#define __LINUX_FOCALTECH_UPGRADE_COMMON_H__
/*****************************************************************************
* 1.Included header files
*****************************************************************************/
#include "../focaltech_flash.h"
/*****************************************************************************
* Private constant and macro definitions using #define
*****************************************************************************/
/*****************************************************************************
* Private enumerations, structures and unions using typedef
*****************************************************************************/
/*****************************************************************************
* Static variables
*****************************************************************************/
/*****************************************************************************
* Global variable or extern global variabls/functions
*****************************************************************************/
/*****************************************************************************
* Static function prototypes
*****************************************************************************/
int fts_ctpm_erase_flash(struct i2c_client *client);
int fts_ctpm_pramboot_ecc(struct i2c_client *client);
bool fts_ctpm_check_run_state(struct i2c_client *client, int state);
void fts_ctpm_start_pramboot(struct i2c_client *client);
int fts_ctpm_start_fw_upgrade(struct i2c_client *client);
bool fts_ctpm_check_in_pramboot(struct i2c_client *client);
int fts_ctpm_upgrade_idc_init(struct i2c_client *client);
int fts_ctpm_write_app_for_idc(struct i2c_client *client, u32 length, u8 *readbuf);
int fts_ctpm_upgrade_ecc(struct i2c_client *client, u32 startaddr, u32 length);
int fts_ctpm_write_pramboot_for_idc(struct i2c_client *client, u32 length, u8 *readbuf);
int fts_writeflash(struct i2c_client *client, u32 writeaddr, u32 length, u8 *readbuf, u32 cnt);
int fts_ctpm_get_app_ver(void);
int fts_ctpm_fw_upgrade(struct i2c_client *client);
int fts_ctpm_lcd_cfg_upgrade(struct i2c_client *client);
#endif

View File

@@ -0,0 +1,461 @@
/*
*
* FocalTech fts 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_upgrade_idc.c
*
* Author: fupeipei
*
* Created: 2016-08-22
*
* Abstract:
*
* Reference:
*
*****************************************************************************/
/*****************************************************************************
* 1.Included header files
*****************************************************************************/
#include "../focaltech_core.h"
#if (FTS_CHIP_IDC == 1)
#include "../focaltech_flash.h"
/*****************************************************************************
* Static variables
*****************************************************************************/
/*****************************************************************************
* Global variable or extern global variabls/functions
*****************************************************************************/
u8 upgrade_ecc;
/*****************************************************************************
* Static function prototypes
*****************************************************************************/
/************************************************************************
* Name: fts_ctpm_upgrade_idc_init
* Brief:
* Input:
* Output:
* Return:
***********************************************************************/
int fts_ctpm_upgrade_idc_init(struct i2c_client *client)
{
int i_ret = 0;
u8 reg_val_id[4] = {0};
u8 auc_i2c_write_buf[10];
FTS_INFO("[UPGRADE]**********Upgrade setting Init**********");
/*read flash ID*/
auc_i2c_write_buf[0] = 0x05;
reg_val_id[0] = 0x00;
i_ret =fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val_id, 1);
if (i_ret < 0)
{
return -EIO;
}
/*set flash clk*/
auc_i2c_write_buf[0] = 0x05;
auc_i2c_write_buf[1] = reg_val_id[0];//0x80;
auc_i2c_write_buf[2] = 0x00;
fts_i2c_write(client, auc_i2c_write_buf, 3);
/*send upgrade type to reg 0x09: 0x0B: upgrade; 0x0A: download*/
auc_i2c_write_buf[0] = 0x09;
auc_i2c_write_buf[1] = 0x0B;
fts_i2c_write(client, auc_i2c_write_buf, 2);
return 0;
}
/************************************************************************
* Name: fts_ctpm_start_pramboot
* Brief:
* Input:
* Output:
* Return:
***********************************************************************/
void fts_ctpm_start_pramboot(struct i2c_client *client)
{
u8 auc_i2c_write_buf[10];
FTS_INFO("[UPGRADE]**********start pramboot**********");
auc_i2c_write_buf[0] = 0x08;
fts_i2c_write(client, auc_i2c_write_buf, 1);
msleep(20);
}
/************************************************************************
* Name: fts_ctpm_start_fw_upgrade
* Brief:
* Input:
* Output:
* Return:
***********************************************************************/
int fts_ctpm_start_fw_upgrade(struct i2c_client *client)
{
int i_ret = 0;
/*send the soft upgrade commond to FW, and start upgrade*/
FTS_INFO("[UPGRADE]**********send 0xAA and 0x55 to FW, start upgrade**********");
i_ret = fts_i2c_write_reg(client, FTS_RST_CMD_REG1, FTS_UPGRADE_AA);
msleep(10);
i_ret = fts_i2c_write_reg(client, FTS_RST_CMD_REG1, FTS_UPGRADE_55);
msleep(200);
return i_ret;
}
/************************************************************************
* Name: fts_ctpm_check_run_state
* Brief:
* Input:
* Output:
* Return:
***********************************************************************/
bool fts_ctpm_check_run_state(struct i2c_client *client, int rstate)
{
int i = 0;
enum FW_STATUS cstate = FTS_RUN_IN_ERROR;
for (i = 0; i < FTS_UPGRADE_LOOP; i++)
{
cstate = fts_ctpm_get_pram_or_rom_id(client);
FTS_DEBUG( "[UPGRADE]: run state = %d", cstate);
if (cstate == rstate)
return true;
msleep(20);
}
return false;
}
/************************************************************************
* Name: fts_ctpm_pramboot_ecc
* Brief:
* Input:
* Output:
* Return:
***********************************************************************/
int fts_ctpm_pramboot_ecc(struct i2c_client *client)
{
u8 auc_i2c_write_buf[10];
u8 reg_val[4] = {0};
FTS_FUNC_ENTER();
/*read out checksum, if pramboot checksum != host checksum, upgrade fail*/
FTS_INFO("[UPGRADE]******read out pramboot checksum******");
auc_i2c_write_buf[0] = 0xcc;
msleep(2);
fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 1);
if (reg_val[0] != upgrade_ecc) /*pramboot checksum != host checksum, upgrade fail*/
{
FTS_ERROR("[UPGRADE]: checksum fail : pramboot_ecc = %X, host_ecc = %X!!",reg_val[0],upgrade_ecc);
return -EIO;
}
FTS_DEBUG("[UPGRADE]: checksum success : pramboot_ecc = %X, host_ecc = %X!!",reg_val[0],upgrade_ecc);
msleep(100);
FTS_FUNC_EXIT();
return 0;
}
/************************************************************************
* Name: fts_ctpm_upgrade_ecc
* Brief:
* Input:
* Output:
* Return:
***********************************************************************/
int fts_ctpm_upgrade_ecc(struct i2c_client *client, u32 startaddr, u32 length)
{
u32 i = 0;
u8 auc_i2c_write_buf[10];
u32 temp;
u8 reg_val[4] = {0};
int i_ret = 0;
FTS_INFO( "[UPGRADE]**********read out checksum**********");
/*check sum init*/
auc_i2c_write_buf[0] = 0x64;
fts_i2c_write(client, auc_i2c_write_buf, 1);
msleep(300);
/*send commond to pramboot to start checksum*/
auc_i2c_write_buf[0] = 0x65;
auc_i2c_write_buf[1] = (u8)(startaddr >> 16);
auc_i2c_write_buf[2] = (u8)(startaddr >> 8);
auc_i2c_write_buf[3] = (u8)(startaddr);
if (length > LEN_FLASH_ECC_MAX)
{
temp = LEN_FLASH_ECC_MAX;
}
else
{
temp = length;
}
auc_i2c_write_buf[4] = (u8)(temp >> 8);
auc_i2c_write_buf[5] = (u8)(temp);
i_ret = fts_i2c_write(client, auc_i2c_write_buf, 6);
msleep(length/256);
/*read status : if check sum is finished?*/
for (i = 0; i < 100; i++)
{
auc_i2c_write_buf[0] = 0x6a;
reg_val[0] = reg_val[1] = 0x00;
fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2);
if (0xF0==reg_val[0] && 0x55==reg_val[1])
{
break;
}
msleep(1);
}
if (length > LEN_FLASH_ECC_MAX)
{
temp = LEN_FLASH_ECC_MAX;
auc_i2c_write_buf[0] = 0x65;
auc_i2c_write_buf[1] = (u8)(temp >> 16);
auc_i2c_write_buf[2] = (u8)(temp >> 8);
auc_i2c_write_buf[3] = (u8)(temp);
temp = length-LEN_FLASH_ECC_MAX;
auc_i2c_write_buf[4] = (u8)(temp >> 8);
auc_i2c_write_buf[5] = (u8)(temp);
i_ret = fts_i2c_write(client, auc_i2c_write_buf, 6);
msleep(length/256);
for (i = 0; i < 100; i++)
{
auc_i2c_write_buf[0] = 0x6a;
reg_val[0] = reg_val[1] = 0x00;
fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2);
if (0xF0==reg_val[0] && 0x55==reg_val[1])
{
break;
}
msleep(1);
}
}
/*read out check sum*/
auc_i2c_write_buf[0] = 0x66;
i_ret = fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 1);
if (reg_val[0] != upgrade_ecc) /*if check sum fail, upgrade fail*/
{
FTS_ERROR( "[UPGRADE]: ecc error! FW=%02x upgrade_ecc=%02x!!", reg_val[0], upgrade_ecc);
return -EIO;
}
FTS_DEBUG( "[UPGRADE]: ecc success : FW=%02x upgrade_ecc=%02x!!", reg_val[0], upgrade_ecc);
upgrade_ecc = 0;
return i_ret;
}
/************************************************************************
* Name: fts_ctpm_erase_flash
* Brief:
* Input:
* Output:
* Return:
***********************************************************************/
int fts_ctpm_erase_flash(struct i2c_client *client)
{
u32 i = 0;
u8 auc_i2c_write_buf[10];
u8 reg_val[4] = {0};
FTS_INFO("[UPGRADE]**********erase app now**********");
/*send to erase flash*/
auc_i2c_write_buf[0] = 0x61;
fts_i2c_write(client, auc_i2c_write_buf, 1);
msleep(1350);
for (i = 0; i < 15; i++)
{
/*get the erase app status, if get 0xF0AA£¬erase flash success*/
auc_i2c_write_buf[0] = 0x6a;
reg_val[0] = reg_val[1] = 0x00;
fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2);
if (0xF0==reg_val[0] && 0xAA==reg_val[1]) /*erase flash success*/
{
break;
}
msleep(50);
}
if ((0xF0!=reg_val[0] || 0xAA!=reg_val[1]) && (i >= 15)) /*erase flash fail*/
{
FTS_ERROR("[UPGRADE]: erase app error.reset tp and reload FW!!");
return -EIO;
}
FTS_DEBUG("[UPGRADE]: erase app ok!!");
return 0;
}
/************************************************************************
* Name: fts_ctpm_write_pramboot_for_idc
* Brief:
* Input:
* Output:
* Return:
***********************************************************************/
int fts_ctpm_write_pramboot_for_idc(struct i2c_client *client, u32 length, u8 *readbuf)
{
u32 i = 0;
u32 j;
u32 temp;
u32 packet_number;
u8 packet_buf[FTS_PACKET_LENGTH + 6];
upgrade_ecc = 0;
FTS_INFO("[UPGRADE]**********write pramboot to pram**********");
temp = 0;
packet_number = (length) / FTS_PACKET_LENGTH;
if ((length) % FTS_PACKET_LENGTH > 0)
{
packet_number++;
}
packet_buf[0] = 0xae;
packet_buf[1] = 0x00;
for (j = 0; j < packet_number; j++)
{
temp = j * FTS_PACKET_LENGTH;
packet_buf[2] = (u8) (temp >> 8);
packet_buf[3] = (u8) temp;
if (j < (packet_number-1))
{
temp = FTS_PACKET_LENGTH;
}
else
{
temp = (length) % FTS_PACKET_LENGTH;
}
packet_buf[4] = (u8) (temp >> 8);
packet_buf[5] = (u8) temp;
for (i = 0; i < temp; i++)
{
packet_buf[6 + i] = readbuf[j * FTS_PACKET_LENGTH + i];
upgrade_ecc ^= packet_buf[6 + i];
}
fts_i2c_write(client, packet_buf, temp + 6);
}
return 0;
}
/************************************************************************
* Name: fts_ctpm_write_app_for_idc
* Brief:
* Input:
* Output:
* Return:
***********************************************************************/
int fts_ctpm_write_app_for_idc(struct i2c_client *client, u32 length, u8 *readbuf)
{
u32 j;
u32 i = 0;
u32 packet_number;
u32 temp;
u32 writelenght;
u8 packet_buf[FTS_PACKET_LENGTH + 6];
u8 auc_i2c_write_buf[10];
u8 reg_val[4] = {0};
FTS_INFO( "[UPGRADE]**********write app to flash**********");
upgrade_ecc = 0;
packet_number = (length) / FTS_PACKET_LENGTH;
if (((length) % FTS_PACKET_LENGTH) > 0)
{
packet_number++;
}
packet_buf[0] = 0xbf;
for (j = 0; j < packet_number; j++)
{
temp = 0x1000+j * FTS_PACKET_LENGTH;
if (j<(packet_number-1))
{
writelenght = FTS_PACKET_LENGTH;
}
else
{
writelenght = ((length) % FTS_PACKET_LENGTH);
}
packet_buf[1] = (u8) (temp >> 16);
packet_buf[2] = (u8) (temp >> 8);
packet_buf[3] = (u8) temp;
packet_buf[4] = (u8) (writelenght >> 8);
packet_buf[5] = (u8) writelenght;
for (i = 0; i < writelenght; i++)
{
packet_buf[6 + i] = readbuf[(temp - 0x1000+i)];
upgrade_ecc ^= packet_buf[6 + i];
}
fts_i2c_write(client, packet_buf, (writelenght + 6));
for (i = 0; i < 30; i++)
{
/*read status and check if the app writting is finished*/
auc_i2c_write_buf[0] = 0x6a;
reg_val[0] = reg_val[1] = 0x00;
fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2);
if ((j + 0x20+0x1000) == (((reg_val[0]) << 8) | reg_val[1]))
{
break;
}
//msleep(1);
fts_ctpm_upgrade_delay(1000);
}
}
msleep(50);
return 0;
}
#endif /* IDC */

View File

@@ -0,0 +1,179 @@
/*
*
* FocalTech fts 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_upgrade_test.c
*
* Author: fupeipei
*
* Created: 2016-08-22
*
* Abstract:
*
* Reference:
*
*****************************************************************************/
/*****************************************************************************
* 1.Included header files
*****************************************************************************/
#include "../focaltech_core.h"
#include "../focaltech_flash.h"
//#include <linux/wakelock.h>
#include <linux/timer.h>
/*****************************************************************************
* Static variables
*****************************************************************************/
#define FTS_GET_UPGRADE_TIME 0
/*****************************************************************************
* Global variable or extern global variabls/functions
*****************************************************************************/
//struct wake_lock ps_lock;
#define FTS_DEBUG_UPGRADE(fmt, args...) do{\
printk(KERN_ERR "[FTS][UPGRADE]:##############################################################################\n");\
printk(KERN_ERR "[FTS][UPGRADE]: "fmt"\n", ##args);\
printk(KERN_ERR "[FTS][UPGRADE]:##############################################################################\n");\
}while(0)\
/*****************************************************************************
* Static function prototypes
*****************************************************************************/
#if (FTS_UPGRADE_STRESS_TEST)
/************************************************************************
* Name: fts_ctpm_auto_upgrade_pingpong
* Brief: 0
* Input: 0
* Output: 0
* Return: 0
***********************************************************************/
static int fts_ctpm_auto_upgrade_pingpong(struct i2c_client *client)
{
u8 uc_tp_fm_ver;
int i_ret = 0;
u8 uc_upgrade_times = 0;
FTS_FUNC_ENTER();
/* pingpong test mode, need upgrade */
FTS_INFO("[UPGRADE]: pingpong test mode, need upgrade!!");
do
{
uc_upgrade_times++;
/* fw upgrade */
i_ret = fts_ctpm_fw_upgrade(client);
if (i_ret == 0) /* upgrade success */
{
fts_i2c_read_reg(client, FTS_REG_FW_VER, &uc_tp_fm_ver);
FTS_DEBUG("[UPGRADE]: upgrade to new version 0x%x", uc_tp_fm_ver);
}
else /* upgrade fail */
{
/* if upgrade fail, reset to run ROM. if app in flash is ok. TP will work success */
FTS_INFO("[UPGRADE]: upgrade fail, reset now!!");
fts_ctpm_rom_or_pram_reset(client);
}
}
while ((i_ret != 0) && (uc_upgrade_times < 2)); /* if upgrade fail, upgrade again. then return */
FTS_FUNC_EXIT();
return i_ret;
}
/************************************************************************
* Name: fts_ctpm_auto_upgrade
* Brief: 0
* Input: 0
* Output: 0
* Return: 0
***********************************************************************/
void fts_ctpm_display_upgrade_time(bool start_time)
{
#if FTS_GET_UPGRADE_TIME
static struct timeval tpend;
static struct timeval tpstart;
static int timeuse;
if (start_time)
{
do_gettimeofday(&tpstart);
}
else
{
do_gettimeofday(&tpend);
timeuse=1000000*(tpend.tv_sec-tpstart.tv_sec)+ tpend.tv_usec-tpstart.tv_usec;
timeuse/=1000000;
FTS_DEBUG( "[UPGRADE]: upgrade success : Use time: %d Seconds!!", timeuse);
}
#endif
}
/************************************************************************
* Name: fts_ctpm_auto_upgrade
* Brief: 0
* Input: 0
* Output: 0
* Return: 0
***********************************************************************/
int fts_ctpm_auto_upgrade(struct i2c_client *client)
{
int i_ret = 0;
static int uc_ErrorTimes = 0;
static int uc_UpgradeTimes = 0;
// wake_lock_init(&ps_lock, WAKE_LOCK_SUSPEND, "tp_wakelock");
// wake_lock(&ps_lock);
/* (FTS_GET_VENDOR_ID_NUM == 0) */
g_fw_file = CTPM_FW;
g_fw_len = fts_getsize(FW_SIZE);
FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW, SIZE:%x", g_fw_len);
do
{
uc_UpgradeTimes++;
FTS_DEBUG_UPGRADE("start to upgrade %d times !!", uc_UpgradeTimes);
fts_ctpm_display_upgrade_time(true);
i_ret = fts_ctpm_auto_upgrade_pingpong(client);
if (i_ret == 0)
{
fts_ctpm_display_upgrade_time(false);
}
else
{
uc_ErrorTimes++;
}
FTS_DEBUG_UPGRADE("upgrade %d times, error %d times!!", uc_UpgradeTimes, uc_ErrorTimes);
}
while (uc_UpgradeTimes < (FTS_UPGRADE_TEST_NUMBER));
// wake_unlock(&ps_lock);
return 0;
}
#endif

View File

@@ -0,0 +1,670 @@
/*
*
* 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;
u8 active;
};
/*****************************************************************************
* 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 i2c_client *client = container_of(dev, struct i2c_client, dev);
mutex_lock(&fts_input_dev->mutex);
fts_i2c_read_reg(client, FTS_REG_GESTURE_EN, &val);
count = sprintf(buf, "Gesture Mode: %s\n", fts_gesture_data.mode ? "On" : "Off");
count += sprintf(buf + count, "Reg(0xD0) = %d\n", val);
mutex_unlock(&fts_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)
{
mutex_lock(&fts_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(&fts_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;
mutex_lock(&fts_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(&fts_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_DEBUG("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_readdata
* 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_fw
* Brief: Check IC's gesture recognise by FW or not
* Input:
* Output:
* Return: 1- FW 0- Driver
***********************************************************************/
static int fts_gesture_fw(void)
{
int ret = 0;
switch (chip_types.chip_idh)
{
case 0x54:
case 0x58:
case 0x64:
case 0x87:
case 0x86:
case 0x80:
case 0xE7:
ret = 1;
break;
default:
ret = 0;
break;
}
return ret;
}
/************************************************************************
* Name: fts_gesture_readdata
* Brief: read data from TP register
* Input:
* Output:
* Return: fail <0
***********************************************************************/
int fts_gesture_readdata(struct i2c_client *client)
{
u8 buf[FTS_GESTRUE_POINTS * 4] = { 0 };
int ret = -1;
int i = 0;
int gestrue_id = 0;
int read_bytes = 0;
u8 pointnum;
FTS_FUNC_ENTER();
/* 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;
}
/* FW recognize gesture */
if (fts_gesture_fw())
{
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(fts_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);
}
FTS_FUNC_EXIT();
return 0;
}
else
{
FTS_ERROR("[GESTURE]IC 0x%x need gesture lib to support gestures.", chip_types.chip_idh);
return 0;
}
#if 0
/* other IC's gestrue in driver, need gesture library */
if (0x24 == buf[0])
{
gestrue_id = 0x24;
fts_gesture_report(fts_input_dev, gestrue_id);
FTS_DEBUG("[GESTURE]%d check_gesture gestrue_id", gestrue_id);
FTS_FUNC_EXIT();
return -1;
}
/* Host Driver recognize gesture */
pointnum = buf[1];
read_bytes = ((int)pointnum) * 4 + 2;
buf[0] = FTS_REG_GESTURE_OUTPUT_ADDRESS;
ret = fts_gesture_read_buffer(client, buf, read_bytes);
if (ret < 0)
{
FTS_ERROR("[GESTURE]Driver recognize gesture - Read gesture touch data failed!!");
FTS_FUNC_EXIT();
return ret;
}
/*
* Host Driver recognize gesture, need gesture lib.a
* Not use now for compatibility
*/
gestrue_id = fetch_object_sample(buf, pointnum);
fts_gesture_report(fts_input_dev, gestrue_id);
FTS_DEBUG("[GESTURE]%d read gestrue_id", gestrue_id);
for (i = 0; i < pointnum; i++)
{
fts_gesture_data.coordinate_x[i] = (((s16) buf[0 + (4 * i+8)]) & 0x0F) << 8
| (((s16) buf[1 + (4 * i+8)])& 0xFF);
fts_gesture_data.coordinate_y[i] = (((s16) buf[2 + (4 * i+8)]) & 0x0F) << 8
| (((s16) buf[3 + (4 * i+8)]) & 0xFF);
}
FTS_FUNC_EXIT();
return -1;
#endif
}
/*****************************************************************************
* 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 (fts_gesture_data.mode && fts_gesture_data.active)
{
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: None
* Return: None
*****************************************************************************/
int fts_gesture_suspend(struct i2c_client *i2c_client)
{
int i;
u8 state;
FTS_FUNC_ENTER();
/* gesture not enable, return immediately */
if (fts_gesture_data.mode == 0)
{
FTS_DEBUG("gesture is disabled");
FTS_FUNC_EXIT();
return -1;
}
for (i = 0; i < 5; i++)
{
fts_i2c_write_reg(i2c_client, 0xd1, 0xff);
fts_i2c_write_reg(i2c_client, 0xd2, 0xff);
fts_i2c_write_reg(i2c_client, 0xd5, 0xff);
fts_i2c_write_reg(i2c_client, 0xd6, 0xff);
fts_i2c_write_reg(i2c_client, 0xd7, 0xff);
fts_i2c_write_reg(i2c_client, 0xd8, 0xff);
fts_i2c_write_reg(i2c_client, FTS_REG_GESTURE_EN, 0x01);
msleep(1);
fts_i2c_read_reg(i2c_client, FTS_REG_GESTURE_EN, &state);
if (state == 1)
break;
}
if (i >= 5)
{
FTS_ERROR("[GESTURE]Enter into gesture(suspend) failed!\n");
FTS_FUNC_EXIT();
return -1;
}
fts_gesture_data.active = 1;
FTS_DEBUG("[GESTURE]Enter into gesture(suspend) successfully!");
FTS_FUNC_EXIT();
return 0;
}
/*****************************************************************************
* Name: fts_gesture_resume
* Brief:
* Input:
* Output: None
* Return: None
*****************************************************************************/
int fts_gesture_resume(struct i2c_client *client)
{
int i;
u8 state;
FTS_FUNC_ENTER();
/* gesture not enable, return immediately */
if (fts_gesture_data.mode == 0)
{
FTS_DEBUG("gesture is disabled");
FTS_FUNC_EXIT();
return -1;
}
if (fts_gesture_data.active == 0)
{
FTS_DEBUG("gesture is unactive");
FTS_FUNC_EXIT();
return -1;
}
fts_gesture_data.active = 0;
for (i = 0; i < 5; i++)
{
fts_i2c_write_reg(client, FTS_REG_GESTURE_EN, 0x00);
msleep(1);
fts_i2c_read_reg(client, FTS_REG_GESTURE_EN, &state);
if (state == 0)
break;
}
if (i >= 5)
{
FTS_ERROR("[GESTURE]Clear gesture(resume) failed!\n");
}
FTS_FUNC_EXIT();
return 0;
}
/*****************************************************************************
* Name: fts_gesture_init
* Brief:
* Input:
* Output: None
* Return: None
*****************************************************************************/
int fts_gesture_init(struct input_dev *input_dev, struct i2c_client *client)
{
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 = 1;
fts_gesture_data.active = 0;
FTS_FUNC_EXIT();
return 0;
}
/************************************************************************
* Name: fts_gesture_exit
* Brief: call when driver removed
* Input:
* Output:
* Return:
***********************************************************************/
int fts_gesture_exit(struct i2c_client *client)
{
FTS_FUNC_ENTER();
sysfs_remove_group(&client->dev.kobj, &fts_gesture_group);
FTS_FUNC_EXIT();
return 0;
}
#endif

View File

@@ -0,0 +1,216 @@
/*
*
* 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_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
*****************************************************************************/
/*****************************************************************************
* 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;
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,
},
};
ret = i2c_transfer(client->adapter, msgs, 2);
if (ret < 0)
{
FTS_ERROR("[IIC]: i2c_transfer(write) error, ret=%d!!", ret);
}
}
else
{
struct i2c_msg msgs[] =
{
{
.addr = client->addr,
.flags = I2C_M_RD,
.len = readlen,
.buf = readbuf,
},
};
ret = i2c_transfer(client->adapter, msgs, 1);
if (ret < 0)
{
FTS_ERROR("[IIC]: i2c_transfer(read) error, ret=%d!!", ret);
}
}
}
mutex_unlock(&i2c_rw_access);
return ret;
}
/************************************************************************
* 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;
mutex_lock(&i2c_rw_access);
if (writelen > 0)
{
struct i2c_msg msgs[] =
{
{
.addr = client->addr,
.flags = 0,
.len = writelen,
.buf = writebuf,
},
};
ret = i2c_transfer(client->adapter, msgs, 1);
if (ret < 0)
{
FTS_ERROR("%s: i2c_transfer(write) error, ret=%d", __func__, ret);
}
}
mutex_unlock(&i2c_rw_access);
return ret;
}
/************************************************************************
* Name: fts_i2c_write_reg
* Brief: write register
* Input: i2c info, reg address, reg value
* Output: no
* Return: fail <0
***********************************************************************/
int fts_i2c_write_reg(struct i2c_client *client, u8 regaddr, u8 regvalue)
{
u8 buf[2] = {0};
buf[0] = regaddr;
buf[1] = regvalue;
return fts_i2c_write(client, buf, sizeof(buf));
}
/************************************************************************
* Name: fts_i2c_read_reg
* Brief: read register
* Input: i2c info, reg address, reg value
* Output: get reg value
* Return: fail <0
***********************************************************************/
int fts_i2c_read_reg(struct i2c_client *client, u8 regaddr, u8 *regvalue)
{
return fts_i2c_read(client, &regaddr, 1, regvalue, 1);
}
/************************************************************************
* Name: fts_i2c_init
* Brief: fts i2c init
* Input:
* Output:
* Return:
***********************************************************************/
int fts_i2c_init(void)
{
FTS_FUNC_ENTER();
FTS_FUNC_EXIT();
return 0;
}
/************************************************************************
* Name: fts_i2c_exit
* Brief: fts i2c exit
* Input:
* Output:
* Return:
***********************************************************************/
int fts_i2c_exit(void)
{
FTS_FUNC_ENTER();
FTS_FUNC_EXIT();
return 0;
}

View File

@@ -0,0 +1,153 @@
/*
*
* 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_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 //ms
/*****************************************************************************
* Private enumerations, structures and unions using typedef
*****************************************************************************/
/*****************************************************************************
* Static variables
*****************************************************************************/
static struct delayed_work fts_point_report_check_work;
static struct workqueue_struct *fts_point_report_check_workqueue = NULL;
/*****************************************************************************
* Global variable or extern global variabls/functions
*****************************************************************************/
/*****************************************************************************
* Static function prototypes
*****************************************************************************/
/*****************************************************************************
* functions body
*****************************************************************************/
/*****************************************************************************
* Name: fts_point_report_check_func
* Brief:
* Input:
* Output:
* Return:
*****************************************************************************/
static void fts_point_report_check_func(struct work_struct *work)
{
#if FTS_MT_PROTOCOL_B_EN
unsigned int finger_count=0;
#endif
FTS_FUNC_ENTER();
mutex_lock(&fts_wq_data->report_mutex);
#if FTS_MT_PROTOCOL_B_EN
for (finger_count = 0; finger_count < fts_wq_data->pdata->max_touch_number; finger_count++)
{
input_mt_slot(fts_input_dev, finger_count);
input_mt_report_slot_state(fts_input_dev, MT_TOOL_FINGER, false);
}
#else
input_mt_sync(fts_input_dev);
#endif
input_report_key(fts_input_dev, BTN_TOUCH, 0);
input_sync(fts_input_dev);
mutex_unlock(&fts_wq_data->report_mutex);
FTS_FUNC_EXIT();
}
void fts_point_report_check_queue_work(void)
{
cancel_delayed_work(&fts_point_report_check_work);
queue_delayed_work(fts_point_report_check_workqueue, &fts_point_report_check_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(void)
{
FTS_FUNC_ENTER();
INIT_DELAYED_WORK(&fts_point_report_check_work, fts_point_report_check_func);
fts_point_report_check_workqueue = create_workqueue("fts_point_report_check_func_wq");
if (fts_point_report_check_workqueue == NULL)
{
FTS_ERROR("[POINT_REPORT]: Failed to create fts_point_report_check_workqueue!!");
}
else
{
FTS_DEBUG("[POINT_REPORT]: Success to create fts_point_report_check_workqueue!!");
}
FTS_FUNC_EXIT();
return 0;
}
/*****************************************************************************
* Name: fts_point_report_check_exit
* Brief:
* Input:
* Output:
* Return:
*****************************************************************************/
int fts_point_report_check_exit(void)
{
FTS_FUNC_ENTER();
destroy_workqueue(fts_point_report_check_workqueue);
FTS_FUNC_EXIT();
return 0;
}
#endif /* FTS_POINT_REPORT_CHECK_EN */

View File

@@ -0,0 +1,329 @@
/*
*
* 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: Sensor
*
* Version: v1.0
*
* Revision History:
* v1.0:
* First release. By luougojin 2016-08-03
*****************************************************************************/
/*****************************************************************************
* Included header files
*****************************************************************************/
#include "focaltech_core.h"
#if FTS_PSENSOR_EN
/*****************************************************************************
* Private constant and macro definitions using #define
*****************************************************************************/
/* psensor register address*/
#define FTS_REG_PSENSOR_ENABLE 0xB0
#define FTS_REG_PSENSOR_STATUS 0x01
/* psensor register bits*/
#define FTS_PSENSOR_ENABLE_MASK 0x01
#define FTS_PSENSOR_STATUS_NEAR 0xC0
#define FTS_PSENSOR_STATUS_FAR 0xE0
#define FTS_PSENSOR_FAR_TO_NEAR 0
#define FTS_PSENSOR_NEAR_TO_FAR 1
#define FTS_PSENSOR_ORIGINAL_STATE_FAR 1
#define FTS_PSENSOR_WAKEUP_TIMEOUT 500
/*****************************************************************************
* Static variables
*****************************************************************************/
static struct sensors_classdev __maybe_unused sensors_proximity_cdev =
{
.name = "fts-proximity",
.vendor = "FocalTech",
.version = 1,
.handle = SENSORS_PROXIMITY_HANDLE,
.type = SENSOR_TYPE_PROXIMITY,
.max_range = "5.0",
.resolution = "5.0",
.sensor_power = "0.1",
.min_delay = 0,
.fifo_reserved_event_count = 0,
.fifo_max_event_count = 0,
.enabled = 0,
.delay_msec = 200,
.sensors_enable = NULL,
.sensors_poll_delay = NULL,
};
/*****************************************************************************
* functions body
*****************************************************************************/
/*****************************************************************************
* Name: fts_psensor_support_enabled
* Brief:
* Input:
* Output:
* Return:
*****************************************************************************/
static inline bool fts_psensor_support_enabled(void)
{
/*return config_enabled(CONFIG_TOUCHSCREEN_FTS_PSENSOR);*/
return FTS_PSENSOR_EN;
}
/*****************************************************************************
* Name: fts_psensor_enable
* Brief:
* Input:
* Output:
* Return:
*****************************************************************************/
static void fts_psensor_enable(struct fts_ts_data *data, int enable)
{
u8 state;
int ret = -1;
if (data->client == NULL)
return;
fts_i2c_read_reg(data->client, FTS_REG_PSENSOR_ENABLE, &state);
if (enable)
state |= FTS_PSENSOR_ENABLE_MASK;
else
state &= ~FTS_PSENSOR_ENABLE_MASK;
ret = fts_i2c_write_reg(data->client, FTS_REG_PSENSOR_ENABLE, state);
if (ret < 0)
FTS_ERROR("write psensor switch command failed");
return;
}
/*****************************************************************************
* Name: fts_psensor_enable_set
* Brief:
* Input:
* Output:
* Return:
*****************************************************************************/
static int fts_psensor_enable_set(struct sensors_classdev *sensors_cdev,
unsigned int enable)
{
struct fts_psensor_platform_data *psensor_pdata =
container_of(sensors_cdev,
struct fts_psensor_platform_data, ps_cdev);
struct fts_ts_data *data = psensor_pdata->data;
struct input_dev *input_dev = data->psensor_pdata->input_psensor_dev;
mutex_lock(&input_dev->mutex);
fts_psensor_enable(data, enable);
psensor_pdata->tp_psensor_data = FTS_PSENSOR_ORIGINAL_STATE_FAR;
if (enable)
psensor_pdata->tp_psensor_opened = 1;
else
psensor_pdata->tp_psensor_opened = 0;
mutex_unlock(&input_dev->mutex);
return enable;
}
/*****************************************************************************
* Name: fts_read_tp_psensor_data
* Brief:
* Input:
* Output:
* Return:
*****************************************************************************/
static int fts_read_tp_psensor_data(struct fts_ts_data *data)
{
u8 psensor_status;
char tmp;
int ret = 1;
fts_i2c_read_reg(data->client,
FTS_REG_PSENSOR_STATUS, &psensor_status);
tmp = data->psensor_pdata->tp_psensor_data;
if (psensor_status == FTS_PSENSOR_STATUS_NEAR)
data->psensor_pdata->tp_psensor_data =
FTS_PSENSOR_FAR_TO_NEAR;
else if (psensor_status == FTS_PSENSOR_STATUS_FAR)
data->psensor_pdata->tp_psensor_data =
FTS_PSENSOR_NEAR_TO_FAR;
if (tmp != data->psensor_pdata->tp_psensor_data)
{
FTS_ERROR("%s sensor data changed", __func__);
ret = 0;
}
return ret;
}
int fts_sensor_read_data(struct fts_ts_data *data)
{
int ret = 0;
if (fts_psensor_support_enabled() && data->psensor_pdata->tp_psensor_opened)
{
ret = fts_read_tp_psensor_data(data);
if ( !ret )
{
if (data->suspended)
{
pm_wakeup_event(&data->client->dev, FTS_PSENSOR_WAKEUP_TIMEOUT);
}
input_report_abs(data->psensor_pdata->input_psensor_dev,
ABS_DISTANCE,
data->psensor_pdata->tp_psensor_data);
input_sync(data->psensor_pdata->input_psensor_dev);
}
return 1;
}
return 0;
}
int fts_sensor_suspend(struct fts_ts_data *data)
{
int ret = 0;
if ( fts_psensor_support_enabled() &&
device_may_wakeup(&data->client->dev) &&
data->psensor_pdata->tp_psensor_opened )
{
ret = enable_irq_wake(data->client->irq);
if ( ret != 0 )
{
FTS_ERROR("%s: set_irq_wake failed", __func__);
}
data->suspended = true;
return 1;
}
return 0;
}
int fts_sensor_resume(struct fts_ts_data *data)
{
int ret = 0;
if ( fts_psensor_support_enabled() &&
device_may_wakeup(&data->client->dev) && data->psensor_pdata->tp_psensor_opened )
{
ret = disable_irq_wake(data->client->irq);
if (ret)
{
FTS_ERROR("%s: disable_irq_wake failed", __func__);
}
data->suspended = false;
return 1;
}
return 0;
}
int fts_sensor_init(struct fts_ts_data *data)
{
struct fts_psensor_platform_data *psensor_pdata;
struct input_dev *psensor_input_dev;
int err;
if (fts_psensor_support_enabled() )
{
device_init_wakeup(&data->client->dev, 1);
psensor_pdata = devm_kzalloc(&data->client->dev,
sizeof(struct fts_psensor_platform_data),
GFP_KERNEL);
if (!psensor_pdata)
{
FTS_ERROR("Failed to allocate memory");
goto irq_free;
}
data->psensor_pdata = psensor_pdata;
psensor_input_dev = input_allocate_device();
if (!psensor_input_dev)
{
FTS_ERROR("Failed to allocate device");
goto free_psensor_pdata;
}
__set_bit(EV_ABS, psensor_input_dev->evbit);
input_set_abs_params(psensor_input_dev, ABS_DISTANCE, 0, 1, 0, 0);
psensor_input_dev->name = "proximity";
psensor_input_dev->id.bustype = BUS_I2C;
psensor_input_dev->dev.parent = &data->client->dev;
data->psensor_pdata->input_psensor_dev = psensor_input_dev;
err = input_register_device(psensor_input_dev);
if (err)
{
FTS_ERROR("Unable to register device, err=%d", err);
goto free_psensor_input_dev;
}
psensor_pdata->ps_cdev = sensors_proximity_cdev;
psensor_pdata->ps_cdev.sensors_enable = fts_psensor_enable_set;
psensor_pdata->data = data;
err = sensors_classdev_register(&data->client->dev, &psensor_pdata->ps_cdev);
if (err)
{
goto unregister_psensor_input_device;
}
}
return 0;
unregister_psensor_input_device:
if (fts_psensor_support_enabled() )
input_unregister_device(data->psensor_pdata->input_psensor_dev);
free_psensor_input_dev:
if (fts_psensor_support_enabled() )
input_free_device(data->psensor_pdata->input_psensor_dev);
free_psensor_pdata:
if (fts_psensor_support_enabled() )
{
devm_kfree(&data->client->dev, psensor_pdata);
data->psensor_pdata = NULL;
}
irq_free:
if (fts_psensor_support_enabled())
device_init_wakeup(&data->client->dev, 0);
free_irq(data->client->irq, data);
return 1;
}
int fts_sensor_remove(struct fts_ts_data *data)
{
if (fts_psensor_support_enabled() )
{
device_init_wakeup(&data->client->dev, 0);
sensors_classdev_unregister(&data->psensor_pdata->ps_cdev);
input_unregister_device(data->psensor_pdata->input_psensor_dev);
devm_kfree(&data->client->dev, data->psensor_pdata);
data->psensor_pdata = NULL;
}
return 0;
}
#endif /* FTS_PSENSOR_EN */