/* drivers/input/touchscreen/silabs_f760.c | |
* | |
* Copyright (C) 2007 Google, Inc. | |
* | |
* 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. | |
* | |
*/ | |
#include <linux/slab.h> | |
#include <linux/module.h> | |
#include <linux/delay.h> | |
#include <linux/earlysuspend.h> | |
#include <linux/hrtimer.h> | |
#include <linux/i2c.h> | |
#include <linux/input.h> | |
#include <linux/interrupt.h> | |
#include <linux/io.h> | |
#include <linux/platform_device.h> | |
#include <mach/gpio.h> | |
#include <linux/device.h> | |
#include <linux/regulator/consumer.h> | |
#include <linux/firmware.h> | |
//PSJ #include <plat/syscfg.h> | |
#define MAX_X 240 | |
#define MAX_Y 320 | |
#define TSP_INT 91 | |
#define TOUCH_EN 43 //PSJ | |
#define F760_MAX_TOUCH 2 | |
#define ESCAPE_ADDR 0xAA | |
#define TS_READ_START_ADDR 0x10 | |
#define TS_READ_VERSION_ADDR 0x1F | |
#define TS_READ_ESD_ADDR 0x1E | |
#define TS_READ_REGS_LEN 13 | |
#define SILABS_MAX_TOUCH F760_MAX_TOUCH | |
#define MTSI_VERSION 0x05 | |
//#define __TOUCH_DEBUG__ 1 | |
#define I2C_RETRY_CNT 3 | |
#define TOUCH_ON 1 | |
#define TOUCH_OFF 0 | |
#define PRESS_KEY 1 | |
#define RELEASE_KEY 0 | |
#define MAX_KEYS 2 | |
#define SET_DOWNLOAD_BY_GPIO 1 | |
#define SILABS_TS_NAME "silabs-f760" | |
#define YTE_MODULE_VER 0x02 | |
#define SMAC_MODULE_VER 0x03 | |
#define YTE_MODULE_VER_OLD 0x04 | |
#define YTE_MODULE_VER_NEW 0x0A | |
#define SMAC_MODULE_VER_OLD 0x05 | |
#define SMAC_MODULE_VER_NEW 0x07 | |
#define FW_VER 0x03 | |
#define FW_VER_OLD 0x0F | |
#define FW_VER_OLD_SMAC 0x14 | |
#define FW_VER_NEW_YTE 0x14 | |
#define FW_VER_NEW_SMAC 0x14 | |
#if defined(CONFIG_TARGET_LOCALE_AUS_TEL) | |
#define T_YTE_MODULE_VER 0x08 | |
#define T_YTE_MODULE_VER_NEW 0x08 | |
#define T_FW_VER_YTE 0x0A | |
#define T_FW_VER_OLD_YTE 0x0A | |
#define T_FW_VER_NEW_YTE 0x0E | |
#define T_SMAC_MODULE_VER 0x14 //Module_ver = 20 | |
#define T_SMAC_FW_VER 0x0F //FW_ver = 15 | |
#endif | |
#define NUM_TX_CHANNEL 12 | |
#define NUM_RX_CHANNEL 9 | |
#define JIG_MODE_COMMAND 0xA0 | |
#define RAWDATA_ADDRESS 0x003A | |
#define BASELINE_ADDRESS 0x0112 | |
#define QUICKSENSE_OVERHEAD 6 | |
#define I2CMAP_BUTTON_ADDRESS (0x0212 + 0x22) | |
#define NUM_MTRBUTTONS 2 | |
static int prev_wdog_val = -1; | |
static struct workqueue_struct *check_ic_wq; | |
static struct regulator *touch_regulator=NULL; | |
//add by brcm | |
int touch_id[2], posX[2], posY[2], strength[2]; | |
int Press_Check=0; | |
static int firmware_ret_val = -1; | |
static int pre_ta_stat = 0; | |
int touch_check=0; | |
int tsp_irq; | |
int tsp_chheck=0; | |
int TSP_MODULE_ID; | |
EXPORT_SYMBOL(TSP_MODULE_ID); | |
int FW_VERSION; | |
EXPORT_SYMBOL(FW_VERSION); | |
uint8_t buf_firmware[3]; | |
int firm_update( void ); | |
void set_tsp_for_ta_detect(int); | |
static int testmode = 1; | |
int PHONE_VER; | |
int tsp_status=0; | |
unsigned long check_node; | |
int Tx_Channel = NUM_TX_CHANNEL; | |
int Rx_Channel = NUM_RX_CHANNEL; | |
uint16_t baseline_node[NUM_TX_CHANNEL][NUM_RX_CHANNEL]={{0,},}; | |
#if SET_DOWNLOAD_BY_GPIO | |
#include "bootloader.h" | |
#endif // SET_DOWNLOAD_BY_GPIO | |
enum | |
{ | |
TOUCH_SCREEN=0, | |
TOUCH_KEY | |
}; | |
struct key_info | |
{ | |
int key_value; | |
int key_press; | |
}; | |
struct muti_touch_info | |
{ | |
int strength; | |
int status; | |
int width; | |
int posX; | |
int posY; | |
}; | |
struct silabs_ts_data { | |
uint16_t addr; | |
struct i2c_client *client; | |
struct input_dev *input_dev; | |
int use_irq; | |
struct hrtimer timer; | |
struct work_struct work; | |
struct work_struct work_timer; | |
struct early_suspend early_suspend; | |
}; | |
struct silabs_ts_data *ts_global; | |
/* sys fs */ | |
struct class *touch_class; | |
EXPORT_SYMBOL(touch_class); | |
struct device *firmware_dev; | |
EXPORT_SYMBOL(firmware_dev); | |
static ssize_t firmware_show(struct device *dev, struct device_attribute *attr, char *buf); | |
static ssize_t firmware_ret_show(struct device *dev, struct device_attribute *attr, char *buf); | |
static DEVICE_ATTR(firmware , S_IRUGO, firmware_show, NULL); | |
static DEVICE_ATTR(firmware_ret , S_IRUGO, firmware_ret_show, NULL); | |
static ssize_t rawdata_show_silabs(struct device *dev, struct device_attribute *attr, char *buf); | |
static ssize_t raw_enable_silabs(struct device *dev, struct device_attribute *attr, char *buf); | |
static ssize_t raw_disable_silabs(struct device *dev, struct device_attribute *attr, char *buf); | |
static ssize_t baseline_show_silabs(struct device *dev, struct device_attribute *attr, char *buf1); | |
static ssize_t diff_show_silabs(struct device *dev, struct device_attribute *attr, char *buf); | |
static ssize_t fimware_show_versname(struct device *dev, struct device_attribute *attr, char *buf); | |
static ssize_t rawdata_pass_fail_silabs(struct device *dev, struct device_attribute *attr, char *buf); | |
static ssize_t read_node(struct device *dev, struct device_attribute *attr, char *buf); | |
static DEVICE_ATTR(reference, S_IRUGO, baseline_show_silabs, NULL) ; | |
static DEVICE_ATTR(raw, S_IRUGO, rawdata_show_silabs, NULL) ; | |
static DEVICE_ATTR(raw_enable, S_IRUGO, raw_enable_silabs, NULL) ; | |
static DEVICE_ATTR(raw_disable, S_IRUGO, raw_disable_silabs, NULL) ; | |
static DEVICE_ATTR(diff, S_IRUGO, diff_show_silabs, NULL) ; | |
static DEVICE_ATTR(versname, S_IRUGO, fimware_show_versname, NULL) ; | |
static DEVICE_ATTR(raw_value, S_IRUGO, rawdata_pass_fail_silabs, NULL) ; | |
static DEVICE_ATTR(node_read, S_IRUGO, read_node, NULL) ; | |
/* sys fs */ | |
#ifdef CONFIG_HAS_EARLYSUSPEND | |
static void silabs_ts_early_suspend(struct early_suspend *h); | |
static void silabs_ts_late_resume(struct early_suspend *h); | |
#endif | |
extern int bcm_gpio_pull_up(unsigned int gpio, bool up); | |
extern int bcm_gpio_pull_up_down_enable(unsigned int gpio, bool enable); | |
extern int set_irq_type(unsigned int irq, unsigned int type); | |
//PSJ extern int tsp_charger_type_status; | |
void TSP_forced_release_forkey(void); | |
static struct muti_touch_info g_Mtouch_info[SILABS_MAX_TOUCH]; | |
static struct key_info touchkey_status[MAX_KEYS]; | |
void touch_ctrl_regulator(int on_off) | |
{ | |
int rc; | |
if(on_off==TOUCH_ON) | |
{ | |
#if 0 | |
regulator_set_voltage(touch_regulator,2900000,2900000); | |
regulator_enable(touch_regulator); | |
#endif | |
rc = gpio_request(TOUCH_EN,"Touch_en"); | |
if (rc < 0) | |
{ | |
printk("[TSP] touch_power_control unable to request GPIO pin"); | |
//printk(KERN_ERR "unable to request GPIO pin %d\n", TSP_INT_GPIO_PIN); | |
} | |
gpio_direction_output(TOUCH_EN,1); | |
gpio_set_value(TOUCH_EN,1); | |
gpio_free(TOUCH_EN); | |
} | |
else | |
{ | |
#if 0 | |
regulator_disable(touch_regulator); | |
#endif | |
gpio_request(TOUCH_EN,"Touch_en"); | |
gpio_direction_output(TOUCH_EN,0); | |
gpio_set_value(TOUCH_EN,0); | |
gpio_free(TOUCH_EN); | |
} | |
} | |
EXPORT_SYMBOL(touch_ctrl_regulator); | |
int tsp_reset( void ) | |
{ | |
int ret=1; | |
printk("[TSP] %s+\n", __func__ ); | |
touch_ctrl_regulator(0); | |
//PSJ gpio_direction_output(30, 0); | |
//PSJ gpio_direction_output(27, 0); | |
//PSJ gpio_direction_output(26, 0); | |
msleep(200); | |
// for TSK | |
TSP_forced_release_forkey(); | |
//PSJ gpio_direction_output(30, 1); | |
//PSJ gpio_direction_output(27, 1); | |
//PSJ gpio_direction_output(26, 1); | |
//PSJ gpio_direction_input(30); | |
//PSJ gpio_direction_input(27); | |
//PSJ gpio_direction_input(26); | |
touch_ctrl_regulator(1); | |
msleep(200); | |
return ret; | |
} | |
int tsp_i2c_write (unsigned char *rbuf, int num) | |
{ | |
int ret; | |
ret = i2c_master_send(ts_global->client, rbuf, num); | |
if(ret<0) { | |
printk("[TSP] Error code : %d, %d\n", __LINE__, ret ); | |
} | |
return ret; | |
} | |
EXPORT_SYMBOL(tsp_i2c_write); | |
int tsp_i2c_read(unsigned char *rbuf, int len) | |
{ | |
int ret; | |
ret = i2c_master_recv(ts_global->client, rbuf, len); | |
if(ret<0) { | |
printk("[TSP] Error code : %d, %d\n", __LINE__, ret ); | |
} | |
return ret; | |
} | |
EXPORT_SYMBOL(tsp_i2c_read); | |
void TSP_forced_release_forkey(void) | |
{ | |
int i, key; | |
int temp_value=0; | |
for(i=0; i<SILABS_MAX_TOUCH; i++) | |
{ | |
if(g_Mtouch_info[i].strength== -1) | |
continue; | |
input_report_abs(ts_global->input_dev, ABS_MT_TRACKING_ID, i); | |
input_report_abs(ts_global->input_dev, ABS_MT_POSITION_X, g_Mtouch_info[i].posX); | |
input_report_abs(ts_global->input_dev, ABS_MT_POSITION_Y, g_Mtouch_info[i].posY); | |
input_report_abs(ts_global->input_dev, ABS_MT_TOUCH_MAJOR, 0 ); | |
input_report_abs(ts_global->input_dev, ABS_MT_WIDTH_MAJOR, g_Mtouch_info[i].width); | |
//PSJ input_report_key(ts_global->input_dev, BTN_TOUCH, 0); | |
input_mt_sync(ts_global->input_dev); | |
printk("[TSP] force release\n"); | |
if(g_Mtouch_info[i].strength == 0) | |
g_Mtouch_info[i].strength = -1; | |
temp_value++; | |
} | |
if(temp_value>0) | |
input_sync(ts_global->input_dev); | |
for(key = 0; key < MAX_KEYS ; key++) | |
{ | |
touchkey_status[key].key_press = RELEASE_KEY; | |
input_report_key(ts_global->input_dev, touchkey_status[key].key_value, touchkey_status[key].key_press); | |
} | |
} | |
EXPORT_SYMBOL(TSP_forced_release_forkey); | |
static irqreturn_t silabs_ts_work_func(int irq, void *dev_id) | |
{ | |
int ret=0, i=0, key=0; | |
uint8_t buf[TS_READ_REGS_LEN]; | |
int touch_num=0, button_num =0, button_status=0, button_check=0; | |
struct silabs_ts_data *ts = dev_id; | |
#ifdef __TOUCH_DEBUG__ | |
printk("[TSP] %s, %d\n", __func__, __LINE__ ); | |
#endif | |
if(ts ==NULL) | |
{ | |
printk("[TSP] silabs_ts_work_func : TS NULL\n"); | |
return IRQ_HANDLED; | |
} | |
buf[0] = ESCAPE_ADDR; | |
buf[1] = 0x02; | |
for(i=0; i<I2C_RETRY_CNT; i++) | |
{ | |
ret = i2c_master_send(ts->client, buf, 2); | |
if(ret >=0) | |
{ | |
ret = i2c_master_recv(ts->client, buf, TS_READ_REGS_LEN); | |
if(ret >=0) | |
{ | |
break; // i2c success | |
} | |
} | |
} | |
if (ret < 0) | |
{ | |
printk("[TSP] silabs_ts_work_func: i2c failed %d\n", ret); | |
tsp_reset(); | |
return IRQ_HANDLED; | |
} | |
else | |
{ | |
touch_num = buf[0]&0x0F; | |
button_num = ((buf[0]&0xC0)>>6); | |
button_status=((buf[1]&0x10)>>4); | |
button_check=buf[1]&0x0F; | |
#ifdef __TOUCH_DEBUG__ | |
printk("[TSP] button_num : %d, touch_num : %d, button_check:%d, buf[1] : %d\n", button_num, touch_num, button_check, buf[1]); | |
#endif | |
if(button_check == 0) | |
{ | |
if(touch_num >0) | |
{ | |
touch_id[0] = (buf[2]&0xf0)>>4; | |
posX[0] = (( buf[3]<< (8) ) + buf[4]); | |
posY[0] = ( buf[5]<< (8) ) + buf[6]; | |
strength[0] = buf[7]; | |
touch_id[1] = (buf[2]&0x0f); | |
posX[1] = (( buf[8]<< (8) ) + buf[9]); | |
posY[1] = ( buf[10]<< (8) ) + buf[11]; | |
strength[1] = buf[12]; | |
} | |
if(touch_num==0) | |
{ | |
touch_id[0]=0; | |
touch_id[1]=0; | |
strength[0]=0; | |
strength[1]=0; | |
} | |
for(i=0; i<2; i++) | |
{ | |
if(touch_id[i] >=1) | |
{ | |
g_Mtouch_info[i].status = 1; | |
} | |
else if(touch_id[i] ==0 && g_Mtouch_info[i].status == 1) | |
{ | |
g_Mtouch_info[i].status = 0; | |
} | |
else if(touch_id[i] ==0 && g_Mtouch_info[i].status == 0) | |
{ | |
g_Mtouch_info[i].status = -1; | |
} | |
if(g_Mtouch_info[i].status == -1) continue; | |
input_report_abs(ts->input_dev, ABS_MT_POSITION_X, posX[i]); | |
input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, posY[i]); | |
input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, touch_id[i] ); | |
input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, strength[i]); | |
input_mt_sync(ts->input_dev); | |
input_report_key(ts->input_dev, BTN_TOUCH, strength[i]); | |
g_Mtouch_info[i].posX = posX[i]; | |
g_Mtouch_info[i].posY = posY[i]; | |
g_Mtouch_info[i].width = strength[i]; | |
g_Mtouch_info[i].strength = strength[i]; | |
#ifdef __TOUCH_DEBUG__ | |
printk("[TSP] i : %d, x: %d, y: %d\n, 3:%d, 4:%d", touch_id[i], posX[i], posY[i], strength[i], strength[i]); | |
#endif | |
} | |
} | |
else | |
{ | |
if (buf[1] & 0x1) | |
key=0; | |
if (buf[1] & 0x2) | |
key=1; | |
touchkey_status[0].key_value= KEY_MENU; | |
touchkey_status[1].key_value= KEY_BACK; | |
touchkey_status[key].key_press=(button_status ? PRESS_KEY : RELEASE_KEY); | |
input_report_key(ts->input_dev, touchkey_status[key].key_value, touchkey_status[key].key_press); | |
input_report_key(ts->input_dev, BTN_TOUCH, 1); | |
#ifdef __TOUCH_DEBUG__ | |
printk(KERN_ERR "[TSP] silabs_ts_work_func: buf[%d] : %d, button_status: %d\n", key, touchkey_status[key].key_value, touchkey_status[key].key_press); | |
#endif | |
} | |
input_sync(ts->input_dev); | |
} | |
return IRQ_HANDLED; | |
} | |
static irqreturn_t silabs_ts_irq_handler(int irq, void *dev_id) | |
{ | |
touch_check=1; | |
#ifdef __TOUCH_DEBUG__ | |
printk("[TSP] %s, %d\n", __func__, __LINE__ ); | |
#endif | |
return IRQ_WAKE_THREAD; | |
} | |
void set_tsp_for_ta_detect(int state) | |
{ | |
int ret=0; | |
uint8_t wdog_val[7] = {0x80, 0x05, 0x00, 0x02, 0x12, 0x20, 0x00}; | |
if((tsp_status==0)&&(testmode==1)) | |
{ | |
if(state) | |
{ | |
printk("[TSP] [1] set_tsp_for_ta_detect!!! state=1\n"); | |
wdog_val[5] = 0x20; | |
ret = i2c_master_send(ts_global->client, (const char *)&wdog_val, 7); | |
if(ret<0) { | |
printk("[TSP] Error code : %d, %d\n", __LINE__, ret ); | |
} | |
pre_ta_stat = 1; | |
} | |
else | |
{ | |
printk("[TSP] [2] set_tsp_for_ta_detect!!! state=0\n"); | |
wdog_val[5] = 0x00; | |
ret = i2c_master_send(ts_global->client, (const char *)&wdog_val, 7); | |
if(ret<0) { | |
printk("[TSP] Error code : %d, %d\n", __LINE__, ret ); | |
} | |
pre_ta_stat = 0; | |
} | |
} | |
} | |
EXPORT_SYMBOL(set_tsp_for_ta_detect); | |
static void check_ic_work_func(struct work_struct *work_timer) | |
{ | |
int ret=0; | |
uint8_t buf_esd[2]; | |
uint8_t wdog_val[1]; | |
struct silabs_ts_data *ts = container_of(work_timer, struct silabs_ts_data, work_timer); | |
//printk("[TSP] testmode : %d\n", testmode); | |
buf_esd[0] = ESCAPE_ADDR; | |
buf_esd[1] = TS_READ_ESD_ADDR; | |
wdog_val[0] = 1; | |
touch_check=0; | |
if(testmode==1) | |
{ | |
#if 0 //PSJ | |
if( pre_ta_stat != tsp_charger_type_status ) | |
{ | |
set_tsp_for_ta_detect(tsp_charger_type_status); | |
} | |
#endif | |
ret = i2c_master_send(ts->client, (const char *)&buf_esd, 2); | |
if(ret >=0) | |
{ | |
ret = i2c_master_recv(ts->client, wdog_val, 1); | |
} | |
if (touch_check==0) | |
{ | |
if(ret < 0) | |
{ | |
tsp_reset(); | |
printk(KERN_ERR "silabs_ts_work_func : i2c_master_send [%d]\n", ret); | |
} | |
else if(wdog_val[0] == (uint8_t)prev_wdog_val) | |
{ | |
printk("[TSP] %s tsp_reset counter = %x, prev = %x\n", __func__, wdog_val[0], (uint8_t)prev_wdog_val); | |
tsp_reset(); | |
prev_wdog_val = -1; | |
} | |
else | |
{ | |
prev_wdog_val = wdog_val[0]; | |
} | |
} | |
} | |
} | |
static enum hrtimer_restart silabs_watchdog_timer_func(struct hrtimer *timer) | |
{ | |
queue_work(check_ic_wq, &ts_global->work_timer); | |
hrtimer_start(&ts_global->timer, ktime_set(1, 0), HRTIMER_MODE_REL); | |
return HRTIMER_NORESTART; | |
} | |
static unsigned int touch_present = 0; | |
static int silabs_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) | |
{ | |
struct silabs_ts_data *ts; | |
int ret = 0; | |
touch_ctrl_regulator(TOUCH_ON); | |
mdelay(200); | |
touch_ctrl_regulator(TOUCH_OFF); | |
mdelay(200); | |
touch_ctrl_regulator(TOUCH_ON); | |
mdelay(200); | |
printk("[TSP] %s, %d\n", __func__, __LINE__ ); | |
ts = kzalloc(sizeof(*ts), GFP_KERNEL); | |
if (ts == NULL) { | |
ret = -ENOMEM; | |
goto err_alloc_data_failed; | |
} | |
INIT_WORK(&ts->work_timer, check_ic_work_func ); | |
ts->client = client; | |
i2c_set_clientdata(client, ts); | |
ts_global = ts; | |
tsp_irq=client->irq; | |
hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); | |
ts->timer.function = silabs_watchdog_timer_func; | |
/* sys fs */ | |
touch_class = class_create(THIS_MODULE, "touch"); | |
if (IS_ERR(touch_class)) | |
pr_err("Failed to create class(touch)!\n"); | |
firmware_dev = device_create(touch_class, NULL, 0, NULL, "firmware"); | |
if (IS_ERR(firmware_dev)) | |
pr_err("Failed to create device(firmware)!\n"); | |
if (device_create_file(firmware_dev, &dev_attr_firmware) < 0) | |
pr_err("Failed to create device file(%s)!\n", dev_attr_firmware.attr.name); | |
if (device_create_file(firmware_dev, &dev_attr_firmware_ret) < 0) | |
pr_err("Failed to create device file(%s)!\n", dev_attr_firmware_ret.attr.name); | |
if (device_create_file(firmware_dev, &dev_attr_versname) < 0) | |
pr_err("Failed to create device file(%s)!\n", dev_attr_versname.attr.name); | |
if (device_create_file(firmware_dev, &dev_attr_raw) < 0) | |
pr_err("Failed to create device file(%s)!\n", dev_attr_raw.attr.name); | |
if (device_create_file(firmware_dev, &dev_attr_reference) < 0) | |
pr_err("Failed to create device file(%s)!\n", dev_attr_reference.attr.name); | |
if (device_create_file(firmware_dev, &dev_attr_diff) < 0) | |
pr_err("Failed to create device file(%s)!\n", dev_attr_diff.attr.name); | |
if (device_create_file(firmware_dev, &dev_attr_raw_value) < 0) | |
pr_err("Failed to create device file(%s)!\n", dev_attr_raw_value.attr.name); | |
if (device_create_file(firmware_dev, &dev_attr_node_read) < 0) | |
pr_err("Failed to create device file(%s)!\n", dev_attr_node_read.attr.name); | |
if (device_create_file(firmware_dev, &dev_attr_raw_enable) < 0) | |
pr_err("Failed to create device file(%s)!\n", dev_attr_raw_enable.attr.name); | |
if (device_create_file(firmware_dev, &dev_attr_raw_disable) < 0) | |
pr_err("Failed to create device file(%s)!\n", dev_attr_raw_disable.attr.name); | |
/* sys fs */ | |
ts->input_dev = input_allocate_device(); | |
if (ts->input_dev == NULL) { | |
ret = -ENOMEM; | |
touch_present = 0; | |
printk(KERN_ERR "silabs_ts_probe: Failed to allocate input device\n"); | |
goto err_input_dev_alloc_failed; | |
} | |
ts->input_dev->name = "sec_touchscreen "; | |
ts->input_dev->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY); | |
ts->input_dev->keybit[BIT_WORD(KEY_MENU)] |= BIT_MASK(KEY_MENU); | |
ts->input_dev->keybit[BIT_WORD(KEY_POWER)] |= BIT_MASK(KEY_POWER); | |
ts->input_dev->keybit[BIT_WORD(KEY_BACK)] |= BIT_MASK(KEY_BACK); | |
ts->input_dev->keybit[BIT_WORD(KEY_SEARCH)] |= BIT_MASK(KEY_SEARCH); | |
set_bit(BTN_TOUCH, ts->input_dev->keybit); | |
set_bit(EV_ABS, ts->input_dev->evbit); | |
ts->input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY); | |
input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, 0, MAX_X, 0, 0); | |
input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, 0, MAX_Y, 0, 0); | |
input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); | |
input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0); | |
set_bit(EV_SYN, ts->input_dev->evbit); | |
set_bit(EV_KEY, ts->input_dev->evbit); | |
set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit); | |
/* ts->input_dev->name = ts->keypad_info->name; */ | |
ret = input_register_device(ts->input_dev); | |
if (ret) { | |
touch_present = 0; | |
printk(KERN_ERR "silabs_ts_probe: Unable to register %s input device\n", ts->input_dev->name); | |
goto err_input_register_device_failed; | |
} | |
printk("[TSP] %s, irq=%d\n", __func__, tsp_irq ); | |
gpio_request(TSP_INT, "ts_irq"); | |
gpio_direction_input(TSP_INT); | |
if (tsp_irq) { | |
ret = request_threaded_irq(tsp_irq, silabs_ts_irq_handler, silabs_ts_work_func, IRQF_TRIGGER_FALLING|IRQF_ONESHOT, client->name, ts); | |
if (ret < 0) | |
dev_err(&client->dev, "request_irq failed, ret:%d \n", ret); | |
} | |
#if 1 | |
#ifdef CONFIG_HAS_EARLYSUSPEND | |
ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN+1; | |
ts->early_suspend.suspend = silabs_ts_early_suspend; | |
ts->early_suspend.resume = silabs_ts_late_resume; | |
register_early_suspend(&ts->early_suspend); | |
#endif | |
#endif | |
if(ts ==NULL) | |
{ | |
printk("[TSP] silabs_ts_init_read : TS NULL\n"); | |
goto err_input_dev_alloc_failed; | |
} | |
touch_present = 1; | |
buf_firmware[0] = ESCAPE_ADDR; | |
buf_firmware[1] = TS_READ_VERSION_ADDR; | |
ret = i2c_master_send(ts->client,(const char *) &buf_firmware, 2); | |
if(ret < 0) | |
{ | |
printk(KERN_ERR "silabs_ts_work_func : i2c_master_send [%d]\n", ret); | |
tsp_chheck=1; | |
} | |
if(tsp_chheck==0) | |
{ | |
ret = i2c_master_recv(ts->client, (char *)&buf_firmware, 3); | |
if(ret < 0) | |
{ | |
printk(KERN_ERR "silabs_ts_work_func : i2c_master_recv [%d]\n", ret); | |
tsp_chheck=1; | |
} | |
printk("[TSP] silabs_ts_probe %d, %d, %d\n", buf_firmware[0], buf_firmware[1], buf_firmware[2]); | |
#if defined(CONFIG_TARGET_LOCALE_AUS_TEL) | |
if (( buf_firmware[2] == T_YTE_MODULE_VER_NEW)&&(buf_firmware[0] < T_FW_VER_NEW_YTE)) | |
{ | |
TSP_MODULE_ID = buf_firmware[2]; | |
PHONE_VER = T_FW_VER_NEW_YTE; | |
local_irq_disable(); | |
ret = Firmware_Download(); | |
printk("[TSP] enable_irq : %d\n", __LINE__ ); | |
printk("[TSP] totoroT taeyang 0x08 update : %d\n", __LINE__ ); | |
local_irq_enable(); | |
if(ret == 0) | |
{ | |
printk(KERN_ERR "SET Download Fail - error code [%d]\n", ret); | |
} | |
} | |
else if(( buf_firmware[2] == T_SMAC_MODULE_VER)&&((buf_firmware[0] < T_SMAC_FW_VER))) | |
{ | |
TSP_MODULE_ID = buf_firmware[2]; | |
PHONE_VER = T_SMAC_FW_VER; | |
local_irq_disable(); | |
ret = Firmware_Download(); | |
printk("[TSP] enable_irq : %d\n", __LINE__ ); | |
printk("[TSP] totoroT SMAC 0x14 update : %d\n", __LINE__ ); | |
local_irq_enable(); | |
if(ret == 0) | |
{ | |
printk(KERN_ERR "SET Download Fail - error code [%d]\n", ret); | |
} | |
} | |
else | |
#endif | |
if ((( buf_firmware[2] == YTE_MODULE_VER)||( buf_firmware[2] == SMAC_MODULE_VER))&&(buf_firmware[0] < FW_VER)) | |
{ | |
TSP_MODULE_ID = buf_firmware[2]; | |
PHONE_VER = FW_VER; | |
local_irq_disable(); | |
//ret = Firmware_Download(); | |
printk("[TSP] enable_irq : %d\n", __LINE__ ); | |
local_irq_enable(); | |
if(ret == 0) | |
{ | |
printk(KERN_ERR "SET Download Fail - error code [%d]\n", ret); | |
} | |
} | |
else if (( buf_firmware[2] == YTE_MODULE_VER_OLD)&&(buf_firmware[0] < FW_VER_OLD)) | |
{ | |
TSP_MODULE_ID = buf_firmware[2]; | |
PHONE_VER = FW_VER_OLD; | |
local_irq_disable(); | |
ret = Firmware_Download(); | |
printk("[TSP] enable_irq : %d\n", __LINE__ ); | |
local_irq_enable(); | |
if(ret == 0) | |
{ | |
printk(KERN_ERR "SET Download Fail - error code [%d]\n", ret); | |
} | |
} | |
else if (( buf_firmware[2] == SMAC_MODULE_VER_OLD)&&(buf_firmware[0] < FW_VER_OLD_SMAC)) | |
{ | |
TSP_MODULE_ID = buf_firmware[2]; | |
PHONE_VER = FW_VER_OLD_SMAC; | |
local_irq_disable(); | |
ret = Firmware_Download(); | |
printk("[TSP] enable_irq : %d\n", __LINE__ ); | |
local_irq_enable(); | |
if(ret == 0) | |
{ | |
printk(KERN_ERR "SET Download Fail - error code [%d]\n", ret); | |
} | |
} | |
else if (( buf_firmware[2] == YTE_MODULE_VER_NEW)&&(buf_firmware[0] < FW_VER_NEW_YTE)) | |
{ | |
TSP_MODULE_ID = buf_firmware[2]; | |
PHONE_VER = FW_VER_NEW_YTE; | |
local_irq_disable(); | |
ret = Firmware_Download(); | |
printk("[TSP] enable_irq : %d\n", __LINE__ ); | |
local_irq_enable(); | |
if(ret == 0) | |
{ | |
printk(KERN_ERR "SET Download Fail - error code [%d]\n", ret); | |
} | |
} | |
else if (( buf_firmware[2] == SMAC_MODULE_VER_NEW)&&(buf_firmware[0] < FW_VER_NEW_SMAC)) | |
{ | |
TSP_MODULE_ID = buf_firmware[2]; | |
PHONE_VER = FW_VER_NEW_SMAC; | |
local_irq_disable(); | |
ret = Firmware_Download(); | |
printk("[TSP] enable_irq : %d\n", __LINE__ ); | |
local_irq_enable(); | |
if(ret == 0) | |
{ | |
printk(KERN_ERR "SET Download Fail - error code [%d]\n", ret); | |
} | |
} | |
else if (( buf_firmware[2] == 0xFF) || (ret<0)) | |
{ | |
TSP_MODULE_ID = buf_firmware[2]; | |
local_irq_disable(); | |
ret = Firmware_Download(); | |
printk("[TSP] enable_irq : %d\n", __LINE__ ); | |
local_irq_enable(); | |
if(ret == 0) | |
{ | |
printk(KERN_ERR "SET Download Fail - error code [%d]\n", ret); | |
} | |
} | |
hrtimer_start(&ts->timer, ktime_set(2, 0), HRTIMER_MODE_REL); | |
} | |
return 0; | |
err_input_register_device_failed: | |
printk(KERN_ERR "silabs-ts: err_input_register_device failed\n"); | |
input_free_device(ts->input_dev); | |
err_input_dev_alloc_failed: | |
printk(KERN_ERR "silabs-ts: err_input_dev_alloc failed\n"); | |
err_alloc_data_failed: | |
printk(KERN_ERR "silabs-ts: err_alloc_data failed_\n"); | |
return 1; | |
} | |
static int silabs_ts_remove(struct i2c_client *client) | |
{ | |
struct silabs_ts_data *ts = i2c_get_clientdata(client); | |
unregister_early_suspend(&ts->early_suspend); | |
if (tsp_irq) | |
free_irq(tsp_irq, ts); | |
//else | |
// hrtimer_cancel(&ts->timer); | |
input_unregister_device(ts->input_dev); | |
kfree(ts); | |
return 0; | |
} | |
static int silabs_ts_suspend(struct i2c_client *client, pm_message_t mesg) | |
{ | |
int ret; | |
struct silabs_ts_data *ts = i2c_get_clientdata(client); | |
printk("[TSP] %s, %d\n", __func__, __LINE__ ); | |
tsp_status=1; | |
if( touch_present ) | |
{ | |
if (tsp_irq) | |
{ | |
disable_irq(tsp_irq); | |
} | |
ret = cancel_work_sync(&ts->work_timer); | |
ret = cancel_work_sync(&ts->work); | |
if (ret && tsp_irq) /* if work was pending disable-count is now 2 */ | |
{ | |
enable_irq(tsp_irq); | |
} | |
if(tsp_chheck==0) | |
hrtimer_cancel(&ts->timer); | |
touch_ctrl_regulator(TOUCH_OFF); | |
//PSJ gpio_direction_output(30, 0); | |
//PSJ gpio_direction_output(27, 0); | |
//PSJ gpio_direction_output(26, 0); | |
msleep(400); | |
} | |
else | |
printk("[TSP] TSP isn't present.\n"); | |
TSP_forced_release_forkey(); | |
printk("[TSP] %s-\n", __func__ ); | |
return 0; | |
} | |
static int silabs_ts_resume(struct i2c_client *client) | |
{ | |
int key; | |
struct silabs_ts_data *ts = i2c_get_clientdata(client); | |
printk("[TSP] %s, %d\n", __func__, __LINE__ ); | |
//enable_irq(client->irq); // scl wave | |
printk("[TSP] %s+\n", __func__ ); | |
if( touch_present ) | |
{ | |
//PSJ gpio_direction_output(30, 1); | |
//PSJ gpio_direction_output(27, 1); | |
//PSJ gpio_direction_output(26, 1); | |
//PSJ gpio_direction_input(30); | |
//PSJ gpio_direction_input(27); | |
//PSJ gpio_direction_input(26); | |
touch_ctrl_regulator(TOUCH_ON); | |
msleep(40); | |
// for TSK | |
for(key = 0; key < MAX_KEYS; key++) | |
touchkey_status[key].key_press = RELEASE_KEY; | |
prev_wdog_val = -1; | |
#if 0 //PSJ | |
if(tsp_charger_type_status == 1) | |
{ | |
set_tsp_for_ta_detect(tsp_charger_type_status); | |
} | |
#endif | |
#if 0 | |
if( tsp_proximity_irq_status == 1) | |
{ | |
set_tsp_for_prox_enable(tsp_proximity_irq_status); | |
} | |
#endif | |
if(tsp_chheck==0) | |
hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL); | |
enable_irq(tsp_irq); | |
} | |
else | |
printk("[TSP] TSP isn't present.\n"); | |
printk("[TSP] %s-\n", __func__ ); | |
tsp_status=0; | |
return 0; | |
} | |
#ifdef CONFIG_HAS_EARLYSUSPEND | |
static void silabs_ts_early_suspend(struct early_suspend *h) | |
{ | |
struct silabs_ts_data *ts; | |
ts = container_of(h, struct silabs_ts_data, early_suspend); | |
silabs_ts_suspend(ts->client, PMSG_SUSPEND); | |
} | |
static void silabs_ts_late_resume(struct early_suspend *h) | |
{ | |
struct silabs_ts_data *ts; | |
ts = container_of(h, struct silabs_ts_data, early_suspend); | |
silabs_ts_resume(ts->client); | |
} | |
#endif | |
static const struct i2c_device_id silabs_ts_id[] = { | |
{ SILABS_TS_NAME, 0 }, | |
{ } | |
}; | |
static struct i2c_driver silabs_ts_driver = { | |
.probe = silabs_ts_probe, | |
.remove = silabs_ts_remove, | |
#if 1 | |
#ifndef CONFIG_HAS_EARLYSUSPEND | |
.suspend = silabs_ts_suspend, | |
.resume = silabs_ts_resume, | |
#endif | |
#endif | |
.id_table = silabs_ts_id, | |
.driver = { | |
.name = SILABS_TS_NAME, | |
}, | |
}; | |
static int __devinit silabs_ts_init(void) | |
{ | |
check_ic_wq = create_singlethread_workqueue("check_ic_wq"); | |
if (!check_ic_wq) | |
return -ENOMEM; | |
touch_regulator = regulator_get(NULL,"touch_vcc"); | |
//PSJ board_sysconfig(SYSCFG_TOUCH, SYSCFG_INIT); | |
return i2c_add_driver(&silabs_ts_driver); | |
} | |
static void __exit silabs_ts_exit(void) | |
{ | |
if (touch_regulator) | |
{ | |
regulator_put(touch_regulator); | |
touch_regulator = NULL; | |
} | |
i2c_del_driver(&silabs_ts_driver); | |
if (check_ic_wq) | |
destroy_workqueue(check_ic_wq); | |
} | |
/* Touch Reference ************************************************************/ | |
static ssize_t raw_enable_silabs(struct device *dev, struct device_attribute *attr, char *buf) | |
{ | |
printk("[TSP] %s stop. line : %d, \n", __func__,__LINE__); | |
testmode=0; | |
return sprintf(buf, "1") ; | |
} | |
static ssize_t raw_disable_silabs(struct device *dev, struct device_attribute *attr, char *buf) | |
{ | |
printk("[TSP] %s stop. line : %d, \n", __func__,__LINE__); | |
testmode=1; | |
touch_ctrl_regulator(0); | |
mdelay(2); | |
touch_ctrl_regulator(1); | |
mdelay(300); | |
return sprintf(buf, "1") ; | |
} | |
int silabs_quicksense ( int address, int size, char* buff ) | |
{ | |
uint8_t buf1[7]={0x78, 0x05, 0x00, 0, 0, 0, 0}; | |
int ret; | |
buf1[3] = (address >> 8) & 0xFF; // Address High Byte | |
buf1[4] = address & 0xFF; // Address Low Byte | |
buf1[5] = size; | |
ret = i2c_master_send(ts_global->client, buf1, 7); | |
if (ret < 0) | |
{ | |
printk("[TSP] i2c_master_send fail! %s : %d, \n", __func__,__LINE__); | |
return -1; | |
} | |
ret = i2c_master_recv(ts_global->client, buff, size + QUICKSENSE_OVERHEAD); | |
if (ret < 0) | |
{ | |
printk("[TSP] i2c_master_recv fail! %s : %d, \n", __func__,__LINE__); | |
return -1; | |
} | |
return 0; | |
} | |
static ssize_t rawdata_pass_fail_silabs(struct device *dev, struct device_attribute *attr, char *buf) | |
{ | |
int Rx_Channel = NUM_RX_CHANNEL; | |
uint8_t buffer1[NUM_TX_CHANNEL*NUM_RX_CHANNEL*2+QUICKSENSE_OVERHEAD]={0,}; | |
uint8_t buffer2[NUM_TX_CHANNEL*NUM_RX_CHANNEL*2+QUICKSENSE_OVERHEAD]={0,}; | |
uint16_t rawdata[NUM_TX_CHANNEL][NUM_RX_CHANNEL]={{0,},}; | |
#if defined(CONFIG_TARGET_LOCALE_AUS_TEL) | |
uint16_t TYE_RAWDATA_MAX[108] = {14250,14370,14370,14390,14320,14290,14265,14175,13915,13515,13660,13665,13700,13620,13590,13555,13460,13195,13470,13615,13615,13650,13585,13550,13515,13415,13145,13470,13600,13590,13625,13565,13530,13500,13405,13130,13455,13590,13600,13630,13555,13515,13485,13300,13110,13410,13555,13590,13620,13520,13485,13460,13360,13080,13245,13490,13555,13600,13505,13490,13475,13415,13410,13230,13470,13540,13600,13520,13480,13460,13400,13280,13215,13445,13505,13565,13500,13460,13430,13375,13235,13215,13430,13480,13535,13480,13455,13430,13350,13195,13380,13415,13445,13495,13440,13415,13395,13320,13160,13935,14110,14130,14190,14110,14090,14060,14000,13825}; | |
uint16_t TYE_RAWDATA_MIN[108] = {10750,10840,10840,10860,10800,10780,10760,10695,10500,10195,10305,10310,10335,10275,10250,10225,10155, 9955,10165,10270,10270,10295,10250,10220,10195,10120, 9920,10160,10260,10255,10280,10235,10210,10185,10110, 9905,10150,10250,10260,10285,10225,10195,10175,10100, 9890,10120,10225,10255,10280,10200,10175,10155,10080, 9870, 9990,10175,10225,10260,10190,10175,10165,10120,10115, 9980,10160,10215,10260,10200,10170,10155,10110,10020, 9970,10140,10190,10235,10185,10155,10130,10090, 9985, 9970,10130,10170,10210,10170,10150,10130,10075, 9955,10095,10120,10145,10180,10140,10120,10105,10050, 9930,10510,10645,10660,10705,10645,10630,10610,10560,10430}; | |
uint16_t SMAC_RAWDATA_MAX[108] = {15075,15183,15165,15194,15106,15077,15054,14971,14698,14692,14844,14859,14902,14801,14755,14720,14627,14346,14668,14814,14828,14880,14792,14741,14700,14606,14327,14660,14788,14792,14847,14768,14713,14667,14571,14298,14622,14749,14771,14821,14733,14682,14637,14539,14260,14566,14704,14737,14784,14686,14644,14608,14518,14240,14415,14654,14700,14755,14658,14636,14612,14558,14606,14401,14638,14686,14745,14653,14613,14590,14537,14453,14387,14628,14675,14735,14644,14589,14575,14527,14403,14367,14603,14650,14698,14619,14568,14557,14493,14339,14536,14583,14619,14668,14599,14549,14533,14459,14298,14799,14982,15011,15075,15003,14955,14917,14852,14696 }; | |
uint16_t SMAC_RAWDATA_MIN[108] = {11143,11223,11209,11230,11166,11144,11127,11065,10864,10860,10972,10983,11014,10940,10906,10880,10811,10604,10842,10950,10960,10998,10934,10895,10866,10796,10589,10836,10930,10934,10974,10916,10875,10841,10770,10568,10808,10901,10917,10955,10889,10852,10819,10747,10540,10766,10868,10893,10928,10855,10824,10798,10730,10526,10655,10832,10866,10906,10834,10818,10800,10760,10796,10645,10820,10855,10899,10831,10801,10784,10745,10683,10634,10812,10847,10891,10824,10783,10773,10737,10645,10619,10793,10828,10864,10805,10768,10759,10713,10599,10744,10779,10805,10842,10791,10753,10741,10687,10568,10939,11074,11095,11143,11089,11053,11025,10978,10862}; | |
#else | |
uint16_t RAWDATA_MAX[108] = {14350,14510,14560,14610,14710,14680,14780,14780,14440,13720,13990,14080,14150,14190,14190,14260,14250,13910,13650,13940,14040,14110,14150,14150,14210,14200,13870,13610,13890,14000,14080,14120,14120,14200,14170,13840,13570,13870,13960,14040,14080,14080,14160,14150,13820,13560,13830,13920,13990,14020,14020,14110,14120,13790,13540,13800,13900,13960,14000,14000,14090,14100,13770,13400,13760,13900,13980,14030,14040,14150,14200,14270,13380,13750,13890,13980,14020,14040,14140,14160,14050,13370,13730,13870,13960,14010,14010,14100,14130,13980,13440,13720,13860,13960,14000,14000,14100,14130,14180,14150,14560,14730,14830,14870,14870,14960,15000,15010}; | |
uint16_t RAWDATA_MIN[108] = {10610,10720,10770,10800,10870,10850,10930,10920,10680,10140,10340,10410,10460,10490,10480,10540,10530,10280,10090,10300,10370,10430,10460,10460,10500,10500,10250,10060,10270,10340,10410,10440,10440,10490,10470,10230,10030,10250,10320,10380,10400,10410,10460,10460,10210,10020,10220,10290,10340,10360,10360,10430,10440,10190,10010,10200,10270,10320,10350,10350,10410,10420,10180,9900,10170,10270,10330,10370,10380,10460,10500,10540,9890,10160,10270,10330,10360,10370,10450,10470,10390,9880,10150,10250,10320,10350,10360,10420,10440,10330,9930,10140,10250,10310,10350,10350,10420,10450,10480,10460,10760,10880,10960,10990,10990,11060,11090,11100}; | |
#endif | |
uint8_t buf_firmware_show[3]; | |
int i, j, ret; | |
printk("[TSP] %s entered. line : %d, \n", __func__,__LINE__); | |
if(testmode==1) return sprintf(buf, "-1"); | |
#if defined(CONFIG_TARGET_LOCALE_AUS_TEL) | |
printk("[TSP] rawdata_pass_fail_silabs at AU Version Read Test \n"); | |
buf_firmware_show[0] = ESCAPE_ADDR; | |
buf_firmware_show[1] = TS_READ_VERSION_ADDR; | |
ret = i2c_master_send(ts_global->client, &buf_firmware_show, 2); | |
if(ret < 0) | |
{ | |
printk(KERN_ERR "silabs_ts_work_func : i2c_master_send [%d]\n", ret); | |
} | |
ret = i2c_master_recv(ts_global->client, &buf_firmware_show, 3); | |
if(ret < 0) | |
{ | |
printk(KERN_ERR "silabs_ts_work_func : i2c_master_recv [%d]\n", ret); | |
} | |
printk("[TSP][rawdata_pass_fail_silabs] ver tsp=0x%x, HW=0x%x, SW=0x%x\n", buf_firmware_show[1], buf_firmware_show[2], buf_firmware_show[0]); | |
if(buf_firmware_show[2] == T_YTE_MODULE_VER_NEW) //TYE Module | |
TSP_MODULE_ID = T_YTE_MODULE_VER_NEW; | |
else if(buf_firmware_show[2] == T_SMAC_MODULE_VER) //TYE Module | |
TSP_MODULE_ID = T_SMAC_MODULE_VER; | |
printk("[TSP][rawdata_pass_fail_silabs] TSP_MODULE_ID = 0x%x \n", TSP_MODULE_ID); | |
#endif | |
mdelay(300); | |
buffer1[0] = ESCAPE_ADDR; | |
buffer1[1] = JIG_MODE_COMMAND; | |
ret = i2c_master_send(ts_global->client, buffer1, 2); | |
if (ret < 0) | |
{ | |
printk("[TSP] i2c_master_send fail! %s : %d, \n", __func__,__LINE__); | |
return sprintf(buf, "-1"); | |
} | |
ret = i2c_master_recv(ts_global->client,buffer2, 1); | |
if (ret < 0) | |
{ | |
printk("[TSP] i2c_master_recv fail! %s : %d, \n", __func__,__LINE__); | |
return sprintf(buf, "-1"); | |
} | |
// | |
// quicksense format for reading rawdata | |
// | |
#if defined(CONFIG_TARGET_LOCALE_AUS_TEL) | |
ret = silabs_quicksense(RAWDATA_ADDRESS,NUM_TX_CHANNEL*NUM_RX_CHANNEL*2, buffer2); | |
#else | |
ret = silabs_quicksense(RAWDATA_ADDRESS,NUM_RX_CHANNEL*2, buffer2); | |
#endif | |
if (ret != 0) | |
{ | |
printk("[TSP] silabs_quicksense fail! %s : %d, \n", __func__,__LINE__); | |
return sprintf(buf, "-1"); | |
} | |
#if defined(CONFIG_TARGET_LOCALE_AUS_TEL) | |
for (i = 0; i < Tx_Channel; i++) | |
{ | |
for(j = 0 ; j < Rx_Channel; j++) | |
{ | |
rawdata[i][j] = (buffer2[(i*Rx_Channel+j)*2 + QUICKSENSE_OVERHEAD -1] <<8) + buffer2[(i*Rx_Channel+j)*2+QUICKSENSE_OVERHEAD]; | |
if(TSP_MODULE_ID == T_YTE_MODULE_VER_NEW) | |
{ | |
if( TYE_RAWDATA_MAX[i*Rx_Channel+j] < rawdata[i][j]) | |
{ | |
printk("[TSP] rawdata_pass_fail_silabs MAX rawdata[%d][%d] = %d \n", i,j,rawdata[i][j]); | |
return sprintf(buf, "0"); // fail | |
} | |
if( TYE_RAWDATA_MIN[i*Rx_Channel+j] > rawdata[i][j]) | |
{ | |
printk("[TSP] rawdata_pass_fail_silabs MIN rawdata[%d][%d] = %d \n", i,j,rawdata[i][j]); | |
return sprintf(buf, "0"); // fail | |
} | |
} | |
else if(TSP_MODULE_ID == T_SMAC_MODULE_VER) | |
{ | |
if( SMAC_RAWDATA_MAX[i*Rx_Channel+j] < rawdata[i][j]) | |
{ | |
printk("[TSP] rawdata_pass_fail_silabs MAX rawdata[%d][%d] = %d \n", i,j,rawdata[i][j]); | |
return sprintf(buf, "0"); // fail | |
} | |
if( SMAC_RAWDATA_MIN[i*Rx_Channel+j] > rawdata[i][j]) | |
{ | |
printk("[TSP] rawdata_pass_fail_silabs MIN rawdata[%d][%d] = %d \n", i,j,rawdata[i][j]); | |
return sprintf(buf, "0"); // fail | |
} | |
} | |
} | |
} | |
#else | |
for (i = 0; i < 1; i++) | |
{ | |
for(j = 0 ; j < Rx_Channel; j++) | |
{ | |
rawdata[i][j] = (buffer2[(i*Rx_Channel+j)*2 + QUICKSENSE_OVERHEAD -1] <<8) + buffer2[(i*Rx_Channel+j)*2+QUICKSENSE_OVERHEAD]; | |
if( RAWDATA_MAX[i*Rx_Channel+j] < rawdata[i][j]) | |
{ | |
return sprintf(buf, "0"); // fail | |
} | |
if( RAWDATA_MIN[i*Rx_Channel+j] > rawdata[i][j]) | |
{ | |
return sprintf(buf, "0"); // fail | |
} | |
} | |
} | |
#endif | |
buf_firmware_show[0] = ESCAPE_ADDR; | |
buf_firmware_show[1] = TS_READ_VERSION_ADDR; | |
ret = i2c_master_send(ts_global->client, (const char *)&buf_firmware_show, 2); | |
if(ret < 0) | |
{ | |
printk(KERN_ERR "silabs_ts_work_func : i2c_master_send [%d]\n", ret); | |
} | |
ret = i2c_master_recv(ts_global->client, (char *)&buf_firmware_show, 3); | |
if(ret < 0) | |
{ | |
printk(KERN_ERR "silabs_ts_work_func : i2c_master_recv [%d]\n", ret); | |
} | |
printk("[TSP] ver tsp=%x, HW=%x, SW=%x\n", buf_firmware_show[1], buf_firmware_show[2], buf_firmware_show[0]); | |
#if defined(CONFIG_TARGET_LOCALE_AUS_TEL) | |
if (buf_firmware_show[2] == T_YTE_MODULE_VER_NEW) | |
PHONE_VER = T_FW_VER_NEW_YTE; | |
else if (buf_firmware_show[2] == T_SMAC_MODULE_VER) | |
PHONE_VER = T_SMAC_FW_VER; | |
else | |
#endif | |
if (( buf_firmware_show[2] == YTE_MODULE_VER)||( buf_firmware_show[2] == SMAC_MODULE_VER)) | |
PHONE_VER = FW_VER; | |
else if ( buf_firmware_show[2] == YTE_MODULE_VER_OLD) | |
PHONE_VER = FW_VER_OLD; | |
else if ( buf_firmware_show[2] == SMAC_MODULE_VER_OLD) | |
PHONE_VER = FW_VER_OLD_SMAC; | |
else if ( buf_firmware_show[2] == YTE_MODULE_VER_NEW) | |
PHONE_VER = FW_VER_NEW_YTE; | |
else if (buf_firmware_show[2] == SMAC_MODULE_VER_NEW) | |
PHONE_VER = FW_VER_NEW_SMAC; | |
printk("[TSP][rawdata_pass_fail_silabs] PHONE_VER = %x \n", PHONE_VER); | |
if(buf_firmware_show[0]!=PHONE_VER) | |
return sprintf(buf, "0"); | |
return sprintf(buf, "1"); // success | |
} | |
static ssize_t rawdata_show_silabs(struct device *dev, struct device_attribute *attr, char *buf) | |
{ | |
int Tx_Channel = NUM_TX_CHANNEL; | |
int Rx_Channel = NUM_RX_CHANNEL; | |
int written_bytes = 0 ; /* & error check */ | |
uint8_t buffer1[NUM_TX_CHANNEL*NUM_RX_CHANNEL*2+QUICKSENSE_OVERHEAD]={0,}; | |
uint8_t buffer2[NUM_TX_CHANNEL*NUM_RX_CHANNEL*2+QUICKSENSE_OVERHEAD]={0,}; | |
uint16_t rawdata[NUM_TX_CHANNEL][NUM_RX_CHANNEL]={{0,},}; | |
uint16_t baseline[NUM_TX_CHANNEL][NUM_RX_CHANNEL]={{0,},}; | |
int i, j, ret; | |
printk("[TSP] %s entered. line : %d, \n", __func__,__LINE__); | |
if(testmode==1) return 0; | |
mdelay(300); | |
buffer1[0] = ESCAPE_ADDR; | |
buffer1[1] = JIG_MODE_COMMAND; | |
ret = i2c_master_send(ts_global->client, buffer1, 2); | |
if (ret < 0) | |
{ | |
printk("[TSP] i2c_master_send fail! %s : %d, \n", __func__,__LINE__); | |
return -1; | |
} | |
ret = i2c_master_recv(ts_global->client,buffer2, 1); | |
if (ret < 0) | |
{ | |
printk("[TSP] i2c_master_recv fail! %s : %d, \n", __func__,__LINE__); | |
return -1; | |
} | |
// | |
// quicksense format for reading baseline | |
// | |
ret = silabs_quicksense(BASELINE_ADDRESS,NUM_TX_CHANNEL*NUM_RX_CHANNEL*2, buffer1); | |
if (ret != 0) | |
{ | |
printk("[TSP] silabs_quicksense fail! %s : %d, \n", __func__,__LINE__); | |
return -1; | |
} | |
for (i = 0; i < Tx_Channel; i++) | |
{ | |
for(j = 0 ; j < Rx_Channel; j++) | |
{ | |
baseline[i][j] = (buffer1[(i*Rx_Channel+j)*2 + QUICKSENSE_OVERHEAD -1] <<8) + buffer1[(i*Rx_Channel+j)*2+QUICKSENSE_OVERHEAD]; | |
} | |
} | |
// | |
// quicksense format for reading rawdata | |
// | |
ret = silabs_quicksense(RAWDATA_ADDRESS,NUM_TX_CHANNEL*NUM_RX_CHANNEL*2, buffer2); | |
if (ret != 0) | |
{ | |
printk("[TSP] silabs_quicksense fail! %s : %d, \n", __func__,__LINE__); | |
return -1; | |
} | |
for (i = 0; i < Tx_Channel; i++) | |
{ | |
for(j = 0 ; j < Rx_Channel; j++) | |
{ | |
rawdata[i][j] = (buffer2[(i*Rx_Channel+j)*2 + QUICKSENSE_OVERHEAD -1] <<8) + buffer2[(i*Rx_Channel+j)*2+QUICKSENSE_OVERHEAD]; | |
written_bytes += sprintf(buf+written_bytes, "%d %d\n", rawdata[i][j], baseline[i][j]-rawdata[i][j]) ; | |
} | |
} | |
if (written_bytes > 0) | |
return written_bytes ; | |
return sprintf(buf, "-1") ; | |
} | |
static ssize_t baseline_show_silabs(struct device *dev, struct device_attribute *attr, char *buf1) | |
{ | |
int Tx_Channel = NUM_TX_CHANNEL; | |
int Rx_Channel = NUM_RX_CHANNEL; | |
int written_bytes = 0 ; /* & error check */ | |
uint8_t buffer[NUM_TX_CHANNEL*NUM_RX_CHANNEL*2+QUICKSENSE_OVERHEAD]={0,}; | |
uint16_t baseline[NUM_TX_CHANNEL][NUM_RX_CHANNEL]={{0,},}; | |
int i, j, ret; | |
if(testmode==1) return 0; | |
printk("[TSP] %s entered. line : %d, \n", __func__,__LINE__); | |
mdelay(300); | |
// | |
// Entering JIG_MODE | |
// | |
buffer[0] = ESCAPE_ADDR; | |
buffer[1] = JIG_MODE_COMMAND; | |
ret = i2c_master_send(ts_global->client, buffer, 2); | |
if (ret < 0) | |
{ | |
printk("[TSP] i2c_master_send fail! %s : %d, \n", __func__,__LINE__); | |
return -1; | |
} | |
ret = i2c_master_recv(ts_global->client,buffer, 1); | |
if (ret < 0) | |
{ | |
printk("[TSP] i2c_master_recv fail! %s : %d, \n", __func__,__LINE__); | |
return -1; | |
} | |
// | |
// quicksense format for reading baseline | |
// | |
ret = silabs_quicksense(BASELINE_ADDRESS,NUM_TX_CHANNEL*NUM_RX_CHANNEL*2, buffer); | |
if (ret != 0) | |
{ | |
printk("[TSP] silabs_quicksense fail! %s : %d, \n", __func__,__LINE__); | |
return -1; | |
} | |
for (i = 0; i < Tx_Channel; i++) | |
{ | |
for(j = 0 ; j < Rx_Channel; j++) | |
{ | |
baseline[i][j] = (buffer[(i*Rx_Channel+j)*2 + QUICKSENSE_OVERHEAD -1] <<8) + buffer[(i*Rx_Channel+j)*2+QUICKSENSE_OVERHEAD]; | |
printk(" %5d", baseline[i][j]); | |
written_bytes += sprintf(buf1+written_bytes, "%d\n", baseline[i][j]) ; | |
} | |
printk("\n"); | |
} | |
if (written_bytes > 0) | |
return written_bytes ; | |
return sprintf(buf1, "-1") ; | |
} | |
static ssize_t diff_show_silabs(struct device *dev, struct device_attribute *attr, char *buf) | |
{ | |
int Tx_Channel = NUM_TX_CHANNEL; | |
int Rx_Channel = NUM_RX_CHANNEL; | |
uint8_t buffer1[NUM_TX_CHANNEL*NUM_RX_CHANNEL*2+QUICKSENSE_OVERHEAD]={0,}; | |
uint8_t buffer2[NUM_TX_CHANNEL*NUM_RX_CHANNEL*2+QUICKSENSE_OVERHEAD]={0,}; | |
uint16_t rawdata[NUM_TX_CHANNEL][NUM_RX_CHANNEL]={{0,},}; | |
uint16_t baseline[NUM_TX_CHANNEL][NUM_RX_CHANNEL]={{0,},}; | |
int i, j, ret; | |
printk("[TSP] %s entered. line : %d, \n", __func__,__LINE__); | |
if(testmode==1) return 0; | |
mdelay(300); | |
buffer1[0] = ESCAPE_ADDR; | |
buffer1[1] = JIG_MODE_COMMAND; | |
ret = i2c_master_send(ts_global->client, buffer1, 2); | |
if (ret < 0) | |
{ | |
printk("[TSP] i2c_master_send fail! %s : %d, \n", __func__,__LINE__); | |
return -1; | |
} | |
ret = i2c_master_recv(ts_global->client, buffer1, 1); | |
if (ret < 0) | |
{ | |
printk("[TSP] i2c_master_recv fail! %s : %d, \n", __func__,__LINE__); | |
return -1; | |
} | |
// | |
// quicksense format for reading baseline | |
// | |
ret = silabs_quicksense(BASELINE_ADDRESS,NUM_TX_CHANNEL*NUM_RX_CHANNEL*2, buffer1); | |
if (ret != 0) | |
{ | |
printk("[TSP] silabs_quicksense fail! %s : %d, \n", __func__,__LINE__); | |
return -1; | |
} | |
for (i = 0; i < Tx_Channel; i++) | |
{ | |
for(j = 0 ; j < Rx_Channel; j++) | |
{ | |
baseline[i][j] = (buffer1[(i*Rx_Channel+j)*2 + QUICKSENSE_OVERHEAD -1] <<8) + buffer1[(i*Rx_Channel+j)*2+QUICKSENSE_OVERHEAD]; | |
//printk(" %5d", baseline[i][j]); | |
} | |
} | |
// | |
// quicksense format for reading rawdata | |
// | |
ret = silabs_quicksense(RAWDATA_ADDRESS,NUM_TX_CHANNEL*NUM_RX_CHANNEL*2, buffer2); | |
if (ret != 0) | |
{ | |
printk("[TSP] silabs_quicksense fail! %s : %d, \n", __func__,__LINE__); | |
return -1; | |
} | |
for (i = 0; i < Tx_Channel; i++) | |
{ | |
for(j = 0 ; j < Rx_Channel; j++) | |
{ | |
rawdata[i][j] = (buffer2[(i*Rx_Channel+j)*2 + QUICKSENSE_OVERHEAD -1] <<8) + buffer2[(i*Rx_Channel+j)*2+QUICKSENSE_OVERHEAD]; | |
printk(" %5d", baseline[i][j]-rawdata[i][j]); | |
} | |
printk("\n"); | |
} | |
return 0; | |
} | |
static ssize_t firmware_show(struct device *dev, struct device_attribute *attr, char *buf) | |
{ | |
uint8_t buf_firmware_show[3]; | |
int ret; | |
/* | |
buf = [1][2][3][4][5][6][7][8] : [1] - Don't care | |
[2][3] - module version | |
[4][5] - TSP part vesion | |
[6][7] - TSP part vesion | |
*/ | |
printk("[TSP] %s\n",__func__); | |
buf_firmware_show[0] = ESCAPE_ADDR; | |
buf_firmware_show[1] = TS_READ_VERSION_ADDR; | |
ret = i2c_master_send(ts_global->client,(const char *) &buf_firmware_show, 2); | |
if(ret < 0) | |
{ | |
printk(KERN_ERR "silabs_ts_work_func : i2c_master_send [%d]\n", ret); | |
} | |
ret = i2c_master_recv(ts_global->client, (char *)&buf_firmware_show, 3); | |
if(ret < 0) | |
{ | |
printk(KERN_ERR "silabs_ts_work_func : i2c_master_recv [%d]\n", ret); | |
} | |
printk("[TSP] ver tsp=%x, HW=%x, SW=%x\n", buf_firmware_show[1], buf_firmware_show[2], buf_firmware_show[0]); | |
if (( buf_firmware_show[2] == YTE_MODULE_VER)||( buf_firmware_show[2] == SMAC_MODULE_VER)) | |
{ | |
PHONE_VER = FW_VER; | |
} | |
else if ( buf_firmware_show[2] == YTE_MODULE_VER_OLD) | |
{ | |
PHONE_VER = FW_VER_OLD; | |
} | |
else if ( buf_firmware_show[2] == SMAC_MODULE_VER_OLD) | |
{ | |
PHONE_VER = FW_VER_OLD_SMAC; | |
sprintf(buf, "10%x%x%x\n", buf_firmware_show[2], buf_firmware_show[0], PHONE_VER); | |
printk("[TSP] %s\n", buf); | |
return sprintf(buf, "%s", buf ); | |
} | |
else if ( buf_firmware_show[2] == YTE_MODULE_VER_NEW) | |
{ | |
PHONE_VER = FW_VER_NEW_YTE; | |
sprintf(buf, "10%x%x%x\n", buf_firmware_show[2], buf_firmware_show[0], PHONE_VER); | |
printk("[TSP] %s\n", buf); | |
return sprintf(buf, "%s", buf ); | |
} | |
else if (buf_firmware_show[2] == SMAC_MODULE_VER_NEW) | |
{ | |
PHONE_VER = FW_VER_NEW_SMAC; | |
sprintf(buf, "10%x%x%x\n", buf_firmware_show[2], buf_firmware_show[0], PHONE_VER); | |
printk("[TSP] %s\n", buf); | |
return sprintf(buf, "%s", buf ); | |
} | |
#if defined(CONFIG_TARGET_LOCALE_AUS_TEL) | |
else if (buf_firmware_show[2] == T_YTE_MODULE_VER_NEW) | |
{ | |
PHONE_VER = T_FW_VER_NEW_YTE; | |
sprintf(buf, "10%x0%x0%x\n", buf_firmware_show[2], buf_firmware_show[0], PHONE_VER); | |
printk("[TSP] %s\n", buf); | |
return sprintf(buf, "%s", buf ); | |
} | |
else if (buf_firmware_show[2] == T_SMAC_MODULE_VER) | |
{ | |
PHONE_VER = T_SMAC_FW_VER; | |
sprintf(buf, "1%x0%x0%x\n", buf_firmware_show[2], buf_firmware_show[0], PHONE_VER); | |
printk("[TSP] %s\n", buf); | |
return sprintf(buf, "%s", buf ); | |
} | |
#endif | |
sprintf(buf, "10%x0%x0%x\n", buf_firmware_show[2], buf_firmware_show[0], PHONE_VER); | |
printk("[TSP] %s\n", buf); | |
return sprintf(buf, "%s", buf ); | |
} | |
static ssize_t fimware_show_versname(struct device *dev, struct device_attribute *attr, char *buf) | |
{ | |
uint8_t buf_firmware_ver[3]; | |
int ret; | |
printk("[TSP] %s\n",__func__); | |
buf_firmware_ver[0] = ESCAPE_ADDR; | |
buf_firmware_ver[1] = TS_READ_VERSION_ADDR; | |
ret = i2c_master_send(ts_global->client,(const char *) &buf_firmware_ver, 2); | |
if(ret < 0) | |
{ | |
printk(KERN_ERR "silabs_ts_work_func : i2c_master_send [%d]\n", ret); | |
} | |
ret = i2c_master_recv(ts_global->client, (char *) &buf_firmware_ver, 3); | |
if(ret < 0) | |
{ | |
printk(KERN_ERR "silabs_ts_work_func : i2c_master_recv [%d]\n", ret); | |
} | |
printk("[TSP] ver tsp=%x, HW=%x, SW=%x\n", buf_firmware_ver[1], buf_firmware_ver[2], buf_firmware_ver[0]); | |
sprintf(buf, "%x\n", buf_firmware_ver[0]); | |
printk("[TSP] %s\n", buf); | |
return sprintf(buf, "%s", buf ); | |
} | |
static ssize_t read_node(struct device *dev, struct device_attribute *attr, char *buf) | |
{ | |
char *after; | |
int written_bytes = 0 ; /* & error check */ | |
uint8_t buffer[NUM_TX_CHANNEL*NUM_RX_CHANNEL*2+QUICKSENSE_OVERHEAD]={0,}; | |
int i, j, ret; | |
check_node = simple_strtoul(buf, &after, 10); | |
printk(KERN_INFO "[TSP] %s, %d\n", __func__, __LINE__); | |
mdelay(300); | |
// | |
// Entering JIG_MODE | |
// | |
buffer[0] = ESCAPE_ADDR; | |
buffer[1] = JIG_MODE_COMMAND; | |
ret = i2c_master_send(ts_global->client, buffer, 2); | |
if (ret < 0) | |
{ | |
printk("[TSP] i2c_master_send fail! %s : %d, \n", __func__,__LINE__); | |
return -1; | |
} | |
ret = i2c_master_recv(ts_global->client,buffer, 1); | |
if (ret < 0) | |
{ | |
printk("[TSP] i2c_master_recv fail! %s : %d, \n", __func__,__LINE__); | |
return -1; | |
} | |
// | |
// quicksense format for reading baseline | |
// | |
ret = silabs_quicksense(BASELINE_ADDRESS,NUM_TX_CHANNEL*NUM_RX_CHANNEL*2, buffer); | |
if (ret != 0) | |
{ | |
printk("[TSP] silabs_quicksense fail! %s : %d, \n", __func__,__LINE__); | |
return -1; | |
} | |
for (i = 0; i < Tx_Channel; i++) | |
{ | |
for(j = 0 ; j < Rx_Channel; j++) | |
{ | |
baseline_node[i][j] = (buffer[(i*Rx_Channel+j)*2 + QUICKSENSE_OVERHEAD -1] <<8) + buffer[(i*Rx_Channel+j)*2+QUICKSENSE_OVERHEAD]; | |
printk(" %5d", baseline_node[i][j]); | |
} | |
printk("\n"); | |
} | |
for (j = 0; j < Rx_Channel; j++) | |
{ | |
for(i = 0 ; i < Tx_Channel; i++) | |
{ | |
written_bytes += sprintf(buf+written_bytes, ",%d", baseline_node[i][j]) ; | |
} | |
} | |
printk("[TSP] %s\n", buf); | |
touch_ctrl_regulator(0); | |
mdelay(2); | |
touch_ctrl_regulator(1); | |
mdelay(300); | |
return written_bytes; | |
} | |
/* firmware - update */ | |
static ssize_t firmware_ret_show(struct device *dev, struct device_attribute *attr, char *buf) | |
{ | |
printk("[TSP] %s!\n", __func__); | |
printk("[TSP] %s : %d\n", __func__, firmware_ret_val); | |
firm_update( ); | |
return sprintf(buf, "%d", firmware_ret_val ); | |
} | |
int firm_update( void ) | |
{ | |
int ret; | |
printk(KERN_INFO "[TSP] %s, %d\n", __func__, __LINE__); | |
disable_irq(tsp_irq); | |
ret = cancel_work_sync(&ts_global->work_timer); | |
ret = cancel_work_sync(&ts_global->work); | |
hrtimer_cancel(&ts_global->timer); | |
touch_ctrl_regulator(TOUCH_OFF); | |
mdelay(200); | |
touch_ctrl_regulator(TOUCH_ON); | |
mdelay(200); | |
TSP_MODULE_ID = buf_firmware[2]; | |
local_irq_disable(); | |
firmware_ret_val = Firmware_Download(); | |
local_irq_enable(); | |
msleep(1000); | |
if( firmware_ret_val ) | |
printk(KERN_INFO "[TSP] %s success, %d\n", __func__, __LINE__); | |
else | |
printk(KERN_INFO "[TSP] %s fail, %d\n", __func__, __LINE__); | |
local_irq_enable(); | |
enable_irq(tsp_irq); | |
hrtimer_start(&ts_global->timer, ktime_set(1, 0), HRTIMER_MODE_REL); | |
return 0; | |
} | |
module_init(silabs_ts_init); | |
module_exit(silabs_ts_exit); | |
MODULE_DESCRIPTION("silabs Touchscreen Driver"); | |
MODULE_LICENSE("GPL"); |