Hi there :) I replace digitizer in my phone (Huawei u8815), but its based on BF6931A1 instead S2100A. BF6931A1 is not proper initialized by driver. It start fail on synaptics_rmi4_read_pdt where ret = i2c_smbus_write_byte_data(ts->client, 0xff, 0x00); is called (set rmi page to zero). Its just the first symptom where i see that the i2c communication fail. I try on many way to reset this chip by software but without success: Dmesg part when the BF6931A1 chip is connected: <6>[1, swapper] [ 1.083416] rmi_bus_init: RMI Bus Driver Init <7>[1, swapper] [ 1.083533] rmi_bus_init: registered bus. <7>[1, swapper] [ 1.083559] rmi_sensor_init: RMI Sensor Init <7>[1, swapper] [ 1.083578] rmi_function_init: RMI Function Init <4>[1, swapper] [ 1.083688] i2c-core: driver [rmi4_ts] using legacy suspend method <4>[1, swapper] [ 1.083718] i2c-core: driver [rmi4_ts] using legacy resume method <4>[1, swapper] [ 1.083804] *************** synaptics_rmi4_probe ****************** <4>[1, swapper] [ 1.083833] Client adress is: 70 <6>[1, swapper] [ 1.083856] the i2c_check_functionality is ok <3>[1, swapper] [ 1.083888] synaptics_rmi4_probe: it's the first touch driver! <3>[1, swapper] [ 1.150668] qup_i2c qup_i2c.1: QUP: I2C status flags :0x1121c4, irq:43 <3>[1, swapper] [ 1.151383] failed to set rmi page <3>[1, swapper] [ 1.151428] qup_i2c qup_i2c.1: QUP: I2C status flags :0x1121c4, irq:43 <3>[1, swapper] [ 1.152136] I2C read failed querying RMI4 $70 capabilities <3>[1, swapper] [ 1.152164] Error identifying device (-5) <4>[60, synaptics_wq] [ 1.152218] do_exit: exit code=4294967292 <4>[60, synaptics_wq] [ 1.152271] synaptics_wq used greatest stack depth: 6552 bytes left <4>[1, swapper] [ 1.152424] *************** synaptics_rmi4_probe ****************** <4>[1, swapper] [ 1.152456] Client adress is: 24 <6>[1, swapper] [ 1.152478] the i2c_check_functionality is ok <3>[1, swapper] [ 1.152509] synaptics_rmi4_probe: it's the first touch driver! <7>[1, swapper] [ 1.152539] gpio_request: gpio-96 (TOUCH_RESET) status -16 <3>[1, swapper] [ 1.218838] qup_i2c qup_i2c.1: QUP: I2C status flags :0x1121c4, irq:43 <3>[1, swapper] [ 1.219549] failed to set rmi page <3>[1, swapper] [ 1.219591] qup_i2c qup_i2c.1: QUP: I2C status flags :0x1121c4, irq:43 <3>[1, swapper] [ 1.220299] I2C read failed querying RMI4 $24 capabilities <3>[1, swapper] [ 1.220326] Error identifying device (-5) And now how its look with original S2100A: <6>[1, swapper] [ 1.039414] rmi_bus_init: RMI Bus Driver Init <7>[1, swapper] [ 1.039529] rmi_bus_init: registered bus. <7>[1, swapper] [ 1.039556] rmi_sensor_init: RMI Sensor Init <7>[1, swapper] [ 1.039576] rmi_function_init: RMI Function Init <4>[1, swapper] [ 1.039683] i2c-core: driver [rmi4_ts] using legacy suspend method <4>[1, swapper] [ 1.039713] i2c-core: driver [rmi4_ts] using legacy resume method <4>[1, swapper] [ 1.039798] *************** synaptics_rmi4_probe ****************** <4>[1, swapper] [ 1.039828] Client adress is: 70 <6>[1, swapper] [ 1.039851] the i2c_check_functionality is ok <3>[1, swapper] [ 1.039883] synaptics_rmi4_probe: it's the first touch driver! <4>[1, swapper] [ 1.106931] set rmi page to zero successfull <6>[1, swapper] [ 1.111396] 2 fingers <6>[1, swapper] [ 1.111419] EGR features: <6>[1, swapper] [ 1.111441] pinch: 0 <6>[1, swapper] [ 1.111463] press: 0 <6>[1, swapper] [ 1.111483] flick: 0 <6>[1, swapper] [ 1.111503] early tap: 0 <6>[1, swapper] [ 1.111524] double tap: 0 <6>[1, swapper] [ 1.111544] tap and hold: 0 <6>[1, swapper] [ 1.111566] single tap: 1 <6>[1, swapper] [ 1.111588] palm detect: 0 <6>[1, swapper] [ 1.113298] max X: 1068; max Y: 1868 <6>[1, swapper] [ 1.114231] Read 0 functions from PDT <3>[1, swapper] [ 1.114256] RMI4 $70 data read: $13 + 15 <6>[1, swapper] [ 1.116009] the ReportingMode is changged ok! <6>[1, swapper] [ 1.116376] input: synaptics as /devices/virtual/input/input0 <6>[1, swapper] [ 1.116594] synaptics input device registered <7>[1, swapper] [ 1.116696] gpio_request: gpio-146 (Synaptics_rmi) status -22 <7>[1, swapper] [ 1.116721] gpio_direction_input: gpio-146 status -22 <6>[1, swapper] [ 1.116738] Requesting IRQ... <6>[1, swapper] [ 1.116828] Received IRQ! <3>[1, swapper] [ 1.116868] probingX for Synaptics RMI4 device Synaptics_rmi at $70... <4>[1, swapper] [ 1.116928] *************** synaptics_rmi4_probe ****************** <4>[1, swapper] [ 1.116958] Client adress is: 24 <6>[1, swapper] [ 1.116979] the i2c_check_functionality is ok <3>[1, swapper] [ 1.117011] synaptics_rmi4_probe: the touch driver has detected :) <4>[1, swapper] [ 1.117054] Synaptics_rmi: probe of 1-0024 failed with error -1 How we can see set rmi page to zero is successfull and also reading capabilities are fine: RMI4 $70 data read: $13 + 15 Now when I switch(without rebooting) again to BF6931A1 I`m able to use my touchscreen without any issues! Now its time to reboot phone and see what dmesg show: <6>[1, swapper] [ 1.039468] rmi_bus_init: RMI Bus Driver Init <7>[1, swapper] [ 1.039583] rmi_bus_init: registered bus. <7>[1, swapper] [ 1.039609] rmi_sensor_init: RMI Sensor Init <7>[1, swapper] [ 1.039628] rmi_function_init: RMI Function Init <4>[1, swapper] [ 1.039736] i2c-core: driver [rmi4_ts] using legacy suspend method <4>[1, swapper] [ 1.039764] i2c-core: driver [rmi4_ts] using legacy resume method <4>[1, swapper] [ 1.039851] *************** synaptics_rmi4_probe ****************** <4>[1, swapper] [ 1.039879] Client adress is: 70 <6>[1, swapper] [ 1.039903] the i2c_check_functionality is ok <3>[1, swapper] [ 1.039934] synaptics_rmi4_probe: it's the first touch driver! <4>[1, swapper] [ 1.106981] set rmi page to zero successfull <6>[1, swapper] [ 1.111361] 2 fingers <6>[1, swapper] [ 1.111384] EGR features: <6>[1, swapper] [ 1.111406] pinch: 0 <6>[1, swapper] [ 1.111426] press: 0 <6>[1, swapper] [ 1.111448] flick: 0 <6>[1, swapper] [ 1.111468] early tap: 0 <6>[1, swapper] [ 1.111489] double tap: 0 <6>[1, swapper] [ 1.111509] tap and hold: 0 <6>[1, swapper] [ 1.111531] single tap: 1 <6>[1, swapper] [ 1.111553] palm detect: 0 <6>[1, swapper] [ 1.113243] max X: 1036; max Y: 1904 <6>[1, swapper] [ 1.114176] Read 0 functions from PDT <3>[1, swapper] [ 1.114203] RMI4 $70 data read: $13 + 15 <7>[18, kworker/0:1] [ 1.254419] gpio_request: gpio-141 (i2c_host_vbus_en) status -22 <3>[18, kworker/0:1] [ 1.254443] failed to request 141 GPIO <6>[18, kworker/0:1] [ 1.354574] msm_hsusb_host msm_hsusb_host.0: Qualcomm On-Chip EHCI Host Controller <6>[18, kworker/0:1] [ 1.354644] msm_hsusb_host msm_hsusb_host.0: new USB bus registered, assigned bus number 1 <6>[18, kworker/0:1] [ 1.354824] msm_hsusb_host msm_hsusb_host.0: irq 47, io base 0xa0800000 <6>[18, kworker/0:1] [ 1.354996] usb usb1: New USB device found, idVendor=1d6b, idProduct=0002 <6>[18, kworker/0:1] [ 1.355034] usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1 <6>[18, kworker/0:1] [ 1.355069] usb usb1: Product: Qualcomm On-Chip EHCI Host Controller <6>[18, kworker/0:1] [ 1.355099] usb usb1: Manufacturer: Linux 3.0.8-perf ehci_hcd <6>[18, kworker/0:1] [ 1.355129] usb usb1: SerialNumber: msm_hsusb_host.0 <6>[18, kworker/0:1] [ 1.355879] hub 1-0:1.0: USB hub found <6>[18, kworker/0:1] [ 1.355934] hub 1-0:1.0: 1 port detected <6>[18, kworker/0:1] [ 1.356509] msm_hsusb_host msm_hsusb_host.0: remove, state 1 <6>[18, kworker/0:1] [ 1.356561] usb usb1: USB disconnect, device number 1 <6>[18, kworker/0:1] [ 1.374768] msm_hsusb_host msm_hsusb_host.0: USB bus 1 deregistered <7>[18, kworker/0:1] [ 1.604413] gpio_request: gpio-141 (i2c_host_vbus_en) status -22 <3>[18, kworker/0:1] [ 1.604451] failed to request 141 GPIO <3>[1, swapper] [ 2.144336] qup_i2c qup_i2c.1: Transaction timed out, SL-AD = 0x70 <3>[1, swapper] [ 2.144371] qup_i2c qup_i2c.1: I2C Status: 349b00 <3>[1, swapper] [ 2.144398] qup_i2c qup_i2c.1: QUP Status: 0 <3>[1, swapper] [ 2.144424] qup_i2c qup_i2c.1: OP Flags: 0 <4>[1, swapper] [ 2.144458] Failed to read IC name. <3>[1, swapper] [ 2.144506] qup_i2c qup_i2c.1: QUP: I2C status flags :0x1121c4, irq:43 <3>[1, swapper] [ 2.145221] tp_read_input_name: i2c_transfer failed at address $70 <6>[1, swapper] [ 2.145286] the ReportingMode is changged ok! <6>[1, swapper] [ 2.145656] input: synaptics as /devices/virtual/input/input0 <6>[1, swapper] [ 2.145863] synaptics input device registered <7>[1, swapper] [ 2.145963] gpio_request: gpio-146 (Synaptics_rmi) status -22 <7>[1, swapper] [ 2.145986] gpio_direction_input: gpio-146 status -22 <6>[1, swapper] [ 2.146004] Requesting IRQ... <6>[1, swapper] [ 2.146093] Received IRQ! <3>[1, swapper] [ 2.146129] probingX for Synaptics RMI4 device Synaptics_rmi at $70... <4>[1, swapper] [ 2.146193] *************** synaptics_rmi4_probe ****************** <4>[1, swapper] [ 2.146223] Client adress is: 24 <6>[1, swapper] [ 2.146244] the i2c_check_functionality is ok <3>[1, swapper] [ 2.146276] synaptics_rmi4_probe: the touch driver has detected :) <4>[1, swapper] [ 2.146316] Synaptics_rmi: probe of 1-0024 failed with error -1 As we can see after reboot driver was able to set rmi page to zero abd read capabilities. Unfortunate In this moment my touchscreen is not responding and in dmesg i see a lot of: <3>[19, kworker/u:1] [ 290.841264] synaptics_rmi4_work_func: i2c_transfer failed <3>[19, kworker/u:1] [ 290.841343] qup_i2c qup_i2c.1: QUP: I2C status flags :0x1121c4, irq:43 <3>[19, kworker/u:1] [ 290.841869] synaptics_rmi4_work_func: i2c_transfer failed <3>[19, kworker/u:1] [ 290.844888] qup_i2c qup_i2c.1: QUP: I2C status flags :0x1121c4, irq:43 This state is until i reconnect BF6931A1, (still the same without connecting the old S2100A). Now again works fine. Then when re-flash new kernel (and sometimes when I disconnect all power) its a big chance to back to state from first dmesg. In attachment i put my latest code. Maybe somebody here have idea what i can do else (maybe some hardware reset of i2c or other magic). General i`m opened on any tip. Best Regards, Grzegorz Hetman.
/* drivers/input/keyboard/synaptics_i2c_rmi.c * * Copyright (C) 2007 Google, Inc. * Copyright (C) 2008 Texas Instrument Inc. * Copyright (C) 2009 Synaptics, Inc. * * provides device files /dev/input/event# * for named device files, use udev * 2D sensors report ABS_X_FINGER(0), ABS_Y_FINGER(0) through ABS_X_FINGER(7), ABS_Y_FINGER(7) * NOTE: requires updated input.h, which should be included with this driver * 1D/Buttons report BTN_0 through BTN_0 + button_count * TODO: report REL_X, REL_Y for flick, BTN_TOUCH for tap (on 1D/0D; done for 2D) * TODO: check ioctl (EVIOCGABS) to query 2D max X & Y, 1D button count * * 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. * */ /* modify for 4125 baseline */ #include <linux/slab.h> #include <linux/module.h> #include <linux/input.h> #include <linux/interrupt.h> #include <linux/hrtimer.h> #include <linux/platform_device.h> #include <linux/i2c.h> #include <linux/delay.h> #include <linux/synaptics_i2c_rmi_1564.h> #include <linux/io.h> #include <linux/gpio.h> #include <linux/earlysuspend.h> #include <linux/device.h> #include <mach/vreg.h> #include <mach/gpio.h> /*include the .h file*/ #include <linux/proc_fs.h> #include <linux/touch_platform_config.h> #ifdef CONFIG_HUAWEI_HW_DEV_DCT #include <linux/hw_dev_dec.h> #endif #define CONFIG_SYNAPTICS_UPDATE_RMI_TS_FIRMWARE #ifdef CONFIG_SYNAPTICS_UPDATE_RMI_TS_FIRMWARE #include <linux/fs.h> #include <asm/uaccess.h> #include <linux/namei.h> #include <linux/vmalloc.h> #endif #define DEV_ATTR(_pre, _name, _mode) \ DEVICE_ATTR(_pre##_##_name,_mode,_pre##_##_name##_show,_pre##_##_name##_store) #include <linux/kernel.h> #include <asm/mach-types.h> #include "linux/hardware_self_adapt.h" #define BTN_F19 BTN_0 #define BTN_F30 BTN_0 #define SCROLL_ORIENTATION REL_Y /* //#define TS_RMI_DEBUG #undef TS_RMI_DEBUG #ifdef TS_RMI_DEBUG #define TS_DEBUG_RMI(fmt, args...) printk(KERN_INFO fmt, ##args) #else #define TS_DEBUG_RMI(fmt, args...) #endif */ #define TS_DEBUG_RMI(fmt, args...) printk(KERN_INFO fmt, ##args) // protoypes,else the structure initialization that follows fail static int dev_open(struct inode *, struct file *); static int dev_rls(struct inode *, struct file *); static ssize_t dev_read(struct file *, char *, size_t, loff_t *); static ssize_t dev_write(struct file *, const char *, size_t, loff_t *); struct i2c_client *global_client; #ifdef CONFIG_SYNAPTICS_UPDATE_RMI_TS_FIRMWARE #define SYNAPITICS_DEBUG(fmt, args...) printk(KERN_DEBUG fmt, ##args) static struct i2c_client *g_client = NULL; static ssize_t update_firmware_show(struct kobject *kobj, struct kobj_attribute *attr,char *buf); static ssize_t update_firmware_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count); static int ts_firmware_file(void); static int i2c_update_firmware(struct i2c_client *client); static struct kobj_attribute update_firmware_attribute = { .attr = {.name = "update_firmware", .mode = 0664}, .show = update_firmware_show, .store = update_firmware_store, }; #endif /* CONFIG_SYNAPTICS_UPDATE_RMI_TS_FIRMWARE */ static int synaptics_debug_mask; module_param_named(synaptics_debug, synaptics_debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP); #define DBG_MASK(x...) do {\ if (synaptics_debug_mask) \ printk(KERN_DEBUG x);\ } while (0) static struct workqueue_struct *synaptics_wq; static struct synaptics_rmi4 *ts = NULL; #define EGR_PINCH_REG 0 #define EGR_PINCH (1 << 6) #define EGR_PRESS_REG 0 #define EGR_PRESS (1 << 5) #define EGR_FLICK_REG 0 #define EGR_FLICK (1 << 4) #define EGR_EARLY_TAP_REG 0 #define EGR_EARLY_TAP (1 << 3) #define EGR_DOUBLE_TAP_REG 0 #define EGR_DOUBLE_TAP (1 << 2) #define EGR_TAP_AND_HOLD_REG 0 #define EGR_TAP_AND_HOLD (1 << 1) #define EGR_SINGLE_TAP_REG 0 #define EGR_SINGLE_TAP (1 << 0) /* Register: EGR_1 */ #define EGR_PALM_DETECT_REG 1 #define EGR_PALM_DETECT (1 << 0) #define FINGER_MAX 9 #define FINGER_CNT (FINGER_MAX+1) #define SYNAPTICS_I2C_RMI_NAME "Synaptics_RMI4" #define ABS_XF 0 #define ABS_YF 1 #define ABS_ZF 2 #define EVENTS_PER_FINGER 3 #define ABS_FINGER(f) (0x29 + EVENTS_PER_FINGER * f) #define ABS_X_FINGER(f) (ABS_FINGER(f) + ABS_XF) #define ABS_Y_FINGER(f) (ABS_FINGER(f) + ABS_YF) #define ABS_Z_FINGER(f) (ABS_FINGER(f) + ABS_ZF) #define ABS_CNT (ABS_MAX+1) struct synaptics_function_descriptor { __u8 queryBase; __u8 commandBase; __u8 controlBase; __u8 dataBase; __u8 intSrc; #define FUNCTION_VERSION(x) ((x >> 5) & 3) #define INTERRUPT_SOURCE_COUNT(x) (x & 7) __u8 functionNumber; }; #define FD_ADDR_MAX 0xE9 #define FD_ADDR_MIN 0x05 #define FD_BYTE_COUNT 6 #define BYD 1 #define CMI 2 #define TRULY 3 #define TPK 4 #define LENSONE 5 #define OFILM 6 #define EELY 7 #define SUCCESS 8 #define ALPS 9 static u16 touch_ic_name = 0; static char touch_info[50] = {0}; static int RMI4_enable_program(struct i2c_client *client); int RMI4_disable_program(struct i2c_client *client); static struct synaptics_function_descriptor fd_34; static struct synaptics_function_descriptor fd_01; static struct i2c_msg query_i2c_msg_name[2]; static __u8 query_name[8]; static int ts_x_max = 0; static int ts_y_max = 0; static int lcd_x = 0; static int lcd_y = 0; static int lcd_all = 0; static __u8 point_supported_huawei = 0; extern struct i2c_device_id synaptics_rmi4_id[]; #ifdef CONFIG_HAS_EARLYSUSPEND static void synaptics_rmi4_early_suspend(struct early_suspend *h); static void synaptics_rmi4_late_resume(struct early_suspend *h); #endif /*Prototypes */ static int synaptics_rmi4_suspend(struct i2c_client *client, pm_message_t mesg); static int synaptics_rmi4_resume(struct i2c_client *client); u12 check_scope_X(u12 x) { u12 temp = x; if (x >= lcd_x -1) { temp = lcd_x -2; } if (x <= 1) { temp = 1; } return temp; } static int synaptics_rmi4_read_pdt(struct synaptics_rmi4 *ts) { int ret = 0; int nFd = 0; int interruptCount = 0; struct i2c_msg fd_i2c_msg[2]; struct i2c_msg query_i2c_msg[2]; struct synaptics_function_descriptor fd; __u8 data_length = 0; __u8 fd_reg; __u8 query[14]; __u8 *egr; /* check whether rmi page is 0 */ printk("\033[22;31m OK sprawdzamy rmi page... \033[01;0m\n"); ret = i2c_smbus_write_byte_data(ts->client, 0xff, 0x00); if(ret < 0) { printk(KERN_ERR "failed to set rmi page\n"); } else { printk("set rmi page to zero successfull\n"); } fd_i2c_msg[0].addr = ts->client->addr; fd_i2c_msg[0].flags = 0; fd_i2c_msg[0].buf = &fd_reg; fd_i2c_msg[0].len = 1; fd_i2c_msg[1].addr = ts->client->addr; fd_i2c_msg[1].flags = I2C_M_RD; fd_i2c_msg[1].buf = (__u8 *)(&fd); fd_i2c_msg[1].len = FD_BYTE_COUNT; query_i2c_msg[0].addr = ts->client->addr; query_i2c_msg[0].flags = 0; query_i2c_msg[0].buf = &fd.queryBase; query_i2c_msg[0].len = 1; query_i2c_msg[1].addr = ts->client->addr; query_i2c_msg[1].flags = I2C_M_RD; query_i2c_msg[1].buf = query; query_i2c_msg[1].len = sizeof(query); ts->hasF11 = false; ts->hasF19 = false; ts->hasF30 = false; ts->data_reg = 0xff; ts->data_length = 0; for (fd_reg = FD_ADDR_MAX; fd_reg >= FD_ADDR_MIN; fd_reg -= FD_BYTE_COUNT){ ret = i2c_transfer(ts->client->adapter, fd_i2c_msg, 2); if (ret < 0){ printk(KERN_ERR "I2C read failed querying RMI4 $%02X capabilities\n", ts->client->addr); return ret; } if (!fd.functionNumber){ /* End of PDT */ ret = nFd; TS_DEBUG_RMI("Read %d functions from PDT\n", fd.functionNumber); break; } ++nFd; switch (fd.functionNumber) { case 0x34: fd_34.queryBase = fd.queryBase; fd_34.dataBase = fd.dataBase; fd_34.controlBase = fd.controlBase; break; case 0x01: /* Interrupt */ ts->f01.data_offset = fd.dataBase; fd_01.queryBase = fd.queryBase; fd_01.dataBase = fd.dataBase; fd_01.commandBase = fd.commandBase; fd_01.controlBase = fd.controlBase; /* * Can't determine data_length * until whole PDT has been read to count interrupt sources * and calculate number of interrupt status registers. * Setting to 0 safely "ignores" for now. */ data_length = 0; break; case 0x11: /* 2D */ ts->hasF11 = true; ts->f11.data_offset = fd.dataBase; ts->f11.interrupt_offset = interruptCount / 8; ts->f11.interrupt_mask = ((1 << INTERRUPT_SOURCE_COUNT(fd.intSrc)) - 1) << (interruptCount % 8); ret = i2c_transfer(ts->client->adapter, query_i2c_msg, 2); if (ret < 0) printk(KERN_ERR "Error reading F11 query registers\n"); ts->f11.points_supported = (query[1] & 7) + 1; if (ts->f11.points_supported == 6) ts->f11.points_supported = 10; ts->f11_fingers = kcalloc(ts->f11.points_supported, sizeof(*ts->f11_fingers), 0); TS_DEBUG_RMI("%d fingers\n", ts->f11.points_supported); ts->f11_has_gestures = (query[1] >> 5) & 1; ts->f11_has_relative = (query[1] >> 3) & 1; /* < DTS2010090603538 zhangtao 20100913 begin */ /* if the sensitivity adjust exist */ ts->f11_has_Sensitivity_Adjust = (query[1] >> 6) & 1; /* DTS2010090603538 zhangtao 20100913 end > */ egr = &query[7]; TS_DEBUG_RMI("EGR features:\n"); ts->hasEgrPinch = egr[EGR_PINCH_REG] & EGR_PINCH; TS_DEBUG_RMI("\tpinch: %u\n", ts->hasEgrPinch); ts->hasEgrPress = egr[EGR_PRESS_REG] & EGR_PRESS; TS_DEBUG_RMI("\tpress: %u\n", ts->hasEgrPress); ts->hasEgrFlick = egr[EGR_FLICK_REG] & EGR_FLICK; TS_DEBUG_RMI("\tflick: %u\n", ts->hasEgrFlick); ts->hasEgrEarlyTap = egr[EGR_EARLY_TAP_REG] & EGR_EARLY_TAP; TS_DEBUG_RMI("\tearly tap: %u\n", ts->hasEgrEarlyTap); ts->hasEgrDoubleTap = egr[EGR_DOUBLE_TAP_REG] & EGR_DOUBLE_TAP; TS_DEBUG_RMI("\tdouble tap: %u\n", ts->hasEgrDoubleTap); ts->hasEgrTapAndHold = egr[EGR_TAP_AND_HOLD_REG] & EGR_TAP_AND_HOLD; TS_DEBUG_RMI("\ttap and hold: %u\n", ts->hasEgrTapAndHold); ts->hasEgrSingleTap = egr[EGR_SINGLE_TAP_REG] & EGR_SINGLE_TAP; TS_DEBUG_RMI("\tsingle tap: %u\n", ts->hasEgrSingleTap); ts->hasEgrPalmDetect = egr[EGR_PALM_DETECT_REG] & EGR_PALM_DETECT; TS_DEBUG_RMI("\tpalm detect: %u\n", ts->hasEgrPalmDetect); query_i2c_msg[0].buf = &fd.controlBase; ret = i2c_transfer(ts->client->adapter, query_i2c_msg, 2); if (ret < 0) printk(KERN_ERR "Error reading F11 control registers\n"); query_i2c_msg[0].buf = &fd.queryBase; ts->f11_max_x = ((query[7] & 0x0f) * 0x100) | query[6]; ts->f11_max_y = ((query[9] & 0x0f) * 0x100) | query[8]; TS_DEBUG_RMI("max X: %d; max Y: %d\n", ts->f11_max_x, ts->f11_max_y); ts->f11.data_length = data_length = /* finger status, four fingers per register */ ((ts->f11.points_supported + 3) / 4) /* absolute data, 5 per finger */ + 5 * ts->f11.points_supported /* two relative registers */ + (ts->f11_has_relative ? 2 : 0) /* F11_2D_Data8 is only present if the egr_0 register is non-zero. */ + (egr[0] ? 1 : 0) /* F11_2D_Data9 is only present if either egr_0 or egr_1 registers are non-zero. */ + ((egr[0] || egr[1]) ? 1 : 0) /* F11_2D_Data10 is only present if EGR_PINCH or EGR_FLICK of egr_0 reports as 1. */ + ((ts->hasEgrPinch || ts->hasEgrFlick) ? 1 : 0) /* F11_2D_Data11 and F11_2D_Data12 are only present if EGR_FLICK of egr_0 reports as 1. */ + (ts->hasEgrFlick ? 2 : 0); break; case 0x30: /* GPIO */ ts->hasF30 = true; ts->f30.data_offset = fd.dataBase; ts->f30.interrupt_offset = interruptCount / 8; ts->f30.interrupt_mask = ((1 < INTERRUPT_SOURCE_COUNT(fd.intSrc)) - 1) << (interruptCount % 8); ret = i2c_transfer(ts->client->adapter, query_i2c_msg, 2); if (ret < 0) printk(KERN_ERR "Error reading F30 query registers\n"); ts->f30.points_supported = query[1] & 0x1F; ts->f30.data_length = data_length = (ts->f30.points_supported + 7) / 8; break; default: goto pdt_next_iter; } /* end swith */ /* Change to end address for comparison NOTE: make sure final value of ts->data_reg is subtracted */ data_length += fd.dataBase; if (data_length > ts->data_length) { ts->data_length = data_length; } if (fd.dataBase < ts->data_reg) { ts->data_reg = fd.dataBase; } pdt_next_iter: interruptCount += INTERRUPT_SOURCE_COUNT(fd.intSrc); } /* end for */ /* Now that PDT has been read, interrupt count determined, F01 data length can be determined.*/ ts->f01.data_length = data_length = 1 + ((interruptCount + 7) / 8); /* Change to end address for comparison NOTE: make sure final value of ts->data_reg is subtracted*/ data_length += ts->f01.data_offset; if (data_length > ts->data_length) { ts->data_length = data_length; } /*Change data_length back from end address to length*/ /*NOTE: make sure this was an address*/ ts->data_length -= ts->data_reg; // I want to read the register from F01_data_reg ts->data_reg = ts->f01.data_offset; ts->data_length = (ts->f01.data_length) + (ts->f11.data_length); ts->f01.data_offset -= ts->data_reg; ts->f11.data_offset -= ts->data_reg; ts->f19.data_offset -= ts->data_reg; ts->f30.data_offset -= ts->data_reg; ts->data = kcalloc(ts->data_length, sizeof(*ts->data), 0); if (ts->data == NULL) { printk(KERN_ERR "Not enough memory to allocate space for RMI4 data\n"); ret = -ENOMEM; } ts->data_i2c_msg[0].addr = ts->client->addr; ts->data_i2c_msg[0].flags = 0; ts->data_i2c_msg[0].len = 1; ts->data_i2c_msg[0].buf = &ts->data_reg; ts->data_i2c_msg[1].addr = ts->client->addr; ts->data_i2c_msg[1].flags = I2C_M_RD; ts->data_i2c_msg[1].len = ts->data_length; ts->data_i2c_msg[1].buf = ts->data; printk(KERN_ERR "RMI4 $%02X data read: $%02X + %d\n", ts->client->addr, ts->data_reg, ts->data_length); return ret; } static void synaptics_rmi4_work_func(struct work_struct *work) { int ret; __u8 finger_status = 0x00; __u8 reg = 0; __u8 *finger_reg = NULL; u12 x = 0; u12 y = 0; u4 wx = 0; u4 wy = 0; u8 z = 0 ; __u8 prev_state = 0; u8 finger_pressed_count = 0; struct synaptics_rmi4 *ts = container_of(work, struct synaptics_rmi4, work); ret = i2c_transfer(ts->client->adapter, ts->data_i2c_msg, 2); if (ret < 0) { printk(KERN_ERR "%s: i2c_transfer failed\n", __func__); } else /* else with "i2c_transfer's return value"*/ { __u8 *interrupt = &ts->data[ts->f01.data_offset + 1]; if (ts->hasF11 && interrupt[ts->f11.interrupt_offset] & ts->f11.interrupt_mask) { __u8 *f11_data = &ts->data[ts->f11.data_offset]; int f = 0; __u8 finger_status_reg = 0; __u8 fsr_len = (ts->f11.points_supported + 3) / 4; TS_DEBUG_RMI("f11.points_supported is %d\n",ts->f11.points_supported); if(ts->is_support_multi_touch) { for (f = 0; f < point_supported_huawei; ++f) { if (!(f % 4)) finger_status_reg = f11_data[f / 4]; finger_status = (finger_status_reg >> ((f % 4) * 2)) & 3; reg = fsr_len + 5 * f; finger_reg = &f11_data[reg]; x = (finger_reg[0] * 0x10) | (finger_reg[2] % 0x10); y = (finger_reg[1] * 0x10) | (finger_reg[2] / 0x10); wx = finger_reg[3] % 0x10; wy = finger_reg[3] / 0x10; z = finger_reg[4]; /* when the esd is get error we reset the touchscreen ic(only on u8820 now) */ if(machine_is_msm7x30_u8820()) { if(interrupt[ts->f11.interrupt_offset] & 0x02) { ret = i2c_smbus_read_byte_data(ts->client, fd_01.dataBase); if(ret & 0x03) { ret = i2c_smbus_write_byte_data(ts->client, fd_01.commandBase, 0x01); printk("the touchscreen is reset yet!\n"); } } } x = x * lcd_x / ts_x_max; if (machine_is_msm7x27a_U8661()) { y = ((ts_y_max - y) * lcd_all ) / ts_y_max; } else { y = ( y * lcd_all ) / ts_y_max; } x = check_scope_X(x); DBG_MASK("the x is %d the y is %d the stauts is %d!\n",x,y,finger_status); prev_state = ts->f11_fingers[f].status; if (prev_state && !finger_status ) { z = wx = wy = 0; } else if (!prev_state && !finger_status ) { continue; } input_report_abs(ts->input_dev, ABS_MT_PRESSURE, z); input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, max(wx, wy)); input_report_abs(ts->input_dev, ABS_MT_TOUCH_MINOR, min(wx, wy)); input_report_abs(ts->input_dev, ABS_MT_ORIENTATION, (wx > wy ? 1 : 0)); input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x); input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y); input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, f); input_mt_sync(ts->input_dev); ts->f11_fingers[f].status = finger_status; if (finger_status > 0) finger_pressed_count++; } input_report_key(ts->input_dev, BTN_TOUCH, finger_pressed_count); } else /* else with "if(ts->is_support_multi_touch)"*/ { finger_status_reg = f11_data[0]; finger_status = (finger_status_reg & 3); TS_DEBUG_RMI("the finger_status is %2d!\n",finger_status); reg = fsr_len; finger_reg = &f11_data[reg]; x = (finger_reg[0] * 0x10) | (finger_reg[2] % 0x10); y = (finger_reg[1] * 0x10) | (finger_reg[2] / 0x10); wx = finger_reg[3] % 0x10; wy = finger_reg[3] / 0x10; z = finger_reg[4]; x = x * lcd_x / ts_x_max; y = y * lcd_all / ts_y_max; /*check the scope of X axes*/ x = check_scope_X(x); TS_DEBUG_RMI(KERN_ERR "the x_sig is %2d ,the y_sig is %2d \n",x, y); input_report_abs(ts->input_dev, ABS_X, x); input_report_abs(ts->input_dev, ABS_Y, y); input_report_abs(ts->input_dev, ABS_PRESSURE, z); input_report_key(ts->input_dev, BTN_TOUCH, finger_status); input_sync(ts->input_dev); } f = (f + 3) / 4 + f * 5; if (ts->f11_has_relative) { f += 2; } if (ts->hasEgrPalmDetect) { input_report_key(ts->input_dev, BTN_DEAD, f11_data[f + EGR_PALM_DETECT_REG] & EGR_PALM_DETECT); } if (ts->hasEgrFlick) { if (f11_data[f + EGR_FLICK_REG] & EGR_FLICK) { input_report_rel(ts->input_dev, REL_X, f11_data[f + 2]); input_report_rel(ts->input_dev, REL_Y, f11_data[f + 3]); } } /*if (ts->hasEgrSingleTap) { input_report_key(ts->input_dev, BTN_TOUCH, f11_data[f + EGR_SINGLE_TAP_REG] & EGR_SINGLE_TAP); }*/ if (ts->hasEgrDoubleTap) { input_report_key(ts->input_dev, BTN_TOOL_DOUBLETAP, f11_data[f + EGR_DOUBLE_TAP_REG] & EGR_DOUBLE_TAP); } } if (ts->hasF19 && interrupt[ts->f19.interrupt_offset] & ts->f19.interrupt_mask) { int reg; int touch = 0; for (reg = 0; reg < ((ts->f19.points_supported + 7) / 8); reg++) { if (ts->data[ts->f19.data_offset + reg]) { touch = 1; break; } } input_report_key(ts->input_dev, BTN_DEAD, touch); } input_sync(ts->input_dev); } /*delete one line*/ if (ts->use_irq) { enable_irq(ts->client->irq); } } static enum hrtimer_restart synaptics_rmi4_timer_func(struct hrtimer *timer) { struct synaptics_rmi4 *ts = container_of(timer, \ struct synaptics_rmi4, timer); queue_work(synaptics_wq, &ts->work); hrtimer_start(&ts->timer, ktime_set(0, 12 * NSEC_PER_MSEC), HRTIMER_MODE_REL); return HRTIMER_NORESTART; } irqreturn_t synaptics_rmi4_irq_handler(int irq, void *dev_id) { struct synaptics_rmi4 *ts = dev_id; disable_irq_nosync(ts->client->irq); queue_work(synaptics_wq, &ts->work); return IRQ_HANDLED; } static void synaptics_rmi4_enable(struct synaptics_rmi4 *ts) { if (ts->use_irq) enable_irq(ts->client->irq); else hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL); ts->enable = 1; } static void synaptics_rmi4_disable(struct synaptics_rmi4 *ts) { if (ts->use_irq) disable_irq_nosync(ts->client->irq); else hrtimer_cancel(&ts->timer); cancel_work_sync(&ts->work); ts->enable = 0; } static ssize_t synaptics_rmi4_enable_show(struct device *dev, struct device_attribute *attr, char *buf) { struct synaptics_rmi4 *ts = dev_get_drvdata(dev); return sprintf(buf, "%u\n", ts->enable); } static ssize_t synaptics_rmi4_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct synaptics_rmi4 *ts = dev_get_drvdata(dev); unsigned long val; int error; error = strict_strtoul(buf, 10, &val); if (error) return error; val = !!val; if (val != ts->enable) { if (val) synaptics_rmi4_enable(ts); else synaptics_rmi4_disable(ts); } return count; } DEV_ATTR(synaptics_rmi4, enable, 0664); static char * get_touch_module_name(u8 module_id) { switch(module_id) { case BYD: return "BYD"; case CMI: return "CMI"; case TRULY: return "TRULY"; case TPK: return "TPK"; case LENSONE: return "LENSONE"; case OFILM: return "OFILM"; case EELY: return "EELY"; case SUCCESS: return "SUCCESS"; case ALPS: return "ALPS"; default: return NULL; } return NULL; } /* named Rule * 2202 3200 : syanptics-IC-Module.ver * for example: syanptics-3200-tpk.2 * * 2000 2100 3000 :syanptics-Module.ver * for example: syanptics-tpk.2 */ char * get_synaptics_touch_info(void) { u32 config_id = 0; char * module_name = NULL; module_name = get_touch_module_name(query_name[2]); if (module_name == NULL) { return NULL; } if (touch_ic_name == 2202) { config_id = query_name[3]; sprintf(touch_info,"synaptics-2202-%s.%d",module_name,config_id); } else if (touch_ic_name == 3200) { config_id = query_name[3]; sprintf(touch_info,"synaptics-3200-%s.%d",module_name,config_id); } else { config_id = query_name[3]; sprintf(touch_info,"synaptics-%s.%d",module_name,config_id); } return touch_info; } #if 0 char * get_touch_info(void) { char * touch_info = NULL; touch_info = get_synaptics_touch_info(); if (touch_info != NULL) { return touch_info; } return NULL; } #endif static void get_ic_name(void) { struct i2c_msg msg[2]; char ic_name_buffer[2]; int ret; u8 addr = fd_01.queryBase+17; msg[0].addr = ts->client->addr; msg[0].flags = 0; msg[0].buf = &addr; msg[0].len = 1; msg[1].addr = ts->client->addr; msg[1].flags = I2C_M_RD; msg[1].buf = ic_name_buffer; msg[1].len = sizeof(ic_name_buffer); ret = i2c_transfer(ts->client->adapter, msg, 2); if (ret < 0) { printk("Failed to read IC name.\n"); return; } touch_ic_name = ic_name_buffer[1] * 0x100 + ic_name_buffer[0]; } static u8 get_module_id(void) { struct i2c_msg msg[2]; char productid[11]; int ret ; unsigned long module_id = 0; u8 querybase = 0; ret = RMI4_enable_program(ts->client); if( ret != 0) { printk("%s:%d:RMI enable program error,return...\n",__FUNCTION__,__LINE__); goto get_module_id_error; } querybase = fd_01.queryBase + 11; msg[0].addr = ts->client->addr; msg[0].flags = 0; msg[0].buf = &querybase; msg[0].len = 1; msg[1].addr = ts->client->addr; msg[1].flags = I2C_M_RD; msg[1].buf = productid; msg[1].len = 10; ret = i2c_transfer(ts->client->adapter, msg, 2); if (ret < 0) { printk(KERN_ERR "%s: i2c_transfer failed\n", __func__); goto get_module_id_error; } productid[10] = '\0'; ret = strict_strtoul(&productid[9], 10, &module_id); if (ret) { pr_err("%s : transfer error\n",__func__); goto get_module_id_error; } RMI4_disable_program(ts->client); return (u8)module_id; get_module_id_error: RMI4_disable_program(ts->client); return -1; } static u8 get_config_version(void) { struct i2c_msg msg[2]; char configver[5]; int ret ; unsigned long config_ver = 0; msg[0].addr = ts->client->addr; msg[0].flags = 0; msg[0].buf = &fd_34.controlBase; msg[0].len = 1; msg[1].addr = ts->client->addr; msg[1].flags = I2C_M_RD; msg[1].buf = configver; msg[1].len = 4; ret = i2c_transfer(ts->client->adapter, msg, 2); if (ret < 0) { printk(KERN_ERR "%s: i2c_transfer failed\n", __func__); return -1; } configver[4] = '\0'; ret = strict_strtoul(configver, 10, &config_ver); if (ret < 0) { pr_err("%s : transfer fail\n",__func__); return -1; } return (u8)config_ver; } static int proc_calc_metrics(char *page, char **start, off_t off, int count, int *eof, int len) { if (len <= off + count) *eof = 1; *start = page + off; len -= off; if (len > count) len = count; if (len < 0) len = 0; return len; } static void tp_read_fn34_input_name(void) { query_name[0] = 1; query_name[1] = 1; query_name[2] = get_module_id(); query_name[3] = get_config_version(); } static int tp_read_input_name(void) { int ret; query_i2c_msg_name[0].addr = ts->client->addr; query_i2c_msg_name[0].flags = 0; query_i2c_msg_name[0].buf = &fd_01.queryBase; query_i2c_msg_name[0].len = 1; query_i2c_msg_name[1].addr = ts->client->addr; query_i2c_msg_name[1].flags = I2C_M_RD; query_i2c_msg_name[1].buf = query_name; query_i2c_msg_name[1].len = sizeof(query_name); ret = i2c_transfer(ts->client->adapter, query_i2c_msg_name, 2); if (ret < 0) { printk(KERN_ERR "%s: i2c_transfer failed at address $%02X \n", __func__, ts->client->addr); } return ret; } static int tp_read_proc( char *page, char **start, off_t off, int count, int *eof, void *data) { int len; len = snprintf(page, PAGE_SIZE, "TP_TYPE:" "%s\n" "Manufacturer ID:" "%x\n" " Product Properties:" "%x\n" "Customer Family:%x\n" "Firmware Revision:%x\n", "synapitcs",query_name[0], query_name[1], query_name[2], query_name[3]); return proc_calc_metrics(page, start, off, count, eof, len); } static int synaptics_rmi4_probe(struct i2c_client *client, const struct i2c_device_id *id) { int i ; int ret = 0; struct proc_dir_entry *d_entry; struct touch_hw_platform_data *touch_pdata = NULL; struct tp_resolution_conversion tp_type_self_check = {0}; printk("*************** synaptics_rmi4_probe ******************\n"); printk("Client adress is: %02X", client->addr); if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)){ printk(KERN_ERR "%s: need I2C_FUNC_I2C\n", __func__); ret = -ENODEV; goto err_check_functionality_failed; } TS_DEBUG_RMI("the i2c_check_functionality is ok \n"); touch_pdata = client->dev.platform_data; if(NULL == touch_pdata) { printk("the touch_pdata is NULL please check the init code !\n"); ret = -ENOMEM; goto err_platform_data_init_failed; } if(touch_pdata->read_touch_probe_flag) { ret = touch_pdata->read_touch_probe_flag(); } if(ret){ printk(KERN_ERR "%s: the touch driver has detected :) \n", __func__); return -1; } else { printk(KERN_ERR "%s: it's the first touch driver! \n", __func__); } if(touch_pdata->touch_power){ ret = touch_pdata->touch_power(1); } if(ret){ printk(KERN_ERR "%s: power on failed \n", __func__); ret = -ENOMEM; printk(KERN_ERR "111111111"); goto err_power_on_failed; } /*move touch_reset function from in get_phone_version function to outside */ if (touch_pdata->touch_reset()){ ret = touch_pdata->touch_reset(); if (ret){ printk(KERN_ERR "%s: reset failed \n", __func__); printk(KERN_ERR "22222222222"); goto err_power_on_failed; } } if(touch_pdata->get_phone_version){ ret = touch_pdata->get_phone_version(&tp_type_self_check); if(ret < 0){ printk(KERN_ERR "%s: reset failed \n", __func__); printk(KERN_ERR "33333333333"); goto err_power_on_failed; } else { lcd_x = tp_type_self_check.lcd_x; lcd_y = tp_type_self_check.lcd_y; lcd_all = tp_type_self_check.lcd_all; } } ts = kzalloc(sizeof(*ts), GFP_KERNEL); if (ts == NULL){ printk(KERN_ERR "%s: check zalloc failed!\n", __func__); ret = -ENOMEM; goto err_alloc_data_failed; } synaptics_wq = create_singlethread_workqueue("synaptics_wq"); if (!synaptics_wq){ printk(KERN_ERR "Could not create work queue synaptics_wq: no memory"); ret = -ENOMEM; goto error_wq_creat_failed; } INIT_WORK(&ts->work, synaptics_rmi4_work_func); ts->is_support_multi_touch = client->flags; ts->client = client; i2c_set_clientdata(client, ts); ret = synaptics_rmi4_read_pdt(ts); if(touch_pdata->set_touch_probe_flag){ touch_pdata->set_touch_probe_flag(ret); } if (ret <= 0){ if (ret == 0) printk(KERN_ERR "Empty PDT\n"); printk(KERN_ERR "Error identifying device (%d)\n", ret); ret = -ENODEV; goto err_pdt_read_failed; } #ifdef CONFIG_SYNAPTICS_UPDATE_RMI_TS_FIRMWARE g_client = client; for (i = 0 ; i < 3; i++) { ret= ts_firmware_file(); if (!ret) { break; } } #endif /* CONFIG_SYNAPTICS_UPDATE_RMI_TS_FIRMWARE */ ts_x_max = ts->f11_max_x; ts_y_max = ts->f11_max_y; get_ic_name(); if ((3200 == touch_ic_name)||(2202 == touch_ic_name)) { tp_read_fn34_input_name(); } else { ret = tp_read_input_name(); if(!ret) { printk("the tp input name is query error!\n "); } } d_entry = create_proc_entry("tp_hw_type", S_IRUGO | S_IWUSR | S_IWGRP, NULL); if (d_entry) { d_entry->read_proc = tp_read_proc; d_entry->data = NULL; } { TS_DEBUG_RMI("the ReportingMode is changged ok!\n"); } ts->input_dev = input_allocate_device(); if (!ts->input_dev) { printk(KERN_ERR "failed to allocate input device.\n"); ret = -EBUSY; goto err_alloc_dev_failed; } ts->input_dev->name = "synaptics"; dev_set_drvdata(&(ts->input_dev->dev), ts); ts->input_dev->phys = client->name; set_bit(EV_ABS, ts->input_dev->evbit); set_bit(EV_SYN, ts->input_dev->evbit); set_bit(EV_KEY, ts->input_dev->evbit); set_bit(BTN_TOUCH, ts->input_dev->keybit); set_bit(ABS_X, ts->input_dev->absbit); set_bit(ABS_Y, ts->input_dev->absbit); set_bit(KEY_NUMLOCK, ts->input_dev->keybit); set_bit(INPUT_PROP_DIRECT,ts->input_dev->propbit); ret = input_register_device(ts->input_dev); if (ret) { printk(KERN_ERR "synaptics_rmi4_probe: Unable to register %s \ input device\n", ts->input_dev->name); ret = -ENODEV; goto err_input_register_device_failed; } else { TS_DEBUG_RMI("synaptics input device registered\n"); } if (ts->hasF11) { #ifdef CONFIG_ARCH_MSM7X27 if (machine_is_msm7x27a_M660()) { if (ts->f11.points_supported > 2) { point_supported_huawei = 2; } else { point_supported_huawei = ts->f11.points_supported; } } else { if (ts->f11.points_supported > 5) { point_supported_huawei = 5; } else { point_supported_huawei = ts->f11.points_supported; } } #endif #ifdef CONFIG_ARCH_MSM7X30 if (machine_is_msm8255_c8860()) { if(HW_VER_SUB_VC == get_hw_sub_board_id()) { if (ts->f11.points_supported > 2) { point_supported_huawei = 2; } else { point_supported_huawei = ts->f11.points_supported; } } else { if (ts->f11.points_supported > 5) { point_supported_huawei = 5; } else { point_supported_huawei = ts->f11.points_supported; } } } else { if (ts->f11.points_supported > 5) { point_supported_huawei = 5; } else { point_supported_huawei = ts->f11.points_supported; } } #endif for (i = 0; i < ts->f11.points_supported; ++i) { if(ts->is_support_multi_touch) { input_set_abs_params(ts->input_dev, ABS_MT_TRACKING_ID, 1, ts->f11.points_supported, 0, 0); input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, 0, lcd_x - 1, 0, 0); input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, 0, lcd_y - 1, 0, 0); input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 0xF, 0, 0); input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MINOR, 0, 0xF, 0, 0); input_set_abs_params(ts->input_dev, ABS_MT_ORIENTATION, 0, 1, 0, 0); input_set_abs_params(ts->input_dev, ABS_MT_PRESSURE, 0, 255, 0, 0); } else { input_set_abs_params(ts->input_dev, ABS_X, 0, lcd_x-1, 0, 0); input_set_abs_params(ts->input_dev, ABS_Y, 0, lcd_y-1, 0, 0); input_set_abs_params(ts->input_dev, ABS_PRESSURE, 0, 255, 0, 0); } } if (ts->hasEgrPalmDetect) set_bit(BTN_DEAD, ts->input_dev->keybit); if (ts->hasEgrFlick) { set_bit(REL_X, ts->input_dev->keybit); set_bit(REL_Y, ts->input_dev->keybit); } if (ts->hasEgrSingleTap) set_bit(BTN_TOUCH, ts->input_dev->keybit); if (ts->hasEgrDoubleTap) set_bit(BTN_TOOL_DOUBLETAP, ts->input_dev->keybit); } if (ts->hasF19) { set_bit(BTN_DEAD, ts->input_dev->keybit); } if (ts->hasF30) { for (i = 0; i < ts->f30.points_supported; ++i) { set_bit(BTN_F30 + i, ts->input_dev->keybit); } } if(touch_pdata->touch_gpio_config_interrupt) { ret = touch_pdata->touch_gpio_config_interrupt(); } if (client->irq) { gpio_request(client->irq, client->name); gpio_direction_input(client->irq); TS_DEBUG_RMI("Requesting IRQ...\n"); if (request_irq(client->irq, synaptics_rmi4_irq_handler, IRQF_TRIGGER_LOW, client->name, ts) >= 0) { TS_DEBUG_RMI("Received IRQ!\n"); ts->use_irq = 1; #if 0 if (set_irq_wake(client->irq, 1) < 0) printk(KERN_ERR "failed to set IRQ wake\n"); #endif } else { TS_DEBUG_RMI("Failed to request IRQ!\n"); } } if (!ts->use_irq) { printk(KERN_ERR "Synaptics RMI4 device %s in polling mode\n", client->name); hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); ts->timer.function = synaptics_rmi4_timer_func; hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL); } ts->enable = 1; dev_set_drvdata(&ts->input_dev->dev, ts); if (sysfs_create_file(&ts->input_dev->dev.kobj, &dev_attr_synaptics_rmi4_enable.attr) < 0) printk("failed to create sysfs file for input device\n"); #ifdef CONFIG_HAS_EARLYSUSPEND ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; ts->early_suspend.suspend = synaptics_rmi4_early_suspend; ts->early_suspend.resume = synaptics_rmi4_late_resume; register_early_suspend(&ts->early_suspend); #endif printk(KERN_ERR "probingX for Synaptics RMI4 device %s at $%02X...\n", client->name, client->addr); #ifdef CONFIG_HUAWEI_HW_DEV_DCT set_hw_dev_flag(DEV_I2C_TOUCH_PANEL); #endif return 0; err_input_register_device_failed: if(NULL != ts->input_dev) input_free_device(ts->input_dev); err_pdt_read_failed: err_alloc_dev_failed: error_wq_creat_failed: if (synaptics_wq) { destroy_workqueue(synaptics_wq); } if (synaptics_wq != NULL) synaptics_wq = NULL; if(NULL != ts) kfree(ts); err_alloc_data_failed: err_check_functionality_failed: /* can't use the flag ret here, it will change the return value of probe function */ touch_pdata->touch_power(0); /* delete 3 lines */ err_platform_data_init_failed: err_power_on_failed: TS_DEBUG_RMI("THE POWER IS FAILED!!!\n"); return ret; } static int synaptics_rmi4_remove(struct i2c_client *client) { struct synaptics_rmi4 *ts = i2c_get_clientdata(client); unregister_early_suspend(&ts->early_suspend); if (ts->use_irq) free_irq(client->irq, ts); else hrtimer_cancel(&ts->timer); input_unregister_device(ts->input_dev); kfree(ts); return 0; } static int synaptics_rmi4_suspend(struct i2c_client *client, pm_message_t mesg) { int ret; struct synaptics_rmi4 *ts = i2c_get_clientdata(client); /* if use interrupt disable the irq ,else disable timer */ if (ts->use_irq) disable_irq_nosync(client->irq); else hrtimer_cancel(&ts->timer); ret = cancel_work_sync(&ts->work); if (ret && ts->use_irq) /* if work was pending disable-count is now 2 */ { enable_irq(client->irq); printk(KERN_ERR "synaptics_ts_suspend: can't cancel the work ,so enable the irq \n"); } ret = i2c_smbus_write_byte_data(client, fd_01.controlBase, 0x01); //use control base to set tp sleep if(ret < 0) { printk(KERN_ERR "synaptics_ts_suspend: the touch can't get into deep sleep \n"); } ts->enable = 0; return 0; } static int synaptics_rmi4_resume(struct i2c_client *client) { int ret; struct synaptics_rmi4 *ts = i2c_get_clientdata(client); ret = i2c_smbus_write_byte_data(ts->client, fd_01.controlBase, 0x00); //use control base to set tp wakeup if(ret < 0) { printk(KERN_ERR "synaptics_ts_resume: the touch can't resume! \n"); } mdelay(50); if (ts->use_irq) { enable_irq(client->irq); } else hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL); printk(KERN_ERR "synaptics_rmi4_touch is resume!\n"); return 0; } #ifdef CONFIG_HAS_EARLYSUSPEND static void synaptics_rmi4_early_suspend(struct early_suspend *h) { struct synaptics_rmi4 *ts; ts = container_of(h, struct synaptics_rmi4, early_suspend); synaptics_rmi4_suspend(ts->client, PMSG_SUSPEND); } static void synaptics_rmi4_late_resume(struct early_suspend *h) { struct synaptics_rmi4 *ts; ts = container_of(h, struct synaptics_rmi4, early_suspend); synaptics_rmi4_resume(ts->client); } #endif /*add the update firmware progrom*/ #ifdef CONFIG_SYNAPTICS_UPDATE_RMI_TS_FIRMWARE struct RMI4_FDT{ unsigned char m_QueryBase; unsigned char m_CommandBase; unsigned char m_ControlBase; unsigned char m_DataBase; unsigned char m_IntSourceCount; unsigned char m_ID; }; static int RMI4_read_PDT(struct i2c_client *client) { // Read config data struct RMI4_FDT temp_buf; struct RMI4_FDT m_PdtF34Flash; struct RMI4_FDT m_PdtF01Common; struct i2c_msg msg[2]; unsigned short start_addr; int ret = 0; memset(&m_PdtF34Flash,0,sizeof(struct RMI4_FDT)); memset(&m_PdtF01Common,0,sizeof(struct RMI4_FDT)); for(start_addr = 0xe9; start_addr > 10; start_addr -= sizeof(struct RMI4_FDT)) { msg[0].addr = client->addr; msg[0].flags = 0; msg[0].len = 1; msg[0].buf = (unsigned char *)&start_addr; msg[1].addr = client->addr; msg[1].flags = I2C_M_RD; msg[1].len = sizeof(struct RMI4_FDT); msg[1].buf = (unsigned char *)&temp_buf; if(i2c_transfer(client->adapter, msg, 2) < 0) { printk("%s:%d: read RIM4 PDT error!\n",__FUNCTION__,__LINE__); return -1; } if(temp_buf.m_ID == 0x34) { memcpy(&m_PdtF34Flash,&temp_buf,sizeof(struct RMI4_FDT )); } else if(temp_buf.m_ID == 0x01) { memcpy(&m_PdtF01Common,&temp_buf,sizeof(struct RMI4_FDT )); } else if (temp_buf.m_ID == 0) //end of PDT { break; } } if((m_PdtF01Common.m_CommandBase != fd_01.commandBase) || (m_PdtF34Flash.m_QueryBase != fd_34.queryBase)) { printk("%s:%d: RIM4 PDT has changed!!!\n",__FUNCTION__,__LINE__); ret = synaptics_rmi4_read_pdt(ts); if(ret < 0) { printk("read pdt error:!\n"); return -1; } return 0; } return 0; } //to be improved ....... int RMI4_wait_attn(struct i2c_client * client,int udleay) { int loop_count=0; int ret=0; do{ mdelay(udleay); ret = i2c_smbus_read_byte_data(client,fd_34.dataBase+18);//read Flash Control // Clear the attention assertion by reading the interrupt status register i2c_smbus_read_byte_data(client,fd_01.dataBase+1);//read the irq Interrupt Status }while(loop_count++ < 0x10 && (ret != 0x80)); if(loop_count >= 0x10) { SYNAPITICS_DEBUG("RMI4 wait attn timeout:ret=0x%x\n",ret); return -1; } return 0; } int RMI4_disable_program(struct i2c_client *client) { unsigned char cdata; unsigned int loop_count=0; printk("RMI4 disable program...\n"); // Issue a reset command i2c_smbus_write_byte_data(client,fd_01.commandBase,0x01); // Wait for ATTN to be asserted to see if device is in idle state RMI4_wait_attn(client,20); // Read F01 Status flash prog, ensure the 6th bit is '0' do{ cdata = i2c_smbus_read_byte_data(client,fd_01.dataBase); udelay(2); } while(((cdata & 0x40) != 0) && (loop_count++ < 10)); //Rescan the Page Description Table return RMI4_read_PDT(client); } static int RMI4_enable_program(struct i2c_client *client) { unsigned short bootloader_id = 0 ; int ret = -1; printk("RMI4 enable program...\n"); // Read and write bootload ID bootloader_id = i2c_smbus_read_word_data(client,fd_34.queryBase); i2c_smbus_write_word_data(client,fd_34.dataBase+2,bootloader_id);//write Block Data 0 // Issue Enable flash command if(i2c_smbus_write_byte_data(client, fd_34.dataBase+18, 0x0F) < 0) //write Flash Control { SYNAPITICS_DEBUG("RMI enter flash mode error\n"); return -1; } ret = RMI4_wait_attn(client,12); //Rescan the Page Description Table RMI4_read_PDT(client); return ret; } static unsigned long ExtractLongFromHeader(const unsigned char* SynaImage) { return((unsigned long)SynaImage[0] + (unsigned long)SynaImage[1]*0x100 + (unsigned long)SynaImage[2]*0x10000 + (unsigned long)SynaImage[3]*0x1000000); } static int RMI4_check_firmware(struct i2c_client *client,const unsigned char *pgm_data) { unsigned long checkSumCode; unsigned long m_firmwareImgSize; unsigned long m_configImgSize; unsigned short m_bootloadImgID; unsigned short bootloader_id; const unsigned char *SynaFirmware; unsigned char m_firmwareImgVersion; unsigned short UI_block_count; unsigned short CONF_block_count; unsigned short fw_block_size; SynaFirmware = pgm_data; checkSumCode = ExtractLongFromHeader(&(SynaFirmware[0])); m_bootloadImgID = (unsigned int)SynaFirmware[4] + (unsigned int)SynaFirmware[5]*0x100; m_firmwareImgVersion = SynaFirmware[7]; m_firmwareImgSize = ExtractLongFromHeader(&(SynaFirmware[8])); m_configImgSize = ExtractLongFromHeader(&(SynaFirmware[12])); UI_block_count = i2c_smbus_read_word_data(client,fd_34.queryBase+5);//read Firmware Block Count 0 fw_block_size = i2c_smbus_read_word_data(client,fd_34.queryBase+3);//read Block Size 0 CONF_block_count = i2c_smbus_read_word_data(client,fd_34.queryBase+7);//read Configuration Block Count 0 bootloader_id = i2c_smbus_read_word_data(client,fd_34.queryBase); return (m_firmwareImgVersion != 0 || bootloader_id == m_bootloadImgID) ? 0 : -1; } static int RMI4_write_image(struct i2c_client *client,unsigned char type_cmd,const unsigned char *pgm_data) { unsigned short block_size; unsigned short img_blocks; unsigned short block_index; const unsigned char * p_data; int i; block_size = i2c_smbus_read_word_data(client,fd_34.queryBase+3);//read Block Size 0 switch(type_cmd ) { case 0x02: img_blocks = i2c_smbus_read_word_data(client,fd_34.queryBase+5); //read UI Firmware break; case 0x06: img_blocks = i2c_smbus_read_word_data(client,fd_34.queryBase+7); //read Configuration Block Count 0 break; default: SYNAPITICS_DEBUG("image type error\n"); goto error; } p_data = pgm_data; for(block_index = 0; block_index < img_blocks; ++block_index) { printk("#"); if(i2c_smbus_write_word_data(client, fd_34.dataBase,block_index) < 0) { SYNAPITICS_DEBUG("write block number error\n"); goto error; } for(i=0;i<block_size;i++) { if(i2c_smbus_write_byte_data(client, fd_34.dataBase+2+i, *(p_data+i)) < 0) //write Block Data { SYNAPITICS_DEBUG("RMI4_write_image: block %d data 0x%x error\n",block_index,*p_data); goto error; } udelay(15); } p_data += block_size; if(i2c_smbus_write_word_data(client, fd_34.dataBase+18, type_cmd) < 0) //write Flash Control { SYNAPITICS_DEBUG("issue write command error\n"); goto error; } if(RMI4_wait_attn(client,5) != 0) { goto error; } } return 0; error: return -1; } static int RMI4_program_configuration(struct i2c_client *client,const unsigned char *pgm_data ) { int ret; unsigned short block_size; unsigned short ui_blocks; printk("\nRMI4 program Config firmware...\n"); block_size = i2c_smbus_read_word_data(client,fd_34.queryBase+3);//read Block Size 0 ui_blocks = i2c_smbus_read_word_data(client,fd_34.queryBase+5); //read Firmware Block Count 0 if(RMI4_write_image(client, 0x06,pgm_data+ui_blocks*block_size ) < 0) { SYNAPITICS_DEBUG("write configure image error\n"); return -1; } ret = i2c_smbus_read_byte_data(client,fd_34.dataBase+18); //read Flash Control return ((ret & 0xF0) == 0x80 ? 0 : ret); } static int RMI4_program_firmware(struct i2c_client *client,const unsigned char *pgm_data) { int ret=0; unsigned short bootloader_id; printk("RMI4 program UI firmware...\n"); bootloader_id = i2c_smbus_read_word_data(client,fd_34.queryBase); i2c_smbus_write_word_data(client,fd_34.dataBase+2, bootloader_id ); //write Block Data0 if(i2c_smbus_write_byte_data(client, fd_34.dataBase+18, 0x03) < 0) //write Flash Control { SYNAPITICS_DEBUG("RMI4_program_firmware error, erase firmware error \n"); return -1; } mdelay(1000); RMI4_wait_attn(client,300); if((ret = i2c_smbus_read_byte_data(client,fd_34.dataBase+18)) != 0x80) //check Flash Control { return -1; } if( RMI4_write_image(client,0x02,pgm_data) <0 ) { SYNAPITICS_DEBUG("write UI firmware error!\n"); return -1; } ret = i2c_smbus_read_byte_data(client,fd_34.dataBase+18); //read Flash Control return ((ret & 0xF0) == 0x80 ? 0 : ret); } static int synaptics_download(struct i2c_client *client,const unsigned char *pgm_data) { int ret; ret = RMI4_read_PDT(client); if(ret != 0) { printk("RMI page func check error\n"); return -1; } ret = RMI4_enable_program(client); if( ret != 0) { printk("%s:%d:RMI enable program error,return...\n",__FUNCTION__,__LINE__); goto error; } ret = RMI4_check_firmware(client,pgm_data); if( ret != 0) { printk("%s:%d:RMI check firmware error,return...\n",__FUNCTION__,__LINE__); goto error; } ret = RMI4_program_firmware(client, pgm_data + 0x100); if( ret != 0) { printk("%s:%d:RMI program firmware error,return...",__FUNCTION__,__LINE__); goto error; } RMI4_program_configuration(client, pgm_data + 0x100); return RMI4_disable_program(client); error: RMI4_disable_program(client); printk("%s:%d:error,return ....",__FUNCTION__,__LINE__); return -1; } static int i2c_update_firmware(struct i2c_client *client) { char *buf; struct file *filp; struct inode *inode = NULL; mm_segment_t oldfs; uint16_t length; int ret = 0; const char filename[]="/sdcard/update/synaptics.img"; oldfs = get_fs(); set_fs(KERNEL_DS); filp = filp_open(filename, O_RDONLY, S_IRUSR); if (IS_ERR(filp)) { printk("%s: file %s filp_open error\n", __FUNCTION__,filename); set_fs(oldfs); return -1; } if (!filp->f_op) { printk("%s: File Operation Method Error\n", __FUNCTION__); filp_close(filp, NULL); set_fs(oldfs); return -1; } inode = filp->f_path.dentry->d_inode; if (!inode) { printk("%s: Get inode from filp failed\n", __FUNCTION__); filp_close(filp, NULL); set_fs(oldfs); return -1; } length = i_size_read(inode->i_mapping->host); if (!( length > 0 && length < 62*1024 )) { printk("file size error\n"); filp_close(filp, NULL); set_fs(oldfs); return -1; } buf = vmalloc(length+(length%2)); /* buf size if even */ if (!buf) { printk("alloctation memory failed\n"); filp_close(filp, NULL); set_fs(oldfs); return -1; } if (filp->f_op->read(filp, buf, length, &filp->f_pos) != length) { printk("%s: file read error\n", __FUNCTION__); filp_close(filp, NULL); set_fs(oldfs); vfree(buf); return -1; } ret = synaptics_download(client,buf); filp_close(filp, NULL); set_fs(oldfs); vfree(buf); return ret; } static int ts_firmware_file(void) { int ret; struct kobject *kobject_ts; kobject_ts = kobject_create_and_add("touch_screen", NULL); if (!kobject_ts) { printk("create kobjetct error!\n"); return -1; } ret = sysfs_create_file(kobject_ts, &update_firmware_attribute.attr); if (ret) { kobject_put(kobject_ts); printk("create file error\n"); return -1; } return 0; } /* * The "update_firmware" file where a static variable is read from and written to. */ static ssize_t update_firmware_show(struct kobject *kobj, struct kobj_attribute *attr,char *buf) { return 1; } static ssize_t update_firmware_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) { char ret = -1; printk("#################update_firmware_store######################\n"); if ( (buf[0] == '2')&&(buf[1] == '\0') ) { /* driver detect its device */ ret = i2c_smbus_read_byte_data(g_client, fd_01.queryBase); printk("The if of synaptics device is : %d\n",ret); disable_irq(g_client->irq); /*update firmware*/ ret = i2c_update_firmware(g_client); enable_irq(g_client->irq); if( 0 != ret ) { printk("Update firmware failed!\n"); ret = -1; } else { printk("Update firmware success!\n"); arm_pm_restart(0,&ret); ret = 1; } } return ret; } #endif static const struct i2c_device_id synaptics_ts_id[] = { { "Synaptics_rmi", 0 }, { } }; static struct i2c_driver synaptics_rmi4_driver = { .probe = synaptics_rmi4_probe, .remove = synaptics_rmi4_remove, #ifndef CONFIG_HAS_EARLYSUSPEND .suspend = synaptics_rmi4_suspend, .resume = synaptics_rmi4_resume, #endif .id_table = synaptics_ts_id, .driver = { .name = "Synaptics_rmi", }, }; static int __devinit synaptics_rmi4_init(void) { return i2c_add_driver(&synaptics_rmi4_driver); } static void __exit synaptics_rmi4_exit(void) { i2c_del_driver(&synaptics_rmi4_driver); if (synaptics_wq) destroy_workqueue(synaptics_wq); } module_init(synaptics_rmi4_init); module_exit(synaptics_rmi4_exit); MODULE_DESCRIPTION("Synaptics RMI4 Driver"); MODULE_LICENSE("GPL");