blob: 6e8a976a626b2eb5580226ad8a3fe758c535245e [file] [log] [blame]
/* drivers/input/touchscreen/ektf.c - ELAN EKTF verions of driver
*
* Copyright (C) 2011 Elan Microelectronics Corporation.
*
* 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.
*
* 2014/0/28: The first release, version 0x0006
* Integrated 2 ,5 ,and 10 fingers driver code together and
* auto-mapping resolution.
* Please change following parameters
* 1. For 5 fingers protocol, please enable ELAN_PROTOCOL.
* The packet size is 18 or 24 bytes.
* 2. For 10 fingers, please enable both ELAN_PROTOCOL and ELAN_TEN_FINGERS.
* The packet size is 40 or 4+40+40+40 (Buffer mode) bytes.
* 3. Please enable the ELAN_BUTTON configuraton to support button.
* 4. For ektf3k serial, Add Re-Calibration Machanism
* So, please enable the define of RE_CALIBRATION.
* 5. Please enable the define of ESD_CHECK, if your firmware support
* "I am live" packet(0x78 0x78 0x78 0x78).
*
*
*/
/* The ELAN_PROTOCOL support normanl packet format */
/* Quanta BU10SW, Stanley Tsao, 2015.12.09, Change finger number to 2 for XU1 { */
//#define FINGER_NUM 10
#define FINGER_NUM 2
/* Quanta BU10SW, Stanley Tsao, 2015.12.09, Change finger number to 2 for XU1 { */
#define ELAN_PROTOCOL
//#define ELAN_BUFFER_MODE
//#define ELAN_BUTTON
/* #define RE_CALIBRATION */ /* Re-Calibration after system resume. */
//#define ELAN_2WIREICE
#define ELAN_POWER_SOURCE
#define ELAN_RESUME_RST
#define DEVICE_NAME "elan_ktf"
#define EKTF3K_FLASH
#if 1 /* Only one of the protocols can be enabled */
#define PROTOCOL_A /* multi-touch protocol */
#else
#define PROTOCOL_B /* Default: PROTOCOL B */
#endif
//#define ELAN_HID_I2C /* for hid over i2c protocol */
/* Quanta BU10SW, Stanley Tsao, 2015.11.23, Add Quanta customized gesture events {*/
//#define FEATURE_QUANTA_GESTURE_CUSTOMIZATION
/* Quanta BU10SW, Stanley Tsao, 2015.11.23, Add Quanta customized gesture events }*/
/* Quanta BU10SW, Stanley Tsao, 2015.12.25, Defer enabling touch irq { */
#define QUANTA_DEFER_ENABLE_IRQ
/* Quanta BU10SW, Stanley Tsao, 2015.12.25, Defer enabling touch irq { */
/* Quanta, BU10SW, Stanley Tsao, 2015.12.22, enable pinctrl usage for msm8909 { */
#define MSM_NEW_VER //cotrol new platform // Stanley Tsao, enable this for msm8909
/* Quanta, BU10SW, Stanley Tsao, 2015.12.22, enable pinctrl usage for msm8909 } */
#define FEATURE_PALM_DETECTION
#define FEATURE_QUANTA_GESTURE_TO_BOOTLOADER
#define FEATURE_QUANTA_GESTURE_TO_RECOVERY
#if defined(FEATURE_QUANTA_GESTURE_TO_BOOTLOADER) || defined(FEATURE_QUANTA_GESTURE_TO_RECOVERY)
#include <linux/reboot.h>
#endif
#include <linux/module.h>
#include <linux/input.h>
#ifdef PROTOCOL_B
#include <linux/input/mt.h>
#endif
#ifdef PROTOCOL_A
#include <linux/input.h>
#endif
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/device.h>
#include <linux/jiffies.h>
#include <linux/miscdevice.h>
#include <linux/debugfs.h>
#if defined(CONFIG_FB)
#include <linux/notifier.h>
#include <linux/fb.h>
/* Quanta BU10SW, Stanley Tsao, 2015.11.17, Fix compiling error { */
#elif defined(CONFIG_HAS_EARLYSUSPEND)
#include <linux/earlysuspend.h>
/* Quanta BU10SW, Stanley Tsao, 2015.11.17, Fix compiling error } */
#endif
// for linux 2.6.36.3
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <asm/ioctl.h>
#include <linux/switch.h>
#include <linux/proc_fs.h>
#include <linux/firmware.h>
#include <linux/wakelock.h>
/* Quanta BU10SW, Stanley Tsao, 2015.11.17, Place elan_ktf.h in the folder in which elan_ktf.c is placed { */
/* #include <linux/elan_ktf.h> */
#include <elan_ktf.h>
/* Quanta BU10SW, Stanley Tsao, 2015.11.17, Place elan_ktf.h in the folder in which elan_ktf.c is placed } */
#include <linux/kthread.h>
//#include "elan_ktf.h"
#if defined(CONFIG_FB)
#include <linux/notifier.h>
#include <linux/fb.h>
#include <linux/regulator/machine.h>
//#include <linux/regulator/krait-regulator.h>
#endif
/* Quanta BU10SW, Stanley Tsao, 2015.11.17, Add kernel version check { */
#include <linux/version.h>
/* Quanta BU10SW, Stanley Tsao, 2015.11.17, Add kernel version check } */
/* Quanta BU10SW, Stanley Tsao, 2015.12.01, Add DT parsing function { */
#include <linux/of_gpio.h>
/* Quanta BU10SW, Stanley Tsao, 2015.12.01, Add DT parsing function } */
#include <linux/qpnp/qpnp-vibrator.h>
#define PACKET_SIZE 8 /* support 2 fingers packet for watch */
#define MAX_FINGER_SIZE 255
#define PWR_STATE_DEEP_SLEEP 0
#define PWR_STATE_NORMAL 1
#define PWR_STATE_IDLE 2
#define PWR_STATE_MASK BIT(3)
#define CMD_S_PKT 0x52
#define CMD_R_PKT 0x53
#define CMD_W_PKT 0x54
#define RESET_PKT 0x77
#define CALIB_PKT 0x66
#define IamAlive_PKT 0x78
#define IDLE_MODE_PKT 0xED /* ED ED ED ED */
#define PEN_PKT 0x71
#define HELLO_PKT 0x55
#define TWO_FINGERS_PKT 0x5A
#define FIVE_FINGERS_PKT 0x5D
#define MTK_FINGERS_PKT 0x6D
#define TEN_FINGERS_PKT 0x62
#define ELAN_HID_PKT 0x3F
#define BUFFER_PKT 0x63
#define BUFFER55_PKT 0x66
#define FEATURE_CHECK_TRUE_INTERRUPT
#ifdef FEATURE_CHECK_TRUE_INTERRUPT
static int touchINT_cnt = 0;
static int IamAlive_PKT_INT_cnt = 0;
#endif
#ifdef FEATURE_PALM_DETECTION
#define PALM_DETECTION_PKT 0xBA
#endif
static const int NEWEST_FW_VER = 0xb013;
/* Common for quanta gestures */
#if defined(FEATURE_QUANTA_GESTURE_TO_BOOTLOADER) || defined(FEATURE_QUANTA_GESTURE_TO_RECOVERY)
#define QUANTA_GESTURE_POINT_OFFSET_TOLERANCE_X 150
#define QUANTA_GESTURE_POINT_OFFSET_TOLERANCE_Y 150
struct quanta_gesture_point {
uint16_t x;
uint16_t y;
};
struct quanta_gesture_point_3 {
struct quanta_gesture_point p1;
struct quanta_gesture_point p2;
struct quanta_gesture_point p3;
};
static bool quanta_gesture_checkpoint
(
uint16_t reported_x,
uint16_t reported_y,
struct quanta_gesture_point target_point
)
{
if (reported_x < target_point.x + QUANTA_GESTURE_POINT_OFFSET_TOLERANCE_X &&
reported_x > target_point.x - QUANTA_GESTURE_POINT_OFFSET_TOLERANCE_X &&
reported_y < target_point.y + QUANTA_GESTURE_POINT_OFFSET_TOLERANCE_Y &&
reported_y > target_point.y - QUANTA_GESTURE_POINT_OFFSET_TOLERANCE_Y )
{
return true;
}
else
return false;
}
#endif
#ifdef FEATURE_QUANTA_GESTURE_TO_RECOVERY
#define QUANTA_GESTURE_TO_RECOVERY_1_X 874
#define QUANTA_GESTURE_TO_RECOVERY_1_Y 150
#define QUANTA_GESTURE_TO_RECOVERY_2_X 512
#define QUANTA_GESTURE_TO_RECOVERY_2_Y 512
#define QUANTA_GESTURE_TO_RECOVERY_3_X 150
#define QUANTA_GESTURE_TO_RECOVERY_3_Y 874
#define QUANTA_GESTURE_TO_RECOVERY_1_POINT_FLAG 0x01
#define QUANTA_GESTURE_TO_RECOVERY_2_POINT_FLAG 0x02
#define QUANTA_GESTURE_TO_RECOVERY_3_POINT_FLAG 0x04
#define QUANTA_GESTURE_TO_RECOVERY_FLAG \
(QUANTA_GESTURE_TO_RECOVERY_1_POINT_FLAG | \
QUANTA_GESTURE_TO_RECOVERY_2_POINT_FLAG | \
QUANTA_GESTURE_TO_RECOVERY_3_POINT_FLAG )
static int quanta_gesture_to_recovery = 0x00;
static bool is_quanta_gesture_to_rcvr_enabled = true;
static bool is_enalbe_vib = true;
/* Pre-defined gesture points */
static struct quanta_gesture_point_3 toRecovery = {
{QUANTA_GESTURE_TO_RECOVERY_1_X, QUANTA_GESTURE_TO_RECOVERY_1_Y},
{QUANTA_GESTURE_TO_RECOVERY_2_X, QUANTA_GESTURE_TO_RECOVERY_2_Y},
{QUANTA_GESTURE_TO_RECOVERY_3_X, QUANTA_GESTURE_TO_RECOVERY_3_Y}
};
static int quanta_gesture_clear_recovery_flag(void)
{
quanta_gesture_to_recovery = 0x00;
printk("[quanta]%s \n", __func__);
return 0;
}
/*
/
/
/
/
/
<
Fomular: y = -x + 1024
*/
static bool is_quanta_gesture_to_recovery_point_on_the_line(uint16_t reported_x, uint16_t reported_y)
{
if (reported_y < (-reported_x + 1024) - QUANTA_GESTURE_POINT_OFFSET_TOLERANCE_Y ||
reported_y > (-reported_x + 1024) + QUANTA_GESTURE_POINT_OFFSET_TOLERANCE_Y)
{
return false;
}
return true;
}
static int quanta_gesture_to_recovery_check(uint16_t reported_x, uint16_t reported_y)
{
// Check the 1st point
if(!(quanta_gesture_to_recovery & QUANTA_GESTURE_TO_RECOVERY_1_POINT_FLAG))
{
if (quanta_gesture_checkpoint(reported_x, reported_y, toRecovery.p1))
{
quanta_gesture_to_recovery |= QUANTA_GESTURE_TO_RECOVERY_1_POINT_FLAG;
printk("[quanta]%s: bootloader point 1 check PASS, quanta_gesture_to_bootloader=%x \n", __func__, quanta_gesture_to_recovery);
}
return 0;
}
/* If any of the points after the 1st matched point is not on the defined line --> reset gesture flag
The folumar for the defined line of gesture to bootloader is y=x
*/
if (!is_quanta_gesture_to_recovery_point_on_the_line(reported_x, reported_y))
{
quanta_gesture_clear_recovery_flag();
return 0;
}
// Check the 2nd point
if(!(quanta_gesture_to_recovery & QUANTA_GESTURE_TO_RECOVERY_2_POINT_FLAG))
{
if (quanta_gesture_checkpoint(reported_x, reported_y, toRecovery.p2))
{
quanta_gesture_to_recovery |= QUANTA_GESTURE_TO_RECOVERY_2_POINT_FLAG;
printk("[quanta]%s: bootloader point 2 check PASS, quanta_gesture_to_bootloader=%x \n", __func__, quanta_gesture_to_recovery);
}
return 0;
}
/* If any of the points after the 1st matched point is not on the defined line --> reset gesture flag
The folumar for the defined line of gesture to bootloader is y=x
*/
if (!is_quanta_gesture_to_recovery_point_on_the_line(reported_x, reported_y))
{
quanta_gesture_clear_recovery_flag();
return 0;
}
// Check the 3rd point
if(!(quanta_gesture_to_recovery & QUANTA_GESTURE_TO_RECOVERY_3_POINT_FLAG))
{
if (quanta_gesture_checkpoint(reported_x, reported_y, toRecovery.p3))
{
quanta_gesture_to_recovery |= QUANTA_GESTURE_TO_RECOVERY_3_POINT_FLAG;
printk("[quanta]%s: bootloader point 3 check PASS, quanta_gesture_to_bootloader=%x \n", __func__, quanta_gesture_to_recovery);
}
return 0;
}
if( quanta_gesture_to_recovery & QUANTA_GESTURE_TO_RECOVERY_FLAG)
{
printk("[quanta]%s: quanta_gesture_to_bootloader %x, restart to bootloader \n", __func__, quanta_gesture_to_recovery);
kernel_restart("recovery");
}
return 0;
}
#endif //FEATURE_QUANTA_GESTURE_TO_BOOTLOADER
#ifdef FEATURE_QUANTA_GESTURE_TO_BOOTLOADER
/* Assume touch resolution is 1024 x 1024 */
#define QUANTA_GESTURE_TO_BOOTLOADER_1_X 150
#define QUANTA_GESTURE_TO_BOOTLOADER_1_Y 150
#define QUANTA_GESTURE_TO_BOOTLOADER_2_X 512
#define QUANTA_GESTURE_TO_BOOTLOADER_2_Y 512
#define QUANTA_GESTURE_TO_BOOTLOADER_3_X 874
#define QUANTA_GESTURE_TO_BOOTLOADER_3_Y 874
#define QUANTA_GESTURE_TO_BOOTLOADER_1_POINT_FLAG 0x01
#define QUANTA_GESTURE_TO_BOOTLOADER_2_POINT_FLAG 0x02
#define QUANTA_GESTURE_TO_BOOTLOADER_3_POINT_FLAG 0x04
#define QUANTA_GESTURE_TO_BOOTLOER_FLAG \
(QUANTA_GESTURE_TO_BOOTLOADER_1_POINT_FLAG | \
QUANTA_GESTURE_TO_BOOTLOADER_2_POINT_FLAG | \
QUANTA_GESTURE_TO_BOOTLOADER_3_POINT_FLAG )
static int quanta_gesture_to_bootloader = 0x00;
static bool is_quanta_gesture_to_bld_enabled = true;
/* Pre-defined gesture points */
static struct quanta_gesture_point_3 toBootloader = {
{QUANTA_GESTURE_TO_BOOTLOADER_1_X, QUANTA_GESTURE_TO_BOOTLOADER_1_Y},
{QUANTA_GESTURE_TO_BOOTLOADER_2_X, QUANTA_GESTURE_TO_BOOTLOADER_2_Y},
{QUANTA_GESTURE_TO_BOOTLOADER_3_X, QUANTA_GESTURE_TO_BOOTLOADER_3_Y}
};
static int quanta_gesture_clear_bootloader_flag(void)
{
quanta_gesture_to_bootloader = 0x00;
printk("[quanta]%s \n", __func__);
return 0;
}
static bool is_quanta_gesture_to_bootlader_point_on_the_line(uint16_t reported_x, uint16_t reported_y)
{
if (reported_y < reported_x - QUANTA_GESTURE_POINT_OFFSET_TOLERANCE_Y ||
reported_y > reported_x + QUANTA_GESTURE_POINT_OFFSET_TOLERANCE_Y)
{
return false;
}
return true;
}
static int quanta_gesture_to_bootloader_check(uint16_t reported_x, uint16_t reported_y)
{
// Check the 1st point
if(!(quanta_gesture_to_bootloader & QUANTA_GESTURE_TO_BOOTLOADER_1_POINT_FLAG))
{
if (quanta_gesture_checkpoint(reported_x, reported_y, toBootloader.p1))
{
quanta_gesture_to_bootloader |= QUANTA_GESTURE_TO_BOOTLOADER_1_POINT_FLAG;
printk("[quanta]%s: bootloader point 1 check PASS, quanta_gesture_to_bootloader=%x \n", __func__, quanta_gesture_to_bootloader);
}
return 0;
}
/* If any of the points after the 1st matched point is not on the defined line --> reset gesture flag
The folumar for the defined line of gesture to bootloader is y=x
*/
if (!is_quanta_gesture_to_bootlader_point_on_the_line(reported_x, reported_y))
{
quanta_gesture_clear_bootloader_flag();
return 0;
}
// Check the 2nd point
if(!(quanta_gesture_to_bootloader & QUANTA_GESTURE_TO_BOOTLOADER_2_POINT_FLAG))
{
if (quanta_gesture_checkpoint(reported_x, reported_y, toBootloader.p2))
{
quanta_gesture_to_bootloader |= QUANTA_GESTURE_TO_BOOTLOADER_2_POINT_FLAG;
printk("[quanta]%s: bootloader point 2 check PASS, quanta_gesture_to_bootloader=%x \n", __func__, quanta_gesture_to_bootloader);
}
return 0;
}
/* If any of the points after the 1st matched point is not on the defined line --> reset gesture flag
The folumar for the defined line of gesture to bootloader is y=x
*/
if (!is_quanta_gesture_to_bootlader_point_on_the_line(reported_x, reported_y))
{
quanta_gesture_clear_bootloader_flag();
return 0;
}
// Check the 3rd point
if(!(quanta_gesture_to_bootloader & QUANTA_GESTURE_TO_BOOTLOADER_3_POINT_FLAG))
{
if (quanta_gesture_checkpoint(reported_x, reported_y, toBootloader.p3))
{
quanta_gesture_to_bootloader |= QUANTA_GESTURE_TO_BOOTLOADER_3_POINT_FLAG;
printk("[quanta]%s: bootloader point 3 check PASS, quanta_gesture_to_bootloader=%x \n", __func__, quanta_gesture_to_bootloader);
}
return 0;
}
if( quanta_gesture_to_bootloader & QUANTA_GESTURE_TO_BOOTLOER_FLAG)
{
printk("[quanta]%s: quanta_gesture_to_bootloader %x, restart to bootloader \n", __func__, quanta_gesture_to_bootloader);
kernel_restart("bootloader");
}
return 0;
}
#endif //FEATURE_QUANTA_GESTURE_TO_BOOTLOADER
/* Quanta BU10SW, Stanley Tsao, 2015.11.23, Add Quanta customized gesture events {*/
#ifdef FEATURE_QUANTA_GESTURE_CUSTOMIZATION
#define QUANTA_GESTURE_PKT 0x9E
#define QUANTA_GESTURE__NUM_GESTURES 8
#define LINUX_KEY_F1 0x3b
#define LINUX_KEY_F2 0x3c
#define LINUX_KEY_F3 0x3d
#define LINUX_KEY_F4 0x3e
#define LINUX_KEY_F5 0x3f
#define LINUX_KEY_F6 0x40
#define LINUX_KEY_F7 0x41
#define LINUX_KEY_F8 0x42
static uint8_t gesture_map_table[QUANTA_GESTURE__NUM_GESTURES] =
{LINUX_KEY_F1, /* toucH ic output 0x12, 12-> 3 */
LINUX_KEY_F2, /* toucH ic output 0x13, 3 -> 12 */
LINUX_KEY_F3, /* toucH ic output 0x14, 3 -> 6 */
LINUX_KEY_F4, /* toucH ic output 0x15, 6 -> 3 */
LINUX_KEY_F5, /* toucH ic output 0x16, 6 -> 9 */
LINUX_KEY_F6, /* toucH ic output 0x17, 9 -> 6 */
LINUX_KEY_F7, /* toucH ic output 0x18, 9 -> 12 */
LINUX_KEY_F8, /* toucH ic output 0x19, 12-> 9 */
};
#endif
/* Quanta BU10SW, Stanley Tsao, 2015.11.23, Add Quanta customized gesture events }*/
/* Quanta, BU10SW, Stanley Tsao, 2015.12.22, enable pinctrl usage for msm8909 { */
#ifdef MSM_NEW_VER
#define PINCTRL_STATE_ACTIVE "pmx_ts_active"
#define PINCTRL_STATE_SUSPEND "pmx_ts_suspend"
#define PINCTRL_STATE_RELEASE "pmx_ts_release"
#endif
/* Quanta, BU10SW, Stanley Tsao, 2015.12.22, enable pinctrl usage for msm8909 } */
#ifdef PROTOCOL_A
#define CURRENT_MT_PROTOCOL "A"
#endif
#ifdef PROTOCOL_B
#define CURRENT_MT_PROTOCOL "B"
#endif
// Reset pin need to be modified by customer
/* Quanta BU10SW, Stanley Tsao, 2015.12.01, Change for XU1 { */
#if 0
#define SYSTEM_RESET_PIN_SR 31 // nexus7_grouper TEGRA_GPIO_PH6: 62, nexus7_flo 31
#else
#define SYSTEM_RESET_PIN_SR 12
#endif
/* Quanta BU10SW, Stanley Tsao, 2015.12.01, Change for XU1 } */
//Add these Define
#define IAP_PORTION
#define PAGERETRY 30
#define IAPRESTART 5
#define ESD_CHECK
#if defined( ESD_CHECK )
static int have_interrupts = 0;
static struct workqueue_struct *esd_wq = NULL;
static struct delayed_work esd_work;
static unsigned long delay = 3*HZ;
static int suspend_ESD = 0;
//declare function
static void elan_touch_esd_func(struct work_struct *work);
#endif
// For Firmware Update
#define ELAN_IOCTLID 0xD0
#define IOCTL_I2C_SLAVE _IOW(ELAN_IOCTLID, 1, int)
#define IOCTL_FW_INFO _IOR(ELAN_IOCTLID, 2, int)
#define IOCTL_MINOR_FW_VER _IOR(ELAN_IOCTLID, 3, int)
#define IOCTL_RESET _IOR(ELAN_IOCTLID, 4, int)
#define IOCTL_IAP_MODE_LOCK _IOR(ELAN_IOCTLID, 5, int)
#define IOCTL_CHECK_RECOVERY_MODE _IOR(ELAN_IOCTLID, 6, int)
#define IOCTL_FW_VER _IOR(ELAN_IOCTLID, 7, int)
#define IOCTL_X_RESOLUTION _IOR(ELAN_IOCTLID, 8, int)
#define IOCTL_Y_RESOLUTION _IOR(ELAN_IOCTLID, 9, int)
#define IOCTL_FW_ID _IOR(ELAN_IOCTLID, 10, int)
#define IOCTL_ROUGH_CALIBRATE _IOR(ELAN_IOCTLID, 11, int)
#define IOCTL_IAP_MODE_UNLOCK _IOR(ELAN_IOCTLID, 12, int)
#define IOCTL_I2C_INT _IOR(ELAN_IOCTLID, 13, int)
#define IOCTL_RESUME _IOR(ELAN_IOCTLID, 14, int)
#define IOCTL_POWER_LOCK _IOR(ELAN_IOCTLID, 15, int)
#define IOCTL_POWER_UNLOCK _IOR(ELAN_IOCTLID, 16, int)
#define IOCTL_FW_UPDATE _IOR(ELAN_IOCTLID, 17, int)
#define IOCTL_BC_VER _IOR(ELAN_IOCTLID, 18, int)
#define IOCTL_2WIREICE _IOR(ELAN_IOCTLID, 19, int)
#define CUSTOMER_IOCTLID 0xA0
#define IOCTL_CIRCUIT_CHECK _IOR(CUSTOMER_IOCTLID, 1, int)
#define IOCTL_GET_UPDATE_PROGREE _IOR(CUSTOMER_IOCTLID, 2, int)
#define ELAN_FW_FILENAME "ElanFW.fw"
/* Debug levels */
#define NO_DEBUG 0
#define DEBUG_ERROR 1
#define DEBUG_INFO 2
#define DEBUG_MESSAGES 5
#define DEBUG_TRACE 10
#define SYSFS_MAX_LEN 100
static unsigned int gPrint_point = 0;
static int debug = DEBUG_TRACE;
#define touch_debug(level, ...) \
do { \
if (debug >= (level)) \
printk("[ektf]:" __VA_ARGS__); \
} while (0)
uint8_t RECOVERY=0x00;
int FW_VERSION=0x00;
/* Quanta BU10SW, Stanley Tsao, 2015.12.01, For XU1 touch resolution { */
#if 0
int X_RESOLUTION=1344; // nexus7 1280 1344
int Y_RESOLUTION=2240; // nexus7 2112 2240
#else /* Quanta XU1 project */
int X_RESOLUTION=1024;
int Y_RESOLUTION=1024;
#endif
/* Quanta BU10SW, Stanley Tsao, 2015.12.01, For XU1 touch resolution } */
/* Quanta BU10SW, Stanley Tsao, 2015.12.25, Defer enabling touch irq { */
#ifdef QUANTA_DEFER_ENABLE_IRQ
#define DEFER_ENABLE_IRQ_TIMER_MS 0
#endif /* QUANTA_DEFER_ENABLE_IRQ */
/* Quanta BU10SW, Stanley Tsao, 2015.12.25, Defer enabling touch irq { */
int BC_VERSION= 0x00;
int FW_ID=0x00;
int work_lock=0x00;
int power_lock=0x00;
int circuit_ver=0x01;
/*++++i2c transfer start+++++++*/
int file_fops_addr=0x10;
/*++++i2c transfer end+++++++*/
struct mutex ktf_mutex;
int button_state = 0;
#ifdef IAP_PORTION
uint8_t ic_status=0x00; //0:OK 1:master fail 2:slave fail
int update_progree=0;
uint8_t I2C_DATA[3] = {0x10, 0x20, 0x21};/*I2C devices address*/
int is_OldBootCode = 0; // 0:new 1:old
static unsigned char firmware[52800];
/*The newest firmware, if update must be changed here*/
static uint8_t file_fw_data[] = {
#include "fw_data_eWD1000_XU1_B013.i"
};
enum
{
PageSize = 132,
ACK_Fail = 0x00,
ACK_OK = 0xAA,
ACK_REWRITE = 0x55,
};
//int PageNum = sizeof(file_fw_data)/132; /*for ektf2xxx/3xxx serial, the page number is 249/351*/
int PageNum = 0;
enum power_mode_type
{
POWER_MODE_NORMAL = 0,
POWER_MODE_IDLE = 1,
POWER_MODE_SLEEP = 2,
};
enum
{
E_FD = -1,
};
#endif
//#define _ENABLE_DBG_LEVEL
#ifdef _ENABLE_DBG_LEVEL
#define PROC_FS_NAME "ektf_dbg"
#define PROC_FS_MAX_LEN 8
static struct proc_dir_entry *dbgProcFile;
#endif
struct elan_ktf_ts_data {
struct i2c_client *client;
struct input_dev *input_dev;
struct workqueue_struct *elan_wq;
struct work_struct work;
/* Quanta BU10SW, Stanley Tsao, 2015.12.25, Defer enabling touch irq { */
#ifdef QUANTA_DEFER_ENABLE_IRQ
struct delayed_work workd;
#endif /* QUANTA_DEFER_ENABLE_IRQ */
/* Quanta BU10SW, Stanley Tsao, 2015.12.25, Defer enabling touch irq } */
#if defined(CONFIG_FB)
struct notifier_block fb_notif;
#elif defined(CONFIG_HAS_EARLYSUSPEND)
struct early_suspend early_suspend;
#endif
int intr_gpio;
int rst_gpio;
// Firmware Information
int fw_ver;
int fw_id;
int bc_ver;
int x_resolution;
int y_resolution;
// For Firmare Update
struct miscdevice firmware;
struct wake_lock wakelock;
/* Quanta BU10SW, Stanley Tsao, 2015.12.03, Add VDD, VDDIO control function { */
struct regulator *vdd;
struct regulator *vcc_i2c;
/* Quanta BU10SW, Stanley Tsao, 2015.12.03, Add VDD, VDDIO control function } */
/* Quanta, BU10SW, Stanley Tsao, 2015.12.22, enable pinctrl usage for msm8909 { */
#ifdef MSM_NEW_VER
struct pinctrl *ts_pinctrl;
struct pinctrl_state *pinctrl_state_active;
struct pinctrl_state *pinctrl_state_suspend;
struct pinctrl_state *pinctrl_state_release;
#endif
/* Quanta, BU10SW, Stanley Tsao, 2015.12.22, enable pinctrl usage for msm8909 { */
uint power_mode;
int irq;
};
static struct elan_ktf_ts_data *private_ts;
static int __fw_packet_handler(struct i2c_client *client);
static int elan_ktf_ts_calibrate(struct i2c_client *client);
static int elan_ktf_ts_resume(struct i2c_client *client);
static int elan_ktf_ts_suspend(struct i2c_client *client, pm_message_t mesg);
void elan_ktf_ts_hw_reset(void);
static int __hello_packet_handler(struct i2c_client *client);
#ifdef IAP_PORTION
//static int Update_FW_in_Driver(void *x);
static int Update_FW_One(int source);
#endif
#ifdef ELAN_2WIREICE
int elan_TWO_WIRE_ICE( struct i2c_client *client);
#endif
/* Quanta BU10SW, Stanley Tsao, 2015.12.01, Add DT parsing function { */
#ifdef CONFIG_OF
static int elan_ktf_parse_dt(struct device *dev, struct elan_ktf_i2c_platform_data *pdata)
{
//int rc;
struct device_node *np = dev->of_node;
//struct property *prop;
printk("[Stanley]%s called \n", __func__);
// get interrupt gpio
// get reset gpio
pdata->rst_gpio = of_get_named_gpio_flags(np, "elan_ktf,reset-gpio", 0, &pdata->rst_gpio_flags);
if (pdata->rst_gpio < 0)
return pdata->rst_gpio;
printk("[stanley]%s: reset gpio=%d, flags=%d \n", __func__, pdata->rst_gpio, pdata->rst_gpio_flags);
pdata->intr_gpio = of_get_named_gpio_flags(np, "elan_ktf,irq-gpio", 0, &pdata->intr_gpio_flags);
if (pdata->intr_gpio < 0)
return pdata->intr_gpio;
printk("[stanley]%s: interrupt gpio=%d, flags=%d \n", __func__, pdata->intr_gpio, pdata->intr_gpio_flags);
return 0;
}
#endif
/* Quanta BU10SW, Stanley Tsao, 2015.12.01, Add DT parsing function } */
/* Quanta, BU10SW, Stanley Tsao, 2015.12.22, enable pinctrl usage for msm8909 { */
#ifdef MSM_NEW_VER
static int elan_ktf_ts_pinctrl_init(struct elan_ktf_ts_data *elan_ktf_data)
{
int retval;
/* Get pinctrl if target uses pinctrl */
elan_ktf_data->ts_pinctrl = devm_pinctrl_get(&(elan_ktf_data->client->dev));
if (IS_ERR_OR_NULL(elan_ktf_data->ts_pinctrl)) {
retval = PTR_ERR(elan_ktf_data->ts_pinctrl);
dev_dbg(&elan_ktf_data->client->dev,
"Target does not use pinctrl %d\n", retval);
goto err_pinctrl_get;
}
elan_ktf_data->pinctrl_state_active
= pinctrl_lookup_state(elan_ktf_data->ts_pinctrl,
PINCTRL_STATE_ACTIVE);
if (IS_ERR_OR_NULL(elan_ktf_data->pinctrl_state_active)) {
retval = PTR_ERR(elan_ktf_data->pinctrl_state_active);
dev_err(&elan_ktf_data->client->dev,
"Can not lookup %s pinstate %d\n",
PINCTRL_STATE_ACTIVE, retval);
goto err_pinctrl_lookup;
}
elan_ktf_data->pinctrl_state_suspend
= pinctrl_lookup_state(elan_ktf_data->ts_pinctrl,
PINCTRL_STATE_SUSPEND);
if (IS_ERR_OR_NULL(elan_ktf_data->pinctrl_state_suspend)) {
retval = PTR_ERR(elan_ktf_data->pinctrl_state_suspend);
dev_err(&elan_ktf_data->client->dev,
"Can not lookup %s pinstate %d\n",
PINCTRL_STATE_SUSPEND, retval);
goto err_pinctrl_lookup;
}
elan_ktf_data->pinctrl_state_release
= pinctrl_lookup_state(elan_ktf_data->ts_pinctrl,
PINCTRL_STATE_RELEASE);
if (IS_ERR_OR_NULL(elan_ktf_data->pinctrl_state_release)) {
retval = PTR_ERR(elan_ktf_data->pinctrl_state_release);
dev_dbg(&elan_ktf_data->client->dev,
"Can not lookup %s pinstate %d\n",
PINCTRL_STATE_RELEASE, retval);
}
return 0;
err_pinctrl_lookup:
devm_pinctrl_put(elan_ktf_data->ts_pinctrl);
err_pinctrl_get:
elan_ktf_data->ts_pinctrl = NULL;
return retval;
}
#endif
/* Quanta, BU10SW, Stanley Tsao, 2015.12.22, enable pinctrl usage for msm8909 | */
/* Quanta BU10SW, Stanley Tsao, 2015.12.25, Defer enabling touch irq { */
#ifdef QUANTA_DEFER_ENABLE_IRQ
static void elan_work(struct work_struct *work)
{
//struct elan_ktf_ts_data *ts = container_of(work, struct elan_ktf_ts_data, work.work);
printk("[Stanley]%s: elan_work\n", __func__);
printk("[Stanley]%s: case elan_work() \n", __func__);
work_lock=0;
enable_irq(private_ts->client->irq);
wake_unlock(&private_ts->wakelock);
}
#endif /* #ifdef QUANTA_DEFER_ENABLE_IRQ */
/* Quanta BU10SW, Stanley Tsao, 2015.12.25, Defer enabling touch irq } */
static int __elan_ktf_ts_poll(struct i2c_client *client)
{
struct elan_ktf_ts_data *ts = i2c_get_clientdata(client);
int status = 0, retry = 10;
do {
status = gpio_get_value(ts->intr_gpio);
if(status==0) break;
touch_debug(DEBUG_MESSAGES, "%s: status = %d\n", __func__, status);
retry--;
mdelay(50);
} while (status == 1 && retry > 0);
touch_debug(DEBUG_INFO, "[elan]%s: poll interrupt status %s\n",
__func__, status == 1 ? "high" : "low");
return (status == 0 ? 0 : -ETIMEDOUT);
}
static int elan_ktf_ts_poll(struct i2c_client *client)
{
return __elan_ktf_ts_poll(client);
}
/************************************
* Restet TP
*************************************/
void elan_ktf_ts_hw_reset()
{
//reset
//gpio_set_value(SYSTEM_RESET_PIN_SR, 0);
//msleep(20);
//gpio_set_value(SYSTEM_RESET_PIN_SR, 1);
//msleep(10);
/* Quanta BU10SW, Stalney Tsao, 2015.12.25, get reset pin number from device tree { */
#if 0
gpio_direction_output(SYSTEM_RESET_PIN_SR, 0);
msleep(20);
gpio_direction_output(SYSTEM_RESET_PIN_SR, 1);
msleep(10);
#else
gpio_direction_output(private_ts->rst_gpio, 0);
msleep(20);
gpio_direction_output(private_ts->rst_gpio, 1);
msleep(10);
#endif
/* Quanta BU10SW, Stalney Tsao, 2015.12.25, get reset pin number from device tree } */
}
/*
void read_test(void)
{
int pos=0;
struct file *firmware_fp;
mm_segment_t oldfs;
oldfs=get_fs();
set_fs(KERNEL_DS);
firmware_fp = filp_open("/data/local/tmp/ME571_IP_10.ekt", O_RDONLY, S_IRUSR |S_IRGRP);
if(PTR_ERR(firmware_fp) == -ENOENT){
touch_debug(DEBUG_ERROR, "open file error\n");
return;
}
PageNum=0;
firmware_fp->f_pos = 0;
for(pos = 0; pos < 500*132; pos += 132,PageNum++){
if(firmware_fp->f_op->read(firmware_fp, firmware + pos,
132, &firmware_fp->f_pos) != 132){
break;
}
}
touch_debug(DEBUG_INFO, "%s: PageNUM %d, Ver %x %x, ID %x %x\n",__func__,PageNum,firmware[34058],firmware[34059],firmware[34586],firmware[34587]);
set_fs(oldfs);
return;
}
*/
// For Firmware Update
int elan_iap_open(struct inode *inode, struct file *filp){
touch_debug(DEBUG_MESSAGES, "[ELAN]into elan_iap_open\n");
if (private_ts == NULL) touch_debug(DEBUG_ERROR,"private_ts is NULL\n");
return 0;
}
int elan_iap_release(struct inode *inode, struct file *filp){
return 0;
}
static ssize_t elan_iap_write(struct file *filp, const char *buff, size_t count, loff_t *offp){
int ret;
char *tmp;
touch_debug(DEBUG_MESSAGES, "[ELAN]into elan_iap_write\n");
#if 0
/*++++i2c transfer start+++++++*/
struct i2c_adapter *adap = private_ts->client->adapter;
struct i2c_msg msg;
/*++++i2c transfer end+++++++*/
#endif
if (count > 8192)
count = 8192;
tmp = kmalloc(count, GFP_KERNEL);
if (tmp == NULL)
return -ENOMEM;
if (copy_from_user(tmp, buff, count)) {
return -EFAULT;
}
/*++++i2c transfer start+++++++*/
#if 0
//down(&worklock);
msg.addr = file_fops_addr;
msg.flags = 0x00;// 0x00
msg.len = count;
msg.buf = (char *)tmp;
//up(&worklock);
ret = i2c_transfer(adap, &msg, 1);
#else
ret = i2c_master_send(private_ts->client, tmp, count);
#endif
/*++++i2c transfer end+++++++*/
//if (ret != count) printk("ELAN i2c_master_send fail, ret=%d \n", ret);
kfree(tmp);
//return ret;
return (ret == 1) ? count : ret;
}
ssize_t elan_iap_read(struct file *filp, char *buff, size_t count, loff_t *offp){
char *tmp;
int ret;
long rc;
touch_debug(DEBUG_MESSAGES,"[ELAN]into elan_iap_read\n");
#if 0
/*++++i2c transfer start+++++++*/
struct i2c_adapter *adap = private_ts->client->adapter;
struct i2c_msg msg;
/*++++i2c transfer end+++++++*/
#endif
if (count > 8192)
count = 8192;
tmp = kmalloc(count, GFP_KERNEL);
if (tmp == NULL)
return -ENOMEM;
/*++++i2c transfer start+++++++*/
#if 0
//down(&worklock);
msg.addr = file_fops_addr;
//msg.flags |= I2C_M_RD;
msg.flags = 0x00;
msg.flags |= I2C_M_RD;
msg.len = count;
msg.buf = tmp;
//up(&worklock);
ret = i2c_transfer(adap, &msg, 1);
#else
ret = i2c_master_recv(private_ts->client, tmp, count);
#endif
/*++++i2c transfer end+++++++*/
if (ret >= 0)
rc = copy_to_user(buff, tmp, count);
kfree(tmp);
//return ret;
return (ret == 1) ? count : ret;
}
static long elan_iap_ioctl( struct file *filp, unsigned int cmd, unsigned long arg){
int __user *ip = (int __user *)arg;
touch_debug(DEBUG_MESSAGES,"[ELAN]into elan_iap_ioctl\n");
touch_debug(DEBUG_MESSAGES,"cmd value %x\n",cmd);
switch (cmd) {
case IOCTL_I2C_SLAVE:
private_ts->client->addr = (int __user)arg;
//file_fops_addr = 0x10;
break;
case IOCTL_FW_INFO:
if(__fw_packet_handler(private_ts->client) < 0)
printk(KERN_ERR "[elan] IOCTL_FW_INFO, res < 0, __fw_packet_handler fail.\n");
break;
case IOCTL_MINOR_FW_VER:
break;
case IOCTL_RESET:
// modify
elan_ktf_ts_hw_reset();
break;
case IOCTL_IAP_MODE_LOCK:
if(work_lock==0)
{
work_lock=1;
disable_irq(private_ts->client->irq);
cancel_work_sync(&private_ts->work);
#if defined( ESD_CHECK )
cancel_delayed_work_sync( &esd_work );
#endif
}
break;
case IOCTL_IAP_MODE_UNLOCK:
if(work_lock==1)
{
work_lock=0;
enable_irq(private_ts->client->irq);
#if defined( ESD_CHECK ) //0604
queue_delayed_work( esd_wq, &esd_work, delay );
#endif
}
break;
case IOCTL_CHECK_RECOVERY_MODE:
return RECOVERY;
break;
case IOCTL_FW_VER:
//__fw_packet_handler(private_ts->client);
return FW_VERSION;
break;
case IOCTL_X_RESOLUTION:
//__fw_packet_handler(private_ts->client);
return X_RESOLUTION;
break;
case IOCTL_Y_RESOLUTION:
//__fw_packet_handler(private_ts->client);
return Y_RESOLUTION;
break;
case IOCTL_FW_ID:
//__fw_packet_handler(private_ts->client);
return FW_ID;
break;
case IOCTL_BC_VER:
return BC_VERSION;
break;
case IOCTL_ROUGH_CALIBRATE:
return elan_ktf_ts_calibrate(private_ts->client);
case IOCTL_I2C_INT:
put_user(gpio_get_value(private_ts->intr_gpio), ip);
break;
case IOCTL_RESUME:
//elan_ktf_ts_resume(private_ts->client);
break;
case IOCTL_POWER_LOCK:
power_lock=1;
break;
case IOCTL_POWER_UNLOCK:
power_lock=0;
break;
#ifdef IAP_PORTION
case IOCTL_GET_UPDATE_PROGREE:
update_progree=(int __user)arg;
break;
case IOCTL_FW_UPDATE:
//read_test();
//Update_FW_in_Driver(0);
Update_FW_One(0);
break;
#endif
#ifdef ELAN_2WIREICE
case IOCTL_2WIREICE:
elan_TWO_WIRE_ICE(private_ts->client);
break;
#endif
case IOCTL_CIRCUIT_CHECK:
return circuit_ver;
break;
default:
touch_debug(DEBUG_ERROR,"[elan] Un-known IOCTL Command %d\n", cmd);
break;
}
return 0;
}
struct file_operations elan_touch_fops = {
.open = elan_iap_open,
.write = elan_iap_write,
.read = elan_iap_read,
.release = elan_iap_release,
.unlocked_ioctl=elan_iap_ioctl,
};
#ifdef IAP_PORTION
int HID_EnterISPMode(struct i2c_client *client)
{
int len = 0;
int j;
uint8_t flash_key[37] = {0x04, 0x00, 0x23, 0x00, 0x03, 0x00, 0x04, 0x54, 0xc0, 0xe1, 0x5a};
uint8_t isp_cmd[37] = {0x04, 0x00, 0x23, 0x00, 0x03, 0x00, 0x04, 0x54, 0x00, 0x12, 0x34};
uint8_t check_addr[37] = {0x04, 0x00, 0x23, 0x00, 0x03, 0x00, 0x01, 0x10};
uint8_t buff[67] = {0};
len = i2c_master_send(private_ts->client, flash_key, 37);
if (len != 37) {
touch_debug(DEBUG_ERROR,"[elan] ERROR: Flash key fail! len=%d\r\n", len);
return -1;
}
else
touch_debug(DEBUG_MESSAGES,"[elan] FLASH key write data successfully! cmd = [%2x, %2x, %2x, %2x]\n", flash_key[7], flash_key[8], flash_key[9], flash_key[10]);
mdelay(20);
len = i2c_master_send(private_ts->client, isp_cmd, 37);
if (len != 37) {
touch_debug(DEBUG_ERROR,"[elan] ERROR: EnterISPMode fail! len=%d\r\n", len);
return -1;
}
else
touch_debug(DEBUG_MESSAGES,"[elan] IAPMode write data successfully! cmd = [%2x, %2x, %2x, %2x]\n", isp_cmd[7], isp_cmd[8], isp_cmd[9], isp_cmd[10]);
mdelay(20);
len = i2c_master_send(private_ts->client, check_addr, sizeof(check_addr));
if (len != sizeof(check_addr)) {
touch_debug(DEBUG_ERROR,"[elan] ERROR: Check Address fail! len=%d\r\n", len);
return -1;
}
else
touch_debug(DEBUG_MESSAGES,"[elan] Check Address write data successfully! cmd = [%2x, %2x, %2x, %2x]\n", check_addr[7], check_addr[8], check_addr[9], check_addr[10]);
mdelay(20);
len=i2c_master_recv(private_ts->client, buff, sizeof(buff));
if (len != sizeof(buff)) {
touch_debug(DEBUG_ERROR,"[elan] ERROR: Check Address Read Data error. len=%d \r\n", len);
return -1;
}
else {
printk("[Check Addr]: ");
for (j=0; j<37; j++)
printk("%x ", buff[j]);
printk("\n");
}
return 0;
}
int EnterISPMode(struct i2c_client *client)
{
int len = 0;
uint8_t isp_cmd[] = {0x45, 0x49, 0x41, 0x50}; //{0x45, 0x49, 0x41, 0x50};
len = i2c_master_send(private_ts->client, isp_cmd, 4);
if (len != 4) {
touch_debug(DEBUG_ERROR,"[elan] ERROR: EnterISPMode fail! len=%d\r\n", len);
return -1;
}
else
touch_debug(DEBUG_MESSAGES,"[elan] IAPMode write data successfully! cmd = [%2x, %2x, %2x, %2x]\n", isp_cmd[0], isp_cmd[1], isp_cmd[2], isp_cmd[3]);
return 0;
}
int ExtractPage(struct file *filp, uint8_t * szPage, int byte)
{
int len = 0;
len = filp->f_op->read(filp, szPage,byte, &filp->f_pos);
if (len != byte)
{
touch_debug(DEBUG_ERROR,"[elan] %s: read page error, read error. len=%d\r\n", __func__, len);
return -1;
}
return 0;
}
int WritePage(const u8 * szPage, int byte)
{
int len = 0;
len = i2c_master_send(private_ts->client, szPage, byte);
if (len != byte)
{
touch_debug(DEBUG_ERROR,"[elan] %s: write page error, write error. len=%d\r\n", __func__, len);
return -1;
}
return 0;
}
int GetAckData(struct i2c_client *client)
{
int rc = 0;
uint8_t buff[67] = {0};
#ifdef ELAN_HID_I2C
rc = elan_ktf_ts_poll(client);
#endif
rc = i2c_master_recv(private_ts->client, buff, sizeof(buff));
if (rc != sizeof(buff)) {
touch_debug(DEBUG_ERROR,"[elan] %s: Read ACK Data error. rc=%d\r\n", __func__, rc);
return -1;
}
touch_debug(DEBUG_MESSAGES, "[elan] %s: %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x\n",__func__,buff[0],buff[1],buff[2],buff[3],buff[4],buff[5],buff[6],buff[7],buff[8],buff[9],buff[10],buff[11]);
#ifndef ELAN_HID_I2C
if (buff[0] == 0xaa && buff[1] == 0xaa)
return ACK_OK;
else if (buff[0] == 0x55 && buff[1] == 0x55)
return ACK_REWRITE;
else
return ACK_Fail;
#endif
return 0;
}
void print_progress(int page, int ic_num, int j)
{
int i, percent,page_tatol=351,percent_tatol;
char str[256];
str[0] = '\0';
for (i=0; i<((page)/10); i++) {
str[i] = '#';
str[i+1] = '\0';
}
/*
page_tatol=page+PageNum*(ic_num-j);
percent = ((100*page)/(PageNum));
percent_tatol = ((100*page_tatol)/(PageNum*ic_num));
*/
percent = ((100*page)/(PageNum));
if ((page) == (PageNum))
percent = 100;
if ((page_tatol) == (PageNum*ic_num))
percent_tatol = 100;
touch_debug(DEBUG_INFO, "\r[elan]progress %s| %d %d", str, percent,page);
if (page == (PageNum))
touch_debug(DEBUG_INFO, "\n");
}
/* fw_source = 0: update fw_data.i compile with driver code
fw_source = 1: update fw at /system/etc/firmware/ElanFW.fw
fw_source = 2: update ekt file at /data/local/tmp/ElanFW.ekt */
static int Update_FW_One(int fw_source)
{
int res = 0,ic_num = 1;
int iPage = 0, rewriteCnt = 0; //rewriteCnt for PAGE_REWRITE
int i = 0;
uint8_t data;
//struct timeval tv1, tv2;
// for open user space file
int pos=0;
struct file *firmware_fp;
mm_segment_t oldfs;
uint8_t boot_buffer[4] = {0};
int byte_count = 0;
const uint8_t *szBuff = NULL;
int curIndex;
const struct firmware *p_fw_entry;
const u8 *fw_data;
int rc, fw_size;
mutex_lock(&ktf_mutex);
touch_debug(DEBUG_INFO, "[elan] %s: Update FW\n", __func__);
IAP_RESTART:
curIndex=0;
data=I2C_DATA[0];//Master
touch_debug(DEBUG_INFO, "[elan] %s: address data=0x%x \r\n", __func__, data);
if(RECOVERY != 0x80)
{
touch_debug(DEBUG_MESSAGES, "[elan] Firmware upgrade normal mode !\n");
} else
touch_debug(DEBUG_MESSAGES, "[elan] Firmware upgrade recovery mode !\n");
/*Send enter bootcode cmd*/
elan_ktf_ts_hw_reset();
mdelay(13);
res = EnterISPMode(private_ts->client); //enter ISP mode
//elan_ktf_ts_poll(private_ts->client);
mdelay(100);
/*check enter bootcode cmd*/
res = i2c_master_recv(private_ts->client, boot_buffer, 4); //55 aa 33 cc
touch_debug(DEBUG_MESSAGES, "[elan] %s :%x,%x,%x,%x\n",__func__,boot_buffer[0],boot_buffer[1],boot_buffer[2],boot_buffer[3]);
/* Send Dummy Byte */
res = i2c_master_send(private_ts->client, &data, sizeof(data));
if(res!=sizeof(data))
{
touch_debug(DEBUG_ERROR, "[elan] dummy error code = %d\n",res);
}
else
touch_debug(DEBUG_ERROR, "[elan] Send Dummy Byte Success!!\n");
/*check fw_source: 0 = fw_data.i; 1 = request_fw at /system; 2 = /data/local/tmp*/
if(fw_source == 1) { //use request firmware at /system/etc/firmware/
touch_debug(DEBUG_INFO, "[elan] request_firmware name = %s\n",ELAN_FW_FILENAME);
rc = request_firmware(&p_fw_entry, ELAN_FW_FILENAME, &private_ts->client->dev);
if (rc != 0) {
touch_debug(DEBUG_ERROR,"[elan] rc=%d, request_firmware fail\n", rc);
return -1;
}
else
printk(KERN_DEBUG "[elan] Request Firmware Size=%zu\n", p_fw_entry->size);
fw_data = p_fw_entry->data;
fw_size = p_fw_entry->size;
PageNum = (fw_size/sizeof(uint8_t)/PageSize);
}
else if(fw_source == 2) { //use request firmware at /data/local/tmp
printk(KERN_DEBUG "[elan] Update Firmware from /data/local/tmp/ElanFW.ekt\n");
oldfs=get_fs();
set_fs(KERNEL_DS);
firmware_fp = filp_open("/data/local/tmp/ElanFW.ekt", O_RDONLY, S_IRUSR |S_IRGRP);
if(PTR_ERR(firmware_fp) == -ENOENT) {
touch_debug(DEBUG_ERROR, "[elan] open file error.\n");
return -1;
} else
touch_debug(DEBUG_ERROR, "[elan] open file success.\n");
PageNum=0;
firmware_fp->f_pos = 0;
for(pos = 0; pos < 1000*132; pos += 132,PageNum++) {
if(firmware_fp->f_op->read(firmware_fp, firmware + pos, 132, &firmware_fp->f_pos) != 132) {
break;
}
//touch_debug(DEBUG_ERROR, "[elan]pos = %d, PageNum = %d\n", pos, PageNum);
}
fw_data = firmware;
//touch_debug(DEBUG_INFO, "[elan]%s: PageNUM %d, FW_Ver %x %x, FW_ID %x %x\n",__func__,PageNum,firmware[34058],firmware[34059],firmware[34586],firmware[34587]);
touch_debug(DEBUG_INFO, "[elan]%s: ekt's PageNUM = %d, \n",__func__, PageNum);
set_fs(oldfs);
filp_close(firmware_fp, NULL);
/*test*/
//touch_debug(DEBUG_INFO, "[elan]%s: test3, return 1\n",__func__);
//mutex_unlock(&ktf_mutex);
//return 1;
}
else { //use fw_data.i
printk(KERN_DEBUG "[elan] Update Firmware by fw_data.i\n");
PageNum = (sizeof(file_fw_data)/sizeof(uint8_t)/PageSize);
fw_data = file_fw_data;
}
printk(KERN_DEBUG "[elan] PageNum = %d.\n", PageNum);
/*end check firmware*/
/* Start IAP*/
for( iPage = 1; iPage <= PageNum; iPage++ )
{
#if 1 // 8byte mode
// 8 bytes
//szBuff = fw_data + ((iPage-1) * PageSize);
for(byte_count=1; byte_count<=17; byte_count++)
{
//touch_debug(DEBUG_INFO, "[elan] byte %d, curIndex = %d\n", byte_count, curIndex );
szBuff = fw_data + curIndex;
if(byte_count!=17)
{
//printk("curIndex =%d\n",curIndex);
curIndex = curIndex + 8;
//ioctl(fd, IOCTL_IAP_MODE_LOCK, data);
res = WritePage(szBuff, 8);
}
else
{
//printk("curIndex =%d\n",curIndex);
curIndex = curIndex + 4;
//ioctl(fd, IOCTL_IAP_MODE_LOCK, data);
res = WritePage(szBuff, 4);
}
} // end of for(byte_count=1;byte_count<=17;byte_count++)
#endif
#if 0 // 132byte mode
//szBuff = fw_data + curIndex;
//szBuff = firmware + curIndex;
szBuff = fw_data + curIndex;
curIndex = curIndex + PageSize;
res = WritePage(szBuff, PageSize);
#endif
#if 1 //if use old bootcode
if(iPage==PageNum || iPage==1)
{
mdelay(600);
}
else
{
mdelay(50);
}
#endif
res = GetAckData(private_ts->client);
if (ACK_OK != res)
{
mdelay(50);
touch_debug(DEBUG_ERROR, "[elan] ERROR: GetAckData fail! res=%d\r\n", res);
rewriteCnt = rewriteCnt + 1;
if (rewriteCnt == PAGERETRY)
{
touch_debug(DEBUG_ERROR, "[elan] %dth page ReWrite %d times fails!\n", iPage, PAGERETRY);
mutex_unlock(&ktf_mutex);
return E_FD;
}
else
{
touch_debug(DEBUG_ERROR, "[elan] %d page ReWrite %d times!\n", iPage, rewriteCnt);
goto IAP_RESTART;
}
}
else
{
rewriteCnt = 0;
print_progress(iPage,ic_num,i);
if (iPage == PageNum)
touch_debug(DEBUG_ERROR, "[elan] %s Firmware Update Successfully!\n", __func__);
}
} // end of for(iPage = 1; iPage <= PageNum; iPage++)
elan_ktf_ts_hw_reset(); //20160114 added, to reset ic
mdelay(100);
RECOVERY=0;
res = __hello_packet_handler(private_ts->client);
if(res == 0x80)
touch_debug(DEBUG_ERROR, "[elan] Recovery mode! res = %02x.\n", res);
else
touch_debug(DEBUG_ERROR, "[elan] hello_packet_handler() res = %d.\n", res);
res = __fw_packet_handler(private_ts->client);
if (res < 0)
touch_debug(DEBUG_ERROR, "[elan] res = %d, Get Firmware information error, maybe received by system interrupt!\n", res);
touch_debug(DEBUG_ERROR, "[elan] fw_update end.\n");
mutex_unlock(&ktf_mutex);
return res; /* 0:sucessfully, 0x80: Recovery, -1: No response */
}
#if 0
static int Update_FW_in_Driver(void *x)
{
int res = 0,ic_num = 1;
int iPage = 0, rewriteCnt = 0; //rewriteCnt for PAGE_REWRITE
int i = 0;
uint8_t data;
//struct timeval tv1, tv2;
uint8_t boot_buffer[4] = {0};
//int byte_count;
uint8_t *szBuff = NULL;
int curIndex = 0;
mutex_lock(&ktf_mutex);
touch_debug(DEBUG_INFO, "[elan] %s: Update FW\n", __func__);
IAP_RESTART:
curIndex=0;
data=I2C_DATA[0];//Master
touch_debug(DEBUG_INFO, "[elan] %s: address data=0x%x \r\n", __func__, data);
if(RECOVERY != 0x80)
{
touch_debug(DEBUG_MESSAGES, "[elan] Firmware upgrade normal mode !\n");
} else
touch_debug(DEBUG_MESSAGES, "[elan] Firmware upgrade recovery mode !\n");
/*Send enter bootcode cmd*/
elan_ktf_ts_hw_reset();
mdelay(13);
res = EnterISPMode(private_ts->client); //enter ISP mode
//elan_ktf_ts_poll(private_ts->client);
mdelay(100);
/*check enter bootcode cmd*/
res = i2c_master_recv(private_ts->client, boot_buffer, 4); //55 aa 33 cc
touch_debug(DEBUG_MESSAGES, "[elan] %s :%x,%x,%x,%x\n",__func__,boot_buffer[0],boot_buffer[1],boot_buffer[2],boot_buffer[3]);
/* Send Dummy Byte */
res = i2c_master_send(private_ts->client, &data, sizeof(data));
if(res!=sizeof(data))
{
touch_debug(DEBUG_ERROR, "[elan] dummy error code = %d\n",res);
}
else
touch_debug(DEBUG_ERROR, "[elan] Send Dummy Byte Success!!\n");
/* Start IAP*/
for( iPage = 1; iPage <= PageNum; iPage++ )
{
#if 0 // 8byte mode
// 8 bytes
//szBuff = fw_data + ((iPage-1) * PageSize);
for(byte_count=1;byte_count<=17;byte_count++)
{
if(byte_count!=17)
{
// printk("[ELAN] byte %d\n",byte_count);
// printk("curIndex =%d\n",curIndex);
szBuff = file_fw_data + curIndex;
curIndex = curIndex + 8;
//ioctl(fd, IOCTL_IAP_MODE_LOCK, data);
res = WritePage(szBuff, 8);
}
else
{
// printk("byte %d\n",byte_count);
// printk("curIndex =%d\n",curIndex);
szBuff = file_fw_data + curIndex;
curIndex = curIndex + 4;
//ioctl(fd, IOCTL_IAP_MODE_LOCK, data);
res = WritePage(szBuff, 4);
}
} // end of for(byte_count=1;byte_count<=17;byte_count++)
#endif
#if 1 // 132byte mode
//szBuff = file_fw_data + curIndex;
szBuff = firmware + curIndex;
curIndex = curIndex + PageSize;
res = WritePage(szBuff, PageSize);
#endif
#if 1 //if use old bootcode
if(iPage==PageNum || iPage==1)
{
mdelay(600);
}
else
{
mdelay(50);
}
#endif
res = GetAckData(private_ts->client);
if (ACK_OK != res)
{
mdelay(50);
touch_debug(DEBUG_ERROR, "[ELAN] ERROR: GetAckData fail! res=%d\r\n", res);
rewriteCnt = rewriteCnt + 1;
if (rewriteCnt == PAGERETRY)
{
touch_debug(DEBUG_ERROR, "[ELAN] %dth page ReWrite %d times fails!\n", iPage, PAGERETRY);
mutex_unlock(&ktf_mutex);
return E_FD;
}
else
{
touch_debug(DEBUG_ERROR, "[ELAN] %d page ReWrite %d times!\n", iPage, rewriteCnt);
goto IAP_RESTART;
}
}
else
{
print_progress(iPage,ic_num,i);
}
} // end of for(iPage = 1; iPage <= PageNum; iPage++)
RECOVERY=0;
res= __hello_packet_handler(private_ts->client);
if (res > 0)
touch_debug(DEBUG_ERROR, "[ELAN] Update ALL Firmware successfully!\n");
mutex_unlock(&ktf_mutex);
return res; /* 0:sucessfully, 0x80: Recovery, -1: No response */
}
#endif
#endif
// End Firmware Update
// Star 2wireIAP which used I2C to simulate JTAG function
#ifdef ELAN_2WIREICE
static uint8_t file_bin_data[] = {
//#include "2wireice.i"
};
int write_ice_status=0;
int shift_out_16(struct i2c_client *client){
int res;
uint8_t buff[] = {0xbb,0xbb,0xbb,0xbb,0xbb,0xbb,0xbb,0xbb,0xbf,0xff};
res = i2c_master_send(client, buff, sizeof(buff));
return res;
}
int tms_reset(struct i2c_client *client){
int res;
uint8_t buff[] = {0xff,0xff,0xff,0xbf};
res = i2c_master_send(client, buff, sizeof(buff));
return res;
}
int mode_gen(struct i2c_client *client){
int res;
int retry = 5;
uint8_t buff[] = {0xff,0xff,0xff,0x31,0xb7,0xb7,0x7b,0xb7,0x7b,0x7b,0xb7,0x7b,0xf3,0xbb,0xbb,0xbb,0xbb,0xbb,0xbb,0xbb,0xbb,0xf1};
uint8_t buff_1[] = {0x2a,0x6a,0xa6,0xa6,0x6e};
char mode_buff[2]={0};
do {
res = i2c_master_send(client, buff, sizeof(buff));
if (res != sizeof(buff)) {
touch_debug(DEBUG_ERROR,"[ELAN] ERROR: mode_gen write buff error, write error. res=%d\r\n", res);
}
else{
touch_debug(DEBUG_MESSAGES,"[ELAN] mode_gen write buff successfully.\r\n");
break;
}
mdelay(20);
retry -=1;
} while(retry);
res = i2c_master_recv(client, mode_buff, sizeof(mode_buff));
if (res != sizeof(mode_buff)) {
touch_debug(DEBUG_ERROR,"[ELAN] ERROR: mode_gen read data error, write error. res=%d\r\n", res);
return -1;
}
else
touch_debug(DEBUG_MESSAGES,"[ELAN] mode gen read successfully(a6 59)! buff[0]=0x%x buff[1]=0x%x \r\n", mode_buff[0], mode_buff[1]);
res = i2c_master_send(client, buff_1, sizeof(buff_1));
if (res != sizeof(buff_1)) {
touch_debug(DEBUG_ERROR,"[ELAN] ERROR: mode_gen write buff_1 error. res=%d\r\n", res);
return -1;
}
return res;
}
int word_scan_out(struct i2c_client *client){
int res;
uint8_t buff[] = {0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x26,0x66};
res = i2c_master_send(client, buff, sizeof(buff));
return res;
}
int long_word_scan_out(struct i2c_client *client){
int res;
uint8_t buff[] = {0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x26,0x66};
res = i2c_master_send(client, buff, sizeof(buff));
return res;
}
int bit_manipulation(int TDI, int TMS, int TCK, int TDO,int TDI_1, int TMS_1, int TCK_1, int TDO_1){
int res;
res= ((TDI<<3 |TMS<<2 |TCK |TDO)<<4) |(TDI_1<<3 |TMS_1<<2 |TCK_1 |TDO_1);
return res;
}
int ins_write(struct i2c_client *client, uint8_t buf){
int res=0;
int length=13;
uint8_t write_buf[7]={0};
int TDI_bit[13]={0};
int TMS_bit[13]={0};
int i=0;
uint8_t buf_rev=0;
int TDI=0, TMS=0, TCK=0,TDO=0;
int bit_tdi, bit_tms;
int len;
for(i=0;i<8;i++)
{
buf_rev = buf_rev | (((buf >> i) & 0x01) << (7-i));
}
TDI = (0x7<<10) | buf_rev <<2 |0x00;
TMS = 0x1007;
TCK=0x2;
TDO=1;
for ( len=0; len<=length-1; len++){
bit_tdi = TDI & 0x1;
bit_tms = TMS & 0x1;
TDI_bit[length-1-len] =bit_tdi;
TMS_bit[length-1-len] = bit_tms;
TDI = TDI >>1;
TMS = TMS >>1;
}
for (len=0;len<=length-1;len=len+2){
if (len == length-1 && len%2 ==0)
res = bit_manipulation(TDI_bit[len], TMS_bit[len], TCK, TDO, 0, 0, 0, 0);
else
res = bit_manipulation(TDI_bit[len], TMS_bit[len], TCK, TDO, TDI_bit[len+1], TMS_bit[len+1], TCK, TDO);
write_buf[len/2] = res;
}
res = i2c_master_send(client, write_buf, sizeof(write_buf));
return res;
}
int word_scan_in(struct i2c_client *client, uint16_t buf){
int res=0;
uint8_t write_buf[10]={0};
int TDI_bit[20]={0};
int TMS_bit[20]={0};
int TDI = buf <<2 |0x00;
int TMS = 0x7;
int TCK=0x2;
int TDO=1;
int bit_tdi, bit_tms;
int len;
for ( len=0; len<=19; len++){ //length =20
bit_tdi = TDI & 0x1;
bit_tms = TMS & 0x1;
TDI_bit[19-len] =bit_tdi;
TMS_bit[19-len] = bit_tms;
TDI = TDI >>1;
TMS = TMS >>1;
}
for (len=0;len<=19;len=len+2){
if (len == 19 && len%2 ==0)
res = bit_manipulation(TDI_bit[len], TMS_bit[len], TCK, TDO, 0,0,0,0);
else
res = bit_manipulation(TDI_bit[len], TMS_bit[len], TCK, TDO, TDI_bit[len+1], TMS_bit[len+1], TCK, TDO);
write_buf[len/2] = res;
}
res = i2c_master_send(client, write_buf, sizeof(write_buf));
return res;
}
int long_word_scan_in(struct i2c_client *client, int buf_1, int buf_2){
uint8_t write_buf[18]={0};
uint8_t TDI_bit[36]={0};
uint8_t TMS_bit[36]={0};
int TDI_1 = buf_1;
int TDI_2 = (buf_2<<2) |0x00;
int TMS = 0x7;
int TCK=0x2;
int TDO=1;
int bit_tdi, bit_tms;
int len=0;
int res=0;
for ( len=0; len<=35; len++){ //length =36
if(len<18)
{
bit_tdi = TDI_2 & 0x1;
}
else
{
bit_tdi = TDI_1 & 0x1;
}
bit_tms = TMS & 0x1;
TDI_bit[35-len] =bit_tdi;
TMS_bit[35-len] = bit_tms;
if(len<18)
{
TDI_2 = TDI_2 >>1;
}
else
{
TDI_1 = TDI_1 >>1;
}
TMS = TMS >>1;
bit_tdi=0;
bit_tms=0;
}
for (len=0;len<=35;len=len+2){
if (len == 35 && len%2 ==0)
res = bit_manipulation(TDI_bit[len], TMS_bit[len], TCK, TDO, 0,0,0,1);
else
res = bit_manipulation(TDI_bit[len], TMS_bit[len], TCK, TDO, TDI_bit[len+1], TMS_bit[len+1], TCK, TDO);
write_buf[len/2] = res;
}
res = i2c_master_send(client, write_buf, sizeof(write_buf));
return res;
}
uint16_t trimtable[8]={0};
int Read_SFR(struct i2c_client *client, int open){
uint8_t voltage_recv[2]={0};
int count, ret;
//uint16_t address_1[8]={0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007};
ins_write(client, 0x6f); // IO write
long_word_scan_in(client, 0x007e, 0x0020);
long_word_scan_in(client, 0x007f, 0x4000);
long_word_scan_in(client, 0x007e, 0x0023);
long_word_scan_in(client, 0x007f, 0x8000);
// 0
ins_write(client, 0x6f); //IO Write
long_word_scan_in(client, 0x007f, 0x9002); //TM=2h
ins_write(client, 0x68); //Program Memory Sequential Read
word_scan_in(client, 0x0000); //set Address 0x0000
shift_out_16(client); //move data to I2C buf
mdelay(10);
count = 0;
ret = i2c_master_recv(client, voltage_recv, sizeof(voltage_recv));
if (ret != sizeof(voltage_recv)) {
touch_debug(DEBUG_ERROR,"[ELAN] %s: read data error. ret=%d\r\n", __func__, ret);
return -1;
}
else
{
trimtable[count]=voltage_recv[0]<<8 | voltage_recv[1];
touch_debug(DEBUG_MESSAGES,"[ELAN] read data successfully! voltage_recv buff[0]=0x%x buff[1]=0x%x trimtable[%d]=0x%x\r\n", voltage_recv[0], voltage_recv[1], count, trimtable[count]);
}
// 1
ins_write(client, 0x6f); // IO write
long_word_scan_in(client, 0x007e, 0x0020);
long_word_scan_in(client, 0x007f, 0x4000);
long_word_scan_in(client, 0x007e, 0x0023);
long_word_scan_in(client, 0x007f, 0x8000);
ins_write(client, 0x6f);
long_word_scan_in(client, 0x007f, 0x9002);
ins_write(client, 0x68);
word_scan_in(client, 0x0001);
shift_out_16(client);
mdelay(1);
count=1;
ret = i2c_master_recv(client, voltage_recv, sizeof(voltage_recv));
if (ret != sizeof(voltage_recv)) {
touch_debug(DEBUG_ERROR,"[ELAN] %s: read data error. ret=%d\r\n", __func__, ret);
return -1;
}
else
{
trimtable[count]=voltage_recv[0]<<8 | voltage_recv[1];
touch_debug(DEBUG_MESSAGES,"[ELAN] read data successfully! voltage_recv buff[0]=0x%x buff[1]=0x%x trimtable[%d]=0x%x\r\n", voltage_recv[0], voltage_recv[1], count, trimtable[count]);
}
// 2
ins_write(client, 0x6f); // IO write
long_word_scan_in(client, 0x007e, 0x0020);
long_word_scan_in(client, 0x007f, 0x4000);
long_word_scan_in(client, 0x007e, 0x0023);
long_word_scan_in(client, 0x007f, 0x8000);
ins_write(client, 0x6f);
long_word_scan_in(client, 0x007f, 0x9002);
ins_write(client, 0x68);
word_scan_in(client, 0x0002);
shift_out_16(client);
mdelay(1);
count=2;
ret = i2c_master_recv(client, voltage_recv, sizeof(voltage_recv));
if (ret != sizeof(voltage_recv)) {
touch_debug(DEBUG_ERROR,"[ELAN] %s: read data error. ret=%d\r\n", __func__, ret);
return -1;
}
else
{
trimtable[count]=voltage_recv[0]<<8 | voltage_recv[1];
touch_debug(DEBUG_MESSAGES,"[ELAN] read data successfully! voltage_recv buff[0]=0x%x buff[1]=0x%x trimtable[%d]=0x%x\r\n", voltage_recv[0], voltage_recv[1], count, trimtable[count]);
}
// 3
ins_write(client, 0x6f); // IO write
long_word_scan_in(client, 0x007e, 0x0020);
long_word_scan_in(client, 0x007f, 0x4000);
long_word_scan_in(client, 0x007e, 0x0023);
long_word_scan_in(client, 0x007f, 0x8000);
ins_write(client, 0x6f);
long_word_scan_in(client, 0x007f, 0x9002);
ins_write(client, 0x68);
word_scan_in(client, 0x0003);
shift_out_16(client);
mdelay(1);
count=3;
ret = i2c_master_recv(client, voltage_recv, sizeof(voltage_recv));
if (ret != sizeof(voltage_recv)) {
touch_debug(DEBUG_ERROR,"[ELAN] %s: read data error. ret=%d\r\n", __func__, ret);
return -1;
}
else
{
trimtable[count]=voltage_recv[0]<<8 | voltage_recv[1];
touch_debug(DEBUG_MESSAGES,"[ELAN] read data successfully! voltage_recv buff[0]=0x%x buff[1]=0x%x trimtable[%d]=0x%x\r\n", voltage_recv[0], voltage_recv[1], count, trimtable[count]);
}
// 4
ins_write(client, 0x6f); // IO write
long_word_scan_in(client, 0x007e, 0x0020);
long_word_scan_in(client, 0x007f, 0x4000);
long_word_scan_in(client, 0x007e, 0x0023);
long_word_scan_in(client, 0x007f, 0x8000);
ins_write(client, 0x6f);
long_word_scan_in(client, 0x007f, 0x9002);
ins_write(client, 0x68);
word_scan_in(client, 0x0004);
shift_out_16(client);
mdelay(1);
count=4;
ret = i2c_master_recv(client, voltage_recv, sizeof(voltage_recv));
if (ret != sizeof(voltage_recv)) {
touch_debug(DEBUG_ERROR,"[ELAN] %s: read data error. ret=%d\r\n", __func__, ret);
return -1;
}
else
{
trimtable[count]=voltage_recv[0]<<8 | voltage_recv[1];
touch_debug(DEBUG_MESSAGES,"[ELAN] read data successfully! voltage_recv buff[0]=0x%x buff[1]=0x%x trimtable[%d]=0x%x\r\n", voltage_recv[0], voltage_recv[1], count, trimtable[count]);
}
// 5
ins_write(client, 0x6f); // IO write
long_word_scan_in(client, 0x007e, 0x0020);
long_word_scan_in(client, 0x007f, 0x4000);
long_word_scan_in(client, 0x007e, 0x0023);
long_word_scan_in(client, 0x007f, 0x8000);
ins_write(client, 0x6f);
long_word_scan_in(client, 0x007f, 0x9002);
ins_write(client, 0x68);
word_scan_in(client, 0x0005);
shift_out_16(client);
mdelay(1);
count=5;
ret = i2c_master_recv(client, voltage_recv, sizeof(voltage_recv));
if (ret != sizeof(voltage_recv)) {
touch_debug(DEBUG_ERROR,"[ELAN] %s: read data error. ret=%d\r\n", __func__, ret);
return -1;
}
else
{
trimtable[count]=voltage_recv[0]<<8 | voltage_recv[1];
touch_debug(DEBUG_MESSAGES,"[ELAN] read data successfully! voltage_recv buff[0]=0x%x buff[1]=0x%x trimtable[%d]=0x%x\r\n", voltage_recv[0], voltage_recv[1], count, trimtable[count]);
}
// 6
ins_write(client, 0x6f); // IO write
long_word_scan_in(client, 0x007e, 0x0020);
long_word_scan_in(client, 0x007f, 0x4000);
long_word_scan_in(client, 0x007e, 0x0023);
long_word_scan_in(client, 0x007f, 0x8000);
ins_write(client, 0x6f);
long_word_scan_in(client, 0x007f, 0x9002);
ins_write(client, 0x68);
word_scan_in(client, 0x0006);
shift_out_16(client);
mdelay(1);
count=6;
ret = i2c_master_recv(client, voltage_recv, sizeof(voltage_recv));
if (ret != sizeof(voltage_recv)) {
touch_debug(DEBUG_ERROR,"[ELAN] %s: read data error. ret=%d\r\n", __func__, ret);
return -1;
}
else
{
trimtable[count]=voltage_recv[0]<<8 | voltage_recv[1];
touch_debug(DEBUG_MESSAGES,"[ELAN] read data successfully! voltage_recv buff[0]=0x%x buff[1]=0x%x trimtable[%d]=0x%x\r\n", voltage_recv[0], voltage_recv[1], count, trimtable[count]);
}
// 7
ins_write(client, 0x6f); // IO write
long_word_scan_in(client, 0x007e, 0x0020);
long_word_scan_in(client, 0x007f, 0x4000);
long_word_scan_in(client, 0x007e, 0x0023);
long_word_scan_in(client, 0x007f, 0x8000);
ins_write(client, 0x6f);
long_word_scan_in(client, 0x007f, 0x9002);
ins_write(client, 0x68);
word_scan_in(client, 0x0007);
shift_out_16(client);
mdelay(1);
count=7;
ret = i2c_master_recv(client, voltage_recv, sizeof(voltage_recv));
if (ret != sizeof(voltage_recv)) {
touch_debug(DEBUG_ERROR,"[ELAN] %s: read data error. ret=%d\r\n", __func__, ret);
return -1;
}
if (open == 1)
trimtable[count]=voltage_recv[0]<<8 | (voltage_recv[1] & 0xbf);
else
trimtable[count]=voltage_recv[0]<<8 | (voltage_recv[1] | 0x40);
touch_debug(DEBUG_ERROR,"[ELAN] Open_High_Voltage recv voltage_recv buff[0]=%x buff[1]=%x, trimtable[%d]=%x \n", voltage_recv[0],voltage_recv[1], count, trimtable[count]);
ins_write(client, 0x6f);
long_word_scan_in(client, 0x007f, 0x8000);
/*
for (count =0; count <8; count++){
ins_write(client, 0x6f); // IO write
long_word_scan_in(client, 0x007e, 0x0020);
long_word_scan_in(client, 0x007f, 0x4000);
long_word_scan_in(client, 0x007e, 0x0023);
long_word_scan_in(client, 0x007f, 0x8000);
ins_write(client, 0x6f);
long_word_scan_in(client, 0x007f, 0x9002);
ins_write(client, 0x68);
word_scan_in(client, address_1[count]);
shift_out_16(client);
mdelay(10);
//count=6;
ret = i2c_master_recv(client, voltage_recv, sizeof(voltage_recv));
trimtable[count]=voltage_recv[0]<<8 | voltage_recv[1];
printk("[elan] Open_High_Voltage recv -1 1word =%x %x, trimtable[%d]=%x \n", voltage_recv[0],voltage_recv[1], count, trimtable[count]);
}
ins_write(client, 0x6f);
long_word_scan_in(client, 0x007f, 0x8000);
*/
return 0;
}
int Write_SFR_2k(struct i2c_client *client, int open){
//set page 1
ins_write(client, 0x6f);
long_word_scan_in(client, 0x0001, 0x0100);
if(open==1)
{
//set HV enable
touch_debug(DEBUG_MESSAGES,"%s set HV enable\n",__func__);
ins_write(client, 0x6f);
long_word_scan_in(client, 0x0050, 0xc041);
}
else
{
//set HV disable
touch_debug(DEBUG_MESSAGES,"%s set HV disable\n",__func__);
ins_write(client, 0x6f);
long_word_scan_in(client, 0x0050, 0xc040);
}
return 0;
}
int Write_SFR(struct i2c_client *client){
ins_write(client, 0x6f);
long_word_scan_in(client, 0x007f, 0x9001);
ins_write(client, 0x66); // Program Memory Write
long_word_scan_in(client, 0x0000, trimtable[0]);
ins_write(client, 0xfd); //Set up the initial addr for sequential access
word_scan_in(client,0x7f);
ins_write(client, 0x66);
long_word_scan_in(client, 0x0001, trimtable[1]);
ins_write(client, 0xfd);
word_scan_in(client,0x7f);
ins_write(client, 0x66);
long_word_scan_in(client, 0x0002, trimtable[2]);
ins_write(client, 0xfd);
word_scan_in(client,0x7f);
ins_write(client, 0x66);
long_word_scan_in(client, 0x0003, trimtable[3]);
ins_write(client, 0xfd);
word_scan_in(client,0x7f);
ins_write(client, 0x66);
long_word_scan_in(client, 0x0004, trimtable[4]);
ins_write(client, 0xfd);
word_scan_in(client,0x7f);
ins_write(client, 0x66);
long_word_scan_in(client, 0x0005, trimtable[5]);
ins_write(client, 0xfd);
word_scan_in(client,0x7f);
ins_write(client, 0x66);
long_word_scan_in(client, 0x0006, trimtable[6]);
ins_write(client, 0xfd);
word_scan_in(client,0x7f);
ins_write(client, 0x66);
long_word_scan_in(client, 0x0007, trimtable[7]);
ins_write(client, 0xfd);
word_scan_in(client,0x7f);
ins_write(client, 0x6f);
long_word_scan_in(client, 0x7f, 0x8000);
/*
for (count=0;count<8;count++){
ins_write(client, 0x66);
long_word_scan_in(client, 0x0000+count, trimtable[count]);
}
*/
return 0;
}
int Enter_Mode(struct i2c_client *client){
mode_gen(client);
tms_reset(client);
ins_write(client,0xfc); //system reset
tms_reset(client);
return 0;
}
int Open_High_Voltage(struct i2c_client *client, int open){
#ifdef EKTF3K_FLASH
Read_SFR(client, open);
Write_SFR(client);
Read_SFR(client, open);
#endif
Write_SFR_2k(client, open);
return 0;
}
int Mass_Erase(struct i2c_client *client){
char mass_buff[4]={0};
char mass_buff_1[2]={0};
int ret, finish=0, i=0;
touch_debug(DEBUG_MESSAGES,"[Elan] Mass_Erase!!!!\n");
ins_write(client,0x01); //id code read
mdelay(2);
long_word_scan_out(client);
ret = i2c_master_recv(client, mass_buff, sizeof(mass_buff));
touch_debug(DEBUG_MESSAGES,"[elan] Mass_Erase mass_buff=%x %x %x %x(c0 08 01 00)\n", mass_buff[0],mass_buff[1],mass_buff[2],mass_buff[3]); //id: c0 08 01 00
/* / add for test
ins_write(client, 0xf3);
word_scan_out(client);
ret = i2c_master_recv(client, mass_buff_1, sizeof(mass_buff_1));
printk("[elan] Mass_Erase mass_buff_1=%x %x(a0 00)\n", mass_buff_1[0],mass_buff_1[1]); // a0 00 : stop
//add for test
//read low->high 5th bit
ins_write(client, 0x6f);
long_word_scan_in(client, 0x007e, 0x0020);
long_word_scan_in(client, 0x007f, 0x4000);
// add for test
ins_write(client, 0xf3);
word_scan_out(client);
ret = i2c_master_recv(client, mass_buff_1, sizeof(mass_buff_1));
printk("[elan] Mass_Erase (II) mass_buff_1=%x %x(40 00)\n", mass_buff_1[0],mass_buff_1[1]); // 40 00
//add for test
mdelay(10); //for malata
*/
ins_write(client,0x6f); //IO Write
/*add by herman*/
long_word_scan_in(client,0x007e,0x0020);
long_word_scan_in(client,0x007f,0x4000);//orig 4000
long_word_scan_in(client,0x007e,0x0023);
long_word_scan_in(client,0x007f,0x8000);
ins_write(client,0x6f);
long_word_scan_in(client,0x007f,0x9040);
ins_write(client,0x66); //Program data Write
long_word_scan_in(client, 0x0000,0x8765);//change by herman
ins_write(client,0x6f); //IO Write
long_word_scan_in(client, 0x007f,0x8000); //clear flash control PROG
ins_write(client,0xf3);
while (finish==0){
word_scan_out(client);
ret = i2c_master_recv(client, mass_buff_1, sizeof(mass_buff_1));
if (ret != sizeof(mass_buff_1)) {
touch_debug(DEBUG_ERROR,"[ELAN] ERROR: read data error. res=%d\r\n", ret);
return -1;
}
else
{
finish = (mass_buff_1[1] >> 4 ) & 0x01;
touch_debug(DEBUG_MESSAGES,"[ELAN] mass_buff_1[0]=%x, mass_buff_1[1]=%x (80 10)!!!!!!!!!! finish=%d \n", mass_buff_1[0], mass_buff_1[1], finish); //80 10: OK, 80 00: fail
}
if (mass_buff_1[1]!= I2C_DATA[0] && finish!=1 && i<100) {
mdelay(100);
//printk("[elan] mass_buff_1[1] >>4 !=1\n");
i++;
if (i == 50) {
touch_debug(DEBUG_ERROR,"[elan] Mass_Erase fail ! \n");
//return -1; //for test
}
}
}
return 0;
}
int Reset_ICE(struct i2c_client *client){
//struct elan_ktf_ts_data *ts = i2c_get_clientdata(client);
int res;
touch_debug(DEBUG_INFO,"[Elan] Reset ICE!!!!\n");
ins_write(client, 0x94);
ins_write(client, 0xd4);
ins_write(client, 0x20);
client->addr = I2C_DATA[0];////Modify address before 2-wire
elan_ktf_ts_hw_reset();
mdelay(250);
res = __hello_packet_handler(client);
return 0;
}
int normal_write_func(struct i2c_client *client, int j, uint8_t *szBuff){
//char buff_check=0;
uint16_t szbuff=0, szbuff_1=0;
uint16_t sendbuff=0;
int write_byte, iw;
ins_write(client,0xfd);
word_scan_in(client, j*64);
ins_write(client,0x65); //Program data sequential write
write_byte =64;
for(iw=0;iw<write_byte;iw++){
szbuff = *szBuff;
szbuff_1 = *(szBuff+1);
sendbuff = szbuff_1 <<8 |szbuff;
touch_debug(DEBUG_MESSAGES,"[elan] Write Page sendbuff=0x%04x @@@\n", sendbuff);
//mdelay(1);
word_scan_in(client, sendbuff); //data???? buff_read_data
szBuff+=2;
}
return 0;
}
int fastmode_write_func(struct i2c_client *client, int j, uint8_t *szBuff){
uint8_t szfwbuff=0, szfwbuff_1=0;
uint8_t sendfwbuff[130]={0};
uint8_t tmpbuff;
int i=0, len=0;
private_ts->client->addr = 0x76;
sendfwbuff[0] = (j*64)>>8;
tmpbuff = ((j*64)<< 8) >> 8;
sendfwbuff[1] = tmpbuff;
//printk("fastmode_write_func, sendfwbuff[0]=0x%x, sendfwbuff[1]=0x%x\n", sendfwbuff[0], sendfwbuff[1]);
for (i=2;i < 129; i=i+2) { // 1 Page = 64 word, 1 word=2Byte
szfwbuff = *szBuff;
szfwbuff_1 = *(szBuff+1);
sendfwbuff[i] = szfwbuff_1;
sendfwbuff[i+1] = szfwbuff;
szBuff+=2;
//printk("[elan] sendfwbuff[%d]=0x%x, sendfwbuff[%d]=0x%x\n", i, sendfwbuff[i], i+1, sendfwbuff[i+1]);
}
len = i2c_master_send(private_ts->client, sendfwbuff, 130);
if (len != 130) { //address+data(128)
touch_debug(DEBUG_ERROR,"[ELAN] ERROR: fastmode write page error, write error. len=%d, Page %d\r\n", len, j);
return -1;
}
//printk("fastmode_write_func, send len=%d (130), Page %d --\n", len, j);
private_ts->client->addr = 0x77;
return 0;
}
int ektSize;
int lastpage_byte;
int lastpage_flag=0;
int Write_Page(struct i2c_client *client, int j, uint8_t *szBuff){
int len, finish=0;
char buff_read_data[2];
int i=0;
ins_write(client,0x6f); //IO Write
//long_word_scan_in(client,0x007e,0x0023);
long_word_scan_in(client,0x007f,0x8000);
long_word_scan_in(client,0x007f,0x9400);
ins_write(client,0x66); //Program Data Write
//long_word_scan_in(client,0x0000,0x5a5a);
long_word_scan_in(client, j*64,0x0000);
//printk("[elan] j*64=0x%x @@ \n", j*64);
//long_word_scan_in(client, j*64,0x5a5a); //set ALE
//normal_write_func(client, j, szBuff); ////////////choose one : normal / fast mode
fastmode_write_func(client, j, szBuff); //////////
ins_write(client,0x6f);
long_word_scan_in(client,0x007f,0x9000);
//ins_write(client,0x6f);
long_word_scan_in(client,0x007f,0x8000);
ins_write(client, 0xf3); //Debug Reg Read
while (finish==0){
word_scan_out(client);
len=i2c_master_recv(client, buff_read_data, sizeof(buff_read_data));
if (len != sizeof(buff_read_data)) {
touch_debug(DEBUG_ERROR,"[ELAN] ERROR: Write_Page read buff_read_data error, len=%d\r\n", len);
return E_FD;
}
else
{
finish = (buff_read_data[1] >> 4 ) & 0x01;
//printk("[ELAN] read data successfully! buff[0]=0x%x buff[1]=0x%x finish=%d\r\n", buff_read_data[0], buff_read_data[1], finish); //80 10: ok
}
if (finish!=1) {
mdelay(10);
//printk("[elan] Write_Page finish !=1\n");
i++;
if (i==50){
touch_debug(DEBUG_ERROR,"[elan] Write_Page finish !=1, Page=%d\n", j);
write_ice_status=1;
return -1;
}
}
}
return 0;
}
int fastmode_read_func(struct i2c_client *client, int j, uint8_t *szBuff){
uint8_t szfrbuff=0, szfrbuff_1=0;
uint8_t sendfrbuff[2]={0};
uint8_t recvfrbuff[130]={0};
uint16_t tmpbuff;
int i=0, len=0, retry=0;
ins_write(client,0x67);
private_ts->client->addr = 0x76;
sendfrbuff[0] = (j*64)>>8;
tmpbuff = ((j*64)<< 8) >> 8;
sendfrbuff[1] = tmpbuff;
//printk("fastmode_write_func, sendfrbuff[0]=0x%x, sendfrbuff[1]=0x%x\n", sendfrbuff[0], sendfrbuff[1]);
len = i2c_master_send(private_ts->client, sendfrbuff, sizeof(sendfrbuff));
len = i2c_master_recv(private_ts->client, recvfrbuff, sizeof(recvfrbuff));
//printk("fastmode_read_func, recv len=%d (128)\n", len);
for (i=2;i < 129;i=i+2){
szfrbuff=*szBuff;
szfrbuff_1=*(szBuff+1);
szBuff+=2;
if (recvfrbuff[i] != szfrbuff_1 || recvfrbuff[i+1] != szfrbuff)
{
touch_debug(DEBUG_ERROR,"[elan] @@@@Read Page Compare Fail. recvfrbuff[%d]=%x, recvfrbuff[i+1]=%x, szfrbuff_1=%x, szfrbuff=%x, ,j =%d@@@@@@@@@@@@@@@@\n\n", i,recvfrbuff[i], recvfrbuff[i+1], szfrbuff_1, szfrbuff, j);
write_ice_status=1;
retry=1;
}
break;//for test
}
private_ts->client->addr = 0x77;
if(retry==1)
{
return -1;
}
else
return 0;
}
int normal_read_func(struct i2c_client *client, int j, uint8_t *szBuff){
char read_buff[2];
int m, len, read_byte;
uint16_t szbuff=0, szbuff_1=0;
ins_write(client,0xfd);
//printk("[elan] Read_Page, j*64=0x%x\n", j*64);
word_scan_in(client, j*64);
ins_write(client,0x67);
word_scan_out(client);
read_byte=64;
//for(m=0;m<64;m++){
for(m=0;m<read_byte;m++){
// compare......
word_scan_out(client);
len=i2c_master_recv(client, read_buff, sizeof(read_buff));
szbuff=*szBuff;
szbuff_1=*(szBuff+1);
szBuff+=2;
touch_debug(DEBUG_MESSAGES,"[elan] Read Page: byte=%x%x, szbuff=%x%x \n", read_buff[0], read_buff[1],szbuff, szbuff_1);
if (read_buff[0] != szbuff_1 || read_buff[1] != szbuff)
{
touch_debug(DEBUG_ERROR,"[elan] @@@@@@@@@@Read Page Compare Fail. j =%d. m=%d.@@@@@@@@@@@@@@@@\n\n", j, m);
write_ice_status=1;
}
}
return 0;
}
int Read_Page(struct i2c_client *client, int j, uint8_t *szBuff){
int res=0;
ins_write(client,0x6f);
//long_word_scan_in(client,0x007e,0x0023);
long_word_scan_in(client,0x007f,0x9000);
ins_write(client,0x68);
//mdelay(10); //for malata
//normal_read_func(client, j, szBuff); ////////////////choose one: normal / fastmode
fastmode_read_func(client, j, szBuff);
//Clear Flashce
ins_write(client,0x6f);
long_word_scan_in(client,0x007f,0x0000);
if(res==-1)
{
return -1;
}
return 0;
}
int TWO_WIRE_ICE(struct i2c_client *client){
int i;
uint8_t *szBuff = NULL;
//char szBuff[128]={0};
int curIndex = 0;
int PageSize=128;
int res;
//int ektSize;
//test
write_ice_status=0;
ektSize = sizeof(file_bin_data) /PageSize;
client->addr = 0x77;////Modify address before 2-wire
touch_debug(DEBUG_INFO,"[Elan] ektSize=%d ,modify address = %x\n ", ektSize, client->addr);
i = Enter_Mode(client);
i = Open_High_Voltage(client, 1);
if (i == -1)
{
touch_debug(DEBUG_ERROR,"[Elan] Open High Voltage fail\n");
return -1;
}
//return 0;
i = Mass_Erase(client); //mark temp
if (i == -1) {
touch_debug(DEBUG_ERROR,"[Elan] Mass Erase fail\n");
return -1;
}
//for fastmode
ins_write(client,0x6f);
long_word_scan_in(client, 0x007e, 0x0036);
long_word_scan_in(client, 0x007f, 0x8000);
long_word_scan_in(client, 0x007e, 0x0023); //add by herman
// client->addr = 0x76;////Modify address before 2-wire
touch_debug(DEBUG_INFO,"[Elan-test] client->addr =%2x\n", client->addr);
//for fastmode
for (i =0 ; i<ektSize; i++)
{
szBuff = file_bin_data + curIndex;
curIndex = curIndex + PageSize;
// printk("[Elan] Write_Page %d........................wait\n ", i);
res=Write_Page(client, i, szBuff);
if (res == -1)
{
touch_debug(DEBUG_ERROR,"[Elan] Write_Page %d fail\n ", i);
break;
}
//printk("[Elan] Read_Page %d........................wait\n ", i);
mdelay(1);
Read_Page(client,i, szBuff);
//printk("[Elan] Finish %d Page!!!!!!!.........wait\n ", i);
}
if(write_ice_status==0)
{
touch_debug(DEBUG_INFO,"[elan] Update_FW_Boot Finish!!! \n");
}
else
{
touch_debug(DEBUG_INFO,"[elan] Update_FW_Boot fail!!! \n");
}
i = Open_High_Voltage(client, 0);
if (i == -1) return -1; //test
Reset_ICE(client);
return 0;
}
int elan_TWO_WIRE_ICE( struct i2c_client *client) // for driver internal 2-wire ice
{
work_lock=1;
disable_irq(private_ts->client->irq);
//wake_lock(&private_ts->wakelock);
TWO_WIRE_ICE(client);
work_lock=0;
enable_irq(private_ts->client->irq);
//wake_unlock(&private_ts->wakelock);
return 0;
}
// End 2WireICE
#endif
int CheckISPstatus(struct i2c_client *client)
{
int len = 0;
int j;
uint8_t checkstatus[37] = {0x04, 0x00, 0x23, 0x00, 0x03, 0x18};
uint8_t buff[67] = {0};
len = i2c_master_send(private_ts->client, checkstatus, sizeof(checkstatus));
if (len != sizeof(checkstatus)) {
touch_debug(DEBUG_ERROR,"[elan] ERROR: Flash key fail! len=%d\r\n", len);
return -1;
}
else
touch_debug(DEBUG_MESSAGES,"[elan] check status write data successfully! cmd = [%x, %x, %x, %x, %x, %x]\n", checkstatus[0], checkstatus[1], checkstatus[2], checkstatus[3], checkstatus[4], checkstatus[5]);
mdelay(10);
len=i2c_master_recv(private_ts->client, buff, sizeof(buff));
if (len != sizeof(buff)) {
touch_debug(DEBUG_ERROR,"[elan] ERROR: Check Address Read Data error. len=%d \r\n", len);
return -1;
}
else {
printk("[elan][Check status]: ");
for (j=0; j<37; j++)
printk("%x ", buff[j]);
printk("\n");
if (buff[6] == 0x80) return 0x80; /* return recovery mode 0x88 */
}
return 0;
}
int HID_RecoveryISP(struct i2c_client *client)
{
int len = 0;
int j;
uint8_t flash_key[37] = {0x04, 0x00, 0x23, 0x00, 0x03, 0x00, 0x04, 0x54, 0xc0, 0xe1, 0x5a};
// uint8_t isp_cmd[37] = {0x04, 0x00, 0x23, 0x00, 0x03, 0x00, 0x04, 0x54, 0x00, 0x12, 0x34};
uint8_t check_addr[37] = {0x04, 0x00, 0x23, 0x00, 0x03, 0x00, 0x01, 0x10};
uint8_t buff[67] = {0};
len = i2c_master_send(private_ts->client, flash_key, 37);
if (len != 37) {
touch_debug(DEBUG_ERROR,"[elan] ERROR: Flash key fail! len=%d\r\n", len);
return -1;
}
else
touch_debug(DEBUG_MESSAGES,"[elan] FLASH key write data successfully! cmd = [%2x, %2x, %2x, %2x]\n", flash_key[7], flash_key[8], flash_key[9], flash_key[10]);
mdelay(20);
/*
len = i2c_master_send(private_ts->client, isp_cmd, 37);
if (len != 37) {
touch_debug(DEBUG_ERROR,"[elan] ERROR: EnterISPMode fail! len=%d\r\n", len);
return -1;
}
else
touch_debug(DEBUG_MESSAGES,"[elan] IAPMode write data successfully! cmd = [%2x, %2x, %2x, %2x]\n", isp_cmd[7], isp_cmd[8], isp_cmd[9], isp_cmd[10]);
*/
mdelay(20);
len = i2c_master_send(private_ts->client, check_addr, sizeof(check_addr));
if (len != sizeof(check_addr)) {
touch_debug(DEBUG_ERROR,"[elan] ERROR: Check Address fail! len=%d\r\n", len);
return -1;
}
else
touch_debug(DEBUG_MESSAGES,"[elan] Check Address write data successfully! cmd = [%2x, %2x, %2x, %2x]\n", check_addr[7], check_addr[8], check_addr[9], check_addr[10]);
mdelay(20);
len=i2c_master_recv(private_ts->client, buff, sizeof(buff));
if (len != sizeof(buff)) {
touch_debug(DEBUG_ERROR,"[elan] ERROR: Check Address Read Data error. len=%d \r\n", len);
return -1;
}
else {
printk("[elan][Check Addr]: ");
for (j=0; j<37; j++)
printk("%x ", buff[j]);
printk("\n");
}
return 0;
}
int SendEndCmd(struct i2c_client *client)
{
int len = 0;
uint8_t send_cmd[37] = {0x04, 0x00, 0x23, 0x00, 0x03, 0x1A};
len = i2c_master_send(private_ts->client, send_cmd, sizeof(send_cmd));
if (len != sizeof(send_cmd)) {
touch_debug(DEBUG_ERROR,"[elan] ERROR: Send Cmd fail! len=%d\r\n", len);
return -1;
}
else
touch_debug(DEBUG_MESSAGES,"[elan] check status write data successfully! cmd = [%x, %x, %x, %x, %x, %x]\n", send_cmd[0], send_cmd[1], send_cmd[2], send_cmd[3], send_cmd[4], send_cmd[5]);
return 0;
}
#if 0
static int HID_FW_Update(struct i2c_client *client, int recovery)
{
int res = 0,ic_num = 1;
int iPage = 0; /* rewriteCnt = 0; rewriteCnt for PAGE_REWRITE */
int j = 0; // i=0;
int write_times = 142;
// int write_bytes = 12;
uint8_t data;
// int restartCnt = 0; // For IAP_RESTART
int byte_count;
const u8 *szBuff = NULL;
u8 write_buf[37] = {0x04, 0x00, 0x23, 0x00, 0x03, 0x21, 0x00, 0x00, 0x28};
u8 cmd_iap_write[37] = {0x04, 0x00, 0x23, 0x00, 0x03, 0x22};
int curIndex = 0;
int offset = 0;
// 0x54, 0x00, 0x12, 0x34
int rc, fw_size;
/* Star Request Firmware */
const u8 *fw_data;
const struct firmware *p_fw_entry;
touch_debug(DEBUG_INFO, "Request_firmware name = %s\n",ELAN_FW_FILENAME);
rc = request_firmware(&p_fw_entry, ELAN_FW_FILENAME, &client->dev);
if (rc != 0) {
touch_debug(DEBUG_ERROR,"rc=%d, Request_firmware fail\n", rc);
return -1;
} else
PageNum=473;
touch_debug(DEBUG_INFO,"Firmware Size=%zu, PageNum=%d\n", p_fw_entry->size,PageNum);
fw_data = p_fw_entry->data;
fw_size = p_fw_entry->size;
/* End Request Firmware */
touch_debug(DEBUG_INFO, "[elan] %s: ic_num=%d\n", __func__, ic_num);
data=I2C_DATA[0];//Master
touch_debug(DEBUG_INFO, "[elan] %s: address data=0x%x \r\n", __func__, data);
elan_ktf_ts_hw_reset();
mdelay(200);
res = CheckISPstatus(private_ts->client);
mdelay(20);
if (res == 0x80) { /* 0x88 recovery mode */
elan_ktf_ts_hw_reset();
mdelay(200);
printk("[elan hid iap] Recovery mode\n");
res = HID_RecoveryISP(private_ts->client);
}
else {
printk("[elan hid iap] Normal mode\n");
res = HID_EnterISPMode(private_ts->client); //enter HID ISP mode
}
mdelay(50);
// Start HID IAP
for( iPage = 1; iPage <= 473; iPage +=30 )
{
offset=0;
if (iPage == 451 ) {
write_times = 109;
//write_bytes = 18;
}
else {
write_times = 142;
//write_bytes = 12;
}
mdelay(5);
for(byte_count=1; byte_count <= write_times; byte_count++)
{
mdelay(5);
if(byte_count != write_times)
{
szBuff = fw_data + curIndex;
write_buf[8] = 28;
write_buf[7] = offset & 0x00ff;
write_buf[6] = offset >> 8;
offset +=28;
curIndex = curIndex + 28;
for (j=0; j<28; j++)
write_buf[j+9]=szBuff[j];
/*
if (iPage == 451) {
printk("[hid_iap] P=%d i=%d: ", iPage,byte_count);
for (j=0; j<37; j++)
printk("%x ", write_buf[j]);
printk("\n");
} */
res = WritePage(write_buf, 37);
}
else
{
szBuff = fw_data + curIndex;
write_buf[8] = 12;
write_buf[7] = offset & 0x00ff;
write_buf[6] = offset >> 8;
curIndex = curIndex + 12;
for (j=0; j<12; j++)
write_buf[j+9]=szBuff[j];
printk("[elan hid iap packet] iPage=%d i=%d times=%d data ", iPage,byte_count, write_times);
for (j=0; j<37; j++)
printk("%x ", write_buf[j]);
printk("\n");
res = WritePage(write_buf, 37);
}
} // end of for(byte_count=1;byte_count<=17;byte_count++)
mdelay(10);
/*
printk("[elan iap write] cmd ");
for (j=0; j<37; j++)
printk("%x ", cmd_iap_write[j]);
printk("\n");
*/
res = WritePage(cmd_iap_write, 37);
mdelay(200);
res = GetAckData(private_ts->client);
mdelay(10);
} // end of for(iPage = 1; iPage <= PageNum; iPage++)
res = SendEndCmd(private_ts->client);
mdelay(200);
elan_ktf_ts_hw_reset();
mdelay(200);
res = elan_ktf_ts_calibrate(private_ts->client);
mdelay(100);
touch_debug(DEBUG_INFO,"[elan] Update Firmware successfully!\n");
return res;
}
#endif
#if 0
static int FW_Update(struct i2c_client *client, int recovery)
{
int res = 0,ic_num = 1;
int iPage = 0, rewriteCnt = 0; //rewriteCnt for PAGE_REWRITE
int i = 0;
uint8_t data;
int restartCnt = 0; // For IAP_RESTART
int byte_count;
const u8 *szBuff = NULL;
int curIndex = 0;
// 0x54, 0x00, 0x12, 0x34
int rc, fw_size;
/* Star Request Firmware */
const u8 *fw_data;
const struct firmware *p_fw_entry;
touch_debug(DEBUG_INFO, "request_firmware name = %s\n",ELAN_FW_FILENAME);
rc = request_firmware(&p_fw_entry, ELAN_FW_FILENAME, &client->dev);
if (rc != 0) {
touch_debug(DEBUG_ERROR,"rc=%d, request_firmware fail\n", rc);
return -1;
} else
touch_debug(DEBUG_INFO,"Firmware Size=%zu\n", p_fw_entry->size);
fw_data = p_fw_entry->data;
fw_size = p_fw_entry->size;
/* End Request Firmware */
touch_debug(DEBUG_INFO, "[elan] %s: ic_num=%d\n", __func__, ic_num);
IAP_RESTART:
data=I2C_DATA[0];//Master
touch_debug(DEBUG_INFO, "[elan] %s: address data=0x%x \r\n", __func__, data);
if(recovery != 0x80)
{
touch_debug(DEBUG_INFO,"[elan] Firmware upgrade normal mode !\n");
elan_ktf_ts_hw_reset();
res = EnterISPMode(private_ts->client); //enter ISP mode
} else
touch_debug(DEBUG_INFO,"[elan] Firmware upgrade recovery mode !\n");
touch_debug(DEBUG_INFO,"[elan] send one byte data:%x,%x",private_ts->client->addr,data);
res = i2c_master_send(private_ts->client, &data, sizeof(data));
if(res!=sizeof(data))
{
printk("[elan] dummy error code = %d\n",res);
touch_debug(DEBUG_ERROR,"[elan] dummy error code = %d\n",res);
}
mdelay(10);
// Start IAP
for( iPage = 1; iPage <= PageNum; iPage++ )
{
PAGE_REWRITE:
for(byte_count=1;byte_count<=17;byte_count++)
{
if(byte_count!=17)
{
szBuff = fw_data + curIndex;
curIndex = curIndex + 8;
res = WritePage(szBuff, 8);
}
else
{
szBuff = fw_data + curIndex;
curIndex = curIndex + 4;
res = WritePage(szBuff, 4);
}
} // end of for(byte_count=1;byte_count<=17;byte_count++)
if(iPage==377 || iPage==1)
{
mdelay(600);
}
else
{
mdelay(50);
}
res = GetAckData(private_ts->client);
if (ACK_OK != res)
{
mdelay(50);
touch_debug(DEBUG_ERROR,"[elan] ERROR: GetAckData fail! res=%d\r\n", res);
if ( res == ACK_REWRITE )
{
rewriteCnt = rewriteCnt + 1;
if (rewriteCnt == PAGERETRY)
{
touch_debug(DEBUG_ERROR,"[elan] ID 0x%02x %dth page ReWrite %d times fails!\n", data, iPage, PAGERETRY);
return E_FD;
}
else
{
touch_debug(DEBUG_ERROR,"[elan] ---%d--- page ReWrite %d times!\n", iPage, rewriteCnt);
goto PAGE_REWRITE;
}
}
else
{
restartCnt = restartCnt + 1;
if (restartCnt >= 5)
{
touch_debug(DEBUG_ERROR,"[elan] ID 0x%02x ReStart %d times fails!\n", data, IAPRESTART);
return E_FD;
}
else
{
printk("[elan] ===%d=== page ReStart %d times!\n", iPage, restartCnt);
touch_debug(DEBUG_ERROR,"[elan] ===%d=== page ReStart %d times!\n", iPage, restartCnt);
goto IAP_RESTART;
}
}
}
else
{
rewriteCnt=0;
print_progress(iPage,ic_num,i);
}
mdelay(10);
} // end of for(iPage = 1; iPage <= PageNum; iPage++)
res= __hello_packet_handler(private_ts->client);
if(res > 0) touch_debug(DEBUG_INFO,"[elan] Update Firmware successfully!\n");
return res;
}
#endif
/*
static ssize_t set_debug_mesg(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int level[SYSFS_MAX_LEN];
sscanf(buf,"%x",&level[0]);
debug=level[0];
touch_debug(DEBUG_INFO, "debug level %d, size %d\n", debug,count);
return count;
}
static ssize_t show_debug_mesg(struct device *dev,
struct device_attribute *attr, char *buf)
{
return sprintf(buf, "Debug level %d \n", debug);
}*/
static ssize_t show_gpio_int(struct device *dev,
struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%d\n", gpio_get_value(private_ts->intr_gpio));
}
static ssize_t show_reset(struct device *dev,
struct device_attribute *attr, char *buf)
{
//struct i2c_client *client = to_i2c_client(dev);
//struct elan_ktf_ts_data *ts = i2c_get_clientdata(client);
elan_ktf_ts_hw_reset();
return sprintf(buf, "Reset Touch Screen Controller \n");
}
static ssize_t store_reset(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
elan_ktf_ts_hw_reset();
printk("[elan] %s: Reset Touch Screen Controller.\n",__func__);
return count;
}
static ssize_t show_enable_irq(struct device *dev,
struct device_attribute *attr, char *buf)
{
// struct i2c_client *client = to_i2c_client(dev);
// struct elan_ktf_ts_data *ts = i2c_get_clientdata(client);
work_lock=0;
enable_irq(private_ts->client->irq);
wake_unlock(&private_ts->wakelock);
return sprintf(buf, "Enable IRQ \n");
}
static ssize_t store_enable_irq(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
work_lock=0;
enable_irq(private_ts->client->irq);
wake_unlock(&private_ts->wakelock);
printk("[elan] %s: Enable IRQ.\n",__func__);
return count;
}
static ssize_t show_disable_irq(struct device *dev,
struct device_attribute *attr, char *buf)
{
// struct i2c_client *client = to_i2c_client(dev);
// struct elan_ktf_ts_data *ts = i2c_get_clientdata(client);
work_lock=1;
disable_irq(private_ts->client->irq);
wake_lock(&private_ts->wakelock);
return sprintf(buf, "Disable IRQ \n");
}
static ssize_t store_disable_irq(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
work_lock=1;
disable_irq(private_ts->client->irq);
wake_lock(&private_ts->wakelock);
printk("[elan] %s: Disable IRQ.\n",__func__);
return count;
}
static ssize_t show_calibrate(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
int ret = 0;
ret = elan_ktf_ts_calibrate(client);
return sprintf(buf, "%s\n", (ret == 0) ? " [elan] Calibrate Finish" : "[elan] Calibrate Fail");
}
static ssize_t store_calibrate(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
int ret = 0;
ret = elan_ktf_ts_calibrate(client);
if (ret == 0)
touch_debug(DEBUG_INFO, " [elan] Calibrate Finish!");
else
touch_debug(DEBUG_INFO, "[elan] Calibrate Fail!");
return count;
}
static ssize_t show_fw_update_in_driver(struct device *dev,
struct device_attribute *attr, char *buf)
{
int ret;
//struct i2c_client *client = to_i2c_client(dev);
work_lock=1;
disable_irq(private_ts->client->irq);
wake_lock(&private_ts->wakelock);
//ret = Update_FW_in_Driver(0);
ret = Update_FW_One(0);
work_lock=0;
enable_irq(private_ts->client->irq);
wake_unlock(&private_ts->wakelock);
return sprintf(buf, "[elan] Update Firmware in driver used fw_data.i\n");
}
static ssize_t store_fw_update_in_driver(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
int ret;
/* Compare current FW version with newest FW version */
if (private_ts->fw_ver < NEWEST_FW_VER) {
work_lock=1;
disable_irq(private_ts->client->irq);
wake_lock(&private_ts->wakelock);
ret = Update_FW_One(0);
work_lock=0;
enable_irq(private_ts->client->irq);
wake_unlock(&private_ts->wakelock);
printk("[elan] %s: Update Firmware in driver used fw_data.i\n", __func__);
return count;
} else{
printk("[elan]%s: Current FW is the newest version %0x \n", __func__, private_ts->fw_ver);
return count;
}
}
#if 0
static ssize_t show_hid_fw_update(struct device *dev,
struct device_attribute *attr, char *buf)
{
int ret;
struct i2c_client *client = to_i2c_client(dev);
work_lock=1;
disable_irq(private_ts->client->irq);
wake_lock(&private_ts->wakelock);
ret = HID_FW_Update(client, 0);
work_lock=0;
enable_irq(private_ts->client->irq);
wake_unlock(&private_ts->wakelock);
return sprintf(buf, "HID Update Firmware\n");
}
#endif
static ssize_t show_fw_update(struct device *dev,
struct device_attribute *attr, char *buf)
{
int ret;
//struct i2c_client *client = to_i2c_client(dev);
work_lock=1;
disable_irq(private_ts->client->irq);
wake_lock(&private_ts->wakelock);
//ret = FW_Update(client, 0);
ret = Update_FW_One(1); //use request firmware
work_lock=0;
enable_irq(private_ts->client->irq);
wake_unlock(&private_ts->wakelock);
return sprintf(buf, "Update Firmware\n");
}
static ssize_t store_fw_update(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
int ret;
work_lock=1;
disable_irq(private_ts->client->irq);
wake_lock(&private_ts->wakelock);
ret = Update_FW_One(1); //use request firmware
work_lock=0;
enable_irq(private_ts->client->irq);
wake_unlock(&private_ts->wakelock);
printk("[elan] %s: Update Firmware at /system/etc/firmware/\n", __func__);
return count;
}
#if 0
static ssize_t show_fw_update_elan(struct device *dev,
struct device_attribute *attr, char *buf)
{
int ret;
work_lock=1;
disable_irq(private_ts->client->irq);
wake_lock(&private_ts->wakelock);
ret = Update_FW_One(2); //firmware is located at /data/local/tmp
work_lock=0;
enable_irq(private_ts->client->irq);
wake_unlock(&private_ts->wakelock);
return sprintf(buf, "Update Firmware\n");
}
#endif
#if 0
static ssize_t store_fw_update_elan(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
int ret;
work_lock=1;
disable_irq(private_ts->client->irq);
wake_lock(&private_ts->wakelock);
ret = Update_FW_One(2); //firmware is located at /data/local/tmp
work_lock=0;
enable_irq(private_ts->client->irq);
wake_unlock(&private_ts->wakelock);
printk("[elan] %s: Update Firmware at /data/local/tmp\n", __func__);
return count;
}
#endif
#ifdef ELAN_2WIREICE
static ssize_t show_2wire(struct device *dev,
struct device_attribute *attr, char *buf)
{
int ret;
struct i2c_client *client = to_i2c_client(dev);
work_lock=1;
disable_irq(private_ts->client->irq);
wake_lock(&private_ts->wakelock);
ret = TWO_WIRE_ICE(client);
work_lock=0;
enable_irq(private_ts->client->irq);
wake_unlock(&private_ts->wakelock);
return sprintf(buf, "Update Firmware by 2wire JTAG\n");
}
#endif
static ssize_t show_fw_version_value(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct elan_ktf_ts_data *ts = i2c_get_clientdata(client);
return sprintf(buf, "FW VER = %0*x\n", 4, ts->fw_ver);
}
static ssize_t show_fw_id_value(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct elan_ktf_ts_data *ts = i2c_get_clientdata(client);
return sprintf(buf, "FW ID = %0*x\n", 4, ts->fw_id);
}
static ssize_t show_bc_version_value(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct elan_ktf_ts_data *ts = i2c_get_clientdata(client);
return sprintf(buf, "BC VER = %0*x\n", 4, ts->bc_ver);
}
static ssize_t show_drv_version_value(struct device *dev,
struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%s\n", "Elan driver version 0x0006");
}
static ssize_t show_iap_mode(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct elan_ktf_ts_data *ts = i2c_get_clientdata(client);
return sprintf(buf, "%s\n",
(ts->fw_ver == 0) ? "Recovery" : "Normal");
}
static ssize_t show_mt_protocol(struct device *dev,
struct device_attribute *attr, char *buf)
{
return sprintf(buf, "Current MT protocol %s\n", CURRENT_MT_PROTOCOL);
}
static ssize_t show_power_mode(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct elan_ktf_ts_data *ts = i2c_get_clientdata(client);
return sprintf(buf, "%s\n",
(ts->power_mode == POWER_MODE_NORMAL) ? "Normal" : "Idle");
}
#ifdef FEATURE_CHECK_TRUE_INTERRUPT
static ssize_t show_int_count(struct device *dev,
struct device_attribute *attr, char *buf)
{
return sprintf(buf, "touchCNT =%d, 78intCNT = %d\n", touchINT_cnt, IamAlive_PKT_INT_cnt);
}
#endif
static ssize_t show_goto_idle_mode(struct device *dev,
struct device_attribute *attr, char *buf)
{
char idle_cmd[] = {0x54, 0x52, 0x00, 0x01};
struct i2c_client *client = to_i2c_client(dev);
int len = i2c_master_send(client, idle_cmd, sizeof(idle_cmd)/sizeof(idle_cmd[0]));
if(len != sizeof(idle_cmd)/sizeof(idle_cmd[0]))
{
return sprintf(buf, "%s\n", "Failed to send i2c cmd to enter idle mode\n");
}
return sprintf(buf, "%s\n", "Enter idle mode, check mode by cat power_mode!! \n");
}
#ifdef FEATURE_QUANTA_GESTURE_TO_BOOTLOADER
static ssize_t store_gestr_bld_ctl(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count
)
{
if (!strncmp("1", buf, 1))
{
is_quanta_gesture_to_bld_enabled = true;
}else if (!strncmp("0", buf, 1)){
is_quanta_gesture_to_bld_enabled = false;
}else {
printk("[quanta]%s: unknown parameter %s \n", __func__, buf);
}
printk("[quanta]%s: is_quanta_gesture_to_bld_enabled %s \n",__func__,
(is_quanta_gesture_to_bld_enabled == true) ? "enable":"disable");
return count;
}
static ssize_t show_gestr_bld_ctl(struct device *dev,
struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%s\n", is_quanta_gesture_to_bld_enabled == true? "enable":"disable");
}
#endif
#ifdef FEATURE_QUANTA_GESTURE_TO_RECOVERY
static ssize_t store_gestr_rcvr_ctl(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count
)
{
if (!strncmp("1", buf, 1))
{
is_quanta_gesture_to_rcvr_enabled = true;
}else if (!strncmp("0", buf, 1)){
is_quanta_gesture_to_rcvr_enabled = false;
}else {
printk("[quanta]%s: unknown parameter %s \n", __func__, buf);
}
printk("[quanta]%s: is_quanta_gesture_to_rcvr_enabled %s \n",__func__,
(is_quanta_gesture_to_rcvr_enabled == true) ? "enable":"disable");
return count;
}
static ssize_t show_gestr_rcvr_ctl(struct device *dev,
struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%s\n", is_quanta_gesture_to_rcvr_enabled == true? "enable":"disable");
}
#endif
//static DEVICE_ATTR(debug_mesg, S_IRUGO | S_IWUGO, show_debug_mesg, set_debug_mesg);
static DEVICE_ATTR(gpio_int, S_IRUGO, show_gpio_int, NULL);
static DEVICE_ATTR(reset, /*S_IRUGO | S_IWUGO*/0660, show_reset, store_reset);
static DEVICE_ATTR(enable_irq, /*S_IRUGO | S_IWUGO*/0660, show_enable_irq, store_enable_irq);
static DEVICE_ATTR(disable_irq, /*S_IRUGO | S_IWUGO*/0660, show_disable_irq, store_disable_irq);
static DEVICE_ATTR(calibrate, /*S_IRUGO | S_IWUGO*/0660, show_calibrate, store_calibrate);
static DEVICE_ATTR(fw_version, S_IRUGO, show_fw_version_value, NULL);
static DEVICE_ATTR(fw_id, S_IRUGO, show_fw_id_value, NULL);
static DEVICE_ATTR(bc_version, S_IRUGO, show_bc_version_value, NULL);
static DEVICE_ATTR(drv_version, S_IRUGO, show_drv_version_value, NULL);
static DEVICE_ATTR(fw_update_in_driver, /*S_IRUGO | S_IWUGO*/0660, show_fw_update_in_driver, store_fw_update_in_driver);
static DEVICE_ATTR(fw_update, /*S_IRUGO | S_IWUGO*/0660, show_fw_update, store_fw_update);
//static DEVICE_ATTR(fw_update_elan, S_IRUGO | S_IWUGO, show_fw_update_elan, store_fw_update_elan);
//static DEVICE_ATTR(hid_fw_update, S_IRUGO, show_hid_fw_update, NULL);
#ifdef ELAN_2WIREICE
static DEVICE_ATTR(2wire, S_IRUGO, show_2wire, NULL);
#endif
static DEVICE_ATTR(iap_mode, S_IRUGO, show_iap_mode, NULL);
static DEVICE_ATTR(mt_protocol, S_IRUGO, show_mt_protocol, NULL);
static DEVICE_ATTR(power_mode, S_IRUGO, show_power_mode, NULL);
static DEVICE_ATTR(goto_idle_mode, S_IRUGO, show_goto_idle_mode, NULL);
#ifdef FEATURE_QUANTA_GESTURE_TO_BOOTLOADER
static DEVICE_ATTR(gestr_bld_ctl, 0660, show_gestr_bld_ctl, store_gestr_bld_ctl);
#endif
#ifdef FEATURE_QUANTA_GESTURE_TO_RECOVERY
static DEVICE_ATTR(gestr_rcvr_ctl, 0660, show_gestr_rcvr_ctl, store_gestr_rcvr_ctl);
#endif
#ifdef FEATURE_CHECK_TRUE_INTERRUPT
static DEVICE_ATTR(intCnt, S_IRUGO, show_int_count, NULL);
#endif
static struct attribute *elan_attributes[] = {
//&dev_attr_debug_mesg.attr,
&dev_attr_gpio_int.attr,
&dev_attr_reset.attr,
&dev_attr_enable_irq.attr,
&dev_attr_disable_irq.attr,
&dev_attr_calibrate.attr,
&dev_attr_fw_version.attr,
&dev_attr_fw_id.attr,
&dev_attr_bc_version.attr,
&dev_attr_drv_version.attr,
&dev_attr_fw_update_in_driver.attr,
&dev_attr_fw_update.attr,
//&dev_attr_fw_update_elan.attr,
//&dev_attr_hid_fw_update.attr,
#ifdef ELAN_2WIREICE
&dev_attr_2wire.attr,
#endif
&dev_attr_iap_mode.attr,
&dev_attr_mt_protocol.attr,
&dev_attr_power_mode.attr,
&dev_attr_goto_idle_mode.attr,
#ifdef FEATURE_QUANTA_GESTURE_TO_BOOTLOADER
&dev_attr_gestr_bld_ctl.attr,
#endif
#ifdef FEATURE_QUANTA_GESTURE_TO_RECOVERY
&dev_attr_gestr_rcvr_ctl.attr,
#endif
#ifdef FEATURE_CHECK_TRUE_INTERRUPT
&dev_attr_intCnt.attr,
#endif
NULL
};
static struct attribute_group elan_attribute_group = {
.name = DEVICE_NAME,
.attrs = elan_attributes,
};
// Start sysfs
static ssize_t elan_ktf_gpio_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
int ret = 0;
struct elan_ktf_ts_data *ts = private_ts;
ret = gpio_get_value(ts->intr_gpio);
touch_debug(DEBUG_MESSAGES, "GPIO_TP_INT_N=%d\n", ts->intr_gpio);
sprintf(buf, "GPIO_TP_INT_N=%d\n", ret);
ret = strlen(buf) + 1;
return ret;
}
static DEVICE_ATTR(gpio, S_IRUGO, elan_ktf_gpio_show, NULL);
static ssize_t elan_ktf_vendor_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
ssize_t ret = 0;
struct elan_ktf_ts_data *ts = private_ts;
sprintf(buf, "%s_x%4.4x\n", "elan_ktf", ts->fw_ver);
ret = strlen(buf) + 1;
return ret;
}
static DEVICE_ATTR(vendor, S_IRUGO, elan_ktf_vendor_show, NULL);
static struct kobject *android_touch_kobj;
static int elan_ktf_touch_sysfs_init(void)
{
int ret ;
android_touch_kobj = kobject_create_and_add("android_touch", NULL) ;
if (android_touch_kobj == NULL) {
touch_debug(DEBUG_ERROR,"[elan]%s: subsystem_register failed\n", __func__);
ret = -ENOMEM;
return ret;
}
ret = sysfs_create_file(android_touch_kobj, &dev_attr_gpio.attr);
if (ret) {
touch_debug(DEBUG_ERROR, "[elan]%s: sysfs_create_file failed\n", __func__);
return ret;
}
ret = sysfs_create_file(android_touch_kobj, &dev_attr_vendor.attr);
if (ret) {
touch_debug(DEBUG_ERROR, "[elan]%s: sysfs_create_group failed\n", __func__);
return ret;
}
return 0 ;
}
static void elan_touch_sysfs_deinit(void)
{
sysfs_remove_file(android_touch_kobj, &dev_attr_vendor.attr);
sysfs_remove_file(android_touch_kobj, &dev_attr_gpio.attr);
kobject_del(android_touch_kobj);
}
// end sysfs
static int elan_ktf_ts_get_data(struct i2c_client *client, uint8_t *cmd, uint8_t *buf, size_t w_size, size_t r_size)
{
int rc;
dev_dbg(&client->dev, "[elan]%s: enter\n", __func__);
if (buf == NULL)
return -EINVAL;
if ((i2c_master_send(client, cmd, w_size)) != w_size) {
dev_err(&client->dev, "[elan]%s: i2c_master_send failed\n", __func__);
return -EINVAL;
}
rc = elan_ktf_ts_poll(client);
if (rc < 0)
printk("%s: poll is high\n",__func__);
if(r_size <= 0) r_size=w_size;
if (i2c_master_recv(client, buf, r_size) != r_size) return -EINVAL;
return 0;
}
static int __hello_packet_handler(struct i2c_client *client)
{
int rc;
uint8_t buf_recv[8] = { 0 };
rc = elan_ktf_ts_poll(client);
if (rc < 0) {
printk( "[elan] %s: Int poll failed!\n", __func__);
}
rc = i2c_master_recv(client, buf_recv, 8);
printk("[elan] %s: hello packet %2x:%2X:%2x:%2x:%2x:%2x:%2x:%2x\n", __func__, buf_recv[0], buf_recv[1], buf_recv[2], buf_recv[3] , buf_recv[4], buf_recv[5], buf_recv[6], buf_recv[7]);
/* Quanta BU10SW, Stanley Tsao, 2015.12.14, if hello packet is 0s ==> No response from device, return immediately { */
if(buf_recv[0]==0x00 && buf_recv[1]==0x00 && buf_recv[2]==0x00 && buf_recv[3]==0x00)
{
printk("[Stanley]%s: hello packet is 0 \n", __func__);
return -ENODEV;
}
/* Quanta BU10SW, Stanley Tsao, 2015.12.14, if hello packet is 0s ==> No response from device, return immediately } */
if(buf_recv[0]==0x55 && buf_recv[1]==0x55 && buf_recv[2]==0x80 && buf_recv[3]==0x80)
{
RECOVERY=0x80;
return RECOVERY;
}
/*this IC won't report 0x66 0x66 0x66 0x66, no need to receive*/
/*
mdelay(300);
rc = elan_ktf_ts_poll(client);
if (rc < 0) {
printk( "[elan] %s: Int poll failed!\n", __func__);
}
rc = i2c_master_recv(client, buf_recv, 8);
printk("[elan] %s: Try Re-Calibration packet %2x:%2X:%2x:%2x\n", __func__, buf_recv[0], buf_recv[1], buf_recv[2], buf_recv[3]);
*/
return 0;
}
static int __fw_packet_handler(struct i2c_client *client)
{
struct elan_ktf_ts_data *ts = i2c_get_clientdata(client);
int rc;
int major, minor;
uint8_t cmd[] = {CMD_R_PKT, 0x00, 0x00, 0x01};/* Get Firmware Version*/
#if 0 /* for one-layer */
uint8_t cmd_x[] = { 0x53, 0x60, 0x00, 0x00 }; /*Get x resolution*/
uint8_t cmd_y[] = { 0x53, 0x63, 0x00, 0x00 }; /*Get y resolution*/
#endif
//uint8_t info_buff[] = { 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00 }; /*Get IC info*/
//uint8_t info_buff_resp[17] = { 0 };
uint8_t cmd_id[] = {0x53, 0xf0, 0x00, 0x01}; /*Get firmware ID*/
uint8_t cmd_bc[] = {CMD_R_PKT, 0x01, 0x00, 0x01};/* Get BootCode Version*/
uint8_t buf_recv[4] = {0};
// Firmware version
rc = elan_ktf_ts_get_data(client, cmd, buf_recv, 4,4);
if (rc < 0)
{
printk("Get Firmware version error\n");
/* Quanta BU10SW, Stanley Tsao, 2015.12.14, Return rc if rc < 0 { */
return rc;
/* Quanta BU10SW, Stanley Tsao, 2015.12.14, Return rc if rc < 0 } */
}
major = ((buf_recv[1] & 0x0f) << 4) | ((buf_recv[2] & 0xf0) >> 4);
minor = ((buf_recv[2] & 0x0f) << 4) | ((buf_recv[3] & 0xf0) >> 4);
ts->fw_ver = major << 8 | minor;
FW_VERSION = ts->fw_ver;
// Firmware ID
rc = elan_ktf_ts_get_data(client, cmd_id, buf_recv, 4,4);
if (rc < 0)
{
printk("Get Firmware ID error\n");
/* Quanta BU10SW, Stanley Tsao, 2015.12.14, Return rc if rc < 0 { */
return rc;
/* Quanta BU10SW, Stanley Tsao, 2015.12.14, Return rc if rc < 0 } */
}
major = ((buf_recv[1] & 0x0f) << 4) | ((buf_recv[2] & 0xf0) >> 4);
minor = ((buf_recv[2] & 0x0f) << 4) | ((buf_recv[3] & 0xf0) >> 4);
ts->fw_id = major << 8 | minor;
FW_ID = ts->fw_id;
// Bootcode version
rc = elan_ktf_ts_get_data(client, cmd_bc, buf_recv, 4,4);
if (rc < 0)
{
printk("Get Bootcode version error\n");
/* Quanta BU10SW, Stanley Tsao, 2015.12.14, Return rc if rc < 0 { */
return rc;
/* Quanta BU10SW, Stanley Tsao, 2015.12.14, Return rc if rc < 0 } */
}
major = ((buf_recv[1] & 0x0f) << 4) | ((buf_recv[2] & 0xf0) >> 4);
minor = ((buf_recv[2] & 0x0f) << 4) | ((buf_recv[3] & 0xf0) >> 4);
ts->bc_ver = major << 8 | minor;
BC_VERSION = ts->bc_ver;
/*Get XY info*/
#if 0 /* for one-layer */
/* X Resolution */
rc = elan_ktf_ts_get_data( client, cmd_x, buf_recv, 4, 4);
if( rc < 0 )
return rc;
minor = (( buf_recv[2] )) | (( buf_recv[3] & 0xF0 ) << 4 );
ts->x_resolution =minor;
X_RESOLUTION = minor;
/* Y Resolution */
rc = elan_ktf_ts_get_data( client, cmd_y, buf_recv, 4, 4);
if( rc < 0 )
return rc;
minor = (( buf_recv[2] )) | (( buf_recv[3] & 0xF0 ) << 4 );
ts->y_resolution =minor;
Y_RESOLUTION = minor;
#endif
#if 0
rc = elan_ktf_ts_get_data(client, info_buff, info_buff_resp, sizeof(info_buff), sizeof(info_buff_resp));
if (rc < 0)
{
printk("[elan] Get XY info error\n");
/* Quanta BU10SW, Stanley Tsao, 2015.12.14, Return rc if rc < 0 { */
return rc;
/* Quanta BU10SW, Stanley Tsao, 2015.12.14, Return rc if rc < 0 } */
}
ts->x_resolution = (info_buff_resp[2] + info_buff_resp[6]
+ info_buff_resp[10] + info_buff_resp[14] - 1)*64;
// X_RESOLUTION = ts->x_resolution;
ts->y_resolution = (info_buff_resp[3] + info_buff_resp[7]
+ info_buff_resp[11] + info_buff_resp[15] - 1)*64;
// Y_RESOLUTION = ts->y_resolution;
#endif
printk(KERN_INFO "[elan] %s: Firmware version: 0x%4.4x\n", __func__, ts->fw_ver);
printk(KERN_INFO "[elan] %s: Firmware ID: 0x%4.4x\n", __func__, ts->fw_id);
printk(KERN_INFO "[elan] %s: Bootcode Version: 0x%4.4x\n", __func__, ts->bc_ver);
printk(KERN_INFO "[elan] %s: x resolution: %d, y resolution: %d\n", __func__, X_RESOLUTION, Y_RESOLUTION);
return 0;
}
static inline int elan_ktf_pen_parse_xy(uint8_t *data,
uint16_t *x, uint16_t *y, uint16_t *p)
{
*x = *y = *p = 0;
*x = data[3];
*x <<= 8;
*x |= data[2];
*y = data[5];
*y <<= 8;
*y |= data[4];
*p = data[7];
*p <<= 8;
*p |= data[6];
return 0;
}
static inline int elan_ktf_ts_parse_xy(uint8_t *data,
uint16_t *x, uint16_t *y)
{
*x = *y = 0;
*x = (data[0] & 0xf0);
*x <<= 4;
*x |= data[1];
*y = (data[0] & 0x0f);
*y <<= 8;
*y |= data[2];
//printk("[Stanley]%s: x=%d y=%d \n", __func__, *x, *y); // Stanley Tsao debug
return 0;
}
static int elan_ktf_ts_setup(struct i2c_client *client)
{
int rc;
rc = __hello_packet_handler(client);
/* Quanta BU10SW, Stanley Tsao, 2015.12.14, Hello packet is 0, return ENODEV { */
if (rc == -ENODEV)
{
return rc;
}
/* Quanta BU10SW, Stanley Tsao, 2015.12.14, Hello packet is 0, return ENODEV } */
if (rc != 0x80){
rc = __fw_packet_handler(client);
if (rc < 0)
printk("[elan] %s, fw_packet_handler fail, rc = %d", __func__, rc);
dev_dbg(&client->dev, "[elan] %s: firmware checking done.\n", __func__);
//Check for FW_VERSION, if 0x0000 means FW update fail!
if ( FW_VERSION == 0x00)
{
rc = 0x80;
printk("[elan] FW_VERSION = %d, last FW update fail\n", FW_VERSION);
}
}
return rc;
}
static int elan_ktf_ts_calibrate(struct i2c_client *client){
#ifdef ELAN_HID_I2C
uint8_t flash_key[37] = {0x04, 0x00, 0x23, 0x00, 0x03, 0x00, 0x04,CMD_W_PKT, 0xc0, 0xe1, 0x5a};
uint8_t cal_cmd[37] = {0x04, 0x00, 0x23, 0x00, 0x03, 0x00, 0x04,CMD_W_PKT, 0x29, 0x00, 0x01};
dev_info(&client->dev, "[elan] %s: Flash Key cmd\n", __func__);
if ((i2c_master_send(client, flash_key, sizeof(flash_key))) != sizeof(flash_key)) {
dev_err(&client->dev, "[elan] %s: i2c_master_send failed\n", __func__);
return -EINVAL;
}
dev_info(&client->dev, "[elan] %s: Calibration cmd: %02x, %02x, %02x, %02x\n", __func__,
cal_cmd[7], cal_cmd[8], cal_cmd[9], cal_cmd[10]);
if ((i2c_master_send(client, cal_cmd, sizeof(cal_cmd))) != sizeof(cal_cmd)) {
dev_err(&client->dev, "[elan] %s: i2c_master_send failed\n", __func__);
return -EINVAL;
}
#else
uint8_t cmd[] = {CMD_W_PKT, 0x29, 0x00, 0x01};
//dev_info(&client->dev, "[elan] %s: enter\n", __func__);
printk("[elan] %s: enter\n", __func__);
dev_info(&client->dev, "[elan] dump cmd: %02x, %02x, %02x, %02x\n", cmd[0], cmd[1], cmd[2], cmd[3]);
if ((i2c_master_send(client, cmd, sizeof(cmd))) != sizeof(cmd)) {
dev_err(&client->dev, "[elan] %s: i2c_master_send failed\n", __func__);
return -EINVAL;
}
#endif
return 0;
}
#ifdef ELAN_POWER_SOURCE
static unsigned now_usb_cable_status=0;
#if 0
static int elan_ktf_ts_hw_reset(struct i2c_client *client)
{
struct elan_ktf_ts_data *ts = i2c_get_clientdata(client);
touch_debug(DEBUG_INFO, "[ELAN] Start HW reset!\n");
gpio_direction_output(ts->rst_gpio, 0);
usleep_range(1000,1500);
gpio_direction_output(ts->rst_gpio, 1);
msleep(5);
return 0;
}
static int elan_ktf_ts_set_power_source(struct i2c_client *client, u8 state)
{
uint8_t cmd[] = {CMD_W_PKT, 0x40, 0x00, 0x01};
int length = 0;
dev_dbg(&client->dev, "[elan] %s: enter\n", __func__);
/*0x52 0x40 0x00 0x01 => Battery Mode
0x52 0x41 0x00 0x01 => AC Adapter Mode
0x52 0x42 0x00 0x01 => USB Mode */
cmd[1] |= state & 0x0F;
dev_dbg(&client->dev,
"[elan] dump cmd: %02x, %02x, %02x, %02x\n",
cmd[0], cmd[1], cmd[2], cmd[3]);
down(&pSem);
length = i2c_master_send(client, cmd, sizeof(cmd));
up(&pSem);
if (length != sizeof(cmd)) {
dev_err(&client->dev,
"[elan] %s: i2c_master_send failed\n", __func__);
return -EINVAL;
}
return 0;
}
static void update_power_source(){
unsigned power_source = now_usb_cable_status;
if(private_ts == NULL || work_lock) return;
if(private_ts->abs_x_max == ELAN_X_MAX) //TF 700T device
return; // do nothing for TF700T;
touch_debug(DEBUG_INFO, "Update power source to %d\n", power_source);
switch(power_source){
case USB_NO_Cable:
elan_ktf_ts_set_power_source(private_ts->client, 0);
break;
case USB_Cable:
elan_ktf_ts_set_power_source(private_ts->client, 1);
break;
case USB_AC_Adapter:
elan_ktf_ts_set_power_source(private_ts->client, 2);
}
}
#endif
void touch_callback(unsigned cable_status){
now_usb_cable_status = cable_status;
//update_power_source();
}
#endif
static int elan_ktf_ts_recv_data(struct i2c_client *client, uint8_t *buf, int bytes_to_recv)
{
int rc;
if (buf == NULL)
return -EINVAL;
memset(buf, 0, bytes_to_recv);
/* The ELAN_PROTOCOL support normanl packet format */
#ifdef ELAN_PROTOCOL
rc = i2c_master_recv(client, buf, bytes_to_recv);
//printk("[elan] Elan protocol rc = %d \n", rc);
if (rc != bytes_to_recv) {
dev_err(&client->dev, "[elan] %s: i2c_master_recv error?! \n", __func__);
return -1;
}
#else
rc = i2c_master_recv(client, buf, bytes_to_recv);
if (rc != 8)
{
printk("[elan] Read the first package error.\n");
mdelay(30);
return -1;
}
printk("[elan_debug] %x %x %x %x %x %x %x %x\n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
mdelay(1);
if (buf[0] == 0x6D){ //for five finger
rc = i2c_master_recv(client, buf+ 8, 8);
if (rc != 8)
{
printk("[elan] Read the second package error.\n");
mdelay(30);
return -1;
}
printk("[elan_debug] %x %x %x %x %x %x %x %x\n", buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]);
rc = i2c_master_recv(client, buf+ 16, 2);
if (rc != 2)
{
printk("[elan] Read the third package error.\n");
mdelay(30);
return -1;
}
mdelay(1);
printk("[elan_debug] %x %x \n", buf[16], buf[17]);
}
#endif
//printk("[elan_debug] end ts_work\n");
return rc;
}
#ifdef PROTOCOL_B
/* Protocol B */
static int mTouchStatus[FINGER_NUM] = {0}; /* finger_num=10 */
void force_release_pos(struct i2c_client *client)
{
struct elan_ktf_ts_data *ts = i2c_get_clientdata(client);
int i;
for (i=0; i < FINGER_NUM; i++) {
if (mTouchStatus[i] == 0) continue;
input_mt_slot(ts->input_dev, i);
input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 0);
mTouchStatus[i] = 0;
}
input_sync(ts->input_dev);
}
static inline int elan_ktf_hid_parse_xy(uint8_t *data,
uint16_t *x, uint16_t *y)
{
*x = *y = 0;
*x = (data[6]);
*x <<= 8;
*x |= data[5];
*y = (data[10]);
*y <<= 8;
*y |= data[9];
return 0;
}
static void elan_ktf_ts_report_data(struct i2c_client *client, uint8_t *buf)
{
struct elan_ktf_ts_data *ts = i2c_get_clientdata(client);
struct input_dev *idev = ts->input_dev;
uint16_t x =0, y =0,touch_size, pressure_size;
uint16_t fbits=0;
uint8_t i, num;
uint16_t active = 0;
uint8_t idx, btn_idx;
int finger_num;
int finger_id;
static uint8_t size_index[10] = {35, 35, 36, 36, 37, 37, 38, 38, 39, 39};
int pen_hover = 0;
int pen_down = 0;
uint16_t p = 0;
/* Quanta BU10SW, Stanley Tsao, 2015.12.09, For customized gesture events { */
#ifdef FEATURE_QUANTA_GESTURE_CUSTOMIZATION
//uint8_t LKC_F1 = 0x3b; // Linux Key Code F1
uint8_t TEV_MIN = 0x12; // Touch Event Value Minimum
//uint8_t code_offset = LKC_F1 - TEV_MIN; // (Linux F1 key code 0x3b) - (minimum touch event value)
uint8_t LKC = 0;
#endif
/* Quanta BU10SW, Stanley Tsao, 2015.12.09, For customized gesture events } */
/* for 10 fingers */
if (buf[0] == TEN_FINGERS_PKT){
finger_num = 10;
num = buf[2] & 0x0f;
fbits = buf[2] & 0x30;
fbits = (fbits << 4) | buf[1];
idx=3;
btn_idx=33;
}
/* for 5 fingers */
else if ((buf[0] == MTK_FINGERS_PKT) || (buf[0] == FIVE_FINGERS_PKT)){
finger_num = 5;
num = buf[1] & 0x07;
fbits = buf[1] >>3;
idx=2;
btn_idx=17;
/* Quanta BU10SW, Stanley Tsao, 2015.12.09, For customized gesture events { */
#ifdef FEATURE_QUANTA_GESTURE_CUSTOMIZATION
}else if (buf[0] == QUANTA_GESTURE_PKT){
//finger_num = 1;
#endif
/* Quanta BU10SW, Stanley Tsao, 2015.12.09, For customized gesture events } */
}else{
/* for 2 fingers */
finger_num = 2;
num = buf[7] & 0x03; // for elan old 5A protocol the finger ID is 0x06
fbits = buf[7] & 0x03;
// fbits = (buf[7] & 0x03) >> 1; // for elan old 5A protocol the finger ID is 0x06
idx=1;
btn_idx=7;
}
switch (buf[0]) {
case MTK_FINGERS_PKT:
case TWO_FINGERS_PKT:
case FIVE_FINGERS_PKT:
case TEN_FINGERS_PKT:
for(i = 0; i < finger_num; i++){
active = fbits & 0x1;
if(active || mTouchStatus[i]){
input_mt_slot(ts->input_dev, i);
input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, active);
if(active){
elan_ktf_ts_parse_xy(&buf[idx], &x, &y);
//y=Y_RESOLUTION -y;
touch_size = ((i & 0x01) ? buf[size_index[i]] : (buf[size_index[i]] >> 4)) & 0x0F;
pressure_size = touch_size << 4; // shift left touch size value to 4 bits for max pressure value 255
input_report_abs(idev, ABS_MT_TOUCH_MAJOR, 100);
input_report_abs(idev, ABS_MT_PRESSURE, 100);
/* Quanta BU10SW, Stanley Tsao, 2015.12.16, Rotate clockwise 90 degree { */
#if 1 /* Touch coordinates match with display coordinates */
input_report_abs(idev, ABS_MT_POSITION_X, x);
input_report_abs(idev, ABS_MT_POSITION_Y, y);
#else /* Rotate clockwise 90 degree */
input_report_abs(idev, ABS_MT_POSITION_X, y);
input_report_abs(idev, ABS_MT_POSITION_Y, X_RESOLUTION-x);
#endif
/* Quanta BU10SW, Stanley Tsao, 2015.12.16, Rotate clockwise 90 degree } */
input_report_key(idev, BTN_TOUCH, 1);
if(unlikely(gPrint_point))
touch_debug(DEBUG_INFO, "[elan] finger id=%d x=%d y=%d size=%d press=%d \n", i, x, y, touch_size, pressure_size);
}
}
mTouchStatus[i] = active;
fbits = fbits >> 1;
idx += 3;
}
if (num == 0){
//printk("[ELAN] ALL Finger Up\n");
input_report_key(idev, BTN_TOUCH, 0); //for all finger up
force_release_pos(client);
}
input_sync(idev);
break;
case PEN_PKT:
pen_hover = buf[1] & 0x1;
pen_down = buf[1] & 0x03;
input_mt_slot(ts->input_dev, 0);
input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, pen_hover);
if (pen_hover){
elan_ktf_pen_parse_xy(&buf[0], &x, &y, &p);
//y=Y_RESOLUTION -y;
if (pen_down == 0x01) { /* report hover function */
input_report_abs(idev, ABS_MT_PRESSURE, 0);
input_report_abs(idev, ABS_MT_DISTANCE, 15);
touch_debug(DEBUG_INFO, "[elan pen] Hover DISTANCE=15 \n");
}
else {
input_report_abs(idev, ABS_MT_TOUCH_MAJOR, 20);
input_report_abs(idev, ABS_MT_PRESSURE, p);
touch_debug(DEBUG_INFO, "[elan pen] PEN PRESSURE=%d \n", p);
}
input_report_abs(idev, ABS_MT_POSITION_X, x);
input_report_abs(idev, ABS_MT_POSITION_Y, y);
}
if(unlikely(gPrint_point)) {
touch_debug(DEBUG_INFO, "[elan pen] %x %x %x %x %x %x %x %x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
touch_debug(DEBUG_INFO, "[elan] x=%d y=%d p=%d \n", x, y, p);
}
if (pen_down == 0){
//printk("[ELAN] ALL Finger Up\n");
input_report_key(idev, BTN_TOUCH, 0); //for all finger up
force_release_pos(client);
}
input_sync(idev);
break;
case ELAN_HID_PKT:
finger_num = buf[62];
if (finger_num > 5) finger_num = 5; /* support 5 fingers */
idx=3;
num = 5;
for(i = 0; i < finger_num; i++){
if ((buf[idx]&0x03) == 0x00) active = 0; /* 0x03: finger down, 0x00 finger up */
else active = 1;
if ((buf[idx] & 0x03) == 0) num --;
finger_id = (buf[idx] & 0xfc) >> 2;
input_mt_slot(ts->input_dev, finger_id);
input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, active);
if(active){
elan_ktf_hid_parse_xy(&buf[idx], &x, &y);
//y = Y_RESOLUTION - y;
input_report_abs(idev, ABS_MT_TOUCH_MAJOR, 100);
input_report_abs(idev, ABS_MT_PRESSURE, 100);
input_report_abs(idev, ABS_MT_POSITION_X, x);
input_report_abs(idev, ABS_MT_POSITION_Y, y);
touch_debug(DEBUG_INFO, "[elan hid] i=%d finger_id=%d x=%d y=%d Finger NO.=%d \n", i, finger_id, x, y, finger_num);
}
mTouchStatus[i] = active;
idx += 11;
}
if (num == 0){
printk("[elan] Release ALL Finger\n");
input_report_key(idev, BTN_TOUCH, 0); //for all finger up
force_release_pos(client);
}
input_sync(idev);
break ;
case IamAlive_PKT:
ts->power_mode = POWER_MODE_NORMAL;
/* touch_debug(DEBUG_TRACE,"%x %x %x %x\n",buf[0],buf[1],buf[2],buf[3] ); */
break;
case IDLE_MODE_PKT:
ts->power_mode = POWER_MODE_IDLE;
#ifdef FEATURE_CHECK_TRUE_INTERRUPT
touchINT_cnt = 0;
#endif
break;
/* Quanta BU10SW, Stanley Tsao, 2015.12.09, For customized gesture events { */
#ifdef FEATURE_QUANTA_GESTURE_CUSTOMIZATION
case QUANTA_GESTURE_PKT:
/* Map touch-reported event value to Linux F1-F8 key codes */
LKC = gesture_map_table[buf[1] - TEV_MIN];
/* Report Linux F1-F8 key codes */
//input_event(idev, EV_MSC, MSC_SCAN, LKC);
input_report_key(idev, LKC, 1);
input_sync(idev);
input_report_key(idev, LKC, 0);
input_sync(idev);
printk("[Stanley]%s: QUANTA_GESTURE_PKT, Receive packet type: %x, event value=%x, LKC=%x \n",
__func__, buf[0], buf[1], LKC);
break;
#endif
/* Quanta BU10SW, Stanley Tsao, 2015.12.09, For customized gesture events } */
#ifdef FEATURE_PALM_DETECTION
case PALM_DETECTION_PKT:
input_report_key(idev, KEY_SLEEP, 1);
input_sync(idev);
input_report_key(idev, KEY_SLEEP, 0);
input_sync(idev);
break;
#endif
default:
dev_err(&client->dev,
"[elan] %s: unknown packet type: %0x\n", __func__, buf[0]);
break;
} // end switch
return;
}
#endif
#ifdef PROTOCOL_A
/* Protocol A */
static void elan_ktf_ts_report_data(struct i2c_client *client, uint8_t *buf)
{
struct elan_ktf_ts_data *ts = i2c_get_clientdata(client);
struct input_dev *idev = ts->input_dev;
uint16_t x, y;
uint16_t fbits=0;
uint8_t i, num, reported = 0;
uint8_t idx, btn_idx;
int finger_num;
/* for 10 fingers */
if (buf[0] == TEN_FINGERS_PKT){
finger_num = 10;
num = buf[2] & 0x0f;
fbits = buf[2] & 0x30;
fbits = (fbits << 4) | buf[1];
idx=3;
btn_idx=33;
}
/* for 5 fingers */
else if ((buf[0] == MTK_FINGERS_PKT) || (buf[0] == FIVE_FINGERS_PKT)){
finger_num = 5;
num = buf[1] & 0x07;
fbits = buf[1] >>3;
idx=2;
btn_idx=17;
}else{
/* for 2 fingers */
finger_num = 2;
num = buf[7] & 0x03; // for elan old 5A protocol the finger ID is 0x06
fbits = buf[7] & 0x03;
// fbits = (buf[7] & 0x03) >> 1; // for elan old 5A protocol the finger ID is 0x06
idx=1;
btn_idx=7;
}
switch (buf[0]) {
case MTK_FINGERS_PKT:
case TWO_FINGERS_PKT:
case FIVE_FINGERS_PKT:
case TEN_FINGERS_PKT:
//input_report_key(idev, BTN_TOUCH, 1);
if (num == 0) {
input_report_key(idev, BTN_TOUCH, 0);
#ifdef FEATURE_QUANTA_GESTURE_TO_BOOTLOADER
if(is_quanta_gesture_to_bld_enabled == true)
{
quanta_gesture_clear_bootloader_flag();
}
#endif /* FEATURE_QUANTA_GESTURE_TO_BOOTLOADER */
#ifdef FEATURE_QUANTA_GESTURE_TO_RECOVERY
if(is_quanta_gesture_to_rcvr_enabled == true)
{
quanta_gesture_clear_recovery_flag();
}
#endif
#ifdef ELAN_BUTTON
if (buf[btn_idx] == 0x21)
{
button_state = 0x21;
input_report_key(idev, KEY_BACK, 1);
input_report_key(idev, KEY_BACK, 0);
printk("[elan_debug] button %x \n", buf[btn_idx]);
}
else if (buf[btn_idx] == 0x41)
{
button_state = 0x41;
input_report_key(idev, KEY_HOME, 1);
}
else if (buf[btn_idx] == 0x81)
{
button_state = 0x81;
input_report_key(idev, KEY_MENU, 1);
}
else if (button_state == 0x21)
{
button_state=0;
input_report_key(idev, KEY_BACK, 0);
}
else if (button_state == 0x41)
{
button_state=0;
input_report_key(idev, KEY_HOME, 0);
}
else if (button_state == 0x81)
{
button_state=0;
input_report_key(idev, KEY_MENU, 0);
}
else
{
dev_dbg(&client->dev, "no press\n");
input_mt_sync(idev);
}
#endif
} else {
dev_dbg(&client->dev, "[elan] %d fingers\n", num);
input_report_key(idev, BTN_TOUCH, 1);
for (i = 0; i < finger_num; i++) {
if ((fbits & 0x01)) {
elan_ktf_ts_parse_xy(&buf[idx], &x, &y);
#ifdef FEATURE_QUANTA_GESTURE_TO_BOOTLOADER
if(is_quanta_gesture_to_bld_enabled == true)
{
quanta_gesture_to_bootloader_check(x, y);
}
#endif
#ifdef FEATURE_QUANTA_GESTURE_TO_RECOVERY
if(is_quanta_gesture_to_rcvr_enabled == true)
{
quanta_gesture_to_recovery_check(x, y);
}
#endif
//x = X_RESOLUTION-x;
//y = Y_RESOLUTION-y;
//printk("[elan_debug] %s, x=%x, y=%x\n",__func__, x , y);
input_report_abs(idev, ABS_MT_TRACKING_ID, i);
input_report_abs(idev, ABS_MT_TOUCH_MAJOR, 100);
input_report_abs(idev, ABS_MT_PRESSURE, 80);
input_report_abs(idev, ABS_MT_POSITION_X, x);
input_report_abs(idev, ABS_MT_POSITION_Y, y);
input_mt_sync(idev);
reported++;
if(unlikely(gPrint_point))
touch_debug(DEBUG_INFO, "[elan] finger id=%d x=%d y=%d \n", i, x, y);
} // end if finger status
fbits = fbits >> 1;
idx += 3;
} // end for
}
if (reported)
input_sync(idev);
else {
input_mt_sync(idev);
input_sync(idev);
}
break;
case IamAlive_PKT://0512
ts->power_mode = POWER_MODE_NORMAL;
/* touch_debug(DEBUG_TRACE,"%x %x %x %x\n",buf[0],buf[1],buf[2],buf[3] ); */
break;
case HELLO_PKT:
//touch_debug(DEBUG_ERROR,"[elan] Report Hello packet: %x %x %x %x\n",buf[0],buf[1],buf[2],buf[3] );
printk("[elan] Report Hello packet: %x %x %x %x\n",buf[0],buf[1],buf[2],buf[3]);
break;
case CALIB_PKT:
//touch_debug(DEBUG_ERROR,"[elan] Report Calibration packet: %x %x %x %x\n",buf[0],buf[1],buf[2],buf[3] );
printk("[elan] Report Calibration packet: %x %x %x %x\n",buf[0],buf[1],buf[2],buf[3]);
break;
case IDLE_MODE_PKT:
ts->power_mode = POWER_MODE_IDLE;
#ifdef FEATURE_CHECK_TRUE_INTERRUPT
touchINT_cnt = 0;
#endif
break;
#ifdef FEATURE_PALM_DETECTION
case PALM_DETECTION_PKT:
input_report_key(idev, KEY_SLEEP, 1);
input_sync(idev);
if(is_enalbe_vib) {
printk(KERN_INFO "vibrator_enable\n");
is_enalbe_vib = false;
vibrator_enable(50);
}
input_report_key(idev, KEY_SLEEP, 0);
input_sync(idev);
break;
#endif
default:
dev_err(&client->dev, "[elan] %s: unknown packet type: %0x %0x %0x %0x\n", __func__, buf[0], buf[1], buf[2], buf[3]);
break;
} // end switch
return;
}
#endif
static irqreturn_t elan_ktf_ts_irq_handler(int irq, void *dev_id)
{
int rc;
struct elan_ktf_ts_data *ts = dev_id;
#ifdef ELAN_BUFFER_MODE
uint8_t buf[4+PACKET_SIZE] = { 0 };
uint8_t buf1[PACKET_SIZE] = { 0 };
#else
uint8_t buf[PACKET_SIZE] = { 0 };
#endif
#if defined( ESD_CHECK )
have_interrupts = 1;
#endif
if (gpio_get_value(ts->intr_gpio))
{
printk("[elan] Detected the jitter on INT pin");
return IRQ_HANDLED;
}
#ifdef ELAN_BUFFER_MODE
rc = elan_ktf_ts_recv_data(ts->client, buf,4+PACKET_SIZE);
if (rc < 0)
{
printk("[elan] Received the packet Error.\n");
return IRQ_HANDLED;
}
#else
rc = elan_ktf_ts_recv_data(ts->client, buf, PACKET_SIZE);
if (rc < 0)
{
printk("[elan] Received the packet Error.\n");
return IRQ_HANDLED;
}
#ifdef FEATURE_CHECK_TRUE_INTERRUPT
if(buf[0] == IamAlive_PKT)
{
IamAlive_PKT_INT_cnt +=1;
}
else
{
touchINT_cnt +=1;
}
#endif
#endif
//printk("[elan_debug] %2x,%2x,%2x,%2x,%2x,%2x,%2x,%2x ....., %2x\n",buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],buf[6],buf[7],buf[17]);
#ifndef ELAN_BUFFER_MODE
elan_ktf_ts_report_data(ts->client, buf);
#else
if((buf[0] == HELLO_PKT) || ((buf[0] == CALIB_PKT) && (buf[1] == CALIB_PKT)))
{
elan_ktf_ts_report_data(ts->client, buf);
}
else
elan_ktf_ts_report_data(ts->client, buf+4);
// Second package
if (((buf[0] == 0x63) || (buf[0] == 0x66)) && ((buf[1] == 2) || (buf[1] == 3))) {
rc = elan_ktf_ts_recv_data(ts->client, buf1, PACKET_SIZE);
if (rc < 0){
return IRQ_HANDLED;
}
elan_ktf_ts_report_data(ts->client, buf1);
// Final package
if (buf[1] == 3) {
rc = elan_ktf_ts_recv_data(ts->client, buf1, PACKET_SIZE);
if (rc < 0){
return IRQ_HANDLED;
}
elan_ktf_ts_report_data(ts->client, buf1);
}
}
#endif
return IRQ_HANDLED;
}
static int elan_ktf_ts_register_interrupt(struct i2c_client *client)
{
struct elan_ktf_ts_data *ts = i2c_get_clientdata(client);
int err = 0;
err = request_threaded_irq(ts->irq, NULL, elan_ktf_ts_irq_handler,
IRQF_TRIGGER_LOW /*| IRQF_TRIGGER_FALLING*/ | IRQF_ONESHOT,
client->name, ts);
if (err) {
dev_err(&client->dev, "[elan] %s: request_irq %d failed\n",
__func__, client->irq);
}
/* Quanta BU10SW, Stanley Tsao, 2015.12.25, Defer enabling touch irq { */
#ifdef QUANTA_DEFER_ENABLE_IRQ
printk("[ELAN] disable IRQ %d", ts->client->irq);
if (private_ts != NULL)
printk("[ELAN] disable IRQ %d", private_ts->client->irq);
work_lock=1;
disable_irq(ts->client->irq);
#endif /* QUANTA_DEFER_ENABLE_IRQ */
/* Quanta BU10SW, Stanley Tsao, 2015.12.25, Defer enabling touch irq { */
return err;
}
#ifdef _ENABLE_DBG_LEVEL
/* Quanta BU10SW, Stanley Tsao, 2015.11.17, Add kernel version check { */
#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 10, 0))
static int ektf_proc_read(struct file *file, char __user *userbuf, size_t bytes, loff_t *off)
{
int ret;
ret=0;
return ret;
}
static int ektf_proc_write(struct file *file, const char __user *userbuf, size_t bytes, loff_t *off)
{
}
/* Quanta BU10SW, Stanley Tsao, 2015.11.18, Add for kernel versio above 3.10 { */
struct file_operations elan_touch_proc_fops = {
.owner = THIS_MODULE,
.read = ektf_proc_read,
.write = ektf_proc_write
};
/* Quanta BU10SW, Stanley Tsao, 2015.11.18, Add for kernel versio above 3.10 } */
#else
static int ektf_proc_read(char *buffer, char **buffer_location, off_t offset, int buffer_length, int *eof, void *data )
{
int ret;
touch_debug(DEBUG_MESSAGES, "call proc_read\n");
if(offset > 0) /* we have finished to read, return 0 */
ret = 0;
else
ret = sprintf(buffer, "Debug Level: Release Date: %s\n","2011/10/05");
return ret;
}
static int ektf_proc_write(struct file *file, const char *buffer, unsigned long count, void *data)
{
char procfs_buffer_size = 0;
int i, ret = 0;
unsigned char procfs_buf[PROC_FS_MAX_LEN+1] = {0};
unsigned int command;
procfs_buffer_size = count;
if(procfs_buffer_size > PROC_FS_MAX_LEN )
procfs_buffer_size = PROC_FS_MAX_LEN+1;
if( copy_from_user(procfs_buf, buffer, procfs_buffer_size) )
{
touch_debug(DEBUG_ERROR, " proc_write faied at copy_from_user\n");
return -EFAULT;
}
command = 0;
for(i=0; i<procfs_buffer_size-1; i++)
{
if( procfs_buf[i]>='0' && procfs_buf[i]<='9' )
command |= (procfs_buf[i]-'0');
else if( procfs_buf[i]>='A' && procfs_buf[i]<='F' )
command |= (procfs_buf[i]-'A'+10);
else if( procfs_buf[i]>='a' && procfs_buf[i]<='f' )
command |= (procfs_buf[i]-'a'+10);
if(i!=procfs_buffer_size-2)
command <<= 4;
}
command = command&0xFFFFFFFF;
switch(command){
case 0xF1:
gPrint_point = 1;
break;
case 0xF2:
gPrint_point = 0;
break;
case 0xFF:
ret = elan_ktf_ts_calibrate(private_ts->client);
break;
}
touch_debug(DEBUG_INFO, "Run command: 0x%08X result:%d\n", command, ret);
return count; // procfs_buffer_size;
}
#endif
/* Quanta BU10SW, Stanley Tsao, 2015.11.17, Add kernel version check } */
#endif // #ifdef _ENABLE_DBG_LEV
#if defined(CONFIG_FB)
static int fb_notifier_callback(struct notifier_block *self,
unsigned long event, void *data)
{
struct fb_event *evdata = data;
int *blank;
pm_message_t pmMsg;
struct elan_ktf_ts_data *elan_dev_data =
container_of(self, struct elan_ktf_ts_data, fb_notif);
is_enalbe_vib = false;
printk("%s fb notifier callback event = %ld\n", __func__, event);
if (evdata && evdata->data && elan_dev_data && private_ts->client) {
if (event == FB_EVENT_BLANK) {
blank = evdata->data;
if (*blank == FB_BLANK_UNBLANK)
{
printk("resume\n");
printk(KERN_INFO "set is_enable_vib to true\n");
is_enalbe_vib = true;
elan_ktf_ts_resume(private_ts->client);
}
else if (*blank == FB_BLANK_POWERDOWN)
{
printk("suspend\n");
pmMsg.event = PM_EVENT_SUSPEND;
elan_ktf_ts_suspend(private_ts->client, pmMsg);
}
}
}
return 0;
}
#endif
#if defined( ESD_CHECK )
static void elan_touch_esd_func(struct work_struct *work)
{
//touch_debug(DEBUG_INFO, "[elan esd] %s: enter.......\n", __FUNCTION__); /* elan_dlx */
if( (have_interrupts == 1) || (work_lock == 1) || (suspend_ESD == 1))
{
/* touch_debug(DEBUG_INFO, "[elan esd] : had interrupt not need check\n"); */
}
else
{
/* Reset TP, if touch controller no any response */
touch_debug(DEBUG_INFO, "[elan esd] : touch controller no any response, reset TP\n");
elan_ktf_ts_hw_reset();
}
have_interrupts = 0;
queue_delayed_work( esd_wq, &esd_work, delay );
/* touch_debug(DEBUG_INFO, "[elan esd] %s: exit.......\n", __FUNCTION__ );*/ /* elan_dlx */
}
#endif
/* Quanta BU10SW, Stanley Tsaos, 2015.12.03, Add VDD, VDDIO control function { */
static int elan_ktf_power_init(struct elan_ktf_ts_data *data, bool on)
{
int rc;
printk("[Stanley]%s \n", __func__);
if (!on)
{
dev_err(&data->client->dev, "elan_ktf_power_init false \n");
goto pwr_deinit;
}
data->vdd = regulator_get(&data->client->dev, "vdd");
if (IS_ERR(data->vdd)) {
rc = PTR_ERR(data->vdd);
dev_err(&data->client->dev, "Regulator get failed vdd rc=%d\n", rc);
return rc;
}
if (regulator_count_voltages(data->vdd) > 0) {
rc = regulator_set_voltage(data->vdd, ELAN_KTF_VTG_MIN_UV, ELAN_KTF_VTG_MAX_UV);
if (rc) {
dev_err(&data->client->dev, "Regulator set_vtg failed vdd rc=%d\n", rc);
goto reg_vdd_put;
}
}
data->vcc_i2c = regulator_get(&data->client->dev, "vcc_i2c");
if (IS_ERR(data->vcc_i2c)) {
rc = PTR_ERR(data->vcc_i2c);
dev_err(&data->client->dev, "Regulator get failed vcc_i2c rc=%d\n", rc);
goto reg_vdd_set_vtg;
}
if (regulator_count_voltages(data->vcc_i2c) > 0) {
rc = regulator_set_voltage(data->vcc_i2c, ELAN_KTF_I2C_VTG_MIN_UV, ELAN_KTF_I2C_VTG_MAX_UV);
if (rc) {
dev_err(&data->client->dev, "Regulator set_vtg failed vcc_i2c rc=%d\n", rc);
goto reg_vcc_i2c_put;
}
}
return 0;
reg_vcc_i2c_put:
regulator_put(data->vcc_i2c);
reg_vdd_set_vtg:
if (regulator_count_voltages(data->vdd) > 0)
regulator_set_voltage(data->vdd, 0, ELAN_KTF_VTG_MAX_UV);
reg_vdd_put:
regulator_put(data->vdd);
return rc;
pwr_deinit:
if (regulator_count_voltages(data->vdd) > 0)
regulator_set_voltage(data->vdd, 0, ELAN_KTF_VTG_MAX_UV);
regulator_put(data->vdd);
if (regulator_count_voltages(data->vcc_i2c) > 0)
regulator_set_voltage(data->vcc_i2c, 0, ELAN_KTF_I2C_VTG_MAX_UV);
regulator_put(data->vcc_i2c);
return 0;
}
static int elan_ktf_power_on(struct elan_ktf_ts_data *data, bool on)
{
int rc = 0;
printk("[Stanley]%s: on=%d \n", __func__, on);
if (!on)
{
printk("[Stanley] Enter %s false ! \n", __func__);
goto power_off;
}
rc = regulator_enable(data->vdd);
if (rc) {
dev_err(&data->client->dev, "Regulator vdd enable failed rc=%d\n", rc);
return rc;
}
rc = regulator_enable(data->vcc_i2c);
if (rc) {
dev_err(&data->client->dev, "Regulator vcc_i2c enable failed rc=%d\n", rc);
regulator_disable(data->vdd);
}
return rc;
power_off:
rc = regulator_disable(data->vdd);
if (rc) {
dev_err(&data->client->dev, "Regulator vdd disable failed rc=%d\n", rc);
return rc;
}
rc = regulator_disable(data->vcc_i2c);
if (rc) {
dev_err(&data->client->dev, "Regulator vcc_i2c disable failed rc=%d\n", rc);
rc = regulator_enable(data->vdd);
if (rc) {
dev_err(&data->client->dev,
"Regulator vdd enable failed rc=%d\n", rc);
}
}
return rc;
}
/* Quanta BU10SW, Stanley Tsao, 2015.12.03, Add VDD, VDDIO control function } */
static int elan_ktf_ts_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int err = 0;
int fw_err = 0;
struct elan_ktf_i2c_platform_data *pdata;
struct elan_ktf_ts_data *ts;
int New_FW_ID;
int New_FW_VER;
//struct task_struct *fw_update_thread;
printk("[Stanley]%s called \n", __func__);
/* Quanta BU10SW, Stanley Tsao, 2015.12.01, parse device tree { */
if (client->dev.of_node) {
printk("[Stanley]%s: client->dev.of_node exists \n", __func__);
pdata = devm_kzalloc(&client->dev, sizeof(struct elan_ktf_i2c_platform_data), GFP_KERNEL);
if (!pdata) {
dev_err(&client->dev, "Failed to allocate memory\n");
return -ENOMEM;
}
err = elan_ktf_parse_dt(&client->dev, pdata);
if (err) {
dev_err(&client->dev, "DT parsing failed\n");
//return err;
}
printk("[Stanley]%s: parse elan touch dt done \n", __func__);
}
else
pdata = client->dev.platform_data;
/* Quanta BU10SW, Stanley Tsao, 2015.12.01, parse device tree } */
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
printk(KERN_ERR "[elan] %s: i2c check functionality error\n", __func__);
err = -ENODEV;
goto err_check_functionality_failed;
}
ts = kzalloc(sizeof(struct elan_ktf_ts_data), GFP_KERNEL);
if (ts == NULL) {
printk(KERN_ERR "[elan] %s: allocate elan_ktf_ts_data failed\n", __func__);
err = -ENOMEM;
goto err_alloc_data_failed;
}
/* Quanta BU10SW, Stanley Tsao, 2015.12.25, Assign pointer right after memory allocation for ts { */
private_ts = ts;
/* Quanta BU10SW, Stanley Tsao, 2015.12.25, Assign pointer right after memory allocation for ts } */
printk("[Stanley]%s current MT protocol=%s \n", __func__, CURRENT_MT_PROTOCOL); // Stanley dbg
ts->client = client;
i2c_set_clientdata(client, ts);
mutex_init(&ktf_mutex);
// james: maybe remove
/*Quanta BU10SW, Stanley Tsao, 2015.12.03, Remove old code { */
#if 0
pdata = client->dev.platform_data;
if (likely(pdata != NULL)) {
ts->intr_gpio = pdata->intr_gpio;
printk("[Stanley]%s: set intr_gpio elan_ktf_ts_data \n", __func__);
}
#endif
ts->intr_gpio = pdata->intr_gpio;
ts->irq = gpio_to_irq(pdata->intr_gpio);
/*Quanta BU10SW, Stanley Tsao, 2015.12.03, Remove old code { */
/* Quanta BU10SW, Stalney Tsao, 2015.12.25, set reset pin from device tree { */
ts->rst_gpio = pdata->rst_gpio;
/* Quanta BU10SW, Stalney Tsao, 2015.12.25, set reset pin from device tree } */
/* Quanta BU10SW, Stanley Tsao, 2015.12.03, Add VDD, VDDIO control function { */
err = elan_ktf_power_init(ts, true);
if(err) {
dev_err(&client->dev, "elan_ktf_power_init power init failed");
goto unreg_inputdev;
}
err = elan_ktf_power_on(ts, true);
if (err) {
dev_err(&client->dev, "power on failed");
goto pwr_deinit;
}
/* Quanta BU10SW, Stanley Tsao, 2015.12.03, Add VDD, VDDIO control function } */
/* Quanta, BU10SW, Stanley Tsao, 2015.12.22, enable pinctrl usage for msm8909 { */
#ifdef MSM_NEW_VER
err = elan_ktf_ts_pinctrl_init(ts);
if (!err && ts->ts_pinctrl) {
/*
* Pinctrl handle is optional. If pinctrl handle is found
* let pins to be configured in active state. If not
* found continue further without error.
*/
err = pinctrl_select_state(ts->ts_pinctrl,
ts->pinctrl_state_active);
if (err < 0) {
dev_err(&client->dev,
"failed to select pin to active state");
}
}
#endif
/* Quanta, BU10SW, Stanley Tsao, 2015.12.22, enable pinctrl usage for msm8909 } */
elan_ktf_ts_hw_reset();
err = gpio_request(private_ts->intr_gpio, "elan_ktf_irq_gpio");
if (err)
dev_err(&client->dev,
"Request elan irq gpio failed\n");
gpio_direction_input(private_ts->intr_gpio);
fw_err = elan_ktf_ts_setup(client);
/* Quanta BU10SW, Stanley Tsao, 2015.12.14, Hello packet is 0, return ENODEV { */
if(fw_err == -ENODEV)
{
printk("[Stanley]%s: elan_ktf_ts_setup() failed, error=%d \n", __func__, fw_err);
/* Power off VDD, VDDIO */
elan_ktf_power_on(ts, false);
printk("[Stanley]%s: power off vdd, vddio \n", __func__);
elan_ktf_power_init(ts,false);
printk("[Stanley]%s: Deinit power \n", __func__);
kfree(ts);
return fw_err;
}
/* Quanta BU10SW, Stanley Tsao, 2015.12.14, Hello packet is 0, return ENODEV } */
if (fw_err < 0) {
printk(KERN_INFO "No Elan chip inside\n");
// fw_err = -ENODEV;
}
wake_lock_init(&ts->wakelock, WAKE_LOCK_SUSPEND, "elan-touchscreen");
ts->input_dev = input_allocate_device();
if (ts->input_dev == NULL) {
err = -ENOMEM;
dev_err(&client->dev, "[elan] Failed to allocate input device\n");
goto err_input_dev_alloc_failed;
}
ts->input_dev->name = "elan-touchscreen";
#ifdef PROTOCOL_A
set_bit(BTN_TOUCH, ts->input_dev->keybit);
#endif
#ifdef ELAN_BUTTON
set_bit(KEY_BACK, ts->input_dev->keybit);
set_bit(KEY_MENU, ts->input_dev->keybit);
set_bit(KEY_HOME, ts->input_dev->keybit);
set_bit(KEY_SEARCH, ts->input_dev->keybit);
#endif
#ifdef PROTOCOL_B
/* Quanta BU10SW, Stanley Tsao, 2015.11.17, Add kernel version check { */
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 7, 0))
input_mt_init_slots(ts->input_dev, FINGER_NUM);
#else
input_mt_init_slots(ts->input_dev, FINGER_NUM, 0);
#endif
/* Quanta BU10SW, Stanley Tsao, 2015.11.17, Add kernel version check } */
#endif
#ifdef PROTOCOL_A
input_set_abs_params(ts->input_dev, ABS_X, 0, X_RESOLUTION, 0, 0);
input_set_abs_params(ts->input_dev, ABS_Y, 0, Y_RESOLUTION, 0, 0);
input_set_abs_params(ts->input_dev, ABS_TOOL_WIDTH, 0, MAX_FINGER_SIZE, 0, 0);
input_set_abs_params(ts->input_dev, ABS_MT_TRACKING_ID, 0, FINGER_NUM, 0, 0);
#endif
input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, 0, Y_RESOLUTION, 0, 0);
input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, 0, X_RESOLUTION, 0, 0);
input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, MAX_FINGER_SIZE, 0, 0);
input_set_abs_params(ts->input_dev, ABS_PRESSURE, 0, MAX_FINGER_SIZE, 0, 0);
input_set_abs_params(ts->input_dev, ABS_MT_PRESSURE, 0, MAX_FINGER_SIZE, 0, 0);
input_set_abs_params(ts->input_dev, ABS_MT_DISTANCE, 0, MAX_FINGER_SIZE, 0, 0);
__set_bit(EV_ABS, ts->input_dev->evbit);
__set_bit(EV_SYN, ts->input_dev->evbit);
__set_bit(EV_KEY, ts->input_dev->evbit);
__set_bit(BTN_TOUCH, ts->input_dev->keybit);
/* Quanta BU10SW, Stanley Tsao, 2015.11.23, Add Quanta customized gesture events {*/
#ifdef FEATURE_QUANTA_GESTURE_CUSTOMIZATION
__set_bit(EV_MSC, ts->input_dev->evbit);
__set_bit(KEY_F1,ts->input_dev->keybit);
__set_bit(KEY_F2,ts->input_dev->keybit);
__set_bit(KEY_F3,ts->input_dev->keybit);
__set_bit(KEY_F4,ts->input_dev->keybit);
__set_bit(KEY_F5,ts->input_dev->keybit);
__set_bit(KEY_F6,ts->input_dev->keybit);
__set_bit(KEY_F7,ts->input_dev->keybit);
__set_bit(KEY_F8,ts->input_dev->keybit);
printk("[Stanley]%s set KEY_F1~F8 keybit \n", __func__);
input_set_capability(ts->input_dev, EV_MSC, MSC_SCAN);
#endif
/* Quanta BU10SW, Stanley Tsao, 2015.11.23, Add Quanta customized gesture events }*/
#ifdef FEATURE_PALM_DETECTION
__set_bit(KEY_SLEEP, ts->input_dev->keybit);
#endif
input_set_capability(ts->input_dev, EV_KEY, KEY_POWER);
err = input_register_device(ts->input_dev);
if (err) {
dev_err(&client->dev,
"[elan]%s: unable to register %s input device\n",
__func__, ts->input_dev->name);
goto err_input_register_device_failed;
}
/* Quanta BU10SW, Stanley Tsao, 2015.12.03, Add VDD, VDDIO control function { */
#if 0
err = elan_ktf_power_init(ts, true);
if(err) {
dev_err(&client->dev, "elan_ktf_power_init power init failed");
goto unreg_inputdev;
}
err = elan_ktf_power_on(ts, true);
if (err) {
dev_err(&client->dev, "power on failed");
goto pwr_deinit;
}
#endif
/* Quanta BU10SW, Stanley Tsao, 2015.12.03, Add VDD, VDDIO control function } */
elan_ktf_ts_register_interrupt(ts->client);
/* Quanta BU10SW, Stanley Tsao, 2015.12.25, Assign pointer right after memory allocation for ts { */
//private_ts = ts;
/* Quanta BU10SW, Stanley Tsao, 2015.12.25, Assign pointer right after memory allocation for ts } */
elan_ktf_touch_sysfs_init();
dev_info(&client->dev, "[elan] Start touchscreen %s in interrupt mode\n",
ts->input_dev->name);
// Firmware Update
ts->firmware.minor = MISC_DYNAMIC_MINOR;
ts->firmware.name = "elan-iap";
ts->firmware.fops = &elan_touch_fops;
ts->firmware.mode = S_IFREG|S_IRWXUGO;
if (misc_register(&ts->firmware) < 0)
printk("[elan]misc_register failed!!\n");
else
printk("[elan]misc_register finished!!\n");
// End Firmware Update
/* register sysfs */
if (sysfs_create_group(&client->dev.kobj, &elan_attribute_group))
dev_err(&client->dev, "sysfs create group error\n");
#ifdef IAP_PORTION
if(0)
{
printk("[elan]misc_register finished!!\n");
work_lock=1;
disable_irq(ts->client->irq);
//cancel_work_sync(&ts->work);
power_lock = 1;
/* FW ID & FW VER*/
/* for ektf31xx iap ekt file */
printk("[elan] [7bd8]=0x%02x, [7bd9]=0x%02x, [7bda]=0x%02x, [7bdb]=0x%02x\n", file_fw_data[31704],file_fw_data[31705],file_fw_data[31706],file_fw_data[31707]);
New_FW_ID = file_fw_data[31707]<<8 | file_fw_data[31708] ;
New_FW_VER = file_fw_data[31705]<<8 | file_fw_data[31704] ;
printk("[elan] FW_ID=0x%x, New_FW_ID=0x%x\n", FW_ID, New_FW_ID);
printk("[elan] FW_VERSION=0x%x, New_FW_VER=0x%x\n", FW_VERSION , New_FW_VER);
/* for firmware auto-upgrade
if (New_FW_ID == FW_ID){
if (New_FW_VER > (FW_VERSION))
{
Update_FW_One(0);
//Update_FW_in_Driver(client, RECOVERY);
}
else
printk("No need to update fw.\n");
} else {
printk("FW_ID is different!");
}
*/
/*
if (FW_ID == 0) RECOVERY=0x80;
Update_FW_One(0);
//Update_FW_in_Driver(client, RECOVERY);
*/
power_lock = 0;
work_lock=0;
enable_irq(ts->client->irq);
}
#endif
#if 0
read_test();
fw_update_thread = kthread_run(Update_FW_One, NULL, "elan_update");
if(IS_ERR(fw_update_thread))
{
printk("[elan] failed to create kernel thread\n");
}
#endif
#ifdef _ENABLE_DBG_LEVEL
/* Quanta BU10SW, Stanley Tsao, 2015.11.17, Add kernel version check { */
#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 10, 0))
dbgProcFile = proc_create(PROC_FS_NAME, 0600, NULL, &elan_touch_proc_fops);
if (dbgProcFile == NULL)
{
touch_debug(DEBUG_INFO, " Could not initialize /proc/%s\n", PROC_FS_NAME);
}
#else
dbgProcFile = create_proc_entry(PROC_FS_NAME, 0600, NULL);
if (dbgProcFile == NULL)
{
remove_proc_entry(PROC_FS_NAME, NULL);
touch_debug(DEBUG_INFO, " Could not initialize /proc/%s\n", PROC_FS_NAME);
}
else
{
dbgProcFile->read_proc = ektf_proc_read;
dbgProcFile->write_proc = ektf_proc_write;
touch_debug(DEBUG_INFO, " /proc/%s created\n", PROC_FS_NAME);
}
#endif
/* Quanta BU10SW, Stanley Tsao, 2015.11.17, Add kernel version check } */
#endif // #ifdef _ENABLE_DBG_LEVEL
#if defined(CONFIG_FB)
private_ts->fb_notif.notifier_call = fb_notifier_callback;
fb_register_client(&private_ts->fb_notif);
#endif
#if defined( ESD_CHECK ) //0604
INIT_DELAYED_WORK( &esd_work, elan_touch_esd_func );
esd_wq = create_singlethread_workqueue( "esd_wq" );
if( !esd_wq )
{
printk("[elan] failed to create esd thread\n");
}
queue_delayed_work( esd_wq, &esd_work, delay );
#endif
/* Quanta BU10SW, Stanley Tsao, 2015.12.25, Defer enabling touch irq { */
printk("[Stanley]%s: INIT_DEFERRABLE_WORK \n", __func__);
printk("[Stanley]%s: INIT_DEFERRABLE_WORK\n", __func__);
INIT_DEFERRABLE_WORK(&ts->workd, elan_work);
schedule_delayed_work(&ts->workd, msecs_to_jiffies(DEFER_ENABLE_IRQ_TIMER_MS));
/* Quanta BU10SW, Stanley Tsao, 2015.12.25, Defer enabling touch irq { */
return 0;
err_input_register_device_failed:
if (ts->input_dev)
input_free_device(ts->input_dev);
err_input_dev_alloc_failed:
kfree(ts);
#ifdef _ENABLE_DBG_LEVEL
remove_proc_entry(PROC_FS_NAME, NULL);
#endif
err_alloc_data_failed:
err_check_functionality_failed:
/* Quanta BU10SW, Stanley Tsao, 2015.12.03, Add VDD, VDDIO control function { */
unreg_inputdev:
input_unregister_device(ts->input_dev);
ts->input_dev = NULL;
pwr_deinit:
elan_ktf_power_init(ts, false);
/* Quanta BU10SW, Stanley Tsao, 2015.12.03, Add VDD, VDDIO control function } */
return err;
}
static int elan_ktf_ts_remove(struct i2c_client *client)
{
struct elan_ktf_ts_data *ts = i2c_get_clientdata(client);
elan_touch_sysfs_deinit();
//unregister_early_suspend(&ts->early_suspend);
free_irq(client->irq, ts);
gpio_free(private_ts->intr_gpio);
/* Quanta BU10SW, Stanley Tsao, 2015.12.03, Add VDD, VDDIO control function { */
elan_ktf_power_on(ts, false);
elan_ktf_power_init(ts, false);
/* Quanta BU10SW, Stanley Tsao, 2015.12.03, Add VDD, VDDIO control function } */
input_unregister_device(ts->input_dev);
kfree(ts);
return 0;
}
static int elan_ktf_ts_set_power_state(struct i2c_client *client, int state)
{
uint8_t cmd[] = {CMD_W_PKT, 0x50, 0x00, 0x01};
dev_dbg(&client->dev, "[elan] %s: enter\n", __func__);
if (state == PWR_STATE_DEEP_SLEEP || state == PWR_STATE_NORMAL)
{
cmd[1] |= (state << 3);
}else if (state == PWR_STATE_IDLE) {
cmd[1] = 0x52;
}else {
printk("[elan]%s: unknown state:%d \n", __func__, state);
return -EINVAL;;
}
dev_dbg(&client->dev,
"[elan] dump cmd: %02x, %02x, %02x, %02x\n",
cmd[0], cmd[1], cmd[2], cmd[3]);
if ((i2c_master_send(client, cmd, sizeof(cmd))) != sizeof(cmd)) {
dev_err(&client->dev,
"[elan] %s: i2c_master_send failed\n", __func__);
return -EINVAL;
}
return 0;
}
static int elan_ktf_ts_get_power_state(struct i2c_client *client)
{
int rc = 0;
uint8_t cmd[] = {CMD_R_PKT, 0x50, 0x00, 0x01};
uint8_t buf[4], power_state;
disable_irq(private_ts->client->irq); //prevent from receving by report function 20160420
rc = elan_ktf_ts_get_data(client, cmd, buf, 4, 4);
enable_irq(private_ts->client->irq);
if (rc)
return rc;
power_state = buf[1];
dev_dbg(&client->dev, "[elan] dump repsponse: %0x\n", power_state);
power_state = (power_state & PWR_STATE_MASK) >> 3;
dev_err(&client->dev, "[elan] power state = %s\n", power_state == PWR_STATE_DEEP_SLEEP ? "Deep Sleep" : "Normal/Idle");
return power_state;
}
static int elan_ktf_ts_suspend(struct i2c_client *client, pm_message_t mesg)
{
/* Quanta, BU10SW, Stanley Tsao, 2015.12.22, enable pinctrl usage for msm8909 { */
#ifdef MSM_NEW_VER
struct elan_ktf_ts_data *data = i2c_get_clientdata(client);
int err;
#endif
/* Quanta, BU10SW, Stanley Tsao, 2015.12.22, enable pinctrl usage for msm8909 } */
int rc = 0;
#ifdef FEATURE_CHECK_TRUE_INTERRUPT
touchINT_cnt = 0;
IamAlive_PKT_INT_cnt = 0;
#endif
if(power_lock==0) /* The power_lock can be removed when firmware upgrade procedure will not be enter into suspend mode. */
{
printk(KERN_INFO "[elan] %s: enter\n", __func__);
rc = elan_ktf_ts_set_power_state(client, PWR_STATE_IDLE);
}
#if defined( ESD_CHECK )
suspend_ESD = 1;
#endif
/* Quanta, BU10SW, Stanley Tsao, 2015.12.22, enable pinctrl usage for msm8909 { */
#ifdef MSM_NEW_VER
if (data->ts_pinctrl) {
err = pinctrl_select_state(data->ts_pinctrl,
data->pinctrl_state_suspend);
if (err < 0)
dev_err(&client->dev, "Cannot get suspend pinctrl state\n");
}
#endif
/* Quanta, BU10SW, Stanley Tsao, 2015.12.22, enable pinctrl usage for msm8909 } */
gpio_direction_input(private_ts->intr_gpio);
enable_irq_wake(private_ts->irq);
return 0;
}
static int elan_ktf_ts_resume(struct i2c_client *client)
{
/* Quanta, BU10SW, Stanley Tsao, 2015.12.22, enable pinctrl usage for msm8909 { */
#ifdef MSM_NEW_VER
struct elan_ktf_ts_data *data = i2c_get_clientdata(client);
int err;
#endif
/* Quanta, BU10SW, Stanley Tsao, 2015.12.22, enable pinctrl usage for msm8909 } */
int rc = 0, retry = 3;
#ifdef RE_CALIBRATION
uint8_t buf_recv[4] = { 0 };
#endif
if(power_lock==0) /* The power_lock can be removed when firmware upgrade procedure will not be enter into suspend mode. */
{
printk(KERN_INFO "[elan] %s: enter\n", __func__);
#ifdef ELAN_RESUME_RST
printk("[elan] %s: Used Rest instead of command to resume touch panel\n", __func__);
elan_ktf_ts_hw_reset();
/* return 0; */
#endif
do {
/* eWD1000 resumes by HW, driver does not have to set power state */
#if 0
rc = elan_ktf_ts_set_power_state(client, PWR_STATE_NORMAL);
mdelay(200);
#endif
#ifdef RE_CALIBRATION
rc = i2c_master_recv(client, buf_recv, 4);
printk("[elan] %s: Re-Calibration Packet %2x:%2x:%2x:%2x\n", __func__, buf_recv[0], buf_recv[1], buf_recv[2], buf_recv[3]);
if (buf_recv[0] != 0x66) {
mdelay(200);
rc = i2c_master_recv(client, buf_recv, 4);
printk("[elan] %s: Re-Calibration Packet, re-try again %2x:%2x:%2x:%2x\n", __func__, buf_recv[0], buf_recv[1], buf_recv[2], buf_recv[3]);
}
#endif
rc = elan_ktf_ts_get_power_state(client);
if (rc != PWR_STATE_NORMAL)
printk(KERN_ERR "[elan] %s: wake up tp failed! err = %d\n", __func__, rc);
else
break;
} while (--retry);
}
#if defined( ESD_CHECK )
suspend_ESD = 0;
#endif
/* Quanta, BU10SW, Stanley Tsao, 2015.12.22, enable pinctrl usage for msm8909 { */
#ifdef MSM_NEW_VER
if (data->ts_pinctrl) {
err = pinctrl_select_state(data->ts_pinctrl,
data->pinctrl_state_active);
if (err < 0)
dev_err(&client->dev, "Cannot get active pinctrl state\n");
}
#endif
/* Quanta, BU10SW, Stanley Tsao, 2015.12.22, enable pinctrl usage for msm8909 } */
return 0;
}
static const struct i2c_device_id elan_ktf_ts_id[] = {
{ ELAN_KTF_NAME, 0 },
{ }
};
/* Quanta BU10SW, Stanley Tsao, 2015.12.03, Add for support of device tree { */
#ifdef CONFIG_OF
static struct of_device_id elan_ktf_match_table[] = {
{ .compatible = ELAN_KTF_NAME,},
{ },
};
#else
#define elan_ktf_match_table NULL
#endif
/* Quanta BU10SW, Stanley Tsao, 2015.12.03, Add for support of device tree } */
static struct i2c_driver ektf_ts_driver = {
.probe = elan_ktf_ts_probe,
.remove = elan_ktf_ts_remove,
.suspend = elan_ktf_ts_suspend,
.resume = elan_ktf_ts_resume,
.id_table = elan_ktf_ts_id,
.driver = {
.name = ELAN_KTF_NAME,
/* Quanta BU10SW, Stanley Tsao, 2015.12.03, Add for support of device tree { */
#ifdef CONFIG_OF
.of_match_table = elan_ktf_match_table,
#endif
/* Quanta BU10SW, Stanley Tsao, 2015.12.03, Add for support of device tree } */
},
};
/* Quanta BU10SW, Stanley Tsao, 2015.11.17, Add kernel version check { */
#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 10, 0))
static int __init elan_ktf_ts_init(void)
#else
static int __devinit elan_ktf_ts_init(void)
#endif
/* Quanta BU10SW, Stanley Tsao, 2015.11.17, Add kernel version check } */
{
printk(KERN_INFO "[elan] %s driver version 0x0005: Integrated 2, 5, and 10 fingers together and auto-mapping resolution\n", __func__);
return i2c_add_driver(&ektf_ts_driver);
}
/* Quanta BU10SW, Stanley Tsao, 2015.11.17, Add kernel version check { */
#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 10, 0))
static void __exit elan_ktf_ts_exit(void)
#else
static void __exit elan_ktf_ts_exit(void)
#endif
/* Quanta BU10SW, Stanley Tsao, 2015.11.17, Add kernel version check } */
{
i2c_del_driver(&ektf_ts_driver);
return;
}
module_init(elan_ktf_ts_init);
module_exit(elan_ktf_ts_exit);
MODULE_DESCRIPTION("ELAN KTF2K Touchscreen Driver");
MODULE_LICENSE("GPL");