blob: 6e4b69935981828d922127429b8e966904b6dd84 [file] [log] [blame]
/* drivers/input/touchscreen/ektf3k.c - ELAN EKTF3K FIFO 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.
*
*/
#define ELAN_BUFFER_MODE
#include <linux/module.h>
#include <linux/input/mt.h>
#include <linux/interrupt.h>
#include <linux/earlysuspend.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>
// 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/wakelock.h>
#define PACKET_SIZE 40
#define NEW_PACKET_SIZE 55
#define FINGER_NUM 10
#define PWR_STATE_DEEP_SLEEP 0
#define PWR_STATE_NORMAL 1
#define PWR_NORMAL_STATE 8
#define PWR_IDLE_STATE 1
#define PWR_STATE_MASK BIT(3)
#define CMD_S_PKT 0x52
#define CMD_R_PKT 0x53
#define CMD_W_PKT 0x54
#define HELLO_PKT 0x55
#define NORMAL_PKT 0x63
#define NEW_NOMARL_PKT 0x66
#define TEN_FINGERS_PKT 0x62
#define RPT_LOCK_PKT 0x56
#define RPT_UNLOCK_PKT 0xA6
#define RESET_PKT 0x77
#define CALIB_PKT 0xA8
#define IDX_FINGER 3
#define MAX_FINGER_SIZE 31
#define MAX_FINGER_PRESSURE 255
#define ABS_MT_POSITION 0x2a /* Group a set of X and Y */
#define ABS_MT_AMPLITUDE 0x2b /* Group a set of Z and W */
#include <linux/i2c/ektf3k.h>
// For Firmware Update
#define ELAN_IOCTLID 0xD0
#define IOCTL_I2C_SLAVE _IOW(ELAN_IOCTLID, 1, int)
#define IOCTL_MAJOR_FW_VER _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_FW_UPDATE _IOR(ELAN_IOCTLID, 22, int)
#define FIRMWARE_UPDATE_WITH_HEADER 1
uint16_t checksum_err=0;
static uint8_t RECOVERY=0x00;
int FW_VERSION=0x00;
int X_RESOLUTION=0x00;
int Y_RESOLUTION=0x00;
int FW_ID=0x00;
static int work_lock=0x00;
#define USB_NO_Cable 0
#define USB_DETECT_CABLE 1
#define USB_SHIFT 0
#define AC_SHIFT 1
#define USB_Cable ((1 << (USB_SHIFT)) | (USB_DETECT_CABLE))
#define USB_AC_Adapter ((1 << (AC_SHIFT)) | (USB_DETECT_CABLE))
#define USB_CALBE_DETECT_MASK (USB_Cable | USB_DETECT_CABLE)
static unsigned now_usb_cable_status=0;
static unsigned int gPrint_point = 0;
#define TOUCH_STRESS_TEST 1
#ifdef TOUCH_STRESS_TEST
#define STRESS_IOC_MAGIC 0xF3
#define STRESS_IOC_MAXNR 4
#define STRESS_POLL_DATA _IOR(STRESS_IOC_MAGIC,2,int )
#define STRESS_IOCTL_START_HEAVY 2
#define STRESS_IOCTL_START_NORMAL 1
#define STRESS_IOCTL_END 0
#define START_NORMAL (HZ/5)
#define START_HEAVY (HZ/200)
static int poll_mode=0;
static struct delayed_work elan_poll_data_work;
static struct workqueue_struct *stress_work_queue;
static atomic_t touch_char_available = ATOMIC_INIT(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_ktf3k_ts_data {
struct i2c_client *client;
struct input_dev *input_dev;
struct workqueue_struct *elan_wq;
struct work_struct work;
int (*power)(int on);
struct early_suspend early_suspend;
int intr_gpio;
// Firmware Information
int fw_ver;
int fw_id;
int x_resolution;
int y_resolution;
// For Firmare Update
struct miscdevice firmware;
struct attribute_group attrs;
int status;
struct switch_dev touch_sdev;
int abs_x_max;
int abs_y_max;
int rst_gpio;
struct wake_lock wakelock;
#ifdef TOUCH_STRESS_TEST
struct miscdevice misc_dev;
#endif
};
static struct elan_ktf3k_ts_data *private_ts = NULL;
static int __fw_packet_handler(struct i2c_client *client, int imediate);
static int elan_ktf3k_ts_rough_calibrate(struct i2c_client *client);
static int elan_ktf3k_ts_hw_reset(struct i2c_client *client);
static int elan_ktf3k_ts_resume(struct i2c_client *client);
#ifdef FIRMWARE_UPDATE_WITH_HEADER
static int firmware_update_header(struct i2c_client *client, const unsigned char *firmware, unsigned int page_number);
#endif
static struct semaphore pSem;
static int mTouchStatus[FINGER_NUM] = {0};
#define FIRMWARE_PAGE_SIZE 132
#define MAX_FIRMWARE_SIZE 32868
#define FIRMWARE_ACK_SIZE 2
/* Debug levels */
#define NO_DEBUG 0
#define DEBUG_ERROR 1
#define DEBUG_INFO 2
#define DEBUG_MESSAGES 5
#define DEBUG_TRACE 10
static int debug = DEBUG_INFO;
#define touch_debug(level, ...) \
do { \
if (debug >= (level)) \
printk("[ektf3k]:" __VA_ARGS__); \
} while (0)
int elan_iap_open(struct inode *inode, struct file *filp){
touch_debug(DEBUG_INFO, "[ELAN]into elan_iap_open\n");
if (private_ts == NULL) touch_debug(DEBUG_ERROR, "private_ts is NULL~~~");
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;
if (count > 8192)
count = 8192;
tmp = kmalloc(count, GFP_KERNEL);
if (tmp == NULL)
return -ENOMEM;
if (copy_from_user(tmp, buff, count)) {
return -EFAULT;
}
ret = i2c_master_send(private_ts->client, tmp, count);
if (ret != count) touch_debug(DEBUG_ERROR, "ELAN i2c_master_send fail, ret=%d \n", ret);
kfree(tmp);
return ret;
}
ssize_t elan_iap_read(struct file *filp, char *buff, size_t count, loff_t *offp){
char *tmp;
int ret;
long rc;
if (count > 8192)
count = 8192;
tmp = kmalloc(count, GFP_KERNEL);
if (tmp == NULL)
return -ENOMEM;
ret = i2c_master_recv(private_ts->client, tmp, count);
if (ret >= 0)
rc = copy_to_user(buff, tmp, count);
kfree(tmp);
return ret;
}
static long elan_iap_ioctl(/*struct inode *inode,*/ struct file *filp, unsigned int cmd, unsigned long arg){
int __user *ip = (int __user *)arg;
touch_debug(DEBUG_INFO, "[ELAN]into elan_iap_ioctl cmd=%u\n", cmd);
switch (cmd) {
case IOCTL_I2C_SLAVE:
private_ts->client->addr = (int __user)arg;
break;
case IOCTL_MAJOR_FW_VER:
break;
case IOCTL_MINOR_FW_VER:
break;
case IOCTL_RESET:
return elan_ktf3k_ts_hw_reset(private_ts->client);
case IOCTL_IAP_MODE_LOCK:
work_lock=1;
disable_irq(private_ts->client->irq);
wake_lock(&private_ts->wakelock);
break;
case IOCTL_IAP_MODE_UNLOCK:
work_lock=0;
enable_irq(private_ts->client->irq);
wake_unlock(&private_ts->wakelock);
break;
case IOCTL_CHECK_RECOVERY_MODE:
return RECOVERY;
break;
case IOCTL_FW_VER:
__fw_packet_handler(private_ts->client, work_lock);
msleep(100);
return FW_VERSION;
break;
case IOCTL_X_RESOLUTION:
__fw_packet_handler(private_ts->client, work_lock);
msleep(100);
return X_RESOLUTION;
break;
case IOCTL_Y_RESOLUTION:
__fw_packet_handler(private_ts->client, work_lock);
msleep(100);
return Y_RESOLUTION;
break;
case IOCTL_FW_ID:
__fw_packet_handler(private_ts->client, work_lock);
msleep(100);
return FW_ID;
break;
case IOCTL_ROUGH_CALIBRATE:
return elan_ktf3k_ts_rough_calibrate(private_ts->client);
case IOCTL_I2C_INT:
put_user(gpio_get_value(private_ts->intr_gpio), ip);
break;
case IOCTL_RESUME:
elan_ktf3k_ts_resume(private_ts->client);
break;
default:
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,
};
/* Detect old / new FW */
static int isOldFW(struct i2c_client *client)
{
struct elan_ktf3k_ts_data *ts = i2c_get_clientdata(client);
touch_debug(DEBUG_MESSAGES, "[elan] GPIO_TP_INT_N=%d\n", ts->intr_gpio);
if (gpio_get_value(ts->intr_gpio) == 0) {
// Old FW
touch_debug(DEBUG_INFO, "[elan]detect intr=>Old FW\n");
return 1;
}
return 0;
}
#ifdef CONFIG_HAS_EARLYSUSPEND
static void elan_ktf3k_ts_early_suspend(struct early_suspend *h);
static void elan_ktf3k_ts_late_resume(struct early_suspend *h);
#endif
static ssize_t elan_ktf3k_gpio_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
int ret = 0;
struct elan_ktf3k_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_ktf3k_gpio_show, NULL);
static ssize_t elan_ktf3k_vendor_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
ssize_t ret = 0;
struct elan_ktf3k_ts_data *ts = private_ts;
sprintf(buf, "%s_x%4.4x\n", "ELAN_KTF3K", ts->fw_ver);
ret = strlen(buf) + 1;
return ret;
}
static DEVICE_ATTR(vendor, S_IRUGO, elan_ktf3k_vendor_show, NULL);
static ssize_t elan_show_status(struct device *dev, struct device_attribute *devattr, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct elan_ktf3k_ts_data *data = i2c_get_clientdata(client);
return sprintf(buf, "%d\n", data->status);
}
DEVICE_ATTR(elan_touchpanel_status, S_IRUGO, elan_show_status, NULL);
static int check_fw_version(const unsigned char*firmware, unsigned int size, int fw_version){
int id, version;
if(size < 2*FIRMWARE_PAGE_SIZE)
return -1;
version = firmware[size - 2*FIRMWARE_PAGE_SIZE + 120] |
(firmware[size - 2*FIRMWARE_PAGE_SIZE + 121] << 8);
id = firmware[size - 2*FIRMWARE_PAGE_SIZE + 122] |
(firmware[size - 2*FIRMWARE_PAGE_SIZE + 123] << 8);
touch_debug(DEBUG_INFO, "The firmware was version 0x%X and id:0x%X\n", version, id);
if(id == 0x3021)
return fw_version == 0xFFFF ? 1 : version - fw_version; // if the touch firmware was empty, always update firmware
else
return 0; // this buffer doesn't contain the touch firmware
}
static ssize_t update_firmware(struct device *dev, struct device_attribute *devattr,const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct elan_ktf3k_ts_data *ts = i2c_get_clientdata(client);
struct file *firmware_fp;
char file_path[100];
unsigned int pos = 0;
mm_segment_t oldfs;
unsigned int page_number;
static unsigned char firmware[MAX_FIRMWARE_SIZE];
int ret = 0, retry = 0;
oldfs=get_fs();
set_fs(KERNEL_DS);
memset(file_path, 0, 100);
sscanf(buf, "%s\n", file_path);
touch_debug(DEBUG_INFO, "Update touch firmware with the file path:%s\n", file_path);
firmware_fp = filp_open(file_path, O_RDONLY, S_IRUSR |S_IRGRP);
if(PTR_ERR(firmware_fp) == -ENOENT){
dev_err(&client->dev, "Error to open file %s\n", file_path);
return -1;
}
//start move the firmware file into memory
firmware_fp->f_pos = 0;
for(pos = 0, page_number = 0; pos < MAX_FIRMWARE_SIZE; pos += FIRMWARE_PAGE_SIZE, page_number++){
if(firmware_fp->f_op->read(firmware_fp, firmware + pos,
FIRMWARE_PAGE_SIZE, &firmware_fp->f_pos) != FIRMWARE_PAGE_SIZE){
break;
}
}
filp_close(firmware_fp, NULL);
// check the firmware ID and version
if(RECOVERY || check_fw_version(firmware, pos, ts->fw_ver) > 0){
touch_debug(DEBUG_INFO, "Firmware update start!\n");
do{
ret = firmware_update_header(client, firmware, page_number);
touch_debug(DEBUG_INFO, "Firmware update finish ret=%d retry=%d !\n", ret, retry++);
}while(ret != 0 && retry < 3);
if(ret == 0 && RECOVERY) RECOVERY = 0;
}else
touch_debug(DEBUG_INFO, "No need to update firmware\n");
return count;
}
DEVICE_ATTR(update_fw, S_IWUSR, NULL, update_firmware);
static struct attribute *elan_attr[] = {
&dev_attr_elan_touchpanel_status.attr,
&dev_attr_vendor.attr,
&dev_attr_gpio.attr,
&dev_attr_update_fw.attr,
NULL
};
static struct kobject *android_touch_kobj;
static int elan_ktf3k_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);
}
static int __elan_ktf3k_ts_poll(struct i2c_client *client)
{
struct elan_ktf3k_ts_data *ts = i2c_get_clientdata(client);
int status = 0, retry = 150;
do {
status = gpio_get_value(ts->intr_gpio);
dev_dbg(&client->dev, "%s: status = %d\n", __func__, status);
retry--;
msleep(20);
} while (status == 1 && retry > 0);
dev_dbg(&client->dev, "[elan]%s: poll interrupt status %s\n",
__func__, status == 1 ? "high" : "low");
return (status == 0 ? 0 : -ETIMEDOUT);
}
static int elan_ktf3k_ts_poll(struct i2c_client *client)
{
return __elan_ktf3k_ts_poll(client);
}
static int elan_ktf3k_ts_get_data(struct i2c_client *client, uint8_t *cmd,
uint8_t *buf, size_t size)
{
int rc;
dev_dbg(&client->dev, "[elan]%s: enter\n", __func__);
if (buf == NULL)
return -EINVAL;
down(&pSem);
rc = i2c_master_send(client, cmd, 4);
up(&pSem);
if(rc != 4){
dev_err(&client->dev,
"[elan]%s: i2c_master_send failed\n", __func__);
return -EINVAL;
}
down(&pSem);
rc = i2c_master_recv(client, buf, size);
up(&pSem);
if(rc != size){
dev_err(&client->dev,
"[elan]%s: i2c_master_read failed\n", __func__);
return -EINVAL;
}
return 0;
}
static int elan_ktf3k_ts_read_command(struct i2c_client *client,
u8* cmd, u16 cmd_length, u8 *value, u16 value_length){
struct i2c_adapter *adapter = client->adapter;
struct i2c_msg msg[2];
__le16 le_addr;
struct elan_ktf3k_ts_data *ts;
int length = 0;
ts = i2c_get_clientdata(client);
msg[0].addr = client->addr;
msg[0].flags = 0x00;
msg[0].len = cmd_length;
msg[0].buf = cmd;
down(&pSem);
length = i2c_transfer(adapter, msg, 1);
up(&pSem);
if (length == 1) // only send on packet
return value_length;
else
return -EIO;
}
static int elan_ktf3k_i2c_read_packet(struct i2c_client *client,
u8 *value, u16 value_length){
struct i2c_adapter *adapter = client->adapter;
struct i2c_msg msg[1];
__le16 le_addr;
struct elan_ktf3k_ts_data *ts;
int length = 0;
ts = i2c_get_clientdata(client);
msg[0].addr = client->addr;
msg[0].flags = I2C_M_RD;
msg[0].len = value_length;
msg[0].buf = (u8 *) value;
down(&pSem);
length = i2c_transfer(adapter, msg, 1);
up(&pSem);
if (length == 1) // only send on packet
return value_length;
else
return -EIO;
}
static int __hello_packet_handler(struct i2c_client *client)
{
int rc;
uint8_t buf_recv[4] = { 0 };
uint8_t buf_recv1[4] = { 0 };
rc = elan_ktf3k_ts_poll(client);
if (rc < 0) {
touch_debug(DEBUG_ERROR, "[elan] %s: IRQ is not low!\n", __func__);
RECOVERY = 1;
}
rc = i2c_master_recv(client, buf_recv, 4);
if(rc < 0){
touch_debug(DEBUG_ERROR, "I2C message no Ack!\n");
return -EINVAL;
}
touch_debug(DEBUG_INFO, "[elan] %s: hello packet %2x:%2X:%2x:%2x\n", __func__, buf_recv[0], buf_recv[1], buf_recv[2], buf_recv[3]);
if(!(buf_recv[0]==0x55 && buf_recv[1]==0x55 && buf_recv[2]==0x55 && buf_recv[3]==0x55)){
RECOVERY=0x80;
return RECOVERY;
}
return 0;
}
static int wait_for_IRQ_Low(struct i2c_client *client, int utime){
struct elan_ktf3k_ts_data *ts = i2c_get_clientdata(client);
int retry_times = 10;
do{
usleep_range(utime,utime + 500);
if(gpio_get_value(ts->intr_gpio) == 0)
return 0;
}while(retry_times-- > 0);
touch_debug("Wait IRQ time out\n");
return -1;
}
static int __fw_packet_handler(struct i2c_client *client, int immediate)
{
struct elan_ktf3k_ts_data *ts = i2c_get_clientdata(client);
int rc;
int major, minor;
uint8_t cmd[] = {CMD_R_PKT, 0x00, 0x00, 0x01};
uint8_t cmd_x[] = {0x53, 0x60, 0x00, 0x00}; /*Get x resolution*/
uint8_t cmd_y[] = {0x53, 0x63, 0x00, 0x00}; /*Get y resolution*/
uint8_t cmd_id[] = {0x53, 0xf0, 0x00, 0x01}; /*Get firmware ID*/
uint8_t buf_recv[4] = {0};
// Firmware version
rc = elan_ktf3k_ts_read_command(client, cmd, 4, buf_recv, 4);
if (rc < 0)
return rc;
if(immediate){
wait_for_IRQ_Low(client, 1000);
elan_ktf3k_i2c_read_packet(client, buf_recv, 4);
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;
touch_debug(DEBUG_INFO, "[elan] %s: firmware version: 0x%4.4x\n", __func__, ts->fw_ver);
}
// X Resolution
rc = elan_ktf3k_ts_read_command(client, cmd_x, 4, buf_recv, 4);
if (rc < 0)
return rc;
if(immediate){
wait_for_IRQ_Low(client, 1000);
elan_ktf3k_i2c_read_packet(client, buf_recv, 4);
minor = ((buf_recv[2])) | ((buf_recv[3] & 0xf0) << 4);
ts->x_resolution =minor;
X_RESOLUTION = ts->x_resolution;
touch_debug(DEBUG_INFO, "[elan] %s: X resolution: 0x%4.4x\n", __func__, ts->x_resolution);
}
// Y Resolution
rc = elan_ktf3k_ts_read_command(client, cmd_y, 4, buf_recv, 4);
if (rc < 0)
return rc;
if(immediate){
wait_for_IRQ_Low(client, 1000);
elan_ktf3k_i2c_read_packet(client, buf_recv, 4);
minor = ((buf_recv[2])) | ((buf_recv[3] & 0xf0) << 4);
ts->y_resolution =minor;
Y_RESOLUTION = ts->y_resolution;
touch_debug(DEBUG_INFO, "[elan] %s: Y resolution: 0x%4.4x\n", __func__, ts->y_resolution);
}
// Firmware ID
rc = elan_ktf3k_ts_read_command(client, cmd_id, 4, buf_recv, 4);
if (rc < 0)
return rc;
if(immediate){
wait_for_IRQ_Low(client, 1000);
elan_ktf3k_i2c_read_packet(client, buf_recv, 4);
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;
touch_debug(DEBUG_INFO, "[elan] %s: firmware id: 0x%4.4x\n", __func__, ts->fw_id);
}
return 0;
}
static inline int elan_ktf3k_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];
return 0;
}
static int elan_ktf3k_ts_setup(struct i2c_client *client)
{
int rc, count = 10;
retry:
// Reset
elan_ktf3k_ts_hw_reset(client);
// Check if old firmware. If not, send the notmal_command to enter normal mode
if( isOldFW(client) == 0 ){ //if check is new bootcode
touch_debug(DEBUG_INFO, "The boot code is new!\n");
}else
touch_debug(DEBUG_INFO, "The boot code is old!\n");
rc = __hello_packet_handler(client);
touch_debug(DEBUG_INFO, "[elan] hello packet's rc = %d\n",rc);
if (rc < 0){
if (rc == -ETIME && count > 0) {
count--;
dev_err(&client->dev, "wait main hello timeout, reset\n");
goto retry;
}
else
goto hand_shake_failed;
}
dev_dbg(&client->dev, "[elan] %s: hello packet got.\n", __func__);
msleep(200);
rc = __fw_packet_handler(client, 1);
if (rc < 0)
goto hand_shake_failed;
dev_dbg(&client->dev, "[elan] %s: firmware checking done.\n", __func__);
hand_shake_failed:
return rc;
}
static int elan_ktf3k_ts_set_power_state(struct i2c_client *client, int state)
{
uint8_t cmd[] = {CMD_W_PKT, 0x50, 0x00, 0x01};
int length;
dev_dbg(&client->dev, "[elan] %s: enter\n", __func__);
cmd[1] |= (state << 3);
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 int elan_ktf3k_ts_rough_calibrate(struct i2c_client *client){
uint8_t cmd[] = {CMD_W_PKT, 0x29, 0x00, 0x01};
int length;
touch_debug(DEBUG_INFO, "[elan] %s: enter\n", __func__);
touch_debug(DEBUG_INFO,
"[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 int elan_ktf3k_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;
rc = elan_ktf3k_ts_get_data(client, cmd, buf, 4);
if (rc)
return rc;
power_state = buf[1];
touch_debug(DEBUG_INFO, "[elan] dump repsponse: %0x\n", power_state);
power_state = power_state & 0x0F;
dev_dbg(&client->dev, "[elan] power state = %s\n",
power_state == PWR_STATE_DEEP_SLEEP ?
"Deep Sleep" : "Normal/Idle");
return power_state;
}
static int elan_ktf3k_ts_hw_reset(struct i2c_client *client)
{
struct elan_ktf3k_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(250);
return 0;
}
static int elan_ktf3k_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 => USB and AC Adapter 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]);
dev_info(&private_ts->client->dev, "Update power source to %d\n", state);
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 int elan_ktf3k_ts_get_power_source(struct i2c_client *client)
{
int rc = 0;
uint8_t cmd[] = {CMD_R_PKT, 0x40, 0x00, 0x01};
uint8_t buf[4] = {0}, power_source;
//rc = elan_ktf2k_ts_get_data(client, cmd, buf, 4);
rc = elan_ktf3k_ts_read_command(client, cmd, 4, buf, 4);
if (rc < 0)
return rc;
return 0;
}
static void update_power_source(){
unsigned power_source = now_usb_cable_status;
if(private_ts == NULL || work_lock) return;
// Send power state 1 if USB cable and AC charger was plugged on.
elan_ktf3k_ts_set_power_source(private_ts->client, power_source != USB_NO_Cable);
}
void touch_callback(unsigned cable_status){
now_usb_cable_status = cable_status;
update_power_source();
}
static int elan_ktf3k_ts_recv_data(struct i2c_client *client, uint8_t *buf, int size)
{
int rc, bytes_to_recv = size;
if (buf == NULL)
return -EINVAL;
memset(buf, 0, bytes_to_recv);
rc = i2c_master_recv(client, buf, bytes_to_recv);
if (rc != bytes_to_recv) {
dev_err(&client->dev,
"[elan] %s: i2c_master_recv error?! \n", __func__);
rc = i2c_master_recv(client, buf, bytes_to_recv);
return -EINVAL;
}
return rc;
}
static void elan_ktf3k_ts_report_data(struct i2c_client *client, uint8_t *buf)
{
struct elan_ktf3k_ts_data *ts = i2c_get_clientdata(client);
struct input_dev *idev = ts->input_dev;
uint16_t x, y, touch_size, pressure_size;
uint16_t fbits=0, checksum=0;
uint8_t i, num;
static uint8_t size_index[10] = {35, 35, 36, 36, 37, 37, 38, 38, 39, 39};
uint16_t active = 0;
uint8_t idx=IDX_FINGER;
num = buf[2] & 0xf;
for (i=0; i<34;i++)
checksum +=buf[i];
if ((num < 3) || ((checksum & 0x00ff) == buf[34])) {
fbits = buf[2] & 0x30;
fbits = (fbits << 4) | buf[1];
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_ktf3k_ts_parse_xy(&buf[idx], &x, &y);
x = x > ts->abs_x_max ? 0 : ts->abs_x_max - x;
y = y > ts->abs_y_max ? ts->abs_y_max : 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, touch_size);
input_report_abs(idev, ABS_MT_PRESSURE, pressure_size);
input_report_abs(idev, ABS_MT_POSITION_X, y);
input_report_abs(idev, ABS_MT_POSITION_Y, x);
if(unlikely(gPrint_point)) touch_debug(DEBUG_INFO, "[elan] finger id=%d X=%d y=%d size=%d pressure=%d\n", i, x, y, touch_size, pressure_size);
}
}
mTouchStatus[i] = active;
fbits = fbits >> 1;
idx += 3;
}
input_sync(idev);
} // checksum
else {
checksum_err +=1;
touch_debug(DEBUG_ERROR, "[elan] Checksum Error %d byte[2]=%X\n", checksum_err, buf[2]);
}
return;
}
static void elan_ktf3k_ts_report_data2(struct i2c_client *client, uint8_t *buf)
{
struct elan_ktf3k_ts_data *ts = i2c_get_clientdata(client);
struct input_dev *idev = ts->input_dev;
uint16_t x, y, touch_size, pressure_size;
uint16_t fbits=0, checksum=0;
uint8_t i, num;
uint16_t active = 0;
uint8_t idx=IDX_FINGER;
num = buf[2] & 0xf;
for (i=0; i<34;i++)
checksum +=buf[i];
if ( (num < 3) || ((checksum & 0x00ff) == buf[34])) {
fbits = buf[2] & 0x30;
fbits = (fbits << 4) | buf[1];
//input_report_key(idev, BTN_TOUCH, 1);
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_ktf3k_ts_parse_xy(&buf[idx], &x, &y);
x = x > ts->abs_x_max ? 0 : ts->abs_x_max - x;
y = y > ts->abs_y_max ? ts->abs_y_max : y;
touch_size = buf[35 + i];
pressure_size = buf[45 + i];
input_report_abs(idev, ABS_MT_TOUCH_MAJOR, touch_size);
input_report_abs(idev, ABS_MT_PRESSURE, pressure_size);
input_report_abs(idev, ABS_MT_POSITION_X, y);
input_report_abs(idev, ABS_MT_POSITION_Y, x);
if(unlikely(gPrint_point)) touch_debug(DEBUG_INFO, "[elan] finger id=%d X=%d y=%d size=%d pressure=%d\n", i, x, y, touch_size, pressure_size);
}
}
mTouchStatus[i] = active;
fbits = fbits >> 1;
idx += 3;
}
input_sync(idev);
} // checksum
else {
checksum_err +=1;
touch_debug(DEBUG_ERROR, "[elan] Checksum Error %d byte[2]=%X\n", checksum_err, buf[2]);
}
return;
}
static void process_resp_message(struct elan_ktf3k_ts_data *ts, const unsigned char *buf,
unsigned int size){
int major, minor;
if(buf == NULL) return;
switch(buf[1] & 0xF0){
case 0x00:// firmware version
major = ((buf[1] & 0x0f) << 4) | ((buf[2] & 0xf0) >> 4);
minor = ((buf[2] & 0x0f) << 4) | ((buf[3] & 0xf0) >> 4);
ts->fw_ver = major << 8 | minor;
FW_VERSION = ts->fw_ver;
break;
case 0x20: // Rough calibrate response
major = buf[2] & 0x0F;
touch_debug(DEBUG_INFO, "Get the Rough Calibrate result:%d\n", major);
break;
case 0x40: // the power source
major = buf[1] & 0x0f;
touch_debug(DEBUG_INFO, "Get the power source:%d\n", major);
case 0x50: // the power state
major = buf[1] & 0x0f;
touch_debug(DEBUG_INFO, "Get the power mode:%d\n", major);
break;
case 0xF0: // firmware id
major = ((buf[1] & 0x0f) << 4) | ((buf[2] & 0xf0) >> 4);
minor = ((buf[2] & 0x0f) << 4) | ((buf[3] & 0xf0) >> 4);
ts->fw_id = major << 8 | minor;
FW_ID = ts->fw_id;
break;
default:
touch_debug(DEBUG_INFO, "[elan] Get unknow packet {0x%02X, 0x%02X, 0x%02X, 0x%02X}\n", buf[0], buf[1], buf[2], buf[3]);
}
}
static void elan_ktf3k_ts_work_func(struct work_struct *work)
{
int rc;
struct elan_ktf3k_ts_data *ts =
container_of(work, struct elan_ktf3k_ts_data, work);
uint8_t buf[NEW_PACKET_SIZE + 4] = { 0 };
uint8_t buf1[NEW_PACKET_SIZE] = { 0 };
uint8_t buf2[NEW_PACKET_SIZE] = { 0 };
if(work_lock!=0) {
touch_debug(DEBUG_INFO, "Firmware update during touch event handling");
enable_irq(ts->client->irq);
return;
}
#ifndef ELAN_BUFFER_MODE
rc = elan_ktf3k_ts_recv_data(ts->client, buf, 40);
#else
down(&pSem);
rc = elan_ktf3k_ts_recv_data(ts->client, buf, 4); // read the first four bytes
#endif
if (rc < 0)
{
up(&pSem);
enable_irq(ts->client->irq);
return;
}
#ifndef ELAN_BUFFER_MODE
elan_ktf3k_ts_report_data(ts->client, buf);
#else
switch(buf[0]){
case NORMAL_PKT:
rc = elan_ktf3k_ts_recv_data(ts->client, buf+4, 40); // read the finger report packet.
up(&pSem);
elan_ktf3k_ts_report_data(ts->client, buf+4);
// Second package
if ((buf[1] == 2) || (buf[1] == 3)) {
rc = elan_ktf3k_ts_recv_data(ts->client, buf1,PACKET_SIZE);
if (rc < 0){
enable_irq(ts->client->irq);
return;
}
elan_ktf3k_ts_report_data(ts->client, buf1);
}
// Final package
if (buf[1] == 3) {
rc = elan_ktf3k_ts_recv_data(ts->client, buf2, PACKET_SIZE);
if (rc < 0){
enable_irq(ts->client->irq);
return;
}
elan_ktf3k_ts_report_data(ts->client, buf2);
}
break;
case NEW_NOMARL_PKT:
rc = elan_ktf3k_ts_recv_data(ts->client, buf+4, NEW_PACKET_SIZE); // read the finger report packet.
up(&pSem);
elan_ktf3k_ts_report_data2(ts->client, buf+4);
// Second package
if ((buf[1] == 2) || (buf[1] == 3)) {
rc = elan_ktf3k_ts_recv_data(ts->client, buf1,NEW_PACKET_SIZE);
if (rc < 0){
enable_irq(ts->client->irq);
return;
}
elan_ktf3k_ts_report_data2(ts->client, buf1);
}
// Final package
if (buf[1] == 3) {
rc = elan_ktf3k_ts_recv_data(ts->client, buf2, NEW_PACKET_SIZE);
if (rc < 0){
enable_irq(ts->client->irq);
return;
}
elan_ktf3k_ts_report_data2(ts->client, buf2);
}
break;
case CMD_S_PKT:
up(&pSem);
process_resp_message(ts, buf, 4);
break;
default:
up(&pSem);
touch_debug(DEBUG_INFO, "[elan] Get unknow packet {0x%02X, 0x%02X, 0x%02X, 0x%02X}\n", buf[0], buf[1], buf[2], buf[3]);
}
#endif
enable_irq(ts->client->irq);
}
static irqreturn_t elan_ktf3k_ts_irq_handler(int irq, void *dev_id)
{
struct elan_ktf3k_ts_data *ts = dev_id;
struct i2c_client *client = ts->client;
dev_dbg(&client->dev, "[elan] %s\n", __func__);
disable_irq_nosync(ts->client->irq);
queue_work(ts->elan_wq, &ts->work);
return IRQ_HANDLED;
}
static int elan_ktf3k_ts_register_interrupt(struct i2c_client *client)
{
struct elan_ktf3k_ts_data *ts = i2c_get_clientdata(client);
int err = 0;
err = request_irq(client->irq, elan_ktf3k_ts_irq_handler,
IRQF_TRIGGER_LOW, client->name, ts);
if (err)
dev_err(&client->dev, "[elan] %s: request_irq %d failed\n",
__func__, client->irq);
return err;
}
static ssize_t elan_touch_switch_name(struct switch_dev *sdev, char *buf)
{
return sprintf(buf, "ELAN-%4.4x-%4.4x\n",
private_ts->fw_id, private_ts->fw_ver);
}
static ssize_t elan_touch_switch_state(struct switch_dev *sdev, char *buf)
{
return sprintf(buf, "%s\n", "0");
}
#ifdef _ENABLE_DBG_LEVEL
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_ktf3k_ts_rough_calibrate(private_ts->client);
break;
}
touch_debug(DEBUG_INFO, "Run command: 0x%08X result:%d\n", command, ret);
return count; // procfs_buffer_size;
}
#endif // #ifdef _ENABLE_DBG_LEV
#ifdef FIRMWARE_UPDATE_WITH_HEADER
#define FIRMWARE_PAGE_SIZE 132
static unsigned char touch_firmware[] = {
#include "fw_data.b"
};
#define SIZE_PER_PACKET 4
static int sendI2CPacket(struct i2c_client *client, const unsigned char *buf, unsigned int length){
int ret, i, retry_times = 10;
for(i = 0; i < length; i += ret){
ret = i2c_master_send(client, buf + i, length < SIZE_PER_PACKET ? length : SIZE_PER_PACKET);
if(ret <= 0){
retry_times--;
ret = 0;
}
if(ret < (length < SIZE_PER_PACKET ? length : SIZE_PER_PACKET)){
touch_debug("Sending packet broken\n");
}
if(retry_times < 0){
touch_debug("Failed sending I2C touch firmware packet.\n");
break;
}
}
return i;
}
static int recvI2CPacket(struct i2c_client *client, unsigned char *buf, unsigned int length){
int ret, i, retry_times = 10;
for(i = 0; i < length; i += ret){
ret = i2c_master_recv(client, buf + i, length - i);
if(ret <= 0){
retry_times--;
ret = 0;
}
if(retry_times < 0){
touch_debug("Failed sending I2C touch firmware packet.\n");
break;
}
}
return i;
}
static int firmware_update_header(struct i2c_client *client, const unsigned char *firmware, unsigned int pages_number){
int ret, i, mode;
int retry_times = 3, write_times;
unsigned char packet_data[8] = {0};
unsigned char isp_cmd[4] = {0x54, 0x00, 0x12, 0x34};
unsigned char nb_isp_cmd[4] = {0x45, 0x49, 0x41, 0x50};
unsigned char *cursor;
int boot_code = 0;
struct elan_ktf3k_ts_data *ts = i2c_get_clientdata(client);
if(ts == NULL)
return -1;
touch_debug(DEBUG_INFO, "Start firmware update!\n");
disable_irq(client->irq); // Blocking call no need to do extra wait
wake_lock(&ts->wakelock);
work_lock = 1;
elan_ktf3k_ts_hw_reset(client);
// Step 1: Check boot code version
boot_code = gpio_get_value(ts->intr_gpio);
if(boot_code == 0){ // if the boot code is old
touch_debug(DEBUG_INFO, "The firmware update of old boot code\n");
if(recvI2CPacket(client, packet_data, 4) < 0)
goto fw_update_failed;
touch_debug(DEBUG_INFO, "The received bytes 0x%X 0x%X 0x%X 0x%X\n", packet_data[0], packet_data[1],
packet_data[2], packet_data[3]);
if(packet_data[0] == 0x55 && packet_data[1] == 0x55 && packet_data[2] == 0x80 && packet_data[3] == 0x80)
touch_debug(DEBUG_INFO, "In the recovery mode\n");
if(sendI2CPacket(client, isp_cmd, sizeof(isp_cmd)) < 0) // get into ISP mode
goto fw_update_failed;
}else{ // if the boot code is new
touch_debug(DEBUG_INFO, "The firmware update of new boot code\n");
if(sendI2CPacket(client, nb_isp_cmd, sizeof(nb_isp_cmd)) < 0) // get into ISP mode
goto fw_update_failed;
}
msleep(100);
packet_data[0] = 0x10;
if(sendI2CPacket(client, packet_data, 1) < 0) // send dummy byte
goto fw_update_failed;
cursor = firmware;
touch_debug(DEBUG_INFO, "pages_number=%d\n", pages_number);
for(i = 0; i < pages_number; i++){
write_times = 0;
page_write_retry:
touch_debug(DEBUG_MESSAGES, "Update page number %d\n", i);
int sendCount;
if((sendCount = sendI2CPacket(client, cursor, FIRMWARE_PAGE_SIZE)) != FIRMWARE_PAGE_SIZE){
dev_err(&client->dev, "Fail to Update page number %d\n", i);
goto fw_update_failed;
}
touch_debug(DEBUG_INFO, "sendI2CPacket send %d bytes\n", sendCount);
int recvCount;
if((recvCount = recvI2CPacket(client, packet_data, FIRMWARE_ACK_SIZE)) != FIRMWARE_ACK_SIZE){
dev_err(&client->dev, "Fail to Update page number %d\n", i);
goto fw_update_failed;
}
touch_debug(DEBUG_INFO, "recvI2CPacket recv %d bytes: %x %x\n", recvCount, packet_data[0], packet_data[1]);
if(packet_data[0] != 0xaa || packet_data[1] != 0xaa){
touch_debug(DEBUG_INFO, "message received: %02X %02X Page %d rewrite\n", packet_data[0], packet_data[1], i);
if(write_times++ > 3)
goto fw_update_failed;
goto page_write_retry;
}
cursor += FIRMWARE_PAGE_SIZE;
}
elan_ktf3k_ts_hw_reset(client);
if(boot_code)
msleep(2000);
else
msleep(300);
if(recvI2CPacket(client, packet_data, 4) < 0)
goto fw_update_failed;
__fw_packet_handler(ts->client, 1);
ret = 0;
goto fw_update_finish;
fw_update_failed:
ret = -1;
fw_update_finish:
work_lock = 0;
wake_unlock(&ts->wakelock);
enable_irq(client->irq);
touch_debug(DEBUG_INFO, "Finish the touch firmware update!\n");
return ret;
}
#endif
#ifdef TOUCH_STRESS_TEST
static void stress_poll_data(struct work_struct * work)
{
bool status;
u8 count[7];
status = elan_ktf3k_ts_recv_data(private_ts->client, count, 7);
if(status < 0)
printk("Read touch sensor data fail\n");
if(poll_mode ==0)
msleep(5);
queue_delayed_work(stress_work_queue, &elan_poll_data_work, poll_mode);
}
int elan_stress_open(struct inode *inode, struct file *filp)
{
printk("%s\n", __func__);
if( !atomic_dec_and_test(&touch_char_available)){
atomic_inc(&touch_char_available);
return -EBUSY; /* already open */
}
return 0; /* success */
}
int elan_stress_release(struct inode *inode, struct file *filp)
{
printk("%s\n", __func__);
atomic_inc(&touch_char_available); /* release the device */
return 0; /* success */
}
int elan_stress_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
int err = 1;
printk("%s\n", __func__, cmd);
if (_IOC_TYPE(cmd) != STRESS_IOC_MAGIC)
return -ENOTTY;
if (_IOC_NR(cmd) > STRESS_IOC_MAXNR)
return -ENOTTY;
if (_IOC_DIR(cmd) & _IOC_READ)
err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd));
else if (_IOC_DIR(cmd) & _IOC_WRITE)
err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd));
if (err) return -EFAULT;
switch (cmd) {
case STRESS_POLL_DATA:
if (arg == STRESS_IOCTL_START_HEAVY){
printk("touch sensor heavey\n");
poll_mode = START_HEAVY;
queue_delayed_work(stress_work_queue, &elan_poll_data_work, poll_mode);
}
else if (arg == STRESS_IOCTL_START_NORMAL){
printk("touch sensor normal\n");
poll_mode = START_NORMAL;
queue_delayed_work(stress_work_queue, &elan_poll_data_work, poll_mode);
}
else if (arg == STRESS_IOCTL_END){
printk("touch sensor end\n");
cancel_delayed_work_sync(&elan_poll_data_work);
}
else
return -ENOTTY;
break;
break;
default: /* redundant, as cmd was checked against MAXNR */
return -ENOTTY;
}
return 0;
}
static struct file_operations stress_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = elan_stress_ioctl,
.open = elan_stress_open,
.release = elan_stress_release,
};
#endif
static int elan_ktf3k_ts_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int err = 0;
struct elan_ktf3k_i2c_platform_data *pdata;
struct elan_ktf3k_ts_data *ts;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
touch_debug(DEBUG_ERROR, "[elan] %s: i2c check functionality error\n", __func__);
err = -ENODEV;
goto err_check_functionality_failed;
}
ts = kzalloc(sizeof(struct elan_ktf3k_ts_data), GFP_KERNEL);
if (ts == NULL) {
touch_debug(DEBUG_INFO, "[elan] %s: allocate elan_ktf3k_ts_data failed\n", __func__);
err = -ENOMEM;
goto err_alloc_data_failed;
}
ts->elan_wq = create_singlethread_workqueue("elan_wq");
if (!ts->elan_wq) {
touch_debug(DEBUG_ERROR, "[elan] %s: create workqueue failed\n", __func__);
err = -ENOMEM;
goto err_create_wq_failed;
}
INIT_WORK(&ts->work, elan_ktf3k_ts_work_func);
ts->client = client;
i2c_set_clientdata(client, ts);
pdata = client->dev.platform_data;
if (likely(pdata != NULL)) {
ts->intr_gpio = pdata->intr_gpio;
ts->rst_gpio = pdata->rst_gpio;
}
sema_init(&pSem, 1);
err = elan_ktf3k_ts_setup(client);
if (err < 0) {
touch_debug(DEBUG_ERROR, "Main code fail\n");
ts->status = 0;
RECOVERY = 1;
err = 0;
//goto err_detect_failed;
}
ts->status = 1; // set I2C status is OK;
wake_lock_init(&ts->wakelock, WAKE_LOCK_SUSPEND, "elan_touch");
if(err==0x80)
touch_debug(DEBUG_INFO, "[ELAN] Touch is in boot mode!\n");
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";
//set_bit(BTN_TOUCH, ts->input_dev->keybit);
ts->abs_x_max = pdata->abs_x_max;
ts->abs_y_max = pdata->abs_y_max;
touch_debug(DEBUG_INFO, "[Elan] Max X=%d, Max Y=%d\n", ts->abs_x_max, ts->abs_y_max);
input_mt_init_slots(ts->input_dev, FINGER_NUM);
input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, pdata->abs_y_min, pdata->abs_y_max, 0, 0); // for 800 * 1280
input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, pdata->abs_x_min, pdata->abs_x_max, 0, 0);// for 800 * 1280
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_MT_PRESSURE, 0, MAX_FINGER_PRESSURE, 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);
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;
}
elan_ktf3k_ts_register_interrupt(ts->client);
if (gpio_get_value(ts->intr_gpio) == 0) {
touch_debug(DEBUG_INFO, "[elan]%s: handle missed interrupt\n", __func__);
elan_ktf3k_ts_irq_handler(client->irq, ts);
}
#ifdef FIRMWARE_UPDATE_WITH_HEADER
if(RECOVERY || check_fw_version(touch_firmware, sizeof(touch_firmware), ts->fw_ver) > 0)
firmware_update_header(client, touch_firmware, sizeof(touch_firmware)/FIRMWARE_PAGE_SIZE);
#endif
#ifdef CONFIG_HAS_EARLYSUSPEND
ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 21;
ts->early_suspend.suspend = elan_ktf3k_ts_early_suspend;
ts->early_suspend.resume = elan_ktf3k_ts_late_resume;
register_early_suspend(&ts->early_suspend);
#endif
private_ts = ts;
//elan_ktf2k_touch_sysfs_init();
ts->attrs.attrs = elan_attr;
err = sysfs_create_group(&client->dev.kobj, &ts->attrs);
if (err) {
dev_err(&client->dev, "Not able to create the sysfs\n");
}
#ifdef _ENABLE_DBG_LEVEL
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 // #ifdef _ENABLE_DBG_LEVEL
#ifdef TOUCH_STRESS_TEST
stress_work_queue = create_singlethread_workqueue("i2c_touchsensor_wq");
if(!stress_work_queue){
dev_err(&client->dev, "Unable to create stress_work_queue workqueue\n");
}
INIT_DELAYED_WORK(&elan_poll_data_work, stress_poll_data);
ts->misc_dev.minor = MISC_DYNAMIC_MINOR;
ts->misc_dev.name = "touchpanel";
ts->misc_dev.fops = &stress_fops;
err = misc_register(&ts->misc_dev);
if (err) {
dev_err(&client->dev, "elan stress test: Unable to register %s \\misc device\n", ts->misc_dev.name);
}
#endif
/* Register Switch file */
ts->touch_sdev.name = "touch";
ts->touch_sdev.print_name = elan_touch_switch_name;
ts->touch_sdev.print_state = elan_touch_switch_state;
if(switch_dev_register(&ts->touch_sdev) < 0){
touch_debug(DEBUG_ERROR, "switch_dev_register for dock failed!\n");
//goto exit;
}
switch_set_state(&ts->touch_sdev, 0);
touch_debug(DEBUG_INFO, "[elan] Start touchscreen %s in interrupt mode\n",
ts->input_dev->name);
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)
touch_debug(DEBUG_ERROR, "[ELAN]misc_register failed!!");
else
touch_debug(DEBUG_INFO, "[ELAN]misc_register finished!!");
update_power_source();
return 0;
err_input_register_device_failed:
if (ts->input_dev)
input_free_device(ts->input_dev);
err_input_dev_alloc_failed:
err_detect_failed:
if (ts->elan_wq)
destroy_workqueue(ts->elan_wq);
err_create_wq_failed:
kfree(ts);
err_alloc_data_failed:
err_check_functionality_failed:
return err;
}
static int elan_ktf3k_ts_remove(struct i2c_client *client)
{
struct elan_ktf3k_ts_data *ts = i2c_get_clientdata(client);
elan_touch_sysfs_deinit();
unregister_early_suspend(&ts->early_suspend);
free_irq(client->irq, ts);
if (ts->elan_wq)
destroy_workqueue(ts->elan_wq);
input_unregister_device(ts->input_dev);
wake_lock_destroy(&ts->wakelock);
#ifdef TOUCH_STRESS_TEST
misc_deregister(&ts->misc_dev);
#endif
kfree(ts);
#ifdef _ENABLE_DBG_LEVEL
remove_proc_entry(PROC_FS_NAME, NULL);
#endif
return 0;
}
void force_release_pos(struct i2c_client *client)
{
struct elan_ktf3k_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 int elan_ktf3k_ts_suspend(struct i2c_client *client, pm_message_t mesg)
{
struct elan_ktf3k_ts_data *ts = i2c_get_clientdata(client);
int rc = 0;
touch_debug(DEBUG_INFO, "[elan] %s: enter\n", __func__);
disable_irq(client->irq);
force_release_pos(client);
rc = cancel_work_sync(&ts->work);
if (rc)
enable_irq(client->irq);
if(work_lock == 0)
rc = elan_ktf3k_ts_set_power_state(client, PWR_STATE_DEEP_SLEEP);
return 0;
}
static int elan_ktf3k_ts_resume(struct i2c_client *client)
{
int rc = 0, retry = 5;
struct elan_ktf3k_ts_data *ts = i2c_get_clientdata(client);
int delay_time;
touch_debug(DEBUG_INFO, "[elan] %s: enter\n", __func__);
if(work_lock == 0){
do {
rc = elan_ktf3k_ts_set_power_state(client, PWR_STATE_NORMAL);
rc = elan_ktf3k_ts_get_power_state(client);
if (rc != PWR_NORMAL_STATE && rc != PWR_IDLE_STATE)
touch_debug(DEBUG_ERROR, "[elan] %s: wake up tp failed! err = %d\n",
__func__, rc);
else
break;
} while (--retry);
}
//force_release_pos(client);
enable_irq(client->irq);
return 0;
}
#ifdef CONFIG_HAS_EARLYSUSPEND
static void elan_ktf3k_ts_early_suspend(struct early_suspend *h)
{
struct elan_ktf3k_ts_data *ts;
ts = container_of(h, struct elan_ktf3k_ts_data, early_suspend);
elan_ktf3k_ts_suspend(ts->client, PMSG_SUSPEND);
}
static void elan_ktf3k_ts_late_resume(struct early_suspend *h)
{
struct elan_ktf3k_ts_data *ts;
ts = container_of(h, struct elan_ktf3k_ts_data, early_suspend);
elan_ktf3k_ts_resume(ts->client);
}
#endif
static const struct i2c_device_id elan_ktf3k_ts_id[] = {
{ ELAN_KTF3K_NAME, 0 },
{ }
};
static struct i2c_driver ektf3k_ts_driver = {
.probe = elan_ktf3k_ts_probe,
.remove = elan_ktf3k_ts_remove,
#ifndef CONFIG_HAS_EARLYSUSPEND
.suspend = elan_ktf3k_ts_suspend,
.resume = elan_ktf3k_ts_resume,
#endif
.id_table = elan_ktf3k_ts_id,
.driver = {
.name = ELAN_KTF3K_NAME,
},
};
static int __devinit elan_ktf3k_ts_init(void)
{
touch_debug(DEBUG_INFO, "[elan] %s\n", __func__);
return i2c_add_driver(&ektf3k_ts_driver);
}
static void __exit elan_ktf3k_ts_exit(void)
{
i2c_del_driver(&ektf3k_ts_driver);
return;
}
module_init(elan_ktf3k_ts_init);
module_exit(elan_ktf3k_ts_exit);
MODULE_DESCRIPTION("ELAN KTF3K Touchscreen Driver");
MODULE_LICENSE("GPL");