/* * * Zinitix touch driver * * Copyright (C) 2009 Zinitix, 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. * */ /* Version 2.0.0 : using reg data file (2010/11/05) Version 2.0.1 : syntxt bug fix (2010/11/09) Version 2.0.2 : Save status cmd delay bug (2010/11/10) Version 2.0.3 : modify delay 10ms -> 50ms for clear hw calibration bit : modify ZINITIX_TOTAL_NUMBER_OF_Y register (read only -> read/write ) : modify SUPPORTED FINGER NUM register (read only -> read/write ) Version 2.0.4 : [20101116] Modify Firmware Upgrade routine. Version 2.0.5 : [20101118] add esd timer function & some bug fix. you can select request_threaded_irq or request_irq, setting USE_THREADED_IRQ. Version 2.0.6 : [20101123] add ABS_MT_WIDTH_MAJOR Report Version 2.0.7 : [20101201] Modify zinitix_early_suspend() / zinitix_late_resume() routine. Version 2.0.8 : [20101216] add using spin_lock option Version 2.0.9 : [20101216] Test Version Version 2.0.10 : [20101217] add USE_THREAD_METHOD option. if USE_THREAD_METHOD = 0, you use workqueue Version 2.0.11 : [20101229] add USE_UPDATE_SYSFS option for update firmware. && TOUCH_MODE == 1 mode. Version 2.0.13 : [20110125] modify esd timer routine Version 2.0.14 : [20110217] esd timer bug fix. (kernel panic) sysfs bug fix. Version 2.0.15 : [20110315] add power off delay ,250ms Version 2.0.16 : [20110316] add upgrade method using isp Version 2.0.17 : [20110406] change naming rule : sain -> zinitix (add) pending interrupt skip add isp upgrade mode remove warning message when complile Version 3.0.2 : [20110711] support bt4x3 series Version 3.0.3 : [20110720] add raw data monitoring func. add the h/w calibration skip option. Version 3.0.4 : [20110728] fix using semaphore bug. Version 3.0.5 : [20110801] fix some bugs. Version 3.0.6 : [20110802] fix Bt4x3 isp upgrade bug. add USE_TS_MISC_DEVICE option for showing info & upgrade remove USE_UPDATE_SYSFS option Version 3.0.7 : [201108016] merge USE_TS_MISC_DEVICE option and USE_TEST_RAW_TH_DATA_MODE fix work proceedure bug. Version 3.0.8 / Version 3.0.9 : [201108017] add ioctl func. Version 3.0.10 : [201108030] support REAL_SUPPORTED_FINGER_NUM Version 3.0.11 : [201109014] support zinitix apps. Version 3.0.12 : [201109015] add disable touch event func. Version 3.0.13 : [201109015] add USING_CHIP_SETTING option : interrupt mask/button num/finger num Version 3.0.14 : [201109020] support apps. above kernel version 2.6.35 Version 3.0.15 : [201101004] modify timing in firmware upgrade retry when failt to upgrade firmware Version 3.0.16 : [20111024] remove thread method. add resume/suspend function check code using checkpatch.pl Version 3.0.19 : [20111124] modify isp timing : 2ms -> 1ms Version 3.0.20 : [20120201] support icecream sandwich remove bt4x2 option */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //#include #include "zinitix_touch.h" #include "zinitix_touch_bt4x3_firmware.h" #include "zinitix_touch_bt4x3_reg_data.h" #define PHONE_FW_VER 0x05 #define TSP_INT 30 #define TSP_SDA 27 #define TSP_SCL 26 #define TOUCH_ON 1 #define TOUCH_OFF 0 static struct regulator *touch_regulator_2_9=NULL; static struct regulator *touch_regulator_3_3=NULL; #define ZINITIX_DEBUG 0 static int m_ts_debug_mode = ZINITIX_DEBUG; static int firmware_ret_val = -1; #define SYSTEM_MAX_X_RESOLUTION 320 #define SYSTEM_MAX_Y_RESOLUTION 480 #define SYSTEM_VALUE 0xFFFB /* interrupt pin number*/ #define GPIO_TOUCH_PIN_NUM 60 /* interrupt pin IRQ number */ #define GPIO_TOUCH_IRQ 0 static struct workqueue_struct *zinitix_workqueue; static struct workqueue_struct *zinitix_tmr_workqueue; #define zinitix_debug_msg(fmt, args...) \ if (m_ts_debug_mode) \ printk(KERN_INFO "[%-18s:%5d]" fmt, \ __func__, __LINE__, ## args); struct _ts_zinitix_coord { u16 x; u16 y; u8 width; u8 sub_status; }; struct _ts_zinitix_point_info { u16 status; u8 finger_cnt; u8 time_stamp; struct _ts_zinitix_coord coord[MAX_SUPPORTED_FINGER_NUM]; }; #define TOUCH_V_FLIP 0x01 #define TOUCH_H_FLIP 0x02 #define TOUCH_XY_SWAP 0x04 struct _ts_capa_info { u16 chip_revision; u16 chip_firmware_version; u16 chip_reg_data_version; u16 x_resolution; u16 y_resolution; u32 chip_fw_size; u32 MaxX; u32 MaxY; u32 MinX; u32 MinY; u32 Orientation; u8 gesture_support; u16 multi_fingers; u16 button_num; u16 chip_int_mask; #if USE_TEST_RAW_TH_DATA_MODE u16 x_node_num; u16 y_node_num; u16 total_node_num; u16 max_y_node; u16 total_cal_n; #endif }; enum _ts_work_proceedure { TS_NO_WORK = 0, TS_NORMAL_WORK, TS_ESD_TIMER_WORK, TS_IN_EALRY_SUSPEND, TS_IN_SUSPEND, TS_IN_RESUME, TS_IN_LATE_RESUME, TS_IN_UPGRADE, TS_REMOVE_WORK, TS_SET_MODE, TS_HW_CALIBRAION, }; struct zinitix_touch_dev { struct input_dev *input_dev; struct task_struct *task; wait_queue_head_t wait; struct work_struct work; struct work_struct tmr_work; struct i2c_client *client; struct semaphore update_lock; u32 i2c_dev_addr; struct _ts_capa_info cap_info; char phys[32]; bool is_valid_event; struct _ts_zinitix_point_info touch_info; struct _ts_zinitix_point_info reported_touch_info; u16 icon_event_reg; u16 event_type; u32 int_gpio_num; u32 irq; u8 button[MAX_SUPPORTED_BUTTON_NUM]; u8 work_proceedure; struct semaphore work_proceedure_lock; u8 use_esd_timer; bool in_esd_timer; struct timer_list esd_timeout_tmr; struct timer_list *p_esd_timeout_tmr; #ifdef CONFIG_HAS_EARLYSUSPEND struct early_suspend early_suspend; #endif #if USE_TEST_RAW_TH_DATA_MODE struct semaphore raw_data_lock; u16 raw_mode_flag; s16 ref_data[MAX_TEST_RAW_DATA]; s16 cur_data[MAX_RAW_DATA]; u8 update; #endif }; #define ZINITIX_DRIVER_NAME "Zinitix_tsp" #define ZINITIX_ISP_NAME "zinitix_isp" static struct i2c_client *m_isp_client; static char IsfwUpdate[20]={0}; #define FW_DOWNLOADING "Downloading" #define FW_DOWNLOAD_COMPLETE "Complete" #define FW_DOWNLOAD_FAIL "FAIL" #define FWUP_NOW -1 static struct i2c_device_id zinitix_idtable[] = { {ZINITIX_ISP_NAME, 0}, {ZINITIX_DRIVER_NAME, 0}, { } }; static int tsp_testmode = 0; static int tsp_check = 1; struct zinitix_touch_dev* g_touch_dev; struct regulator *tsp_regulator_18 = NULL; struct regulator *tsp_regulator_33 = NULL; /* 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_sw_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 ssize_t zinitix_enter_testmode(struct device *dev, struct device_attribute *attr, char *buf); static ssize_t zinitix_enter_normalmode(struct device *dev, struct device_attribute *attr, char *buf); static ssize_t rawdata_pass_fail_zinitix(struct device *dev, struct device_attribute *attr, char *buf); static ssize_t phone_firmware_show(struct device *dev, struct device_attribute *attr, char *buf); static ssize_t part_firmware_show(struct device *dev, struct device_attribute *attr, char *buf); static ssize_t threshold_firmware_show(struct device *dev, struct device_attribute *attr, char *buf); static ssize_t config_firmware_show(struct device *dev, struct device_attribute *attr, char *buf); static ssize_t read_node(struct device *dev, struct device_attribute *attr, char *buf); static ssize_t read_touchkey(struct device *dev, struct device_attribute *attr, char *buf); static ssize_t scantime_zinitix(struct device *dev, struct device_attribute *attr, char *buf); static ssize_t firmware_update_status(struct device *dev, struct device_attribute *attr, char *buf); static DEVICE_ATTR(raw_enable, 0444, zinitix_enter_testmode, NULL) ; static DEVICE_ATTR(raw_disable, 0444, zinitix_enter_normalmode, NULL) ; static DEVICE_ATTR(raw_value, 0444, rawdata_pass_fail_zinitix, NULL) ; static DEVICE_ATTR(firmware , S_IRUGO, firmware_show, NULL); static DEVICE_ATTR(firmware_ver , 0444, firmware_show, NULL); static DEVICE_ATTR(firmware_ret , S_IRUGO, firmware_ret_show, NULL); static DEVICE_ATTR(phone_fw_ver,0444, phone_firmware_show, NULL); static DEVICE_ATTR(part_fw_ver, 0444, part_firmware_show, NULL); static DEVICE_ATTR(threshold_fw_ver, 0444, threshold_firmware_show, NULL); static DEVICE_ATTR(config_fw_ver, 0444, config_firmware_show, NULL); static DEVICE_ATTR(node_read, 0444, read_node, NULL) ; static DEVICE_ATTR(touchkey_read, 0444, read_touchkey, NULL) ; static DEVICE_ATTR(ncount_read, 0444, scantime_zinitix, NULL) ; static DEVICE_ATTR(fw_upstatus, 0444, firmware_update_status, NULL); /* sys fs */ /*<= you must set key button mapping*/ u32 BUTTON_MAPPING_KEY[MAX_SUPPORTED_BUTTON_NUM] = {KEY_MENU, KEY_BACK}; void touch_delay(int time) { mdelay(time); } /* define i2c sub functions*/ inline s32 ts_read_data(struct i2c_client *client, u16 reg, u8 *values, u16 length) { s32 ret; /* select register*/ ret = i2c_master_send(client , (u8 *)® , 2); zinitix_debug_msg("%s, %d, ret : %d\n", __func__, __LINE__, ret ); if (ret < 0) return ret; /* for setup tx transaction. */ udelay(DELAY_FOR_TRANSCATION); ret = i2c_master_recv(client , values , length); zinitix_debug_msg("%s, %d, ret : %d, value, %d\n", __func__, __LINE__, ret ); if (ret < 0) return ret; udelay(DELAY_FOR_POST_TRANSCATION); return length; } inline s32 ts_write_data(struct i2c_client *client, u16 reg, u8 *values, u16 length) { s32 ret; u8 pkt[4]; pkt[0] = (reg)&0xff; pkt[1] = (reg >> 8)&0xff; pkt[2] = values[0]; pkt[3] = values[1]; ret = i2c_master_send(client , pkt , length+2); if (ret < 0) return ret; udelay(DELAY_FOR_POST_TRANSCATION); return length; } inline s32 ts_write_reg(struct i2c_client *client, u16 reg, u16 value) { if (ts_write_data(client, reg, (u8 *)&value, 2) < 0) return I2C_FAIL; return I2C_SUCCESS; } inline s32 ts_write_cmd(struct i2c_client *client, u16 reg) { s32 ret; ret = i2c_master_send(client , (u8 *)® , 2); if (ret < 0) return I2C_FAIL; udelay(DELAY_FOR_POST_TRANSCATION); return I2C_SUCCESS; } inline s32 ts_read_raw_data(struct i2c_client *client, u16 reg, u8 *values, u16 length) { s32 ret; /* select register */ ret = i2c_master_send(client , (u8 *)® , 2); if (ret < 0) return ret; /* for setup tx transaction. */ udelay(200); ret = i2c_master_recv(client , values , length); if (ret < 0) return ret; udelay(DELAY_FOR_POST_TRANSCATION); return length; } inline s32 ts_read_firmware_data(struct i2c_client *client, char *addr, u8 *values, u16 length) { s32 ret; if (addr != NULL) { /* select register*/ ret = i2c_master_send(client , addr , 2); if (ret < 0) return ret; /* for setup tx transaction. */ touch_delay(1); } ret = i2c_master_recv(client , values , length); if (ret < 0) return ret; udelay(DELAY_FOR_POST_TRANSCATION); return length; } inline s32 ts_write_firmware_data(struct i2c_client *client, u8 *values, u16 length) { s32 ret; ret = i2c_master_send(client , values , length); if (ret < 0) return ret; udelay(DELAY_FOR_POST_TRANSCATION); return length; } static int zinitix_touch_probe(struct i2c_client *client, const struct i2c_device_id *i2c_id); static int zinitix_touch_remove(struct i2c_client *client); static bool ts_init_touch(struct zinitix_touch_dev *touch_dev); static void zinitix_clear_report_data(struct zinitix_touch_dev *touch_dev); #ifdef CONFIG_HAS_EARLYSUSPEND static void zinitix_early_suspend(struct early_suspend *h); static void zinitix_late_resume(struct early_suspend *h); #endif static void ts_esd_timer_start(u16 sec, struct zinitix_touch_dev *touch_dev); static void ts_esd_timer_stop(struct zinitix_touch_dev *touch_dev); static void ts_esd_timer_init(struct zinitix_touch_dev *touch_dev); static void ts_esd_timeout_handler(unsigned long data); #if USE_TEST_RAW_TH_DATA_MODE #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) static int ts_misc_fops_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); #else static long ts_misc_fops_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); #endif static int ts_misc_fops_open(struct inode *inode, struct file *filp); static int ts_misc_fops_close(struct inode *inode, struct file *filp); static const struct file_operations ts_misc_fops = { .owner = THIS_MODULE, .open = ts_misc_fops_open, .release = ts_misc_fops_close, #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) .ioctl = ts_misc_fops_ioctl, #else .unlocked_ioctl = ts_misc_fops_ioctl, #endif }; static struct miscdevice touch_misc_device = { .minor = MISC_DYNAMIC_MINOR, .name = "zinitix_touch_misc", .fops = &ts_misc_fops, }; #define TOUCH_IOCTL_BASE 0xbc #define TOUCH_IOCTL_GET_DEBUGMSG_STATE _IOW(TOUCH_IOCTL_BASE, 0, int) #define TOUCH_IOCTL_SET_DEBUGMSG_STATE _IOW(TOUCH_IOCTL_BASE, 1, int) #define TOUCH_IOCTL_GET_CHIP_REVISION _IOW(TOUCH_IOCTL_BASE, 2, int) #define TOUCH_IOCTL_GET_FW_VERSION _IOW(TOUCH_IOCTL_BASE, 3, int) #define TOUCH_IOCTL_GET_REG_DATA_VERSION _IOW(TOUCH_IOCTL_BASE, 4, int) #define TOUCH_IOCTL_VARIFY_UPGRADE_SIZE _IOW(TOUCH_IOCTL_BASE, 5, int) #define TOUCH_IOCTL_VARIFY_UPGRADE_DATA _IOW(TOUCH_IOCTL_BASE, 6, int) #define TOUCH_IOCTL_START_UPGRADE _IOW(TOUCH_IOCTL_BASE, 7, int) #define TOUCH_IOCTL_GET_X_NODE_NUM _IOW(TOUCH_IOCTL_BASE, 8, int) #define TOUCH_IOCTL_GET_Y_NODE_NUM _IOW(TOUCH_IOCTL_BASE, 9, int) #define TOUCH_IOCTL_GET_TOTAL_NODE_NUM _IOW(TOUCH_IOCTL_BASE, 10, int) #define TOUCH_IOCTL_SET_RAW_DATA_MODE _IOW(TOUCH_IOCTL_BASE, 11, int) #define TOUCH_IOCTL_GET_RAW_DATA _IOW(TOUCH_IOCTL_BASE, 12, int) #define TOUCH_IOCTL_GET_X_RESOLUTION _IOW(TOUCH_IOCTL_BASE, 13, int) #define TOUCH_IOCTL_GET_Y_RESOLUTION _IOW(TOUCH_IOCTL_BASE, 14, int) #define TOUCH_IOCTL_HW_CALIBRAION _IOW(TOUCH_IOCTL_BASE, 15, int) #define TOUCH_IOCTL_GET_REG _IOW(TOUCH_IOCTL_BASE, 16, int) #define TOUCH_IOCTL_SET_REG _IOW(TOUCH_IOCTL_BASE, 17, int) #define TOUCH_IOCTL_SEND_SAVE_STATUS _IOW(TOUCH_IOCTL_BASE, 18, int) #define TOUCH_IOCTL_DONOT_TOUCH_EVENT _IOW(TOUCH_IOCTL_BASE, 19, int) struct zinitix_touch_dev *misc_touch_dev; #endif /*USE_TEST_RAW_TH_DATA_MODE */ /* id -> include/linux/i2c-id.h */ static struct i2c_driver zinitix_touch_driver = { .probe = zinitix_touch_probe, .remove = zinitix_touch_remove, #ifndef CONFIG_HAS_EARLYSUSPEND .suspend = zinitix_early_suspend, .resume = zinitix_late_resume, #endif .id_table = zinitix_idtable, .driver = { .name = ZINITIX_DRIVER_NAME, }, }; #if USE_TEST_RAW_TH_DATA_MODE static bool ts_get_raw_data(struct zinitix_touch_dev *touch_dev) { u32 total_node = touch_dev->cap_info.total_node_num; u32 sz; u16 udata; down(&touch_dev->raw_data_lock); if (touch_dev->raw_mode_flag == TOUCH_TEST_RAW_MODE) { sz = (total_node*2 + MAX_TEST_POINT_INFO*2); if (ts_read_raw_data(touch_dev->client, ZINITIX_RAWDATA_REG, (char *)touch_dev->cur_data, sz) < 0) { printk(KERN_INFO "[zinitix_touch] error : read zinitix tc raw data\n"); up(&touch_dev->raw_data_lock); return false; } /* no point, so update ref_data*/ udata = touch_dev->cur_data[total_node]; if (!zinitix_bit_test(udata, BIT_ICON_EVENT) && !zinitix_bit_test(udata, BIT_PT_EXIST)) memcpy((u8 *)touch_dev->ref_data, (u8 *)touch_dev->cur_data, total_node*2); touch_dev->update = 1; memcpy((u8 *)(&touch_dev->touch_info), (u8 *)&touch_dev->cur_data[total_node], sizeof(struct _ts_zinitix_point_info)); up(&touch_dev->raw_data_lock); return true; } else if (touch_dev->raw_mode_flag != TOUCH_NORMAL_MODE) { zinitix_debug_msg("read raw data\r\n"); sz = total_node*2 + sizeof(struct _ts_zinitix_point_info); if (touch_dev->raw_mode_flag == TOUCH_ZINITIX_CAL_N_MODE) { int total_cal_n = touch_dev->cap_info.total_cal_n; if (total_cal_n == 0) total_cal_n = 160; sz = (total_cal_n*2 + sizeof(struct _ts_zinitix_point_info)); if (ts_read_raw_data(touch_dev->client, ZINITIX_RAWDATA_REG, (char *)touch_dev->cur_data, sz) < 0) { printk(KERN_INFO "[zinitix_touch] error : read zinitix tc raw data\n"); up(&touch_dev->raw_data_lock); return false; } misc_touch_dev->update = 1; memcpy((u8 *)(&touch_dev->touch_info), (u8 *)&touch_dev->cur_data[total_cal_n], sizeof(struct _ts_zinitix_point_info)); up(&touch_dev->raw_data_lock); return true; } if (ts_read_raw_data(touch_dev->client, ZINITIX_RAWDATA_REG, (char *)touch_dev->cur_data, sz) < 0) { printk(KERN_INFO "[zinitix_touch] error : read zinitix tc raw data\n"); up(&touch_dev->raw_data_lock); return false; } udata = touch_dev->cur_data[total_node]; if (!zinitix_bit_test(udata, BIT_ICON_EVENT) && !zinitix_bit_test(udata, BIT_PT_EXIST)) memcpy((u8 *)touch_dev->ref_data, (u8 *)touch_dev->cur_data, total_node*2); touch_dev->update = 1; memcpy((u8 *)(&touch_dev->touch_info), (u8 *)&touch_dev->cur_data[total_node], sizeof(struct _ts_zinitix_point_info)); } up(&touch_dev->raw_data_lock); return true; } #endif static bool ts_get_samples(struct zinitix_touch_dev *touch_dev) { int i; zinitix_debug_msg("ts_get_samples+\r\n"); if (gpio_get_value(touch_dev->int_gpio_num)) { /*interrupt pin is high, not valid data.*/ zinitix_debug_msg("woops... inturrpt pin is high\r\n"); return false; } #if USE_TEST_RAW_TH_DATA_MODE if (touch_dev->raw_mode_flag != TOUCH_NORMAL_MODE) { if (ts_get_raw_data(touch_dev) == false) return false; goto continue_check_point_data; } #endif if (ts_read_data(touch_dev->client, ZINITIX_POINT_STATUS_REG, (u8 *)(&touch_dev->touch_info), sizeof(struct _ts_zinitix_point_info)) < 0) { zinitix_debug_msg("error read point info using i2c.-\n"); return false; } continue_check_point_data: zinitix_debug_msg("status = 0x%x , pt cnt = %d, t stamp = %d\n", touch_dev->touch_info.status, touch_dev->touch_info.finger_cnt, touch_dev->touch_info.time_stamp); if (touch_dev->touch_info.status == 0x0 && touch_dev->touch_info.finger_cnt == 100) { zinitix_debug_msg("periodical esd repeated int occured\r\n"); return true; } for (i = 0; i < MAX_SUPPORTED_BUTTON_NUM; i++) touch_dev->button[i] = ICON_BUTTON_UNCHANGE; if (zinitix_bit_test(touch_dev->touch_info.status, BIT_ICON_EVENT)) { udelay(20); if (ts_read_data(touch_dev->client, ZINITIX_ICON_STATUS_REG, (u8 *)(&touch_dev->icon_event_reg), 2) < 0) { printk(KERN_INFO "[zinitix_touch] error read icon info using i2c.\n"); return false; } } zinitix_debug_msg("ts_get_samples-\r\n"); return true; } static bool ts_read_coord(struct zinitix_touch_dev *hDevice) { struct zinitix_touch_dev *touch_dev = (struct zinitix_touch_dev *)hDevice; if (ts_get_samples(touch_dev) == false) return false; ts_write_cmd(touch_dev->client, ZINITIX_CLEAR_INT_STATUS_CMD); udelay(DELAY_FOR_SIGNAL_DELAY); return true; } void firmware_touch_ctrl_regulator(int on_off) { if(on_off==TOUCH_OFF) { // touch_ctrl_regulator(TOUCH_OFF); printk("Tsp off\n"); regulator_disable(tsp_regulator_33); udelay(100); } else { // touch_ctrl_regulator(TOUCH_ON); regulator_enable(tsp_regulator_33); udelay(100); printk("Tsp on\n"); } } void touch_ctrl_regulator(int on_off) { if(on_off==TOUCH_OFF) { // touch_ctrl_regulator(TOUCH_OFF); printk("Tsp off\n"); regulator_disable(tsp_regulator_33); udelay(100); regulator_disable(tsp_regulator_18); } else { // touch_ctrl_regulator(TOUCH_ON); regulator_enable(tsp_regulator_33); udelay(100); regulator_enable(tsp_regulator_18); printk("Tsp on\n"); } } EXPORT_SYMBOL(touch_ctrl_regulator); static void ts_power_control(struct zinitix_touch_dev *touch_dev, u8 ctl) { if (ctl == POWER_OFF) { // touch_ctrl_regulator(TOUCH_OFF); printk("Tsp off\n"); regulator_disable(tsp_regulator_33); regulator_disable(tsp_regulator_18); } else if (ctl == POWER_ON) { // touch_ctrl_regulator(TOUCH_ON); regulator_enable(tsp_regulator_33); udelay(100); regulator_enable(tsp_regulator_18); printk("Tsp on\n"); } } static bool ts_mini_init_touch(struct zinitix_touch_dev *touch_dev) { u16 reg_val; int i; #if USE_CHECKSUM u16 chip_check_reg0, chip_check_reg1, chip_check_reg2, chip_check_reg3; #endif u16 Setvaule = SYSTEM_VALUE; if (touch_dev == NULL) { printk(KERN_INFO "[zinitix_touch] ts_mini_init_touch : error (touch_dev == NULL?)\r\n"); return false; } zinitix_debug_msg("check checksum\r\n"); #if USE_CHECKSUM if (ts_read_data(touch_dev->client, ZINITIX_CHECK_REG0, (u8 *)&chip_check_reg0, 2) < 0) { printk("[zinitix_touch] %s, %d\n", __func__, __LINE__ ); goto fail_mini_init; } if (ts_read_data(touch_dev->client, ZINITIX_CHECK_REG1, (u8 *)&chip_check_reg1, 2) < 0) { printk("[zinitix_touch] %s, %d\n", __func__, __LINE__ ); goto fail_mini_init; } if (ts_read_data(touch_dev->client, ZINITIX_CHECK_REG2, (u8 *)&chip_check_reg2, 2) < 0) { printk("[zinitix_touch] %s, %d\n", __func__, __LINE__ ); goto fail_mini_init; } if (ts_read_data(touch_dev->client, ZINITIX_CHECK_REG3, (u8 *)&chip_check_reg3, 2) < 0) { printk("[Zinitix] %s, %d\n", __func__, __LINE__ ); goto fail_mini_init; } if( (chip_check_reg0!=chip_check_reg2) || (chip_check_reg1!=chip_check_reg3) ) { printk(KERN_INFO "[zinitix_touch] fail to check firmware data\r\n"); goto fail_mini_init; } #endif if (ts_write_cmd(touch_dev->client, ZINITIX_SWRESET_CMD) != I2C_SUCCESS) { printk(KERN_INFO "[zinitix_touch] fail to write reset command\r\n"); goto fail_mini_init; } /* initialize */ if (ts_write_reg(touch_dev->client, ZINITIX_X_RESOLUTION, (u16)(touch_dev->cap_info.x_resolution)) != I2C_SUCCESS) { printk("[Zinitix] %s, %d\n", __func__, __LINE__ ); goto fail_mini_init; } if (ts_write_reg(touch_dev->client, ZINITIX_Y_RESOLUTION, (u16)( touch_dev->cap_info.y_resolution)) != I2C_SUCCESS) { printk("[Zinitix] %s, %d\n", __func__, __LINE__ ); goto fail_mini_init; } if (ts_write_reg(touch_dev->client, 0x00CB, (u16)(Setvaule)) != I2C_SUCCESS) goto fail_mini_init; zinitix_debug_msg("touch max x = %d\r\n", touch_dev->cap_info.x_resolution); zinitix_debug_msg("touch max y = %d\r\n", touch_dev->cap_info.y_resolution); if (ts_write_reg(touch_dev->client, ZINITIX_BUTTON_SUPPORTED_NUM, (u16)touch_dev->cap_info.button_num) != I2C_SUCCESS) { printk("[Zinitix] %s, %d\n", __func__, __LINE__ ); goto fail_mini_init; } if (ts_write_reg(touch_dev->client, ZINITIX_SUPPORTED_FINGER_NUM, (u16)MAX_SUPPORTED_FINGER_NUM) != I2C_SUCCESS) { printk("[Zinitix] %s, %d\n", __func__, __LINE__ ); goto fail_mini_init; } #if USE_TEST_RAW_TH_DATA_MODE if (touch_dev->raw_mode_flag != TOUCH_NORMAL_MODE) { /* Test Mode */ if (ts_write_reg(touch_dev->client, ZINITIX_TOUCH_MODE, touch_dev->raw_mode_flag) != I2C_SUCCESS) { printk("[zinitix_touch] %s, %d\n", __func__, __LINE__ ); goto fail_mini_init; } } else #endif { reg_val = TOUCH_MODE; if (ts_write_reg(touch_dev->client, ZINITIX_TOUCH_MODE, reg_val) != I2C_SUCCESS) { printk("[zinitix_touch] %s, %d\n", __func__, __LINE__ ); goto fail_mini_init; } } /* soft calibration */ if (ts_write_cmd(touch_dev->client, ZINITIX_CALIBRATE_CMD) != I2C_SUCCESS) { printk("[zinitix_touch] %s, %d\n", __func__, __LINE__ ); goto fail_mini_init; } if (ts_write_reg(touch_dev->client, ZINITIX_INT_ENABLE_FLAG, touch_dev->cap_info.chip_int_mask) != I2C_SUCCESS) { printk("[zinitix_touch] %s, %d\n", __func__, __LINE__ ); goto fail_mini_init; } /* read garbage data */ for (i = 0; i < 10; i++) { ts_write_cmd(touch_dev->client, ZINITIX_CLEAR_INT_STATUS_CMD); udelay(10); } #if USE_TEST_RAW_TH_DATA_MODE if (touch_dev->raw_mode_flag != TOUCH_NORMAL_MODE) { /* Test Mode */ if (ts_write_reg(touch_dev->client, ZINITIX_PERIODICAL_INTERRUPT_INTERVAL, ZINITIX_SCAN_RATE_HZ *ZINITIX_RAW_DATA_ESD_TIMER_INTERVAL) != I2C_SUCCESS) printk(KERN_INFO "[zinitix_touch] Fail to set ZINITIX_RAW_DATA_ESD_TIMER_INTERVAL.\r\n"); } else #endif { if (ZINITIX_ESD_TIMER_INTERVAL) { if (ts_write_reg(touch_dev->client, ZINITIX_PERIODICAL_INTERRUPT_INTERVAL, ZINITIX_SCAN_RATE_HZ *ZINITIX_ESD_TIMER_INTERVAL) != I2C_SUCCESS) { printk("[zinitix_touch] %s, %d\n", __func__, __LINE__ ); goto fail_mini_init; } } } if (touch_dev->use_esd_timer) { ts_esd_timer_start(ZINITIX_CHECK_ESD_TIMER, touch_dev); zinitix_debug_msg("esd timer start\r\n"); } zinitix_debug_msg("successfully mini initialized\r\n"); return true; fail_mini_init: printk(KERN_INFO"[zinitix_touch] early mini init fail\n"); if(ts_init_touch(touch_dev) == false) { zinitix_debug_msg("fail initialized\r\n"); return false; } if (touch_dev->use_esd_timer) { ts_esd_timer_start(ZINITIX_CHECK_ESD_TIMER, touch_dev); zinitix_debug_msg("esd timer start\r\n"); } return true; } static void zinitix_touch_tmr_work(struct work_struct *work) { struct zinitix_touch_dev *touch_dev = container_of(work, struct zinitix_touch_dev, tmr_work); printk(KERN_INFO "[zinitix_touch] tmr queue work ++\r\n"); if (touch_dev == NULL) { printk(KERN_INFO "[zinitix_touch] touch dev == NULL ?\r\n"); goto fail_time_out_init; } down(&touch_dev->work_proceedure_lock); if (touch_dev->work_proceedure != TS_NO_WORK) { printk(KERN_INFO "[zinitix_touch] other process occupied (%d)\r\n", touch_dev->work_proceedure); up(&touch_dev->work_proceedure_lock); return; } touch_dev->work_proceedure = TS_ESD_TIMER_WORK; disable_irq(touch_dev->irq); printk(KERN_INFO "[zinitix_touch] error. timeout occured. maybe ts device dead. so reset & reinit.\r\n"); touch_delay(CHIP_POWER_OFF_DELAY); ts_power_control(touch_dev, POWER_OFF); touch_delay(CHIP_POWER_OFF_DELAY); ts_power_control(touch_dev, POWER_ON); touch_delay(CHIP_ON_DELAY); zinitix_debug_msg("clear all reported points\r\n"); zinitix_clear_report_data(touch_dev); if (ts_mini_init_touch(touch_dev) == false) goto fail_time_out_init; touch_dev->work_proceedure = TS_NO_WORK; enable_irq(touch_dev->irq); up(&touch_dev->work_proceedure_lock); printk(KERN_INFO "[zinitix_touch] tmr queue work ----\r\n"); return; fail_time_out_init: printk(KERN_INFO "[zinitix_touch] tmr work : restart error\r\n"); ts_esd_timer_start(ZINITIX_CHECK_ESD_TIMER, touch_dev); touch_dev->work_proceedure = TS_NO_WORK; enable_irq(touch_dev->irq); up(&touch_dev->work_proceedure_lock); } static void ts_esd_timer_start(u16 sec, struct zinitix_touch_dev *touch_dev) { if (touch_dev->p_esd_timeout_tmr != NULL) del_timer(touch_dev->p_esd_timeout_tmr); touch_dev->p_esd_timeout_tmr = NULL; init_timer(&(touch_dev->esd_timeout_tmr)); touch_dev->esd_timeout_tmr.data = (unsigned long)(touch_dev); touch_dev->esd_timeout_tmr.function = ts_esd_timeout_handler; touch_dev->esd_timeout_tmr.expires = jiffies + HZ*sec; touch_dev->p_esd_timeout_tmr = &touch_dev->esd_timeout_tmr; add_timer(&touch_dev->esd_timeout_tmr); } static void ts_esd_timer_stop(struct zinitix_touch_dev *touch_dev) { if (touch_dev->p_esd_timeout_tmr) del_timer(touch_dev->p_esd_timeout_tmr); touch_dev->p_esd_timeout_tmr = NULL; } static void ts_esd_timer_init(struct zinitix_touch_dev *touch_dev) { init_timer(&(touch_dev->esd_timeout_tmr)); touch_dev->esd_timeout_tmr.data = (unsigned long)(touch_dev); touch_dev->esd_timeout_tmr.function = ts_esd_timeout_handler; touch_dev->p_esd_timeout_tmr = NULL; } static void ts_esd_timeout_handler(unsigned long data) { struct zinitix_touch_dev *touch_dev = (struct zinitix_touch_dev *)data; touch_dev->p_esd_timeout_tmr = NULL; queue_work(zinitix_tmr_workqueue, &touch_dev->tmr_work); } #if TOUCH_ONESHOT_UPGRADE static bool ts_check_need_upgrade(u16 curVersion, u16 curRegVersion) { u16 newVersion; newVersion = (u16) (m_firmware_data[0] | (m_firmware_data[1]<<8)); printk(KERN_INFO "[zinitix_touch] cur Version = 0x%x, new Version = 0x%x\n", curVersion, newVersion); if ((curVersion < newVersion)|(curVersion == 0xFFFF)|(curVersion == 0)) return true; else if (curVersion > newVersion) return false; if (m_firmware_data[FIRMWARE_VERSION_POS+2] == 0xff && m_firmware_data[FIRMWARE_VERSION_POS+3] == 0xff) return false; newVersion = (u16) (m_firmware_data[FIRMWARE_VERSION_POS+2] | (m_firmware_data[FIRMWARE_VERSION_POS+3]<<8)); if (curRegVersion < newVersion) return true; return false; } #endif #define TC_PAGE_SZ 64 #define TC_SECTOR_SZ 8 static u8 ts_upgrade_firmware(struct zinitix_touch_dev *touch_dev, const u8 *firmware_data, u32 size) { u16 flash_addr; u8 *verify_data; int retry_cnt = 0; u8 i2c_buffer[TC_PAGE_SZ+2]; zinitix_debug_msg("ts_upgrade_firmware\r\n"); if (m_isp_client == NULL) { printk(KERN_ERR "[zinitix_touch] i2c client for isp is not register \r\n"); return false; } verify_data = kzalloc(size, GFP_KERNEL); if (verify_data == NULL) { printk(KERN_ERR "[zinitix_touch] cannot alloc verify buffer\n"); return false; } retry_isp_firmware_upgrade: firmware_touch_ctrl_regulator(POWER_OFF); mdelay(CHIP_POWER_OFF_AF_FZ_DELAY); firmware_touch_ctrl_regulator(POWER_ON); mdelay(1); /* under 4ms*/ printk(KERN_INFO "[zinitix_touch] write firmware data\n"); for (flash_addr = 0; flash_addr < size; flash_addr += TC_PAGE_SZ) { #if !USE_HW_CALIBRATION if (flash_addr >= CALIBRATION_AREA*2) break; #endif printk(KERN_INFO "."); printk("firmware write : addr = %04x, len = %d\n", flash_addr, TC_PAGE_SZ); i2c_buffer[0] = (flash_addr>>8)&0xff; /*addr_h*/ i2c_buffer[1] = (flash_addr)&0xff; /*addr_l*/ memcpy(&i2c_buffer[2], &firmware_data[flash_addr], TC_PAGE_SZ); if (ts_write_firmware_data(m_isp_client, i2c_buffer, TC_PAGE_SZ+2) < 0) { printk(KERN_INFO"[zinitix_touch] error : write zinitix tc firmare\n"); goto fail_upgrade; } mdelay(20); } mdelay(CHIP_POWER_OFF_AF_FZ_DELAY); printk(KERN_INFO "\r\n[zinitix_touch] read firmware data\n"); flash_addr = 0; i2c_buffer[0] = (flash_addr>>8)&0xff; /*addr_h*/ i2c_buffer[1] = (flash_addr)&0xff; /*addr_l*/ #if !USE_HW_CALIBRATION size = CALIBRATION_AREA*2; #endif if (ts_read_firmware_data(m_isp_client, i2c_buffer, &verify_data[flash_addr], size) < 0) { printk(KERN_INFO "[zinitix_touch] error : read zinitix tc firmare: addr = %04x, len = %d\n", flash_addr, size); goto fail_upgrade; } if (memcmp((u8 *)&firmware_data[flash_addr], (u8 *)&verify_data[flash_addr], size) != 0) { printk(KERN_INFO "[zinitix_touch] error : verify error : addr = %04x, len = %d\n", flash_addr, size); goto fail_upgrade; } mdelay(CHIP_POWER_OFF_AF_FZ_DELAY); firmware_touch_ctrl_regulator(POWER_OFF); mdelay(CHIP_POWER_OFF_AF_FZ_DELAY); firmware_touch_ctrl_regulator(POWER_ON); mdelay(CHIP_ON_AF_FZ_DELAY); printk(KERN_INFO "[zinitix_touch] upgrade finished\n"); kfree(verify_data); return true; fail_upgrade: mdelay(CHIP_POWER_OFF_AF_FZ_DELAY); firmware_touch_ctrl_regulator(POWER_OFF); mdelay(CHIP_POWER_OFF_AF_FZ_DELAY); firmware_touch_ctrl_regulator(POWER_ON); mdelay(CHIP_ON_AF_FZ_DELAY); printk(KERN_INFO "[zinitix_touch] upgrade fail : so retry... (%d)\n", ++retry_cnt); if (retry_cnt <= ZINITIX_INIT_RETRY_CNT) goto retry_isp_firmware_upgrade; if (verify_data != NULL) kfree(verify_data); printk(KERN_INFO "[zinitix_touch] upgrade fail..\n"); return false; } static bool ts_init_touch(struct zinitix_touch_dev *touch_dev) { u16 reg_val; int i; int j, k=0; u16 SetMaxX = SYSTEM_MAX_X_RESOLUTION; u16 SetMaxY = SYSTEM_MAX_Y_RESOLUTION; u16 Setvaule = SYSTEM_VALUE; u16 chip_revision; u16 chip_firmware_version; u16 chip_reg_data_version; u16 chip_eeprom_info; u16 irq_check; #if USE_CHECKSUM u16 chip_check_reg0, chip_check_reg1, chip_check_reg2, chip_check_reg3; u8 checksum_err; #endif #if TOUCH_ONESHOT_UPGRADE s16 stmp; #endif int retry_cnt = 0; if (touch_dev == NULL) { printk(KERN_ERR "[zinitix_touch] error touch_dev == null?\r\n"); return false; } retry_init: zinitix_debug_msg("check checksum\r\n"); #if 1//temp #if USE_CHECKSUM checksum_err = 0; for (i = 0; i < ZINITIX_INIT_RETRY_CNT; i++) { if (ts_read_data(touch_dev->client, ZINITIX_CHECK_REG0, (u8 *)&chip_check_reg0, 2) < 0) { touch_delay(50); continue; } if (ts_read_data(touch_dev->client, ZINITIX_CHECK_REG1, (u8 *)&chip_check_reg1, 2) < 0){ touch_delay(50); continue; } if (ts_read_data(touch_dev->client, ZINITIX_CHECK_REG2, (u8 *)&chip_check_reg2, 2) < 0){ touch_delay(50); continue; } if (ts_read_data(touch_dev->client, ZINITIX_CHECK_REG3, (u8 *)&chip_check_reg3, 2) < 0){ touch_delay(50); continue; } if( (chip_check_reg0==chip_check_reg2) && (chip_check_reg1==chip_check_reg3) ) break; else { checksum_err = 1; break; } } if (i == ZINITIX_INIT_RETRY_CNT || checksum_err) { printk(KERN_INFO "[zinitix_touch] fail to check firmware data\r\n"); if(checksum_err == 1 && retry_cnt < ZINITIX_INIT_RETRY_CNT) retry_cnt = ZINITIX_INIT_RETRY_CNT; goto fail_init; } #endif if (ts_write_cmd(touch_dev->client, ZINITIX_SWRESET_CMD) != I2C_SUCCESS) { printk(KERN_INFO "[zinitix_touch] fail to write reset command\r\n"); goto fail_init; } #if USING_CHIP_SETTING if (ts_read_data(touch_dev->client, ZINITIX_INT_ENABLE_FLAG, (u8 *)&touch_dev->cap_info.chip_int_mask, 2) < 0) goto fail_init; printk(KERN_INFO "[zinitix_touch] zinitix touch interrupt mask = %04x\r\n", touch_dev->cap_info.chip_int_mask); if (touch_dev->cap_info.chip_int_mask == 0 || touch_dev->cap_info.chip_int_mask == 0xffff) goto fail_init; #else touch_dev->cap_info.button_num = SUPPORTED_BUTTON_NUM; reg_val = 0; zinitix_bit_set(reg_val, BIT_PT_CNT_CHANGE); zinitix_bit_set(reg_val, BIT_DOWN); zinitix_bit_set(reg_val, BIT_MOVE); zinitix_bit_set(reg_val, BIT_UP); if (touch_dev->cap_info.button_num > 0) zinitix_bit_set(reg_val, BIT_ICON_EVENT); touch_dev->cap_info.chip_int_mask = reg_val; #endif if (ts_write_reg(touch_dev->client, ZINITIX_INT_ENABLE_FLAG, 0x0) != I2C_SUCCESS) goto fail_init; zinitix_debug_msg("send reset command\r\n"); if (ts_write_cmd(touch_dev->client, ZINITIX_SWRESET_CMD) != I2C_SUCCESS) goto fail_init; /* get chip revision id */ if (ts_read_data(touch_dev->client, ZINITIX_CHIP_REVISION, (u8 *)&chip_revision, 2) < 0) { printk(KERN_INFO "[zinitix_touch] fail to read chip revision\r\n"); goto fail_init; } printk(KERN_INFO "[zinitix_touch] zinitix touch chip revision id = %x\r\n", chip_revision); touch_dev->cap_info.chip_fw_size = 32*1024; #if USE_TEST_RAW_TH_DATA_MODE if (ts_read_data(touch_dev->client, ZINITIX_TOTAL_NUMBER_OF_X, (u8 *)&touch_dev->cap_info.x_node_num, 2) < 0) goto fail_init; printk(KERN_INFO "[zinitix_touch] zinitix touch chip x node num = %d\r\n", touch_dev->cap_info.x_node_num); if (ts_read_data(touch_dev->client, ZINITIX_TOTAL_NUMBER_OF_Y, (u8 *)&touch_dev->cap_info.y_node_num, 2) < 0) goto fail_init; printk(KERN_INFO "[zinitix_touch] zinitix touch chip y node num = %d\r\n", touch_dev->cap_info.y_node_num); touch_dev->cap_info.total_node_num = touch_dev->cap_info.x_node_num*touch_dev->cap_info.y_node_num; printk(KERN_INFO "[zinitix_touch] zinitix touch chip total node num = %d\r\n", touch_dev->cap_info.total_node_num); if (ts_read_data(touch_dev->client, ZINITIX_MAX_Y_NUM, (u8 *)&touch_dev->cap_info.max_y_node, 2) < 0) goto fail_init; printk(KERN_INFO "[zinitix_touch] zinitix touch chip max y node num = %d\r\n", touch_dev->cap_info.max_y_node); if (ts_read_data(touch_dev->client, ZINITIX_CAL_N_TOTAL_NUM, (u8 *)&touch_dev->cap_info.total_cal_n, 2) < 0) goto fail_init; printk(KERN_INFO "[zinitix_touch] zinitix touch chip total cal n data num = %d\r\n", touch_dev->cap_info.total_cal_n); #endif /* get chip firmware version */ if (ts_read_data(touch_dev->client, ZINITIX_FIRMWARE_VERSION, (u8 *)&chip_firmware_version, 2) < 0) goto fail_init; printk(KERN_INFO "[zinitix_touch] zinitix touch chip firmware version = %x\r\n", chip_firmware_version); #endif//temp //ts_upgrade_firmware(touch_dev, &m_firmware_data[2], // touch_dev->cap_info.chip_fw_size); #if TOUCH_ONESHOT_UPGRADE chip_reg_data_version = 0xffff; if (ts_read_data(touch_dev->client, ZINITIX_DATA_VERSION_REG, (u8 *)&chip_reg_data_version, 2) < 0) goto fail_init; zinitix_debug_msg("touch reg data version = %d\r\n", chip_reg_data_version); if (ts_check_need_upgrade(chip_firmware_version, chip_reg_data_version) == true) { printk(KERN_INFO "[zinitix_touch] start upgrade firmware\n"); ts_upgrade_firmware(touch_dev, &m_firmware_data[2], touch_dev->cap_info.chip_fw_size); /* get chip revision id */ if (ts_read_data(touch_dev->client, ZINITIX_CHIP_REVISION, (u8 *)&chip_revision, 2) < 0) { printk(KERN_INFO "[zinitix_touch] fail to read chip revision\r\n"); goto fail_init; } printk(KERN_INFO "[zinitix_touch] zinitix touch chip revision id = %x\r\n", chip_revision); /* get chip firmware version */ if (ts_read_data(touch_dev->client, ZINITIX_FIRMWARE_VERSION, (u8 *)&chip_firmware_version, 2) < 0) goto fail_init; printk(KERN_INFO "[zinitix_touch] zinitix touch chip renewed firmware version = %x\r\n", chip_firmware_version); } #endif if (ts_read_data(touch_dev->client, ZINITIX_DATA_VERSION_REG, (u8 *)&chip_reg_data_version, 2) < 0) goto fail_init; zinitix_debug_msg("touch reg data version = %d\r\n", chip_reg_data_version); #if TOUCH_ONESHOT_UPGRADE if (chip_reg_data_version < m_reg_data[ZINITIX_DATA_VERSION_REG].reg_val) { zinitix_debug_msg("write new reg data( %d < %d)\r\n", chip_reg_data_version, m_reg_data[ZINITIX_DATA_VERSION_REG].reg_val); for (i = 0; i < MAX_REG_COUNT; i++) { if (m_reg_data[i].valid == 1) { if (ts_write_reg(touch_dev->client, (u16)i, (u16)(m_reg_data[i].reg_val)) != I2C_SUCCESS) goto fail_init; if (i == ZINITIX_TOTAL_NUMBER_OF_X || i == ZINITIX_TOTAL_NUMBER_OF_Y) mdelay(50); if (ts_read_data(touch_dev->client, (u16)i, (u8 *)&stmp, 2) < 0) goto fail_init; if (memcmp((char *)&m_reg_data[i].reg_val, (char *)&stmp, 2) < 0) printk(KERN_WARNING "[zinitix_touch] register data is different. (addr = 0x%02X , %d != %d)\r\n", i, m_reg_data[i].reg_val, stmp); } } zinitix_debug_msg("done new reg data( %d < %d)\r\n", chip_reg_data_version, m_reg_data[ZINITIX_DATA_VERSION_REG].reg_val); if (ts_write_cmd(touch_dev->client, ZINITIX_SAVE_STATUS_CMD) != I2C_SUCCESS) goto fail_init; mdelay(1000); /* for fusing eeprom */ } #endif if (ts_read_data(touch_dev->client, ZINITIX_EEPROM_INFO_REG, (u8 *)&chip_eeprom_info, 2) < 0) goto fail_init; zinitix_debug_msg("touch eeprom info = 0x%04X\r\n", chip_eeprom_info); #if USE_HW_CALIBRATION if (zinitix_bit_test(chip_eeprom_info, 0)) { /* hw calibration bit*/ if (touch_dev->cap_info.chip_int_mask != 0) if (ts_write_reg(touch_dev->client, ZINITIX_INT_ENABLE_FLAG, touch_dev->cap_info.chip_int_mask) != I2C_SUCCESS) goto fail_init; /* h/w calibration */ mdelay(100); if (ts_write_reg(touch_dev->client, ZINITIX_TOUCH_MODE, 0x07) != I2C_SUCCESS) goto fail_init; mdelay(250); if (ts_write_cmd(touch_dev->client, ZINITIX_CALIBRATE_CMD) != I2C_SUCCESS) goto fail_init; if (ts_write_cmd(touch_dev->client, ZINITIX_SWRESET_CMD) != I2C_SUCCESS) goto fail_init; mdelay(10); /* wait for h/w calibration*/ do { ts_write_cmd(touch_dev->client, ZINITIX_CLEAR_INT_STATUS_CMD); touch_delay(1000); if (ts_read_data(touch_dev->client, ZINITIX_EEPROM_INFO_REG, (u8 *)&chip_eeprom_info, 2) < 0) goto fail_init; zinitix_debug_msg("touch eeprom info = 0x%04X\r\n", chip_eeprom_info); if (!zinitix_bit_test(chip_eeprom_info, 0)) break; } while (1); if (ts_write_reg(touch_dev->client, ZINITIX_TOUCH_MODE, TOUCH_MODE) != I2C_SUCCESS) goto fail_init; touch_delay(10); if (ts_write_cmd(touch_dev->client, ZINITIX_SWRESET_CMD) != I2C_SUCCESS) goto fail_init; touch_delay(10); if (ts_write_cmd(touch_dev->client, ZINITIX_SAVE_CALIBRATION_CMD) != I2C_SUCCESS) goto fail_init; touch_delay(500); /* disable chip interrupt */ if (ts_write_reg(touch_dev->client, ZINITIX_INT_ENABLE_FLAG, 0) != I2C_SUCCESS) goto fail_init; } #endif touch_dev->cap_info.chip_revision = (u16)chip_revision; touch_dev->cap_info.chip_firmware_version = (u16)chip_firmware_version; touch_dev->cap_info.chip_reg_data_version = (u16)chip_reg_data_version; /* initialize */ if (ts_write_reg(touch_dev->client, ZINITIX_X_RESOLUTION, (u16)(SetMaxX)) != I2C_SUCCESS) goto fail_init; if (ts_write_reg(touch_dev->client, ZINITIX_Y_RESOLUTION, (u16)(SetMaxY)) != I2C_SUCCESS) goto fail_init; if (ts_write_reg(touch_dev->client, 0x00CB, (u16)(Setvaule)) != I2C_SUCCESS) goto fail_init; if (ts_read_data(touch_dev->client, ZINITIX_X_RESOLUTION, (u8 *)&touch_dev->cap_info.x_resolution, 2) < 0) goto fail_init; zinitix_debug_msg("touch max x = %d\r\n", touch_dev->cap_info.x_resolution); if (ts_read_data(touch_dev->client, ZINITIX_Y_RESOLUTION, (u8 *)&touch_dev->cap_info.y_resolution, 2) < 0) goto fail_init; zinitix_debug_msg("touch max y = %d\r\n", touch_dev->cap_info.y_resolution); touch_dev->cap_info.MinX = (u32)0; touch_dev->cap_info.MinY = (u32)0; touch_dev->cap_info.MaxX = (u32)touch_dev->cap_info.x_resolution; touch_dev->cap_info.MaxY = (u32)touch_dev->cap_info.y_resolution; #if USING_CHIP_SETTING if (ts_read_data(touch_dev->client, ZINITIX_BUTTON_SUPPORTED_NUM, (u8 *)&touch_dev->cap_info.button_num, 2) < 0) goto fail_init; zinitix_debug_msg("supported button num = %d\r\n", touch_dev->cap_info.button_num); if (ts_read_data(touch_dev->client, ZINITIX_SUPPORTED_FINGER_NUM, (u8 *)&touch_dev->cap_info.multi_fingers, 2) < 0) goto fail_init; zinitix_debug_msg("supported finger num = %d\r\n", touch_dev->cap_info.multi_fingers); #else if (ts_write_reg(touch_dev->client, ZINITIX_BUTTON_SUPPORTED_NUM, (u16)touch_dev->cap_info.button_num) != I2C_SUCCESS) goto fail_init; if (ts_write_reg(touch_dev->client, ZINITIX_SUPPORTED_FINGER_NUM, (u16)MAX_SUPPORTED_FINGER_NUM) != I2C_SUCCESS) goto fail_init; touch_dev->cap_info.multi_fingers = REAL_SUPPORTED_FINGER_NUM; #endif zinitix_debug_msg("max supported finger num = %d, \ real supported finger num = %d\r\n", touch_dev->cap_info.multi_fingers, REAL_SUPPORTED_FINGER_NUM); touch_dev->cap_info.gesture_support = 0; zinitix_debug_msg("set other configuration\r\n"); #if USE_TEST_RAW_TH_DATA_MODE if (touch_dev->raw_mode_flag != TOUCH_NORMAL_MODE) { /* Test Mode */ if (ts_write_reg(touch_dev->client, ZINITIX_TOUCH_MODE, touch_dev->raw_mode_flag) != I2C_SUCCESS) goto fail_init; } else #endif { reg_val = TOUCH_MODE; if (ts_write_reg(touch_dev->client, ZINITIX_TOUCH_MODE, reg_val) != I2C_SUCCESS) goto fail_init; } /* soft calibration */ if (ts_write_cmd(touch_dev->client, ZINITIX_CALIBRATE_CMD) != I2C_SUCCESS) goto fail_init; if (ts_write_reg(touch_dev->client, ZINITIX_INT_ENABLE_FLAG, touch_dev->cap_info.chip_int_mask) != I2C_SUCCESS) goto fail_init; /* read garbage data */ for (i = 0; i < 10; i++) { ts_write_cmd(touch_dev->client, ZINITIX_CLEAR_INT_STATUS_CMD); udelay(10); } #if USE_TEST_RAW_TH_DATA_MODE if (touch_dev->raw_mode_flag != TOUCH_NORMAL_MODE) { /* Test Mode */ if (ts_write_reg(touch_dev->client, ZINITIX_PERIODICAL_INTERRUPT_INTERVAL, ZINITIX_SCAN_RATE_HZ *ZINITIX_RAW_DATA_ESD_TIMER_INTERVAL) != I2C_SUCCESS) printk(KERN_INFO "[zinitix_touch] Fail to set ZINITIX_RAW_DATA_ESD_TIMER_INTERVAL.\r\n"); } else #endif { if (ZINITIX_ESD_TIMER_INTERVAL) { if (ts_write_reg(touch_dev->client, ZINITIX_PERIODICAL_INTERRUPT_INTERVAL, ZINITIX_SCAN_RATE_HZ *ZINITIX_ESD_TIMER_INTERVAL) != I2C_SUCCESS) goto fail_init; if (ts_read_data(touch_dev->client, ZINITIX_PERIODICAL_INTERRUPT_INTERVAL, (u8 *)®_val, 2) < 0) goto fail_init; zinitix_debug_msg("esd timer register = %d\r\n", reg_val); } } if (!ts_read_data(touch_dev->client, ZINITIX_INT_ENABLE_FLAG, (u8 *)&irq_check, 2) ) { if(irq_check==0) { if (ts_write_reg(touch_dev->client, ZINITIX_INT_ENABLE_FLAG, touch_dev->cap_info.chip_int_mask) != I2C_SUCCESS) goto fail_init; } } zinitix_debug_msg("successfully initialized\r\n"); return true; fail_init: if (++retry_cnt <= ZINITIX_INIT_RETRY_CNT) { firmware_touch_ctrl_regulator(POWER_OFF); touch_delay(CHIP_POWER_OFF_DELAY); firmware_touch_ctrl_regulator(POWER_ON); touch_delay(CHIP_ON_DELAY); zinitix_debug_msg("retry to initiallize(retry cnt = %d)\r\n", retry_cnt); goto retry_init; } else if(retry_cnt == ZINITIX_INIT_RETRY_CNT+1){ touch_dev->cap_info.chip_fw_size = 32*1024; zinitix_debug_msg("retry to initiallize(retry cnt = %d)\r\n", retry_cnt); #if 1//TOUCH_FORCE_UPGRADE zinitix_debug_msg("TOUCH_FORCE_UPGRADE+++\r\n"); if( ts_upgrade_firmware(touch_dev, &m_firmware_data[2], touch_dev->cap_info.chip_fw_size) == false) { printk(KERN_INFO "[zinitix_touch] Upgrade Fail\n"); return false; } zinitix_debug_msg("TOUCH_FORCE_UPGRADE---\r\n"); touch_delay(100); // hw calibration and make checksum if (ts_write_reg(touch_dev->client, ZINITIX_TOUCH_MODE, 0x07) != I2C_SUCCESS) goto fail_hwcal_init; touch_delay(250); if (ts_write_cmd(touch_dev->client, ZINITIX_CALIBRATE_CMD) != I2C_SUCCESS) goto fail_hwcal_init; if (ts_write_cmd(touch_dev->client, ZINITIX_SWRESET_CMD) != I2C_SUCCESS) goto fail_hwcal_init; touch_delay(10); /* wait for h/w calibration*/ do { ts_write_cmd(touch_dev->client, ZINITIX_CLEAR_INT_STATUS_CMD); touch_delay(1000); if (ts_read_data(touch_dev->client, ZINITIX_EEPROM_INFO_REG, (u8 *)&chip_eeprom_info, 2) < 0) goto fail_hwcal_init; zinitix_debug_msg("touch eeprom info = 0x%04X\r\n", chip_eeprom_info); if (!zinitix_bit_test(chip_eeprom_info, 0)) break; } while (1); if (ts_write_reg(touch_dev->client, ZINITIX_TOUCH_MODE, TOUCH_MODE) != I2C_SUCCESS) goto fail_hwcal_init; touch_delay(10); if (ts_write_cmd(touch_dev->client, ZINITIX_SWRESET_CMD) != I2C_SUCCESS) goto fail_hwcal_init; touch_delay(10); if (ts_write_cmd(touch_dev->client, ZINITIX_SAVE_CALIBRATION_CMD) != I2C_SUCCESS) goto fail_hwcal_init; touch_delay(1000); //for fuzing fail_hwcal_init: // to read new information goto retry_init; #endif } printk("[zinitix touch] failed to initiallize\r\n"); return false; } static void zinitix_clear_report_data(struct zinitix_touch_dev *touch_dev) { int i; u8 reported = 0; u8 sub_status; for (i = 0; i < touch_dev->cap_info.multi_fingers; i++) { sub_status = touch_dev->reported_touch_info.coord[i].sub_status; if (zinitix_bit_test(sub_status, SUB_BIT_EXIST)) { #ifdef ABS_MT_TRACKING_ID input_report_abs(touch_dev->input_dev, ABS_MT_TRACKING_ID, i); #endif input_report_abs(touch_dev->input_dev, ABS_MT_TOUCH_MAJOR, 0); input_report_abs(touch_dev->input_dev, ABS_MT_WIDTH_MAJOR, 0); input_report_abs(touch_dev->input_dev, ABS_MT_POSITION_X, touch_dev->reported_touch_info.coord[i].x); input_report_abs(touch_dev->input_dev, ABS_MT_POSITION_Y, touch_dev->reported_touch_info.coord[i].y); input_mt_sync(touch_dev->input_dev); reported = 1; } touch_dev->reported_touch_info.coord[i].sub_status = 0; } if (reported) { input_report_key(touch_dev->input_dev, BTN_TOUCH, 0); /* ice cream */ input_sync(touch_dev->input_dev); } } static irqreturn_t zinitix_touch_work(int irq, void *data) { struct zinitix_touch_dev* touch_dev = (struct zinitix_touch_dev*)data; int i; u8 reported = false; u8 sub_status; u32 x, y; u32 w; u32 tmp; zinitix_debug_msg("zinitix_touch_thread : semaphore signalled\r\n"); if (touch_dev->use_esd_timer) { ts_esd_timer_stop(touch_dev); zinitix_debug_msg("esd timer stop\r\n"); } down(&touch_dev->work_proceedure_lock); if (touch_dev->work_proceedure != TS_NO_WORK) { zinitix_debug_msg("zinitix_touch_thread : \ [warning] other process occupied..\r\n"); udelay(DELAY_FOR_SIGNAL_DELAY); if (!gpio_get_value(touch_dev->int_gpio_num)) { ts_write_cmd(touch_dev->client, ZINITIX_CLEAR_INT_STATUS_CMD); udelay(DELAY_FOR_SIGNAL_DELAY); } goto continue_read_samples; } touch_dev->work_proceedure = TS_NORMAL_WORK; if (ts_read_coord(touch_dev) == false) { zinitix_debug_msg("couldn't read touch_dev sample\r\n"); goto continue_read_samples; } #if USE_TEST_RAW_TH_DATA_MODE if (touch_dev->raw_mode_flag == TOUCH_TEST_RAW_MODE) goto continue_read_samples; #endif /* invalid : maybe periodical repeated int. */ if (touch_dev->touch_info.status == 0x0) { //printk("status = %X TSP Period INT\r\n", touch_dev->touch_info.status);//temp goto continue_read_samples; } reported = false; if (zinitix_bit_test(touch_dev->touch_info.status, BIT_ICON_EVENT)) { for (i = 0; i < touch_dev->cap_info.button_num; i++) { if (zinitix_bit_test(touch_dev->icon_event_reg, (BIT_O_ICON0_DOWN+i))) { touch_dev->button[i] = ICON_BUTTON_DOWN; input_report_key(touch_dev->input_dev, BUTTON_MAPPING_KEY[i], 1); reported = true; zinitix_debug_msg("button down = %d \r\n", i); //printk("status = %X button down = %d \r\n", touch_dev->touch_info.status, i);//temp } } for (i = 0; i < touch_dev->cap_info.button_num; i++) { if (zinitix_bit_test(touch_dev->icon_event_reg, (BIT_O_ICON0_UP+i))) { touch_dev->button[i] = ICON_BUTTON_UP; input_report_key(touch_dev->input_dev, BUTTON_MAPPING_KEY[i], 0); reported = true; zinitix_debug_msg("button up = %d \r\n", i); //printk("status = %X button up = %d \r\n", touch_dev->touch_info.status, i);//temp } } } /* if button press or up event occured... */ if (reported == true) { for (i = 0; i < touch_dev->cap_info.multi_fingers; i++) { sub_status = touch_dev->reported_touch_info.coord[i].sub_status; x = touch_dev->reported_touch_info.coord[i].x; y = touch_dev->reported_touch_info.coord[i].y; if (zinitix_bit_test(sub_status, SUB_BIT_EXIST)) { zinitix_debug_msg("finger [%02d] up \r\n", i); //printk("status = %X finger [%02d] up \r\n", touch_dev->touch_info.status, i);//temp #ifdef ABS_MT_TRACKING_ID input_report_abs(touch_dev->input_dev, ABS_MT_TRACKING_ID,i); #endif input_report_abs(touch_dev->input_dev, ABS_MT_TOUCH_MAJOR, 0); input_report_abs(touch_dev->input_dev, ABS_MT_WIDTH_MAJOR, 0); input_report_abs(touch_dev->input_dev, ABS_MT_POSITION_X, x); input_report_abs(touch_dev->input_dev, ABS_MT_POSITION_Y, y); input_mt_sync(touch_dev->input_dev); } } memset(&touch_dev->reported_touch_info, 0x0, sizeof(struct _ts_zinitix_point_info)); input_report_key(touch_dev->input_dev, BTN_TOUCH, 0); /* ice cream */ input_sync(touch_dev->input_dev); udelay(100); goto continue_read_samples; } if (touch_dev->touch_info.finger_cnt > MAX_SUPPORTED_FINGER_NUM) touch_dev->touch_info.finger_cnt = MAX_SUPPORTED_FINGER_NUM; if (!zinitix_bit_test(touch_dev->touch_info.status, BIT_PT_EXIST)) { for (i = 0; i < touch_dev->cap_info.multi_fingers; i++) { sub_status = touch_dev->reported_touch_info.coord[i].sub_status; x = touch_dev->reported_touch_info.coord[i].x; y = touch_dev->reported_touch_info.coord[i].y; if (zinitix_bit_test(sub_status, SUB_BIT_EXIST)) { zinitix_debug_msg("finger [%02d] up \r\n", i); //printk("status = %X finger [%02d] up \r\n", touch_dev->touch_info.status, i);//temp #ifdef ABS_MT_TRACKING_ID input_report_abs(touch_dev->input_dev, ABS_MT_TRACKING_ID,i); #endif input_report_abs(touch_dev->input_dev, ABS_MT_TOUCH_MAJOR, 0); input_report_abs(touch_dev->input_dev, ABS_MT_WIDTH_MAJOR, 0); input_report_abs(touch_dev->input_dev, ABS_MT_POSITION_X, x); input_report_abs(touch_dev->input_dev, ABS_MT_POSITION_Y, y); input_mt_sync(touch_dev->input_dev); } } memset(&touch_dev->reported_touch_info, 0x0, sizeof(struct _ts_zinitix_point_info)); input_report_key(touch_dev->input_dev, BTN_TOUCH, 0); /* ice cream */ input_sync(touch_dev->input_dev); goto continue_read_samples; } for (i = 0; i < touch_dev->cap_info.multi_fingers; i++) { sub_status = touch_dev->touch_info.coord[i].sub_status; if (zinitix_bit_test(sub_status, SUB_BIT_DOWN) || zinitix_bit_test(sub_status, SUB_BIT_MOVE) || zinitix_bit_test(sub_status, SUB_BIT_EXIST)) { ; } else if (zinitix_bit_test(sub_status, SUB_BIT_UP)) { zinitix_debug_msg("finger [%02d] up \r\n", i); x = touch_dev->reported_touch_info.coord[i].x; y = touch_dev->reported_touch_info.coord[i].y; memset(&touch_dev->touch_info.coord[i], 0x0, sizeof(struct _ts_zinitix_coord)); #ifdef ABS_MT_TRACKING_ID input_report_abs(touch_dev->input_dev, ABS_MT_TRACKING_ID,i); #endif input_report_abs(touch_dev->input_dev, ABS_MT_TOUCH_MAJOR, 0); input_report_abs(touch_dev->input_dev, ABS_MT_WIDTH_MAJOR, 0); input_report_abs(touch_dev->input_dev, ABS_MT_POSITION_X, x); input_report_abs(touch_dev->input_dev, ABS_MT_POSITION_Y, y); input_mt_sync(touch_dev->input_dev); } } for (i = 0; i < touch_dev->cap_info.multi_fingers; i++) { sub_status = touch_dev->touch_info.coord[i].sub_status; if (zinitix_bit_test(sub_status, SUB_BIT_DOWN) || zinitix_bit_test(sub_status, SUB_BIT_MOVE) || zinitix_bit_test(sub_status, SUB_BIT_EXIST)) { x = touch_dev->touch_info.coord[i].x; y = touch_dev->touch_info.coord[i].y; w = touch_dev->touch_info.coord[i].width; /* transformation from touch to screen orientation */ if (touch_dev->cap_info.Orientation & TOUCH_V_FLIP) y = touch_dev->cap_info.MaxY + touch_dev->cap_info.MinY - y; if (touch_dev->cap_info.Orientation & TOUCH_H_FLIP) x = touch_dev->cap_info.MaxX + touch_dev->cap_info.MinX - x; if (touch_dev->cap_info.Orientation & TOUCH_XY_SWAP) zinitix_swap_v(x, y, tmp); touch_dev->touch_info.coord[i].x = x; touch_dev->touch_info.coord[i].y = y; zinitix_debug_msg("finger [%02d] x = %d, y = %d \r\n", i, x, y); if (w == 0) w = 5; #ifdef ABS_MT_TRACKING_ID input_report_abs(touch_dev->input_dev, ABS_MT_TRACKING_ID,i); #endif input_report_abs(touch_dev->input_dev, ABS_MT_TOUCH_MAJOR, (u32)w); input_report_abs(touch_dev->input_dev, ABS_MT_WIDTH_MAJOR, (u32)w); input_report_abs(touch_dev->input_dev, ABS_MT_POSITION_X, x); input_report_abs(touch_dev->input_dev, ABS_MT_POSITION_Y, y); input_mt_sync(touch_dev->input_dev); } else if (zinitix_bit_test(sub_status, SUB_BIT_UP)) { ; } else memset(&touch_dev->touch_info.coord[i], 0x0, sizeof(struct _ts_zinitix_coord)); } memcpy((char *)&touch_dev->reported_touch_info, (char *)&touch_dev->touch_info, sizeof(struct _ts_zinitix_point_info)); input_report_key(touch_dev->input_dev, BTN_TOUCH, 1); /* ice cream */ input_sync(touch_dev->input_dev); continue_read_samples: /* check_interrupt_pin, if high, enable int & wait signal */ if (touch_dev->work_proceedure == TS_NORMAL_WORK) { if (touch_dev->use_esd_timer) { ts_esd_timer_start(ZINITIX_CHECK_ESD_TIMER, touch_dev); zinitix_debug_msg("esd tmr start\n"); } touch_dev->work_proceedure = TS_NO_WORK; } up(&touch_dev->work_proceedure_lock); return IRQ_HANDLED; } #ifdef CONFIG_HAS_EARLYSUSPEND static void zinitix_late_resume(struct early_suspend *h) { struct zinitix_touch_dev *touch_dev; touch_dev = container_of(h, struct zinitix_touch_dev, early_suspend); printk(KERN_INFO "[zinitix_touch] resume++\r\n"); if (touch_dev == NULL) return; down(&touch_dev->work_proceedure_lock); if (touch_dev->work_proceedure != TS_IN_RESUME && touch_dev->work_proceedure != TS_IN_EALRY_SUSPEND) { printk(KERN_INFO"[zinitix_touch] zinitix_late_resume : invalid work proceedure (%d)\r\n", touch_dev->work_proceedure); up(&touch_dev->work_proceedure_lock); return; } //board_sysconfig(SYSCFG_TOUCH, SYSCFG_INIT); gpio_direction_input(TSP_INT); touch_ctrl_regulator(TOUCH_ON); ts_write_cmd(touch_dev->client, ZINITIX_WAKEUP_CMD); mdelay(150); if (ts_mini_init_touch(touch_dev) == false) goto fail_resume; enable_irq(touch_dev->irq); touch_dev->work_proceedure = TS_NO_WORK; up(&touch_dev->work_proceedure_lock); printk(KERN_INFO "[zinitix_touch] resume--\n"); return; fail_resume: printk(KERN_ERR "[zinitix_touch] failed to resume\n"); enable_irq(touch_dev->irq); touch_dev->work_proceedure = TS_NO_WORK; up(&touch_dev->work_proceedure_lock); return; } static void zinitix_early_suspend(struct early_suspend *h) { struct zinitix_touch_dev *touch_dev = container_of(h, struct zinitix_touch_dev, early_suspend); if (touch_dev == NULL) return; printk(KERN_INFO "[zinitix_touch] early suspend++\n"); flush_work(&touch_dev->tmr_work); flush_work(&touch_dev->work); down(&touch_dev->work_proceedure_lock); if (touch_dev->work_proceedure != TS_NO_WORK) { printk(KERN_INFO"[zinitix_touch] zinitix_early_suspend : invalid work proceedure (%d)\r\n", touch_dev->work_proceedure); up(&touch_dev->work_proceedure_lock); return; } touch_dev->work_proceedure = TS_IN_EALRY_SUSPEND; zinitix_debug_msg("clear all reported points\r\n"); zinitix_clear_report_data(touch_dev); if (touch_dev->use_esd_timer) { ts_write_reg(touch_dev->client, ZINITIX_PERIODICAL_INTERRUPT_INTERVAL, 0); ts_esd_timer_stop(touch_dev); printk(KERN_INFO "[zinitix_touch] ts_esd_timer_stop\n"); } disable_irq(touch_dev->irq); #if !(USING_CHIP_SETTING) ts_write_reg(touch_dev->client, ZINITIX_INT_ENABLE_FLAG, 0x0); #endif udelay(100); ts_write_cmd(touch_dev->client, ZINITIX_CLEAR_INT_STATUS_CMD); #if 0 if (ts_write_cmd(touch_dev->client, ZINITIX_SLEEP_CMD) != I2C_SUCCESS) { printk(KERN_ERR "failed to enter into sleep mode\n"); up(&touch_dev->work_proceedure_lock); return; } #endif gpio_direction_output( TSP_INT , 0 ); #if 0 gpio_direction_output( TSP_SCL , 0 ); gpio_direction_output( TSP_SDA , 0 ); #endif msleep(20); touch_ctrl_regulator(TOUCH_OFF); up(&touch_dev->work_proceedure_lock); printk(KERN_INFO "[zinitix_touch] early suspend--\n"); return; } #endif /* CONFIG_HAS_EARLYSUSPEND */ #if USE_TEST_RAW_TH_DATA_MODE static ssize_t zinitix_get_test_raw_data(struct device *dev, struct device_attribute *attr, char *buf) { int total_n_num; if (misc_touch_dev == NULL) { zinitix_debug_msg("device NULL : NULL\n"); return 0; } down(&misc_touch_dev->raw_data_lock); total_n_num = misc_touch_dev->cap_info.total_node_num; if (zinitix_bit_test( misc_touch_dev->cur_data[total_n_num], BIT_PT_EXIST)) { /*x_lsb*/ buf[20] = (misc_touch_dev->cur_data[total_n_num+1]&0xff); /*x_msb*/ buf[21] = ((misc_touch_dev->cur_data[total_n_num+1]>>8)&0xff); /*y_lsb*/ buf[22] = (misc_touch_dev->cur_data[total_n_num+2]&0xff); /*y_msb*/ buf[23] = ((misc_touch_dev->cur_data[total_n_num+2] >>8)&0xff); } else { buf[20] = 0; /*x_lsb*/ buf[21] = 0; /*x_msb*/ buf[22] = 0; /*y_lsb*/ buf[23] = 0; /*y_msb*/ } /*lsb*/ buf[0] = (char)(misc_touch_dev->ref_data[22]&0xff); /*msb*/ buf[1] = (char)((misc_touch_dev->ref_data[22]>>8)&0xff); /*delta lsb*/ buf[2] = (char)(((s16)(misc_touch_dev->cur_data[22] - misc_touch_dev->ref_data[22]))&0xff); /*delta msb*/ buf[3] = (char)((((s16)(misc_touch_dev->cur_data[22] - misc_touch_dev->ref_data[22]))>>8)&0xff); /* buf[4] = (char)(misc_touch_dev->ref_data[51]&0xff); buf[5] = (char)((misc_touch_dev->ref_data[51]>>8)&0xff); buf[6] = (char)(((s16)(misc_touch_dev->cur_data[51] -misc_touch_dev->ref_data[51]))&0xff); buf[7] = (char)((((s16)(misc_touch_dev->cur_data[51] -misc_touch_dev->ref_data[51]))>>8)&0xff); buf[8] = (char)(misc_touch_dev->ref_data[102]&0xff); buf[9] = (char)((misc_touch_dev->ref_data[102]>>8)&0xff); buf[10] = (char)(((s16)(misc_touch_dev->cur_data[102] -misc_touch_dev->ref_data[102]))&0xff); buf[11] = (char)((((s16)(misc_touch_dev->cur_data[102] -misc_touch_dev->ref_data[102]))>>8)&0xff); buf[12] = (char)(misc_touch_dev->ref_data[169]&0xff); buf[13] = (char)((misc_touch_dev->ref_data[169]>>8)&0xff); buf[14] = (char)(((s16)(misc_touch_dev->cur_data[169] -misc_touch_dev->ref_data[169]))&0xff); buf[15] = (char)((((s16)(misc_touch_dev->cur_data[169] -misc_touch_dev->ref_data[169]))>>8)&0xff); buf[16] = (char)(misc_touch_dev->ref_data[178]&0xff); buf[17] = (char)((misc_touch_dev->ref_data[178]>>8)&0xff); buf[18] = (char)(((s16)(misc_touch_dev->cur_data[178] -misc_touch_dev->ref_data[178]))&0xff); buf[19] = (char)((((s16)(misc_touch_dev->cur_data[178] - misc_touch_dev->ref_data[178]))>>8)&0xff); */ up(&misc_touch_dev->raw_data_lock); return 24; } ssize_t zinitix_set_testmode(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { unsigned char value = 0; printk(KERN_INFO "[zinitix_touch] zinitix_set_testmode, buf = %d\r\n", *buf); if (misc_touch_dev == NULL) { zinitix_debug_msg("device NULL : NULL\n"); return 0; } sscanf(buf, "%c", &value); if (value != TOUCH_TEST_RAW_MODE && value != TOUCH_NORMAL_MODE) { printk(KERN_WARNING "[zinitix_touch] test mode setting value error. you must set %d[=normal] or %d[=raw mode]\r\n", TOUCH_NORMAL_MODE, TOUCH_TEST_RAW_MODE); return 1; } down(&misc_touch_dev->raw_data_lock); misc_touch_dev->raw_mode_flag = value; printk(KERN_INFO "[zinitix_touch] zinitix_set_testmode, touchkey_testmode = %d\r\n", misc_touch_dev->raw_mode_flag); if (misc_touch_dev->raw_mode_flag == TOUCH_NORMAL_MODE) { /* enter into normal mode */ printk(KERN_INFO "[zinitix_touch] TEST Mode Exit\r\n"); if (ts_write_reg(misc_touch_dev->client, ZINITIX_PERIODICAL_INTERRUPT_INTERVAL, ZINITIX_SCAN_RATE_HZ *ZINITIX_ESD_TIMER_INTERVAL) != I2C_SUCCESS) printk(KERN_INFO "[zinitix_touch] Fail to set ZINITIX_PERIODICAL_INTERRUPT_INTERVAL.\r\n"); if (ts_write_reg(misc_touch_dev->client, ZINITIX_TOUCH_MODE, TOUCH_MODE) != I2C_SUCCESS) printk(KERN_INFO "[zinitix_touch] Fail to set touch mode %d.\r\n", TOUCH_MODE); /* clear garbage data */ ts_write_cmd(misc_touch_dev->client, ZINITIX_CLEAR_INT_STATUS_CMD); touch_delay(100); ts_write_cmd(misc_touch_dev->client, ZINITIX_CLEAR_INT_STATUS_CMD); } else { /* enter into test mode */ printk(KERN_INFO "[zinitix_touch] TEST Mode Enter\r\n"); if (ts_write_reg(misc_touch_dev->client, ZINITIX_PERIODICAL_INTERRUPT_INTERVAL, ZINITIX_SCAN_RATE_HZ *ZINITIX_RAW_DATA_ESD_TIMER_INTERVAL) != I2C_SUCCESS) printk(KERN_INFO "[zinitix_touch] Fail to set ZINITIX_RAW_DATA_ESD_TIMER_INTERVAL.\r\n"); if (ts_write_reg(misc_touch_dev->client, ZINITIX_TOUCH_MODE, TOUCH_TEST_RAW_MODE) != I2C_SUCCESS) printk(KERN_INFO "[zinitix_touch] Fail to set touch mode %d.\r\n", TOUCH_TEST_RAW_MODE); ts_write_cmd(misc_touch_dev->client, ZINITIX_CLEAR_INT_STATUS_CMD); /* clear garbage data */ touch_delay(100); ts_write_cmd(misc_touch_dev->client, ZINITIX_CLEAR_INT_STATUS_CMD); memset(&misc_touch_dev->reported_touch_info, 0x0, sizeof(struct _ts_zinitix_point_info)); memset(&misc_touch_dev->touch_info, 0x0, sizeof(struct _ts_zinitix_point_info)); } up(&misc_touch_dev->raw_data_lock); return 1; } static DEVICE_ATTR(get_touch_raw_data, S_IRUGO | S_IWUSR | S_IWOTH | S_IXOTH, zinitix_get_test_raw_data, zinitix_set_testmode); static int ts_misc_fops_open(struct inode *inode, struct file *filp) { return 0; } static int ts_misc_fops_close(struct inode *inode, struct file *filp) { return 0; } #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) static int ts_misc_fops_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) #else static long ts_misc_fops_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) #endif { void __user *argp = (void __user *)arg; struct _raw_ioctl raw_ioctl; u8 *u8Data; int i, j; int ret = 0; size_t sz = 0; u16 version; u8 div_node; int total_cal_n; u16 mode; u16 chip_eeprom_info; struct _reg_ioctl reg_ioctl; u16 val; int nval = 0; if (misc_touch_dev == NULL) return -1; /* zinitix_debug_msg("cmd = %d, argp = 0x%x\n", cmd, (int)argp); */ switch (cmd) { case TOUCH_IOCTL_GET_DEBUGMSG_STATE: ret = m_ts_debug_mode; if (copy_to_user(argp, &ret, sizeof(ret))) return -1; break; case TOUCH_IOCTL_SET_DEBUGMSG_STATE: if (copy_from_user(&nval, argp, 4)) { printk(KERN_INFO "[zinitix_touch] error : copy_from_user\n"); return -1; } if (nval) printk(KERN_INFO "[zinitix_touch] on debug mode (%d)\n", nval); else printk(KERN_INFO "[zinitix_touch] off debug mode (%d)\n", nval); m_ts_debug_mode = nval; break; case TOUCH_IOCTL_GET_CHIP_REVISION: ret = misc_touch_dev->cap_info.chip_revision; if (copy_to_user(argp, &ret, sizeof(ret))) return -1; break; case TOUCH_IOCTL_GET_FW_VERSION: ret = misc_touch_dev->cap_info.chip_firmware_version; if (copy_to_user(argp, &ret, sizeof(ret))) return -1; break; case TOUCH_IOCTL_GET_REG_DATA_VERSION: ret = misc_touch_dev->cap_info.chip_reg_data_version; if (copy_to_user(argp, &ret, sizeof(ret))) return -1; break; case TOUCH_IOCTL_VARIFY_UPGRADE_SIZE: if (copy_from_user(&sz, argp, sizeof(size_t))) return -1; printk(KERN_INFO "[zinitix_touch] firmware size = %d\r\n", sz); if (misc_touch_dev->cap_info.chip_fw_size != sz) { printk(KERN_INFO "[zinitix_touch] firmware size error\r\n"); return -1; } break; case TOUCH_IOCTL_VARIFY_UPGRADE_DATA: if (copy_from_user(&m_firmware_data[2], argp, misc_touch_dev->cap_info.chip_fw_size)) return -1; version = (u16)(((u16)m_firmware_data[FIRMWARE_VERSION_POS+1]<<8) |(u16)m_firmware_data[FIRMWARE_VERSION_POS]); printk(KERN_INFO "[zinitix_touch] firmware version = %x\r\n", version); if (copy_to_user(argp, &version, sizeof(version))) return -1; break; case TOUCH_IOCTL_START_UPGRADE: disable_irq(misc_touch_dev->irq); down(&misc_touch_dev->work_proceedure_lock); misc_touch_dev->work_proceedure = TS_IN_UPGRADE; if (misc_touch_dev->use_esd_timer) ts_esd_timer_stop(misc_touch_dev); zinitix_debug_msg("clear all reported points\r\n"); zinitix_clear_report_data(misc_touch_dev); printk(KERN_INFO "[zinitix_touch] start upgrade firmware\n"); if (ts_upgrade_firmware(misc_touch_dev, &m_firmware_data[2], misc_touch_dev->cap_info.chip_fw_size) == false) { enable_irq(misc_touch_dev->irq); misc_touch_dev->work_proceedure = TS_NO_WORK; up(&misc_touch_dev->work_proceedure_lock); return -1; } if (ts_init_touch(misc_touch_dev) == false) { enable_irq(misc_touch_dev->irq); misc_touch_dev->work_proceedure = TS_NO_WORK; up(&misc_touch_dev->work_proceedure_lock); return -1; } if (misc_touch_dev->use_esd_timer) { ts_esd_timer_start(ZINITIX_CHECK_ESD_TIMER, misc_touch_dev); zinitix_debug_msg("esd timer start\r\n"); } enable_irq(misc_touch_dev->irq); misc_touch_dev->work_proceedure = TS_NO_WORK; up(&misc_touch_dev->work_proceedure_lock); break; case TOUCH_IOCTL_GET_X_RESOLUTION: ret = misc_touch_dev->cap_info.x_resolution; if (copy_to_user(argp, &ret, sizeof(ret))) return -1; break; case TOUCH_IOCTL_GET_Y_RESOLUTION: ret = misc_touch_dev->cap_info.y_resolution; if (copy_to_user(argp, &ret, sizeof(ret))) return -1; break; case TOUCH_IOCTL_GET_X_NODE_NUM: ret = misc_touch_dev->cap_info.x_node_num; if (copy_to_user(argp, &ret, sizeof(ret))) return -1; break; case TOUCH_IOCTL_GET_Y_NODE_NUM: ret = misc_touch_dev->cap_info.y_node_num; if (copy_to_user(argp, &ret, sizeof(ret))) return -1; break; case TOUCH_IOCTL_GET_TOTAL_NODE_NUM: ret = misc_touch_dev->cap_info.total_node_num; if (copy_to_user(argp, &ret, sizeof(ret))) return -1; break; case TOUCH_IOCTL_HW_CALIBRAION: ret = -1; disable_irq(misc_touch_dev->irq); down(&misc_touch_dev->work_proceedure_lock); if (misc_touch_dev->work_proceedure != TS_NO_WORK) { printk(KERN_INFO"[zinitix_touch] other process occupied.. (%d)\r\n", misc_touch_dev->work_proceedure); up(&misc_touch_dev->work_proceedure_lock); return -1; } misc_touch_dev->work_proceedure = TS_HW_CALIBRAION; touch_delay(100); /* h/w calibration */ if (ts_write_reg(misc_touch_dev->client, ZINITIX_TOUCH_MODE, 0x07) != I2C_SUCCESS) goto fail_hw_cal; touch_delay(250); if (ts_write_cmd(misc_touch_dev->client, ZINITIX_CALIBRATE_CMD) != I2C_SUCCESS) goto fail_hw_cal; if (ts_write_cmd(misc_touch_dev->client, ZINITIX_SWRESET_CMD) != I2C_SUCCESS) goto fail_hw_cal; touch_delay(10); ts_write_cmd(misc_touch_dev->client, ZINITIX_CLEAR_INT_STATUS_CMD); /* wait for h/w calibration */ do { touch_delay(1000); if (ts_read_data(misc_touch_dev->client, ZINITIX_EEPROM_INFO_REG, (u8 *)&chip_eeprom_info, 2) < 0) goto fail_hw_cal; zinitix_debug_msg("touch eeprom info = 0x%04X\r\n", chip_eeprom_info); if (!zinitix_bit_test(chip_eeprom_info, 0)) break; } while (1); touch_delay(10); if (ts_write_cmd(misc_touch_dev->client, ZINITIX_SAVE_CALIBRATION_CMD) != I2C_SUCCESS) goto fail_hw_cal; touch_delay(500); ret = 0; fail_hw_cal: if (misc_touch_dev->raw_mode_flag == TOUCH_NORMAL_MODE) mode = TOUCH_MODE; else mode = misc_touch_dev->raw_mode_flag; if (ts_write_reg(misc_touch_dev->client, ZINITIX_TOUCH_MODE, mode) != I2C_SUCCESS) { printk(KERN_INFO "[zinitix_touch] fail to set touch mode %d.\n", mode); goto fail_hw_cal2; } if (ts_write_cmd(misc_touch_dev->client, ZINITIX_SWRESET_CMD) != I2C_SUCCESS) goto fail_hw_cal2; enable_irq(misc_touch_dev->irq); misc_touch_dev->work_proceedure = TS_NO_WORK; up(&misc_touch_dev->work_proceedure_lock); return ret; fail_hw_cal2: enable_irq(misc_touch_dev->irq); misc_touch_dev->work_proceedure = TS_NO_WORK; up(&misc_touch_dev->work_proceedure_lock); return -1; case TOUCH_IOCTL_SET_RAW_DATA_MODE: if (misc_touch_dev == NULL) { zinitix_debug_msg("misc device NULL?\n"); return -1; } down(&misc_touch_dev->work_proceedure_lock); if (misc_touch_dev->work_proceedure != TS_NO_WORK) { printk(KERN_INFO"[zinitix_touch] other process occupied.. (%d)\r\n", misc_touch_dev->work_proceedure); up(&misc_touch_dev->work_proceedure_lock); return -1; } misc_touch_dev->work_proceedure = TS_SET_MODE; if (copy_from_user(&nval, argp, 4)) { printk(KERN_INFO "[zinitix_touch] error : copy_from_user\r\n"); misc_touch_dev->work_proceedure = TS_NO_WORK; return -1; } zinitix_debug_msg("[zinitix_touch] touchkey_testmode = %d\r\n", misc_touch_dev->raw_mode_flag); if (nval == TOUCH_NORMAL_MODE && misc_touch_dev->raw_mode_flag != TOUCH_NORMAL_MODE) { /* enter into normal mode */ misc_touch_dev->raw_mode_flag = nval; printk(KERN_INFO "[zinitix_touch] raw data mode exit\r\n"); if (ts_write_reg(misc_touch_dev->client, ZINITIX_PERIODICAL_INTERRUPT_INTERVAL, ZINITIX_SCAN_RATE_HZ*ZINITIX_ESD_TIMER_INTERVAL) != I2C_SUCCESS) printk(KERN_INFO "[zinitix_touch] Fail to set ZINITIX_PERIODICAL_INTERRUPT_INTERVAL.\n"); if (ts_write_reg(misc_touch_dev->client, ZINITIX_TOUCH_MODE, TOUCH_MODE) != I2C_SUCCESS) printk(KERN_INFO "[zinitix_touch] fail to set TOUCH_MODE.\r\n"); /* clear garbage data */ ts_write_cmd(misc_touch_dev->client, ZINITIX_CLEAR_INT_STATUS_CMD); touch_delay(100); ts_write_cmd(misc_touch_dev->client, ZINITIX_CLEAR_INT_STATUS_CMD); } else if (nval != TOUCH_NORMAL_MODE) { /* enter into test mode*/ misc_touch_dev->raw_mode_flag = nval; printk(KERN_INFO "[zinitix_touch] raw data mode enter\r\n"); if (ts_write_reg(misc_touch_dev->client, ZINITIX_PERIODICAL_INTERRUPT_INTERVAL, ZINITIX_SCAN_RATE_HZ *ZINITIX_RAW_DATA_ESD_TIMER_INTERVAL) != I2C_SUCCESS) printk(KERN_INFO "[zinitix_touch] Fail to set ZINITIX_RAW_DATA_ESD_TIMER_INTERVAL.\n"); if (ts_write_reg(misc_touch_dev->client, ZINITIX_TOUCH_MODE, misc_touch_dev->raw_mode_flag) != I2C_SUCCESS) printk(KERN_INFO "[zinitix_touch] raw data mode : Fail to set TOUCH_MODE %d.\n", misc_touch_dev->raw_mode_flag); ts_write_cmd(misc_touch_dev->client, ZINITIX_CLEAR_INT_STATUS_CMD); /* clear garbage data */ touch_delay(100); ts_write_cmd(misc_touch_dev->client, ZINITIX_CLEAR_INT_STATUS_CMD); } misc_touch_dev->work_proceedure = TS_NO_WORK; up(&misc_touch_dev->work_proceedure_lock); return 0; case TOUCH_IOCTL_GET_REG: if (misc_touch_dev == NULL) { zinitix_debug_msg("misc device NULL?\n"); return -1; } down(&misc_touch_dev->work_proceedure_lock); if (misc_touch_dev->work_proceedure != TS_NO_WORK) { printk(KERN_INFO "[zinitix_touch] other process occupied.. (%d)\n", misc_touch_dev->work_proceedure); up(&misc_touch_dev->work_proceedure_lock); return -1; } misc_touch_dev->work_proceedure = TS_SET_MODE; if (copy_from_user(®_ioctl, argp, sizeof(struct _reg_ioctl))) { misc_touch_dev->work_proceedure = TS_NO_WORK; up(&misc_touch_dev->work_proceedure_lock); printk(KERN_INFO "[zinitix_touch] error : copy_from_user\n"); return -1; } if (ts_read_data(misc_touch_dev->client, reg_ioctl.addr, (u8 *)&val, 2) < 0) ret = -1; nval = (int)val; if (copy_to_user(reg_ioctl.val, (u8 *)&nval, 4)) { misc_touch_dev->work_proceedure = TS_NO_WORK; up(&misc_touch_dev->work_proceedure_lock); printk(KERN_INFO "[zinitix_touch] error : copy_to_user\n"); return -1; } zinitix_debug_msg("read : reg addr = 0x%x, val = 0x%x\n", reg_ioctl.addr, nval); misc_touch_dev->work_proceedure = TS_NO_WORK; up(&misc_touch_dev->work_proceedure_lock); return ret; case TOUCH_IOCTL_SET_REG: if (misc_touch_dev == NULL) { zinitix_debug_msg("misc device NULL?\n"); return -1; } down(&misc_touch_dev->work_proceedure_lock); if (misc_touch_dev->work_proceedure != TS_NO_WORK) { printk(KERN_INFO "[zinitix_touch] other process occupied.. (%d)\n", misc_touch_dev->work_proceedure); up(&misc_touch_dev->work_proceedure_lock); return -1; } misc_touch_dev->work_proceedure = TS_SET_MODE; if (copy_from_user(®_ioctl, argp, sizeof(struct _reg_ioctl))) { misc_touch_dev->work_proceedure = TS_NO_WORK; up(&misc_touch_dev->work_proceedure_lock); printk(KERN_INFO "[zinitix_touch] error : copy_from_user\n"); return -1; } if (copy_from_user(&val, reg_ioctl.val, 4)) { misc_touch_dev->work_proceedure = TS_NO_WORK; up(&misc_touch_dev->work_proceedure_lock); printk(KERN_INFO "[zinitix_touch] error : copy_from_user\n"); return -1; } if (ts_write_reg(misc_touch_dev->client, reg_ioctl.addr, val) != I2C_SUCCESS) ret = -1; zinitix_debug_msg("write : reg addr = 0x%x, val = 0x%x\r\n", reg_ioctl.addr, val); misc_touch_dev->work_proceedure = TS_NO_WORK; up(&misc_touch_dev->work_proceedure_lock); return ret; case TOUCH_IOCTL_DONOT_TOUCH_EVENT: if (misc_touch_dev == NULL) { zinitix_debug_msg("misc device NULL?\n"); return -1; } down(&misc_touch_dev->work_proceedure_lock); if (misc_touch_dev->work_proceedure != TS_NO_WORK) { printk(KERN_INFO"[zinitix_touch] other process occupied.. (%d)\r\n", misc_touch_dev->work_proceedure); up(&misc_touch_dev->work_proceedure_lock); return -1; } misc_touch_dev->work_proceedure = TS_SET_MODE; if (ts_write_reg(misc_touch_dev->client, ZINITIX_INT_ENABLE_FLAG, 0) != I2C_SUCCESS) ret = -1; zinitix_debug_msg("write : reg addr = 0x%x, val = 0x0\r\n", ZINITIX_INT_ENABLE_FLAG); misc_touch_dev->work_proceedure = TS_NO_WORK; up(&misc_touch_dev->work_proceedure_lock); return ret; case TOUCH_IOCTL_SEND_SAVE_STATUS: if (misc_touch_dev == NULL) { zinitix_debug_msg("misc device NULL?\n"); return -1; } down(&misc_touch_dev->work_proceedure_lock); if (misc_touch_dev->work_proceedure != TS_NO_WORK) { printk(KERN_INFO"[zinitix_touch] other process occupied.. (%d)\r\n", misc_touch_dev->work_proceedure); up(&misc_touch_dev->work_proceedure_lock); return -1; } misc_touch_dev->work_proceedure = TS_SET_MODE; ret = 0; if (ts_write_cmd(misc_touch_dev->client, ZINITIX_SAVE_STATUS_CMD) != I2C_SUCCESS) ret = -1; touch_delay(1000); /* for fusing eeprom */ misc_touch_dev->work_proceedure = TS_NO_WORK; up(&misc_touch_dev->work_proceedure_lock); return ret; case TOUCH_IOCTL_GET_RAW_DATA: if (misc_touch_dev == NULL) { zinitix_debug_msg("misc device NULL?\n"); return -1; } if (misc_touch_dev->raw_mode_flag == TOUCH_NORMAL_MODE) return -1; down(&misc_touch_dev->raw_data_lock); if (misc_touch_dev->update == 0) { up(&misc_touch_dev->raw_data_lock); return -2; } if (copy_from_user(&raw_ioctl, argp, sizeof(raw_ioctl))) { up(&misc_touch_dev->raw_data_lock); printk(KERN_INFO "[zinitix_touch] error : copy_from_user\r\n"); return -1; } misc_touch_dev->update = 0; u8Data = (u8 *)&misc_touch_dev->cur_data[0]; if (misc_touch_dev->raw_mode_flag == TOUCH_ZINITIX_CAL_N_MODE) { j = 0; total_cal_n = misc_touch_dev->cap_info.total_cal_n; if (total_cal_n == 0) total_cal_n = 160; div_node = (u8)misc_touch_dev->cap_info.max_y_node; if (div_node == 0) div_node = 16; u8Data = (u8 *)&misc_touch_dev->cur_data[0]; for (i = 0; i < total_cal_n*2; i++) { if (i%div_node < misc_touch_dev->cap_info.y_node_num) { misc_touch_dev->ref_data[j] = (u16)u8Data[i]; j++; } } u8Data = (u8 *)&misc_touch_dev->ref_data[0]; } if (copy_to_user(raw_ioctl.buf, (u8 *)u8Data, raw_ioctl.sz)) { up(&misc_touch_dev->raw_data_lock); return -1; } up(&misc_touch_dev->raw_data_lock); return 0; default: break; } return 0; } #endif /* USE_TEST_RAW_TH_DATA_MODE */ static int zinitix_regulator(void) { int err; tsp_regulator_18 = regulator_get(NULL, REGU_NAME_TP1); if (IS_ERR(tsp_regulator_18)) { pr_err("zinitix:could not get 1.8v regulator\n"); return -1; } err = regulator_set_voltage(tsp_regulator_18,1800000,1800000); if (err) pr_err("zinitix:could not set to 1800mv.\n"); tsp_regulator_33 = regulator_get(NULL, REGU_NAME_TP); if (IS_ERR(tsp_regulator_33)) { pr_err("zinitix:could not get 3.3v regulator\n"); return -1; } err =regulator_set_voltage(tsp_regulator_33,3000000,3000000); if (err) pr_err("zinitix:could not set to 3300mv.\n"); return 0; } static int zinitix_touch_probe(struct i2c_client *client, const struct i2c_device_id *i2c_id) { int ret = 0; struct zinitix_touch_dev *touch_dev; int i; zinitix_regulator(); zinitix_debug_msg("zinitix_touch_probe+\r\n"); zinitix_debug_msg("Above BT4x3 Driver\r\n"); printk(KERN_INFO "[zinitix touch] driver version = %s\r\n", TS_DRVIER_VERSION); #ifdef ABS_MT_TRACKING_ID printk(KERN_INFO "[zinitix touch] use tracking id\r\n"); #endif if (strcmp(client->name, ZINITIX_ISP_NAME) == 0) { printk(KERN_INFO "[zinitix_touch] isp client probe \r\n"); m_isp_client = client; return 0; } touch_ctrl_regulator(1); mdelay(CHIP_ON_DELAY); mdelay(500); firmware_touch_ctrl_regulator(0); mdelay(1000); firmware_touch_ctrl_regulator(1); mdelay(CHIP_ON_DELAY); mdelay(500); zinitix_debug_msg("i2c check function \r\n"); if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { printk(KERN_ERR "[zinitix_touch] error : not compatible i2c function \r\n"); ret = -ENODEV; goto err_check_functionality; } zinitix_debug_msg("touch data alloc \r\n"); touch_dev = kzalloc(sizeof(struct zinitix_touch_dev), GFP_KERNEL); if (!touch_dev) { printk(KERN_ERR "[zinitix_touch] unabled to allocate touch data \r\n"); ret = -ENOMEM; goto err_alloc_dev_data; } touch_dev->client = client; i2c_set_clientdata(client, touch_dev); g_touch_dev = touch_dev; zinitix_debug_msg("allocate input device \r\n"); touch_dev->input_dev = input_allocate_device(); if (touch_dev->input_dev == 0) { printk(KERN_ERR "[zinitix_touch] unabled to allocate input device \r\n"); ret = -ENOMEM; goto err_input_allocate_device; } /* initialize zinitix touch ic */ gpio_request(GPIO_TOUCH_PIN_NUM,"zinitix_irq" ); touch_dev->int_gpio_num = GPIO_TOUCH_PIN_NUM;//client->irq; /* for upgrade */ memset(&touch_dev->reported_touch_info, 0x0, sizeof(struct _ts_zinitix_point_info)); #if USE_TEST_RAW_TH_DATA_MODE /* not test mode */ touch_dev->raw_mode_flag = TOUCH_NORMAL_MODE; #endif if(ts_init_touch(touch_dev) == false) { goto err_input_register_device; } touch_dev->use_esd_timer = 0; INIT_WORK(&touch_dev->tmr_work, zinitix_touch_tmr_work); zinitix_tmr_workqueue = create_singlethread_workqueue("zinitix_tmr_workqueue"); if (!zinitix_tmr_workqueue) { printk(KERN_ERR "[zinitix_touch] unabled to create touch tmr work queue \r\n"); ret = -1; goto err_kthread_create_failed; } if (ZINITIX_ESD_TIMER_INTERVAL) { touch_dev->use_esd_timer = 1; ts_esd_timer_init(touch_dev); ts_esd_timer_start(ZINITIX_CHECK_ESD_TIMER, touch_dev); printk(KERN_INFO " [zinitix_touch] ts_esd_timer_start\n"); } sprintf(touch_dev->phys, "input(ts)"); touch_dev->input_dev->name = ZINITIX_DRIVER_NAME; touch_dev->input_dev->id.bustype = BUS_I2C; touch_dev->input_dev->id.vendor = 0x0001; touch_dev->input_dev->phys = touch_dev->phys; touch_dev->input_dev->id.product = 0x0002; touch_dev->input_dev->id.version = 0x0100; set_bit(EV_SYN, touch_dev->input_dev->evbit); set_bit(EV_KEY, touch_dev->input_dev->evbit); set_bit(BTN_TOUCH, touch_dev->input_dev->keybit); set_bit(EV_ABS, touch_dev->input_dev->evbit); for (i = 0; i < MAX_SUPPORTED_BUTTON_NUM; i++) set_bit(BUTTON_MAPPING_KEY[i], touch_dev->input_dev->keybit); set_bit(KEY_POWER, touch_dev->input_dev->keybit); if (touch_dev->cap_info.Orientation & TOUCH_XY_SWAP) { input_set_abs_params(touch_dev->input_dev, ABS_MT_POSITION_Y, touch_dev->cap_info.MinX, touch_dev->cap_info.MaxX + ABS_PT_OFFSET, 0, 0); input_set_abs_params(touch_dev->input_dev, ABS_MT_POSITION_X, touch_dev->cap_info.MinY, touch_dev->cap_info.MaxY + ABS_PT_OFFSET, 0, 0); } else { input_set_abs_params(touch_dev->input_dev, ABS_MT_POSITION_X, touch_dev->cap_info.MinX, touch_dev->cap_info.MaxX + ABS_PT_OFFSET, 0, 0); input_set_abs_params(touch_dev->input_dev, ABS_MT_POSITION_Y, touch_dev->cap_info.MinY, touch_dev->cap_info.MaxY + ABS_PT_OFFSET, 0, 0); } input_set_abs_params(touch_dev->input_dev, ABS_TOOL_WIDTH, 0, 255, 0, 0); input_set_abs_params(touch_dev->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); input_set_abs_params(touch_dev->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0); #ifdef ABS_MT_TRACKING_ID input_set_abs_params(touch_dev->input_dev, ABS_MT_TRACKING_ID, 0, touch_dev->cap_info.multi_fingers, 0, 0); #endif zinitix_debug_msg("register %s input device \r\n", touch_dev->input_dev->name); ret = input_register_device(touch_dev->input_dev); if (ret) { printk(KERN_ERR "[zinitix_touch] unable to register %s input device\r\n", touch_dev->input_dev->name); goto err_input_register_device; } /* configure touchscreen interrupt gpio */ touch_dev->int_gpio_num = GPIO_TOUCH_PIN_NUM; #if 0 //GPIO_TOUCH_IRQ touch_dev->irq = GPIO_TOUCH_IRQ; #else printk("First check : touch_dev->irq : %d, touch_dev->client->irq : %d\n",touch_dev->irq,touch_dev->client->irq); touch_dev->irq = gpio_to_irq(GPIO_TOUCH_PIN_NUM); touch_dev->client->irq = touch_dev->irq; printk("touch_dev->irq : %d, touch_dev->client->irq : %d\n",touch_dev->irq,touch_dev->client->irq); if (touch_dev->irq <= 0) printk(KERN_INFO "[zinitix_touch] error. gpio_to_irq(..) function is not \ supported? you should define GPIO_TOUCH_IRQ.\r\n"); #endif zinitix_debug_msg("request irq (irq = %d, pin = %d) \r\n", touch_dev->client->irq, touch_dev->int_gpio_num); touch_dev->work_proceedure = TS_NO_WORK; sema_init(&touch_dev->work_proceedure_lock, 1); if (touch_dev->client->irq) { ret = request_threaded_irq(touch_dev->client->irq, NULL, zinitix_touch_work, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "zinitix_ts", touch_dev); if (ret) { printk(KERN_ERR "[zinitix_touch] [zinitix_touch] unable to register irq.(%s)\r\n", touch_dev->input_dev->name); goto err_request_irq; } } dev_info(&client->dev, "zinitix touch probe.\r\n"); #ifdef CONFIG_HAS_EARLYSUSPEND touch_dev->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; touch_dev->early_suspend.suspend = zinitix_early_suspend; touch_dev->early_suspend.resume = zinitix_late_resume; register_early_suspend(&touch_dev->early_suspend); #endif #if USE_TEST_RAW_TH_DATA_MODE sema_init(&touch_dev->raw_data_lock, 1); misc_touch_dev = touch_dev; ret = misc_register(&touch_misc_device); if (ret) zinitix_debug_msg("Fail to register touch misc device.\n"); if (device_create_file(touch_misc_device.this_device, &dev_attr_get_touch_raw_data) < 0) printk(KERN_INFO "[zinitix_touch] Failed to create device file(%s)!\n", dev_attr_get_touch_raw_data.attr.name); #endif /* sys fs */ touch_class = class_create(THIS_MODULE, "touch"); if (IS_ERR(touch_class)) pr_err("[TSP] Failed to create class(touch)!\n"); firmware_dev = device_create(touch_class, NULL, 0, NULL, "firmware"); if (IS_ERR(firmware_dev)) pr_err("[TSP] 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_ver) < 0) pr_err("[TSP] Failed to create device file(%s)!\n", dev_attr_firmware_ver.attr.name); if (device_create_file(firmware_dev, &dev_attr_firmware_ret) < 0) pr_err("[TSP] Failed to create device file(%s)!\n", dev_attr_firmware_ret.attr.name); if (device_create_file(firmware_dev, &dev_attr_phone_fw_ver) < 0) pr_err("[TSP] Failed to create device file(%s)!\n", dev_attr_phone_fw_ver.attr.name); if (device_create_file(firmware_dev, &dev_attr_part_fw_ver) < 0) pr_err("[TSP] Failed to create device file(%s)!\n", dev_attr_part_fw_ver.attr.name); if (device_create_file(firmware_dev, &dev_attr_threshold_fw_ver) < 0) pr_err("[TSP] Failed to create device file(%s)!\n", dev_attr_threshold_fw_ver.attr.name); if (device_create_file(firmware_dev, &dev_attr_config_fw_ver) < 0) pr_err("[TSP] Failed to create device file(%s)!\n", dev_attr_config_fw_ver.attr.name); if (device_create_file(firmware_dev, &dev_attr_fw_upstatus) < 0) pr_err("[TSP] Failed to create device file(%s)!\n", dev_attr_fw_upstatus.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); 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_ncount_read) < 0) pr_err("Failed to create device file(%s)!\n", dev_attr_ncount_read.attr.name); if (device_create_file(firmware_dev, &dev_attr_touchkey_read) < 0) pr_err("Failed to create device file(%s)!\n", dev_attr_touchkey_read.attr.name); /* sys fs */ return 0; err_request_irq: input_unregister_device(touch_dev->input_dev); err_input_register_device: input_free_device(touch_dev->input_dev); err_kthread_create_failed: err_input_allocate_device: kfree(touch_dev); err_alloc_dev_data: err_check_functionality: return ret; } static int zinitix_touch_remove(struct i2c_client *client) { struct zinitix_touch_dev *touch_dev = i2c_get_clientdata(client); zinitix_debug_msg("zinitix_touch_remove+ \r\n"); down(&touch_dev->work_proceedure_lock); if (touch_dev->work_proceedure != TS_NO_WORK) flush_work(&touch_dev->work); touch_dev->work_proceedure = TS_REMOVE_WORK; if (touch_dev->use_esd_timer != 0) { flush_work(&touch_dev->tmr_work); ts_write_reg(touch_dev->client, ZINITIX_PERIODICAL_INTERRUPT_INTERVAL, 0); ts_esd_timer_stop(touch_dev); zinitix_debug_msg(KERN_INFO " ts_esd_timer_stop\n"); destroy_workqueue(zinitix_tmr_workqueue); } if (touch_dev->irq) free_irq(touch_dev->irq, touch_dev); #if USE_TEST_RAW_TH_DATA_MODE device_remove_file(touch_misc_device.this_device, &dev_attr_get_touch_raw_data); misc_deregister(&touch_misc_device); #endif #ifdef CONFIG_HAS_EARLYSUSPEND unregister_early_suspend(&touch_dev->early_suspend); #endif destroy_workqueue(zinitix_workqueue); if (gpio_is_valid(touch_dev->int_gpio_num) != 0) gpio_free(touch_dev->int_gpio_num); input_unregister_device(touch_dev->input_dev); input_free_device(touch_dev->input_dev); up(&touch_dev->work_proceedure_lock); kfree(touch_dev); return 0; } static int __devinit zinitix_touch_init(void) { #if TOUCH_USING_ISP_METHOD m_isp_client = NULL; #endif printk("[zinitix_touch] zinitix_touch_init ! \n"); // touch_regulator_2_9 = regulator_get(NULL,"touch_vcc_2.9v"); // touch_regulator_3_3 = regulator_get(NULL,"touch_vcc_3.3v"); //board_sysconfig(SYSCFG_TOUCH, SYSCFG_INIT); m_isp_client = NULL; return i2c_add_driver(&zinitix_touch_driver); } static void __exit zinitix_touch_exit(void) { i2c_del_driver(&zinitix_touch_driver); } static ssize_t phone_firmware_show(struct device *dev, struct device_attribute *attr, char *buf) { zinitix_debug_msg("[TSP] %s\n",__func__); int HW_ver; int phone_ver; int ic_ver; HW_ver = g_touch_dev->cap_info.chip_revision; ic_ver = g_touch_dev->cap_info.chip_reg_data_version; phone_ver = (u16) (m_firmware_data[FIRMWARE_VERSION_POS+2] | (m_firmware_data[FIRMWARE_VERSION_POS+3]<<8)); sprintf(buf, "%02x\n", phone_ver); return sprintf(buf, "%s", buf ); } static ssize_t firmware_show(struct device *dev, struct device_attribute *attr, char *buf) { u16 phone_version; u16 hw_version; u16 chip_revision; printk("[zinitix_touch] %s\n",__func__); /* get chip firmware version */ //phone_version = g_touch_dev->cap_info.chip_firmware_version; /* get chip revision id */ if (ts_read_data(g_touch_dev->client, ZINITIX_CHIP_REVISION, (u8 *)&chip_revision, 2) < 0) { printk(KERN_INFO "[zinitix_touch] fail to read chip revision\r\n"); } printk(KERN_INFO "[zinitix_touch] zinitix touch chip revision id = %x\r\n", chip_revision); if (ts_read_data(g_touch_dev->client, ZINITIX_DATA_VERSION_REG, (u8*)&phone_version, 2)<0){ printk(KERN_INFO "[zinitix_touch] fail to read chip revision\r\n"); } printk(KERN_INFO "[zinitix_touch] zinitix touch chip firmware version = %x\r\n", phone_version); if (ts_read_data(g_touch_dev->client, ZINITIX_TSP_TYPE, (u8*)&hw_version, 2)<0){ printk(KERN_INFO "[zinitix_touch] fail to read chip revision\r\n"); } printk(KERN_INFO "[zinitix_touch] zinitix touch chip firmware version = %x\r\n", hw_version); sprintf(buf, "10%x0%x0%x\n", hw_version, phone_version, PHONE_FW_VER); printk("[zinitix_touch] %s\n", buf); return sprintf(buf, "%s", buf); } static ssize_t part_firmware_show(struct device *dev, struct device_attribute *attr, char *buf) { zinitix_debug_msg("[zinitix_touch] %s\n",__func__); int HW_ver; int phone_ver; int ic_ver; HW_ver = g_touch_dev->cap_info.chip_revision; ic_ver = g_touch_dev->cap_info.chip_reg_data_version; phone_ver = (u16) (m_firmware_data[FIRMWARE_VERSION_POS+2] | (m_firmware_data[FIRMWARE_VERSION_POS+3]<<8)); sprintf(buf, "%02x\n",ic_ver); return sprintf(buf, "%s", buf ); } static ssize_t threshold_firmware_show(struct device *dev, struct device_attribute *attr, char *buf) { zinitix_debug_msg("[zinitix_touch] %s\n",__func__); int HW_ver; int phone_ver; int ic_ver; HW_ver = g_touch_dev->cap_info.chip_revision; ic_ver = g_touch_dev->cap_info.chip_reg_data_version; phone_ver = (u16) (m_firmware_data[FIRMWARE_VERSION_POS+2] | (m_firmware_data[FIRMWARE_VERSION_POS+3]<<8)); sprintf(buf, "%02x\n", 0x300); printk("[zinitix_touch] threshold_firmware_show : %02x\n", 0x300); return sprintf(buf, "%s", buf ); } static ssize_t config_firmware_show(struct device *dev, struct device_attribute *attr, char *buf) { zinitix_debug_msg("[zinitix_touch] %s\n",__func__); int HW_ver; int phone_ver; int ic_ver; HW_ver = g_touch_dev->cap_info.chip_revision; ic_ver = g_touch_dev->cap_info.chip_reg_data_version; phone_ver = (u16) (m_firmware_data[FIRMWARE_VERSION_POS+2] | (m_firmware_data[FIRMWARE_VERSION_POS+3]<<8)); //zinitix_debug_msg("chip_revision : %d, HW_ver = %d\n", g_touch_dev->cap_info.chip_revision, HW_ver); // 0xb , 11 //zinitix_debug_msg("chip_firmware_version : %d, phone_ver = %d\n", g_touch_dev->cap_info.chip_firmware_version, phone_ver); //0x102, 258 //zinitix_debug_msg("phone(m_firmware_data[0]) = %d\n", m_firmware_data[0]); // sprintf(buf, "0%d\n", (HW_ver*100000) + (phone_ver*1000)+(ic_ver*10)); sprintf(buf, "%02x\n", HW_ver); return sprintf(buf, "%s", buf ); } static ssize_t firmware_ret_show(struct device *dev, struct device_attribute *attr, char *buf) { int i; u16 chip_eeprom_info; printk("[zinitix_touch] %s\n",__func__); sprintf(IsfwUpdate,"%s\n",FW_DOWNLOADING); disable_irq(g_touch_dev->irq); down(&g_touch_dev->work_proceedure_lock); g_touch_dev->work_proceedure = TS_IN_UPGRADE; #if ZINITIX_ESD_TIMER_INTERVAL if(g_touch_dev->use_esd_timer) { ts_esd_timer_stop(g_touch_dev); } #endif zinitix_debug_msg("clear all reported points\r\n"); zinitix_clear_report_data(g_touch_dev); g_touch_dev->cap_info.chip_fw_size = 32*1024; for(i=0; i < 5; i++) { zinitix_debug_msg("[zinitix touch] manual upgrade count = %d\r\n", i); if( ts_upgrade_firmware(g_touch_dev, &m_firmware_data[2], g_touch_dev->cap_info.chip_fw_size) == true) break; } if(i >= 5) { zinitix_debug_msg("[zinitix touch] failed to manual upgrade\r\n"); return sprintf(buf, "%d", -1 ); //return sprintf(buf, "%s", "fail!!\n" ); } else { // hw calibration and make checksum zinitix_debug_msg("HW calibration 1 !!! \r\n"); if (ts_write_reg(g_touch_dev->client, ZINITIX_TOUCH_MODE, 0x07) != I2C_SUCCESS) goto fail_hwcal_init; zinitix_debug_msg("HW calibration 2 !!! \r\n"); if (ts_write_cmd(g_touch_dev->client, ZINITIX_CALIBRATE_CMD) != I2C_SUCCESS) goto fail_hwcal_init; zinitix_debug_msg("HW calibration 3 !!! \r\n"); if (ts_write_cmd(g_touch_dev->client, ZINITIX_SWRESET_CMD) != I2C_SUCCESS) goto fail_hwcal_init; mdelay(100); ts_write_cmd(g_touch_dev->client, ZINITIX_CLEAR_INT_STATUS_CMD); mdelay(100); ts_write_cmd(g_touch_dev->client, ZINITIX_CLEAR_INT_STATUS_CMD); mdelay(100); ts_write_cmd(g_touch_dev->client, ZINITIX_CLEAR_INT_STATUS_CMD); mdelay(100); /* wait for h/w calibration*/ do { mdelay(1000); if (ts_read_data(g_touch_dev->client, ZINITIX_EEPROM_INFO_REG, (u8 *)&chip_eeprom_info, 2) < 0) goto fail_hwcal_init; zinitix_debug_msg("touch eeprom info = 0x%04X\r\n", chip_eeprom_info); if (!zinitix_bit_test(chip_eeprom_info, 0)) break; } while (1); zinitix_debug_msg("HW calibration 4 !!! \r\n"); if (ts_write_reg(g_touch_dev->client, ZINITIX_TOUCH_MODE, TOUCH_MODE) != I2C_SUCCESS) goto fail_hwcal_init; mdelay(10); zinitix_debug_msg("HW calibration 5 !!! \r\n"); if (ts_write_cmd(g_touch_dev->client, ZINITIX_SWRESET_CMD) != I2C_SUCCESS) goto fail_hwcal_init; mdelay(10); zinitix_debug_msg("HW calibration 6 !!! \r\n"); if (ts_write_cmd(g_touch_dev->client, ZINITIX_SAVE_CALIBRATION_CMD) != I2C_SUCCESS) goto fail_hwcal_init; mdelay(1000); } if(ts_init_touch(g_touch_dev)==false) { enable_irq(g_touch_dev->irq); g_touch_dev->work_proceedure = TS_NO_WORK; up(&g_touch_dev->work_proceedure_lock); zinitix_debug_msg("\n[TSP] fail firmware_update\n"); return sprintf(buf, "%d", -1 ); //return sprintf(buf, "%s", "fail!!\n" ); } enable_irq(g_touch_dev->irq); g_touch_dev->work_proceedure = TS_NO_WORK; up(&g_touch_dev->work_proceedure_lock); sprintf(IsfwUpdate,"%s\n",FW_DOWNLOAD_COMPLETE); zinitix_debug_msg("\n[TSP] success firmware_update\n"); return sprintf(buf, "%d", 1 ); //return sprintf(buf, "%s", "success!!\n" ); fail_hwcal_init: #if ZINITIX_ESD_TIMER_INTERVAL if(g_touch_dev->use_esd_timer) { ts_esd_timer_start(ZINITIX_CHECK_ESD_TIMER, g_touch_dev); zinitix_debug_msg("esd timer start\r\n"); } #endif enable_irq(g_touch_dev->irq); g_touch_dev->work_proceedure = TS_NO_WORK; up(&g_touch_dev->work_proceedure_lock); sprintf(IsfwUpdate,"%s\n",FW_DOWNLOAD_FAIL); zinitix_debug_msg("\n[TSP] fail firmware_update\n"); return sprintf(buf, "%d", -1 ); //return sprintf(buf, "%s", "fail!!\n" ); } static ssize_t firmware_update_status(struct device *dev, struct device_attribute *attr, char *buf) { zinitix_debug_msg("[zinitix_touch] %s\n",__func__); return sprintf(buf, "%s\n", IsfwUpdate); } static int16_t zinitix_raw_data[X_RAW_DATA][Y_RAW_DATA] = {0}; static int8_t zinitix_ncount_data[X_RAW_DATA][Y_RAW_DATA] = {0}; static ssize_t zinitix_enter_testmode(struct device *dev, struct device_attribute *attr, char *buf) { printk(KERN_INFO "[zinitix_touch] %s 111 name : %s\r\n", __FUNCTION__, misc_touch_dev->client->name); if(misc_touch_dev == NULL) { zinitix_debug_msg("device NULL : NULL\n"); return snprintf(buf, 2, "-1"); } down(&misc_touch_dev->raw_data_lock); misc_touch_dev->raw_mode_flag = TOUCH_TEST_RAW_MODE; if (ts_write_reg(misc_touch_dev->client, ZINITIX_PERIODICAL_INTERRUPT_INTERVAL, ZINITIX_SCAN_RATE_HZ*ZINITIX_RAW_DATA_ESD_TIMER_INTERVAL)!=I2C_SUCCESS) printk(KERN_INFO "[zinitix_touch] Fail to set ZINITIX_RAW_DATA_ESD_TIMER_INTERVAL.\r\n"); if (ts_write_reg(misc_touch_dev->client, ZINITIX_TOUCH_MODE, TOUCH_TEST_RAW_MODE)!=I2C_SUCCESS) { printk(KERN_INFO "[zinitix_touch] TEST Mode : Fail to set ZINITX_TOUCH_MODE %d.\r\n", TOUCH_TEST_RAW_MODE); } ts_write_cmd(misc_touch_dev->client, ZINITIX_CLEAR_INT_STATUS_CMD); // clear garbage data mdelay(100); ts_write_cmd(misc_touch_dev->client, ZINITIX_CLEAR_INT_STATUS_CMD); memset(&misc_touch_dev->reported_touch_info, 0x0, sizeof(struct _ts_zinitix_point_info)); memset(&misc_touch_dev->touch_info, 0x0, sizeof(struct _ts_zinitix_point_info)); up(&misc_touch_dev->raw_data_lock); return 1; } static ssize_t zinitix_enter_normalmode(struct device *dev, struct device_attribute *attr, char *buf) { printk(KERN_INFO "[zinitix_touch] %s\r\n", __FUNCTION__); if(misc_touch_dev == NULL) { zinitix_debug_msg("device NULL : NULL\n"); return 0; } down(&misc_touch_dev->raw_data_lock); misc_touch_dev->raw_mode_flag = TOUCH_NORMAL_MODE; printk(KERN_INFO "[zinitix_touch] TEST Mode Exit\r\n"); if (ts_write_reg(misc_touch_dev->client, ZINITIX_PERIODICAL_INTERRUPT_INTERVAL, ZINITIX_SCAN_RATE_HZ*ZINITIX_ESD_TIMER_INTERVAL)!=I2C_SUCCESS) printk(KERN_INFO "[zinitix_touch] Fail to set ZINITIX_PERIODICAL_INTERRUPT_INTERVAL.\r\n"); if (ts_write_reg(misc_touch_dev->client, ZINITIX_TOUCH_MODE, TOUCH_MODE)!=I2C_SUCCESS) { printk(KERN_INFO "[zinitix_touch] Fail to set ZINITX_TOUCH_MODE %d.\r\n", TOUCH_MODE); } // clear garbage data ts_write_cmd(misc_touch_dev->client, ZINITIX_CLEAR_INT_STATUS_CMD); mdelay(100); ts_write_cmd(misc_touch_dev->client, ZINITIX_CLEAR_INT_STATUS_CMD); up(&misc_touch_dev->raw_data_lock); return 1; } static ssize_t rawdata_pass_fail_zinitix(struct device *dev, struct device_attribute *attr, char *buf) { int time_out = 0; int i,j; int interrup_detecting; int written_bytes = 0; /* error check */ int phone_ver; int ic_ver; int16_t raw_data[X_RAW_DATA][Y_RAW_DATA] = {{0,},}; // 2 byte printk(KERN_INFO "[zinitix_touch] zinitix_read_raw_data( )\r\n"); disable_irq(misc_touch_dev->client->irq); if (ts_write_reg(misc_touch_dev->client, ZINITIX_TOUCH_MODE, 7) != I2C_SUCCESS) { printk(KERN_INFO "[zinitix_touch] ZINITIX_TOUCH_MODE fail\r\n"); goto fail_read_raw; } udelay(10); for (i = 0; i < INT_WAIT_TIME; i++) { ts_write_cmd(misc_touch_dev->client, ZINITIX_CLEAR_INT_STATUS_CMD); time_out = 0; interrup_detecting = 1; while (gpio_get_value(misc_touch_dev->int_gpio_num)) { msleep(1); if (time_out++ > 20) { printk(KERN_INFO "[zinitix_touch] interrupt disable timed out\r\n"); interrup_detecting = 0; break; } } if (i == INT_WAIT_TIME) { printk(KERN_INFO "[zinitix_touch] interrupt disable timed out\r\n"); goto fail_read_raw; } if ((interrup_detecting == 1) && (time_out < 20)) { if (ts_read_raw_data(misc_touch_dev->client, ZINITIX_RAWDATA_REG, (char *)raw_data, MAX_TEST_RAW_DATA*2) < 0) { printk(KERN_INFO "[zinitix_touch] ZINITIX_RAWDATA_REG fail\r\n"); goto fail_read_raw; } memcpy(zinitix_raw_data, raw_data, MAX_TEST_RAW_DATA*2); #ifdef ZINITIX_N_TEST for (j = 0; j < (MAX_TEST_RAW_DATA*2); j++) { printk(KERN_INFO "[zinitix_touch] temp_buff[%d]" "= %5d\r\n", j, zinitix_raw_data[j]); } #endif break; } } ts_write_cmd(misc_touch_dev->client, ZINITIX_CLEAR_INT_STATUS_CMD); udelay(10); if (ts_write_reg(misc_touch_dev->client, ZINITIX_TOUCH_MODE, TOUCH_MODE) != I2C_SUCCESS) { printk(KERN_INFO "[zinitix_touch] ZINITIX_TOUCH_MODE fail\r\n"); goto fail_read_raw; } ts_write_cmd(misc_touch_dev->client, ZINITIX_CLEAR_INT_STATUS_CMD); udelay(10); enable_irq(misc_touch_dev->client->irq); for (i = 0; i < misc_touch_dev->cap_info.x_node_num; i++) { printk(KERN_CONT "[zinitix_touch] "); for (j = 0; j < misc_touch_dev->cap_info.y_node_num; j++) printk(KERN_CONT " %5d", raw_data[i][j]); printk(KERN_CONT "\n"); } // TSP ndata for (i = 0; i < misc_touch_dev->cap_info.x_node_num-1; i++) { for (j = 0; j < misc_touch_dev->cap_info.y_node_num; j++) { if (raw_data[i][j] < CAL_MIN_NUM) { printk("[zinitix1] : returned by -> raw_data[%d][%d] %5d \n", i, j, raw_data[i][j]); return snprintf(buf, 2, "0"); // fail } if (raw_data[i][j] > CAL_MAX_NUM) { printk("[zinitix2] : returned by -> raw_data[%d][%d] %5d \n", i, j, raw_data[i][j]); return snprintf(buf, 2, "0"); // fail } } } // TOUCH KEY ndata for (j = 0; j < misc_touch_dev->cap_info.y_node_num; j++) { if ((j == 1) || (j == 8)) { if (raw_data[misc_touch_dev->cap_info.x_node_num-1][j] < CAL_MIN_NUM) { printk("[zinitix3] : returned by -> raw_data[%d][%d] %5d \n", misc_touch_dev->cap_info.x_node_num-1, j, raw_data[misc_touch_dev->cap_info.x_node_num-1][j]); return snprintf(buf, 2, "0"); // fail } if (raw_data[misc_touch_dev->cap_info.x_node_num-1][j] > CAL_MAX_NUM) { printk("[zinitix4] : returned by -> raw_data[%d][%d] %5d \n", misc_touch_dev->cap_info.x_node_num-1, j, raw_data[misc_touch_dev->cap_info.x_node_num-1][j]); return snprintf(buf, 2, "0"); // fail } } } ic_ver = g_touch_dev->cap_info.chip_reg_data_version; phone_ver = (u16) (m_firmware_data[FIRMWARE_VERSION_POS+2] | (m_firmware_data[FIRMWARE_VERSION_POS+3]<<8)); zinitix_debug_msg("phone_ver = %d, ic_ver = %d\n",phone_ver,ic_ver); if(phone_ver != ic_ver) return snprintf(buf, 2, "0"); // fail return snprintf(buf, 2, "1"); // success for (i = 0; i < misc_touch_dev->cap_info.x_node_num; i++) { for (j = 0; j < misc_touch_dev->cap_info.y_node_num; j++) { written_bytes += sprintf(buf+written_bytes, "%d,",raw_data[i][j]); } } printk("[zinitix_touch] written_bytes = %d \n",written_bytes); if(written_bytes > 0) return written_bytes; fail_read_raw: if (ts_write_reg(misc_touch_dev->client, ZINITIX_TOUCH_MODE, TOUCH_MODE) != I2C_SUCCESS) { printk(KERN_INFO "[zinitix_touch] ZINITIX_TOUCH_MODE fail\r\n"); goto fail_read_raw; } ts_write_cmd(misc_touch_dev->client, ZINITIX_CLEAR_INT_STATUS_CMD); udelay(10); enable_irq(misc_touch_dev->client->irq); return snprintf(buf, 2, "-1"); } static ssize_t scantime_zinitix(struct device *dev, struct device_attribute *attr, char *buf) { int i, j; int written_bytes = 0; /* error check */ u8 raw_data[20][16] = {{0,},}; u8 scantime_data[X_RAW_DATA][Y_RAW_DATA] = {{0,},}; printk(KERN_INFO "[zinitix_touch] scantime_zinitix( )\r\n"); disable_irq(misc_touch_dev->client->irq); if (ts_write_reg(misc_touch_dev->client, ZINITIX_TOUCH_MODE, 8) != I2C_SUCCESS) { printk(KERN_INFO "[zinitix_touch] ZINITIX_TOUCH_MODE fail\r\n"); goto fail_read_raw; } msleep(100); ts_write_cmd(misc_touch_dev->client, ZINITIX_CLEAR_INT_STATUS_CMD); if (ts_read_raw_data(misc_touch_dev->client, ZINITIX_RAWDATA_REG, (char *)raw_data, 320) < 0) { printk(KERN_INFO "error : read zinitix tc Cal N raw data\n"); goto fail_read_raw; } msleep(10); ts_write_cmd(misc_touch_dev->client, ZINITIX_CLEAR_INT_STATUS_CMD); msleep(10); if (ts_write_reg(misc_touch_dev->client, ZINITIX_TOUCH_MODE, TOUCH_MODE) != I2C_SUCCESS) { printk(KERN_INFO "[zinitix_touch] ZINITIX_TOUCH_MODE fail\r\n"); goto fail_read_raw; } ts_write_cmd(misc_touch_dev->client, ZINITIX_CLEAR_INT_STATUS_CMD); msleep(10); enable_irq(misc_touch_dev->client->irq); for (i = 0; i < misc_touch_dev->cap_info.x_node_num; i++) { printk(KERN_CONT "[TSP]"); for (j = 0; j < misc_touch_dev->cap_info.y_node_num; j++) { scantime_data[i][j] = raw_data[i][j]; printk(KERN_CONT " %d", scantime_data[i][j]); } printk(KERN_CONT "\n"); } for (i = 0; i < misc_touch_dev->cap_info.x_node_num; i++) { for (j = 0; j < misc_touch_dev->cap_info.y_node_num; j++) { written_bytes += sprintf(buf+written_bytes, ",%5d", raw_data[i][j]) ; } } if (written_bytes > 0) { return written_bytes;} return snprintf(buf, 2, "-1"); fail_read_raw: if (ts_write_reg(misc_touch_dev->client, ZINITIX_TOUCH_MODE, TOUCH_MODE) != I2C_SUCCESS) { printk(KERN_INFO "[zinitix_touch] ZINITIX_TOUCH_MODE fail\r\n"); goto fail_read_raw; } ts_write_cmd(misc_touch_dev->client, ZINITIX_CLEAR_INT_STATUS_CMD); udelay(10); enable_irq(misc_touch_dev->client->irq); return snprintf(buf, 2, "-1"); } static ssize_t read_node(struct device *dev, struct device_attribute *attr, char *buf) { int time_out = 0; int i,j; int interrup_detecting; int written_bytes = 0; /* error check */ int16_t raw_data[X_RAW_DATA][Y_RAW_DATA] = {{0,},}; // 2 byte printk(KERN_INFO "[zinitix_touch] zinitix_read_raw_data( )\r\n"); disable_irq(misc_touch_dev->client->irq); if (ts_write_reg(misc_touch_dev->client, ZINITIX_TOUCH_MODE, 7) != I2C_SUCCESS) { printk(KERN_INFO "[zinitix_touch] ZINITIX_TOUCH_MODE fail\r\n"); goto fail_read_raw; } udelay(10); for (i = 0; i < INT_WAIT_TIME; i++) { ts_write_cmd(misc_touch_dev->client, ZINITIX_CLEAR_INT_STATUS_CMD); time_out = 0; interrup_detecting = 1; while (gpio_get_value(misc_touch_dev->int_gpio_num)) { msleep(1); if (time_out++ > 20) { printk(KERN_INFO "[zinitix_touch] interrupt disable timed out\r\n"); interrup_detecting = 0; break; } } if (i == INT_WAIT_TIME) { printk(KERN_INFO "[zinitix_touch] interrupt disable timed out\r\n"); goto fail_read_raw; } if ((interrup_detecting == 1) && (time_out < 20)) { if (ts_read_raw_data(misc_touch_dev->client, ZINITIX_RAWDATA_REG, (char *)raw_data, MAX_TEST_RAW_DATA*2) < 0) { printk(KERN_INFO "[zinitix_touch] ZINITIX_RAWDATA_REG fail\r\n"); goto fail_read_raw; } memcpy(zinitix_raw_data, raw_data, MAX_TEST_RAW_DATA*2); #ifdef ZINITIX_N_TEST for (j = 0; j < (MAX_TEST_RAW_DATA*2); j++) { printk(KERN_INFO "[zinitix_touch] temp_buff[%d]" "= %5d\r\n", j, zinitix_raw_data[j]); } #endif break; } } ts_write_cmd(misc_touch_dev->client, ZINITIX_CLEAR_INT_STATUS_CMD); udelay(10); if (ts_write_reg(misc_touch_dev->client, ZINITIX_TOUCH_MODE, TOUCH_MODE) != I2C_SUCCESS) { printk(KERN_INFO "[zinitix_touch] ZINITIX_TOUCH_MODE fail\r\n"); goto fail_read_raw; } ts_write_cmd(misc_touch_dev->client, ZINITIX_CLEAR_INT_STATUS_CMD); udelay(10); enable_irq(misc_touch_dev->client->irq); for (i = 0; i < misc_touch_dev->cap_info.x_node_num; i++) { printk(KERN_CONT "[zinitix_touch] "); for (j = 0; j < misc_touch_dev->cap_info.y_node_num; j++) printk(KERN_CONT " %5d", raw_data[i][j]); printk(KERN_CONT "\n"); } for (i = 0; i < misc_touch_dev->cap_info.x_node_num; i++) { for (j = 0; j < misc_touch_dev->cap_info.y_node_num; j++) { written_bytes += sprintf(buf+written_bytes, ",%5d", raw_data[i][j]) ; } } printk("[zinitix_touch] written_bytes = %d \n",written_bytes); if(written_bytes > 0) return written_bytes; fail_read_raw: if (ts_write_reg(misc_touch_dev->client, ZINITIX_TOUCH_MODE, TOUCH_MODE) != I2C_SUCCESS) { printk(KERN_INFO "[zinitix_touch] ZINITIX_TOUCH_MODE fail\r\n"); goto fail_read_raw; } ts_write_cmd(misc_touch_dev->client, ZINITIX_CLEAR_INT_STATUS_CMD); udelay(10); enable_irq(misc_touch_dev->client->irq); return 1; } static ssize_t read_touchkey(struct device *dev, struct device_attribute *attr, char *buf) { int time_out = 0; int i,j; int interrup_detecting; int written_bytes = 0; /* error check */ int16_t raw_data[X_RAW_DATA][Y_RAW_DATA] = {{0,},}; // 2 byte printk(KERN_INFO "[zinitix_touch] zinitix_read_raw_data( )\r\n"); disable_irq(misc_touch_dev->client->irq); if (ts_write_reg(misc_touch_dev->client, ZINITIX_TOUCH_MODE, 7) != I2C_SUCCESS) { printk(KERN_INFO "[zinitix_touch] ZINITIX_TOUCH_MODE fail\r\n"); goto fail_read_raw; } udelay(10); for (i = 0; i < INT_WAIT_TIME; i++) { ts_write_cmd(misc_touch_dev->client, ZINITIX_CLEAR_INT_STATUS_CMD); time_out = 0; interrup_detecting = 1; while (gpio_get_value(misc_touch_dev->int_gpio_num)) { msleep(1); if (time_out++ > 20) { printk(KERN_INFO "[zinitix_touch] interrupt disable timed out\r\n"); interrup_detecting = 0; break; } } if (i == INT_WAIT_TIME) { printk(KERN_INFO "[zinitix_touch] interrupt disable timed out\r\n"); goto fail_read_raw; } if ((interrup_detecting == 1) && (time_out < 20)) { if (ts_read_raw_data(misc_touch_dev->client, ZINITIX_RAWDATA_REG, (char *)raw_data, MAX_TEST_RAW_DATA*2) < 0) { printk(KERN_INFO "[zinitix_touch] ZINITIX_RAWDATA_REG fail\r\n"); goto fail_read_raw; } memcpy(zinitix_raw_data, raw_data, MAX_TEST_RAW_DATA*2); #ifdef ZINITIX_N_TEST for (j = 0; j < (MAX_TEST_RAW_DATA*2); j++) { printk(KERN_INFO "[zinitix_touch] temp_buff[%d]" "= %5d\r\n", j, zinitix_raw_data[j]); } #endif break; } } ts_write_cmd(misc_touch_dev->client, ZINITIX_CLEAR_INT_STATUS_CMD); udelay(10); if (ts_write_reg(misc_touch_dev->client, ZINITIX_TOUCH_MODE, TOUCH_MODE) != I2C_SUCCESS) { printk(KERN_INFO "[zinitix_touch] ZINITIX_TOUCH_MODE fail\r\n"); goto fail_read_raw; } ts_write_cmd(misc_touch_dev->client, ZINITIX_CLEAR_INT_STATUS_CMD); udelay(10); enable_irq(misc_touch_dev->client->irq); // TOUCH KEY ndata for (j = 0; j < misc_touch_dev->cap_info.y_node_num; j++) { if ((j == 1) || (j == 8)) { if (raw_data[misc_touch_dev->cap_info.x_node_num-1][j] < CAL_MIN_NUM) { printk("[zinitix3] : returned by -> raw_data[%d][%d] %5d \n", misc_touch_dev->cap_info.x_node_num-1, j, raw_data[misc_touch_dev->cap_info.x_node_num-1][j]); written_bytes += sprintf(buf+written_bytes, "%5d", raw_data[misc_touch_dev->cap_info.x_node_num-1][j]) ; } else written_bytes += sprintf(buf+written_bytes, "%5d", raw_data[misc_touch_dev->cap_info.x_node_num-1][j]) ; if (raw_data[misc_touch_dev->cap_info.x_node_num-1][j] > CAL_MAX_NUM) { printk("[zinitix4] : returned by -> raw_data[%d][%d] %5d \n", misc_touch_dev->cap_info.x_node_num-1, j, raw_data[misc_touch_dev->cap_info.x_node_num-1][j]); written_bytes += sprintf(buf+written_bytes, "%5d", raw_data[misc_touch_dev->cap_info.x_node_num-1][j]) ; } else written_bytes += sprintf(buf+written_bytes, "%5d", raw_data[misc_touch_dev->cap_info.x_node_num-1][j]) ; } } printk("[zinitix_touch] written_bytes = %d \n",written_bytes); if(written_bytes > 0) return written_bytes; fail_read_raw: if (ts_write_reg(misc_touch_dev->client, ZINITIX_TOUCH_MODE, TOUCH_MODE) != I2C_SUCCESS) { printk(KERN_INFO "[zinitix_touch] ZINITIX_TOUCH_MODE fail\r\n"); goto fail_read_raw; } ts_write_cmd(misc_touch_dev->client, ZINITIX_CLEAR_INT_STATUS_CMD); udelay(10); enable_irq(misc_touch_dev->client->irq); return 1; } module_init(zinitix_touch_init); module_exit(zinitix_touch_exit); MODULE_DESCRIPTION("zinitix touch-screen device driver using i2c interface"); MODULE_AUTHOR("sohnet "); MODULE_LICENSE("GPL");