summaryrefslogtreecommitdiff
path: root/ANDROID_3.4.5/drivers/input/touchscreen
diff options
context:
space:
mode:
Diffstat (limited to 'ANDROID_3.4.5/drivers/input/touchscreen')
-rw-r--r--ANDROID_3.4.5/drivers/input/touchscreen/Kconfig24
-rw-r--r--ANDROID_3.4.5/drivers/input/touchscreen/Makefile16
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/AW5306_Base.bbin0 -> 41612 bytes
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/AW5306_Clb.bbin0 -> 32804 bytes
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/AW5306_Drv.bbin0 -> 114476 bytes
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/AW5306_Drv.h158
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/AW5306_Reg.h187
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/AW5306_ts.c1614
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/AW5306_userpara.c196
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/AW5306_userpara.h99
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/Kconfig11
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/Makefile35
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/irq_gpio.c149
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/irq_gpio.h13
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/cyp140_ts/Kconfig16
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/cyp140_ts/Makefile33
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/cyp140_ts/cyp140_i2c.c1412
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/cyp140_ts/cyttsp.h696
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/cyp140_ts/cyttsp_fw_upgrade.c993
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/cyp140_ts/debug.txt3
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/cyp140_ts/wmt_ts.c1094
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/cyp140_ts/wmt_ts.h120
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/ft5x0x/Kconfig11
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/ft5x0x/Makefile34
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/ft5x0x/ft5402_config.c2295
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/ft5x0x/ft5402_config.h71
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/ft5x0x/ft5402_ini_config.h411
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/ft5x0x/ft5x0x.c937
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/ft5x0x/ft5x0x.h207
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/ft5x0x/ft5x0x_upg.c506
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/ft5x0x/ini.c406
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/ft5x0x/ini.h43
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/Kconfig11
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/Makefile34
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/focaltech_ctl.h27
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ft5402_config.c2295
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ft5402_config.h71
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ft5402_ini_config.h411
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ft5x0x.c896
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ft5x0x.h205
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ft5x0x_upg.c506
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ft6x06_ex_fun.c1021
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ft6x06_ex_fun.h79
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ft6x06_ts.c511
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ft6x06_ts.h52
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ini.c406
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ini.h43
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/gsl1680_ts/Kconfig16
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/gsl1680_ts/Makefile33
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/gsl1680_ts/gslX680.c1416
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/gsl1680_ts/gslX680.h35
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/gsl1680_ts/gsl_point_id.bbin0 -> 38321 bytes
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/gsl1680_ts/wmt_ts.c1102
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/gsl1680_ts/wmt_ts.h117
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/gt9xx_ts/Kconfig11
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/gt9xx_ts/Makefile34
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/gt9xx_ts/goodix_tool.c615
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/gt9xx_ts/gt9xx.c2163
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/gt9xx_ts/gt9xx.h278
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/gt9xx_ts/gt9xx_firmware.h6
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/gt9xx_ts/gt9xx_update.c1939
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/icn83xx_ts/Kconfig16
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/icn83xx_ts/Makefile32
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/icn83xx_ts/flash.c973
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/icn83xx_ts/icn83xx.c2034
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/icn83xx_ts/icn83xx.h434
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/icn83xx_ts/icn83xx_fw.h3
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/icn85xx_ts/Kconfig16
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/icn85xx_ts/Makefile32
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/icn85xx_ts/icn85xx.c2431
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/icn85xx_ts/icn85xx.h500
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/icn85xx_ts/icn85xx_flash.c1050
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/icn85xx_ts/icn85xx_fw.h2517
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/lw86x0_ts/Kconfig11
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/lw86x0_ts/Makefile34
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/lw86x0_ts/lw86x0_ts.c1321
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/lw86x0_ts/lw86x0_ts.h53
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/lw86x0_ts/wmt_ts.c1165
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/lw86x0_ts/wmt_ts.h98
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/metusb/Makefile33
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/metusb/metusb.c856
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/semisens/Makefile33
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/semisens/sn310m-touch-pdata.h201
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/semisens/sn310m-touch.c332
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/semisens/sn310m-touch.h97
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/semisens/touch.c1121
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/semisens/touch.h54
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/sis_usbhid_ts/Kconfig16
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/sis_usbhid_ts/Makefile32
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/sis_usbhid_ts/hid-sis.c1104
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/sitronix/Kconfig11
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/sitronix/Makefile34
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/sitronix/irq_gpio.c148
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/sitronix/irq_gpio.h13
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/sitronix/sitronix_i2c.c817
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/sitronix/sitronix_i2c.h137
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/ssd253x_ts/Kconfig16
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/ssd253x_ts/Makefile32
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/ssd253x_ts/ssd253x-ts.c1827
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/ssd253x_ts/ssd253x-ts.h28
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/ssd253x_ts/wmt_ts.c810
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/ssd253x_ts/wmt_ts.h116
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/vt1609_ts/Makefile4
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/vt1609_ts/vt1609_dual.c692
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/vt1609_ts/vt1609_ts.c1481
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/vt1609_ts/vt1609_ts.h301
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/zet6221_ts/Kconfig16
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/zet6221_ts/Makefile32
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/zet6221_ts/wmt_ts.c833
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/zet6221_ts/wmt_ts.h149
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/zet6221_ts/zet6221_downloader.c1209
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/zet6221_ts/zet6221_i2c.c2786
-rwxr-xr-xANDROID_3.4.5/drivers/input/touchscreen/zet6221_ts/zet6221_ts.h6
113 files changed, 54220 insertions, 0 deletions
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/Kconfig b/ANDROID_3.4.5/drivers/input/touchscreen/Kconfig
index 1e7c563c..873ca6c3 100644
--- a/ANDROID_3.4.5/drivers/input/touchscreen/Kconfig
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/Kconfig
@@ -851,4 +851,28 @@ config TOUCHSCREEN_TPS6507X
To compile this driver as a module, choose M here: the
module will be called tps6507x_ts.
+config TOUCHSCREEN_VT1609
+ tristate "Vt1609 Dual-touch Support,Compatible with Vt1603a Single-touch"
+ default y
+ depends on ARCH_WMT
+ help
+ Say Y here if you have a vt1603a single or vt1609 dual touchscreen and
+ want to enable support for the built-in touchscreen.
+
+ To compile this driver as a module, choose M here: the
+ module will be called vt1609_dual_ts.
+
+source "drivers/input/touchscreen/gsl1680_ts/Kconfig"
+source "drivers/input/touchscreen/sitronix/Kconfig"
+source "drivers/input/touchscreen/zet6221_ts/Kconfig"
+source "drivers/input/touchscreen/cyp140_ts/Kconfig"
+source "drivers/input/touchscreen/ft5x0x/Kconfig"
+source "drivers/input/touchscreen/ft6x0x/Kconfig"
+source "drivers/input/touchscreen/aw5306_ts/Kconfig"
+source "drivers/input/touchscreen/ssd253x_ts/Kconfig"
+source "drivers/input/touchscreen/lw86x0_ts/Kconfig"
+source "drivers/input/touchscreen/gt9xx_ts/Kconfig"
+source "drivers/input/touchscreen/icn83xx_ts/Kconfig"
+source "drivers/input/touchscreen/icn85xx_ts/Kconfig"
+source "drivers/input/touchscreen/sis_usbhid_ts/Kconfig"
endif
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/Makefile b/ANDROID_3.4.5/drivers/input/touchscreen/Makefile
index 175d6414..b632eb48 100644
--- a/ANDROID_3.4.5/drivers/input/touchscreen/Makefile
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/Makefile
@@ -70,3 +70,19 @@ obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o
obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o
obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o
obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o
+
+obj-$(CONFIG_TOUCHSCREEN_VT1609) += vt1609_ts/
+#GSL1680 touchscreen
+obj-$(CONFIG_TOUCHSCREEN_GSL1680) += gsl1680_ts/
+obj-$(CONFIG_TOUCHSCREEN_SITRONIX) += sitronix/
+obj-$(CONFIG_TOUCHSCREEN_ZET6221) += zet6221_ts/
+obj-$(CONFIG_TOUCHSCREEN_CYP140) += cyp140_ts/
+obj-$(CONFIG_TOUCHSCREEN_FT5X0X) += ft5x0x/
+obj-$(CONFIG_TOUCHSCREEN_FT6X0X) += ft6x0x/
+obj-$(CONFIG_TOUCHSCREEN_AW5306) += aw5306_ts/
+obj-$(CONFIG_TOUCHSCREEN_SSD253X) += ssd253x_ts/
+obj-$(CONFIG_TOUCHSCREEN_LW86X0) += lw86x0_ts/
+obj-$(CONFIG_TOUCHSCREEN_GT9XX) += gt9xx_ts/
+obj-$(CONFIG_TOUCHSCREEN_ICN83XX) += icn83xx_ts/
+obj-$(CONFIG_TOUCHSCREEN_ICN85XX) += icn85xx_ts/
+obj-$(CONFIG_TOUCHSCREEN_SIS) += sis_usbhid_ts/
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/AW5306_Base.b b/ANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/AW5306_Base.b
new file mode 100755
index 00000000..e3e6c22a
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/AW5306_Base.b
Binary files differ
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/AW5306_Clb.b b/ANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/AW5306_Clb.b
new file mode 100755
index 00000000..40e49326
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/AW5306_Clb.b
Binary files differ
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/AW5306_Drv.b b/ANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/AW5306_Drv.b
new file mode 100755
index 00000000..03f070a1
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/AW5306_Drv.b
Binary files differ
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/AW5306_Drv.h b/ANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/AW5306_Drv.h
new file mode 100755
index 00000000..47042361
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/AW5306_Drv.h
@@ -0,0 +1,158 @@
+/**************************************************************************
+* AW5306_Drv.h
+*
+* AW5306 Driver code version 1.0
+*
+* Create Date : 2012/06/25
+*
+* Modify Date :
+*
+* Create by : wuhaijun
+*
+**************************************************************************/
+
+#ifndef AW5306_DRV_H
+
+#define AW5306_DRV_H
+
+#define Release_Ver 219
+
+
+#define MAX_POINT 5
+
+#define NUM_TX 21 // TX number of TOUCH IC
+#define NUM_RX 12 // RX number of TOUCH IC
+
+//#define NEWBASE_PROCESS //new base process need test!!!
+
+#define ABS(X) ((X > 0) ? (X) : (-X))
+
+
+typedef enum{
+ RawDataMode = 0,
+ DeltaMode,
+ MonitorMode
+}enumWorkMode;
+
+typedef enum{
+ BASE_INITIAL,
+ BASE_FAST_TRACE,
+ BASE_STABLE,
+ TEMP_DRIFT
+} CompensateMode;
+
+typedef struct {
+ unsigned short Base[NUM_TX][NUM_RX];
+ unsigned short ChipBase[NUM_TX][NUM_RX];
+ signed char Flag[NUM_TX][NUM_RX];
+ signed char BaseCnt[NUM_TX][NUM_RX];
+ unsigned char CompensateFlag;
+ unsigned char TraceTempIncCnt;
+ unsigned char TraceTempDecCnt;
+ unsigned char CompensateStateFrameCnt;
+ short LastMaxDiff;
+ CompensateMode CompensateState;
+ unsigned int InitialFrameCnt;
+ unsigned char PosBigAreaTouchFlag;
+ unsigned char NegBigAreaTouchFlag;
+ unsigned char BigAreaFirstFlag;
+ unsigned char BigAreaChangeFlag;
+ unsigned short BigTouchFrame;
+ unsigned short FrameCnt;
+ unsigned char LongStableCnt;
+ unsigned char PosPeakCnt;
+ unsigned char NegPeakCnt;
+ unsigned char PeakCheckFrameCnt;
+ unsigned char BaseFrozen;
+ unsigned char PosPeakCompensateCnt[MAX_POINT];
+ unsigned char NegPeakCompensateCnt[MAX_POINT];
+}STRUCTBASE;
+
+typedef struct {
+ unsigned char Peak[MAX_POINT][2];
+ unsigned char LastPeak[MAX_POINT][2];
+ unsigned char NegPeak[MAX_POINT][2];
+ unsigned char CurrentPointNum;
+ unsigned char CurrentNegPointNum;
+ unsigned char LastPointNum;
+}STRUCTPEAK;
+
+typedef struct {
+ unsigned short X,Y; // X,Y coordinate
+ unsigned char PointID; // Assigned point ID
+ unsigned char Event; // Event of current point
+}STRUCTPOINT;
+
+typedef struct {
+ STRUCTPOINT PointInfo[MAX_POINT];
+ STRUCTPOINT RptPoint[MAX_POINT];
+ unsigned char PointNum;
+ unsigned char LastPointNum;
+ unsigned char NegPointNum;
+ unsigned char FilterPointCnt;
+ unsigned char FirstLiftUpFlag;
+ unsigned char TouchStatus;
+ unsigned char PointHoldCnt[MAX_POINT];
+ unsigned char PointPressCnt[MAX_POINT];
+
+}STRUCTFRAME;
+
+typedef struct {
+ unsigned char fileflag[14];
+ unsigned char TXOFFSET[(NUM_TX+1)/2];
+ unsigned char RXOFFSET[(NUM_RX+1)/2];
+ unsigned char TXCAC[NUM_TX];
+ unsigned char RXCAC[NUM_RX];
+ unsigned char TXGAIN[NUM_TX];
+ short SOFTOFFSET[NUM_TX][NUM_RX];
+}STRUCTCALI;
+
+#define NOISE_LISTENING 0
+#define NOISE_SCAN 1
+#define NOISE_FREQ_JUMP 2
+#define NOISE_SEEK_FAIL 3
+
+#define NOISE_FRM_NORMAL 0
+#define NOISE_FRM_PRE_MEASURE 1
+#define NOISE_FRM_MEASURE 2
+
+typedef struct {
+ unsigned char AllFrmCnt; // Frame counter to generate noise meaure frame indicator
+ unsigned char NoiseFrmCnt; // Frame counter for noise level checking
+ unsigned char IdleFrmCnt; // No touch frame counter
+ unsigned char State; // Noise checking state: LISTENING, SCAN, JUMP
+ unsigned char FrmState; // Frame type indicator: PRE_MEAUSRE, MEAUSRE, NORMAL
+ short NoiseNormal; // Noise in working freq
+ short NoiseScan; // Noise in scan freq
+ short Better_NoiseScan; //pfx:smaller Noise in Scan freq
+ unsigned char Better_ScanFreqID; //pfx:the Scan Freq for the smaller Noise
+ unsigned char ScanFreqID; // Scan freq ID
+ unsigned char WorkFreqID; // Current freq ID
+ short NoiseTh1; // Diff threshold for noise too high judgement
+ char JumpTh; // frame number threshold for freq jumping
+ char FailedFreqList [32]; // Searched freq indicator for freq scanning
+}STRUCTNOISE;
+
+
+void AW5306_TP_Init(void);
+void AW5306_TP_Reinit(void);
+void AW5306_Sleep(void);
+char AW5306_TouchProcess(void);
+void AW5306_ChargeMode(char mode);
+unsigned char AW5306_GetPointNum(void);
+unsigned char AW5306_GetPeakNum(void);
+char AW5306_GetPoint(int *x,int *y, int *id, int *event,char Index);
+void AW5306_GetBase(unsigned short *data, char x,char y);
+void AW5306_GetDiff(short *data, char x,char y);
+char AW5306_GetPeak(unsigned char *x,unsigned char *y,unsigned char Index);
+char AW5306_GetNegPeak(unsigned char *x,unsigned char *y,unsigned char Index);
+char AW5306_GetCalcPoint(unsigned short *x,unsigned short *y,unsigned char Index);
+char AW5306_CLB(void);
+void AW5306_CLB_GetCfg(void);
+void AW5306_CLB_WriteCfg(void);
+void TP_Force_Calibration(void);
+void FreqScan(unsigned char BaseFreq);
+
+
+
+#endif
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/AW5306_Reg.h b/ANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/AW5306_Reg.h
new file mode 100755
index 00000000..2bbbeb00
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/AW5306_Reg.h
@@ -0,0 +1,187 @@
+/**************************************************************************
+* AW5306_Reg.h
+*
+* AW5306 Driver code version 1.0
+*
+* Create Date : 2012/06/25
+*
+* Modify Date :
+*
+* Create by : wuhaijun
+*
+**************************************************************************/
+
+#ifndef AW5306_REG_H
+
+#define AW5306_REG_H
+
+#define SA_PAGE 0x00
+#define SA_IDRST 0x01
+#define SA_CTRL 0x02
+#define SA_SCANMD 0x03
+#define SA_IER 0x04
+#define SA_RX_NUM 0x05
+#define SA_RX_START 0x06
+#define SA_TX_NUM 0x07
+#define SA_TX_INDEX0 0x08
+#define SA_TX_INDEX1 0x09
+#define SA_TX_INDEX2 0x0A
+#define SA_TX_INDEX3 0x0B
+#define SA_TX_INDEX4 0x0C
+#define SA_TX_INDEX5 0x0D
+#define SA_TX_INDEX6 0x0E
+#define SA_TX_INDEX7 0x0F
+#define SA_TX_INDEX8 0x10
+#define SA_TX_INDEX9 0x11
+#define SA_TX_INDEX10 0x12
+#define SA_TX_INDEX11 0x13
+#define SA_TX_INDEX12 0x14
+#define SA_TX_INDEX13 0x15
+#define SA_TX_INDEX14 0x16
+#define SA_TX_INDEX15 0x17
+#define SA_TX_INDEX16 0x18
+#define SA_TX_INDEX17 0x19
+#define SA_TX_INDEX18 0x1A
+#define SA_TX_INDEX19 0x1B
+#define SA_TX_INDEX20 0x1C
+#define SA_TXCAC0 0x1D
+#define SA_TXCAC1 0x1E
+#define SA_TXCAC2 0x1F
+#define SA_TXCAC3 0x20
+#define SA_TXCAC4 0x21
+#define SA_TXCAC5 0x22
+#define SA_TXCAC6 0x23
+#define SA_TXCAC7 0x24
+#define SA_TXCAC8 0x25
+#define SA_TXCAC9 0x26
+#define SA_TXCAC10 0x27
+#define SA_TXCAC11 0x28
+#define SA_TXCAC12 0x29
+#define SA_TXCAC13 0x2A
+#define SA_TXCAC14 0x2B
+#define SA_TXCAC15 0x2C
+#define SA_TXCAC16 0x2D
+#define SA_TXCAC17 0x2E
+#define SA_TXCAC18 0x2F
+#define SA_TXCAC19 0x30
+#define SA_TXCAC20 0x31
+#define SA_TXOFFSET0 0x32
+#define SA_TXOFFSET1 0x33
+#define SA_TXOFFSET2 0x34
+#define SA_TXOFFSET3 0x35
+#define SA_TXOFFSET4 0x36
+#define SA_TXOFFSET5 0x37
+#define SA_TXOFFSET6 0x38
+#define SA_TXOFFSET7 0x39
+#define SA_TXOFFSET8 0x3A
+#define SA_TXOFFSET9 0x3B
+#define SA_TXOFFSET10 0x3C
+#define SA_RXCAC0 0x3E
+#define SA_RXCAC1 0x3F
+#define SA_RXCAC2 0x40
+#define SA_RXCAC3 0x41
+#define SA_RXCAC4 0x42
+#define SA_RXCAC5 0x43
+#define SA_RXCAC6 0x44
+#define SA_RXCAC7 0x45
+#define SA_RXCAC8 0x46
+#define SA_RXCAC9 0x47
+#define SA_RXCAC10 0x48
+#define SA_RXCAC11 0x49
+#define SA_RXOFFSET0 0x4A
+#define SA_RXOFFSET1 0x4B
+#define SA_RXOFFSET2 0x4C
+#define SA_RXOFFSET3 0x4D
+#define SA_RXOFFSET4 0x4E
+#define SA_RXOFFSET5 0x4F
+#define SA_DRV_VLT 0x51
+#define SA_SCANFREQ1 0x52
+#define SA_SCANFREQ2 0x53
+#define SA_SCANFREQ3 0x54
+#define SA_TXADCGAIN0 0x55
+#define SA_TXADCGAIN1 0x56
+#define SA_TXADCGAIN2 0x57
+#define SA_TXADCGAIN3 0x58
+#define SA_TXADCGAIN4 0x59
+#define SA_TXADCGAIN5 0x5A
+#define SA_TXADCGAIN6 0x5B
+#define SA_TXADCGAIN7 0x5C
+#define SA_TXADCGAIN8 0x5D
+#define SA_TXADCGAIN9 0x5E
+#define SA_TXADCGAIN10 0x5F
+#define SA_TXADCGAIN11 0x60
+#define SA_TXADCGAIN12 0x61
+#define SA_TXADCGAIN13 0x62
+#define SA_TXADCGAIN14 0x63
+#define SA_TXADCGAIN15 0x64
+#define SA_TXADCGAIN16 0x65
+#define SA_TXADCGAIN17 0x66
+#define SA_TXADCGAIN18 0x67
+#define SA_TXADCGAIN19 0x68
+#define SA_TXADCGAIN20 0x69
+#define SA_WAITTIME 0x6A
+#define SA_TCLKDLY 0x6B
+#define SA_FINEADJ 0x6C
+#define SA_TXCLKFREQ 0x6D
+#define SA_SCANTIM 0x6E
+#define SA_READSEL 0x70
+#define SA_ISR 0x71
+#define SA_STATE1 0x72
+#define SA_POSCNT 0x73
+#define SA_NEGCNT 0x74
+#define SA_VLDNUM 0x75
+#define SA_ADDRH 0x7D
+#define SA_ADDRL 0x7E
+#define SA_RAWDATA 0x7F
+////////////////////////
+// Page 2
+////////////////////////
+#define SA_SINETABE1 0x03
+#define SA_SINETABE2 0x04
+#define SA_DATAOFFSET 0x05
+#define SA_TRACECTRL1 0x10
+#define SA_TRACECTRL2 0x11
+#define SA_TRACECTRL3 0x12
+#define SA_TRACEST 0x13
+#define SA_RPTNEGTH 0x14
+#define SA_RPTPOSTH 0x15
+#define SA_TRACESTEP 0x16
+#define SA_TRCLVLLO 0x17
+#define SA_TRCLVLPOSHI 0x18
+#define SA_TRCLVLNEGHI 0x19
+#define SA_TRACEINTERVAL 0x1A
+#define SA_RXSTABLETH 0x1B
+#define SA_POSLEVELTH 0x1C
+#define SA_POSNUMTH 0x1D
+#define SA_NEGLEVELTH 0x1E
+#define SA_NEGNUMTH 0x1F
+#define SA_BIGPOINTTH 0x20
+#define SA_BIGPOSTIMTH 0x21
+#define SA_BIGNEGTIMTH 0x22
+#define SA_NEGTIMTH 0x23
+#define SA_TRACEHIGHTIM 0x24
+#define SA_INITPNTTH 0x25
+#define SA_TCHCLRTIMSET 0x26
+#define SA_INITLVTH 0x27
+#define SA_MAXCHKTH 0x28
+#define SA_MINCHKTH 0x29
+#define SA_INITFORCEQUIT 0x2A
+#define SA_CHAMPCFG 0x30
+#define SA_ADCCFG 0x31
+#define SA_IBCFG1 0x32
+#define SA_IBCFG2 0x33
+#define SA_LDOCFG 0x34
+#define SA_OSCCFG1 0x35
+#define SA_OSCCFG2 0x36
+#define SA_OSCCFG3 0x37
+#define SA_EN_CLK_QNTZ1 0x38
+#define SA_EN_CLK_QNTZ2 0x39
+#define SA_CPFREQ 0x3A
+#define SA_ATEST1 0x3B
+#define SA_ATEST2 0x3C
+#define SA_RAMTST 0x60
+#define SA_TESTCFG 0x61
+#define SA_TSTDATAH 0x62
+#define SA_TSTDATAL 0x63
+#endif
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/AW5306_ts.c b/ANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/AW5306_ts.c
new file mode 100755
index 00000000..f623c646
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/AW5306_ts.c
@@ -0,0 +1,1614 @@
+/*
+ * drivers/input/touchscreen/aw5306/aw5306.c
+ *
+ * FocalTech aw5306 TouchScreen driver.
+ *
+ * Copyright (c) 2010 Focal tech Ltd.
+ *
+ * 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.
+ *
+ *
+ * note: only support mulititouch Wenfs 2010-10-01
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <mach/hardware.h>
+#include <linux/platform_device.h>
+#include <linux/suspend.h>
+#include <linux/wait.h>
+#include <asm/uaccess.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <mach/wmt_iomux.h>
+#include <linux/slab.h>
+#include "AW5306_Drv.h"
+#include "AW5306_userpara.h"
+#include "irq_gpio.h"
+
+#define CONFIG_AW5306_MULTITOUCH (1)
+#define DEV_AW5306 "touch_aw5306"
+#define TS_I2C_NAME "aw5306-ts"
+#define AW5306_I2C_ADDR 0x38
+#define AW5306_I2C_BUS 0x01
+
+//#define DEBUG_EN
+
+#undef dbg
+#ifdef DEBUG_EN
+ #define dbg(fmt,args...) printk("DBG:%s_%d:"fmt,__FUNCTION__,__LINE__,##args)
+#else
+ #define dbg(fmt,args...)
+#endif
+
+#undef dbg_err
+#define dbg_err(fmt,args...) printk("ERR:%s_%d:"fmt,__FUNCTION__,__LINE__,##args)
+
+
+
+struct ts_event {
+ int x[5];
+ int y[5];
+ int pressure;
+ int touch_ID[5];
+ int touch_point;
+ int pre_point;
+};
+
+struct AW5306_ts_data {
+ const char *name;
+ struct input_dev *input_dev;
+ struct ts_event event;
+ struct work_struct pen_event_work;
+ struct workqueue_struct *ts_workqueue;
+ struct kobject *kobj;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend early_suspend;
+#endif
+ struct timer_list touch_timer;
+
+ int irq;
+ int irqgpio;
+ int rstgpio;
+
+ int reslx;
+ int resly;
+ int nt;
+ int nb;
+ int xch;
+ int ych;
+ int swap;
+ int dbg;
+ int lcd_exchg;
+};
+
+
+struct AW5306_ts_data *pContext=NULL;
+static struct i2c_client *l_client=NULL;
+static unsigned char suspend_flag=0; //0: sleep out; 1: sleep in
+static short tp_idlecnt = 0;
+static char tp_SlowMode = 0;
+//static struct class *i2c_dev_class;
+
+extern char AW5306_CLB(void);
+extern void AW5306_CLB_GetCfg(void);
+extern STRUCTCALI AW_Cali;
+extern AW5306_UCF AWTPCfg;
+extern STRUCTBASE AW_Base;
+extern short Diff[NUM_TX][NUM_RX];
+extern short adbDiff[NUM_TX][NUM_RX];
+extern short AWDeltaData[32];
+
+char AW_CALI_FILENAME[50] = {0,};
+char AW_UCF_FILENAME[50] = {0,};
+
+extern int wmt_setsyspara(char *varname, unsigned char *varval);
+extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
+
+
+void __aeabi_unwind_cpp_pr0(void)
+{
+}
+
+void __aeabi_unwind_cpp_pr1(void)
+{
+}
+
+
+int AW_nvram_read(char *filename, char *buf, ssize_t len, int offset)
+{
+ struct file *fd;
+ //ssize_t ret;
+ int retLen = -1;
+
+ mm_segment_t old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ fd = filp_open(filename, O_RDONLY, 0);
+
+ if(IS_ERR(fd)) {
+ printk("[AW5306][nvram_read] : failed to open!!\n");
+ return -1;
+ }
+
+ do{
+ if ((fd->f_op == NULL) || (fd->f_op->read == NULL))
+ {
+ printk("[AW5306][nvram_read] : file can not be read!!\n");
+ break;
+ }
+
+ if (fd->f_pos != offset) {
+ if (fd->f_op->llseek) {
+ if(fd->f_op->llseek(fd, offset, 0) != offset) {
+ printk("[AW5306][nvram_read] : failed to seek!!\n");
+ break;
+ }
+ } else {
+ fd->f_pos = offset;
+ }
+ }
+
+ retLen = fd->f_op->read(fd,
+ buf,
+ len,
+ &fd->f_pos);
+
+ }while(false);
+
+ filp_close(fd, NULL);
+
+ set_fs(old_fs);
+
+
+ return retLen;
+}
+
+int AW_nvram_write(char *filename, char *buf, ssize_t len, int offset)
+{
+ struct file *fd;
+ //ssize_t ret;
+ int retLen = -1;
+
+ mm_segment_t old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ fd = filp_open(filename, O_WRONLY|O_CREAT, 0666);
+
+ if(IS_ERR(fd)) {
+ printk("[AW5306][nvram_write] : failed to open!!\n");
+ return -1;
+ }
+
+ do{
+ if ((fd->f_op == NULL) || (fd->f_op->write == NULL))
+ {
+ printk("[AW5306][nvram_write] : file can not be write!!\n");
+ break;
+ } /* End of if */
+
+ if (fd->f_pos != offset) {
+ if (fd->f_op->llseek) {
+ if(fd->f_op->llseek(fd, offset, 0) != offset) {
+ printk("[AW5306][nvram_write] : failed to seek!!\n");
+ break;
+ }
+ } else {
+ fd->f_pos = offset;
+ }
+ }
+
+ retLen = fd->f_op->write(fd,
+ buf,
+ len,
+ &fd->f_pos);
+
+ }while(false);
+
+ filp_close(fd, NULL);
+
+ set_fs(old_fs);
+
+ return retLen;
+}
+
+
+int AW_I2C_WriteByte(u8 addr, u8 para)
+{
+ int ret;
+ u8 buf[3];
+ struct i2c_msg msg[] = {
+ {
+ .addr = l_client->addr,
+ .flags = 0,
+ .len = 2,
+ .buf = buf,
+ },
+ };
+ buf[0] = addr;
+ buf[1] = para;
+ ret = i2c_transfer(l_client->adapter, msg, 1);
+ return ret;
+}
+
+
+unsigned char AW_I2C_ReadByte(u8 addr)
+{
+ int ret;
+ u8 buf[2] = {0};
+ struct i2c_msg msgs[] = {
+ {
+ .addr = l_client->addr,
+ .flags = 0,
+ .len = 1,
+ .buf = buf,
+ },
+ {
+ .addr = l_client->addr,
+ .flags = I2C_M_RD,
+ .len = 1,
+ .buf = buf,
+ },
+ };
+ buf[0] = addr;
+ //msleep(1);
+ ret = i2c_transfer(l_client->adapter, msgs, 2);
+ return buf[0];
+}
+
+unsigned char AW_I2C_ReadXByte( unsigned char *buf, unsigned char addr, unsigned short len)
+{
+ int ret,i;
+ u8 rdbuf[512] = {0};
+ struct i2c_msg msgs[] = {
+ {
+ .addr = l_client->addr,
+ .flags = 0,
+ .len = 1,
+ .buf = rdbuf,
+ },
+ {
+ .addr = l_client->addr,
+ .flags = I2C_M_RD,
+ .len = len,
+ .buf = rdbuf,
+ },
+ };
+ rdbuf[0] = addr;
+ //msleep(1);
+ ret = i2c_transfer(l_client->adapter, msgs, 2);
+ if (ret < 0)
+ pr_err("msg %s i2c read error: %d\n", __func__, ret);
+ for(i = 0; i < len; i++)
+ {
+ buf[i] = rdbuf[i];
+ }
+ return ret;
+}
+
+unsigned char AW_I2C_WriteXByte( unsigned char *buf, unsigned char addr, unsigned short len)
+{
+ int ret,i;
+ u8 wdbuf[512] = {0};
+
+ struct i2c_msg msgs[] = {
+ {
+ .addr = l_client->addr,
+ .flags = 0,
+ .len = len+1,
+ .buf = wdbuf,
+ }
+ };
+
+ wdbuf[0] = addr;
+ for(i = 0; i < len; i++)
+ {
+ wdbuf[i+1] = buf[i];
+ }
+ //msleep(1);
+ ret = i2c_transfer(l_client->adapter, msgs, 1);
+ if (ret < 0)
+ pr_err("msg %s i2c read error: %d\n", __func__, ret);
+ return ret;
+}
+
+
+void AW_Sleep(unsigned int msec)
+{
+ msleep(msec);
+}
+
+static ssize_t AW5306_get_Cali(struct device* cd,struct device_attribute *attr, char* buf);
+static ssize_t AW5306_set_Cali(struct device* cd,struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t AW5306_get_reg(struct device* cd,struct device_attribute *attr, char* buf);
+static ssize_t AW5306_write_reg(struct device* cd,struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t AW5306_get_Base(struct device* cd,struct device_attribute *attr, char* buf);
+static ssize_t AW5306_get_Diff(struct device* cd,struct device_attribute *attr, char* buf);
+static ssize_t AW5306_get_adbBase(struct device* cd,struct device_attribute *attr, char* buf);
+static ssize_t AW5306_get_adbDiff(struct device* cd,struct device_attribute *attr, char* buf);
+static ssize_t AW5306_get_FreqScan(struct device* cd,struct device_attribute *attr, char* buf);
+static ssize_t AW5306_Set_FreqScan(struct device* cd, struct device_attribute *attr,const char* buf, size_t len);
+static ssize_t AW5306_GetUcf(struct device* cd,struct device_attribute *attr, char* buf);
+
+
+
+static DEVICE_ATTR(cali, S_IRUGO | S_IWUGO, AW5306_get_Cali, AW5306_set_Cali);
+static DEVICE_ATTR(readreg, S_IRUGO | S_IWUGO, AW5306_get_reg, AW5306_write_reg);
+static DEVICE_ATTR(base, S_IRUGO | S_IWUSR, AW5306_get_Base, NULL);
+static DEVICE_ATTR(diff, S_IRUGO | S_IWUSR, AW5306_get_Diff, NULL);
+static DEVICE_ATTR(adbbase, S_IRUGO | S_IWUSR, AW5306_get_adbBase, NULL);
+static DEVICE_ATTR(adbdiff, S_IRUGO | S_IWUSR, AW5306_get_adbDiff, NULL);
+static DEVICE_ATTR(freqscan, S_IRUGO | S_IWUGO, AW5306_get_FreqScan, AW5306_Set_FreqScan);
+static DEVICE_ATTR(getucf, S_IRUGO | S_IWUSR, AW5306_GetUcf, NULL);
+
+
+static ssize_t AW5306_get_Cali(struct device* cd,struct device_attribute *attr, char* buf)
+{
+ unsigned char i,j;
+ ssize_t len = 0;
+
+ len += snprintf(buf+len, PAGE_SIZE-len,"AWINIC RELEASE CODE VER = %d\n", Release_Ver);
+
+ len += snprintf(buf+len, PAGE_SIZE-len,"*****AW5306 Calibrate data*****\n");
+ len += snprintf(buf+len, PAGE_SIZE-len,"TXOFFSET:");
+
+ for(i=0;i<11;i++)
+ {
+ len += snprintf(buf+len, PAGE_SIZE-len, "0x%02X ", AW_Cali.TXOFFSET[i]);
+ }
+
+ len += snprintf(buf+len, PAGE_SIZE-len, "\n");
+ len += snprintf(buf+len, PAGE_SIZE-len, "RXOFFSET:");
+
+ for(i=0;i<6;i++)
+ {
+ len += snprintf(buf+len, PAGE_SIZE-len, "0x%02X ", AW_Cali.RXOFFSET[i]);
+ }
+
+ len += snprintf(buf+len, PAGE_SIZE-len, "\n");
+ len += snprintf(buf+len, PAGE_SIZE-len, "TXCAC:");
+
+ for(i=0;i<21;i++)
+ {
+ len += snprintf(buf+len, PAGE_SIZE-len, "0x%02X ", AW_Cali.TXCAC[i]);
+ }
+
+ len += snprintf(buf+len, PAGE_SIZE-len, "\n");
+ len += snprintf(buf+len, PAGE_SIZE-len, "RXCAC:");
+
+ for(i=0;i<12;i++)
+ {
+ len += snprintf(buf+len, PAGE_SIZE-len, "0x%02X ", AW_Cali.RXCAC[i]);
+ }
+
+ len += snprintf(buf+len, PAGE_SIZE-len, "\n");
+ len += snprintf(buf+len, PAGE_SIZE-len, "TXGAIN:");
+
+ for(i=0;i<21;i++)
+ {
+ len += snprintf(buf+len, PAGE_SIZE-len, "0x%02X ", AW_Cali.TXGAIN[i]);
+ }
+
+ len += snprintf(buf+len, PAGE_SIZE-len, "\n");
+
+ for(i=0;i<AWTPCfg.TX_LOCAL;i++)
+ {
+ for(j=0;j<AWTPCfg.RX_LOCAL;j++)
+ {
+ len += snprintf(buf+len, PAGE_SIZE-len, "%4d ", AW_Cali.SOFTOFFSET[i][j]);
+ }
+ len += snprintf(buf+len, PAGE_SIZE-len, "\n");
+ }
+ return len;
+
+}
+
+static ssize_t AW5306_set_Cali(struct device* cd,struct device_attribute *attr, const char* buf, size_t count)
+{
+ struct AW5306_ts_data *data = i2c_get_clientdata(l_client);
+
+ unsigned long on_off = simple_strtoul(buf, NULL, 10);
+
+ if(on_off == 1)
+ {
+ #ifdef INTMODE
+ wmt_disable_gpirq(data ->irqgpio);
+ AW5306_Sleep();
+ suspend_flag = 1;
+ AW_Sleep(50);
+
+ TP_Force_Calibration();
+
+ AW5306_TP_Reinit();
+ wmt_enable_gpirq(data->irqgpio);
+ suspend_flag = 0;
+
+ #else
+ suspend_flag = 1;
+ AW_Sleep(50);
+
+ TP_Force_Calibration();
+
+ AW5306_TP_Reinit();
+ tp_idlecnt = 0;
+ tp_SlowMode = 0;
+ suspend_flag = 0;
+ data->touch_timer.expires = jiffies + HZ/AWTPCfg.FAST_FRAME;
+ add_timer(&data->touch_timer);
+ #endif
+ }
+
+ return count;
+}
+
+
+static ssize_t AW5306_get_adbBase(struct device* cd,struct device_attribute *attr, char* buf)
+{
+ unsigned char i,j;
+ ssize_t len = 0;
+
+ len += snprintf(buf+len, PAGE_SIZE-len, "base: \n");
+ for(i=0;i< AWTPCfg.TX_LOCAL;i++)
+ {
+ for(j=0;j<AWTPCfg.RX_LOCAL;j++)
+ {
+ len += snprintf(buf+len, PAGE_SIZE-len, "%4d, ",AW_Base.Base[i][j]+AW_Cali.SOFTOFFSET[i][j]);
+ }
+ len += snprintf(buf+len, PAGE_SIZE-len, "\n");
+ }
+
+ return len;
+}
+
+static ssize_t AW5306_get_Base(struct device* cd,struct device_attribute *attr, char* buf)
+{
+ unsigned char i,j;
+ ssize_t len = 0;
+
+ *(buf+len) = AWTPCfg.TX_LOCAL;
+ len++;
+ *(buf+len) = AWTPCfg.RX_LOCAL;
+ len++;
+
+ for(i=0;i< AWTPCfg.TX_LOCAL;i++)
+ {
+ for(j=0;j<AWTPCfg.RX_LOCAL;j++)
+ {
+ *(buf+len) = (char)(((AW_Base.Base[i][j]+AW_Cali.SOFTOFFSET[i][j]) & 0xFF00)>>8);
+ len++;
+ *(buf+len) = (char)((AW_Base.Base[i][j]+AW_Cali.SOFTOFFSET[i][j]) & 0x00FF);
+ len++;
+ }
+ }
+ return len;
+
+}
+
+static ssize_t AW5306_get_adbDiff(struct device* cd,struct device_attribute *attr, char* buf)
+{
+ unsigned char i,j;
+ ssize_t len = 0;
+
+ len += snprintf(buf+len, PAGE_SIZE-len, "Diff: \n");
+ for(i=0;i< AWTPCfg.TX_LOCAL;i++)
+ {
+ for(j=0;j<AWTPCfg.RX_LOCAL;j++)
+ {
+ len += snprintf(buf+len, PAGE_SIZE-len, "%4d, ",adbDiff[i][j]);
+ }
+ len += snprintf(buf+len, PAGE_SIZE-len, "\n");
+ }
+
+ return len;
+}
+
+static ssize_t AW5306_get_Diff(struct device* cd,struct device_attribute *attr, char* buf)
+{
+ unsigned char i,j;
+ ssize_t len = 0;
+
+ *(buf+len) = AWTPCfg.TX_LOCAL;
+ len++;
+ *(buf+len) = AWTPCfg.RX_LOCAL;
+ len++;
+
+ for(i=0;i< AWTPCfg.TX_LOCAL;i++)
+ {
+ for(j=0;j<AWTPCfg.RX_LOCAL;j++)
+ {
+ *(buf+len) = (char)((adbDiff[i][j] & 0xFF00)>>8);
+ len++;
+ *(buf+len) = (char)(adbDiff[i][j] & 0x00FF);
+ len++;
+ }
+ }
+ return len;
+}
+
+static ssize_t AW5306_get_FreqScan(struct device* cd,struct device_attribute *attr, char* buf)
+{
+ unsigned char i;
+ ssize_t len = 0;
+
+ for(i=0;i< 32;i++)
+ {
+ //*(buf+len) = (char)((AWDeltaData[i] & 0xFF00)>>8);
+ //len++;
+ //*(buf+len) = (char)(AWDeltaData[i] & 0x00FF);
+ //len++;
+ len += snprintf(buf+len, PAGE_SIZE-len, "%4d, ",AWDeltaData[i]);
+ }
+
+ len += snprintf(buf+len, PAGE_SIZE-len, "\n");
+ return len;
+}
+
+static ssize_t AW5306_Set_FreqScan(struct device* cd, struct device_attribute *attr,
+ const char* buf, size_t len)
+{
+ struct AW5306_ts_data *data = i2c_get_clientdata(l_client);
+ unsigned long Basefreq = simple_strtoul(buf, NULL, 10);
+
+ if(Basefreq < 16)
+ {
+ #ifdef INTMODE
+ wmt_disable_gpirq(data ->irqgpio);
+ AW5306_Sleep();
+ suspend_flag = 1;
+ AW_Sleep(50);
+
+ FreqScan(Basefreq);
+
+ AW5306_TP_Reinit();
+ wmt_enable_gpirq(data ->irqgpio);
+ suspend_flag = 0;
+ #else
+ suspend_flag = 1;
+ AW_Sleep(50);
+
+ FreqScan(Basefreq);
+
+ AW5306_TP_Reinit();
+ tp_idlecnt = 0;
+ tp_SlowMode = 0;
+ suspend_flag = 0;
+ data->touch_timer.expires = jiffies + HZ/AWTPCfg.FAST_FRAME;
+ add_timer(&data->touch_timer);
+ #endif
+ }
+
+ return len;
+}
+
+static ssize_t AW5306_get_reg(struct device* cd,struct device_attribute *attr, char* buf)
+{
+ struct AW5306_ts_data *data = i2c_get_clientdata(l_client);
+ u8 reg_val[128];
+ ssize_t len = 0;
+ u8 i;
+
+ if(suspend_flag != 1)
+ {
+#ifdef INTMODE
+ wmt_disable_gpirq(data ->irqgpio);
+ AW5306_Sleep();
+ suspend_flag = 1;
+ AW_Sleep(50);
+
+ AW_I2C_ReadXByte(reg_val,0,127);
+
+ AW5306_TP_Reinit();
+ wmt_enable_gpirq(data->irqgpio);
+ suspend_flag = 0;
+#else
+ suspend_flag = 1;
+
+ AW_Sleep(50);
+
+ AW_I2C_ReadXByte(reg_val,0,127);
+
+ AW5306_TP_Reinit();
+ tp_idlecnt = 0;
+ tp_SlowMode = 0;
+ suspend_flag = 0;
+ data->touch_timer.expires = jiffies + HZ/AWTPCfg.FAST_FRAME;
+ add_timer(&data->touch_timer);
+#endif
+ }
+ else
+ {
+ AW_I2C_ReadXByte(reg_val,0,127);
+ }
+ for(i=0;i<0x7F;i++)
+ {
+ len += snprintf(buf+len, PAGE_SIZE-len, "reg%02X = 0x%02X, ", i,reg_val[i]);
+ }
+
+ return len;
+
+}
+
+static ssize_t AW5306_write_reg(struct device* cd,struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct AW5306_ts_data *data = i2c_get_clientdata(l_client);
+ int databuf[2];
+
+ if(2 == sscanf(buf, "%d %d", &databuf[0], &databuf[1]))
+ {
+ if(suspend_flag != 1)
+ {
+ #ifdef INTMODE
+ wmt_disable_gpirq(data ->irqgpio);
+ AW5306_Sleep();
+ suspend_flag = 1;
+ AW_Sleep(50);
+
+ AW_I2C_WriteByte((u8)databuf[0],(u8)databuf[1]);
+
+ AW5306_TP_Reinit();
+ //ctp_enable_irq();
+ wmt_enable_gpirq(data->irqgpio);
+ suspend_flag = 0;
+ #else
+ suspend_flag = 1;
+ AW_Sleep(50);
+
+ AW_I2C_WriteByte((u8)databuf[0],(u8)databuf[1]);
+
+ AW5306_TP_Reinit();
+ tp_idlecnt = 0;
+ tp_SlowMode = 0;
+ suspend_flag = 0;
+ data->touch_timer.expires = jiffies + HZ/AWTPCfg.FAST_FRAME;
+ add_timer(&data->touch_timer);
+ #endif
+ }
+ else
+ {
+ AW_I2C_WriteByte((u8)databuf[0],(u8)databuf[1]);
+ }
+ }
+ else
+ {
+ printk("invalid content: '%s', length = %d\n", buf, count);
+ }
+ return count;
+}
+
+static ssize_t AW5306_GetUcf(struct device* cd,struct device_attribute *attr, char* buf)
+{
+ ssize_t len = 0;
+
+ len += snprintf(buf+len, PAGE_SIZE-len,"*****AW5306 UCF DATA*****\n");
+ len += snprintf(buf+len, PAGE_SIZE-len,"%d,%d,\n",AWTPCfg.TX_LOCAL,AWTPCfg.RX_LOCAL);
+ len += snprintf(buf+len, PAGE_SIZE-len,"(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d}\n",
+ AWTPCfg.TX_ORDER[0],AWTPCfg.TX_ORDER[1],AWTPCfg.TX_ORDER[2],AWTPCfg.TX_ORDER[3],AWTPCfg.TX_ORDER[4],
+ AWTPCfg.TX_ORDER[5],AWTPCfg.TX_ORDER[6],AWTPCfg.TX_ORDER[7],AWTPCfg.TX_ORDER[8],AWTPCfg.TX_ORDER[9],
+ AWTPCfg.TX_ORDER[10],AWTPCfg.TX_ORDER[11],AWTPCfg.TX_ORDER[12],AWTPCfg.TX_ORDER[13],AWTPCfg.TX_ORDER[14],
+ AWTPCfg.TX_ORDER[15],AWTPCfg.TX_ORDER[16],AWTPCfg.TX_ORDER[17],AWTPCfg.TX_ORDER[19],AWTPCfg.TX_ORDER[19],
+ AWTPCfg.TX_ORDER[20]);
+ len += snprintf(buf+len, PAGE_SIZE-len,"{%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d},\n",
+ AWTPCfg.RX_ORDER[0],AWTPCfg.RX_ORDER[1],AWTPCfg.RX_ORDER[2],AWTPCfg.RX_ORDER[3],
+ AWTPCfg.RX_ORDER[4],AWTPCfg.RX_ORDER[5],AWTPCfg.RX_ORDER[6],AWTPCfg.RX_ORDER[7],
+ AWTPCfg.RX_ORDER[8],AWTPCfg.RX_ORDER[9],AWTPCfg.RX_ORDER[10],AWTPCfg.RX_ORDER[11]);
+ len += snprintf(buf+len, PAGE_SIZE-len,"%d,%d,\n",AWTPCfg.RX_START,AWTPCfg.HAVE_KEY_LINE);
+ len += snprintf(buf+len, PAGE_SIZE-len,"{%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d},\n",
+ AWTPCfg.KeyLineValid[0],AWTPCfg.KeyLineValid[1],AWTPCfg.KeyLineValid[2],AWTPCfg.KeyLineValid[3],
+ AWTPCfg.KeyLineValid[4],AWTPCfg.KeyLineValid[5],AWTPCfg.KeyLineValid[6],AWTPCfg.KeyLineValid[7],
+ AWTPCfg.KeyLineValid[8],AWTPCfg.KeyLineValid[9],AWTPCfg.KeyLineValid[10],AWTPCfg.KeyLineValid[11]);
+ len += snprintf(buf+len, PAGE_SIZE-len,"%d,%d,\n",AWTPCfg.MAPPING_MAX_X,AWTPCfg.MAPPING_MAX_Y);
+ len += snprintf(buf+len, PAGE_SIZE-len,"%d,%d,\n",AWTPCfg.GainClbDeltaMax,AWTPCfg.GainClbDeltaMin);
+ len += snprintf(buf+len, PAGE_SIZE-len,"%d,%d,\n",AWTPCfg.KeyLineDeltaMax,AWTPCfg.KeyLineDeltaMin);
+ len += snprintf(buf+len, PAGE_SIZE-len,"%d,%d,\n",AWTPCfg.OffsetClbExpectedMax,AWTPCfg.OffsetClbExpectedMin);
+ len += snprintf(buf+len, PAGE_SIZE-len,"%d,%d,\n",AWTPCfg.RawDataDeviation,AWTPCfg.CacMultiCoef);
+ len += snprintf(buf+len, PAGE_SIZE-len,"%d,%d,\n",AWTPCfg.RawDataCheckMin,AWTPCfg.RawDataCheckMax);
+ len += snprintf(buf+len, PAGE_SIZE-len,"%d,%d,%d,\n",AWTPCfg.FLYING_TH,AWTPCfg.MOVING_TH,AWTPCfg.MOVING_ACCELER);
+ len += snprintf(buf+len, PAGE_SIZE-len,"%d,%d,\n",AWTPCfg.PEAK_TH,AWTPCfg.GROUP_TH);
+ len += snprintf(buf+len, PAGE_SIZE-len,"%d,%d,%d,\n",AWTPCfg.BIGAREA_TH,AWTPCfg.BIGAREA_CNT,AWTPCfg.BIGAREA_FRESHCNT);
+ len += snprintf(buf+len, PAGE_SIZE-len,"%d,%d,%d,\n",AWTPCfg.CACULATE_COEF,AWTPCfg.FIRST_CALI,AWTPCfg.RAWDATA_DUMP_SWITCH);
+ len += snprintf(buf+len, PAGE_SIZE-len,"%d,%d,0x%x,\n",AWTPCfg.MULTI_SCANFREQ,AWTPCfg.BASE_FREQ,AWTPCfg.FREQ_OFFSET);
+ len += snprintf(buf+len, PAGE_SIZE-len,"0x%x,0x%x,0x%x,\n",AWTPCfg.WAIT_TIME,AWTPCfg.CHAMP_CFG,AWTPCfg.POSLEVEL_TH);
+ len += snprintf(buf+len, PAGE_SIZE-len,"%d,\n",AWTPCfg.ESD_PROTECT);
+ len += snprintf(buf+len, PAGE_SIZE-len,"%d,%d,%d,%d,%d,\n",AWTPCfg.MARGIN_COMPENSATE,AWTPCfg.MARGIN_COMP_DATA_UP,
+ AWTPCfg.MARGIN_COMP_DATA_DOWN,AWTPCfg.MARGIN_COMP_DATA_LEFT,AWTPCfg.MARGIN_COMP_DATA_RIGHT);
+ len += snprintf(buf+len, PAGE_SIZE-len,"%d,%d,%d,%d,\n",AWTPCfg.POINT_RELEASEHOLD,AWTPCfg.MARGIN_RELEASEHOLD,
+ AWTPCfg.POINT_PRESSHOLD,AWTPCfg.KEY_PRESSHOLD);
+ len += snprintf(buf+len, PAGE_SIZE-len,"%d,%d,%d,\n",AWTPCfg.PEAK_ROW_COMPENSATE,AWTPCfg.PEAK_COL_COMPENSATE,
+ AWTPCfg.PEAK_COMPENSATE_COEF);
+ len += snprintf(buf+len, PAGE_SIZE-len,"%d,%d,\n",AWTPCfg.LCD_NOISE_PROCESS,AWTPCfg.LCD_NOISETH);
+ len += snprintf(buf+len, PAGE_SIZE-len,"%d,%d,\n",AWTPCfg.FALSE_PEAK_PROCESS,AWTPCfg.FALSE_PEAK_TH);
+ len += snprintf(buf+len, PAGE_SIZE-len,"%d,%d,\n",AWTPCfg.STABLE_DELTA_X,AWTPCfg.STABLE_DELTA_Y);
+ len += snprintf(buf+len, PAGE_SIZE-len,"%d,%d,%d,\n",AWTPCfg.DEBUG_LEVEL,AWTPCfg.FAST_FRAME,AWTPCfg.SLOW_FRAME);
+ len += snprintf(buf+len, PAGE_SIZE-len,"%d,%d,\n",AWTPCfg.GAIN_CLB_SEPERATE,AWTPCfg.MARGIN_PREFILTER);
+ len += snprintf(buf+len, PAGE_SIZE-len,"%d,%d,\n",AWTPCfg.BIGAREA_HOLDPOINT,AWTPCfg.CHARGE_NOISE);
+ len += snprintf(buf+len, PAGE_SIZE-len,"%d,%d,\n",AWTPCfg.FREQ_JUMP,AWTPCfg.PEAK_VALID_CHECK);
+ len += snprintf(buf+len, PAGE_SIZE-len,"%d,%d,\n",AWTPCfg.WATER_REMOVE,AWTPCfg.INT_MODE);
+
+ return len;
+
+}
+
+
+static int AW5306_create_sysfs(struct i2c_client *client)
+{
+ int err;
+ struct device *dev = &(client->dev);
+
+ //TS_DBG("%s", __func__);
+
+ err = device_create_file(dev, &dev_attr_cali);
+ err = device_create_file(dev, &dev_attr_readreg);
+ err = device_create_file(dev, &dev_attr_base);
+ err = device_create_file(dev, &dev_attr_diff);
+ err = device_create_file(dev, &dev_attr_adbbase);
+ err = device_create_file(dev, &dev_attr_adbdiff);
+ err = device_create_file(dev, &dev_attr_freqscan);
+ err = device_create_file(dev, &dev_attr_getucf);
+ return err;
+}
+
+static void AW5306_ts_release(void)
+{
+ struct AW5306_ts_data *data = pContext;
+#ifdef CONFIG_AW5306_MULTITOUCH
+ #ifdef TOUCH_KEY_SUPPORT
+ if(1 == key_tp){
+ if(key_val == 1){
+ input_report_key(data->input_dev, KEY_MENU, 0);
+ input_sync(data->input_dev);
+ }
+ else if(key_val == 2){
+ input_report_key(data->input_dev, KEY_BACK, 0);
+ input_sync(data->input_dev);
+ // printk("===KEY 2 upupupupupu===++=\n");
+ }
+ else if(key_val == 3){
+ input_report_key(data->input_dev, KEY_SEARCH, 0);
+ input_sync(data->input_dev);
+ // printk("===KEY 3 upupupupupu===++=\n");
+ }
+ else if(key_val == 4){
+ input_report_key(data->input_dev, KEY_HOMEPAGE, 0);
+ input_sync(data->input_dev);
+ // printk("===KEY 4 upupupupupu===++=\n");
+ }
+ else if(key_val == 5){
+ input_report_key(data->input_dev, KEY_VOLUMEDOWN, 0);
+ input_sync(data->input_dev);
+ // printk("===KEY 5 upupupupupu===++=\n");
+ }
+ else if(key_val == 6){
+ input_report_key(data->input_dev, KEY_VOLUMEUP, 0);
+ input_sync(data->input_dev);
+ // printk("===KEY 6 upupupupupu===++=\n");
+ }
+// input_report_key(data->input_dev, key_val, 0);
+ //printk("Release Key = %d\n",key_val);
+ //printk("Release Keyi+++++++++++++++++++++++++++++\n");
+ } else{
+ input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, 0);
+ }
+ #else
+ input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, 0);
+ #endif
+
+#else
+ input_report_abs(data->input_dev, ABS_PRESSURE, 0);
+ input_report_key(data->input_dev, BTN_TOUCH, 0);
+#endif
+
+ input_mt_sync(data->input_dev);
+ input_sync(data->input_dev);
+ return;
+
+}
+
+
+static void Point_adjust(int *x, int *y)
+{
+ struct AW5306_ts_data *AW5306_ts = pContext;
+ int temp;
+
+ if (AW5306_ts->swap) {
+ temp = *x;
+ *x = *y;
+ *y = temp;
+ }
+ if (AW5306_ts->xch)
+ *x = AW5306_ts->reslx - *x;
+ if (AW5306_ts->ych)
+ *y = AW5306_ts->resly - *y;
+
+ if (AW5306_ts->lcd_exchg) {
+ int tmp;
+ tmp = *x;
+ *x = *y;
+ *y = AW5306_ts->reslx - tmp;
+ }
+}
+
+
+static int AW5306_read_data(void)
+{
+ struct AW5306_ts_data *data = pContext;
+ struct ts_event *event = &data->event;
+ int Pevent;
+ int i = 0;
+
+ AW5306_TouchProcess();
+
+ //memset(event, 0, sizeof(struct ts_event));
+ event->touch_point = AW5306_GetPointNum();
+
+ for(i=0;i<event->touch_point;i++)
+ {
+ AW5306_GetPoint(&event->x[i],&event->y[i],&event->touch_ID[i],&Pevent,i);
+ //swap(event->x[i], event->y[i]);
+ Point_adjust(&event->x[i], &event->y[i]);
+// printk("key%d = %d,%d,%d \n",i,event->x[i],event->y[i],event->touch_ID[i] );
+ }
+
+ if (event->touch_point == 0)
+ {
+ if(tp_idlecnt <= AWTPCfg.FAST_FRAME*5)
+ {
+ tp_idlecnt++;
+ }
+ if(tp_idlecnt > AWTPCfg.FAST_FRAME*5)
+ {
+ tp_SlowMode = 1;
+ }
+
+ if (event->pre_point != 0)
+ {
+ AW5306_ts_release();
+ event->pre_point = 0;
+ }
+ return 1;
+ }
+ else
+ {
+ tp_SlowMode = 0;
+ tp_idlecnt = 0;
+ event->pre_point = event->touch_point;
+ event->pressure = 200;
+ dbg("%s: 1:%d %d 2:%d %d \n", __func__,
+ event->x[0], event->y[0], event->x[1], event->y[1]);
+
+ return 0;
+ }
+}
+
+static void AW5306_report_multitouch(void)
+{
+ struct AW5306_ts_data *data = pContext;
+ struct ts_event *event = &data->event;
+
+#ifdef TOUCH_KEY_SUPPORT
+ if(1 == key_tp){
+ return;
+ }
+#endif
+
+ switch(event->touch_point) {
+ case 5:
+ input_report_abs(data->input_dev, ABS_MT_TRACKING_ID, event->touch_ID[4]);
+ //input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, event->pressure);
+ input_report_abs(data->input_dev, ABS_MT_POSITION_X, event->x[4]);
+ input_report_abs(data->input_dev, ABS_MT_POSITION_Y, event->y[4]);
+ //input_report_abs(data->input_dev, ABS_MT_WIDTH_MAJOR, 1);
+ input_mt_sync(data->input_dev);
+ // printk("=++==x5 = %d,y5 = %d ====\n",event->x[4],event->y[4]);
+ case 4:
+ input_report_abs(data->input_dev, ABS_MT_TRACKING_ID, event->touch_ID[3]);
+ //input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, event->pressure);
+ input_report_abs(data->input_dev, ABS_MT_POSITION_X, event->x[3]);
+ input_report_abs(data->input_dev, ABS_MT_POSITION_Y, event->y[3]);
+ //input_report_abs(data->input_dev, ABS_MT_WIDTH_MAJOR, 1);
+ input_mt_sync(data->input_dev);
+ // printk("===x4 = %d,y4 = %d ====\n",event->x[3],event->y[3]);
+ case 3:
+ input_report_abs(data->input_dev, ABS_MT_TRACKING_ID, event->touch_ID[2]);
+ //input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, event->pressure);
+ input_report_abs(data->input_dev, ABS_MT_POSITION_X, event->x[2]);
+ input_report_abs(data->input_dev, ABS_MT_POSITION_Y, event->y[2]);
+ //input_report_abs(data->input_dev, ABS_MT_WIDTH_MAJOR, 1);
+ input_mt_sync(data->input_dev);
+ // printk("===x3 = %d,y3 = %d ====\n",event->x[2],event->y[2]);
+ case 2:
+ input_report_abs(data->input_dev, ABS_MT_TRACKING_ID, event->touch_ID[1]);
+ //input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, event->pressure);
+ input_report_abs(data->input_dev, ABS_MT_POSITION_X, event->x[1]);
+ input_report_abs(data->input_dev, ABS_MT_POSITION_Y, event->y[1]);
+ //input_report_abs(data->input_dev, ABS_MT_WIDTH_MAJOR, 1);
+ input_mt_sync(data->input_dev);
+ // printk("===x2 = %d,y2 = %d ====\n",event->x[1],event->y[1]);
+ case 1:
+ input_report_abs(data->input_dev, ABS_MT_TRACKING_ID, event->touch_ID[0]);
+ //input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, event->pressure);
+ input_report_abs(data->input_dev, ABS_MT_POSITION_X, event->x[0]);
+ input_report_abs(data->input_dev, ABS_MT_POSITION_Y, event->y[0]);
+ //input_report_abs(data->input_dev, ABS_MT_WIDTH_MAJOR, 1);
+ input_mt_sync(data->input_dev);
+ // printk("===x1 = %d,y1 = %d ====\n",event->x[0],event->y[0]);
+ break;
+ default:
+// print_point_info("==touch_point default =\n");
+ break;
+ }
+
+ input_sync(data->input_dev);
+ dbg("%s: 1:%d %d 2:%d %d \n", __func__,
+ event->x[0], event->y[0], event->x[1], event->y[1]);
+ return;
+}
+
+#ifdef TOUCH_KEY_SUPPORT
+static void AW5306_report_touchkey(void)
+{
+ struct AW5306_ts_data *data = pContext;
+ struct ts_event *event = &data->event;
+ //printk("x=%d===Y=%d\n",event->x[0],event->y[0]);
+
+#ifdef TOUCH_KEY_FOR_ANGDA
+ if((1==event->touch_point)&&(event->x1 > TOUCH_KEY_X_LIMIT)){
+ key_tp = 1;
+ if(event->x1 < 40){
+ key_val = 1;
+ input_report_key(data->input_dev, key_val, 1);
+ input_sync(data->input_dev);
+ // print_point_info("===KEY 1====\n");
+ }else if(event->y1 < 90){
+ key_val = 2;
+ input_report_key(data->input_dev, key_val, 1);
+ input_sync(data->input_dev);
+ // print_point_info("===KEY 2 ====\n");
+ }else{
+ key_val = 3;
+ input_report_key(data->input_dev, key_val, 1);
+ input_sync(data->input_dev);
+ // print_point_info("===KEY 3====\n");
+ }
+ } else{
+ key_tp = 0;
+ }
+#endif
+#ifdef TOUCH_KEY_FOR_EVB13
+ if((1==event->touch_point)&&((event->y[0] > 510)&&(event->y[0]<530)))
+ {
+ if(key_tp != 1)
+ {
+ input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, 0);
+ input_sync(data->input_dev);
+ }
+ else
+ {
+ //printk("===KEY touch ++++++++++====++=\n");
+
+ if(event->x[0] < 90){
+ key_val = 1;
+ input_report_key(data->input_dev, KEY_MENU, 1);
+ input_sync(data->input_dev);
+ // printk("===KEY 1===++=\n");
+ }else if((event->x[0] < 230)&&(event->x[0]>185)){
+ key_val = 2;
+ input_report_key(data->input_dev, KEY_BACK, 1);
+ input_sync(data->input_dev);
+ // printk("===KEY 2 ====\n");
+ }else if((event->x[0] < 355)&&(event->x[0]>305)){
+ key_val = 3;
+ input_report_key(data->input_dev, KEY_SEARCH, 1);
+ input_sync(data->input_dev);
+ // print_point_info("===KEY 3====\n");
+ }else if ((event->x[0] < 497)&&(event->x[0]>445)) {
+ key_val = 4;
+ input_report_key(data->input_dev, KEY_HOMEPAGE, 1);
+ input_sync(data->input_dev);
+ // print_point_info("===KEY 4====\n");
+ }else if ((event->x[0] < 615)&&(event->x[0]>570)) {
+ key_val = 5;
+ input_report_key(data->input_dev, KEY_VOLUMEDOWN, 1);
+ input_sync(data->input_dev);
+ // print_point_info("===KEY 5====\n");
+ }else if ((event->x[0] < 750)&&(event->x[0]>705)) {
+ key_val = 6;
+ input_report_key(data->input_dev, KEY_VOLUMEUP, 1);
+ input_sync(data->input_dev);
+ // print_point_info("===KEY 6====\n");
+ }
+ }
+ key_tp = 1;
+ }
+ else
+ {
+ key_tp = 0;
+ }
+#endif
+
+#ifdef TOUCH_KEY_LIGHT_SUPPORT
+ AW5306_lighting();
+#endif
+ return;
+}
+#endif
+
+
+static void AW5306_report_value(void)
+{
+ AW5306_report_multitouch();
+#ifdef TOUCH_KEY_SUPPORT
+ AW5306_report_touchkey();
+#endif
+ return;
+} /*end AW5306_report_value*/
+
+
+#ifdef INTMODE
+static void AW5306_ts_pen_irq_work(struct work_struct *work)
+{
+ int ret = -1;
+
+ ret = AW5306_read_data();
+ if (ret == 0)
+ AW5306_report_value();
+
+ wmt_enable_gpirq(pContext->irqgpio);
+
+ return;
+}
+#else
+static void AW5306_ts_pen_irq_work(struct work_struct *work)
+{
+ int ret = -1;
+
+ if(suspend_flag != 1)
+ {
+ ret = AW5306_read_data();
+ if (ret == 0) {
+ AW5306_report_value();
+ }
+ }
+ else
+ {
+ AW5306_Sleep();
+ }
+}
+
+#endif
+
+
+
+static irqreturn_t aw5306_interrupt(int irq, void *dev)
+{
+ struct AW5306_ts_data *AW5306_ts= dev;
+
+//printk("I\n");
+ if (wmt_is_tsint(AW5306_ts->irqgpio))
+ {
+ wmt_clr_int(AW5306_ts->irqgpio);
+ if (wmt_is_tsirq_enable(AW5306_ts->irqgpio))
+ {
+ wmt_disable_gpirq(AW5306_ts->irqgpio);
+ #ifdef CONFIG_HAS_EARLYSUSPEND
+ if(!AW5306_ts->earlysus) queue_work(AW5306_ts->ts_workqueue , &AW5306_ts->pen_event_work);
+ #else
+ queue_work(AW5306_ts->ts_workqueue , &AW5306_ts->pen_event_work);
+ #endif
+
+ }
+ return IRQ_HANDLED;
+ }
+ return IRQ_NONE;
+}
+/*
+static void aw5306_reset(struct AW5306_ts_data *aw5306)
+{
+ gpio_set_value(aw5306->rstgpio, 0);
+ mdelay(5);
+ gpio_set_value(aw5306->rstgpio, 1);
+ mdelay(5);
+ gpio_set_value(aw5306->rstgpio, 0);
+ mdelay(5);
+
+ return;
+}
+*/
+
+void AW5306_tpd_polling(unsigned long data)
+ {
+ struct AW5306_ts_data *AW5306_ts = i2c_get_clientdata(l_client);
+
+#ifdef INTMODE
+ if (!work_pending(&AW5306_ts->pen_event_work)) {
+ queue_work(AW5306_ts->ts_workqueue, &AW5306_ts->pen_event_work);
+ }
+#else
+
+ if (!work_pending(&AW5306_ts->pen_event_work)) {
+ queue_work(AW5306_ts->ts_workqueue, &AW5306_ts->pen_event_work);
+ }
+ if(suspend_flag != 1)
+ {
+ #ifdef AUTO_RUDUCEFRAME
+ if(tp_SlowMode)
+ {
+ AW5306_ts->touch_timer.expires = jiffies + HZ/AWTPCfg.SLOW_FRAME;
+ }
+ else
+ {
+ AW5306_ts->touch_timer.expires = jiffies + HZ/AWTPCfg.FAST_FRAME;
+ }
+ #else
+ AW5306_ts->touch_timer.expires = jiffies + HZ/AWTPCfg.FAST_FRAME;
+ #endif
+ add_timer(&AW5306_ts->touch_timer);
+ }
+#endif
+ }
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void aw5306_early_suspend(struct early_suspend *handler)
+{
+#ifdef INTMODE
+ if(suspend_flag != 1)
+ {
+ wmt_disable_gpirq(AW5306_ts->irqgpio);
+ AW5306_Sleep();
+ suspend_flag = 1;
+ }
+#else
+ if(suspend_flag != 1)
+ {
+ printk("AW5306 SLEEP!!!");
+ suspend_flag = 1;
+ }
+#endif
+
+ return;
+}
+
+static void aw5306_late_resume(struct early_suspend *handler)
+{
+ struct AW5306_ts_data *AW5306_ts= container_of(handler, struct AW5306_ts_data , early_suspend);
+#ifdef INTMODE
+ if(suspend_flag != 0)
+ {
+ gpio_direction_output(AW5306_ts->rstgpio, 0);
+ AW5306_User_Cfg1();
+ AW5306_TP_Reinit();
+ wmt_enable_gpirq(AW5306_ts->irqgpio);
+ suspend_flag = 0;
+ }
+#else
+ if(suspend_flag != 0)
+ {
+ gpio_direction_output(AW5306_ts->rstgpio, 0);
+ AW5306_User_Cfg1();
+ AW5306_TP_Reinit();
+ tp_idlecnt = 0;
+ tp_SlowMode = 0;
+ suspend_flag = 0;
+ printk("AW5306 WAKE UP!!!");
+ AW5306_ts->touch_timer.expires = jiffies + HZ/AWTPCfg.FAST_FRAME;
+ add_timer(&AW5306_ts->touch_timer);
+ }
+#endif
+
+ return;
+}
+#endif //CONFIG_HAS_EARLYSUSPEND
+
+#ifdef CONFIG_PM
+static int aw5306_suspend(struct platform_device *pdev, pm_message_t state)
+{
+#ifdef INTMODE
+ if(suspend_flag != 1)
+ {
+ wmt_disable_gpirq(pContext->irqgpio);
+ AW5306_Sleep();
+ suspend_flag = 1;
+ }
+#else
+ if(suspend_flag != 1)
+ {
+ printk("AW5306 SLEEP!!!");
+ suspend_flag = 1;
+ }
+#endif
+ return 0;
+
+}
+
+static int aw5306_resume(struct platform_device *pdev)
+{
+ struct AW5306_ts_data *AW5306_ts= dev_get_drvdata(&pdev->dev);
+
+#ifdef INTMODE
+ if(suspend_flag != 0)
+ {
+ gpio_direction_output(AW5306_ts->rstgpio, 0);
+ AW5306_User_Cfg1();
+ AW5306_TP_Reinit();
+ suspend_flag = 0;
+ printk("AW5306 WAKE UP_intmode!!!");
+ wmt_enable_gpirq(AW5306_ts->irqgpio);
+ }
+#else
+ if(suspend_flag != 0)
+ {
+ gpio_direction_output(AW5306_ts->rstgpio, 0);
+ AW5306_User_Cfg1();
+ AW5306_TP_Reinit();
+ tp_idlecnt = 0;
+ tp_SlowMode = 0;
+ suspend_flag = 0;
+ printk("AW5306 WAKE UP!!!");
+ AW5306_ts->touch_timer.expires = jiffies + HZ/AWTPCfg.FAST_FRAME;
+ add_timer(&AW5306_ts->touch_timer);
+ }
+#endif
+
+ return 0;
+}
+
+#else
+#define aw5306_suspend NULL
+#define aw5306_resume NULL
+#endif
+
+static int aw5306_probe(struct platform_device *pdev)
+{
+ int err = 0;
+ struct AW5306_ts_data *AW5306_ts = platform_get_drvdata( pdev);
+ u8 reg_value;
+
+ //aw5306_reset(AW5306_ts);
+
+ reg_value = AW_I2C_ReadByte(0x01);
+ if(reg_value != 0xA8)
+ {
+ //l_client->addr = 0x39;
+ dbg_err("AW5306_ts_probe: CHIP ID NOT CORRECT\n");
+ return -ENODEV;
+ }
+
+ i2c_set_clientdata(l_client, AW5306_ts);
+
+ INIT_WORK(&AW5306_ts->pen_event_work, AW5306_ts_pen_irq_work);
+ AW5306_ts->ts_workqueue = create_singlethread_workqueue(AW5306_ts->name);
+ if (!AW5306_ts->ts_workqueue ) {
+ err = -ESRCH;
+ goto exit_create_singlethread;
+ }
+
+ AW5306_ts->input_dev = input_allocate_device();
+ if (!AW5306_ts->input_dev) {
+ err = -ENOMEM;
+ dbg_err("failed to allocate input device\n");
+ goto exit_input_dev_alloc_failed;
+ }
+
+ AW5306_ts->input_dev->name = AW5306_ts->name;
+ AW5306_ts->input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ set_bit(INPUT_PROP_DIRECT, AW5306_ts->input_dev->propbit);
+
+ if (AW5306_ts->lcd_exchg) {
+ input_set_abs_params(AW5306_ts->input_dev,
+ ABS_MT_POSITION_X, 0, AW5306_ts->resly, 0, 0);
+ input_set_abs_params(AW5306_ts->input_dev,
+ ABS_MT_POSITION_Y, 0, AW5306_ts->reslx, 0, 0);
+ } else {
+ input_set_abs_params(AW5306_ts->input_dev,
+ ABS_MT_POSITION_X, 0, AW5306_ts->reslx, 0, 0);
+ input_set_abs_params(AW5306_ts->input_dev,
+ ABS_MT_POSITION_Y, 0, AW5306_ts->resly, 0, 0);
+ }
+ input_set_abs_params(AW5306_ts->input_dev,
+ ABS_MT_TRACKING_ID, 0, 4, 0, 0);
+
+ err = input_register_device(AW5306_ts->input_dev);
+ if (err) {
+ dbg_err("aw5306_ts_probe: failed to register input device.\n");
+ goto exit_input_register_device_failed;
+ }
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ AW5306_ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+ AW5306_ts->early_suspend.suspend = aw5306_early_suspend;
+ AW5306_ts->early_suspend.resume = aw5306_late_resume;
+ register_early_suspend(&AW5306_ts->early_suspend);
+#endif
+
+ AW5306_create_sysfs(l_client);
+ memcpy(AW_CALI_FILENAME,"/data/tpcali",12);
+ //memcpy(AW_UCF_FILENAME,"/data/AWTPucf",13);
+ printk("ucf file: %s\n", AW_UCF_FILENAME);
+
+ AW5306_TP_Init();
+
+ AW5306_ts->touch_timer.function = AW5306_tpd_polling;
+ AW5306_ts->touch_timer.data = 0;
+ init_timer(&AW5306_ts->touch_timer);
+ AW5306_ts->touch_timer.expires = jiffies + HZ*10;
+ add_timer(&AW5306_ts->touch_timer);
+
+#ifdef INTMODE
+
+ if(request_irq(AW5306_ts->irq, aw5306_interrupt, IRQF_SHARED, AW5306_ts->name, AW5306_ts) < 0){
+ dbg_err("Could not allocate irq for ts_aw5306 !\n");
+ err = -1;
+ goto exit_register_irq;
+ }
+
+ wmt_set_gpirq(AW5306_ts->irqgpio, IRQ_TYPE_EDGE_FALLING);
+ wmt_enable_gpirq(AW5306_ts->irqgpio);
+
+#endif
+
+
+
+
+ return 0;
+
+exit_register_irq:
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&AW5306_ts->early_suspend);
+#endif
+exit_input_register_device_failed:
+ input_free_device(AW5306_ts->input_dev);
+exit_input_dev_alloc_failed:
+//exit_create_group:
+ cancel_work_sync(&AW5306_ts->pen_event_work);
+ destroy_workqueue(AW5306_ts->ts_workqueue );
+exit_create_singlethread:
+ return err;
+}
+
+static int aw5306_remove(struct platform_device *pdev)
+{
+ struct AW5306_ts_data *AW5306_ts= platform_get_drvdata( pdev);
+
+ del_timer(&AW5306_ts->touch_timer);
+
+
+#ifdef INTMODE
+ wmt_disable_gpirq(AW5306_ts->irqgpio);
+ free_irq(AW5306_ts->irq, AW5306_ts);
+#endif
+
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&AW5306_ts->early_suspend);
+#endif
+ input_unregister_device(AW5306_ts->input_dev);
+ input_free_device(AW5306_ts->input_dev);
+
+ cancel_work_sync(&AW5306_ts->pen_event_work);
+ flush_workqueue(AW5306_ts->ts_workqueue);
+ destroy_workqueue(AW5306_ts->ts_workqueue);
+
+ dbg("remove...\n");
+ return 0;
+}
+
+static void aw5306_release(struct device *device)
+{
+ return;
+}
+
+static struct platform_device aw5306_device = {
+ .name = DEV_AW5306,
+ .id = 0,
+ .dev = {.release = aw5306_release},
+};
+
+static struct platform_driver aw5306_driver = {
+ .driver = {
+ .name = DEV_AW5306,
+ .owner = THIS_MODULE,
+ },
+ .probe = aw5306_probe,
+ .remove = aw5306_remove,
+ .suspend = aw5306_suspend,
+ .resume = aw5306_resume,
+};
+
+static int check_touch_env(struct AW5306_ts_data *AW5306_ts)
+{
+ int ret = 0;
+ int len = 96;
+ int Enable;
+ char retval[96] = {0};
+ char ucfname[20] = {0};
+ char *p=NULL, *s=NULL;
+
+ // Get u-boot parameter
+ ret = wmt_getsyspara("wmt.io.touch", retval, &len);
+ if(ret){
+ //printk("MST FT5x0x:Read wmt.io.touch Failed.\n");
+ return -EIO;
+ }
+ sscanf(retval,"%d:",&Enable);
+ //check touch enable
+ if(Enable == 0){
+ //printk("FT5x0x Touch Screen Is Disabled.\n");
+ return -ENODEV;
+ }
+
+ p = strchr(retval,':');
+ p++;
+ if(strncmp(p,"aw5306",6)) return -ENODEV;
+ AW5306_ts->name = DEV_AW5306;
+ s = strchr(p, ':');
+ p = p + 7;
+ if (s <= p)
+ return -ENODEV;
+ strncpy(ucfname, p, s-p);
+ sprintf(AW_UCF_FILENAME, "/lib/firmware/%s", ucfname);
+
+ s++;
+ sscanf(s,"%d:%d:%d:%d:%d:%d:%d:%d", &AW5306_ts->irqgpio, &AW5306_ts->reslx, &AW5306_ts->resly, &AW5306_ts->rstgpio, &AW5306_ts->swap, &AW5306_ts->xch, &AW5306_ts->ych, &AW5306_ts->nt);
+
+ AW5306_ts->irq = IRQ_GPIO;
+
+ printk("%s irqgpio=%d, reslx=%d, resly=%d, rstgpio=%d, swap=%d, xch=%d, ych=%d, nt=%d\n", AW5306_ts->name, AW5306_ts->irqgpio, AW5306_ts->reslx, AW5306_ts->resly, AW5306_ts->rstgpio, AW5306_ts->swap, AW5306_ts->xch, AW5306_ts->ych, AW5306_ts->nt);
+
+ memset(retval,0,sizeof(retval));
+ ret = wmt_getsyspara("wmt.display.fb0", retval, &len);
+ if (!ret) {
+ int tmp[6];
+ p = retval;
+ sscanf(p, "%d:[%d:%d:%d:%d:%d", &tmp[0], &tmp[1], &tmp[2], &tmp[3], &tmp[4], &tmp[5]);
+ if (tmp[4] > tmp[5])
+ AW5306_ts->lcd_exchg = 1;
+ }
+
+ return 0;
+}
+
+struct i2c_board_info ts_i2c_board_info = {
+ .type = TS_I2C_NAME,
+ .flags = 0x00,
+ .addr = AW5306_I2C_ADDR,
+ .platform_data = NULL,
+ .archdata = NULL,
+ .irq = -1,
+};
+
+static int ts_i2c_register_device (void)
+{
+ struct i2c_board_info *ts_i2c_bi;
+ struct i2c_adapter *adapter = NULL;
+ //struct i2c_client *client = NULL;
+
+ //ts_i2c_board_info.addr = AW5306_I2C_ADDR;
+ ts_i2c_bi = &ts_i2c_board_info;
+ adapter = i2c_get_adapter(AW5306_I2C_BUS);/*in bus 1*/
+
+ if (NULL == adapter) {
+ printk("can not get i2c adapter, client address error\n");
+ return -1;
+ }
+ l_client = i2c_new_device(adapter, ts_i2c_bi);
+ if (l_client == NULL) {
+ printk("allocate i2c client failed\n");
+ return -1;
+ }
+ i2c_put_adapter(adapter);
+ return 0;
+}
+
+static void ts_i2c_unregister_device(void)
+{
+ if (l_client != NULL)
+ {
+ i2c_unregister_device(l_client);
+ l_client = NULL;
+ }
+}
+
+static int __init aw5306_init(void)
+{
+ int ret = -ENOMEM;
+ struct AW5306_ts_data *AW5306_ts=NULL;
+
+ if (ts_i2c_register_device()<0)
+ {
+ dbg("Error to run ts_i2c_register_device()!\n");
+ return -1;
+ }
+
+ AW5306_ts = kzalloc(sizeof(struct AW5306_ts_data), GFP_KERNEL);
+ if(!AW5306_ts){
+ dbg_err("mem alloc failed.\n");
+ return -ENOMEM;
+ }
+
+ pContext = AW5306_ts;
+ ret = check_touch_env(AW5306_ts);
+ if(ret < 0)
+ goto exit_free_mem;
+
+ ret = gpio_request(AW5306_ts->irqgpio, "ts_irq");
+ if (ret < 0) {
+ printk("gpio(%d) touchscreen irq request fail\n", AW5306_ts->irqgpio);
+ goto exit_free_mem;
+ }
+ //wmt_gpio_setpull(AW5306_ts->irqgpio, WMT_GPIO_PULL_UP);
+ gpio_direction_input(AW5306_ts->irqgpio);
+
+ ret = gpio_request(AW5306_ts->rstgpio, "ts_rst");
+ if (ret < 0) {
+ printk("gpio(%d) touchscreen reset request fail\n", AW5306_ts->rstgpio);
+ goto exit_free_irqgpio;
+ }
+ gpio_direction_output(AW5306_ts->rstgpio, 0);
+
+
+ ret = platform_device_register(&aw5306_device);
+ if(ret){
+ dbg_err("register platform drivver failed!\n");
+ goto exit_free_gpio;
+ }
+ platform_set_drvdata(&aw5306_device, AW5306_ts);
+
+ ret = platform_driver_register(&aw5306_driver);
+ if(ret){
+ dbg_err("register platform device failed!\n");
+ goto exit_unregister_pdev;
+ }
+
+/*
+ i2c_dev_class = class_create(THIS_MODULE,"aw_i2c_dev");
+ if (IS_ERR(i2c_dev_class)) {
+ ret = PTR_ERR(i2c_dev_class);
+ class_destroy(i2c_dev_class);
+ }
+*/
+
+
+ return ret;
+
+exit_unregister_pdev:
+ platform_device_unregister(&aw5306_device);
+exit_free_gpio:
+ gpio_free(AW5306_ts->rstgpio);
+exit_free_irqgpio:
+ gpio_free(AW5306_ts->irqgpio);
+exit_free_mem:
+ kfree(AW5306_ts);
+ pContext = NULL;
+ return ret;
+}
+
+static void aw5306_exit(void)
+{
+ if(!pContext) return;
+
+ platform_driver_unregister(&aw5306_driver);
+ platform_device_unregister(&aw5306_device);
+ gpio_free(pContext->rstgpio);
+ gpio_free(pContext->irqgpio);
+ kfree(pContext);
+ ts_i2c_unregister_device();
+ return;
+}
+
+late_initcall(aw5306_init);
+module_exit(aw5306_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("FocalTech.Touch");
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/AW5306_userpara.c b/ANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/AW5306_userpara.c
new file mode 100755
index 00000000..99f65f87
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/AW5306_userpara.c
@@ -0,0 +1,196 @@
+#include "AW5306_Reg.h"
+#include "AW5306_Drv.h"
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include "AW5306_userpara.h"
+
+#define POS_PRECISION 64
+
+extern AW5306_UCF AWTPCfg;
+extern STRUCTCALI AW_Cali;
+extern char AW5306_WorkMode;
+extern STRUCTNOISE AW_Noise;
+
+extern void AW5306_CLB_WriteCfg(void);
+extern int AW_I2C_WriteByte(unsigned char addr, unsigned char data);
+extern unsigned char AW_I2C_ReadByte(unsigned char addr);
+extern unsigned char AW_I2C_ReadXByte( unsigned char *buf, unsigned char addr, unsigned short len);
+extern unsigned char AW5306_RAWDATACHK(void);
+
+const STRUCTCALI Default_Cali1 =
+{
+ "AWINIC TP CALI",
+ //{0x33,0x23,0x22,0x22,0x22,0x22,0x22,0x02,0x22,0x22}, //TXOFFSET
+ {0x32,0x32,0x23,0x32,0x33,0x33,0x33,0x03,0x22,0x22}, //TXOFFSET
+ //{0x9A,0xA9,0xAA,0xA9,0x9B,0x00}, //RXOFFSET
+ {0x35,0x44,0x55,0x54,0x34,0x00}, //RXOFFSET
+ //{0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c},//TXCAC
+ {0x2C,0x2B,0x2B,0x2A,0x2A,0x2C,0x2C,0x2C,0x2C,0x2C,0x2D,0x2D,0x2D,0x2D,0x31,0x2C,0x2C,0x2C,0x2C,0x2C},//TXCAC
+ //{0x3d,0x3c,0x3c,0x3c,0x3e,0x3a,0x3a,0x3e,0x3c,0x3b,0x3c,0x3c},//RXCAC
+ {0x84,0x84,0x82,0x82,0x80,0x86,0x86,0x80,0x8C,0x82,0x84,0x84},//RXCAC
+ //{0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x2e,0x2e,0x0e,0x0e,0x0e,0x0e,0x0e},//TXGAIN
+ {0x88,0x88,0x88,0x88,0x88,0x68,0x68,0x68,0x68,0x68,0x48,0x48,0x48,0x48,0x28,0x08,0x08,0x08,0x08,0x08},//TXGAIN
+};
+
+const AW5306_UCF Default_UCF =
+{
+ 15, //TX_NUM
+ 10, //RX_NUM
+ {17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0,0,0}, //TX_ORDER
+ {9,8,7,6,5,4,3,2,1,0,0,0}, //RX_ORDER
+ 0, //RX_START
+ 0, //HAVE_KEY_LINE
+ {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, //KeyLineValid
+
+ 600, //MAPPING_MAX_X
+ 1024, //MAPPING_MAX_Y
+
+ 350, //GainClbDeltaMin
+ 450, //GainClbDeltaMax
+ 550, //KeyLineDeltaMin
+ 650, //KeyLineDeltaMax
+ 8300, //OffsetClbExpectedMin
+ 8500, //OffsetClbExpectedMax
+ 300, //RawDataDeviation
+ 8, //CacMultiCoef
+
+ 7000, //RawDataCheckMin
+ 10000, //RawDataCheckMax
+
+ 200, //FLYING_TH
+ 100, //MOVING_TH
+ 50, //MOVING_ACCELER
+
+ 70, //PEAK_TH
+ 80, //GROUP_TH
+ 90, //BIGAREA_TH
+ 25, //BIGAREA_CNT
+ 20, //BIGAREA_FRESHCNT
+
+ 1, //CACULATE_COEF
+
+ 1, //FIRST_CALI
+ 0, //RAWDATA_DUMP_SWITCH
+
+ 1, //MULTI_SCANFREQ
+ 5, //BASE_FREQ
+ 0x83, //FREQ_OFFSET
+ 0x00, //WAIT_TIME
+ 0x2b, //CHAMP_CFG
+ 0x10, //POSLEVEL_TH
+
+ 1, //ESD_PROTECT
+
+ 0, //MARGIN_COMPENSATE
+ 0, //MARGIN_COMP_DATA_UP
+ 0, //MARGIN_COMP_DATA_DOWN
+ 0, //MARGIN_COMP_DATA_LEFT
+ 0, //MARGIN_COMP_DATA_RIGHT
+
+ 1, //POINT_RELEASEHOLD
+ 0, //MARGIN_RELEASEHOLD
+ 0, //POINT_PRESSHOLD
+ 1, //KEY_PRESSHOLD
+
+ 0, //PEAK_ROW_COMPENSATE
+ 1, //PEAK_COL_COMPENSATE
+ 3, //PEAK_COMPENSATE_COEF
+
+ 0, //LCD_NOISE_PROCESS
+ 50, //LCD_NOISETH
+
+ 0, //FALSE_PEAK_PROCESS
+ 100, //FALSE_PEAK_TH
+
+ 6, //STABLE_DELTA_X
+ 6, //STABLE_DELTA_Y
+
+ 0, //DEBUG_LEVEL
+
+ 50, //FAST_FRAME
+ 20, //SLOW_FRAME
+
+ 0, //GAIN_CLB_SEPERATE
+ 5, //MARGIN_PREFILTER
+ 0, //BIGAREA_HOLDPOINT
+ 50, //CHARGE_NOISE
+ 0, //FREQ_JUMP
+ 0, //PEAK_VALID_CHECK
+ 1, //WATER_REMOVE
+
+#ifdef INTMODE
+ 1 //INT_MODE
+#else
+ 0 //POLL_MODE
+#endif
+};
+
+void AW5306_User_Cfg1(void)
+{
+ unsigned char i;
+
+
+ for(i=0;i<AWTPCfg.TX_LOCAL;i++)
+ {
+ AW_I2C_WriteByte(SA_TX_INDEX0+i,AWTPCfg.TX_ORDER[i]); //TX REVERT
+ }
+
+ AW_I2C_WriteByte(SA_TX_NUM,AWTPCfg.TX_LOCAL);
+ AW_I2C_WriteByte(SA_RX_NUM,AWTPCfg.RX_LOCAL);
+
+ if(1 == AWTPCfg.MULTI_SCANFREQ)
+ {
+ AW_I2C_WriteByte(SA_SCANFREQ1,AWTPCfg.BASE_FREQ);
+ AW_I2C_WriteByte(SA_SCANFREQ2,AWTPCfg.BASE_FREQ);
+ AW_I2C_WriteByte(SA_SCANFREQ3,AWTPCfg.BASE_FREQ);
+ }
+ else
+ {
+ AW_I2C_WriteByte(SA_SCANFREQ1,AWTPCfg.BASE_FREQ); //3-5
+ }
+
+
+ AW_I2C_WriteByte(SA_WAITTIME,AWTPCfg.WAIT_TIME);
+ AW_I2C_WriteByte(SA_RX_START,AWTPCfg.RX_START);
+ AW_I2C_WriteByte(SA_SCANTIM,4); // set to 32 TX cycles mode
+
+ AW_I2C_WriteByte(SA_PAGE,1);
+ AW_I2C_WriteByte(SA_CHAMPCFG,AWTPCfg.CHAMP_CFG); //
+ AW_I2C_WriteByte(SA_OSCCFG1,AWTPCfg.FREQ_OFFSET); //
+ AW_I2C_WriteByte(SA_OSCCFG2,0x10); //TRIM register
+ AW_I2C_WriteByte(SA_POSLEVELTH,AWTPCfg.POSLEVEL_TH);
+
+ AW_I2C_WriteByte(SA_CPFREQ,0x00); //for AW256
+ AW_I2C_WriteByte(SA_PAGE,0);
+
+ AW5306_CLB_WriteCfg();
+ //printk("AW5306 user config finished TXCAC0 = %x",AW_Cali.TXCAC[0] );
+}
+
+void AW5306_User_Init(void)
+{
+ unsigned char ret;
+
+ ret = 0;
+
+ AW5306_WorkMode = DeltaMode; //DeltaMode: chip output delta data RawDataMode: chip output rawdata
+
+ memcpy(&AWTPCfg,&Default_UCF,sizeof(AW5306_UCF));
+ memcpy(&AW_Cali,&Default_Cali1,sizeof(STRUCTCALI)); //load default cali value
+
+
+ //AW_I2C_WriteByte(SA_PAGE,0);
+ //AW_I2C_WriteByte(SA_IDRST,0x55);
+
+ AW5306_User_Cfg1();
+
+ AW_Noise.FrmState = NOISE_FRM_NORMAL;
+ AW_Noise.WorkFreqID = 16;
+ AW_Noise.ScanFreqID = AW_Noise.WorkFreqID;
+ AW_Noise.State = NOISE_LISTENING;
+ AW_Noise.NoiseTh1 = 60;
+ AW_Noise.JumpTh = 5;
+ AW_Noise.Better_NoiseScan = 1000;
+ //ret = AW5306_RAWDATACHK();
+
+}
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/AW5306_userpara.h b/ANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/AW5306_userpara.h
new file mode 100755
index 00000000..15d5c180
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/AW5306_userpara.h
@@ -0,0 +1,99 @@
+#ifndef AW5306_USERPARA_H
+
+#define AW5306_USERPARA_H
+
+#define INTMODE
+
+typedef struct {
+ unsigned char TX_LOCAL; // 15 //TX number of TP
+ unsigned char RX_LOCAL; // 10 //RX number of TP
+ unsigned char TX_ORDER[22]; // TX ORDER
+ unsigned char RX_ORDER[12]; // RX mapping in inverted order
+ unsigned char RX_START; //RX START LINE
+ unsigned char HAVE_KEY_LINE; // 0: no KEY line, 1: have key line on TX line TX_LOCAL-1
+ unsigned char KeyLineValid[16];
+
+ unsigned short MAPPING_MAX_X; // 320
+ unsigned short MAPPING_MAX_Y; // 460
+
+ unsigned short GainClbDeltaMin; // Expected minimum delta for GAIN calibration
+ unsigned short GainClbDeltaMax; // Expected maximum delta for GAIN calibration
+ unsigned short KeyLineDeltaMin;
+ unsigned short KeyLineDeltaMax;
+ unsigned short OffsetClbExpectedMin; // Expected minimum data for OFFSET calibration
+ unsigned short OffsetClbExpectedMax; // Expected minimum data for OFFSET calibration
+ unsigned short RawDataDeviation; // Maximum deviation in a frame
+ unsigned short CacMultiCoef;
+
+ unsigned short RawDataCheckMin;
+ unsigned short RawDataCheckMax;
+
+ unsigned short FLYING_TH;
+ unsigned short MOVING_TH;
+ unsigned short MOVING_ACCELER;
+
+ unsigned char PEAK_TH;
+ unsigned char GROUP_TH;
+ unsigned char BIGAREA_TH;
+ unsigned char BIGAREA_CNT;
+ unsigned char BIGAREA_FRESHCNT;
+
+ unsigned char CACULATE_COEF;
+
+ unsigned char FIRST_CALI;
+ unsigned char RAWDATA_DUMP_SWITCH;
+ unsigned char MULTI_SCANFREQ;
+ unsigned char BASE_FREQ;
+ unsigned char FREQ_OFFSET;
+ unsigned char WAIT_TIME;
+ unsigned char CHAMP_CFG;
+ unsigned char POSLEVEL_TH;
+
+ unsigned char ESD_PROTECT;
+
+ unsigned char MARGIN_COMPENSATE;
+ unsigned char MARGIN_COMP_DATA_UP;
+ unsigned char MARGIN_COMP_DATA_DOWN;
+ unsigned char MARGIN_COMP_DATA_LEFT;
+ unsigned char MARGIN_COMP_DATA_RIGHT;
+
+ unsigned char POINT_RELEASEHOLD;
+ unsigned char MARGIN_RELEASEHOLD;
+ unsigned char POINT_PRESSHOLD;
+ unsigned char KEY_PRESSHOLD;
+
+ unsigned char PEAK_ROW_COMPENSATE;
+ unsigned char PEAK_COL_COMPENSATE;
+ unsigned char PEAK_COMPENSATE_COEF;
+
+ unsigned char LCD_NOISE_PROCESS;
+ unsigned char LCD_NOISETH;
+
+ unsigned char FALSE_PEAK_PROCESS;
+ unsigned char FALSE_PEAK_TH;
+
+ unsigned char STABLE_DELTA_X;
+ unsigned char STABLE_DELTA_Y;
+
+ unsigned char DEBUG_LEVEL;
+
+ unsigned char FAST_FRAME;
+ unsigned char SLOW_FRAME;
+
+ unsigned char GAIN_CLB_SEPERATE;
+
+ unsigned char MARGIN_PREFILTER;
+
+ unsigned char BIGAREA_HOLDPOINT;
+ unsigned char CHARGE_NOISE;
+ unsigned char FREQ_JUMP;
+ unsigned char PEAK_VALID_CHECK;
+ unsigned char WATER_REMOVE;
+ unsigned char INT_MODE;
+
+}AW5306_UCF;
+
+void AW5306_User_Init(void);
+void AW5306_User_Cfg1(void);
+
+#endif
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/Kconfig b/ANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/Kconfig
new file mode 100755
index 00000000..32029915
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/Kconfig
@@ -0,0 +1,11 @@
+config TOUCHSCREEN_AW5306
+ tristate "AW5306 Capacity Touchscreen Device Support"
+ default y
+ depends on ARCH_WMT
+ ---help---
+ Say Y here if you have an WMT based board with touchscreen
+ attached to it.
+ If unsure, say N.
+ To compile this driver as a module, choose M here: the
+ module will be called s_wmt_ts_aw5306.
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/Makefile b/ANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/Makefile
new file mode 100755
index 00000000..2a79cbe6
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/Makefile
@@ -0,0 +1,35 @@
+KERNELDIR=../../../../
+CROSS = arm_1103_le-
+CC= $(CROSS)gcc
+LD= $(CROSS)ld
+STRIP = $(CROSS)strip
+
+DEBUG = n
+
+# Add your debugging flag (or not) to EXTRA_CFLAGS
+ifeq ($(DEBUG),y)
+# DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+DEBFLAGS = -O0 -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+
+else
+ DEBFLAGS = -O2 -Wall
+ #DEBFLAGS = -O2 -Wall -L./libAW5306.a
+endif
+
+EXTRA_CFLAGS += $(DEBFLAGS)
+
+
+MY_MODULE_NAME=s_wmt_ts_aw5306
+
+#obj-$(CONFIG_TOUCHSCREEN_FT5X0X) := $(MY_MODULE_NAME).o
+obj-m := $(MY_MODULE_NAME).o
+$(MY_MODULE_NAME)-objs := AW5306_ts.o irq_gpio.o AW5306_userpara.o AW5306_Base.b AW5306_Clb.b AW5306_Drv.b
+
+default:
+ $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules
+ $(STRIP) --strip-debug $(MY_MODULE_NAME).ko
+# @rm -rf *.o *~ core .depend .*.cmd *.mod.c .tmp_versions *.order *.symvers
+
+clean:
+ @rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.order *.symvers modules.builtin
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/irq_gpio.c b/ANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/irq_gpio.c
new file mode 100755
index 00000000..8bdf9f20
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/irq_gpio.c
@@ -0,0 +1,149 @@
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+#include <mach/hardware.h>
+#include "irq_gpio.h"
+
+int wmt_enable_gpirq(int num)
+{
+ if(num > 15)
+ return -1;
+
+ if(num < 4)
+ REG32_VAL(__GPIO_BASE+0x0300) |= 1<<(num*8+7); //enable interrupt
+ else if(num >= 4 && num < 8)
+ REG32_VAL(__GPIO_BASE+0x0304) |= 1<<((num-4)*8+7); //enable interrupt
+ else if(num >= 8 && num < 12)
+ REG32_VAL(__GPIO_BASE+0x0308) |= 1<<((num-8)*8+7); //enable interrupt
+ else
+ REG32_VAL(__GPIO_BASE+0x030C) |= 1<<((num-12)*8+7); //enable interrupt
+
+ return 0;
+}
+
+int wmt_disable_gpirq(int num)
+{
+ if(num > 15)
+ return -1;
+
+ if(num<4)
+ REG32_VAL(__GPIO_BASE+0x0300) &= ~(1<<(num*8+7)); //enable interrupt
+ else if(num >= 4 && num < 8)
+ REG32_VAL(__GPIO_BASE+0x0304) &= ~(1<<((num-4)*8+7)); //enable interrupt
+ else if(num >= 8 && num < 12)
+ REG32_VAL(__GPIO_BASE+0x0308) &= ~(1<<((num-8)*8+7)); //enable interrupt
+ else
+ REG32_VAL(__GPIO_BASE+0x030C) &= ~(1<<((num-12)*8+7)); //enable interrupt
+
+ return 0;
+}
+
+int wmt_is_tsirq_enable(int num)
+{
+ int val = 0;
+
+ if(num > 15)
+ return 0;
+
+ if(num<4)
+ val = REG32_VAL(__GPIO_BASE+0x0300) & (1<<(num*8+7));
+ else if(num >= 4 && num < 8)
+ val = REG32_VAL(__GPIO_BASE+0x0304) & (1<<((num-4)*8+7));
+ else if(num >= 8 && num < 12)
+ val = REG32_VAL(__GPIO_BASE+0x0308) & (1<<((num-8)*8+7));
+ else
+ val = REG32_VAL(__GPIO_BASE+0x030C) & (1<<((num-12)*8+7));
+
+ return val?1:0;
+
+}
+
+int wmt_is_tsint(int num)
+{
+ if (num > 15)
+ {
+ return 0;
+ }
+ return (REG32_VAL(__GPIO_BASE+0x0360) & (1<<num)) ? 1: 0;
+}
+
+void wmt_clr_int(int num)
+{
+ if (num > 15)
+ {
+ return;
+ }
+ REG32_VAL(__GPIO_BASE+0x0360) = 1<<num;
+}
+
+int wmt_set_gpirq(int num, int type)
+{
+ int shift;
+ int offset;
+ unsigned long reg;
+
+ if(num >15)
+ return -1;
+ //if (num > 9)
+ //GPIO_PIN_SHARING_SEL_4BYTE_VAL &= ~BIT4; // gpio10,11 as gpio
+
+ REG32_VAL(__GPIO_BASE+0x0040) &= ~(1<<num);//|=(1<<num);// //enable gpio
+ REG32_VAL(__GPIO_BASE+0x0080) &= ~(1<<num); //set input
+ REG32_VAL(__GPIO_BASE+0x04c0) |= (1<<num); //pull down
+ REG32_VAL(__GPIO_BASE+0x0480) &= ~(1<<num); //enable pull up/down
+
+ //set gpio irq triger type
+ if(num < 4){//[0,3]
+ shift = num;
+ offset = 0x0300;
+ }else if(num >= 4 && num < 8){//[4,7]
+ shift = num-4;
+ offset = 0x0304;
+ }else if(num >= 8 && num < 12){//[8,11]
+ shift = num-8;
+ offset = 0x0308;
+ }else{// [12,15]
+ shift = num-12;
+ offset = 0x030C;
+ }
+
+ reg = REG32_VAL(__GPIO_BASE + offset);
+
+ switch(type){
+ case IRQ_TYPE_LEVEL_LOW:
+ reg &= ~(1<<(shift*8+2));
+ reg &= ~(1<<(shift*8+1));
+ reg &= ~(1<<(shift*8));
+ break;
+ case IRQ_TYPE_LEVEL_HIGH:
+ reg &= ~(1<<(shift*8+2));
+ reg &= ~(1<<(shift*8+1));
+ reg |= (1<<(shift*8));
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ reg &= ~(1<<(shift*8+2));
+ reg |= (1<<(shift*8+1));
+ reg &= ~(1<<(shift*8));
+ break;
+ case IRQ_TYPE_EDGE_RISING:
+ reg &= ~(1<<(shift*8+2));
+ reg |= (1<<(shift*8+1));
+ reg |= (1<<(shift*8));
+ break;
+ default://both edge
+ reg |= (1<<(shift*8+2));
+ reg &= ~(1<<(shift*8+1));
+ reg &= ~(1<<(shift*8));
+ break;
+
+ }
+ //reg |= 1<<(shift*8+7);//enable interrupt
+ reg &= ~(1<<(shift*8+7)); //disable int
+
+ REG32_VAL(__GPIO_BASE + offset) = reg;
+ REG32_VAL(__GPIO_BASE+0x0360) = 1<<num; //clear interrupt status
+ msleep(5);
+ return 0;
+}
+
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/irq_gpio.h b/ANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/irq_gpio.h
new file mode 100755
index 00000000..0232bd04
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/aw5306_ts/irq_gpio.h
@@ -0,0 +1,13 @@
+#ifndef _LINUX_IRQ_GPIO_H
+#define _LINUX_IRQ_GPIO_H
+
+
+extern int wmt_enable_gpirq(int num);
+extern int wmt_disable_gpirq(int num);
+extern int wmt_is_tsirq_enable(int num);
+extern int wmt_is_tsint(int num);
+extern void wmt_clr_int(int num);
+extern int wmt_set_gpirq(int num, int type);
+
+
+#endif
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/cyp140_ts/Kconfig b/ANDROID_3.4.5/drivers/input/touchscreen/cyp140_ts/Kconfig
new file mode 100755
index 00000000..3a8e1de0
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/cyp140_ts/Kconfig
@@ -0,0 +1,16 @@
+#
+# CYP140 capacity touch screen driver configuration
+#
+config TOUCHSCREEN_CYP140
+ tristate "CYPRESS CYP140 I2C Capacitive Touchscreen Input Driver Support"
+ depends on ARCH_WMT
+ default m
+ help
+ Say Y here if you have an WMT based board with touchscreen
+ attached to it.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called s_wmt_ts_cyp140
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/cyp140_ts/Makefile b/ANDROID_3.4.5/drivers/input/touchscreen/cyp140_ts/Makefile
new file mode 100755
index 00000000..46229059
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/cyp140_ts/Makefile
@@ -0,0 +1,33 @@
+#KERNELDIR=/home/hangyan/android8850/kernel/ANDROID_3.0.8
+KERNELDIR=../../../../
+CROSS = arm_1103_le-
+CC= $(CROSS)gcc
+LD= $(CROSS)ld
+STRIP = $(CROSS)strip
+
+DEBUG = n
+
+# Add your debugging flag (or not) to EXTRA_CFLAGS
+ifeq ($(DEBUG),y)
+# DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+DEBFLAGS = -O0 -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+
+else
+ DEBFLAGS = -O2 -Wall
+endif
+
+EXTRA_CFLAGS += $(DEBFLAGS)
+
+
+MY_MODULE_NAME=s_wmt_ts_cyp140
+
+obj-$(CONFIG_TOUCHSCREEN_CYP140) := $(MY_MODULE_NAME).o
+#obj-m := $(MY_MODULE_NAME).o
+$(MY_MODULE_NAME)-objs := cyp140_i2c.o wmt_ts.o cyttsp_fw_upgrade.o
+
+default:
+ $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules
+ rm -rf *.o *~ core .depend .*.cmd *.mod.c .tmp_versions *.order *.symvers
+
+clean:
+ rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.order *.symvers
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/cyp140_ts/cyp140_i2c.c b/ANDROID_3.4.5/drivers/input/touchscreen/cyp140_ts/cyp140_i2c.c
new file mode 100755
index 00000000..ca4717ac
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/cyp140_ts/cyp140_i2c.c
@@ -0,0 +1,1412 @@
+/* drivers/input/touchscreen/cyp140_i2c.c
+ * 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.
+ * ZEITEC Semiconductor Co., Ltd
+ * Tel: +886-3-579-0045
+ * Fax: +886-3-579-9960
+ * http://www.zeitecsemi.com
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/platform_device.h>
+#include <linux/jiffies.h>
+#include <linux/io.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kthread.h>
+#include <linux/bitops.h>
+
+#include "wmt_ts.h"
+#define TP_POINTS_CNT 5
+#define U8 unsigned char
+//fw update.
+//#include "cyp140_fw.h"
+
+//****************************add for cyp140 2013-1-6
+//extern struct tpd_device *tpd;
+static struct i2c_client *i2c_client = NULL;
+static struct task_struct *thread = NULL;
+
+static DECLARE_WAIT_QUEUE_HEAD(waiter);
+
+#define TPD_DEVICE "cyp140"
+static int tpd_load_status = 0;//add !!!2013-1-6
+//static struct early_suspend early_suspend;
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static struct early_suspend early_suspend;
+static void tpd_early_suspend(struct early_suspend *handler);
+static void tpd_late_resume(struct early_suspend *handler);
+#endif
+
+static int tilt = 1, rev_x = -1, rev_y = 1;
+static int max_x = 1024, max_y = 600;
+//static int max_x = 800, max_y = 480;
+
+//extern void mt65xx_eint_unmask(unsigned int line);
+//extern void mt65xx_eint_mask(unsigned int line);
+//extern void mt65xx_eint_set_hw_debounce(kal_uint8 eintno, kal_uint32 ms);
+//extern kal_uint32 mt65xx_eint_set_sens(kal_uint8 eintno, kal_bool sens);
+//extern mt65xx_eint_set_polarity(unsigned int eint_num, unsigned int pol);
+//extern void mt65xx_eint_registration(kal_uint8 eintno, kal_bool Dbounce_En,
+ // kal_bool ACT_Polarity, void (EINT_FUNC_PTR)(void),
+ // kal_bool auto_umask);
+
+
+static irqreturn_t tpd_eint_interrupt_handler(int irq, void *dev_id);
+//static int tpd_get_bl_info(int show);
+static int __devinit tpd_probe(struct i2c_client *client);
+//static int tpd_detect(struct i2c_client *client, int kind, struct i2c_board_info *info);
+//static int __devexit tpd_remove(struct i2c_client *client);
+static int touch_event_handler(void *unused);
+//static int tpd_initialize(struct i2c_client * client);
+
+
+volatile static int tpd_flag = 0;//0; debug 2013-5-6
+
+#ifdef TPD_HAVE_BUTTON
+static int tpd_keys_local[TPD_KEY_COUNT] = TPD_KEYS;
+static int tpd_keys_dim_local[TPD_KEY_COUNT][4] = TPD_KEYS_DIM;
+#endif
+
+#define TPD_OK 0
+//#define TPD_EREA_Y 799
+//#define TPD_EREA_X 479
+#define TPD_EREA_Y 479
+#define TPD_EREA_X 319
+
+#define TPD_DISTANCE_LIMIT 100
+
+#define TPD_REG_BASE 0x00
+#define TPD_SOFT_RESET_MODE 0x01
+#define TPD_OP_MODE 0x00
+#define TPD_LOW_PWR_MODE 0x04
+#define TPD_SYSINFO_MODE 0x10
+#define GET_HSTMODE(reg) ((reg & 0x70) >> 4) // in op mode or not
+#define GET_BOOTLOADERMODE(reg) ((reg & 0x10) >> 4) // in bl mode
+//#define GPIO_CTP_EN_PIN_M_GPIO 0
+//#define GPIO_CTP_EN_PIN 0xff
+
+static u8 bl_cmd[] = {
+ 0x00, 0x00, 0xFF, 0xA5,
+ 0x00, 0x01, 0x02,
+ 0x03, 0x04, 0x05,
+ 0x06, 0x07};
+//exit bl mode
+struct tpd_operation_data_t{
+ U8 hst_mode;
+ U8 tt_mode;
+ U8 tt_stat;
+
+ U8 x1_M,x1_L;
+ U8 y1_M,y1_L;
+ U8 x5_M;
+ U8 touch12_id;
+
+ U8 x2_M,x2_L;
+ U8 y2_M,y2_L;
+ U8 x5_L;
+ U8 gest_cnt;
+ U8 gest_id;
+ //U8 gest_set;
+
+
+ U8 x3_M,x3_L;
+ U8 y3_M,y3_L;
+ U8 y5_M;
+ U8 touch34_id;
+
+ U8 x4_M,x4_L;
+ U8 y4_M,y4_L;
+ U8 y5_L;
+
+ //U8 x5_M,x5_L;
+ U8 Undefinei1B;
+ U8 Undefined1C;
+ U8 Undefined1D;
+ U8 GEST_SET;
+ U8 touch5_id;
+};
+
+struct tpd_bootloader_data_t{
+ U8 bl_file;
+ U8 bl_status;
+ U8 bl_error;
+ U8 blver_hi,blver_lo;
+ U8 bld_blver_hi,bld_blver_lo;
+
+ U8 ttspver_hi,ttspver_lo;
+ U8 appid_hi,appid_lo;
+ U8 appver_hi,appver_lo;
+
+ U8 cid_0;
+ U8 cid_1;
+ U8 cid_2;
+
+};
+
+struct tpd_sysinfo_data_t{
+ U8 hst_mode;
+ U8 mfg_cmd;
+ U8 mfg_stat;
+ U8 cid[3];
+ u8 tt_undef1;
+
+ u8 uid[8];
+ U8 bl_verh;
+ U8 bl_verl;
+
+ u8 tts_verh;
+ u8 tts_verl;
+
+ U8 app_idh;
+ U8 app_idl;
+ U8 app_verh;
+ U8 app_verl;
+
+ u8 tt_undef2[6];
+ U8 act_intrvl;
+ U8 tch_tmout;
+ U8 lp_intrvl;
+
+};
+
+struct touch_info {
+ int x[5];
+ int y[5];
+ int p[5];
+ int id[5];
+ int count;
+};
+
+struct id_info{
+ int pid1;
+ int pid2;
+ int reportid1;
+ int reportid2;
+ int id1;
+ int id2;
+
+};
+static struct tpd_operation_data_t g_operation_data;
+//static struct tpd_bootloader_data_t g_bootloader_data;
+//static struct tpd_sysinfo_data_t g_sysinfo_data;
+
+//********************************************************
+
+/* -------------- global variable definition -----------*/
+#define _MACH_MSM_TOUCH_H_
+
+#define ZET_TS_ID_NAME "cyp140-ts"
+
+#define MJ5_TS_NAME "cyp140_touchscreen"
+
+//#define TS_INT_GPIO S3C64XX_GPN(9) /*s3c6410*/
+//#define TS1_INT_GPIO AT91_PIN_PB17 /*AT91SAM9G45 external*/
+//#define TS1_INT_GPIO AT91_PIN_PA27 /*AT91SAM9G45 internal*/
+//#define TS_RST_GPIO S3C64XX_GPN(10)
+
+#define TS_RST_GPIO
+#define TPINFO 1
+#define X_MAX 800 //1024
+#define Y_MAX 480 //576
+#define FINGER_NUMBER 5
+#define KEY_NUMBER 3 //0
+#define P_MAX 1
+#define D_POLLING_TIME 25000
+#define U_POLLING_TIME 25000
+#define S_POLLING_TIME 100
+#define REPORT_POLLING_TIME 5
+
+#define MAX_KEY_NUMBER 8
+#define MAX_FINGER_NUMBER 16
+#define TRUE 1
+#define FALSE 0
+
+//#define debug_mode 1
+//#define DPRINTK(fmt,args...) do { if (debug_mode) printk(KERN_EMERG "[%s][%d] "fmt"\n", __FUNCTION__, __LINE__, ##args);} while(0)
+
+//#define TRANSLATE_ENABLE 1
+#define TOPRIGHT 0
+#define TOPLEFT 1
+#define BOTTOMRIGHT 2
+#define BOTTOMLEFT 3
+#define ORIGIN BOTTOMRIGHT
+
+#define TIME_CHECK_CHARGE 3000
+
+struct msm_ts_platform_data {
+ unsigned int x_max;
+ unsigned int y_max;
+ unsigned int pressure_max;
+};
+
+struct tpd_device{
+ struct i2c_client * client;//i2c_ts;
+ struct work_struct work1;
+ struct input_dev *input;
+ struct timer_list polling_timer;
+ struct delayed_work work; // for polling
+ struct workqueue_struct *queue;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend early_suspend;
+#endif
+ unsigned int gpio; /* GPIO used for interrupt of TS1*/
+ unsigned int irq;
+ unsigned int x_max;
+ unsigned int y_max;
+ unsigned int pressure_max;
+};
+//
+struct tpd_device *tpd;
+
+
+//static int l_suspend = 0; // 1:suspend, 0:normal state
+
+//static int resetCount = 0; //albert++ 20120807
+
+
+//static u16 polling_time = S_POLLING_TIME;
+
+//static int l_powermode = -1;
+//static struct mutex i2c_mutex;
+
+
+//static int __devinit cyp140_ts_probe(struct i2c_client *client, const struct i2c_device_id *id);
+//static int __devexit cyp140_ts_remove(struct i2c_client *dev);
+
+
+
+
+
+//static int filterCount = 0;
+//static u32 filterX[MAX_FINGER_NUMBER][2], filterY[MAX_FINGER_NUMBER][2];
+
+//static u8 key_menu_pressed = 0x1;
+//static u8 key_back_pressed = 0x1;
+//static u8 key_search_pressed = 0x1;
+
+//static u16 ResolutionX=X_MAX;
+//static u16 ResolutionY=Y_MAX;
+//static u16 FingerNum=0;
+//static u16 KeyNum=0;
+//static int bufLength=0;
+//static u8 xyExchange=0;
+//static u16 inChargerMode = 0;
+//static struct i2c_client *this_client;
+struct workqueue_struct *ts_wq = NULL;
+#if 0
+static int l_tskey[4][2] = {
+ {KEY_BACK,0},
+ {KEY_MENU,0},
+ {KEY_HOME,0},
+ {KEY_SEARCH,0},
+};
+#endif
+u8 pc[8];
+// {IC Model, FW Version, FW version,Codebase Type=0x08, Customer ID, Project ID, Config Board No, Config Serial No}
+
+//Touch Screen
+/*static const struct i2c_device_id cyp140_ts_idtable[] = {
+ { ZET_TS_ID_NAME, 0 },
+ { }
+};
+
+static struct i2c_driver cyp140_ts_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = ZET_TS_ID_NAME,
+ },
+ .probe = cyp140_ts_probe,
+ .remove = __devexit_p(cyp140_ts_remove),
+ .id_table = cyp140_ts_idtable,
+};
+*/
+
+
+/***********************************************************************
+ [function]:
+ callback: Timer Function if there is no interrupt fuction;
+ [parameters]:
+ arg[in]: arguments;
+ [return]:
+ NULL;
+************************************************************************/
+
+
+//extern int wmt_i2c_xfer_continue_if_4(struct i2c_msg *msg, unsigned int num,int bus_id);
+/***********************************************************************
+ [function]:
+ callback: read data by i2c interface;
+ [parameters]:
+ client[in]: struct i2c_client — represent an I2C slave device;
+ data [out]: data buffer to read;
+ length[in]: data length to read;
+ [return]:
+ Returns negative errno, else the number of messages executed;
+************************************************************************/
+int cyp140_i2c_read_tsdata(struct i2c_client *client, u8 *data, u8 length)
+{
+ struct i2c_msg msg;
+ msg.addr = client->addr;
+ msg.flags = I2C_M_RD;
+ msg.len = length;
+ msg.buf = data;
+ return i2c_transfer(client->adapter,&msg, 1);
+
+ /*int rc = 0;
+
+ memset(data, 0, length);
+ rc = i2c_master_recv(client, data, length);
+ if (rc <= 0)
+ {
+ errlog("error!\n");
+ return -EINVAL;
+ } else if (rc != length)
+ {
+ dbg("want:%d,real:%d\n", length, rc);
+ }
+ return rc;*/
+}
+
+/***********************************************************************
+ [function]:
+ callback: write data by i2c interface;
+ [parameters]:
+ client[in]: struct i2c_client — represent an I2C slave device;
+ data [out]: data buffer to write;
+ length[in]: data length to write;
+ [return]:
+ Returns negative errno, else the number of messages executed;
+************************************************************************/
+int cyp140_i2c_write_tsdata(struct i2c_client *client, u8 *data, u8 length)
+{
+ struct i2c_msg msg;
+ msg.addr = client->addr;
+ msg.flags = 0;
+ msg.len = length;
+ msg.buf = data;
+ return i2c_transfer(client->adapter,&msg, 1);
+
+ /*int ret = i2c_master_recv(client, data, length);
+ if (ret <= 0)
+ {
+ errlog("error!\n");
+ }
+ return ret;
+ */
+}
+
+/***********************************************************************
+ [function]:
+ callback: coordinate traslating;
+ [parameters]:
+ px[out]: value of X axis;
+ py[out]: value of Y axis;
+ p [in]: pressed of released status of fingers;
+ [return]:
+ NULL;
+************************************************************************/
+void touch_coordinate_traslating(u32 *px, u32 *py, u8 p)
+{
+ int i;
+ u8 pressure;
+
+ #if ORIGIN == TOPRIGHT
+ for(i=0;i<MAX_FINGER_NUMBER;i++){
+ pressure = (p >> (MAX_FINGER_NUMBER-i-1)) & 0x1;
+ if(pressure)
+ {
+ px[i] = X_MAX - px[i];
+ }
+ }
+ #elif ORIGIN == BOTTOMRIGHT
+ for(i=0;i<MAX_FINGER_NUMBER;i++){
+ pressure = (p >> (MAX_FINGER_NUMBER-i-1)) & 0x1;
+ if(pressure)
+ {
+ px[i] = X_MAX - px[i];
+ py[i] = Y_MAX - py[i];
+ }
+ }
+ #elif ORIGIN == BOTTOMLEFT
+ for(i=0;i<MAX_FINGER_NUMBER;i++){
+ pressure = (p >> (MAX_FINGER_NUMBER-i-1)) & 0x1;
+ if(pressure)
+ {
+ py[i] = Y_MAX - py[i];
+ }
+ }
+ #endif
+}
+
+/***********************************************************************
+ [function]:
+ callback: reset function;
+ [parameters]:
+ void;
+ [return]:
+ void;
+************************************************************************/
+void ctp_reset(void)
+{
+#if defined(TS_RST_GPIO)
+ //reset mcu
+ /* gpio_direction_output(TS_RST_GPIO, 1);
+ msleep(1);
+ gpio_direction_output(TS_RST_GPIO, 0);
+ msleep(10);
+ gpio_direction_output(TS_RST_GPIO, 1);
+ msleep(20);*/
+ wmt_rst_output(1);
+ msleep(1);
+ wmt_rst_output(0);
+ msleep(10);
+ wmt_rst_output(1);
+ msleep(20);
+ dbg("has done\n");
+#else
+ u8 ts_reset_cmd[1] = {0xb0};
+ cyp140_i2c_write_tsdata(this_client, ts_reset_cmd, 1);
+#endif
+
+}
+
+//*************************************************
+#if 1
+#include <linux/sched.h> //wake_up_process()
+#include <linux/kthread.h> //kthread_create()ã€kthread_run()
+//#include <err.h> //IS_ERR()ã€PTR_ERR()
+
+void cyttsp_sw_reset(void);
+//static struct task_struct *esd_task;
+volatile bool need_rst_flag = 0;
+volatile int tp_interrupt_flag = 0;
+volatile int tp_suspend_flag = 0;
+volatile int tp_reseting_flag = 0;
+
+void cyttsp_print_reg(struct i2c_client *client)
+{
+#if 1
+ char buffer[20];
+ int status=0;
+ int i;
+
+ status = i2c_smbus_read_i2c_block_data(i2c_client, 0x00, 16, &(buffer[0]));
+
+ printk("++++cyttsp_print_reg=%d: ",status);
+ for(i = 0; i<16;i++)
+ printk(" %02x", buffer[i]);
+ printk("\n");
+#endif
+
+}
+
+int exit_boot_mode(void)
+{
+
+ //int retval = TPD_OK;
+
+ char buffer[2];
+ int status=0;
+ status = i2c_smbus_read_i2c_block_data(i2c_client, 0x01, 1, &(buffer[0]));
+ if(status<0) {
+ printk ("++++exit_boot_mode failed---1\n");
+ return status;
+ }
+ else
+ {
+ if(buffer[0] & 0x10)
+ {
+ status = i2c_master_send(i2c_client, bl_cmd, 12);
+ if( status < 0)
+ {
+ printk ("++++exit_boot_mode failed---2\n");
+ return status;
+ }
+ else
+ {
+ //printk("++++exit_boot_mode ok\n");
+ }
+ msleep(300);
+ status = i2c_smbus_read_i2c_block_data(i2c_client, 0x01, 1, &(buffer[0]));
+ if(status<0) {
+ printk ("++++exit_boot_mode set failed\n");
+ return status;
+ }
+// printk("++++exit_boot_mode set: 0x%x\n",buffer[0]);
+ cyttsp_print_reg(i2c_client);
+ }
+ else
+ {
+ // printk("++++exit_boot_mode-- not in bootmode\n");
+ }
+
+ }
+ return 0;
+
+}
+
+void esd_check(void)
+{
+ if(need_rst_flag)
+ {
+ if(tp_suspend_flag == 0)
+ {
+ printk("++++esd_check---rst\n");
+ //mt65xx_eint_mask(CUST_EINT_TOUCH_PANEL_NUM);
+ tp_reseting_flag = 1;
+ cyttsp_sw_reset();
+ tp_reseting_flag = 0;
+ //mt65xx_eint_unmask(CUST_EINT_TOUCH_PANEL_NUM);
+ }
+ need_rst_flag = 0;
+ }
+}
+static int fp_count = 0;
+#if 0 //close 2013-1-6
+void esd_thread(void)
+{
+ static int i = 0, j = 0;
+ while(1)
+ {
+ printk("++++esd_thread, need_rst_flag=%d, fp_count=%d\n", need_rst_flag,fp_count);
+ fp_count = 0;
+ if(need_rst_flag)
+ {
+ j = 0;
+ while(tp_interrupt_flag==1 && j<200) //wujinyou
+ {
+ j ++;
+ if(tp_suspend_flag)
+ msleep(1000);
+ else
+ msleep(10);
+ }
+ if(tp_suspend_flag == 0)
+ {
+ printk("++++esd_thread, start reset, mask int\n");
+ //mt65xx_eint_mask(CUST_EINT_TOUCH_PANEL_NUM);
+ tp_reseting_flag = 1;
+ cyttsp_sw_reset();
+ i = 0;
+ need_rst_flag = 0;
+ tp_reseting_flag = 0;
+ //mt65xx_eint_unmask(CUST_EINT_TOUCH_PANEL_NUM);
+ }
+ }
+ msleep(1000);
+ i ++;
+ if(i == 10)
+ {
+ i = 0;
+ //cyttsp_sw_reset();
+ //need_rst_flag = 1;
+ }
+ }
+}
+static int esd_init_thread(void)
+{
+ int err;
+ printk("++++%s, line %d----\n", __FUNCTION__, __LINE__);
+
+ esd_task = kthread_create(esd_thread, NULL, "esd_task");
+
+ if(IS_ERR(esd_task)){
+ printk("++++Unable to start kernel thread.\n");
+ err = PTR_ERR(esd_task);
+ esd_task = NULL;
+ return err;
+ }
+
+ wake_up_process(esd_task);
+
+ return 0;
+
+}
+#endif //close 2013-1-6
+
+#endif
+
+static void tpd_down(int x, int y, int p) {
+
+
+ //printk("<<<<<<x,y (%d, %d)\n", x, y);//debug 2013-5-6
+
+//printk("++++tpd_down: %d,%d,%d\n", x, y, p);
+#if 0 //def TPD_HAVE_BUTTON
+ if (boot_mode != NORMAL_BOOT) {
+ if(y > 480) {
+ tpd_button(x, y, 1);
+ }
+ }
+#endif
+ //*****here process x y coord and then report!!!! 2013-1-7
+
+#if 1//0
+ int tmp;
+ if (tilt)
+ {
+ tmp = x;
+ x = y;
+ y =tmp;
+ }
+ if (rev_x < 0)
+ x = max_x -x;
+ if (rev_y < 0)
+ y = max_y -y;
+
+
+#endif
+ if (wmt_ts_get_lcdexchg()) {
+ int t;
+ t = x;
+ x = y;
+ y = max_x - t;
+ }
+
+ //printk("<<<<<< transfer x,y (%d, %d)\n", x, y);//debug 2013-5-6
+
+ input_report_abs(tpd->input, ABS_PRESSURE,p);
+ input_report_key(tpd->input, BTN_TOUCH, 1);
+ //input_report_abs(tpd->input,ABS_MT_TRACKING_ID,i);
+ input_report_abs(tpd->input, ABS_MT_TOUCH_MAJOR, 1);
+ input_report_abs(tpd->input, ABS_MT_POSITION_X, x);
+ input_report_abs(tpd->input, ABS_MT_POSITION_Y, y);
+ ////TPD_DEBUG("Down x:%4d, y:%4d, p:%4d \n ", x, y, p);
+ input_mt_sync(tpd->input);
+ //TPD_DOWN_DEBUG_TRACK(x,y);
+ fp_count ++;
+}
+
+static void tpd_up(int x, int y,int p) {
+
+ input_report_abs(tpd->input, ABS_PRESSURE, 0);
+ input_report_key(tpd->input, BTN_TOUCH, 0);
+ // input_report_abs(tpd->input,ABS_MT_TRACKING_ID,i);
+ input_report_abs(tpd->input, ABS_MT_TOUCH_MAJOR, 0);
+ //input_report_abs(tpd->input, ABS_MT_POSITION_X, x);
+ //input_report_abs(tpd->input, ABS_MT_POSITION_Y, y); //!!!!
+ //TPD_DEBUG("Up x:%4d, y:%4d, p:%4d \n", x, y, 0);
+ input_mt_sync(tpd->input);
+ // TPD_UP_DEBUG_TRACK(x,y);
+}
+void test_retval(s32 ret)
+{
+#if 1
+ if(ret<0)
+ {
+ need_rst_flag = 1;
+ printk("++++test_retval=1-------\n");
+ }
+#endif
+}
+static int tpd_touchinfo(struct touch_info *cinfo, struct touch_info *pinfo)
+{
+
+ s32 retval;
+ static u8 tt_mode;
+ //pinfo->count = cinfo->count;
+ u8 data0,data1;
+
+ memcpy(pinfo, cinfo, sizeof(struct touch_info));
+ memset(cinfo, 0, sizeof(struct touch_info));
+// printk("pinfo->count =%d\n",pinfo->count);
+
+ retval = i2c_smbus_read_i2c_block_data(i2c_client, TPD_REG_BASE, 8, (u8 *)&g_operation_data);
+ retval += i2c_smbus_read_i2c_block_data(i2c_client, TPD_REG_BASE + 8, 8, (((u8 *)(&g_operation_data)) + 8));
+ retval += i2c_smbus_read_i2c_block_data(i2c_client, TPD_REG_BASE + 16, 8, (((u8 *)(&g_operation_data)) + 16));
+ retval += i2c_smbus_read_i2c_block_data(i2c_client, TPD_REG_BASE + 24, 8, (((u8 *)(&g_operation_data)) + 24));
+
+
+ //cyttsp_print_reg(i2c_client);
+ ////TPD_DEBUG("received raw data from touch panel as following:\n");
+
+ /*("hst_mode = %02X, tt_mode = %02X, tt_stat = %02X\n", \
+ g_operation_data.hst_mode,\
+ g_operation_data.tt_mode,\
+ g_operation_data.tt_stat); */
+
+ cinfo->count = (g_operation_data.tt_stat & 0x0f) ; //point count
+
+ //TPD_DEBUG("cinfo->count =%d\n",cinfo->count);
+
+ //TPD_DEBUG("Procss raw data...\n");
+
+ cinfo->x[0] = (( g_operation_data.x1_M << 8) | ( g_operation_data.x1_L)); //point 1
+ cinfo->y[0] = (( g_operation_data.y1_M << 8) | ( g_operation_data.y1_L));
+ cinfo->p[0] = 0;//g_operation_data.z1;
+
+ //printk("Before: cinfo->x0 = %3d, cinfo->y0 = %3d, cinfo->p0 = %3d cinfo->id0 = %3d\n", cinfo->x[0] ,cinfo->y[0] ,cinfo->p[0], cinfo->id[0]);
+ if(cinfo->x[0] < 1) cinfo->x[0] = 1;
+ if(cinfo->y[0] < 1) cinfo->y[0] = 1;
+ cinfo->id[0] = ((g_operation_data.touch12_id & 0xf0) >>4) -1;
+ //printk("After: cinfo->x0 = %3d, cinfo->y0 = %3d, cinfo->p0 = %3d cinfo->id0 = %3d\n", cinfo->x[0] ,cinfo->y[0] ,cinfo->p[0], cinfo->id[0]);
+
+ if(cinfo->count >1)
+ {
+ cinfo->x[1] = (( g_operation_data.x2_M << 8) | ( g_operation_data.x2_L)); //point 2
+ cinfo->y[1] = (( g_operation_data.y2_M << 8) | ( g_operation_data.y2_L));
+ cinfo->p[1] = 0;//g_operation_data.z2;
+
+ //printk("before: cinfo->x2 = %3d, cinfo->y2 = %3d, cinfo->p2 = %3d\n", cinfo->x2, cinfo->y2, cinfo->p2);
+ if(cinfo->x[1] < 1) cinfo->x[1] = 1;
+ if(cinfo->y[1] < 1) cinfo->y[1] = 1;
+ cinfo->id[1] = ((g_operation_data.touch12_id & 0x0f)) -1;
+ //printk("After: cinfo->x[1] = %3d, cinfo->y[1] = %3d, cinfo->p[1] = %3d, cinfo->id[1] = %3d\n", cinfo->x[1], cinfo->y[1], cinfo->p[1], cinfo->id[1]);
+
+ if (cinfo->count > 2)
+ {
+ cinfo->x[2]= (( g_operation_data.x3_M << 8) | ( g_operation_data.x3_L)); //point 3
+ cinfo->y[2] = (( g_operation_data.y3_M << 8) | ( g_operation_data.y3_L));
+ cinfo->p[2] = 0;//g_operation_data.z3;
+ cinfo->id[2] = ((g_operation_data.touch34_id & 0xf0) >> 4) -1;
+
+ //printk("before: cinfo->x[2] = %3d, cinfo->y[2] = %3d, cinfo->p[2] = %3d\n", cinfo->x[2], cinfo->y[2], cinfo->p[2]);
+ if(cinfo->x[2] < 1) cinfo->x[2] = 1;
+ if(cinfo->y[2]< 1) cinfo->y[2] = 1;
+ //printk("After: cinfo->x[2]= %3d, cinfo->y[2] = %3d, cinfo->p[2]= %3d, cinfo->id[2] = %3d\n", cinfo->x[2], cinfo->y[2], cinfo->p[2], cinfo->id[2]);
+
+ if (cinfo->count > 3)
+ {
+ cinfo->x[3] = (( g_operation_data.x4_M << 8) | ( g_operation_data.x4_L)); //point 3
+ cinfo->y[3] = (( g_operation_data.y4_M << 8) | ( g_operation_data.y4_L));
+ cinfo->p[3] = 0;//g_operation_data.z4;
+ cinfo->id[3] = ((g_operation_data.touch34_id & 0x0f)) -1;
+
+ //printk("before: cinfo->x[3] = %3d, cinfo->y[3] = %3d, cinfo->p[3] = %3d, cinfo->id[3] = %3d\n", cinfo->x[3], cinfo->y[3], cinfo->p[3], cinfo->id[3]);
+ //printk("before: x4_M = %3d, x4_L = %3d\n", g_operation_data.x4_M, g_operation_data.x4_L);
+ if(cinfo->x[3] < 1) cinfo->x[3] = 1;
+ if(cinfo->y[3] < 1) cinfo->y[3] = 1;
+ //printk("After: cinfo->x[3] = %3d, cinfo->y[3] = %3d, cinfo->p[3]= %3d, cinfo->id[3] = %3d\n", cinfo->x[3], cinfo->y[3], cinfo->p[3], cinfo->id[3]);
+ }
+ if (cinfo->count > 4)
+ {
+ cinfo->x[4] = (( g_operation_data.x5_M << 8) | ( g_operation_data.x5_L)); //point 3
+ cinfo->y[4] = (( g_operation_data.y5_M << 8) | ( g_operation_data.y5_L));
+ cinfo->p[4] = 0;//g_operation_data.z4;
+ cinfo->id[4] = ((g_operation_data.touch5_id & 0xf0) >> 4) -1;
+
+ //printk("before: cinfo->x[4] = %3d, cinfo->y[4] = %3d, cinfo->id[4] = %3d\n", cinfo->x[4], cinfo->y[4], cinfo->id[4]);
+ //printk("before: x5_M = %3d, x5_L = %3d\n", g_operation_data.x5_M, g_operation_data.x5_L);
+ if(cinfo->x[4] < 1) cinfo->x[4] = 1;
+ if(cinfo->y[4] < 1) cinfo->y[4] = 1;
+ //printk("After: cinfo->x[4] = %3d, cinfo->y[4] = %3d, cinfo->id[4] = %3d\n", cinfo->x[4], cinfo->y[4], cinfo->id[4]);
+ }
+ }
+
+ }
+
+ if (!cinfo->count) return true; // this is a touch-up event
+
+ if (g_operation_data.tt_mode & 0x20) {
+ //TPD_DEBUG("uffer is not ready for use!\n");
+ memcpy(cinfo, pinfo, sizeof(struct touch_info));
+ return false;
+ }//return false; // buffer is not ready for use// buffer is not ready for use
+
+ // data toggle
+
+ data0 = i2c_smbus_read_i2c_block_data(i2c_client, TPD_REG_BASE, 1, (u8*)&g_operation_data);
+ ////TPD_DEBUG("before hst_mode = %02X \n", g_operation_data.hst_mode);
+
+ if((g_operation_data.hst_mode & 0x80)==0)
+ g_operation_data.hst_mode = g_operation_data.hst_mode|0x80;
+ else
+ g_operation_data.hst_mode = g_operation_data.hst_mode & (~0x80);
+
+ ////TPD_DEBUG("after hst_mode = %02X \n", g_operation_data.hst_mode);
+ data1 = i2c_smbus_write_i2c_block_data(i2c_client, TPD_REG_BASE, sizeof(g_operation_data.hst_mode), &g_operation_data.hst_mode);
+
+
+ if (tt_mode == g_operation_data.tt_mode) {
+ //TPD_DEBUG("sampling not completed!\n");
+ memcpy(cinfo, pinfo, sizeof(struct touch_info));
+ return false;
+ }// sampling not completed
+ else
+ tt_mode = g_operation_data.tt_mode;
+
+ return true;
+
+};
+
+static int touch_event_handler(void *unused)
+{
+ int i,j;
+ int keeppoint[5];
+ struct touch_info cinfo, pinfo;
+ struct sched_param param = { .sched_priority = 70/*RTPM_PRIO_TPD*/ };
+ sched_setscheduler(current, SCHED_RR, &param);
+
+ do
+ {
+ //printk("++++%s, line %d----unmask int\n", __FUNCTION__, __LINE__);
+ // mt65xx_eint_unmask(CUST_EINT_TOUCH_PANEL_NUM);
+ wmt_enable_gpirq();
+ set_current_state(TASK_INTERRUPTIBLE);
+ tp_interrupt_flag = 0;
+ //printk("++++%s, line %d----end\n", __FUNCTION__, __LINE__);
+ wait_event_interruptible(waiter,tpd_flag!=0);
+// printk("++++%s, line %d----start\n", __FUNCTION__, __LINE__);
+
+ tpd_flag = 0; //debg 2013-5-6
+ set_current_state(TASK_RUNNING);
+
+ exit_boot_mode();
+ if (tpd_touchinfo(&cinfo, &pinfo))
+ {
+ memset(keeppoint, 0x0, sizeof(keeppoint));
+ if(cinfo.count >0 && cinfo.count < (TP_POINTS_CNT+1))
+ {
+ switch(cinfo.count)
+ {
+ case 5:
+ {
+ tpd_down(cinfo.x[4], cinfo.y[4], cinfo.p[4]);
+ }
+ case 4:
+ {
+ tpd_down(cinfo.x[3], cinfo.y[3], cinfo.p[3]);
+ }
+ case 3:
+ {
+ tpd_down(cinfo.x[2], cinfo.y[2], cinfo.p[2]);
+ }
+ case 2:
+ {
+ tpd_down(cinfo.x[1], cinfo.y[1], cinfo.p[1]);
+ }
+ case 1:
+ {
+ tpd_down(cinfo.x[0], cinfo.y[0], cinfo.p[0]);
+ }
+ default:
+ break;
+ }
+ for(i = 0; i < cinfo.count; i++)
+ for(j = 0; j < pinfo.count; j++)
+ {
+ if(cinfo.id[i] == pinfo.id[j])keeppoint[j] = 1;
+ else if(keeppoint[j] != 1)keeppoint[j] = 0;
+ }
+
+ for(j = 0; j < pinfo.count; j++)
+ {
+ if(keeppoint[j] != 1)
+ {
+ tpd_up(pinfo.x[j], pinfo.y[j], pinfo.p[j]);
+ }
+ }
+
+ }
+ else if(cinfo.count == 0 && pinfo.count !=0)
+ {
+ switch(pinfo.count )
+ {
+ case 5:
+ {
+ tpd_up(pinfo.x[4], pinfo.y[4], pinfo.p[4]);
+ }
+ case 4:
+ {
+ tpd_up(pinfo.x[3], pinfo.y[3], pinfo.p[3]);
+ }
+ case 3:
+ {
+ tpd_up(pinfo.x[2], pinfo.y[2], pinfo.p[2]);
+ }
+ case 2:
+ {
+ tpd_up(pinfo.x[1], pinfo.y[1], pinfo.p[1]);
+ }
+ case 1:
+ {
+ tpd_up(pinfo.x[0], pinfo.y[0], pinfo.p[0]);
+ }
+ default:
+ break;
+ }
+ }
+
+ input_sync(tpd->input);
+
+ }
+
+
+
+ }while(!kthread_should_stop());
+ tp_interrupt_flag = 0;
+
+ return 0;
+}
+
+
+
+
+static irqreturn_t tpd_eint_interrupt_handler(int irq, void *dev_id)
+{
+ static int i = 0;
+ i ++;
+ //printk("++++eint=%d\n",i);
+
+ //mt65xx_eint_mask(CUST_EINT_TOUCH_PANEL_NUM);
+// printk("++++%s, line %d, tpd_flag=%d,i=%d\n", __FUNCTION__, __LINE__, tpd_flag,i);
+
+ if (wmt_is_tsint())
+ {
+ // printk("<<<<in %s\n", __FUNCTION__);
+ wmt_clr_int();
+ //return IRQ_HANDLED;//!!!!!
+ if (wmt_is_tsirq_enable())
+ {
+ wmt_disable_gpirq();
+ }
+ tp_interrupt_flag = 1;
+ ////TPD_DEBUG("TPD interrupt has been triggered\n");
+ //if(tpd_flag)
+ //return;
+ tpd_flag = 1;
+ wake_up_interruptible(&waiter);
+
+ return IRQ_HANDLED;
+
+ }
+ return IRQ_NONE;
+}
+static void ctp_power_on(int on)
+{
+ printk("++++ctp_power_on = %d\n",on);
+ //return ;
+
+ if(on == 1)
+ {
+ //mt_set_gpio_mode(GPIO_CTP_EN_PIN, GPIO_CTP_EN_PIN_M_GPIO);
+ //mt_set_gpio_dir(GPIO_CTP_EN_PIN, GPIO_DIR_OUT);
+ //mt_set_gpio_out(GPIO_CTP_EN_PIN, GPIO_OUT_ONE);
+ ;
+
+ }
+ else
+ {
+ //return -EIO;
+ ;
+ }
+}
+//}
+
+#include "cyttsp.h"
+extern void cyttsp_fw_upgrade(void);
+void cyttsp_hw_reset(void)
+{
+ ctp_power_on(0); //wujinyou
+ msleep(200);
+
+ ctp_power_on(1); //wujinyou
+ msleep(100);
+ //mt_set_gpio_mode(GPIO_CTP_RST_PIN, GPIO_CTP_RST_PIN_M_GPIO);
+// mt_set_gpio_dir(GPIO_CTP_RST_PIN, GPIO_DIR_OUT);
+ //mt_set_gpio_out(GPIO_CTP_RST_PIN, GPIO_OUT_ONE);
+ msleep(100);
+ //mt_set_gpio_out(GPIO_CTP_RST_PIN, GPIO_OUT_ZERO);
+ msleep(100);
+}
+void cyttsp_sw_reset(void)
+{
+ //int retval = TPD_OK;
+// int status = 0;
+ printk("++++cyttsp_sw_reset---------start\n");
+#if 0//1
+ mt_set_gpio_mode(GPIO_CTP_RST_PIN, GPIO_CTP_RST_PIN_M_GPIO);
+ mt_set_gpio_dir(GPIO_CTP_RST_PIN, GPIO_DIR_OUT);
+ mt_set_gpio_out(GPIO_CTP_RST_PIN, GPIO_OUT_ONE);
+ msleep(20);
+ ctp_power_on(0);
+ msleep(200);
+ #if 1
+ ctp_power_on(1);
+ #endif
+
+ msleep(20);
+ mt_set_gpio_out(GPIO_CTP_RST_PIN, GPIO_OUT_ZERO);
+ msleep(100);
+
+ ////TPD_DEBUG("TPD wake up\n");
+ status = i2c_master_send(i2c_client, bl_cmd, 12);
+ if( status < 0)
+ {
+ printk("++++ [cyttsp_sw_reset], cyttsp tpd exit bootloader mode failed--tpd_resume!\n");
+ return status;
+ }
+ msleep(300);
+ //exit_boot_mode();
+ //mt65xx_eint_unmask(CUST_EINT_TOUCH_PANEL_NUM);
+#endif
+ printk("++++cyttsp_sw_reset---------end\n");
+ //return retval;
+}
+
+
+//***************cyp140 probe 2013-1-6
+// wmtenv set wmt.io.touch 1:cyp140:7:600:1024:4:0:1:-1:5 //ok 2013-5-8
+static int __devinit tpd_probe(struct i2c_client *client)
+{
+ struct input_dev *input_dev;
+ int retval = TPD_OK;
+ int gpio_irq = wmt_ts_get_irqgpnum();
+ int gpio_rst = wmt_ts_get_resetgpnum();
+ //int result;
+ i2c_client = client;
+
+ retval = gpio_request(gpio_irq, "ts_irq");
+ if (retval < 0) {
+ printk("gpio(%d) touchscreen irq request fail\n", gpio_irq);
+ return retval;
+ }
+
+ retval = gpio_request(gpio_rst, "ts_rst");
+ if (retval < 0) {
+ printk("gpio(%d) touchscreen reset request fail\n", gpio_rst);
+ goto Fail_request_rstgpio;
+ }
+ //char buffer[2];
+ //int status=0;
+
+ //int res_x, res_y;
+
+ printk("<<< enter %s: %d\n",__FUNCTION__, __LINE__);
+
+#if 1 //0
+ tilt = wmt_ts_get_xaxis();
+ rev_x = wmt_ts_get_xdir();
+ rev_y = wmt_ts_get_ydir();
+#if 0
+ if (tilt){
+ max_y = wmt_ts_get_resolvX();
+ max_x = wmt_ts_get_resolvY();
+ }
+ else
+ {
+ max_x = wmt_ts_get_resolvX();
+ max_y =wmt_ts_get_resolvY();
+ }
+#else
+ max_x = wmt_ts_get_resolvX();
+ max_y =wmt_ts_get_resolvY();
+#endif
+
+#endif
+#if 0
+ if (0)
+ {
+ res_x = max_y;
+ res_y = max_x;
+ }
+ else
+ {
+ res_x = max_x;
+ res_y = max_y;
+ }
+ max_x = res_x;
+ max_y = res_y;
+#endif
+ //************************add input device 2013-1-6
+ tpd = kzalloc(sizeof(struct tpd_device), GFP_KERNEL);
+
+ input_dev = input_allocate_device();
+ if (!input_dev || !tpd) {
+ return -ENOMEM;
+ }
+
+ tpd->client/*i2c_ts*/ = client;
+ i2c_set_clientdata(client, tpd);
+ tpd->input = input_dev;
+
+ input_dev->name = "touch_cyp140"; //MJ5_TS_NAME;
+ input_dev->phys = "cyp140_touch/input0";
+ input_dev->id.bustype = BUS_HOST;
+ input_dev->id.vendor = 0x0001;
+ input_dev->id.product = 0x0002;
+ input_dev->id.version = 0x0100;
+
+ input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+ if (wmt_ts_get_lcdexchg()) {
+ input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, max_y/*480*//*600*//*ResolutionX*//*ResolutionX*/, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, max_x /*ResolutionY*//*800*//* 1024*/, 0, 0);
+ } else {
+ input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, max_x/*480*//*600*//*ResolutionX*//*ResolutionX*/, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, max_y /*ResolutionY*//*800*//* 1024*/, 0, 0);
+ }
+
+ set_bit(KEY_BACK, input_dev->keybit);
+ set_bit(KEY_HOME, input_dev->keybit);
+ set_bit(KEY_MENU, input_dev->keybit);
+ retval = input_register_device(input_dev);
+ if (retval)
+ {
+ printk("%s input register device error!!\n", __FUNCTION__);
+ goto E_REG_INPUT;
+ }
+ //****************************
+ //ctp_power_on(1); //wujinyou //!!!!2013-1-6
+
+ msleep(1000);
+
+ //printk("<<<<here ??/\n");
+ //************************add for wmt 2013-1-6
+ wmt_tsreset_init();
+ wmt_set_rst_pull(1);
+ //wmt_enable_rst_pull(1);
+ wmt_rst_output(1);
+
+ wmt_set_gpirq(IRQ_TYPE_EDGE_FALLING);
+ //wmt_set_gpirq(IRQ_TYPE_EDGE_RISING); //debug 2013-5-8 also no interrupt
+ wmt_disable_gpirq();
+
+ tpd->irq = wmt_get_tsirqnum();
+ retval = request_irq(tpd->irq, tpd_eint_interrupt_handler,IRQF_SHARED, "cypcm", tpd);
+ //****************************************
+
+ printk("tpd_probe request_irq retval=%d!\n",retval);
+ msleep(100);
+ msleep(1000);
+
+ cust_ts.client = i2c_client;
+// cyttsp_fw_upgrade(); //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+#if 0 //by linda 20130126
+ status = i2c_smbus_read_i2c_block_data(i2c_client, 0x01, 1, &(buffer[0]));
+ printk("tpd_probe request_irq status=%d!\n",status);
+
+ retval = i2c_master_send(i2c_client, bl_cmd, 12);
+ if( retval < 0)
+ {
+ printk("tpd_probe i2c_master_send retval=%d!\n",retval);
+
+ //return retval;
+ goto I2C_ERR;
+ }
+#else
+ retval = exit_boot_mode();
+ if (retval)
+ {
+ printk("%s exit_boot_mod error!\n", __FUNCTION__);
+ goto I2C_ERR;
+ }
+
+#endif
+/*
+ msleep(1000);
+ retval = i2c_smbus_read_i2c_block_data(i2c_client, 0x00, 1, &(buffer[0]));
+ if(retval<0) {
+ retval = i2c_smbus_read_i2c_block_data(i2c_client, 0x00, 1, &(buffer[0]));
+ if(retval<0) {
+ printk("error read !%d\n", __LINE__);
+
+ goto I2C_ERR;
+ }
+ }
+*/
+ //TPD_DEBUG("[mtk-tpd], cyttsp tpd_i2c_probe success!!\n");
+ tpd_load_status = 1;
+ thread = kthread_run(touch_event_handler, 0, TPD_DEVICE);
+ if (IS_ERR(thread)) {
+ retval = PTR_ERR(thread);
+ return retval;
+
+ }
+
+
+ msleep(100);
+ printk("++++tpd_probe,retval=%d\n", retval);
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ tpd->early_suspend.suspend = tpd_early_suspend,
+ tpd->early_suspend.resume = tpd_late_resume,
+ tpd->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB + 1;//,EARLY_SUSPEND_LEVEL_DISABLE_FB + 2;
+ register_early_suspend(&tpd->early_suspend);
+#endif
+ //disable_irq(cyp140_ts->irq);
+
+ wmt_enable_gpirq();
+
+//cust_timer_init();
+// esd_init_thread(); //close it 2013-1-6
+ return 0; //retval;
+ I2C_ERR:
+ free_irq(tpd->irq, tpd);
+ input_unregister_device(input_dev); //
+ E_REG_INPUT:
+ input_free_device(input_dev);
+ kfree(tpd);
+ //return retval;
+ Fail_request_rstgpio:
+ gpio_free(gpio_rst);
+ gpio_free(gpio_irq);
+ return retval;
+
+}
+//*******************************
+
+//module_init(cyp140_ts_init);
+static int tpd_local_init(void)
+{
+ if (tpd_probe(ts_get_i2c_client()))// ????
+ {
+ return -1;
+ }
+
+
+ if(tpd_load_status == 0){
+ //return -1;
+ ;
+ }
+
+#ifdef TPD_HAVE_BUTTON
+ tpd_button_setting(TPD_KEY_COUNT, tpd_keys_local, tpd_keys_dim_local);// initialize tpd button data
+ boot_mode = get_boot_mode();
+#endif
+ return 0;//!!!!2013-1-7
+}
+
+//**********************suspend & resume
+static int tpd_resume(/*struct i2c_client *client*/struct platform_device *pdev)
+{
+ int retval = TPD_OK;
+ int status = 0;
+ printk("++++%s, line %d----end\n", __FUNCTION__, __LINE__);
+ //mt65xx_eint_mask(CUST_EINT_TOUCH_PANEL_NUM);
+ msleep(100);
+ #if 1
+ ctp_power_on(1);
+ #endif
+
+ msleep(1);
+ wmt_rst_output(0);
+ msleep(1);
+ wmt_rst_output(1);
+ msleep(100);
+
+ wmt_set_gpirq(IRQ_TYPE_EDGE_FALLING);//sometimes gpio7 will in low after resume 2013-5-9
+ wmt_enable_gpirq();
+ printk("++++%s, line %d----end\n", __FUNCTION__, __LINE__);
+
+ //TPD_DEBUG("TPD wake up\n");
+
+ #if 0 //0 // by linda 20120126 change rambo 2013-5-6
+ status = i2c_master_send(i2c_client, bl_cmd, 12);
+ #else
+ exit_boot_mode();
+ #endif
+ printk("++++%s, line %d----end\n", __FUNCTION__, __LINE__);
+
+ if( status < 0)
+ {
+ printk("++++ [mtk-tpd], cyttsp tpd exit bootloader mode failed--tpd_resume!\n");
+ return status;
+ }
+ //exit_boot_mode();
+ printk("++++%s, line %d----end\n", __FUNCTION__, __LINE__);
+ msleep(300);
+ //wmt_enable_gpirq(); //debg 2013-5-6
+ tp_suspend_flag = 0;
+ return retval;
+}
+
+static int tpd_suspend(/*struct i2c_client *client*/struct platform_device *pdev, pm_message_t message)
+{
+ int i = 0;
+ int retval = TPD_OK;
+ //u8 sleep_mode = 0x02; // 0x02--CY_DEEP_SLEEP_MODE, 0x04--CY_LOW_PWR_MODE
+ //TPD_DEBUG("TPD enter sleep\n");
+ //u8 sleep_reg[2] = {0, 2};
+ printk("++++%s, line %d----end\n", __FUNCTION__, __LINE__);
+ wmt_disable_gpirq();
+ //wmt_disable_gpirq(); //dbg 2013-5-6
+
+ while((tp_reseting_flag || tp_interrupt_flag) && i<30)
+ {
+ i ++;
+ msleep(100);
+ }
+ tp_suspend_flag = 1;
+#if 1
+ //retval = i2c_smbus_write_i2c_block_data(i2c_client,0x00,sizeof(sleep_mode), &sleep_mode);
+ //retval = i2c_master_send(i2c_client, sleep_reg, 2); //send cmd error -5!
+ msleep(1);
+ ctp_power_on(0);
+ mdelay(1);
+#else
+ mt_set_gpio_mode(GPIO_CTP_RST_PIN, GPIO_CTP_RST_PIN_M_GPIO);
+ mt_set_gpio_dir(GPIO_CTP_RST_PIN, GPIO_DIR_OUT);
+ mt_set_gpio_out(GPIO_CTP_RST_PIN, GPIO_OUT_ONE);
+#endif
+
+ return retval;
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void tpd_early_suspend(struct early_suspend *handler)
+{
+ tpd_suspend(i2c_client, PMSG_SUSPEND);
+}
+
+static void tpd_late_resume(struct early_suspend *handler)
+{
+ tpd_resume(i2c_client);
+}
+#endif
+//****************************
+
+
+static void cyp140_ts_exit(void)
+{
+ printk("<<<%s\n", __FUNCTION__);
+
+ wmt_disable_gpirq();
+ free_irq(tpd->irq, tpd);
+ //kthread_stop(thread); // halt rmmod??
+ input_unregister_device(tpd->input); //
+
+ input_free_device(tpd->input);
+ kfree(tpd);
+ gpio_free(wmt_ts_get_irqgpnum());
+ gpio_free(wmt_ts_get_resetgpnum());
+}
+//module_exit(cyp140_ts_exit);
+
+void cyp140_set_ts_mode(u8 mode)
+{
+ dbg( "[Touch Screen]ts mode = %d \n", mode);
+}
+//EXPORT_SYMBOL_GPL(cyp140_set_ts_mode);
+
+struct wmtts_device cyp140_tsdev = {
+ .driver_name = WMT_TS_I2C_NAME,
+ .ts_id = "cyp140",
+ .init = tpd_local_init,
+ .exit = cyp140_ts_exit,
+ .suspend = tpd_suspend,
+ .resume = tpd_resume,
+};
+
+
+
+MODULE_DESCRIPTION("cyp140 I2C Touch Screen driver");
+MODULE_LICENSE("GPL v2");
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/cyp140_ts/cyttsp.h b/ANDROID_3.4.5/drivers/input/touchscreen/cyp140_ts/cyttsp.h
new file mode 100755
index 00000000..6020018f
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/cyp140_ts/cyttsp.h
@@ -0,0 +1,696 @@
+/* Header file for:
+ * Cypress TrueTouch(TM) Standard Product touchscreen drivers.
+ * include/linux/cyttsp.h
+ *
+ * Copyright (C) 2009, 2010 Cypress Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2, and only version 2, as published by the
+ * Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Cypress reserves the right to make changes without further notice
+ * to the materials described herein. Cypress does not assume any
+ * liability arising out of the application described herein.
+ *
+ * Contact Cypress Semiconductor at www.cypress.com
+ *
+ */
+
+
+#ifndef __CYTTSP_H__
+#define __CYTTSP_H__
+
+#include <linux/input.h>
+#include <linux/timer.h>
+#include <linux/workqueue.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+
+#include <asm/mach-types.h>
+
+#define CYPRESS_TTSP_NAME "cyttsp"
+#define CY_I2C_NAME "cyttsp-i2c"
+#define CY_SPI_NAME "cyttsp-spi"
+
+#ifdef CY_DECLARE_GLOBALS
+ uint32_t cyttsp_tsdebug;
+ module_param_named(tsdebug, cyttsp_tsdebug, uint, 0664);
+ uint32_t cyttsp_tsxdebug;
+ module_param_named(tsxdebug, cyttsp_tsxdebug, uint, 0664);
+
+ uint32_t cyttsp_disable_touch;
+ module_param_named(disable_touch, cyttsp_disable_touch, uint, 0664);
+#else
+ extern uint32_t cyttsp_tsdebug;
+ extern uint32_t cyttsp_tsxdebug;
+ extern uint32_t cyttsp_disable_touch;
+#endif
+
+
+
+/******************************************************************************
+ * Global Control, Used to control the behavior of the driver
+ */
+
+/* defines for Gen2 (Txx2xx); Gen3 (Txx3xx)
+ * use these defines to set cyttsp_platform_data.gen in board config file
+ */
+#define CY_GEN2 2
+#define CY_GEN3 3
+
+/* define for using I2C driver
+ */
+#define CY_USE_I2C_DRIVER
+
+/* defines for using SPI driver */
+/*
+#define CY_USE_SPI_DRIVER
+ */
+#define CY_SPI_DFLT_SPEED_HZ 1000000
+#define CY_SPI_MAX_SPEED_HZ 4000000
+#define CY_SPI_SPEED_HZ CY_SPI_DFLT_SPEED_HZ
+#define CY_SPI_BITS_PER_WORD 8
+#define CY_SPI_DAV 139 /* set correct gpio id */
+#define CY_SPI_BUFSIZE 512
+
+/* Voltage and Current ratings */
+#define CY_TMA300_VTG_MAX_UV 5500000
+#define CY_TMA300_VTG_MIN_UV 1710000
+#define CY_TMA300_CURR_24HZ_UA 17500
+#define CY_I2C_VTG_MAX_UV 1800000
+#define CY_I2C_VTG_MIN_UV 1800000
+#define CY_I2C_CURR_UA 9630
+
+
+/* define for inclusion of TTSP App Update Load File
+ * use this define if update to the TTSP Device is desired
+ */
+/*
+#define CY_INCLUDE_LOAD_FILE
+*/
+
+/* define if force new load file for bootloader load */
+/*
+#define CY_FORCE_FW_UPDATE
+*/
+
+/* undef for production use */
+/*
+#define CY_USE_DEBUG
+*/
+
+/* undef for irq use; use this define in the board configuration file */
+/*
+#define CY_USE_TIMER
+ */
+
+/* undef to allow use of extra debug capability */
+/*
+#define CY_ALLOW_EXTRA_DEBUG
+*/
+
+/* undef to remove additional debug prints */
+/*
+#define CY_USE_EXTRA_DEBUG
+*/
+
+/* undef to remove additional debug prints */
+/*
+#define CY_USE_EXTRA_DEBUG1
+ */
+
+/* undef to use operational touch timer jiffies; else use test jiffies */
+/*
+ */
+ /*
+#define CY_USE_TIMER_DEBUG
+*/
+/* define to use canned test data */
+/*
+#define CY_USE_TEST_DATA
+ */
+
+/* define if gesture signaling is used
+ * and which gesture groups to use
+ */
+/*
+#define CY_USE_GEST
+#define CY_USE_GEST_GRP1
+#define CY_USE_GEST_GRP2
+#define CY_USE_GEST_GRP3
+#define CY_USE_GEST_GRP4
+ */
+/* Active distance in pixels for a gesture to be reported
+ * if set to 0, then all gesture movements are reported
+ */
+#define CY_ACT_DIST_DFLT 8
+#define CY_ACT_DIST CY_ACT_DIST_DFLT
+
+/* define if MT signals are desired */
+/*
+*/
+#define CY_USE_MT_SIGNALS
+
+/* define if MT tracking id signals are used */
+/*
+#define CY_USE_MT_TRACK_ID
+ */
+
+/* define if ST signals are required */
+/*
+*/
+//#define CY_USE_ST_SIGNALS
+
+/* define to send handshake to device */
+/*
+*/
+#define CY_USE_HNDSHK
+
+/* define if log all raw motion signals to a sysfs file */
+/*
+#define CY_LOG_TO_FILE
+*/
+
+
+/* End of the Global Control section
+ ******************************************************************************
+ */
+#define CY_DIFF(m, n) ((m) != (n))
+
+#ifdef CY_LOG_TO_FILE
+ #define cyttsp_openlog() /* use sysfs */
+#else
+ #define cyttsp_openlog()
+#endif /* CY_LOG_TO_FILE */
+
+/* see kernel.h for pr_xxx def'ns */
+#define cyttsp_info(f, a...) pr_info("%s:" f, __func__ , ## a)
+#define cyttsp_error(f, a...) pr_err("%s:" f, __func__ , ## a)
+#define cyttsp_alert(f, a...) pr_alert("%s:" f, __func__ , ## a)
+
+#ifdef CY_USE_DEBUG
+ #define cyttsp_debug(f, a...) pr_alert("%s:" f, __func__ , ## a)
+#else
+ #define cyttsp_debug(f, a...) {if (cyttsp_tsdebug) \
+ pr_alert("%s:" f, __func__ , ## a); }
+#endif /* CY_USE_DEBUG */
+
+#ifdef CY_ALLOW_EXTRA_DEBUG
+#ifdef CY_USE_EXTRA_DEBUG
+ #define cyttsp_xdebug(f, a...) pr_alert("%s:" f, __func__ , ## a)
+#else
+ #define cyttsp_xdebug(f, a...) {if (cyttsp_tsxdebug) \
+ pr_alert("%s:" f, __func__ , ## a); }
+#endif /* CY_USE_EXTRA_DEBUG */
+
+#ifdef CY_USE_EXTRA_DEBUG1
+ #define cyttsp_xdebug1(f, a...) pr_alert("%s:" f, __func__ , ## a)
+#else
+ #define cyttsp_xdebug1(f, a...)
+#endif /* CY_USE_EXTRA_DEBUG1 */
+#else
+ #define cyttsp_xdebug(f, a...)
+ #define cyttsp_xdebug1(f, a...)
+#endif /* CY_ALLOW_EXTRA_DEBUG */
+
+#ifdef CY_USE_TIMER_DEBUG
+ #define TOUCHSCREEN_TIMEOUT (msecs_to_jiffies(1000))
+#else
+ #define TOUCHSCREEN_TIMEOUT (msecs_to_jiffies(28))
+#endif
+
+/* reduce extra signals in MT only build
+ * be careful not to lose backward compatibility for pre-MT apps
+ */
+#ifdef CY_USE_ST_SIGNALS
+ #define CY_USE_ST 1
+#else
+ #define CY_USE_ST 0
+#endif /* CY_USE_ST_SIGNALS */
+
+/* rely on kernel input.h to define Multi-Touch capability */
+/* if input.h defines the Multi-Touch signals, then use MT */
+#if defined(ABS_MT_TOUCH_MAJOR) && defined(CY_USE_MT_SIGNALS)
+ #define CY_USE_MT 1
+ #define CY_MT_SYNC(input) input_mt_sync(input)
+#else
+ #define CY_USE_MT 0
+ #define CY_MT_SYNC(input)
+ /* the following includes are provided to ensure a compile;
+ * the code that compiles with these defines will not be executed if
+ * the CY_USE_MT is properly used in the platform structure init
+ */
+ #ifndef ABS_MT_TOUCH_MAJOR
+ #define ABS_MT_TOUCH_MAJOR 0x30 /* touching ellipse */
+ #define ABS_MT_TOUCH_MINOR 0x31 /* (omit if circular) */
+ #define ABS_MT_WIDTH_MAJOR 0x32 /* approaching ellipse */
+ #define ABS_MT_WIDTH_MINOR 0x33 /* (omit if circular) */
+ #define ABS_MT_ORIENTATION 0x34 /* Ellipse orientation */
+ #define ABS_MT_POSITION_X 0x35 /* Center X ellipse position */
+ #define ABS_MT_POSITION_Y 0x36 /* Center Y ellipse position */
+ #define ABS_MT_TOOL_TYPE 0x37 /* Type of touching device */
+ #define ABS_MT_BLOB_ID 0x38 /* Group set of pkts as blob */
+ #endif /* ABS_MT_TOUCH_MAJOR */
+#endif /* ABS_MT_TOUCH_MAJOR and CY_USE_MT_SIGNALS */
+#if defined(ABS_MT_TRACKING_ID) && defined(CY_USE_MT_TRACK_ID)
+ #define CY_USE_TRACKING_ID 1
+#else
+ #define CY_USE_TRACKING_ID 0
+/* define only if not defined already by system;
+ * value based on linux kernel 2.6.30.10
+ */
+#ifndef ABS_MT_TRACKING_ID
+ #define ABS_MT_TRACKING_ID (ABS_MT_BLOB_ID+1)
+#endif
+#endif /* ABS_MT_TRACKING_ID */
+
+#define CY_USE_DEEP_SLEEP_SEL 0x80
+#define CY_USE_LOW_POWER_SEL 0x01
+
+#ifdef CY_USE_TEST_DATA
+ #define cyttsp_testdat(ray1, ray2, sizeofray) \
+ { \
+ int i; \
+ u8 *up1 = (u8 *)ray1; \
+ u8 *up2 = (u8 *)ray2; \
+ for (i = 0; i < sizeofray; i++) { \
+ up1[i] = up2[i]; \
+ } \
+ }
+#else
+ #define cyttsp_testdat(xy, test_xy, sizeofray)
+#endif /* CY_USE_TEST_DATA */
+
+/* helper macros */
+#define GET_NUM_TOUCHES(x) ((x) & 0x0F)
+#define GET_TOUCH1_ID(x) (((x) & 0xF0) >> 4)
+#define GET_TOUCH2_ID(x) ((x) & 0x0F)
+#define GET_TOUCH3_ID(x) (((x) & 0xF0) >> 4)
+#define GET_TOUCH4_ID(x) ((x) & 0x0F)
+#define IS_LARGE_AREA(x) (((x) & 0x10) >> 4)
+#define FLIP_DATA_FLAG 0x01
+#define REVERSE_X_FLAG 0x02
+#define REVERSE_Y_FLAG 0x04
+#define FLIP_DATA(flags) ((flags) & FLIP_DATA_FLAG)
+#define REVERSE_X(flags) ((flags) & REVERSE_X_FLAG)
+#define REVERSE_Y(flags) ((flags) & REVERSE_Y_FLAG)
+#define FLIP_XY(x, y) { \
+ u16 tmp; \
+ tmp = (x); \
+ (x) = (y); \
+ (y) = tmp; \
+ }
+#define INVERT_X(x, xmax) ((xmax) - (x))
+#define INVERT_Y(y, maxy) ((maxy) - (y))
+#define SET_HSTMODE(reg, mode) ((reg) & (mode))
+#define GET_HSTMODE(reg) ((reg & 0x70) >> 4)
+#define GET_BOOTLOADERMODE(reg) ((reg & 0x10) >> 4)
+
+/* constant definitions */
+/* maximum number of concurrent ST track IDs */
+#define CY_NUM_ST_TCH_ID 2
+
+/* maximum number of concurrent MT track IDs */
+#define CY_NUM_MT_TCH_ID 4
+
+/* maximum number of track IDs */
+#define CY_NUM_TRK_ID 16
+
+#define CY_NTCH 0 /* no touch (lift off) */
+#define CY_TCH 1 /* active touch (touchdown) */
+#define CY_ST_FNGR1_IDX 0
+#define CY_ST_FNGR2_IDX 1
+#define CY_MT_TCH1_IDX 0
+#define CY_MT_TCH2_IDX 1
+#define CY_MT_TCH3_IDX 2
+#define CY_MT_TCH4_IDX 3
+#define CY_XPOS 0
+#define CY_YPOS 1
+#define CY_IGNR_TCH (-1)
+#define CY_SMALL_TOOL_WIDTH 10
+#define CY_LARGE_TOOL_WIDTH 255
+#define CY_REG_BASE 0x00
+#define CY_REG_GEST_SET 0x1E
+#define CY_REG_ACT_INTRVL 0x1D
+#define CY_REG_TCH_TMOUT (CY_REG_ACT_INTRVL+1)
+#define CY_REG_LP_INTRVL (CY_REG_TCH_TMOUT+1)
+#define CY_SOFT_RESET ((1 << 0))
+#define CY_DEEP_SLEEP ((1 << 1))
+#define CY_LOW_POWER ((1 << 2))
+#define CY_MAXZ 255
+#define CY_OK 0
+#define CY_INIT 1
+#define CY_DLY_DFLT 10 /* ms */
+#define CY_DLY_SYSINFO 20 /* ms */
+#define CY_DLY_BL 300
+#define CY_DLY_DNLOAD 100 /* ms */
+#define CY_NUM_RETRY 4 /* max num touch data read */
+
+/* handshake bit in the hst_mode reg */
+#define CY_HNDSHK_BIT 0x80
+#ifdef CY_USE_HNDSHK
+ #define CY_SEND_HNDSHK 1
+#else
+ #define CY_SEND_HNDSHK 0
+#endif
+
+/* Bootloader File 0 offset */
+#define CY_BL_FILE0 0x00
+
+/* Bootloader command directive */
+#define CY_BL_CMD 0xFF
+
+/* Bootloader Initiate Bootload */
+#define CY_BL_INIT_LOAD 0x38
+
+/* Bootloader Write a Block */
+#define CY_BL_WRITE_BLK 0x39
+
+/* Bootloader Terminate Bootload */
+#define CY_BL_TERMINATE 0x3B
+
+/* Bootloader Exit and Verify Checksum command */
+#define CY_BL_EXIT 0xA5
+
+/* Bootloader default keys */
+#define CY_BL_KEY0 0x00
+#define CY_BL_KEY1 0x01
+#define CY_BL_KEY2 0x02
+#define CY_BL_KEY3 0x03
+#define CY_BL_KEY4 0x04
+#define CY_BL_KEY5 0x05
+#define CY_BL_KEY6 0x06
+#define CY_BL_KEY7 0x07
+
+/* Active Power state scanning/processing refresh interval */
+#define CY_ACT_INTRVL_DFLT 0x00
+
+/* touch timeout for the Active power */
+#define CY_TCH_TMOUT_DFLT 0xFF
+
+/* Low Power state scanning/processing refresh interval */
+#define CY_LP_INTRVL_DFLT 0x0A
+
+#define CY_IDLE_STATE 0
+#define CY_ACTIVE_STATE 1
+#define CY_LOW_PWR_STATE 2
+#define CY_SLEEP_STATE 3
+
+/* device mode bits */
+#define CY_OP_MODE 0x00
+#define CY_SYSINFO_MODE 0x10
+
+/* power mode select bits */
+#define CY_SOFT_RESET_MODE 0x01 /* return to Bootloader mode */
+#define CY_DEEP_SLEEP_MODE 0x02
+#define CY_LOW_PWR_MODE 0x04
+
+#define CY_NUM_KEY 8
+
+#ifdef CY_USE_GEST
+ #define CY_USE_GESTURES 1
+#else
+ #define CY_USE_GESTURES 0
+#endif /* CY_USE_GESTURE_SIGNALS */
+
+#ifdef CY_USE_GEST_GRP1
+ #define CY_GEST_GRP1 0x10
+#else
+ #define CY_GEST_GRP1 0x00
+#endif /* CY_USE_GEST_GRP1 */
+#ifdef CY_USE_GEST_GRP2
+ #define CY_GEST_GRP2 0x20
+#else
+ #define CY_GEST_GRP2 0x00
+#endif /* CY_USE_GEST_GRP2 */
+#ifdef CY_USE_GEST_GRP3
+ #define CY_GEST_GRP3 0x40
+#else
+ #define CY_GEST_GRP3 0x00
+#endif /* CY_USE_GEST_GRP3 */
+#ifdef CY_USE_GEST_GRP4
+ #define CY_GEST_GRP4 0x80
+#else
+ #define CY_GEST_GRP4 0x00
+#endif /* CY_USE_GEST_GRP4 */
+
+struct cyttsp_regulator {
+ const char *name;
+ u32 min_uV;
+ u32 max_uV;
+ u32 load_uA;
+};
+
+struct cyttsp_platform_data {
+ u32 panel_maxx;
+ u32 panel_maxy;
+ u32 disp_resx;
+ u32 disp_resy;
+ u32 disp_minx;
+ u32 disp_miny;
+ u32 disp_maxx;
+ u32 disp_maxy;
+ u8 correct_fw_ver;
+ u32 flags;
+ u8 gen;
+ u8 use_st;
+ u8 use_mt;
+ u8 use_hndshk;
+ u8 use_trk_id;
+ u8 use_sleep;
+ u8 use_gestures;
+ u8 gest_set;
+ u8 act_intrvl;
+ u8 tch_tmout;
+ u8 lp_intrvl;
+ u8 power_state;
+ bool wakeup;
+ int sleep_gpio;
+ int resout_gpio;
+ int irq_gpio;
+ struct cyttsp_regulator *regulator_info;
+ u8 num_regulators;
+ const char *fw_fname;
+#ifdef CY_USE_I2C_DRIVER
+ s32 (*init)(struct i2c_client *client);
+ s32 (*resume)(struct i2c_client *client);
+#endif
+#ifdef CY_USE_SPI_DRIVER
+ s32 (*init)(struct spi_device *spi);
+ s32 (*resume)(struct spi_device *spi);
+#endif
+};
+
+/* TrueTouch Standard Product Gen3 (Txx3xx) interface definition */
+struct cyttsp_gen3_xydata_t {
+ u8 hst_mode;
+ u8 tt_mode;
+ u8 tt_stat;
+ u16 x1 __attribute__ ((packed));
+ u16 y1 __attribute__ ((packed));
+ u8 z1;
+ u8 touch12_id;
+ u16 x2 __attribute__ ((packed));
+ u16 y2 __attribute__ ((packed));
+ u8 z2;
+ u8 gest_cnt;
+ u8 gest_id;
+ u16 x3 __attribute__ ((packed));
+ u16 y3 __attribute__ ((packed));
+ u8 z3;
+ u8 touch34_id;
+ u16 x4 __attribute__ ((packed));
+ u16 y4 __attribute__ ((packed));
+ u8 z4;
+ u8 tt_undef[3];
+ u8 gest_set;
+ u8 tt_reserved;
+};
+
+/* TrueTouch Standard Product Gen2 (Txx2xx) interface definition */
+#define CY_GEN2_NOTOUCH 0x03 /* Both touches removed */
+#define CY_GEN2_GHOST 0x02 /* ghost */
+#define CY_GEN2_2TOUCH 0x03 /* 2 touch; no ghost */
+#define CY_GEN2_1TOUCH 0x01 /* 1 touch only */
+#define CY_GEN2_TOUCH2 0x01 /* 1st touch removed;
+ * 2nd touch remains */
+struct cyttsp_gen2_xydata_t {
+ u8 hst_mode;
+ u8 tt_mode;
+ u8 tt_stat;
+ u16 x1 __attribute__ ((packed));
+ u16 y1 __attribute__ ((packed));
+ u8 z1;
+ u8 evnt_idx;
+ u16 x2 __attribute__ ((packed));
+ u16 y2 __attribute__ ((packed));
+ u8 tt_undef1;
+ u8 gest_cnt;
+ u8 gest_id;
+ u8 tt_undef[14];
+ u8 gest_set;
+ u8 tt_reserved;
+};
+
+/* TTSP System Information interface definition */
+struct cyttsp_sysinfo_data_t {
+ u8 hst_mode;
+ u8 mfg_cmd;
+ u8 mfg_stat;
+ u8 cid[3];
+ u8 tt_undef1;
+ u8 uid[8];
+ u8 bl_verh;
+ u8 bl_verl;
+ u8 tts_verh;
+ u8 tts_verl;
+ u8 app_idh;
+ u8 app_idl;
+ u8 app_verh;
+ u8 app_verl;
+ u8 tt_undef[6];
+ u8 act_intrvl;
+ u8 tch_tmout;
+ u8 lp_intrvl;
+};
+
+/* TTSP Bootloader Register Map interface definition */
+#define CY_BL_CHKSUM_OK 0x01
+struct cyttsp_bootloader_data_t {
+ u8 bl_file;
+ u8 bl_status;
+ u8 bl_error;
+ u8 blver_hi;
+ u8 blver_lo;
+ u8 bld_blver_hi;
+ u8 bld_blver_lo;
+ u8 ttspver_hi;
+ u8 ttspver_lo;
+ u8 appid_hi;
+ u8 appid_lo;
+ u8 appver_hi;
+ u8 appver_lo;
+ u8 cid_0;
+ u8 cid_1;
+ u8 cid_2;
+};
+
+#define cyttsp_wake_data_t cyttsp_gen3_xydata_t
+#ifdef CY_DECLARE_GLOBALS
+ #ifdef CY_INCLUDE_LOAD_FILE
+ /* this file declares:
+ * firmware download block array (cyttsp_fw[]),
+ * the number of command block records (cyttsp_fw_records),
+ * and the version variables
+ */
+ #include "cyttsp_fw.h" /* imports cyttsp_fw[] array */
+ #define cyttsp_app_load() 1
+ #ifdef CY_FORCE_FW_UPDATE
+ #define cyttsp_force_fw_load() 1
+ #else
+ #define cyttsp_force_fw_load() 0
+ #endif
+
+ #else
+ /* the following declarations are to allow
+ * some debugging capability
+ */
+ unsigned char cyttsp_fw_tts_verh = 0x00;
+ unsigned char cyttsp_fw_tts_verl = 0x01;
+ unsigned char cyttsp_fw_app_idh = 0x02;
+ unsigned char cyttsp_fw_app_idl = 0x03;
+ unsigned char cyttsp_fw_app_verh = 0x04;
+ unsigned char cyttsp_fw_app_verl = 0x05;
+ unsigned char cyttsp_fw_cid_0 = 0x06;
+ unsigned char cyttsp_fw_cid_1 = 0x07;
+ unsigned char cyttsp_fw_cid_2 = 0x08;
+ #define cyttsp_app_load() 0
+ #define cyttsp_force_fw_load() 0
+ #endif
+ #define cyttsp_tts_verh() cyttsp_fw_tts_verh
+ #define cyttsp_tts_verl() cyttsp_fw_tts_verl
+ #define cyttsp_app_idh() cyttsp_fw_app_idh
+ #define cyttsp_app_idl() cyttsp_fw_app_idl
+ #define cyttsp_app_verh() cyttsp_fw_app_verh
+ #define cyttsp_app_verl() cyttsp_fw_app_verl
+ #define cyttsp_cid_0() cyttsp_fw_cid_0
+ #define cyttsp_cid_1() cyttsp_fw_cid_1
+ #define cyttsp_cid_2() cyttsp_fw_cid_2
+ #ifdef CY_USE_TEST_DATA
+ static struct cyttsp_gen2_xydata_t tt_gen2_testray[] = {
+ {0x00}, {0x00}, {0x04},
+ {0x4000}, {0x8000}, {0x80},
+ {0x03},
+ {0x2000}, {0x1000}, {0x00},
+ {0x00},
+ {0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x00},
+ {0x00}
+ };
+
+ static struct cyttsp_gen3_xydata_t tt_gen3_testray[] = {
+ {0x00}, {0x00}, {0x04},
+ {0x4000}, {0x8000}, {0x80},
+ {0x12},
+ {0x2000}, {0x1000}, {0xA0},
+ {0x00}, {0x00},
+ {0x8000}, {0x4000}, {0xB0},
+ {0x34},
+ {0x4000}, {0x1000}, {0xC0},
+ {0x00, 0x00, 0x00},
+ {0x00},
+ {0x00}
+ };
+ #endif /* CY_USE_TEST_DATA */
+
+#else
+ extern u8 g_appload_ray[];
+#endif
+#define FW_FNAME_LEN 40
+#define TP_ID_GPIO 85
+
+
+/* CY TTSP I2C Driver private data */
+struct cyttsp {
+ struct i2c_client *client;
+ struct input_dev *input;
+ struct work_struct work;
+ struct timer_list timer;
+ struct mutex mutex;
+ char phys[32];
+ struct cyttsp_platform_data *platform_data;
+ u8 num_prv_st_tch;
+ u16 act_trk[CY_NUM_TRK_ID];
+ u16 prv_st_tch[CY_NUM_ST_TCH_ID];
+ u16 prv_mt_tch[CY_NUM_MT_TCH_ID];
+ u16 prv_mt_pos[CY_NUM_TRK_ID][2];
+ atomic_t irq_enabled;
+ bool cyttsp_update_fw;
+ bool cyttsp_fwloader_mode;
+ bool is_suspended;
+ struct regulator **vdd;
+ char fw_fname[FW_FNAME_LEN];
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend early_suspend;
+#endif /* CONFIG_HAS_EARLYSUSPEND */
+ int tpid;
+
+};
+extern struct cyttsp cust_ts;
+extern void cyttsp_fw_upgrade(void);
+extern void cyttsp_hw_reset(void);
+
+
+#endif /* __CYTTSP_H__ */
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/cyp140_ts/cyttsp_fw_upgrade.c b/ANDROID_3.4.5/drivers/input/touchscreen/cyp140_ts/cyttsp_fw_upgrade.c
new file mode 100755
index 00000000..ca6e9d10
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/cyp140_ts/cyttsp_fw_upgrade.c
@@ -0,0 +1,993 @@
+/* Source for:
+ * Cypress TrueTouch(TM) Standard Product I2C touchscreen driver.
+ * drivers/input/touchscreen/cyttsp-i2c.c
+ *
+ * Copyright (C) 2009, 2010 Cypress Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2, and only version 2, as published by the
+ * Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Cypress reserves the right to make changes without further notice
+ * to the materials described herein. Cypress does not assume any
+ * liability arising out of the application described herein.
+ *
+ * Contact Cypress Semiconductor at www.cypress.com
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+#include <linux/workqueue.h>
+#include <linux/byteorder/generic.h>
+#include <linux/bitops.h>
+#include <linux/pm_runtime.h>
+#include <linux/firmware.h>
+#include <linux/mutex.h>
+#include <linux/regulator/consumer.h>
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif /* CONFIG_HAS_EARLYSUSPEND */
+//#include <mach/vreg.h>
+
+#define CY_DECLARE_GLOBALS
+
+#include "cyttsp.h"
+
+#include <linux/miscdevice.h>
+#include <asm/uaccess.h>
+
+#include <linux/poll.h>
+
+#define LOG_TP() printk("++++%s, Line %d\n", __FUNCTION__, __LINE__);
+
+
+#define CYTTSP_SUPPORT_READ_TP_VERSION
+
+#define CYTTSP_SUPPORT_TP_SENSOR
+// need upgrade,add MACRO
+//#ifdef CONFIG_LCT_AW551_YL
+#define CYTTSP_SUPPORT_SYS_NODE
+//#endif
+
+extern struct tpd_device *tpd;//add 2013-1-7
+
+int cyttsp_vendor_id=20;
+int cyttsp_firmware_version= -1;
+
+int cyttsp_has_bootloader=0;
+
+#ifdef CYTTSP_SUPPORT_TP_SENSOR
+
+#define CYTTSP_DEBUG_TP_SENSOR
+
+#define CYTTSP_SUPPORT_TP_SENSOR_FIRMWARE_VERSION (0xc) //if we change this value we should also change func apds9900_init_dev in file apds9000.c
+static DEFINE_MUTEX(cyttsp_sensor_mutex);
+static DECLARE_WAIT_QUEUE_HEAD(cyttsp_sensor_waitqueue);
+
+//static char cyttsp_sensor_data = 0; // 0 near 1 far
+//static int cyttsp_sensor_data_changed = 0;
+//static struct i2c_client *tp_sensor_I2Cclient = NULL;
+//static int cyttsp_sensor_opened = 0;
+
+
+
+#endif
+
+
+
+#define CYTTSP_AW551_OFILM "cyttspfw_aw551_ofilm.fw"
+#define CYTTSP_AW551_TRULY "cyttspfw_aw551_truly.fw"
+#define CYTTSP_AW550_TRULY "cyttspfw_aw550_truly.fw"
+
+uint32_t cyttsp_tsdebug1 = 0xff;
+
+module_param_named(tsdebug1, cyttsp_tsdebug1, uint, 0664);
+
+#define FW_FNAME_LEN 40
+#define TP_ID_GPIO 85
+
+//static u8 irq_cnt; /* comparison counter with register valuw */
+//static u32 irq_cnt_total; /* total interrupts */
+//static u32 irq_err_cnt; /* count number of touch interrupts with err */
+#define CY_IRQ_CNT_MASK 0x000000FF /* mapped for sizeof count in reg */
+#define CY_IRQ_CNT_REG 0x00 /* tt_undef[0]=reg 0x1B - Gen3 only */
+
+
+
+/* ****************************************************************************
+ * Prototypes for static functions
+ * ************************************************************************** */
+
+static int cyttsp_putbl(struct cyttsp *ts, int show,
+ int show_status, int show_version, int show_cid);
+/*static int __devinit cyttsp_probe(struct i2c_client *client,
+ const struct i2c_device_id *id); */
+//static int __devexit cyttsp_remove(struct i2c_client *client);
+//static int cyttsp_resume(struct device *dev);
+//static int cyttsp_suspend(struct device *dev);
+
+#ifdef CYTTSP_SUPPORT_SYS_NODE
+//static int cyttsp_power_down(void);
+#endif
+
+
+
+/* Static variables */
+//static struct cyttsp_gen3_xydata_t g_xy_data;
+static struct cyttsp_bootloader_data_t g_bl_data;
+static struct cyttsp_sysinfo_data_t g_sysinfo_data;
+static const struct i2c_device_id cyttsp_id[] = {
+ { CY_I2C_NAME, 0 }, { }
+};
+static u8 bl_cmd[] = {
+ CY_BL_FILE0, CY_BL_CMD, CY_BL_EXIT,
+ CY_BL_KEY0, CY_BL_KEY1, CY_BL_KEY2,
+ CY_BL_KEY3, CY_BL_KEY4, CY_BL_KEY5,
+ CY_BL_KEY6, CY_BL_KEY7};
+
+MODULE_DEVICE_TABLE(i2c, cyttsp_id);
+
+
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard touchscreen driver");
+MODULE_AUTHOR("Cypress");
+
+
+
+#ifdef CYTTSP_SUPPORT_TP_SENSOR
+#define CYTTSP_SENSOR_IOM 'r'
+
+#define CYTTSP_SENSOR_IOC_SET_PS_ENABLE _IOW(CYTTSP_SENSOR_IOM, 0, char *)
+#define CYTTSP_SENSOR_READ_PS_DATA _IOR(CYTTSP_SENSOR_IOM, 2, char *)
+
+
+
+
+#endif
+
+
+
+
+
+
+
+
+
+static void cyttsp_exit_bl_mode(struct cyttsp *ts);
+
+
+
+
+
+#ifdef CYTTSP_SUPPORT_SYS_NODE
+/* firmware flashing block */
+#define BLK_SIZE 16
+#define DATA_REC_LEN 64
+#define START_ADDR 0x0880//0x0b00
+#define BLK_SEED 0xff
+#define RECAL_REG 0x1b
+
+enum bl_commands {
+ BL_CMD_WRBLK = 0x39,
+ BL_CMD_INIT = 0x38,
+ BL_CMD_TERMINATE = 0x3b,
+};
+/* TODO: Add key as part of platform data */
+#define KEY_CS (0 + 1 + 2 + 3 + 4 + 5 + 6 + 7)
+#define KEY {0, 1, 2, 3, 4, 5, 6, 7}
+
+static const char _key[] = KEY;
+#define KEY_LEN sizeof(_key)
+
+static int rec_cnt;
+struct fw_record {
+ u8 seed;
+ u8 cmd;
+ u8 key[KEY_LEN];
+ u8 blk_hi;
+ u8 blk_lo;
+ u8 data[DATA_REC_LEN];
+ u8 data_cs;
+ u8 rec_cs;
+};
+#define fw_rec_size (sizeof(struct fw_record))
+
+struct cmd_record {
+ u8 reg;
+ u8 seed;
+ u8 cmd;
+ u8 key[KEY_LEN];
+};
+#define cmd_rec_size (sizeof(struct cmd_record))
+
+static struct fw_record data_record = {
+ .seed = BLK_SEED,
+ .cmd = BL_CMD_WRBLK,
+ .key = KEY,
+};
+
+static const struct cmd_record terminate_rec = {
+ .reg = 0,
+ .seed = BLK_SEED,
+ .cmd = BL_CMD_TERMINATE,
+ .key = KEY,
+};
+static const struct cmd_record initiate_rec = {
+ .reg = 0,
+ .seed = BLK_SEED,
+ .cmd = BL_CMD_INIT,
+ .key = KEY,
+};
+
+#define BL_REC1_ADDR 0x0780
+#define BL_REC2_ADDR 0x07c0
+
+#define ID_INFO_REC ":40078000"
+#define ID_INFO_OFFSET_IN_REC 77
+
+#define REC_START_CHR ':'
+#define REC_LEN_OFFSET 1
+#define REC_ADDR_HI_OFFSET 3
+#define REC_ADDR_LO_OFFSET 5
+#define REC_TYPE_OFFSET 7
+#define REC_DATA_OFFSET 9
+#define REC_LINE_SIZE 141
+
+static int cyttsp_soft_reset(struct cyttsp *ts)
+{
+ int retval = 0, tries = 0;
+ u8 host_reg = CY_SOFT_RESET_MODE;
+
+ #if 0
+ gpio_set_value(ts->platform_data->resout_gpio, 1); //reset high valid
+ msleep(100);
+ gpio_set_value(ts->platform_data->resout_gpio, 0);
+ msleep(1000);
+ #endif
+ LOG_TP();
+
+ #if 1// 0 modify 2013-1-7!!!!!!!!!!!
+ do {
+ retval = i2c_smbus_write_i2c_block_data(ts->client,
+ CY_REG_BASE, sizeof(host_reg), &host_reg);
+ if (retval < 0)
+ msleep(20);
+ } while (tries++ < 10 && (retval < 0));
+
+ if (retval < 0) {
+ pr_err("%s: failed\n", __func__);
+ return retval;
+ }
+ #else
+ cyttsp_hw_reset(); //!!!! 2013-1-7 may not go here !!!
+ #endif
+
+ LOG_TP();
+ tries = 0;
+ do {
+ msleep(20);
+ cyttsp_putbl(ts, 1, true, true, false);
+ } while (g_bl_data.bl_status != 0x10 &&
+ g_bl_data.bl_status != 0x11 &&
+ tries++ < 100);
+ LOG_TP();
+ if (g_bl_data.bl_status != 0x11 && g_bl_data.bl_status != 0x10)
+ return -EINVAL;
+ LOG_TP();
+ return 0;
+}
+
+static void cyttsp_exit_bl_mode(struct cyttsp *ts)
+{
+ int retval, tries = 0;
+
+ do {
+ retval = i2c_smbus_write_i2c_block_data(ts->client,
+ CY_REG_BASE, sizeof(bl_cmd), bl_cmd);
+ if (retval < 0)
+ msleep(20);
+ } while (tries++ < 10 && (retval < 0));
+}
+
+static void cyttsp_set_sysinfo_mode(struct cyttsp *ts)
+{
+ int retval, tries = 0;
+ u8 host_reg = CY_SYSINFO_MODE;
+
+ do {
+ retval = i2c_smbus_write_i2c_block_data(ts->client,
+ CY_REG_BASE, sizeof(host_reg), &host_reg);
+ if (retval < 0)
+ msleep(20);
+ } while (tries++ < 10 && (retval < 0));
+
+ /* wait for TTSP Device to complete switch to SysInfo mode */
+ if (!(retval < 0)) {
+ retval = i2c_smbus_read_i2c_block_data(ts->client,
+ CY_REG_BASE,
+ sizeof(struct cyttsp_sysinfo_data_t),
+ (u8 *)&g_sysinfo_data);
+ } else
+ pr_err("%s: failed\n", __func__);
+}
+
+static void cyttsp_set_opmode(struct cyttsp *ts)
+{
+ int retval, tries = 0;
+ u8 host_reg = CY_OP_MODE;
+
+ do {
+ retval = i2c_smbus_write_i2c_block_data(ts->client,
+ CY_REG_BASE, sizeof(host_reg), &host_reg);
+ if (retval < 0)
+ msleep(20);
+ } while (tries++ < 10 && (retval < 0));
+}
+
+static int str2uc(char *str, u8 *val)
+{
+ char substr[3];
+ unsigned long ulval;
+ int rc;
+
+ if (!str && strlen(str) < 2)
+ return -EINVAL;
+
+ substr[0] = str[0];
+ substr[1] = str[1];
+ substr[2] = '\0';
+
+ rc = strict_strtoul(substr, 16, &ulval);
+ if (rc != 0)
+ return rc;
+
+ *val = (u8) ulval;
+
+ return 0;
+}
+
+static int flash_block(struct cyttsp *ts, u8 *blk, int len)
+{
+ int retval, i, tries = 0;
+ char buf[(2 * (BLK_SIZE + 1)) + 1];
+ char *p = buf;
+
+ for (i = 0; i < len; i++, p += 2)
+ sprintf(p, "%02x", blk[i]);
+ pr_debug("%s: size %d, pos %ld payload %s\n",
+ __func__, len, (long)0, buf);
+
+ do {
+ retval = i2c_smbus_write_i2c_block_data(ts->client,
+ CY_REG_BASE, len, blk);
+ if (retval < 0)
+ msleep(20);
+ } while (tries++ < 20 && (retval < 0));
+
+ if (retval < 0) {
+ pr_err("%s: failed\n", __func__);
+ return retval;
+ }
+
+ return 0;
+}
+
+static int flash_command(struct cyttsp *ts, const struct cmd_record *record)
+{
+ return flash_block(ts, (u8 *)record, cmd_rec_size);
+}
+
+static void init_data_record(struct fw_record *rec, unsigned short addr)
+{
+ addr >>= 6;
+ rec->blk_hi = (addr >> 8) & 0xff;
+ rec->blk_lo = addr & 0xff;
+ rec->rec_cs = rec->blk_hi + rec->blk_lo +
+ (unsigned char)(BLK_SEED + BL_CMD_WRBLK + KEY_CS);
+ rec->data_cs = 0;
+}
+
+static int check_record(u8 *rec)
+{
+ int rc;
+ u16 addr;
+ u8 r_len, type, hi_off, lo_off;
+
+ rc = str2uc(rec + REC_LEN_OFFSET, &r_len);
+ if (rc < 0)
+ return rc;
+
+ rc = str2uc(rec + REC_TYPE_OFFSET, &type);
+ if (rc < 0)
+ return rc;
+
+ if (*rec != REC_START_CHR || r_len != DATA_REC_LEN || type != 0)
+ return -EINVAL;
+
+ rc = str2uc(rec + REC_ADDR_HI_OFFSET, &hi_off);
+ if (rc < 0)
+ return rc;
+
+ rc = str2uc(rec + REC_ADDR_LO_OFFSET, &lo_off);
+ if (rc < 0)
+ return rc;
+
+ addr = (hi_off << 8) | lo_off;
+
+ if (addr >= START_ADDR || addr == BL_REC1_ADDR || addr == BL_REC2_ADDR)
+ return 0;
+
+ return -EINVAL;
+}
+
+static struct fw_record *prepare_record(u8 *rec)
+{
+ int i, rc;
+ u16 addr;
+ u8 hi_off, lo_off;
+ u8 *p;
+
+ rc = str2uc(rec + REC_ADDR_HI_OFFSET, &hi_off);
+ if (rc < 0)
+ return ERR_PTR((long) rc);
+
+ rc = str2uc(rec + REC_ADDR_LO_OFFSET, &lo_off);
+ if (rc < 0)
+ return ERR_PTR((long) rc);
+
+ addr = (hi_off << 8) | lo_off;
+
+ init_data_record(&data_record, addr);
+ p = rec + REC_DATA_OFFSET;
+ for (i = 0; i < DATA_REC_LEN; i++) {
+ rc = str2uc(p, &data_record.data[i]);
+ if (rc < 0)
+ return ERR_PTR((long) rc);
+ data_record.data_cs += data_record.data[i];
+ data_record.rec_cs += data_record.data[i];
+ p += 2;
+ }
+ data_record.rec_cs += data_record.data_cs;
+
+ return &data_record;
+}
+
+static int flash_record(struct cyttsp *ts, const struct fw_record *record)
+{
+ int len = fw_rec_size;
+ int blk_len, rc;
+ u8 *rec = (u8 *)record;
+ u8 data[BLK_SIZE + 1];
+ u8 blk_offset;
+
+ for (blk_offset = 0; len; len -= blk_len) {
+ data[0] = blk_offset;
+ blk_len = len > BLK_SIZE ? BLK_SIZE : len;
+ memcpy(data + 1, rec, blk_len);
+ rec += blk_len;
+ rc = flash_block(ts, data, blk_len + 1);
+ if (rc < 0)
+ return rc;
+ blk_offset += blk_len;
+ }
+ return 0;
+}
+
+static int flash_data_rec(struct cyttsp *ts, u8 *buf)
+{
+ struct fw_record *rec;
+ int rc, tries;
+LOG_TP();
+ if (!buf)
+ return -EINVAL;
+
+ rc = check_record(buf);
+
+ if (rc < 0) {
+ pr_debug("%s: record ignored %s", __func__, buf);
+ return 0;
+ }
+
+ rec = prepare_record(buf);
+ if (IS_ERR_OR_NULL(rec))
+ return PTR_ERR(rec);
+
+ rc = flash_record(ts, rec);
+ if (rc < 0)
+ return rc;
+
+ tries = 0;
+ do {
+//printk("++++%s, Line %d, tries=%d\n", __FUNCTION__, __LINE__,tries ); //wujinyou
+
+ //if (rec_cnt%2)
+ //msleep(20);
+ if(tries >50)
+ {
+ printk("++++%s, Line %d, tries=%d\n", __FUNCTION__, __LINE__,tries ); //wujinyou
+ msleep(20);
+ }
+ cyttsp_putbl(ts, 4, true, false, false);
+ } while (g_bl_data.bl_status != 0x10 &&
+ g_bl_data.bl_status != 0x11 &&
+ tries++ < 100);
+ rec_cnt++;
+ return rc;
+}
+
+static int cyttspfw_flash_firmware(struct cyttsp *ts, const u8 *data,
+ int data_len)
+{
+ u8 *buf;
+ int i, j;
+ int rc, tries = 0;
+ LOG_TP();
+
+ /* initiate bootload: this will erase all the existing data */
+ rc = flash_command(ts, &initiate_rec);
+ if (rc < 0)
+ return rc;
+
+ do {
+// LOG_TP();
+printk("++++%s, Line %d, tries=%d\n", __FUNCTION__, __LINE__,tries );
+ msleep(60);
+ cyttsp_putbl(ts, 4, true, false, false);
+ } while (g_bl_data.bl_status != 0x10 &&
+ g_bl_data.bl_status != 0x11 &&
+ tries++ < 100);
+
+ buf = kzalloc(REC_LINE_SIZE + 1, GFP_KERNEL);
+ if (!buf) {
+ pr_err("%s: no memory\n", __func__);
+ return -ENOMEM;
+ }
+ LOG_TP();
+ rec_cnt = 0;
+ /* flash data records */
+ for (i = 0, j = 0; i < data_len; i++, j++) {
+ if ((data[i] == REC_START_CHR) && j) {
+ buf[j] = 0;
+ rc = flash_data_rec(ts, buf);
+ if (rc < 0)
+ return rc;
+ j = 0;
+ }
+ buf[j] = data[i];
+ }
+ LOG_TP();
+ /* flash last data record */
+ if (j) {
+ buf[j] = 0;
+ rc = flash_data_rec(ts, buf);
+ if (rc < 0)
+ return rc;
+ }
+ LOG_TP();
+ kfree(buf);
+
+ /* termiate bootload */
+ tries = 0;
+ rc = flash_command(ts, &terminate_rec);
+ do {
+ msleep(100);
+printk("++++%s, Line %d, tries=%d\n", __FUNCTION__, __LINE__,tries );
+
+ cyttsp_putbl(ts, 4, true, false, false);
+ } while (g_bl_data.bl_status != 0x10 &&
+ g_bl_data.bl_status != 0x11 &&
+ tries++ < 100);
+ LOG_TP();
+ return rc;
+}
+
+static int get_hex_fw_ver(u8 *p, u8 *ttspver_hi, u8 *ttspver_lo,
+ u8 *appid_hi, u8 *appid_lo, u8 *appver_hi,
+ u8 *appver_lo, u8 *cid_0, u8 *cid_1, u8 *cid_2)
+{
+ int rc;
+
+ p = p + ID_INFO_OFFSET_IN_REC;
+ rc = str2uc(p, ttspver_hi);
+ if (rc < 0)
+ return rc;
+ p += 2;
+ rc = str2uc(p, ttspver_lo);
+ if (rc < 0)
+ return rc;
+ p += 2;
+ rc = str2uc(p, appid_hi);
+ if (rc < 0)
+ return rc;
+ p += 2;
+ rc = str2uc(p, appid_lo);
+ if (rc < 0)
+ return rc;
+ p += 2;
+ rc = str2uc(p, appver_hi);
+ if (rc < 0)
+ return rc;
+ p += 2;
+ rc = str2uc(p, appver_lo);
+ if (rc < 0)
+ return rc;
+ p += 2;
+ rc = str2uc(p, cid_0);
+ if (rc < 0)
+ return rc;
+ p += 2;
+ rc = str2uc(p, cid_1);
+ if (rc < 0)
+ return rc;
+ p += 2;
+ rc = str2uc(p, cid_2);
+ if (rc < 0)
+ return rc;
+
+ return 0;
+}
+
+static void cyttspfw_flash_start(struct cyttsp *ts, const u8 *data,
+ int data_len, u8 *buf, bool force)
+{
+ int rc;
+ u8 ttspver_hi = 0, ttspver_lo = 0, fw_upgrade = 0;
+ u8 appid_hi = 0, appid_lo = 0;
+ u8 appver_hi = 0, appver_lo = 0;
+ u8 cid_0 = 0, cid_1 = 0, cid_2 = 0;
+ char *p = buf;
+
+ /* get hex firmware version */
+ rc = get_hex_fw_ver(p, &ttspver_hi, &ttspver_lo,
+ &appid_hi, &appid_lo, &appver_hi,
+ &appver_lo, &cid_0, &cid_1, &cid_2);
+printk("++++tpd-fw-ver: %x %x %x %x %x %x %x %x %x\n", ttspver_hi, ttspver_lo, appid_hi, appid_lo, appver_hi,appver_lo, cid_0, cid_1,cid_2);
+ if (rc < 0) {
+ pr_err("%s: unable to get hex firmware version\n", __func__);
+ return;
+ }
+#if 0 //wujinyou
+ /* disable interrupts before flashing */
+ if (ts->client->irq == 0)
+ del_timer(&ts->timer);
+ else
+ disable_irq(ts->client->irq);
+
+ rc = cancel_work_sync(&ts->work);
+
+ if (rc && ts->client->irq)
+ enable_irq(ts->client->irq);
+#endif
+
+ /* enter bootloader idle mode */
+ rc = cyttsp_soft_reset(ts);
+ //LOG_TP();
+ printk("++++%s, Line %d, rc=%d\n", __FUNCTION__, __LINE__,rc);
+
+ if (rc < 0) {
+ LOG_TP();
+ pr_err("%s: cyttsp_soft_reset try entering into idle mode"
+ " second time\n", __func__);
+ msleep(1000);
+
+ rc = cyttsp_soft_reset(ts);
+ }
+
+ if (rc < 0) {
+ LOG_TP();
+ pr_err("%s:cyttsp_soft_reset try again later\n", __func__);
+ return;
+ }
+
+ LOG_TP();
+
+ pr_info("Current firmware:lusongbai %d.%d.%d", g_bl_data.appid_lo,
+ g_bl_data.appver_hi, g_bl_data.appver_lo);
+ pr_info("New firmware: %d.%d.%d", appid_lo, appver_hi, appver_lo);
+ LOG_TP();
+
+ if (force)
+ fw_upgrade = 1;
+ else
+ if ((appid_hi == g_bl_data.appid_hi) &&
+ (appid_lo == g_bl_data.appid_lo)) {
+ if (appver_hi > g_bl_data.appver_hi) {
+ fw_upgrade = 1;
+ } else if ((appver_hi == g_bl_data.appver_hi) &&
+ (appver_lo > g_bl_data.appver_lo)) {
+ fw_upgrade = 1;
+ } else {
+ fw_upgrade = 0;
+ pr_info("%s: Firmware version "
+ "lesser/equal to existing firmware, "
+ "upgrade not needed\n", __func__);
+ }
+ } else {
+ fw_upgrade = 0;
+ pr_info("%s: Firware versions do not match, "
+ "cannot upgrade\n", __func__);
+ }
+
+ printk("++++%s, Line %d, fw_upgrade=%d\n", __FUNCTION__, __LINE__,fw_upgrade);
+
+ if (fw_upgrade) {
+ pr_info("%s: Starting firmware upgrade\n", __func__);
+ rc = cyttspfw_flash_firmware(ts, data, data_len);
+ if (rc < 0)
+ pr_err("%s: firmware upgrade failed\n", __func__);
+ else
+ pr_info("%s: lusongbai firmware upgrade success\n", __func__);
+ }
+ LOG_TP();
+
+ /* enter bootloader idle mode */
+ cyttsp_soft_reset(ts);
+ LOG_TP();
+
+ /* exit bootloader mode */
+ cyttsp_exit_bl_mode(ts);
+ LOG_TP();
+
+ msleep(100);
+ /* set sysinfo details */
+ cyttsp_set_sysinfo_mode(ts);
+ LOG_TP();
+
+ /* enter application mode */
+ cyttsp_set_opmode(ts);
+ LOG_TP();
+
+ if((fw_upgrade == 1) && (rc >= 0))
+ {
+ u8 tmpData[18] = {0};
+ rc = i2c_smbus_read_i2c_block_data(ts->client,CY_REG_BASE,18, tmpData);
+ if(rc < 0)
+ {
+ printk(KERN_ERR"cyttspfw_flash_start read version and module error\n");
+ }
+ else
+ {
+ cyttsp_vendor_id=tmpData[16];
+ cyttsp_firmware_version = tmpData[17];
+ printk(KERN_ERR"cyttspfw_flash_start tp module is:%x firmware version is %x:\n",tmpData[16],tmpData[17]);
+ }
+ }
+ LOG_TP();
+
+ /* enable interrupts */
+#if 0
+ if (ts->client->irq == 0)
+ mod_timer(&ts->timer, jiffies + TOUCHSCREEN_TIMEOUT);
+ else
+ enable_irq(ts->client->irq);
+#endif
+ LOG_TP();
+
+}
+
+static void cyttspfw_upgrade_start(struct cyttsp *ts, const u8 *data,
+ int data_len, bool force)
+{
+ int i, j;
+ u8 *buf;
+
+ buf = kzalloc(REC_LINE_SIZE + 1, GFP_KERNEL);
+ if (!buf) {
+ pr_err("%s: no memory\n", __func__);
+ return;
+ }
+
+ for (i = 0, j = 0; i < data_len; i++, j++) {
+ if ((data[i] == REC_START_CHR) && j) {
+ buf[j] = 0;
+ j = 0;
+ if (!strncmp(buf, ID_INFO_REC, strlen(ID_INFO_REC))) {
+ cyttspfw_flash_start(ts, data, data_len,
+ buf, force);
+ break;
+ }
+ }
+ buf[j] = data[i];
+ }
+
+ /* check in the last record of firmware */
+ if (j) {
+ buf[j] = 0;
+ if (!strncmp(buf, ID_INFO_REC, strlen(ID_INFO_REC))) {
+ cyttspfw_flash_start(ts, data, data_len,
+ buf, force);
+ }
+ }
+
+ kfree(buf);
+}
+static bool cyttsp_IsTpInBootloader(struct cyttsp *ts)
+{
+ int retval = -1;
+ u8 tmpData[18] = {0};
+ retval = i2c_smbus_read_i2c_block_data(ts->client,CY_REG_BASE,18, tmpData);
+ if(retval < 0)
+ {
+ printk(KERN_ERR"cyttsp_IsTpInBootloader read version and module error\n");
+ return false;
+ }
+ else
+ {
+ retval = 0;
+ retval = ((tmpData[1] & 0x10) >> 4);
+
+ printk(KERN_ERR"cyttsp_IsTpInBootloader tmpData[1]:%x retval:%x\n",tmpData[1],retval);
+ }
+ if(retval == 0)
+ {
+ return false;
+ }
+ return true;
+
+}
+
+const u8 fw_hex_of[] = {
+// #include "BOOT_AG500_OF_DW_2802_V2_20120702.i"
+// #include "BOOT_AG500_OF_DW_2803_V3_20120711.i"
+};
+const u8 fw_hex_hhx[] = {
+// #include "BOOT_AG500_F5_HHX_2503_V3_20120711.i"
+};
+struct cyttsp cust_ts;
+const u8* fw_hex = fw_hex_hhx;
+extern void cyttsp_print_reg(struct i2c_client *client);
+
+int read_vender_id(void)
+{
+ char buffer[32];
+ int ret =0;
+
+ ret = i2c_smbus_read_i2c_block_data(cust_ts.client, 0x00, 24, &(buffer[0]));
+ if(ret<0)
+ {
+ return -1;
+ }
+ cyttsp_vendor_id = buffer[3];
+ printk("++++cyttp read_vender_id=0x%x\n", cyttsp_vendor_id);
+ cyttsp_print_reg(cust_ts.client);
+ return 0;
+}
+
+
+void cyttsp_fw_upgrade(void)
+{
+ struct cyttsp *ts = &cust_ts;
+ bool force = 1;
+ /* check and start upgrade */
+ //if upgrade failed we should force upgrage when next power up
+
+ if(read_vender_id() != 0)
+ {
+ printk("++++cyttspfw_upgrade read vender id failed!\n");
+ return;
+ }
+ switch(cyttsp_vendor_id)
+ {
+ case 0x28:
+ fw_hex = fw_hex_of;
+ break;
+ case 0x25:
+ fw_hex = fw_hex_hhx;
+ break;
+ case 0x0:
+ break;
+ default:
+ break;
+ }
+
+ if(cyttsp_IsTpInBootloader(ts) == true)
+ {
+ LOG_TP();
+ printk(KERN_ERR"cyttspfw_upgrade we should force upgrade tp fw\n");
+ cyttspfw_upgrade_start(ts, fw_hex,
+ sizeof(fw_hex_of), true);
+ }
+ else
+ {
+ LOG_TP();
+ cyttspfw_upgrade_start(ts, fw_hex,
+ sizeof(fw_hex_of), force);
+ }
+}
+
+#endif
+
+
+
+static int cyttsp_putbl(struct cyttsp *ts, int show,
+ int show_status, int show_version, int show_cid)
+{
+ int retval = CY_OK;
+
+ int num_bytes = (show_status * 3) + (show_version * 6) + (show_cid * 3);
+
+ if (show_cid)
+ num_bytes = sizeof(struct cyttsp_bootloader_data_t);
+ else if (show_version)
+ num_bytes = sizeof(struct cyttsp_bootloader_data_t) - 3;
+ else
+ num_bytes = sizeof(struct cyttsp_bootloader_data_t) - 9;
+ LOG_TP();
+
+ if (show) {
+ retval = i2c_smbus_read_i2c_block_data(ts->client,
+ CY_REG_BASE, num_bytes, (u8 *)&g_bl_data);
+
+ {
+ int i = 0;
+ printk("cyttsp_putbl:");
+ for(i=0; i<num_bytes; i++)
+ printk(" 0x%x",*((u8 *)&g_bl_data+i));
+ printk("\n");
+ }
+ if (show_status) {
+ cyttsp_debug("BL%d: f=%02X s=%02X err=%02X bl=%02X%02X bld=%02X%02X\n", \
+ show, \
+ g_bl_data.bl_file, \
+ g_bl_data.bl_status, \
+ g_bl_data.bl_error, \
+ g_bl_data.blver_hi, g_bl_data.blver_lo, \
+ g_bl_data.bld_blver_hi, g_bl_data.bld_blver_lo);
+ }
+ if (show_version) {
+ cyttsp_debug("BL%d: ttspver=0x%02X%02X appid=0x%02X%02X appver=0x%02X%02X\n", \
+ show, \
+ g_bl_data.ttspver_hi, g_bl_data.ttspver_lo, \
+ g_bl_data.appid_hi, g_bl_data.appid_lo, \
+ g_bl_data.appver_hi, g_bl_data.appver_lo);
+ }
+ if (show_cid) {
+ cyttsp_debug("BL%d: cid=0x%02X%02X%02X\n", \
+ show, \
+ g_bl_data.cid_0, \
+ g_bl_data.cid_1, \
+ g_bl_data.cid_2);
+ }
+ }
+ //LOG_TP();
+
+ return retval;
+}
+
+
+#ifndef CYTTSP_SUPPORT_SYS_NODE
+static void cyttsp_exit_bl_mode(struct cyttsp *ts)
+{
+ int retval, tries = 0;
+
+ do {
+ retval = i2c_smbus_write_i2c_block_data(ts->client,
+ CY_REG_BASE, sizeof(bl_cmd), bl_cmd);
+ if (retval < 0)
+ msleep(20);
+ } while (tries++ < 10 && (retval < 0));
+}
+#endif
+
+
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/cyp140_ts/debug.txt b/ANDROID_3.4.5/drivers/input/touchscreen/cyp140_ts/debug.txt
new file mode 100755
index 00000000..a424c186
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/cyp140_ts/debug.txt
@@ -0,0 +1,3 @@
+/ # wmtenv get wmt.io.touch
+1:cyp140:7:600:1024:4:0:1:-1:5 //it seems ok
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/cyp140_ts/wmt_ts.c b/ANDROID_3.4.5/drivers/input/touchscreen/cyp140_ts/wmt_ts.c
new file mode 100755
index 00000000..d7234ac3
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/cyp140_ts/wmt_ts.c
@@ -0,0 +1,1094 @@
+#include <linux/unistd.h>
+#include <linux/time.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+//#include <asm/semaphore.h>
+#include <linux/proc_fs.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/suspend.h>
+#include <linux/input.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <mach/hardware.h>
+#include <linux/i2c.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <mach/wmt_iomux.h>
+
+#include <asm/uaccess.h>
+#include <linux/fs.h>
+#include <linux/syscalls.h>
+
+#include "wmt_ts.h"
+//#include "zet6221_ts.h"
+
+/////////////////////////////////////////////////////////////////
+
+// commands for ui
+#define TS_IOC_MAGIC 't'
+
+#define TS_IOCTL_CAL_START _IO(TS_IOC_MAGIC, 1)
+#define TS_IOCTL_CAL_DONE _IOW(TS_IOC_MAGIC, 2, int*)
+#define TS_IOCTL_GET_RAWDATA _IOR(TS_IOC_MAGIC, 3, int*)
+#define TS_IOCTL_CAL_QUIT _IOW(TS_IOC_MAGIC, 4, int*)
+#define TS_IOCTL_AUTO_CALIBRATION _IOW(TS_IOC_MAGIC, 5, int*)
+#define TS_IOC_MAXNR 5
+
+#define TP_INFOR_ARRAY_SIZE (sizeof(l_tpinfor)/sizeof(l_tpinfor[1]))
+//
+#define TS_MAJOR 11
+#define TS_DRIVER_NAME "wmtts_touch"
+#define TS_NAME "wmtts"
+#define WMTTS_PROC_NAME "wmtts_config"
+
+#define EXT_GPIO0 0
+#define EXT_GPIO1 1
+#define EXT_GPIO2 2
+#define EXT_GPIO3 3
+#define EXT_GPIO4 4
+#define EXT_GPIO5 5
+#define EXT_GPIO6 6
+#define EXT_GPIO7 7
+
+typedef struct {
+ int a1;
+ int b1;
+ int c1;
+ int a2;
+ int b2;
+ int c2;
+ int delta;
+}CALIBRATION_PARAMETER, *PCALIBRATION_PARAMETER;
+
+
+static int irq_gpio = 7;//!!!2012-12-28
+static int rst_gpio = 4;//
+static int panelres_x;
+static int panelres_y;
+static DECLARE_WAIT_QUEUE_HEAD(queue);
+static CALIBRATION_PARAMETER g_CalcParam;
+static TS_EVENT g_evLast;
+static struct mutex cal_mutex;
+static DECLARE_WAIT_QUEUE_HEAD(ts_penup_wait_queue);
+static int lcd_exchg = 0;
+
+static struct class* l_dev_class = NULL;
+static struct device *l_clsdevice = NULL;
+extern struct wmtts_device cyp140_tsdev;
+static struct wmtts_device* l_tsdev = &cyp140_tsdev;
+struct proc_dir_entry* l_tsproc = NULL;
+static struct i2c_client *l_client=NULL;
+static int l_penup = 1; // 1-pen up,0-pen down
+
+struct tp_infor
+{
+ //enum tp_type type;
+ char name[64];
+ //unsigned int i2caddr;
+ unsigned int xaxis; //0: x,1: x swap with y
+ unsigned int xdir; // 1: positive,-1: revert
+ unsigned int ydir; // 1: positive,-1: revert
+ unsigned int max_finger_num;
+};
+
+static int l_tpindex = -1;
+static struct tp_infor l_tpinfor[1];
+
+/////////////////////////////////////////////////////
+// function declare
+/////////////////////////////////////////////////////
+extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
+extern int wmt_setsyspara(char *varname, unsigned char *varval);
+static int ts_writeproc( struct file *file,
+ const char *buffer,
+ unsigned long count,
+ void *data );
+static int ts_readproc(char *page, char **start, off_t off,
+ int count, int *eof, void *data);
+///////////////////////////////////////////////////////////////////////
+void TouchPanelCalibrateAPoint(
+ int UncalX, //@PARM The uncalibrated X coordinate
+ int UncalY, //@PARM The uncalibrated Y coordinate
+ int *pCalX, //@PARM The calibrated X coordinate
+ int *pCalY //@PARM The calibrated Y coordinate
+ )
+{
+ int x, y;
+ mutex_lock(&cal_mutex);
+ x = (g_CalcParam.a1 * UncalX + g_CalcParam.b1 * UncalY +
+ g_CalcParam.c1) / g_CalcParam.delta;
+ y = (g_CalcParam.a2 * UncalX + g_CalcParam.b2 * UncalY +
+ g_CalcParam.c2) / g_CalcParam.delta;
+
+//klog("afer(%d,%d)(%d,%d)\n", x,y,panelres_x,panelres_y);
+ if ( x < 0 )
+ x = 0;
+
+ if ( y < 0 )
+ y = 0;
+ if (x >= panelres_x)
+ x = panelres_x-1;
+ if (y >= panelres_y)
+ y = panelres_y-1;
+
+ *pCalX = x;
+ *pCalY = y;
+ mutex_unlock(&cal_mutex);
+ return;
+}
+
+int wmt_ts_if_updatefw(void)
+{
+ /*if ((!strcmp(l_tpinfor[l_tpindex].name,"ZET6221_7dgntpc0350")) ||
+ (!strcmp(l_tpinfor[l_tpindex].name,"ZET6221_7zcc1950")) ||
+ (!strcmp(l_tpinfor[l_tpindex].name,"ZET6221_8dgntpc0406")) ||
+ (!strcmp(l_tpinfor[l_tpindex].name,"ZET6221_7adc700148")) ||
+ (!strcmp(l_tpinfor[l_tpindex].name,"ZET6221_8xdc806")) ||
+ (!strcmp(l_tpinfor[l_tpindex].name,"ZET6221_7tp070005q8")) ||
+ (!strcmp(l_tpinfor[l_tpindex].name,"ZET6221_7yiheng7002")) ||
+ (!strcmp(l_tpinfor[l_tpindex].name,"ZET6221_7atc7031"))||
+ (!strcmp(l_tpinfor[l_tpindex].name,"ZET6221_7xclg7027a")) ||
+ (!strcmp(l_tpinfor[l_tpindex].name,"ZET6221_7est07000416")))
+ {
+ return 1;
+ }
+
+ return 0;
+ */
+
+ struct file *fp;
+ char filepath[128];
+
+ sprintf(filepath,"/lib/firmware/%s_fw.ts",l_tpinfor[l_tpindex].name);
+
+ fp = filp_open(filepath, O_RDONLY, 0);
+ if (IS_ERR(fp))
+ {
+ //printk("create file error\n");
+ return 0;
+ }
+ filp_close(fp, NULL);
+ return 1;
+}
+
+unsigned int wmt_ts_get_xaxis(void)
+{
+ return l_tpinfor[l_tpindex].xaxis;
+}
+
+unsigned int wmt_ts_get_xdir(void)
+{
+ return l_tpinfor[l_tpindex].xdir;
+}
+
+unsigned int wmt_ts_get_ydir(void)
+{
+ return l_tpinfor[l_tpindex].ydir;
+}
+
+unsigned int wmt_ts_get_maxfingernum(void)
+{
+ return l_tpinfor[l_tpindex].max_finger_num;
+}
+
+#if 0
+static int parse_firmwarefile(char* filedata, unsigned char** firmarr, int maxlen)
+{
+ char endflag[]="/* End flag */";
+ char* p = filedata;
+ int i = 0;
+ int j = 0;
+ char* s = NULL;
+
+ s = p;
+ // calculate the number of array
+ while (strncmp(p,endflag,strlen(endflag)))
+ {
+ if (!strncmp(p,"0x",strlen("0x")))
+ {
+ i++;
+ }
+ p++;
+ };
+ dbg("the number of arry:0x%x\n", i);
+ // alloc the memory for array
+ j = i + i%4;
+ *firmarr = kzalloc(sizeof(unsigned char)*j, GFP_KERNEL);
+ // parse the value of array
+ p = s;
+ j = 0;
+ while (strncmp(p,endflag,strlen(endflag)))
+ {
+ if (!strncmp(p,"0x",strlen("0x")))
+ {
+ //dbg("find 0x!\n");
+ sscanf(p,"0x%x", &((*firmarr)[j]));
+ //dbg("arry[0x%x]:%x\n",j,(*firmarr)[j]);
+ j++;
+ p+=4;
+ } else {
+ p++;
+ }
+ //p = strchr(p,'}');
+ if (j>=i-2)
+ {
+ dbg("%s",p);
+ }
+
+ };
+ if (i != j)
+ {
+ errlog("Error parsing file(the number of arry not match)!\n");
+ return -1;
+ };
+ dbg("paring firmware file end.\n");
+ return i;
+}
+
+//filepath:the path of firmware file;
+//firmdata:store the data from firmware file;
+//return:0-successful,negative-parsing error.
+int read_firmwarefile(char* filepath, unsigned char** firmdata)
+{
+ struct file *fp;
+ mm_segment_t fs;
+ loff_t pos;
+ char* data = NULL;
+ long fsize;
+ int alloclen = 2052*(8*5+2)+200;
+ int i = 0;
+
+ klog("ts firmware file:%s\n",filepath);
+ data = kzalloc(alloclen, GFP_KERNEL);
+ if (data == NULL)
+ {
+ errlog("Error when alloc memory for firmware file!\n");
+ return -1;
+ }
+ fp = filp_open(filepath, O_RDONLY, 0);
+ if (IS_ERR(fp)) {
+ printk("create file error\n");
+ goto error_flip_open;
+ }
+ fs = get_fs();
+ set_fs(KERNEL_DS);
+ pos = 0;
+ fsize = vfs_read(fp, data, alloclen, &pos);
+ dbg("filesize:0x%x,alloclen:0x%x\n",fsize,alloclen);
+ if (fsize <= 0)
+ {
+ errlog("alloc size is too small.\n");
+ goto error_vfs_read;
+ }
+ i = parse_firmwarefile(data,firmdata,fsize);
+ // Check the parsing and ori file
+ /* for (i=0;i < maxlen; i++)
+ {
+ if (firmdata[i]!=nvctp_BinaryFile_default[i])
+ {
+ errlog("Don't match:i=%x,parse:0x%x,ori:0x%x\n",i,firmdata[i], nvctp_BinaryFile_default[i]);
+ break;
+ }
+ };
+ dbg("parsing match with ori.\n");
+ */
+ filp_close(fp, NULL);
+ set_fs(fs);
+ kfree(data);
+ dbg("success to read firmware file!\n");;
+
+ //sscanf(data,"%hd %hd %hd",&offset.u.x,&offset.u.y,&offset.u.z);
+ return i;
+error_vfs_read:
+ filp_close(fp, NULL);
+ set_fs(fs);
+error_flip_open:
+ kfree(data);
+ return -1;
+}
+#endif
+
+void wmt_ts_get_firmwname(char* firmname)
+{
+ sprintf(firmname,"/lib/firmware/%s_fw.ts",l_tpinfor[l_tpindex].name);
+}
+
+ int wmt_ts_get_irqgpnum(void)
+{
+ return irq_gpio;
+}
+
+int wmt_ts_get_resetgpnum(void)
+{
+ return rst_gpio;
+}
+
+ int wmt_ts_get_lcdexchg(void)
+{
+ return lcd_exchg;
+}
+
+int wmt_ts_get_resolvX(void)
+{
+ return panelres_x;
+}
+
+int wmt_ts_get_resolvY(void)
+{
+ return panelres_y;
+}
+
+//up:1-pen up,0-pen down
+void wmt_ts_set_penup(int up)
+{
+ l_penup = up;
+}
+
+//
+int wmt_ts_wait_penup(void)
+{
+ int ret = wait_event_interruptible(
+ ts_penup_wait_queue,
+ (1==l_penup));
+ return ret;
+}
+
+// return:1-pen up,0-pen dwon
+int wmt_ts_ispenup(void)
+{
+ return l_penup;
+}
+
+
+void wmt_ts_wakeup_penup(void)
+{
+ wake_up(&ts_penup_wait_queue);
+}
+
+int wmt_is_tsirq_enable(void)
+{
+ int val = 0;
+ int num = irq_gpio;
+
+ if(num > 11)
+ return 0;
+
+ if(num<4)
+ val = REG32_VAL(__GPIO_BASE+0x0300) & (1<<(num*8+7));
+ else if(num >= 4 && num < 8)
+ val = REG32_VAL(__GPIO_BASE+0x0304) & (1<<((num-4)*8+7));
+ else
+ val = REG32_VAL(__GPIO_BASE+0x0308) & (1<<((num-8)*8+7));
+
+ return val?1:0;
+
+}
+
+int wmt_is_tsint(void)
+{
+ int num = irq_gpio;
+
+ if (num > 11)
+ {
+ return 0;
+ }
+ return (REG32_VAL(__GPIO_BASE+0x0360) & (1<<num)) ? 1: 0;
+}
+
+void wmt_clr_int(void)
+{
+ int num = irq_gpio;
+
+ if (num > 11)
+ {
+ return;
+ }
+ REG32_VAL(__GPIO_BASE+0x0360) = 1<<num;
+}
+
+void wmt_tsreset_init(void)
+{
+ int num = rst_gpio;
+/*
+ REG32_VAL(__GPIO_BASE+0x0040) |= (1<<num);//&= ~(1<<num); //enable gpio
+ REG32_VAL(__GPIO_BASE+0x00C0) &= ~(1<<num); // out low
+ REG32_VAL(__GPIO_BASE+0x0080) |= (1<<num); //output enable
+ msleep(10);
+ REG32_VAL(__GPIO_BASE+0x00C0) |= (1<<num); // out high
+*/
+ gpio_direction_output(num, 0);
+ msleep(10);
+ gpio_set_value(num, 1);
+}
+/*
+// enable:0-disable,1-enable
+void wmt_enable_rst_pull(int enable)
+{
+ if (enable)
+ {
+ REG32_VAL(__GPIO_BASE+0x0480) |= (1<<rst_gpio); //enable pull up/down
+ } else {
+ REG32_VAL(__GPIO_BASE+0x0480) &= ~(1<<rst_gpio); //disable pull up/down
+ }
+}
+*/
+
+// enable:0-disable,1-enable
+void wmt_disable_rst_pull(void)
+{
+ wmt_gpio_setpull(rst_gpio, WMT_GPIO_PULL_NONE);
+
+}
+
+// up:0-pull down,1-pull up
+void wmt_set_rst_pull(int up)
+{
+ wmt_gpio_setpull(rst_gpio, up ? WMT_GPIO_PULL_UP : WMT_GPIO_PULL_DOWN);
+}
+
+// high:0-low level,1-high level
+void wmt_rst_output(int high)
+{
+ if (high)
+ gpio_direction_output(rst_gpio, 1);
+ else
+ gpio_direction_output(rst_gpio, 0);
+}
+
+void wmt_rst_input(void)
+{
+ gpio_direction_input(rst_gpio);
+}
+
+void wmt_set_intasgp(void)
+{
+ REG32_VAL(__GPIO_BASE+0x0040) |= (1<<irq_gpio); //enable gpio
+}
+
+// val:1--high,0-low
+void wmt_intgp_out(int val)
+{
+ if (val)
+ {
+ REG32_VAL(__GPIO_BASE+0x00C0) |= (1<<irq_gpio); // high
+ } else {
+ REG32_VAL(__GPIO_BASE+0x00C0) &= ~(1<<irq_gpio); // low
+ }
+ REG32_VAL(__GPIO_BASE+0x0080) |= (1<<irq_gpio); //set output
+}
+
+void wmt_ts_set_irqinput(void)
+{
+ int num = irq_gpio;
+
+ REG32_VAL(__GPIO_BASE+0x0040) |= (1<<num); //enable gpio
+ REG32_VAL(__GPIO_BASE+0x0080) &= ~(1<<num); //set input
+}
+
+unsigned int wmt_ts_irqinval(void)
+{
+ return REG32_VAL(__GPIO_BASE+0x0000)&(1<<irq_gpio);
+}
+
+int wmt_set_gpirq(int type)
+{
+ int shift;
+ int offset;
+ unsigned long reg;
+ int num = irq_gpio;
+
+ if(num >11)
+ return -1;
+ //if (num > 9)
+ //GPIO_PIN_SHARING_SEL_4BYTE_VAL &= ~BIT4; // gpio10,11 as gpio
+ REG32_VAL(__GPIO_BASE+0x0040) &= ~(1<<num);//|=(1<<num);// //enable gpio
+ REG32_VAL(__GPIO_BASE+0x0080) &= ~(1<<num); //set input
+ REG32_VAL(__GPIO_BASE+0x04c0) |= (1<<num); //pull up
+ //REG32_VAL(__GPIO_BASE+0x0480) &= ~(1<<num); //enable pull up/down .debug pulldown 2013-5-8
+ REG32_VAL(__GPIO_BASE+0x0480) |= (1<<num); //enable pull up/down 2013-1-4 replace 2013-5-7 default enable!!
+ //REG32_VAL(__GPIO_BASE+0x0480) &= ~(1<<num); //enable pull up/down
+ //set gpio irq triger type
+ if(num < 4){//[0,3]
+ shift = num;
+ offset = 0x0300;
+ }else if(num >= 4 && num < 8){//[4,7]
+ shift = num-4;
+ offset = 0x0304;
+ }else{// [8,11]
+ shift = num-8;
+ offset = 0x0308;
+ }
+
+ reg = REG32_VAL(__GPIO_BASE + offset);
+
+ switch(type){
+ case IRQ_TYPE_LEVEL_LOW:
+ reg &= ~(1<<(shift*8+2));
+ reg &= ~(1<<(shift*8+1));
+ reg &= ~(1<<(shift*8));
+ break;
+ case IRQ_TYPE_LEVEL_HIGH:
+ reg &= ~(1<<(shift*8+2));
+ reg &= ~(1<<(shift*8+1));
+ reg |= (1<<(shift*8));
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ reg &= ~(1<<(shift*8+2));
+ reg |= (1<<(shift*8+1));
+ reg &= ~(1<<(shift*8));
+ break;
+ case IRQ_TYPE_EDGE_RISING:
+ reg &= ~(1<<(shift*8+2));
+ reg |= (1<<(shift*8+1));
+ reg |= (1<<(shift*8));
+ break;
+ default://both edge
+ reg |= (1<<(shift*8+2));
+ reg &= ~(1<<(shift*8+1));
+ reg &= ~(1<<(shift*8));
+ break;
+
+ }
+ //reg |= 1<<(shift*8+7);//enable interrupt
+ reg &= ~(1<<(shift*8+7)); //disable int
+
+ REG32_VAL(__GPIO_BASE + offset) = reg;
+ REG32_VAL(__GPIO_BASE+0x0360) = 1<<num; //clear interrupt status
+ msleep(5);
+ return 0;
+}
+
+int wmt_enable_gpirq(void)
+{
+ int num = irq_gpio;
+
+ if(num > 11)
+ return -1;
+
+ if(num<4)
+ REG32_VAL(__GPIO_BASE+0x0300) |= 1<<(num*8+7); //enable interrupt
+ else if(num >= 4 && num < 8)
+ REG32_VAL(__GPIO_BASE+0x0304) |= 1<<((num-4)*8+7); //enable interrupt
+ else
+ REG32_VAL(__GPIO_BASE+0x0308) |= 1<<((num-8)*8+7); //enable interrupt
+
+ return 0;
+}
+
+int wmt_disable_gpirq(void)
+{
+ int num = irq_gpio;
+
+ if(num > 11)
+ return -1;
+
+ if(num<4)
+ REG32_VAL(__GPIO_BASE+0x0300) &= ~(1<<(num*8+7)); //enable interrupt
+ else if(num >= 4 && num < 8)
+ REG32_VAL(__GPIO_BASE+0x0304) &= ~(1<<((num-4)*8+7)); //enable interrupt
+ else
+ REG32_VAL(__GPIO_BASE+0x0308) &= ~(1<<((num-8)*8+7)); //enable interrupt
+
+ return 0;
+}
+
+
+int wmt_get_tsirqnum(void)
+{
+ return IRQ_GPIO;
+}
+
+
+int wmt_ts_set_rawcoord(unsigned short x, unsigned short y)
+{
+ g_evLast.x = x;
+ g_evLast.y = y;
+ //dbg("raw(%d,%d)*\n", x, y);
+ return 0;
+}
+
+static void wmt_ts_platform_release(struct device *device)
+{
+ return;
+}
+
+static struct platform_device wmt_ts_plt_device = {
+ .name = TS_DRIVER_NAME,
+ .id = 0,
+ .dev = {
+ .release = wmt_ts_platform_release,
+ },
+// .num_resources = ARRAY_SIZE(wm9715_ts_resources),
+// .resource = wm9715_ts_resources,
+};
+
+static int wmt_ts_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ dbg("ts suspend....\n");
+ return l_tsdev->suspend(pdev, state);
+}
+static int wmt_ts_resume(struct platform_device *pdev)
+{
+ dbg("ts resume....\n");
+ return l_tsdev->resume(pdev);
+}
+
+static int wmt_ts_probe(struct platform_device *pdev)
+{
+ l_tsproc= create_proc_entry(WMTTS_PROC_NAME, 0666, NULL/*&proc_root*/);
+ if (l_tsproc != NULL)
+ {
+ l_tsproc->read_proc = ts_readproc;
+ l_tsproc->write_proc = ts_writeproc;
+ }
+
+ if (l_tsdev->probe != NULL)
+ return l_tsdev->probe(pdev);
+ else
+ return 0;
+}
+
+static int wmt_ts_remove(struct platform_device *pdev)
+{
+ if (l_tsproc != NULL)
+ {
+ remove_proc_entry(WMTTS_PROC_NAME, NULL);
+ l_tsproc = NULL;
+ }
+
+ if (l_tsdev->remove != NULL)
+ return l_tsdev->remove(pdev);
+ else
+ return 0;
+}
+
+static struct platform_driver wmt_ts_plt_driver = {
+ .driver = {
+ .name = TS_DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = wmt_ts_probe,
+ .remove = wmt_ts_remove,
+ .suspend = wmt_ts_suspend,
+ .resume = wmt_ts_resume,
+};
+
+static int wmt_ts_open(struct inode *inode, struct file *filp)
+{
+ int ret = 0;
+
+ klog("wmt ts driver opening...\n");
+
+ //ts_clear();
+ //try_module_get(THIS_MODULE);
+
+ return ret;
+}
+
+static int wmt_ts_close(struct inode *inode, struct file *filp)
+{
+ klog("wmt ts driver closing...\n");
+ //ts_clear();
+ //module_put(THIS_MODULE);
+
+ return 0;
+}
+
+static unsigned int wmt_ts_poll(struct file *filp, struct poll_table_struct *wait)
+{
+#if 0
+ poll_wait(filp, &queue, wait);
+ if ( head != tail )
+ return (POLLIN | POLLRDNORM);
+#endif
+ return 0;
+}
+
+static long wmt_ts_ioctl(/*struct inode * node,*/ struct file *dev, unsigned int cmd, unsigned long arg)
+{
+ int nBuff[7];
+ char env_val[96]={0};
+ //dbg("wmt_ts_ioctl(node=0x%p, dev=0x%p, cmd=0x%08x, arg=0x%08lx)\n", node, dev, cmd, arg);
+
+ if (_IOC_TYPE(cmd) != TS_IOC_MAGIC){
+ dbg("CMD ERROR!");
+ return -ENOTTY;
+ }
+
+ if (_IOC_NR(cmd) > TS_IOC_MAXNR){
+ dbg("NO SUCH IO CMD!\n");
+ return -ENOTTY;
+ }
+
+ switch (cmd) {
+
+ case TS_IOCTL_CAL_DONE:
+ klog("wmt_ts_ioctl: TS_IOCTL_CAL_DONE\n");
+ copy_from_user(nBuff, (unsigned int*)arg, 7*sizeof(int));
+
+ mutex_lock(&cal_mutex);
+ g_CalcParam.a1 = nBuff[0];
+ g_CalcParam.b1 = nBuff[1];
+ g_CalcParam.c1 = nBuff[2];
+ g_CalcParam.a2 = nBuff[3];
+ g_CalcParam.b2 = nBuff[4];
+ g_CalcParam.c2 = nBuff[5];
+ g_CalcParam.delta = nBuff[6];
+
+ if(g_CalcParam.delta == 0)
+ g_CalcParam.delta =1;//avoid divide by zero
+
+ mutex_unlock(&cal_mutex);
+
+ sprintf(env_val,"%d %d %d %d %d %d %d",nBuff[0],nBuff[1],nBuff[2],nBuff[3],nBuff[4],nBuff[5],nBuff[6]);
+ wmt_setsyspara("wmt.io.ts.2dcal", env_val);
+ klog("Tsc calibrate done data: [%s]\n",env_val);
+
+ return 0;
+
+
+ case TS_IOCTL_GET_RAWDATA:
+ // wait for point up
+ dbg("test wait_penup\n");
+ //l_tsdev->wait_penup(&gt811_tsdev);
+ klog("wmt_ts_ioctl: TS_IOCTL_GET_RAWDATA\n");
+ wmt_ts_wait_penup();
+
+ nBuff[0] = g_evLast.x;
+ nBuff[1] = g_evLast.y;
+ copy_to_user((unsigned int*)arg, nBuff, 2*sizeof(int));
+ klog("raw data: x=%d, y=%d\n", nBuff[0], nBuff[1]);
+
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static ssize_t wmt_ts_read(struct file *filp, char *buf, size_t count, loff_t *l)
+{
+ // read firmware file
+
+ return 0;
+}
+
+
+static struct file_operations wmt_ts_fops = {
+ .read = wmt_ts_read,
+ .poll = wmt_ts_poll,
+ .unlocked_ioctl = wmt_ts_ioctl,
+ .open = wmt_ts_open,
+ .release = wmt_ts_close,
+};
+
+static int ts_writeproc( struct file *file,
+ const char *buffer,
+ unsigned long count,
+ void *data )
+{
+ int calibrate = 0;
+ int val = 0;
+
+ if (sscanf(buffer, "calibrate=%d\n", &calibrate))
+ {
+ if (1 == calibrate)
+ {
+ if((l_tsdev->capacitance_calibrate != NULL) &&
+ (0 == l_tsdev->capacitance_calibrate()))
+ {
+ printk(KERN_ALERT "%s calibration successfully!\n", l_tsdev->ts_id);
+ } else {
+ printk(KERN_ALERT "%s calibration failed!\n", l_tsdev->ts_id);
+ }
+ }
+ } else if (sscanf(buffer, "reset=%d\n", &val))
+ {
+
+ }
+ return count;
+}
+
+static int ts_readproc(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int len = 0;
+
+ len = sprintf(page,
+ "echo calibrate=1 > /proc/wmtts_config to calibrate ts.\n");
+ return len;
+}
+
+static int wmt_check_touch_env(void)
+{
+ int ret = 0;
+ int len = 96, i = 0;
+ char retval[200] = {0},*p=NULL,*s=NULL;
+ //int nBuff[7] = {0};
+ int Enable=0; //Gpio=0,PX=0,PY=0;
+ int val,val1;
+
+ // Get u-boot parameter
+ ret = wmt_getsyspara("wmt.io.touch", retval, &len);
+ if(ret){
+ errlog("Read wmt.io.touch Failed.\n");
+ return -EIO;
+ }
+ memset(l_tpinfor,0,sizeof(l_tpinfor[0]));
+ p = retval;
+ sscanf(p,"%d:", &Enable);
+ p = strchr(p,':');p++;
+ s = strchr(p,':');
+ strncpy(l_tpinfor[0].name,p, (s-p));
+ p = s+1;
+ dbg("ts_name=%s\n", l_tpinfor[0].name);
+
+ ret = sscanf(p,"%d:%d:%d:%d:%d:%d:%d:%d",
+ &irq_gpio,&panelres_x,&panelres_y,&rst_gpio,
+ &(l_tpinfor[0].xaxis),&(l_tpinfor[0].xdir),&(l_tpinfor[0].ydir),
+ &(l_tpinfor[0].max_finger_num));
+ if (ret != 8)
+ {
+ dbg("Wrong format ts u-boot param(%d)!\n",ret);
+ return -ENODEV;
+ }
+ //check touch enable
+ if(Enable == 0){
+ errlog("Touch Screen Is Disabled.\n");
+ return -ENODEV;
+ }
+
+ /*p = strchr(retval,':');
+ p++;
+ if(strncmp(p, l_tsdev->ts_id,strlen(l_tsdev->ts_id))){//check touch ID
+ //errlog(" %s!=====\n", l_tsdev->ts_id);
+ return -ENODEV;
+ }*/
+
+ //sscanf(p,"%s:", );
+#if 1
+ if (strstr(l_tpinfor[0].name, l_tsdev->ts_id) == NULL)// cyp140
+ {
+ dbg("Can't find %s!\n", l_tsdev->ts_id);
+ return -ENODEV;
+ }
+#endif //comment 2012-12-31
+ l_tpindex = 0;
+
+/*
+ p = strchr(p,':');
+ p++;
+ sscanf(p,"%d:%d:%d:%d",&irq_gpio,&panelres_x,&panelres_y,&rst_gpio);
+
+ irq_gpio = Gpio;
+ panelres_x = PX;
+ panelres_y = PY;
+ */
+ klog("p.x = %d, p.y = %d, gpio=%d, resetgpio=%d,xaxis=%d,xdir=%d,ydri=%d,maxfingernum=%d\n",
+ panelres_x, panelres_y, irq_gpio, rst_gpio,
+ l_tpinfor[0].xaxis,l_tpinfor[0].xdir,l_tpinfor[0].ydir,
+ l_tpinfor[0].max_finger_num);
+
+ // parse touch key param
+ memset(retval,0,sizeof(retval));
+ ret = wmt_getsyspara("wmt.io.tskeyindex", retval, &len);
+ if(ret){
+ dbg("no touch key!\n");
+ //return -EIO;
+ } else {
+ p = retval;
+ // the number of touch key
+ sscanf(retval,"%d:", &val);
+ dbg("tskey num:%d\n",val);
+ p = strchr(p,':');
+ p++;
+ // touch key range
+ for (i=0;i<val;i++)
+ {
+ sscanf(p,"%d:",&val1);
+ p = strchr(p,':');
+ p++;
+ //zet6221_set_tskey(i, val1); //own tp ic 2012-12-31??!!!
+ dbg("key%d:(%d)\n",i,val1);
+ };
+ }
+
+ ret = wmt_getsyspara("wmt.display.fb0", retval, &len);
+ if (!ret) {
+ int tmp[6];
+ p = retval;
+ sscanf(p, "%d:[%d:%d:%d:%d:%d", &tmp[0], &tmp[1], &tmp[2], &tmp[3], &tmp[4], &tmp[5]);
+ if (tmp[4] > tmp[5])
+ lcd_exchg = 1;
+ }
+
+/* memset(retval,0,sizeof(retval));
+ ret = wmt_getsyspara("wmt.io.ts.2dcal", retval, &len);
+ if(ret){
+ errlog("Read env wmt.io.ts.2dcal Failed.\n ");
+ //return -EIO;
+ }
+ i = 0;
+ while(i < sizeof(retval)){
+ if(retval[i]==' ' || retval[i]==',' || retval[i]==':')
+ retval[i] = '\0';
+ i++;
+ }
+
+ i = 0;
+ p = retval;
+ while(i<7 && p < (retval + sizeof(retval))){
+ if(*p == '\0')
+ p++;
+ else{
+ sscanf(p,"%d",&nBuff[i]);
+ //printk("%d\n",nBuff[i]);
+ p=p+strlen(p);
+ i++;
+ }
+ }
+ //sscanf(retval,"%d %d %d %d %d %d %d %d",&nBuff[0],&nBuff[1],&nBuff[2],&nBuff[3],&nBuff[4],&nBuff[5],&nBuff[6]);
+ dbg("Tsc calibrate init data: [%d %d %d %d %d %d %d]\n",nBuff[0],nBuff[1],nBuff[2],nBuff[3],nBuff[4],nBuff[5],nBuff[6]);
+
+ g_CalcParam.a1 = nBuff[0];
+ g_CalcParam.b1 = nBuff[1];
+ g_CalcParam.c1 = nBuff[2];
+ g_CalcParam.a2 = nBuff[3];
+ g_CalcParam.b2 = nBuff[4];
+ g_CalcParam.c2 = nBuff[5];
+ g_CalcParam.delta = nBuff[6];
+
+ if(g_CalcParam.delta == 0)
+ g_CalcParam.delta =1;//avoid divide by zero
+*/
+ return 0;
+}
+
+struct i2c_board_info ts_i2c_board_info = {
+ .type = WMT_TS_I2C_NAME,
+ .flags = 0x00,
+ .addr = WMT_TS_I2C_ADDR,
+ .platform_data = NULL,
+ .archdata = NULL,
+ .irq = -1,
+};
+
+static int ts_i2c_register_device (void)
+{
+ struct i2c_board_info *ts_i2c_bi;
+ struct i2c_adapter *adapter = NULL;
+ //struct i2c_client *client = NULL;
+ ts_i2c_bi = &ts_i2c_board_info;
+ adapter = i2c_get_adapter(1);/*in bus 1*/
+
+ if (NULL == adapter) {
+ printk("can not get i2c adapter, client address error\n");
+ return -1;
+ }
+ l_client = i2c_new_device(adapter, ts_i2c_bi);
+ if (l_client == NULL) {
+ printk("allocate i2c client failed\n");
+ return -1;
+ }
+ i2c_put_adapter(adapter);
+ return 0;
+}
+
+static void ts_i2c_unregister_device(void)
+{
+ if (l_client != NULL)
+ {
+ i2c_unregister_device(l_client);
+ l_client = NULL;
+ }
+}
+
+struct i2c_client* ts_get_i2c_client(void)
+{
+ return l_client;
+}
+
+static int __init wmt_ts_init(void)
+{
+ int ret = 0;
+
+
+
+ if(wmt_check_touch_env())
+ return -ENODEV;
+
+ //ts_i2c_board_info.addr = l_tpinfor[l_tpindex].i2caddr;
+ if (ts_i2c_register_device()<0)
+ {
+ dbg("Error to run ts_i2c_register_device()!\n");
+ return -1;
+ }
+ mutex_init(&cal_mutex);
+
+ if (l_tsdev->init() < 0){
+ dbg("Errors to init %s ts IC!!!\n", l_tsdev->ts_id);
+ ret = -1;
+ goto err_init;
+ }
+ // Create device node
+ if (register_chrdev (TS_MAJOR, TS_NAME, &wmt_ts_fops)) {
+ printk (KERN_ERR "wmt touch: unable to get major %d\n", TS_MAJOR);
+ return -EIO;
+ }
+
+ l_dev_class = class_create(THIS_MODULE, TS_NAME);
+ if (IS_ERR(l_dev_class)){
+ ret = PTR_ERR(l_dev_class);
+ printk(KERN_ERR "Can't class_create touch device !!\n");
+ return ret;
+ }
+ l_clsdevice = device_create(l_dev_class, NULL, MKDEV(TS_MAJOR, 0), NULL, TS_NAME);
+ if (IS_ERR(l_clsdevice)){
+ ret = PTR_ERR(l_clsdevice);
+ printk(KERN_ERR "Failed to create device %s !!!",TS_NAME);
+ return ret;
+ }
+
+ // register device and driver of platform
+ ret = platform_device_register(&wmt_ts_plt_device);
+ if(ret){
+ errlog("wmt ts plat device register failed!\n");
+ return ret;
+ }
+ ret = platform_driver_register(&wmt_ts_plt_driver);
+ if(ret){
+ errlog("can not register platform_driver_register\n");
+ platform_device_unregister(&wmt_ts_plt_device);
+ return ret;
+ }
+
+ klog("%s driver init ok!\n",l_tsdev->ts_id);
+ return 0;
+err_init:
+ ts_i2c_unregister_device();
+ return ret;
+}
+
+static void __exit wmt_ts_exit(void)
+{
+ dbg("%s\n",__FUNCTION__);
+
+ l_tsdev->exit();
+ platform_driver_unregister(&wmt_ts_plt_driver);
+ platform_device_unregister(&wmt_ts_plt_device);
+ device_destroy(l_dev_class, MKDEV(TS_MAJOR, 0));
+ unregister_chrdev(TS_MAJOR, TS_NAME);
+ class_destroy(l_dev_class);
+ mutex_destroy(&cal_mutex);
+ ts_i2c_unregister_device();
+}
+
+
+module_init(wmt_ts_init);
+module_exit(wmt_ts_exit);
+
+MODULE_LICENSE("GPL");
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/cyp140_ts/wmt_ts.h b/ANDROID_3.4.5/drivers/input/touchscreen/cyp140_ts/wmt_ts.h
new file mode 100755
index 00000000..11261348
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/cyp140_ts/wmt_ts.h
@@ -0,0 +1,120 @@
+
+#ifndef WMT_TSH_201010191758
+#define WMT_TSH_201010191758
+
+#include <linux/platform_device.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/suspend.h>
+#include <linux/i2c.h>
+
+
+//#define DEBUG_WMT_TS
+#ifdef DEBUG_WMT_TS
+#undef dbg
+#define dbg(fmt, args...) printk(KERN_ALERT "[%s]: " fmt, __FUNCTION__ , ## args)
+
+//#define dbg(fmt, args...) if (kpadall_isrundbg()) printk(KERN_ALERT "[%s]: " fmt, __FUNCTION__, ## args)
+
+#else
+#define dbg(fmt, args...)
+#endif
+
+#undef errlog
+#undef klog
+#define errlog(fmt, args...) printk("[%s]: " fmt, __FUNCTION__, ## args)
+#define klog(fmt, args...) printk("[%s]: " fmt, __FUNCTION__, ## args)
+
+#define WMT_TS_I2C_NAME "cyp140-ts"
+#define WMT_TS_I2C_ADDR 0x24 //0x76
+
+
+
+
+
+//////////////////////////////data type///////////////////////////
+typedef struct {
+ short pressure;
+ short x;
+ short y;
+ //short millisecs;
+} TS_EVENT;
+
+struct wmtts_device
+{
+ //data
+ char* driver_name;
+ char* ts_id;
+ //function
+ int (*init)(void);
+ int (*probe)(struct platform_device *platdev);
+ int (*remove)(struct platform_device *pdev);
+ void (*exit)(void);
+ int (*suspend)(struct platform_device *pdev, pm_message_t state);
+ int (*resume)(struct platform_device *pdev);
+ int (*capacitance_calibrate)(void);
+ int (*wait_penup)(struct wmtts_device*tsdev); // waiting untill penup
+ int penup; // 0--pendown;1--penup
+
+};
+
+//////////////////////////function interface/////////////////////////
+extern int wmt_ts_get_irqgpnum(void);
+extern int wmt_ts_iscalibrating(void);
+extern int wmt_ts_get_resolvX(void);
+extern int wmt_ts_get_resolvY(void);
+extern int wmt_ts_set_rawcoord(unsigned short x, unsigned short y);
+extern int wmt_set_gpirq(int type);
+extern int wmt_get_tsirqnum(void);
+extern int wmt_disable_gpirq(void);
+extern int wmt_enable_gpirq(void);
+extern int wmt_is_tsirq_enable(void);
+extern int wmt_is_tsint(void);
+extern void wmt_clr_int(void);
+extern void wmt_tsreset_init(void);
+extern int wmt_ts_get_resetgpnum(void);
+extern int wmt_ts_get_lcdexchg(void);
+extern void wmt_disable_rst_pull(void);
+extern void wmt_set_rst_pull(int up);
+extern void wmt_rst_output(int high);
+extern void wmt_rst_input(void);
+extern void wmt_set_intasgp(void);
+extern void wmt_intgp_out(int val);
+extern void wmt_ts_set_irqinput(void);
+extern unsigned int wmt_ts_irqinval(void);
+extern void wmt_ts_set_penup(int up);
+extern int wmt_ts_wait_penup(void);
+extern void wmt_ts_wakeup_penup(void);
+extern struct i2c_client* ts_get_i2c_client(void);
+extern int wmt_ts_ispenup(void);
+extern void wmt_ts_get_firmwname(char* firmname);
+extern unsigned int wmt_ts_get_maxfingernum(void);
+extern unsigned int wmt_ts_get_ictype(void);
+extern unsigned int wmt_ts_get_xaxis(void);
+extern unsigned int wmt_ts_get_xdir(void);
+extern unsigned int wmt_ts_get_ydir(void);
+// short
+extern unsigned int wmt_ts_get_touchheight(void);
+// long
+extern unsigned int wmt_ts_get_touchwidth(void);
+extern int wmt_ts_if_updatefw(void);
+
+
+
+extern void TouchPanelCalibrateAPoint(
+ int UncalX, //@PARM The uncalibrated X coordinate
+ int UncalY, //@PARM The uncalibrated Y coordinate
+ int *pCalX, //@PARM The calibrated X coordinate
+ int *pCalY //@PARM The calibrated Y coordinate
+ );
+
+//filepath:the path of firmware file;
+//firmdata:store the data from firmware file;
+//maxlen: the max len of firmdata;
+//return:the length of firmware data,negative-parsing error.
+//extern int read_firmwarefile(char* filepath, unsigned char** firmdata);
+
+#endif
+
+
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/ft5x0x/Kconfig b/ANDROID_3.4.5/drivers/input/touchscreen/ft5x0x/Kconfig
new file mode 100755
index 00000000..7dadb37f
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/ft5x0x/Kconfig
@@ -0,0 +1,11 @@
+config TOUCHSCREEN_FT5X0X
+ tristate "FT5X0X Capacity Touchscreen Device Support"
+ default y
+ depends on ARCH_WMT
+ ---help---
+ Say Y here if you have an WMT based board with touchscreen
+ attached to it.
+ If unsure, say N.
+ To compile this driver as a module, choose M here: the
+ module will be called ft5x0x.
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/ft5x0x/Makefile b/ANDROID_3.4.5/drivers/input/touchscreen/ft5x0x/Makefile
new file mode 100755
index 00000000..0283c3ec
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/ft5x0x/Makefile
@@ -0,0 +1,34 @@
+KERNELDIR=../../../../
+CROSS = arm_1103_le-
+CC= $(CROSS)gcc
+LD= $(CROSS)ld
+STRIP = $(CROSS)strip
+
+DEBUG = n
+
+# Add your debugging flag (or not) to EXTRA_CFLAGS
+ifeq ($(DEBUG),y)
+# DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+DEBFLAGS = -O0 -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+
+else
+ DEBFLAGS = -O2 -Wall
+endif
+
+EXTRA_CFLAGS += $(DEBFLAGS)
+
+
+MY_MODULE_NAME=s_wmt_ts_ft5x0x
+
+#obj-$(CONFIG_TOUCHSCREEN_FT5X0X) := $(MY_MODULE_NAME).o
+obj-m := $(MY_MODULE_NAME).o
+$(MY_MODULE_NAME)-objs := ft5x0x.o ft5x0x_upg.o ft5402_config.o ini.o
+
+default:
+ $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules
+ $(STRIP) --strip-debug $(MY_MODULE_NAME).ko
+ @rm -rf *.o *~ core .depend .*.cmd *.mod.c .tmp_versions *.order *.symvers
+
+clean:
+ @rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.order *.symvers
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/ft5x0x/ft5402_config.c b/ANDROID_3.4.5/drivers/input/touchscreen/ft5x0x/ft5402_config.c
new file mode 100755
index 00000000..58683ebd
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/ft5x0x/ft5402_config.c
@@ -0,0 +1,2295 @@
+#include "ft5402_config.h"
+//#include <linux/i2c/ft5402_ts.h>
+
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/semaphore.h>
+#include <linux/mutex.h>
+#include <linux/interrupt.h>
+#include <mach/irqs.h>
+
+#include <linux/syscalls.h>
+#include <asm/unistd.h>
+#include <asm/uaccess.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+
+#include "ini.h"
+#include "ft5402_ini_config.h"
+#include "ft5x0x.h"
+
+
+extern int ft5x0x_i2c_txdata(char *txdata, int length);
+
+int ft5402_write_reg(struct i2c_client * client, u8 regaddr, u8 regvalue)
+{
+ unsigned char buf[2] = {0};
+ buf[0] = regaddr;
+ buf[1] = regvalue;
+
+ return ft5x0x_i2c_txdata(buf, 2);
+}
+
+int ft5402_read_reg(struct i2c_client * client, u8 regaddr, u8 * regvalue)
+{
+ int ret;
+
+ struct i2c_msg msgs[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = 1,
+ .buf = &regaddr,
+ },
+ {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = 1,
+ .buf = regvalue,
+ },
+ };
+ ret = i2c_transfer(client->adapter, msgs, 2);
+ if (ret < 0)
+ pr_err("function:%s. i2c read error: %d\n", __func__, ret);
+ return ret;
+}
+
+/*set tx order
+*@txNO: offset from tx order start
+*@txNO1: tx NO.
+*/
+static int ft5402_set_tx_order(struct i2c_client * client, u8 txNO, u8 txNO1)
+{
+ unsigned char ReCode = 0;
+ if (txNO < FT5402_TX_TEST_MODE_1)
+ ReCode = ft5402_write_reg(client, FT5402_REG_TX_ORDER_START + txNO,
+ txNO1);
+ else {
+ ReCode = ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE_2<<4); /*enter Test mode 2*/
+ if (ReCode >= 0)
+ ReCode = ft5402_write_reg(client,
+ FT5402_REG_TX_ORDER_START + txNO - FT5402_TX_TEST_MODE_1,
+ txNO1);
+ ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE<<4); /*enter Test mode*/
+ }
+ return ReCode;
+}
+
+/*set tx order
+*@txNO: offset from tx order start
+*@pTxNo: return value of tx NO.
+*/
+static int ft5402_get_tx_order(struct i2c_client * client, u8 txNO, u8 *pTxNo)
+{
+ unsigned char ReCode = 0;
+ if (txNO < FT5402_TX_TEST_MODE_1)
+ ReCode = ft5402_read_reg(client, FT5402_REG_TX_ORDER_START + txNO,
+ pTxNo);
+ else {
+ ReCode = ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE_2<<4); /*enter Test mode 2*/
+ if(ReCode >= 0)
+ ReCode = ft5402_read_reg(client,
+ FT5402_REG_TX_ORDER_START + txNO - FT5402_TX_TEST_MODE_1,
+ pTxNo);
+ ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE<<4); /*enter Test mode*/
+ }
+ return ReCode;
+}
+
+/*set tx cap
+*@txNO: tx NO.
+*@cap_value: value of cap
+*/
+static int ft5402_set_tx_cap(struct i2c_client * client, u8 txNO, u8 cap_value)
+{
+ unsigned char ReCode = 0;
+ if (txNO < FT5402_TX_TEST_MODE_1)
+ ReCode = ft5402_write_reg(client, FT5402_REG_TX_CAP_START + txNO,
+ cap_value);
+ else {
+ ReCode = ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE_2<<4); /*enter Test mode 2*/
+ if (ReCode >= 0)
+ ReCode = ft5402_write_reg(client,
+ FT5402_REG_TX_CAP_START + txNO - FT5402_TX_TEST_MODE_1,
+ cap_value);
+ ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE<<4); /*enter Test mode*/
+ }
+ return ReCode;
+}
+
+/*get tx cap*/
+static int ft5402_get_tx_cap(struct i2c_client * client, u8 txNO, u8 *pCap)
+{
+ unsigned char ReCode = 0;
+ if (txNO < FT5402_TX_TEST_MODE_1)
+ ReCode = ft5402_read_reg(client, FT5402_REG_TX_CAP_START + txNO,
+ pCap);
+ else {
+ ReCode = ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE_2<<4); /*enter Test mode 2*/
+ if (ReCode >= 0)
+ ReCode = ft5402_read_reg(client,
+ FT5402_REG_TX_CAP_START + txNO - FT5402_TX_TEST_MODE_1,
+ pCap);
+ ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE<<4); /*enter Test mode*/
+ }
+ return ReCode;
+}
+
+/*set tx offset*/
+static int ft5402_set_tx_offset(struct i2c_client * client, u8 txNO, u8 offset_value)
+{
+ unsigned char temp=0;
+ unsigned char ReCode = 0;
+ if (txNO < FT5402_TX_TEST_MODE_1) {
+ ReCode = ft5402_read_reg(client,
+ FT5402_REG_TX_OFFSET_START + (txNO>>1), &temp);
+ if (ReCode >= 0) {
+ if (txNO%2 == 0)
+ ReCode = ft5402_write_reg(client,
+ FT5402_REG_TX_OFFSET_START + (txNO>>1),
+ (temp&0xf0) + (offset_value&0x0f));
+ else
+ ReCode = ft5402_write_reg(client,
+ FT5402_REG_TX_OFFSET_START + (txNO>>1),
+ (temp&0x0f) + (offset_value<<4));
+ }
+ } else {
+ ReCode = ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE_2<<4); /*enter Test mode 2*/
+ if (ReCode >= 0) {
+ ReCode = ft5402_read_reg(client,
+ FT5402_REG_DEVICE_MODE+((txNO-FT5402_TX_TEST_MODE_1)>>1),
+ &temp); /*enter Test mode 2*/
+ if (ReCode >= 0) {
+ if(txNO%2 == 0)
+ ReCode = ft5402_write_reg(client,
+ FT5402_REG_TX_OFFSET_START+((txNO-FT5402_TX_TEST_MODE_1)>>1),
+ (temp&0xf0)+(offset_value&0x0f));
+ else
+ ReCode = ft5402_write_reg(client,
+ FT5402_REG_TX_OFFSET_START+((txNO-FT5402_TX_TEST_MODE_1)>>1),
+ (temp&0xf0)+(offset_value<<4));
+ }
+ }
+ ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE<<4); /*enter Test mode*/
+ }
+
+ return ReCode;
+}
+
+/*get tx offset*/
+static int ft5402_get_tx_offset(struct i2c_client * client, u8 txNO, u8 *pOffset)
+{
+ unsigned char temp=0;
+ unsigned char ReCode = 0;
+ if (txNO < FT5402_TX_TEST_MODE_1)
+ ReCode = ft5402_read_reg(client,
+ FT5402_REG_TX_OFFSET_START + (txNO>>1), &temp);
+ else {
+ ReCode = ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE_2<<4); /*enter Test mode 2*/
+ if (ReCode >= 0)
+ ReCode = ft5402_read_reg(client,
+ FT5402_REG_TX_OFFSET_START+((txNO-FT5402_TX_TEST_MODE_1)>>1),
+ &temp);
+ ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE<<4); /*enter Test mode*/
+ }
+
+ if (ReCode >= 0)
+ (txNO%2 == 0) ? (*pOffset = (temp&0x0f)) : (*pOffset = (temp>>4));
+ return ReCode;
+}
+
+/*set rx order*/
+static int ft5402_set_rx_order(struct i2c_client * client, u8 rxNO, u8 rxNO1)
+{
+ unsigned char ReCode = 0;
+ ReCode = ft5402_write_reg(client, FT5402_REG_RX_ORDER_START + rxNO,
+ rxNO1);
+ return ReCode;
+}
+
+/*get rx order*/
+static int ft5402_get_rx_order(struct i2c_client * client, u8 rxNO, u8 *prxNO1)
+{
+ unsigned char ReCode = 0;
+ ReCode = ft5402_read_reg(client, FT5402_REG_RX_ORDER_START + rxNO,
+ prxNO1);
+ return ReCode;
+}
+
+/*set rx cap*/
+static int ft5402_set_rx_cap(struct i2c_client * client, u8 rxNO, u8 cap_value)
+{
+ unsigned char ReCode = 0;
+ if (rxNO < FT5402_RX_TEST_MODE_1)
+ ReCode = ft5402_write_reg(client, FT5402_REG_RX_CAP_START + rxNO,
+ cap_value);
+ else {
+ ReCode = ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE_2<<4); /*enter Test mode 2*/
+ if(ReCode >= 0)
+ ReCode = ft5402_write_reg(client,
+ FT5402_REG_RX_CAP_START + rxNO - FT5402_RX_TEST_MODE_1,
+ cap_value);
+ ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE<<4); /*enter Test mode*/
+ }
+
+ return ReCode;
+}
+
+/*get rx cap*/
+static int ft5402_get_rx_cap(struct i2c_client * client, u8 rxNO, u8 *pCap)
+{
+ unsigned char ReCode = 0;
+ if (rxNO < FT5402_RX_TEST_MODE_1)
+ ReCode = ft5402_read_reg(client, FT5402_REG_RX_CAP_START + rxNO,
+ pCap);
+ else {
+ ReCode = ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE_2<<4); /*enter Test mode 2*/
+ if(ReCode >= 0)
+ ReCode = ft5402_read_reg(client,
+ FT5402_REG_RX_CAP_START + rxNO - FT5402_RX_TEST_MODE_1,
+ pCap);
+ ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE<<4); /*enter Test mode*/
+ }
+
+ return ReCode;
+}
+
+/*set rx offset*/
+static int ft5402_set_rx_offset(struct i2c_client * client, u8 rxNO, u8 offset_value)
+{
+ unsigned char temp=0;
+ unsigned char ReCode = 0;
+ if (rxNO < FT5402_RX_TEST_MODE_1) {
+ ReCode = ft5402_read_reg(client,
+ FT5402_REG_RX_OFFSET_START + (rxNO>>1), &temp);
+ if (ReCode >= 0) {
+ if (rxNO%2 == 0)
+ ReCode = ft5402_write_reg(client,
+ FT5402_REG_RX_OFFSET_START + (rxNO>>1),
+ (temp&0xf0) + (offset_value&0x0f));
+ else
+ ReCode = ft5402_write_reg(client,
+ FT5402_REG_RX_OFFSET_START + (rxNO>>1),
+ (temp&0x0f) + (offset_value<<4));
+ }
+ }
+ else {
+ ReCode = ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE_2<<4); /*enter Test mode 2*/
+ if (ReCode >= 0) {
+ ReCode = ft5402_read_reg(client,
+ FT5402_REG_DEVICE_MODE+((rxNO-FT5402_RX_TEST_MODE_1)>>1),
+ &temp); /*enter Test mode 2*/
+ if (ReCode >= 0) {
+ if (rxNO%2 == 0)
+ ReCode = ft5402_write_reg(client,
+ FT5402_REG_RX_OFFSET_START+((rxNO-FT5402_RX_TEST_MODE_1)>>1),
+ (temp&0xf0)+(offset_value&0x0f));
+ else
+ ReCode = ft5402_write_reg(client,
+ FT5402_REG_RX_OFFSET_START+((rxNO-FT5402_RX_TEST_MODE_1)>>1),
+ (temp&0xf0)+(offset_value<<4));
+ }
+ }
+ ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE<<4); /*enter Test mode*/
+ }
+
+ return ReCode;
+}
+
+/*get rx offset*/
+static int ft5402_get_rx_offset(struct i2c_client * client, u8 rxNO, u8 *pOffset)
+{
+ unsigned char temp = 0;
+ unsigned char ReCode = 0;
+ if (rxNO < FT5402_RX_TEST_MODE_1)
+ ReCode = ft5402_read_reg(client,
+ FT5402_REG_RX_OFFSET_START + (rxNO>>1), &temp);
+ else {
+ ReCode = ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE_2<<4); /*enter Test mode 2*/
+ if (ReCode >= 0)
+ ReCode = ft5402_read_reg(client,
+ FT5402_REG_RX_OFFSET_START+((rxNO-FT5402_RX_TEST_MODE_1)>>1),
+ &temp);
+
+ ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE<<4); /*enter Test mode*/
+ }
+
+ if (ReCode >= 0) {
+ if (0 == (rxNO%2))
+ *pOffset = (temp&0x0f);
+ else
+ *pOffset = (temp>>4);
+ }
+
+ return ReCode;
+}
+
+/*set tx num*/
+static int ft5402_set_tx_num(struct i2c_client *client, u8 txnum)
+{
+ return ft5402_write_reg(client, FT5402_REG_TX_NUM, txnum);
+}
+
+/*get tx num*/
+static int ft5402_get_tx_num(struct i2c_client *client, u8 *ptxnum)
+{
+ return ft5402_read_reg(client, FT5402_REG_TX_NUM, ptxnum);
+}
+
+/*set rx num*/
+static int ft5402_set_rx_num(struct i2c_client *client, u8 rxnum)
+{
+ return ft5402_write_reg(client, FT5402_REG_RX_NUM, rxnum);
+}
+
+/*get rx num*/
+static int ft5402_get_rx_num(struct i2c_client *client, u8 *prxnum)
+{
+ return ft5402_read_reg(client, FT5402_REG_RX_NUM, prxnum);
+}
+
+/*set resolution*/
+static int ft5402_set_Resolution(struct i2c_client *client, u16 x, u16 y)
+{
+ unsigned char cRet = 0;
+ cRet &= ft5402_write_reg(client,
+ FT5402_REG_RESOLUTION_X_H, ((unsigned char)(x>>8)));
+ cRet &= ft5402_write_reg(client,
+ FT5402_REG_RESOLUTION_X_L, ((unsigned char)(x&0x00ff)));
+
+ cRet &= ft5402_write_reg(client,
+ FT5402_REG_RESOLUTION_Y_H, ((unsigned char)(y>>8)));
+ cRet &= ft5402_write_reg(client,
+ FT5402_REG_RESOLUTION_Y_L, ((unsigned char)(y&0x00ff)));
+
+ return cRet;
+}
+
+/*get resolution*/
+static int ft5402_get_Resolution(struct i2c_client *client,
+ u16 *px, u16 *py)
+{
+ unsigned char cRet = 0, temp1 = 0, temp2 = 0;
+ cRet &= ft5402_read_reg(client,
+ FT5402_REG_RESOLUTION_X_H, &temp1);
+ cRet &= ft5402_read_reg(client,
+ FT5402_REG_RESOLUTION_X_L, &temp2);
+ (*px) = (((u16)temp1) << 8) | ((u16)temp2);
+
+ cRet &= ft5402_read_reg(client,
+ FT5402_REG_RESOLUTION_Y_H, &temp1);
+ cRet &= ft5402_read_reg(client,
+ FT5402_REG_RESOLUTION_Y_L, &temp2);
+ (*py) = (((u16)temp1) << 8) | ((u16)temp2);
+
+ return cRet;
+}
+
+
+/*set voltage*/
+static int ft5402_set_vol(struct i2c_client *client, u8 Vol)
+{
+ return ft5402_write_reg(client, FT5402_REG_VOLTAGE, Vol);
+}
+
+/*get voltage*/
+static int ft5402_get_vol(struct i2c_client *client, u8 *pVol)
+{
+ return ft5402_read_reg(client, FT5402_REG_VOLTAGE, pVol);
+}
+
+/*set gain*/
+static int ft5402_set_gain(struct i2c_client *client, u8 Gain)
+{
+ return ft5402_write_reg(client, FT5402_REG_GAIN, Gain);
+}
+
+/*get gain*/
+static int ft5402_get_gain(struct i2c_client *client, u8 *pGain)
+{
+ return ft5402_read_reg(client, FT5402_REG_GAIN, pGain);
+}
+
+/*get start rx*/
+static int ft5402_get_start_rx(struct i2c_client *client, u8 *pRx)
+{
+ return ft5402_read_reg(client, FT5402_REG_START_RX, pRx);
+}
+
+
+/*get adc target*/
+static int ft5402_get_adc_target(struct i2c_client *client, u16 *pvalue)
+{
+ int err = 0;
+ u8 tmp1, tmp2;
+ err = ft5402_read_reg(client, FT5402_REG_ADC_TARGET_HIGH,
+ &tmp1);
+ if (err < 0)
+ dev_err(&client->dev, "%s:get adc target high failed\n",
+ __func__);
+ err = ft5402_read_reg(client, FT5402_REG_ADC_TARGET_LOW,
+ &tmp2);
+ if (err < 0)
+ dev_err(&client->dev, "%s:get adc target low failed\n",
+ __func__);
+
+ *pvalue = ((u16)tmp1<<8) + (u16)tmp2;
+ return err;
+}
+
+static int ft5402_set_face_detect_statistics_tx_num(struct i2c_client *client, u8 prevalue)
+{
+ return ft5402_write_reg(client, FT5402_REG_FACE_DETECT_STATISTICS_TX_NUM,
+ prevalue);
+}
+
+static int ft5402_get_face_detect_statistics_tx_num(struct i2c_client *client, u8 *pprevalue)
+{
+ return ft5402_read_reg(client, FT5402_REG_FACE_DETECT_STATISTICS_TX_NUM,
+ pprevalue);
+}
+
+static int ft5402_set_face_detect_pre_value(struct i2c_client *client, u8 prevalue)
+{
+ return ft5402_write_reg(client, FT5402_REG_FACE_DETECT_PRE_VALUE,
+ prevalue);
+}
+
+static int ft5402_get_face_detect_pre_value(struct i2c_client *client, u8 *pprevalue)
+{
+ return ft5402_read_reg(client, FT5402_REG_FACE_DETECT_PRE_VALUE,
+ pprevalue);
+}
+
+static int ft5402_set_face_detect_num(struct i2c_client *client, u8 num)
+{
+ return ft5402_write_reg(client, FT5402_REG_FACE_DETECT_NUM,
+ num);
+}
+
+static int ft5402_get_face_detect_num(struct i2c_client *client, u8 *pnum)
+{
+ return ft5402_read_reg(client, FT5402_REG_FACE_DETECT_NUM,
+ pnum);
+}
+
+
+static int ft5402_set_peak_value_min(struct i2c_client *client, u8 min)
+{
+ return ft5402_write_reg(client, FT5402_REG_BIGAREA_PEAK_VALUE_MIN,
+ min);
+}
+
+static int ft5402_get_peak_value_min(struct i2c_client *client, u8 *pmin)
+{
+ return ft5402_read_reg(client, FT5402_REG_BIGAREA_PEAK_VALUE_MIN,
+ pmin);
+}
+
+static int ft5402_set_diff_value_over_num(struct i2c_client *client, u8 num)
+{
+ return ft5402_write_reg(client, FT5402_REG_BIGAREA_DIFF_VALUE_OVER_NUM,
+ num);
+}
+static int ft5402_get_diff_value_over_num(struct i2c_client *client, u8 *pnum)
+{
+ return ft5402_read_reg(client, FT5402_REG_BIGAREA_DIFF_VALUE_OVER_NUM,
+ pnum);
+}
+
+
+static int ft5402_set_customer_id(struct i2c_client *client, u8 num)
+{
+ return ft5402_write_reg(client, FT5402_REG_CUSTOMER_ID,
+ num);
+}
+static int ft5402_get_customer_id(struct i2c_client *client, u8 *pnum)
+{
+ return ft5402_read_reg(client, FT5402_REG_CUSTOMER_ID,
+ pnum);
+}
+
+static int ft5402_set_kx(struct i2c_client *client, u16 value)
+{
+ int err = 0;
+ err = ft5402_write_reg(client, FT5402_REG_KX_H,
+ value >> 8);
+ if (err < 0)
+ dev_err(&client->dev, "%s:set kx high failed\n",
+ __func__);
+ err = ft5402_write_reg(client, FT5402_REG_KX_L,
+ value);
+ if (err < 0)
+ dev_err(&client->dev, "%s:set kx low failed\n",
+ __func__);
+
+ return err;
+}
+
+static int ft5402_get_kx(struct i2c_client *client, u16 *pvalue)
+{
+ int err = 0;
+ u8 tmp1, tmp2;
+ err = ft5402_read_reg(client, FT5402_REG_KX_H,
+ &tmp1);
+ if (err < 0)
+ dev_err(&client->dev, "%s:get kx high failed\n",
+ __func__);
+ err = ft5402_read_reg(client, FT5402_REG_KX_L,
+ &tmp2);
+ if (err < 0)
+ dev_err(&client->dev, "%s:get kx low failed\n",
+ __func__);
+
+ *pvalue = ((u16)tmp1<<8) + (u16)tmp2;
+ return err;
+}
+static int ft5402_set_ky(struct i2c_client *client, u16 value)
+{
+ int err = 0;
+ err = ft5402_write_reg(client, FT5402_REG_KY_H,
+ value >> 8);
+ if (err < 0)
+ dev_err(&client->dev, "%s:set ky high failed\n",
+ __func__);
+ err = ft5402_write_reg(client, FT5402_REG_KY_L,
+ value);
+ if (err < 0)
+ dev_err(&client->dev, "%s:set ky low failed\n",
+ __func__);
+
+ return err;
+}
+
+static int ft5402_get_ky(struct i2c_client *client, u16 *pvalue)
+{
+ int err = 0;
+ u8 tmp1, tmp2;
+ err = ft5402_read_reg(client, FT5402_REG_KY_H,
+ &tmp1);
+ if (err < 0)
+ dev_err(&client->dev, "%s:get ky high failed\n",
+ __func__);
+ err = ft5402_read_reg(client, FT5402_REG_KY_L,
+ &tmp2);
+ if (err < 0)
+ dev_err(&client->dev, "%s:get ky low failed\n",
+ __func__);
+
+ *pvalue = ((u16)tmp1<<8) + (u16)tmp2;
+ return err;
+}
+static int ft5402_set_lemda_x(struct i2c_client *client, u8 value)
+{
+ return ft5402_write_reg(client, FT5402_REG_LEMDA_X,
+ value);
+}
+
+static int ft5402_get_lemda_x(struct i2c_client *client, u8 *pvalue)
+{
+ return ft5402_read_reg(client, FT5402_REG_LEMDA_X,
+ pvalue);
+}
+static int ft5402_set_lemda_y(struct i2c_client *client, u8 value)
+{
+ return ft5402_write_reg(client, FT5402_REG_LEMDA_Y,
+ value);
+}
+
+static int ft5402_get_lemda_y(struct i2c_client *client, u8 *pvalue)
+{
+ return ft5402_read_reg(client, FT5402_REG_LEMDA_Y,
+ pvalue);
+}
+static int ft5402_set_pos_x(struct i2c_client *client, u8 value)
+{
+ return ft5402_write_reg(client, FT5402_REG_DIRECTION,
+ value);
+}
+
+static int ft5402_get_pos_x(struct i2c_client *client, u8 *pvalue)
+{
+ return ft5402_read_reg(client, FT5402_REG_DIRECTION,
+ pvalue);
+}
+
+static int ft5402_set_scan_select(struct i2c_client *client, u8 value)
+{
+ return ft5402_write_reg(client, FT5402_REG_SCAN_SELECT,
+ value);
+}
+
+static int ft5402_get_scan_select(struct i2c_client *client, u8 *pvalue)
+{
+ return ft5402_read_reg(client, FT5402_REG_SCAN_SELECT,
+ pvalue);
+}
+
+static int ft5402_set_other_param(struct i2c_client *client)
+{
+ int err = 0;
+ err = ft5402_write_reg(client, FT5402_REG_THGROUP, (u8)(g_param_ft5402.ft5402_THGROUP));
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write THGROUP failed.\n", __func__);
+ return err;
+ }
+ err = ft5402_write_reg(client, FT5402_REG_THPEAK, g_param_ft5402.ft5402_THPEAK);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write THPEAK failed.\n",
+ __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_PWMODE_CTRL,
+ g_param_ft5402.ft5402_PWMODE_CTRL);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write PERIOD_CTRL failed.\n", __func__);
+ return err;
+ }
+ err = ft5402_write_reg(client, FT5402_REG_PERIOD_ACTIVE,
+ g_param_ft5402.ft5402_PERIOD_ACTIVE);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write PERIOD_ACTIVE failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FACE_DETECT_STATISTICS_TX_NUM,
+ g_param_ft5402.ft5402_FACE_DETECT_STATISTICS_TX_NUM);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FACE_DETECT_STATISTICS_TX_NUM failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_MAX_TOUCH_VALUE_HIGH,
+ g_param_ft5402.ft5402_MAX_TOUCH_VALUE>>8);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write MAX_TOUCH_VALUE_HIGH failed.\n", __func__);
+ return err;
+ }
+ err = ft5402_write_reg(client, FT5402_REG_MAX_TOUCH_VALUE_LOW,
+ g_param_ft5402.ft5402_MAX_TOUCH_VALUE);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write MAX_TOUCH_VALUE_LOW failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FACE_DETECT_MODE,
+ g_param_ft5402.ft5402_FACE_DETECT_MODE);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FACE_DETECT_MODE failed.\n", __func__);
+ return err;
+ }
+ err = ft5402_write_reg(client, FT5402_REG_DRAW_LINE_TH,
+ g_param_ft5402.ft5402_DRAW_LINE_TH);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write DRAW_LINE_TH failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_POINTS_SUPPORTED,
+ g_param_ft5402.ft5402_POINTS_SUPPORTED);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write POINTS_SUPPORTED failed.\n", __func__);
+ return err;
+ }
+ err = ft5402_write_reg(client, FT5402_REG_ESD_FILTER_FRAME,
+ g_param_ft5402.ft5402_ESD_FILTER_FRAME);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_ESD_FILTER_FRAME failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_POINTS_STABLE_MACRO,
+ g_param_ft5402.ft5402_POINTS_STABLE_MACRO);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_POINTS_STABLE_MACRO failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_MIN_DELTA_X,
+ g_param_ft5402.ft5402_MIN_DELTA_X);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_MIN_DELTA_X failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_MIN_DELTA_Y,
+ g_param_ft5402.ft5402_MIN_DELTA_Y);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_MIN_DELTA_Y failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_MIN_DELTA_STEP,
+ g_param_ft5402.ft5402_MIN_DELTA_STEP);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_MIN_DELTA_STEP failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_ESD_NOISE_MACRO,
+ g_param_ft5402.ft5402_ESD_NOISE_MACRO);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_ESD_NOISE_MACRO failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_ESD_DIFF_VAL,
+ g_param_ft5402.ft5402_ESD_DIFF_VAL);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_ESD_DIFF_VAL failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_ESD_NEGTIVE,
+ g_param_ft5402.ft5402_ESD_NEGTIVE);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_ESD_NEGTIVE failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_ESD_FILTER_FRAMES,
+ g_param_ft5402.ft5402_ESD_FILTER_FRAMES);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_ESD_FILTER_FRAMES failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_IO_LEVEL_SELECT,
+ g_param_ft5402.ft5402_IO_LEVEL_SELECT);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_IO_LEVEL_SELECT failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_POINTID_DELAY_COUNT,
+ g_param_ft5402.ft5402_POINTID_DELAY_COUNT);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_POINTID_DELAY_COUNT failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_LIFTUP_FILTER_MACRO,
+ g_param_ft5402.ft5402_LIFTUP_FILTER_MACRO);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_LIFTUP_FILTER_MACRO failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_DIFF_HANDLE_MACRO,
+ g_param_ft5402.ft5402_DIFF_HANDLE_MACRO);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_DIFF_HANDLE_MACRO failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_MIN_WATER,
+ g_param_ft5402.ft5402_MIN_WATER);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_MIN_WATER failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_MAX_NOISE,
+ g_param_ft5402.ft5402_MAX_NOISE);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_MAX_NOISE failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_WATER_START_RX,
+ g_param_ft5402.ft5402_WATER_START_RX);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_WATER_START_RX failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_WATER_START_TX,
+ g_param_ft5402.ft5402_WATER_START_TX);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_WATER_START_TX failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_HOST_NUMBER_SUPPORTED_MACRO,
+ g_param_ft5402.ft5402_HOST_NUMBER_SUPPORTED_MACRO);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_HOST_NUMBER_SUPPORTED_MACRO failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_RAISE_THGROUP,
+ g_param_ft5402.ft5402_RAISE_THGROUP);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_RAISE_THGROUP failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_CHARGER_STATE,
+ g_param_ft5402.ft5402_CHARGER_STATE);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_CHARGER_STATE failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_FILTERID_START,
+ g_param_ft5402.ft5402_FILTERID_START);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_FILTERID_START failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_FRAME_FILTER_EN_MACRO,
+ g_param_ft5402.ft5402_FRAME_FILTER_EN_MACRO);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_FRAME_FILTER_EN_MACRO failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_FRAME_FILTER_SUB_MAX_TH,
+ g_param_ft5402.ft5402_FRAME_FILTER_SUB_MAX_TH);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_FRAME_FILTER_SUB_MAX_TH failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_FRAME_FILTER_ADD_MAX_TH,
+ g_param_ft5402.ft5402_FRAME_FILTER_ADD_MAX_TH);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_FRAME_FILTER_ADD_MAX_TH failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_FRAME_FILTER_SKIP_START_FRAME,
+ g_param_ft5402.ft5402_FRAME_FILTER_SKIP_START_FRAME);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_FRAME_FILTER_SKIP_START_FRAME failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_FRAME_FILTER_BAND_EN,
+ g_param_ft5402.ft5402_FRAME_FILTER_BAND_EN);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_FRAME_FILTER_BAND_EN failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_FRAME_FILTER_BAND_WIDTH,
+ g_param_ft5402.ft5402_FRAME_FILTER_BAND_WIDTH);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_FRAME_FILTER_BAND_WIDTH failed.\n", __func__);
+ return err;
+ }
+
+ return err;
+}
+
+static int ft5402_get_other_param(struct i2c_client *client)
+{
+ int err = 0;
+ u8 value = 0x00;
+ err = ft5402_read_reg(client, FT5402_REG_THGROUP, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write THGROUP failed.\n", __func__);
+ return err;
+ } else
+ DBG("THGROUP=%02x\n", value);
+ err = ft5402_read_reg(client, FT5402_REG_THPEAK, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write THPEAK failed.\n",
+ __func__);
+ return err;
+ } else
+ DBG("THPEAK=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_PWMODE_CTRL, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write PWMODE_CTRL failed.\n", __func__);
+ return err;
+ } else
+ DBG("CTRL=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_PERIOD_ACTIVE,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write PERIOD_ACTIVE failed.\n", __func__);
+ return err;
+ } else
+ DBG("PERIOD_ACTIVE=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_MAX_TOUCH_VALUE_HIGH,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write MAX_TOUCH_VALUE_HIGH failed.\n", __func__);
+ return err;
+ } else
+ DBG("MAX_TOUCH_VALUE_HIGH=%02x\n", value);
+ err = ft5402_read_reg(client, FT5402_REG_MAX_TOUCH_VALUE_LOW,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write MAX_TOUCH_VALUE_LOW failed.\n", __func__);
+ return err;
+ } else
+ DBG("MAX_TOUCH_VALUE_LOW=%02x\n", value);
+ err = ft5402_read_reg(client, FT5402_REG_FACE_DETECT_MODE,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FACE_DETECT_MODE failed.\n", __func__);
+ return err;
+ } else
+ DBG("FACE_DEC_MODE=%02x\n", value);
+ err = ft5402_read_reg(client, FT5402_REG_DRAW_LINE_TH,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write DRAW_LINE_TH failed.\n", __func__);
+ return err;
+ } else
+ DBG("DRAW_LINE_TH=%02x\n", value);
+ err = ft5402_read_reg(client, FT5402_REG_POINTS_SUPPORTED,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_POINTS_SUPPORTED failed.\n", __func__);
+ return err;
+ } else
+ DBG("ft5402_POINTS_SUPPORTED=%02x\n", value);
+ err = ft5402_read_reg(client, FT5402_REG_ESD_FILTER_FRAME,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_ESD_FILTER_FRAME failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_ESD_FILTER_FRAME=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_POINTS_STABLE_MACRO,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_POINTS_STABLE_MACRO failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_POINTS_STABLE_MACRO=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_MIN_DELTA_X,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_MIN_DELTA_X failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_MIN_DELTA_X=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_MIN_DELTA_Y,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_MIN_DELTA_Y failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_MIN_DELTA_Y=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_MIN_DELTA_STEP,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_MIN_DELTA_STEP failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_MIN_DELTA_STEP=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_ESD_NOISE_MACRO,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_ESD_NOISE_MACRO failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_ESD_NOISE_MACRO=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_ESD_DIFF_VAL,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_ESD_DIFF_VAL failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_ESD_DIFF_VAL=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_ESD_NEGTIVE,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_ESD_NEGTIVE failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_ESD_NEGTIVE=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_ESD_FILTER_FRAMES,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_ESD_FILTER_FRAMES failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_ESD_FILTER_FRAMES=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_IO_LEVEL_SELECT,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_IO_LEVEL_SELECT failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_IO_LEVEL_SELECT=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_POINTID_DELAY_COUNT,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_POINTID_DELAY_COUNT failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_POINTID_DELAY_COUNT=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_LIFTUP_FILTER_MACRO,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_LIFTUP_FILTER_MACRO failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_LIFTUP_FILTER_MACRO=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_DIFF_HANDLE_MACRO,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_DIFF_HANDLE_MACRO failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_DIFF_HANDLE_MACRO=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_MIN_WATER,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_MIN_WATER failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_MIN_WATER=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_MAX_NOISE,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_MAX_NOISE failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_MAX_NOISE=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_WATER_START_RX,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_WATER_START_RX failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_WATER_START_RX=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_WATER_START_TX,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_WATER_START_TX failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_WATER_START_TX=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_HOST_NUMBER_SUPPORTED_MACRO,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_HOST_NUMBER_SUPPORTED_MACRO failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_HOST_NUMBER_SUPPORTED_MACRO=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_RAISE_THGROUP,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_RAISE_THGROUP failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_RAISE_THGROUP=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_CHARGER_STATE,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_CHARGER_STATE failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_CHARGER_STATE=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_FILTERID_START,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_FILTERID_START failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_FILTERID_START=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_FRAME_FILTER_EN_MACRO,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_FRAME_FILTER_EN_MACRO failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_FRAME_FILTER_EN_MACRO=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_FRAME_FILTER_SUB_MAX_TH,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_FRAME_FILTER_SUB_MAX_TH failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_FRAME_FILTER_SUB_MAX_TH=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_FRAME_FILTER_ADD_MAX_TH,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_FRAME_FILTER_ADD_MAX_TH failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_FRAME_FILTER_ADD_MAX_TH=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_FRAME_FILTER_SKIP_START_FRAME,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_FRAME_FILTER_SKIP_START_FRAME failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_FRAME_FILTER_SKIP_START_FRAME=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_FRAME_FILTER_BAND_EN,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_FRAME_FILTER_BAND_EN failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_FRAME_FILTER_BAND_EN=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_FRAME_FILTER_BAND_WIDTH,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_FRAME_FILTER_BAND_WIDTH failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_FRAME_FILTER_BAND_WIDTH=%02x\n", value);
+
+ return err;
+}
+int ft5402_get_ic_param(struct i2c_client *client)
+{
+ int err = 0;
+ int i = 0;
+ u8 value = 0x00;
+ u16 xvalue = 0x0000, yvalue = 0x0000;
+
+ /*enter factory mode*/
+ err = ft5402_write_reg(client, FT5402_REG_DEVICE_MODE, FT5402_FACTORYMODE_VALUE);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:enter factory mode failed.\n", __func__);
+ goto RETURN_WORK;
+ }
+
+ for (i = 0; i < g_ft5402_tx_num; i++) {
+ DBG("tx%d:", i);
+ /*get tx order*/
+ err = ft5402_get_tx_order(client, i, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get tx%d order.\n",
+ __func__, i);
+ goto RETURN_WORK;
+ }
+ DBG("order=%d ", value);
+ /*get tx cap*/
+ err = ft5402_get_tx_cap(client, i, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get tx%d cap.\n",
+ __func__, i);
+ goto RETURN_WORK;
+ }
+ DBG("cap=%02x\n", value);
+ }
+ /*get tx offset*/
+ err = ft5402_get_tx_offset(client, 0, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get tx 0 offset.\n",
+ __func__);
+ goto RETURN_WORK;
+ } else
+ DBG("tx offset = %02x\n", value);
+
+ /*get rx offset and cap*/
+ for (i = 0; i < g_ft5402_rx_num; i++) {
+ /*get rx order*/
+ DBG("rx%d:", i);
+ err = ft5402_get_rx_order(client, i, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get rx%d order.\n",
+ __func__, i);
+ goto RETURN_WORK;
+ }
+ DBG("order=%d ", value);
+ /*get rx cap*/
+ err = ft5402_get_rx_cap(client, i, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get rx%d cap.\n",
+ __func__, i);
+ goto RETURN_WORK;
+ }
+ DBG("cap=%02x ", value);
+ err = ft5402_get_rx_offset(client, i, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get rx offset.\n",
+ __func__);
+ goto RETURN_WORK;
+ }
+ DBG("offset=%02x\n", value);
+ }
+
+ /*get scan select*/
+ err = ft5402_get_scan_select(client, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get scan select.\n",
+ __func__);
+ goto RETURN_WORK;
+ } else
+ DBG("scan select = %02x\n", value);
+
+ /*get tx number*/
+ err = ft5402_get_tx_num(client, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get tx num.\n",
+ __func__);
+ goto RETURN_WORK;
+ } else
+ DBG("tx num = %02x\n", value);
+ /*get rx number*/
+ err = ft5402_get_rx_num(client, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get rx num.\n",
+ __func__);
+ goto RETURN_WORK;
+ } else
+ DBG("rx num = %02x\n", value);
+
+ /*get gain*/
+ err = ft5402_get_gain(client, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get gain.\n",
+ __func__);
+ goto RETURN_WORK;
+ } else
+ DBG("gain = %02x\n", value);
+ /*get voltage*/
+ err = ft5402_get_vol(client, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get voltage.\n",
+ __func__);
+ goto RETURN_WORK;
+ } else
+ DBG("voltage = %02x\n", value);
+ /*get start rx*/
+ err = ft5402_get_start_rx(client, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get start rx.\n",
+ __func__);
+ goto RETURN_WORK;
+ } else
+ DBG("start rx = %02x\n", value);
+ /*get adc target*/
+ err = ft5402_get_adc_target(client, &xvalue);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get adc target.\n",
+ __func__);
+ goto ERR_EXIT;
+ } else
+ DBG("ADC target = %02x\n", xvalue);
+
+
+RETURN_WORK:
+ /*enter work mode*/
+ err = ft5402_write_reg(client, FT5402_REG_DEVICE_MODE, FT5402_WORKMODE_VALUE);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:enter work mode failed.\n", __func__);
+ goto ERR_EXIT;
+ }
+
+ /*get resolution*/
+ err = ft5402_get_Resolution(client, &xvalue, &yvalue);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get resolution.\n",
+ __func__);
+ goto ERR_EXIT;
+ } else
+ DBG("resolution X = %d Y = %d\n", xvalue, yvalue);
+
+
+ /*get face detect statistics tx num*/
+ err = ft5402_get_face_detect_statistics_tx_num(client,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev,
+ "%s:could not get face detect statistics tx num.\n",
+ __func__);
+ goto ERR_EXIT;
+ } else
+ DBG("FT5402_FACE_DETECT_STATISTICS_TX_NUM = %02x\n", value);
+ /*get face detect pre value*/
+ err = ft5402_get_face_detect_pre_value(client,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev,
+ "%s:could not get face detect pre value.\n",
+ __func__);
+ goto ERR_EXIT;
+ } else
+ DBG("FT5402_FACE_DETECT_PRE_VALUE = %02x\n", value);
+ /*get face detect num*/
+ err = ft5402_get_face_detect_num(client, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get face detect num.\n",
+ __func__);
+ goto ERR_EXIT;
+ } else
+ DBG("face detect num = %02x\n", value);
+
+ /*get min peak value*/
+ err = ft5402_get_peak_value_min(client,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get min peak value.\n",
+ __func__);
+ goto ERR_EXIT;
+ } else
+ DBG("FT5402_BIGAREA_PEAK_VALUE_MIN = %02x\n", value);
+ /*get diff value over num*/
+ err = ft5402_get_diff_value_over_num(client,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get diff value over num.\n",
+ __func__);
+ goto ERR_EXIT;
+ } else
+ DBG("FT5402_BIGAREA_DIFF_VALUE_OVER_NUM = %02x\n", value);
+ /*get customer id*/
+ err = ft5402_get_customer_id(client,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get customer id.\n",
+ __func__);
+ goto ERR_EXIT;
+ } else
+ DBG("FT5402_CUSTOMER_ID = %02x\n", value);
+ /*get kx*/
+ err = ft5402_get_kx(client, &xvalue);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get kx.\n",
+ __func__);
+ goto ERR_EXIT;
+ } else
+ DBG("kx = %02x\n", xvalue);
+ /*get ky*/
+ err = ft5402_get_ky(client, &xvalue);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get ky.\n",
+ __func__);
+ goto ERR_EXIT;
+ } else
+ DBG("ky = %02x\n", xvalue);
+ /*get lemda x*/
+ err = ft5402_get_lemda_x(client,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get lemda x.\n",
+ __func__);
+ goto ERR_EXIT;
+ } else
+ DBG("lemda x = %02x\n", value);
+ /*get lemda y*/
+ err = ft5402_get_lemda_y(client,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get lemda y.\n",
+ __func__);
+ goto ERR_EXIT;
+ } else
+ DBG("lemda y = %02x\n", value);
+ /*get pos x*/
+ err = ft5402_get_pos_x(client, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get pos x.\n",
+ __func__);
+ goto ERR_EXIT;
+ } else
+ DBG("pos x = %02x\n", value);
+
+ err = ft5402_get_other_param(client);
+
+ERR_EXIT:
+ return err;
+}
+
+int ft5402_Init_IC_Param(struct i2c_client *client)
+{
+ int err = 0;
+ int i = 0;
+
+ /*enter factory mode*/
+ err = ft5402_write_reg(client, FT5402_REG_DEVICE_MODE, FT5402_FACTORYMODE_VALUE);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:enter factory mode failed.\n", __func__);
+ goto RETURN_WORK;
+ }
+
+ for (i = 0; i < g_ft5402_tx_num; i++) {
+ if (g_ft5402_tx_order[i] != 0xFF) {
+ /*set tx order*/
+ err = ft5402_set_tx_order(client, i, g_ft5402_tx_order[i]);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set tx%d order.\n",
+ __func__, i);
+ goto RETURN_WORK;
+ }
+ }
+ /*set tx cap*/
+ err = ft5402_set_tx_cap(client, i, g_ft5402_tx_cap[i]);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set tx%d cap.\n",
+ __func__, i);
+ goto RETURN_WORK;
+ }
+ }
+ /*set tx offset*/
+ err = ft5402_set_tx_offset(client, 0, g_ft5402_tx_offset);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set tx 0 offset.\n",
+ __func__);
+ goto RETURN_WORK;
+ }
+
+ /*set rx offset and cap*/
+ for (i = 0; i < g_ft5402_rx_num; i++) {
+ /*set rx order*/
+ err = ft5402_set_rx_order(client, i, g_ft5402_rx_order[i]);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set rx%d order.\n",
+ __func__, i);
+ goto RETURN_WORK;
+ }
+ /*set rx cap*/
+ err = ft5402_set_rx_cap(client, i, g_ft5402_rx_cap[i]);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set rx%d cap.\n",
+ __func__, i);
+ goto RETURN_WORK;
+ }
+ }
+ for (i = 0; i < g_ft5402_rx_num/2; i++) {
+ err = ft5402_set_rx_offset(client, i*2, g_ft5402_rx_offset[i]>>4);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set rx offset.\n",
+ __func__);
+ goto RETURN_WORK;
+ }
+ err = ft5402_set_rx_offset(client, i*2+1, g_ft5402_rx_offset[i]&0x0F);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set rx offset.\n",
+ __func__);
+ goto RETURN_WORK;
+ }
+ }
+
+ /*set scan select*/
+ err = ft5402_set_scan_select(client, g_ft5402_scanselect);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set scan select.\n",
+ __func__);
+ goto RETURN_WORK;
+ }
+
+ /*set tx number*/
+ err = ft5402_set_tx_num(client, g_ft5402_tx_num);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set tx num.\n",
+ __func__);
+ goto RETURN_WORK;
+ }
+ /*set rx number*/
+ err = ft5402_set_rx_num(client, g_ft5402_rx_num);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set rx num.\n",
+ __func__);
+ goto RETURN_WORK;
+ }
+
+ /*set gain*/
+ err = ft5402_set_gain(client, g_ft5402_gain);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set gain.\n",
+ __func__);
+ goto RETURN_WORK;
+ }
+ /*set voltage*/
+ err = ft5402_set_vol(client, g_ft5402_voltage);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set voltage.\n",
+ __func__);
+ goto RETURN_WORK;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_ADC_TARGET_HIGH,
+ g_param_ft5402.ft5402_ADC_TARGET>>8);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ADC_TARGET_HIGH failed.\n", __func__);
+ return err;
+ }
+ err = ft5402_write_reg(client, FT5402_REG_ADC_TARGET_LOW,
+ g_param_ft5402.ft5402_ADC_TARGET);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ADC_TARGET_LOW failed.\n", __func__);
+ return err;
+ }
+
+RETURN_WORK:
+ /*enter work mode*/
+ err = ft5402_write_reg(client, FT5402_REG_DEVICE_MODE, FT5402_WORKMODE_VALUE);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:enter work mode failed.\n", __func__);
+ goto ERR_EXIT;
+ }
+
+ /*set resolution*/
+ err = ft5402_set_Resolution(client, g_param_ft5402.ft5402_RESOLUTION_X,
+ g_param_ft5402.ft5402_RESOLUTION_Y);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set resolution.\n",
+ __func__);
+ goto ERR_EXIT;
+ }
+
+ /*set face detect statistics tx num*/
+ err = ft5402_set_face_detect_statistics_tx_num(client,
+ g_param_ft5402.ft5402_FACE_DETECT_STATISTICS_TX_NUM);
+ if (err < 0) {
+ dev_err(&client->dev,
+ "%s:could not set face detect statistics tx num.\n",
+ __func__);
+ goto ERR_EXIT;
+ }
+ /*set face detect pre value*/
+ err = ft5402_set_face_detect_pre_value(client,
+ g_param_ft5402.ft5402_FACE_DETECT_PRE_VALUE);
+ if (err < 0) {
+ dev_err(&client->dev,
+ "%s:could not set face detect pre value.\n",
+ __func__);
+ goto ERR_EXIT;
+ }
+ /*set face detect num*/
+ err = ft5402_set_face_detect_num(client,
+ g_param_ft5402.ft5402_FACE_DETECT_NUM);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set face detect num.\n",
+ __func__);
+ goto ERR_EXIT;
+ }
+
+ /*set min peak value*/
+ err = ft5402_set_peak_value_min(client,
+ g_param_ft5402.ft5402_BIGAREA_PEAK_VALUE_MIN);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set min peak value.\n",
+ __func__);
+ goto ERR_EXIT;
+ }
+ /*set diff value over num*/
+ err = ft5402_set_diff_value_over_num(client,
+ g_param_ft5402.ft5402_BIGAREA_DIFF_VALUE_OVER_NUM);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set diff value over num.\n",
+ __func__);
+ goto ERR_EXIT;
+ }
+ /*set customer id*/
+ err = ft5402_set_customer_id(client,
+ g_param_ft5402.ft5402_CUSTOMER_ID);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set customer id.\n",
+ __func__);
+ goto ERR_EXIT;
+ }
+ /*set kx*/
+ err = ft5402_set_kx(client, g_param_ft5402.ft5402_KX);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set kx.\n",
+ __func__);
+ goto ERR_EXIT;
+ }
+ /*set ky*/
+ err = ft5402_set_ky(client, g_param_ft5402.ft5402_KY);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set ky.\n",
+ __func__);
+ goto ERR_EXIT;
+ }
+ /*set lemda x*/
+ err = ft5402_set_lemda_x(client,
+ g_param_ft5402.ft5402_LEMDA_X);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set lemda x.\n",
+ __func__);
+ goto ERR_EXIT;
+ }
+ /*set lemda y*/
+ err = ft5402_set_lemda_y(client,
+ g_param_ft5402.ft5402_LEMDA_Y);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set lemda y.\n",
+ __func__);
+ goto ERR_EXIT;
+ }
+ /*set pos x*/
+ err = ft5402_set_pos_x(client, g_param_ft5402.ft5402_DIRECTION);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set pos x.\n",
+ __func__);
+ goto ERR_EXIT;
+ }
+
+ err = ft5402_set_other_param(client);
+
+ERR_EXIT:
+ return err;
+}
+
+
+char dst[512];
+static char * ft5402_sub_str(char * src, int n)
+{
+ char *p = src;
+ int i;
+ int m = 0;
+ int len = strlen(src);
+
+ while (n >= 1 && m <= len) {
+ i = 0;
+ dst[10] = ' ';
+ n--;
+ while ( *p != ',' && *p != ' ') {
+ dst[i++] = *(p++);
+ m++;
+ if (i >= len)
+ break;
+ }
+ dst[i++] = '\0';
+ p++;
+ }
+ return dst;
+}
+static int ft5402_GetInISize(char *config_name)
+{
+ struct file *pfile = NULL;
+ struct inode *inode;
+ unsigned long magic;
+ off_t fsize = 0;
+ char filepath[128];
+ memset(filepath, 0, sizeof(filepath));
+
+ sprintf(filepath, "%s%s", FT5402_INI_FILEPATH, config_name);
+
+ if (NULL == pfile)
+ pfile = filp_open(filepath, O_RDONLY, 0);
+
+ if (IS_ERR(pfile)) {
+ pr_err("error occured while opening file %s.\n", filepath);
+ return -EIO;
+ }
+
+ inode = pfile->f_dentry->d_inode;
+ magic = inode->i_sb->s_magic;
+ fsize = inode->i_size;
+ filp_close(pfile, NULL);
+ return fsize;
+}
+
+static int ft5x0x_ReadInIData(char *config_name,
+ char *config_buf)
+{
+ struct file *pfile = NULL;
+ struct inode *inode;
+ unsigned long magic;
+ off_t fsize;
+ char filepath[128];
+ loff_t pos;
+ mm_segment_t old_fs;
+
+ memset(filepath, 0, sizeof(filepath));
+ sprintf(filepath, "%s%s", FT5402_INI_FILEPATH, config_name);
+ if (NULL == pfile)
+ pfile = filp_open(filepath, O_RDONLY, 0);
+ if (IS_ERR(pfile)) {
+ pr_err("error occured while opening file %s.\n", filepath);
+ return -EIO;
+ }
+
+ inode = pfile->f_dentry->d_inode;
+ magic = inode->i_sb->s_magic;
+ fsize = inode->i_size;
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ pos = 0;
+ vfs_read(pfile, config_buf, fsize, &pos);
+ filp_close(pfile, NULL);
+ set_fs(old_fs);
+
+ return 0;
+}
+
+int ft5402_Get_Param_From_Ini(char *config_name)
+{
+ char key[64];
+ char value[512];
+ char section[64];
+ int i = 0;//,ret=0;
+ int j = 0;
+ char *filedata = NULL;
+ unsigned char legal_byte1 = 0x00;
+ unsigned char legal_byte2 = 0x00;
+
+ int inisize = ft5402_GetInISize(config_name);
+
+ if (inisize <= 0) {
+ pr_err("%s ERROR:Get firmware size failed\n",
+ __func__);
+ return -EIO;
+ }
+
+ filedata = kmalloc(inisize + 1, GFP_ATOMIC);
+
+ if (ft5x0x_ReadInIData(config_name, filedata)) {
+ pr_err("%s() - ERROR: request_firmware failed\n",
+ __func__);
+ kfree(filedata);
+ return -EIO;
+ }
+
+ /*check ini if it is illegal*/
+ sprintf(section, "%s", FT5402_APP_LEGAL);
+ sprintf(key, "%s", FT5402_APP_LEGAL_BYTE_1_STR);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ legal_byte1 = atoi(value);
+ DBG("legal_byte1=%s\n", value);
+ sprintf(key, "%s", FT5402_APP_LEGAL_BYTE_2_STR);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ legal_byte2 = atoi(value);
+ DBG("lega2_byte1=%s\n", value);
+ if(FT5402_APP_LEGAL_BYTE_1_VALUE == legal_byte1 &&
+ FT5402_APP_LEGAL_BYTE_2_VALUE == legal_byte2)
+ DBG("the ini file is valid\n");
+ else {
+ pr_err("[FTS]-----the ini file is invalid!please check it.\n");
+ goto ERROR_RETURN;
+ }
+
+ /*get ini param*/
+ sprintf(section, "%s", FT5402_APP_NAME);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_KX = atoi(value);
+ DBG("ft5402_KX=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_KY = atoi(value);
+ DBG("ft5402_KY=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_LEMDA_X = atoi(value);
+ DBG("ft5402_LEMDA_X=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_LEMDA_Y = atoi(value);
+ DBG("ft5402_LEMDA_Y=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_RESOLUTION_X = atoi(value);
+ DBG("ft5402_RESOLUTION_X=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_RESOLUTION_Y = atoi(value);
+ DBG("ft5402_RESOLUTION_Y=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_DIRECTION= atoi(value);
+ DBG("ft5402_DIRECTION=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_FACE_DETECT_PRE_VALUE = atoi(value);
+ DBG("ft5402_FACE_DETECT_PRE_VALUE=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_FACE_DETECT_NUM = atoi(value);
+ DBG("ft5402_FACE_DETECT_NUM=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_BIGAREA_PEAK_VALUE_MIN = atoi(value);/*The min value to be decided as the big point*/
+ DBG("ft5402_BIGAREA_PEAK_VALUE_MIN=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_BIGAREA_DIFF_VALUE_OVER_NUM = atoi(value);/*The min big points of the big area*/
+ DBG("ft5402_BIGAREA_DIFF_VALUE_OVER_NUM=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_CUSTOMER_ID = atoi(value);
+ DBG("ft5402_CUSTOM_ID=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_PERIOD_ACTIVE = atoi(value);
+ DBG("ft5402_PERIOD_ACTIVE=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_FACE_DETECT_STATISTICS_TX_NUM = atoi(value);
+ DBG("ft5402_FACE_DETECT_STATISTICS_TX_NUM=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_THGROUP = atoi(value);
+ DBG("ft5402_THGROUP=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_THPEAK = atoi(value);
+ DBG("ft5402_THPEAK=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_FACE_DETECT_MODE = atoi(value);
+ DBG("ft5402_FACE_DETECT_MODE=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_MAX_TOUCH_VALUE = atoi(value);
+ DBG("ft5402_MAX_TOUCH_VALUE=%s\n", value);
+
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_PWMODE_CTRL= atoi(value);
+ DBG("ft5402_PWMODE_CTRL=%s\n", value);
+
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+
+ i++;
+ g_param_ft5402.ft5402_DRAW_LINE_TH = atoi(value);
+ DBG("ft5402_DRAW_LINE_TH=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_POINTS_SUPPORTED= atoi(value);
+ DBG("ft5402_POINTS_SUPPORTED=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_START_RX = atoi(value);
+ DBG("ft5402_START_RX=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+
+ g_param_ft5402.ft5402_ADC_TARGET = atoi(value);
+ DBG("ft5402_ADC_TARGET=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+
+ g_param_ft5402.ft5402_ESD_FILTER_FRAME = atoi(value);
+ DBG("ft5402_ESD_FILTER_FRAME=%s\n", value);
+
+/*********************************************************************/
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_ft5402_tx_num = atoi(value);
+ DBG("ft5402_tx_num=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_ft5402_rx_num = atoi(value);
+ DBG("ft5402_rx_num=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_ft5402_gain = atoi(value);
+ DBG("ft5402_gain=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_ft5402_voltage = atoi(value);
+ DBG("ft5402_voltage=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_ft5402_scanselect = atoi(value);
+ DBG("ft5402_scanselect=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ for(j = 0; j < g_ft5402_tx_num; j++)
+ {
+ char * psrc = value;
+ g_ft5402_tx_order[j] = atoi(ft5402_sub_str(psrc, j+1));
+ }
+ DBG("ft5402_tx_order=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_ft5402_tx_offset = atoi(value);
+ DBG("ft5402_tx_offset=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ for(j = 0; j < g_ft5402_tx_num; j++)
+ {
+ char * psrc = value;
+ g_ft5402_tx_cap[j] = atoi(ft5402_sub_str(psrc, j+1));
+ }
+ DBG("ft5402_tx_cap=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ for(j = 0; j < g_ft5402_rx_num; j++)
+ {
+ char * psrc = value;
+ g_ft5402_rx_order[j] = atoi(ft5402_sub_str(psrc, j+1));
+ }
+ DBG("ft5402_rx_order=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ for(j = 0; j < g_ft5402_rx_num/2; j++)
+ {
+ char * psrc = value;
+ g_ft5402_rx_offset[j] = atoi(ft5402_sub_str(psrc, j+1));
+ }
+ DBG("ft5402_rx_offset=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ for(j = 0; j < g_ft5402_rx_num; j++)
+ {
+ char * psrc = value;
+ g_ft5402_rx_cap[j] = atoi(ft5402_sub_str(psrc, j+1));
+ }
+ DBG("ft5402_rx_cap=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_POINTS_STABLE_MACRO = atoi(value);
+ DBG("ft5402_POINTS_STABLE_MACRO=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_MIN_DELTA_X = atoi(value);
+ DBG("ft5402_MIN_DELTA_X=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_MIN_DELTA_Y = atoi(value);
+ DBG("ft5402_MIN_DELTA_Y=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_MIN_DELTA_STEP = atoi(value);
+ DBG("ft5402_MIN_DELTA_STEP=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_ESD_NOISE_MACRO = atoi(value);
+ DBG("ft5402_ESD_NOISE_MACRO=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_ESD_DIFF_VAL = atoi(value);
+ DBG("ft5402_ESD_DIFF_VAL=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_ESD_NEGTIVE = atoi(value);
+ DBG("ft5402_ESD_NEGTIVE=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_ESD_FILTER_FRAMES = atoi(value);
+ DBG("ft5402_ESD_FILTER_FRAMES=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_IO_LEVEL_SELECT = atoi(value);
+ DBG("ft5402_IO_LEVEL_SELECT=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_POINTID_DELAY_COUNT = atoi(value);
+ DBG("ft5402_POINTID_DELAY_COUNT=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_LIFTUP_FILTER_MACRO = atoi(value);
+ DBG("ft5402_LIFTUP_FILTER_MACRO=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_DIFF_HANDLE_MACRO = atoi(value);
+ DBG("ft5402_DIFF_HANDLE_MACRO=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_MIN_WATER = atoi(value);
+ DBG("ft5402_MIN_WATER=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_MAX_NOISE = atoi(value);
+ DBG("ft5402_MAX_NOISE=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_WATER_START_RX = atoi(value);
+ DBG("ft5402_WATER_START_RX=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_WATER_START_TX = atoi(value);
+ DBG("ft5402_WATER_START_TX=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_HOST_NUMBER_SUPPORTED_MACRO = atoi(value);
+ DBG("ft5402_HOST_NUMBER_SUPPORTED_MACRO=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_RAISE_THGROUP = atoi(value);
+ DBG("ft5402_RAISE_THGROUP=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_CHARGER_STATE = atoi(value);
+ DBG("ft5402_CHARGER_STATE=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_FILTERID_START = atoi(value);
+ DBG("ft5402_FILTERID_START=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_FRAME_FILTER_EN_MACRO = atoi(value);
+ DBG("ft5402_FRAME_FILTER_EN_MACRO=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_FRAME_FILTER_SUB_MAX_TH = atoi(value);
+ DBG("ft5402_FRAME_FILTER_SUB_MAX_TH=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_FRAME_FILTER_ADD_MAX_TH = atoi(value);
+ DBG("ft5402_FRAME_FILTER_ADD_MAX_TH=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_FRAME_FILTER_SKIP_START_FRAME = atoi(value);
+ DBG("ft5402_FRAME_FILTER_SKIP_START_FRAME=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_FRAME_FILTER_BAND_EN = atoi(value);
+ DBG("ft5402_FRAME_FILTER_BAND_EN=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_FRAME_FILTER_BAND_WIDTH = atoi(value);
+ DBG("ft5402_FRAME_FILTER_BAND_WIDTH=%s\n", value);
+
+
+ if (filedata)
+ kfree(filedata);
+ return 0;
+ERROR_RETURN:
+ if (filedata)
+ kfree(filedata);
+ return -1;
+}
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/ft5x0x/ft5402_config.h b/ANDROID_3.4.5/drivers/input/touchscreen/ft5x0x/ft5402_config.h
new file mode 100755
index 00000000..b0c63889
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/ft5x0x/ft5402_config.h
@@ -0,0 +1,71 @@
+#ifndef __FT5402_CONFIG_H__
+#define __FT5402_CONFIG_H__
+/*FT5402 config*/
+
+
+#define FT5402_START_RX 0
+#define FT5402_ADC_TARGET 8500
+#define FT5402_KX 120
+#define FT5402_KY 120
+#define FT5402_RESOLUTION_X 480
+#define FT5402_RESOLUTION_Y 800
+#define FT5402_LEMDA_X 0
+#define FT5402_LEMDA_Y 0
+#define FT5402_PWMODE_CTRL 1
+#define FT5402_POINTS_SUPPORTED 5
+#define FT5402_DRAW_LINE_TH 150
+#define FT5402_FACE_DETECT_MODE 0
+#define FT5402_FACE_DETECT_STATISTICS_TX_NUM 3
+#define FT5402_FACE_DETECT_PRE_VALUE 20
+#define FT5402_FACE_DETECT_NUM 10
+#define FT5402_THGROUP 25
+#define FT5402_THPEAK 60
+#define FT5402_BIGAREA_PEAK_VALUE_MIN 100
+#define FT5402_BIGAREA_DIFF_VALUE_OVER_NUM 50
+#define FT5402_MIN_DELTA_X 2
+#define FT5402_MIN_DELTA_Y 2
+#define FT5402_MIN_DELTA_STEP 2
+#define FT5402_ESD_DIFF_VAL 20
+#define FT5402_ESD_NEGTIVE -50
+#define FT5402_ESD_FILTER_FRAME 10
+#define FT5402_MAX_TOUCH_VALUE 600
+#define FT5402_CUSTOMER_ID 121
+#define FT5402_IO_LEVEL_SELECT 0
+#define FT5402_DIRECTION 1
+#define FT5402_POINTID_DELAY_COUNT 3
+#define FT5402_LIFTUP_FILTER_MACRO 1
+#define FT5402_POINTS_STABLE_MACRO 1
+#define FT5402_ESD_NOISE_MACRO 1
+#define FT5402_RV_G_PERIOD_ACTIVE 16
+#define FT5402_DIFFDATA_HANDLE 1
+#define FT5402_MIN_WATER_VAL -50
+#define FT5402_MAX_NOISE_VAL 10
+#define FT5402_WATER_HANDLE_START_RX 0
+#define FT5402_WATER_HANDLE_START_TX 0
+#define FT5402_HOST_NUMBER_SUPPORTED 1
+#define FT5402_RV_G_RAISE_THGROUP 30
+#define FT5402_RV_G_CHARGER_STATE 0
+#define FT5402_RV_G_FILTERID_START 2
+#define FT5402_FRAME_FILTER_EN 1
+#define FT5402_FRAME_FILTER_SUB_MAX_TH 2
+#define FT5402_FRAME_FILTER_ADD_MAX_TH 2
+#define FT5402_FRAME_FILTER_SKIP_START_FRAME 6
+#define FT5402_FRAME_FILTER_BAND_EN 1
+#define FT5402_FRAME_FILTER_BAND_WIDTH 128
+#define FT5402_OTP_PARAM_ID 0
+
+
+unsigned char g_ft5402_tx_num = 27;
+unsigned char g_ft5402_rx_num = 16;
+unsigned char g_ft5402_gain = 10;
+unsigned char g_ft5402_voltage = 3;
+unsigned char g_ft5402_scanselect = 12;
+unsigned char g_ft5402_tx_order[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26};
+unsigned char g_ft5402_tx_offset = 2;
+unsigned char g_ft5402_tx_cap[] = {42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42};
+unsigned char g_ft5402_rx_order[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+unsigned char g_ft5402_rx_offset[] = {68,68,68,68,68,68,68,68};
+unsigned char g_ft5402_rx_cap[] = {84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84};
+
+
+#endif \ No newline at end of file
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/ft5x0x/ft5402_ini_config.h b/ANDROID_3.4.5/drivers/input/touchscreen/ft5x0x/ft5402_ini_config.h
new file mode 100755
index 00000000..138f42e2
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/ft5x0x/ft5402_ini_config.h
@@ -0,0 +1,411 @@
+#ifndef __LINUX_FT5402_INI_CONFIG_H__
+#define __LINUX_FT5402_INI_CONFIG_H
+
+
+/*Init param register address*/
+/*factory mode register from 14-131*/
+#define FT5402_REG_TX_NUM 0x03
+#define FT5402_REG_RX_NUM 0x04
+#define FT5402_REG_VOLTAGE 0x05
+#define FT5402_REG_GAIN 0x07
+#define FT5402_REG_SCAN_SELECT 0x4E
+#define FT5402_REG_TX_ORDER_START 0x50
+#define FT5402_REG_TX_CAP_START 0x78
+#define FT5402_REG_TX_OFFSET_START 0xBF
+#define FT5402_REG_RX_ORDER_START 0xeb
+#define FT5402_REG_RX_CAP_START 0xA0
+#define FT5402_REG_RX_OFFSET_START 0xD3
+#define FT5402_REG_START_RX 0x06
+#define FT5402_REG_ADC_TARGET_HIGH 0x08
+#define FT5402_REG_ADC_TARGET_LOW 0x09
+
+
+#define FT5402_REG_DEVICE_MODE 0x00
+
+
+/*work mode register from 0-13(0,1,12,13verify or Reserved)and 132-177(159 Reserved)*/
+#define FT5402_REG_THGROUP (0x00+0x80)
+#define FT5402_REG_THPEAK (0x01+0x80)
+#define FT5402_REG_PWMODE_CTRL (0x06+0x80)
+#define FT5402_REG_PERIOD_ACTIVE (0x59+0x80)
+#define FT5402_REG_POINTS_SUPPORTED (0x0A+0x80)
+#define FT5402_REG_ESD_FILTER_FRAME (0x4F+0x80)
+
+#define FT5402_REG_RESOLUTION_X_H (0x18+0x80)
+#define FT5402_REG_RESOLUTION_X_L (0x19+0x80)
+#define FT5402_REG_RESOLUTION_Y_H (0x1a+0x80)
+#define FT5402_REG_RESOLUTION_Y_L (0x1b+0x80)
+#define FT5402_REG_KX_H (0x1c+0x80)
+#define FT5402_REG_KX_L (0x9d)
+#define FT5402_REG_KY_H (0x9e)
+#define FT5402_REG_KY_L (0x1f+0x80)
+#define FT5402_REG_CUSTOMER_ID (0xA8)
+#define FT5402_REG_DRAW_LINE_TH (0xAe)
+#define FT5402_REG_FACE_DETECT_MODE (0xB0)
+#define FT5402_REG_MAX_TOUCH_VALUE_HIGH (0xD0)
+#define FT5402_REG_MAX_TOUCH_VALUE_LOW (0xD1)
+
+#define FT5402_REG_DIRECTION (0x53+0x80)
+#define FT5402_REG_LEMDA_X (0x41+0x80)
+#define FT5402_REG_LEMDA_Y (0x42+0x80)
+#define FT5402_REG_FACE_DETECT_STATISTICS_TX_NUM (0x43+0x80)
+#define FT5402_REG_FACE_DETECT_PRE_VALUE (0x44+0x80)
+#define FT5402_REG_FACE_DETECT_NUM (0x45+0x80)
+#define FT5402_REG_BIGAREA_PEAK_VALUE_MIN (0x33+0x80)
+#define FT5402_REG_BIGAREA_DIFF_VALUE_OVER_NUM (0x34+0x80)
+
+/**************************************************************************/
+#define FT5402_REG_FT5402_POINTS_STABLE_MACRO (0x57+0x80)
+#define FT5402_REG_FT5402_MIN_DELTA_X (0x4a+0x80)
+#define FT5402_REG_FT5402_MIN_DELTA_Y (0x4b+0x80)
+#define FT5402_REG_FT5402_MIN_DELTA_STEP (0x4c+0x80)
+
+#define FT5402_REG_FT5402_ESD_NOISE_MACRO (0x58+0x80)
+#define FT5402_REG_FT5402_ESD_DIFF_VAL (0x4d+0x80)
+#define FT5402_REG_FT5402_ESD_NEGTIVE (0xCe)
+#define FT5402_REG_FT5402_ESD_FILTER_FRAMES (0x4f+0x80)
+
+#define FT5402_REG_FT5402_IO_LEVEL_SELECT (0x52+0x80)
+
+#define FT5402_REG_FT5402_POINTID_DELAY_COUNT (0x54+0x80)
+
+#define FT5402_REG_FT5402_LIFTUP_FILTER_MACRO (0x55+0x80)
+
+#define FT5402_REG_FT5402_DIFF_HANDLE_MACRO (0x5A+0x80)
+#define FT5402_REG_FT5402_MIN_WATER (0x5B+0x80)
+#define FT5402_REG_FT5402_MAX_NOISE (0x5C+0x80)
+#define FT5402_REG_FT5402_WATER_START_RX (0x5D+0x80)
+#define FT5402_REG_FT5402_WATER_START_TX (0xDE)
+
+#define FT5402_REG_FT5402_HOST_NUMBER_SUPPORTED_MACRO (0x38+0x80)
+#define FT5402_REG_FT5402_RAISE_THGROUP (0x36+0x80)
+#define FT5402_REG_FT5402_CHARGER_STATE (0x35+0x80)
+
+#define FT5402_REG_FT5402_FILTERID_START (0x37+0x80)
+
+#define FT5402_REG_FT5402_FRAME_FILTER_EN_MACRO (0x5F+0x80)
+#define FT5402_REG_FT5402_FRAME_FILTER_SUB_MAX_TH (0x60+0x80)
+#define FT5402_REG_FT5402_FRAME_FILTER_ADD_MAX_TH (0x61+0x80)
+#define FT5402_REG_FT5402_FRAME_FILTER_SKIP_START_FRAME (0x62+0x80)
+#define FT5402_REG_FT5402_FRAME_FILTER_BAND_EN (0x63+0x80)
+#define FT5402_REG_FT5402_FRAME_FILTER_BAND_WIDTH (0x64+0x80)
+/**************************************************************************/
+
+#define FT5402_REG_TEST_MODE 0x04
+#define FT5402_REG_TEST_MODE_2 0x05
+#define FT5402_TX_TEST_MODE_1 0x28
+#define FT5402_RX_TEST_MODE_1 0x1E
+#define FT5402_FACTORYMODE_VALUE 0x40
+#define FT5402_WORKMODE_VALUE 0x00
+
+/************************************************************************/
+/* string */
+/************************************************************************/
+#define STRING_FT5402_KX "FT5X02_KX"
+#define STRING_FT5402_KY "FT5X02_KY"
+#define STRING_FT5402_LEMDA_X "FT5X02_LEMDA_X"
+#define STRING_FT5402_LEMDA_Y "FT5X02_LEMDA_Y"
+#define STRING_FT5402_RESOLUTION_X "FT5X02_RESOLUTION_X"
+#define STRING_FT5402_RESOLUTION_Y "FT5X02_RESOLUTION_Y"
+#define STRING_FT5402_DIRECTION "FT5X02_DIRECTION"
+
+
+
+#define STRING_FT5402_FACE_DETECT_PRE_VALUE "FT5X02_FACE_DETECT_PRE_VALUE"
+#define STRING_FT5402_FACE_DETECT_NUM "FT5X02_FACE_DETECT_NUM"
+#define STRING_FT5402_BIGAREA_PEAK_VALUE_MIN "FT5X02_BIGAREA_PEAK_VALUE_MIN"
+#define STRING_FT5402_BIGAREA_DIFF_VALUE_OVER_NUM "FT5X02_BIGAREA_DIFF_VALUE_OVER_NUM"
+#define STRING_FT5402_CUSTOMER_ID "FT5X02_CUSTOMER_ID"
+#define STRING_FT5402_PERIOD_ACTIVE "FT5X02_RV_G_PERIOD_ACTIVE"
+#define STRING_FT5402_FACE_DETECT_STATISTICS_TX_NUM "FT5X02_FACE_DETECT_STATISTICS_TX_NUM"
+
+#define STRING_FT5402_THGROUP "FT5X02_THGROUP"
+#define STRING_FT5402_THPEAK "FT5X02_THPEAK"
+#define STRING_FT5402_FACE_DETECT_MODE "FT5X02_FACE_DETECT_MODE"
+#define STRING_FT5402_MAX_TOUCH_VALUE "FT5X02_MAX_TOUCH_VALUE"
+
+#define STRING_FT5402_PWMODE_CTRL "FT5X02_PWMODE_CTRL"
+#define STRING_FT5402_DRAW_LINE_TH "FT5X02_DRAW_LINE_TH"
+
+#define STRING_FT5402_POINTS_SUPPORTED "FT5X02_POINTS_SUPPORTED"
+
+#define STRING_FT5402_START_RX "FT5X02_START_RX"
+#define STRING_FT5402_ADC_TARGET "FT5X02_ADC_TARGET"
+#define STRING_FT5402_ESD_FILTER_FRAME "FT5X02_ESD_FILTER_FRAME"
+
+#define STRING_FT5402_POINTS_STABLE_MACRO "FT5X02_POINTS_STABLE_MACRO"
+#define STRING_FT5402_MIN_DELTA_X "FT5X02_MIN_DELTA_X"
+#define STRING_FT5402_MIN_DELTA_Y "FT5X02_MIN_DELTA_Y"
+#define STRING_FT5402_MIN_DELTA_STEP "FT5X02_MIN_DELTA_STEP"
+
+#define STRING_FT5402_ESD_NOISE_MACRO "FT5X02_ESD_NOISE_MACRO"
+#define STRING_FT5402_ESD_DIFF_VAL "FT5X02_ESD_DIFF_VAL"
+#define STRING_FT5402_ESD_NEGTIVE "FT5X02_ESD_NEGTIVE"
+#define STRING_FT5402_ESD_FILTER_FRAME "FT5X02_ESD_FILTER_FRAME"
+
+#define STRING_FT5402_IO_LEVEL_SELECT "FT5X02_IO_LEVEL_SELECT"
+#define STRING_FT5402_POINTID_DELAY_COUNT "FT5X02_POINTID_DELAY_COUNT"
+
+#define STRING_FT5402_LIFTUP_FILTER_MACRO "FT5X02_LIFTUP_FILTER_MACRO"
+
+#define STRING_FT5402_DIFFDATA_HANDLE "FT5X02_DIFFDATA_HANDLE" //_MACRO
+#define STRING_FT5402_MIN_WATER_VAL "FT5X02_MIN_WATER_VAL"
+#define STRING_FT5402_MAX_NOISE_VAL "FT5X02_MAX_NOISE_VAL"
+#define STRING_FT5402_WATER_HANDLE_START_RX "FT5X02_WATER_HANDLE_START_RX"
+#define STRING_FT5402_WATER_HANDLE_START_TX "FT5X02_WATER_HANDLE_START_TX"
+
+#define STRING_FT5402_HOST_NUMBER_SUPPORTED "FT5X02_HOST_NUMBER_SUPPORTED"
+#define STRING_FT5402_RV_G_RAISE_THGROUP "FT5X02_RV_G_RAISE_THGROUP"
+#define STRING_FT5402_RV_G_CHARGER_STATE "FT5X02_RV_G_CHARGER_STATE"
+
+#define STRING_FT5402_RV_G_FILTERID_START "FT5X02_RV_G_FILTERID_START"
+
+#define STRING_FT5402_FRAME_FILTER_EN "FT5X02_FRAME_FILTER_EN"
+#define STRING_FT5402_FRAME_FILTER_SUB_MAX_TH "FT5X02_FRAME_FILTER_SUB_MAX_TH"
+#define STRING_FT5402_FRAME_FILTER_ADD_MAX_TH "FT5X02_FRAME_FILTER_ADD_MAX_TH"
+#define STRING_FT5402_FRAME_FILTER_SKIP_START_FRAME "FT5X02_FRAME_FILTER_SKIP_START_FRAME"
+#define STRING_FT5402_FRAME_FILTER_BAND_EN "FT5X02_FRAME_FILTER_BAND_EN"
+#define STRING_FT5402_FRAME_FILTER_BAND_WIDTH "FT5X02_FRAME_FILTER_BAND_WIDTH"
+
+
+#define STRING_ft5402_tx_num "FT5X02_tx_num"
+#define STRING_ft5402_rx_num "FT5X02_rx_num"
+#define STRING_ft5402_gain "FT5X02_gain"
+#define STRING_ft5402_voltage "FT5X02_voltage"
+#define STRING_ft5402_scanselect "FT5X02_scanselect"
+
+#define STRING_ft5402_tx_order "FT5X02_tx_order"
+#define STRING_ft5402_tx_offset "FT5X02_tx_offset"
+#define STRING_ft5402_tx_cap "FT5X02_tx_cap"
+
+#define STRING_ft5402_rx_order "FT5X02_rx_order"
+#define STRING_ft5402_rx_offset "FT5X02_rx_offset"
+#define STRING_ft5402_rx_cap "FT5X02_rx_cap"
+
+struct Struct_Param_FT5402 {
+ short ft5402_KX;
+ short ft5402_KY;
+ unsigned char ft5402_LEMDA_X;
+ unsigned char ft5402_LEMDA_Y;
+ short ft5402_RESOLUTION_X;
+ short ft5402_RESOLUTION_Y;
+ unsigned char ft5402_DIRECTION;
+ unsigned char ft5402_FACE_DETECT_PRE_VALUE;
+ unsigned char ft5402_FACE_DETECT_NUM;
+
+ unsigned char ft5402_BIGAREA_PEAK_VALUE_MIN;
+ unsigned char ft5402_BIGAREA_DIFF_VALUE_OVER_NUM;
+ unsigned char ft5402_CUSTOMER_ID;
+ unsigned char ft5402_PERIOD_ACTIVE;
+ unsigned char ft5402_FACE_DETECT_STATISTICS_TX_NUM;
+
+ short ft5402_THGROUP;
+ unsigned char ft5402_THPEAK;
+ unsigned char ft5402_FACE_DETECT_MODE;
+ short ft5402_MAX_TOUCH_VALUE;
+
+ unsigned char ft5402_PWMODE_CTRL;
+ unsigned char ft5402_DRAW_LINE_TH;
+ unsigned char ft5402_POINTS_SUPPORTED;
+
+ unsigned char ft5402_START_RX;
+ short ft5402_ADC_TARGET;
+ unsigned char ft5402_ESD_FILTER_FRAME;
+
+ unsigned char ft5402_POINTS_STABLE_MACRO;
+ unsigned char ft5402_MIN_DELTA_X;
+ unsigned char ft5402_MIN_DELTA_Y;
+ unsigned char ft5402_MIN_DELTA_STEP;
+
+ unsigned char ft5402_ESD_NOISE_MACRO;
+ unsigned char ft5402_ESD_DIFF_VAL;
+ char ft5402_ESD_NEGTIVE; //negtive
+ unsigned char ft5402_ESD_FILTER_FRAMES;
+
+ unsigned char ft5402_IO_LEVEL_SELECT;
+
+ unsigned char ft5402_POINTID_DELAY_COUNT;
+
+ unsigned char ft5402_LIFTUP_FILTER_MACRO;
+
+ unsigned char ft5402_DIFF_HANDLE_MACRO;
+ char ft5402_MIN_WATER; //negtive
+ unsigned char ft5402_MAX_NOISE;
+ unsigned char ft5402_WATER_START_RX;
+ unsigned char ft5402_WATER_START_TX;
+
+ unsigned char ft5402_HOST_NUMBER_SUPPORTED_MACRO;
+ unsigned char ft5402_RAISE_THGROUP;
+ unsigned char ft5402_CHARGER_STATE;
+
+ unsigned char ft5402_FILTERID_START;
+
+ unsigned char ft5402_FRAME_FILTER_EN_MACRO;
+ unsigned char ft5402_FRAME_FILTER_SUB_MAX_TH;
+ unsigned char ft5402_FRAME_FILTER_ADD_MAX_TH;
+ unsigned char ft5402_FRAME_FILTER_SKIP_START_FRAME;
+ unsigned char ft5402_FRAME_FILTER_BAND_EN;
+ unsigned char ft5402_FRAME_FILTER_BAND_WIDTH;
+
+};
+
+struct Struct_Param_FT5402 g_param_ft5402 = {
+ FT5402_KX,
+ FT5402_KY,
+ FT5402_LEMDA_X,
+ FT5402_LEMDA_Y,
+ FT5402_RESOLUTION_X,
+ FT5402_RESOLUTION_Y,
+ FT5402_DIRECTION,
+
+ FT5402_FACE_DETECT_PRE_VALUE,
+ FT5402_FACE_DETECT_NUM,
+ FT5402_BIGAREA_PEAK_VALUE_MIN,
+ FT5402_BIGAREA_DIFF_VALUE_OVER_NUM,
+ FT5402_CUSTOMER_ID,
+ FT5402_RV_G_PERIOD_ACTIVE,
+ FT5402_FACE_DETECT_STATISTICS_TX_NUM,
+
+ FT5402_THGROUP,
+ FT5402_THPEAK,
+ FT5402_FACE_DETECT_MODE,
+ FT5402_MAX_TOUCH_VALUE,
+
+ FT5402_PWMODE_CTRL,
+ FT5402_DRAW_LINE_TH,
+ FT5402_POINTS_SUPPORTED,
+
+ FT5402_START_RX,
+ FT5402_ADC_TARGET,
+ FT5402_ESD_FILTER_FRAME,
+
+ FT5402_POINTS_STABLE_MACRO,
+ FT5402_MIN_DELTA_X,
+ FT5402_MIN_DELTA_Y,
+ FT5402_MIN_DELTA_STEP,
+
+ FT5402_ESD_NOISE_MACRO,
+ FT5402_ESD_DIFF_VAL,
+ FT5402_ESD_NEGTIVE,
+ FT5402_ESD_FILTER_FRAME,
+
+ FT5402_IO_LEVEL_SELECT,
+
+ FT5402_POINTID_DELAY_COUNT,
+
+ FT5402_LIFTUP_FILTER_MACRO,
+
+ FT5402_DIFFDATA_HANDLE,
+ FT5402_MIN_WATER_VAL,
+ FT5402_MAX_NOISE_VAL,
+ FT5402_WATER_HANDLE_START_RX,
+ FT5402_WATER_HANDLE_START_TX,
+
+ FT5402_HOST_NUMBER_SUPPORTED,
+ FT5402_RV_G_RAISE_THGROUP,
+ FT5402_RV_G_CHARGER_STATE,
+
+ FT5402_RV_G_FILTERID_START,
+
+ FT5402_FRAME_FILTER_EN,
+ FT5402_FRAME_FILTER_SUB_MAX_TH,
+ FT5402_FRAME_FILTER_ADD_MAX_TH,
+ FT5402_FRAME_FILTER_SKIP_START_FRAME,
+ FT5402_FRAME_FILTER_BAND_EN,
+ FT5402_FRAME_FILTER_BAND_WIDTH,
+};
+
+char String_Param_FT5402[][64] = {
+ STRING_FT5402_KX,
+ STRING_FT5402_KY,
+ STRING_FT5402_LEMDA_X,
+ STRING_FT5402_LEMDA_Y,
+ STRING_FT5402_RESOLUTION_X,
+ STRING_FT5402_RESOLUTION_Y,
+ STRING_FT5402_DIRECTION,
+ STRING_FT5402_FACE_DETECT_PRE_VALUE,
+ STRING_FT5402_FACE_DETECT_NUM,
+ STRING_FT5402_BIGAREA_PEAK_VALUE_MIN,
+ STRING_FT5402_BIGAREA_DIFF_VALUE_OVER_NUM,
+ STRING_FT5402_CUSTOMER_ID,
+ STRING_FT5402_PERIOD_ACTIVE,
+ STRING_FT5402_FACE_DETECT_STATISTICS_TX_NUM,
+
+ STRING_FT5402_THGROUP,
+ STRING_FT5402_THPEAK,
+ STRING_FT5402_FACE_DETECT_MODE,
+ STRING_FT5402_MAX_TOUCH_VALUE,
+
+ STRING_FT5402_PWMODE_CTRL,
+ STRING_FT5402_DRAW_LINE_TH,
+ STRING_FT5402_POINTS_SUPPORTED,
+
+ STRING_FT5402_START_RX,
+ STRING_FT5402_ADC_TARGET,
+ STRING_FT5402_ESD_FILTER_FRAME,
+
+
+ STRING_ft5402_tx_num,
+ STRING_ft5402_rx_num,
+ STRING_ft5402_gain,
+ STRING_ft5402_voltage ,
+ STRING_ft5402_scanselect,
+
+ STRING_ft5402_tx_order,
+ STRING_ft5402_tx_offset,
+ STRING_ft5402_tx_cap,
+
+ STRING_ft5402_rx_order,
+ STRING_ft5402_rx_offset,
+ STRING_ft5402_rx_cap,
+
+ STRING_FT5402_POINTS_STABLE_MACRO,
+ STRING_FT5402_MIN_DELTA_X,
+ STRING_FT5402_MIN_DELTA_Y,
+ STRING_FT5402_MIN_DELTA_STEP,
+
+ STRING_FT5402_ESD_NOISE_MACRO,
+ STRING_FT5402_ESD_DIFF_VAL,
+ STRING_FT5402_ESD_NEGTIVE,
+ STRING_FT5402_ESD_FILTER_FRAME,
+
+ STRING_FT5402_IO_LEVEL_SELECT,
+
+ STRING_FT5402_POINTID_DELAY_COUNT,
+
+ STRING_FT5402_LIFTUP_FILTER_MACRO,
+
+ STRING_FT5402_DIFFDATA_HANDLE,
+ STRING_FT5402_MIN_WATER_VAL,
+ STRING_FT5402_MAX_NOISE_VAL,
+ STRING_FT5402_WATER_HANDLE_START_RX,
+ STRING_FT5402_WATER_HANDLE_START_TX,
+
+ STRING_FT5402_HOST_NUMBER_SUPPORTED,
+ STRING_FT5402_RV_G_RAISE_THGROUP,
+ STRING_FT5402_RV_G_CHARGER_STATE,
+
+ STRING_FT5402_RV_G_FILTERID_START,
+
+ STRING_FT5402_FRAME_FILTER_EN,
+ STRING_FT5402_FRAME_FILTER_SUB_MAX_TH,
+ STRING_FT5402_FRAME_FILTER_ADD_MAX_TH,
+ STRING_FT5402_FRAME_FILTER_SKIP_START_FRAME,
+ STRING_FT5402_FRAME_FILTER_BAND_EN,
+ STRING_FT5402_FRAME_FILTER_BAND_WIDTH,
+
+};
+
+#define FT5402_APP_NAME "FT5X02_param"
+
+#define FT5402_APP_LEGAL "Legal_File"
+#define FT5402_APP_LEGAL_BYTE_1_STR "BYTE_1"
+#define FT5402_APP_LEGAL_BYTE_2_STR "BYTE_2"
+
+#define FT5402_APP_LEGAL_BYTE_1_VALUE 107
+#define FT5402_APP_LEGAL_BYTE_2_VALUE 201
+
+
+#define FT5402_INI_FILEPATH "/system/etc/firmware/"
+
+#endif
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/ft5x0x/ft5x0x.c b/ANDROID_3.4.5/drivers/input/touchscreen/ft5x0x/ft5x0x.c
new file mode 100755
index 00000000..9bb63b83
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/ft5x0x/ft5x0x.c
@@ -0,0 +1,937 @@
+/*
+ * drivers/input/touchscreen/ft5x0x/ft5x0x.c
+ *
+ * FocalTech ft5x0x TouchScreen driver.
+ *
+ * Copyright (c) 2010 Focal tech Ltd.
+ *
+ * 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.
+ *
+ *
+ * note: only support mulititouch Wenfs 2010-10-01
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <mach/hardware.h>
+#include <linux/platform_device.h>
+#include <linux/suspend.h>
+#include <linux/wait.h>
+#include <asm/uaccess.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <mach/wmt_iomux.h>
+#include <linux/slab.h>
+#include "ft5x0x.h"
+#include "../../../video/backlight/wmt_bl.h"
+
+struct ft5x0x_data *pContext=NULL;
+static struct i2c_client *l_client=NULL;
+
+#ifdef TOUCH_KEY
+static int keycodes[NUM_KEYS] ={
+ KEY_MENU,
+ KEY_HOME,
+ KEY_BACK,
+ KEY_SEARCH
+};
+#endif
+
+#define FT5402_CONFIG_NAME "fttpconfig_5402public.ini"
+extern int ft5x0x_read_fw_ver(void);
+extern int ft5x0x_auto_clb(void);
+extern int ft5x0x_upg_fw_bin(struct ft5x0x_data *ft5x0x, int check_ver);
+extern int ft5402_Get_Param_From_Ini(char *config_name);
+extern int ft5402_Init_IC_Param(struct i2c_client *client);
+extern int ft5402_get_ic_param(struct i2c_client *client);
+extern int ft5402_read_reg(struct i2c_client * client, u8 regaddr, u8 * regvalue);
+
+extern int register_bl_notifier(struct notifier_block *nb);
+
+extern int unregister_bl_notifier(struct notifier_block *nb);
+
+
+int ft5x0x_i2c_rxdata(char *rxdata, int length)
+{
+ int ret;
+ struct i2c_msg msg[2];
+
+ msg[0].addr = pContext->addr;
+ msg[0].flags = 0 | I2C_M_NOSTART;
+ msg[0].len = 1;
+ msg[0].buf = rxdata;
+
+ msg[1].addr = pContext->addr;
+ msg[1].flags = I2C_M_RD;
+ msg[1].len = length;
+ msg[1].buf = rxdata;
+
+ ret = i2c_transfer(pContext->client->adapter, msg, 2);
+ if (ret <= 0)
+ dbg_err("msg i2c read error: %d\n", ret);
+
+ return ret;
+}
+
+
+int ft5x0x_i2c_txdata(char *txdata, int length)
+{
+ int ret;
+ struct i2c_msg msg[1];
+
+ msg[0].addr = pContext->addr;
+ msg[0].flags = 0;
+ msg[0].len = length;
+ msg[0].buf = txdata;
+
+ ret = i2c_transfer(pContext->client->adapter, msg, 1);
+ if (ret <= 0)
+ dbg_err("msg i2c read error: %d\n", ret);
+
+ return ret;
+}
+
+static void ft5x0x_penup(struct ft5x0x_data *ft5x0x)
+{
+ input_mt_sync(ft5x0x->input_dev);
+ input_sync(ft5x0x->input_dev);
+#ifdef TOUCH_KEY
+ if(ft5x0x->tskey_used && ft5x0x->tkey_pressed && ft5x0x->tkey_idx < NUM_KEYS ){
+ input_report_key(ft5x0x->input_dev, keycodes[ft5x0x->tkey_idx], 1);
+ input_sync(ft5x0x->input_dev);
+ input_report_key(ft5x0x->input_dev, keycodes[ft5x0x->tkey_idx], 0);
+ input_sync(ft5x0x->input_dev);
+ dbg("report as key event %d \n",ft5x0x->tkey_idx);
+ }
+#endif
+
+ dbg("pen up\n");
+ return;
+}
+
+#ifdef TOUCH_KEY
+static int ft5x0x_read_tskey(struct ft5x0x_data *ft5x0x,int x,int y)
+{
+ int px,py;
+
+ if(ft5x0x->tkey.axis){
+ px = y;
+ py = x;
+ }else{
+ px = x;
+ py = y;
+ }
+
+ if(px >= ft5x0x->tkey.x_lower && px<=ft5x0x->tkey.x_upper){
+ ft5x0x->tkey_pressed = 1;
+ if(py>= ft5x0x->tkey.ypos[0].y_lower && py<= ft5x0x->tkey.ypos[0].y_upper){
+ ft5x0x->tkey_idx= 0;
+ }else if(py>= ft5x0x->tkey.ypos[1].y_lower && py<= ft5x0x->tkey.ypos[1].y_upper){
+ ft5x0x->tkey_idx = 1;
+ }else if(py>= ft5x0x->tkey.ypos[2].y_lower && py<= ft5x0x->tkey.ypos[2].y_upper){
+ ft5x0x->tkey_idx = 2;
+ }else if(py>= ft5x0x->tkey.ypos[3].y_lower && py<= ft5x0x->tkey.ypos[3].y_upper){
+ ft5x0x->tkey_idx = 3;
+ }else{
+ ft5x0x->tkey_idx = NUM_KEYS;
+ }
+
+ return 1;
+ }
+
+ ft5x0x->tkey_pressed = 0;
+ return 0;
+}
+#endif
+
+static int ft5x0x_read_data(struct ft5x0x_data *ft5x0x)
+{
+ int ret = -1;
+ int i = 0;
+ u16 x,y,px,py;
+ u8 buf[64] = {0}, id;
+ struct ts_event *event = &ft5x0x->event;
+
+ if(ft5x0x->nt == 10)
+ ret = ft5x0x_i2c_rxdata(buf, 64);
+ else if(ft5x0x->nt == 5)
+ ret = ft5x0x_i2c_rxdata(buf, 31);
+
+ if (ret <= 0) {
+ dbg_err("read_data i2c_rxdata failed: %d\n", ret);
+ return ret;
+ }
+
+ memset(event, 0, sizeof(struct ts_event));
+ //event->tpoint = buf[2] & 0x03;// 0000 0011
+ //event->tpoint = buf[2] & 0x07;// 000 0111
+ event->tpoint = buf[2]&0x0F;
+ if (event->tpoint == 0) {
+ ft5x0x_penup(ft5x0x);
+ return 1;
+ }
+
+ if (event->tpoint > ft5x0x->nt){
+ dbg_err("tounch pointnum=%d > max:%d\n", event->tpoint,ft5x0x->nt);
+ return -1;
+ }
+
+ for (i = 0; i < event->tpoint; i++){
+ id = (buf[5+i*6] >>4) & 0x0F;//get track id
+ if(ft5x0x->swap){
+ px = (buf[3+i*6] & 0x0F)<<8 |buf[4+i*6];
+ py = (buf[5+i*6] & 0x0F)<<8 |buf[6+i*6];
+ }else{
+ px = (buf[5+i*6] & 0x0F)<<8 |buf[6+i*6];
+ py = (buf[3+i*6] & 0x0F)<<8 |buf[4+i*6];
+ }
+
+ x = px;
+ y = py;
+
+ if(ft5x0x->xch)
+ x = ft5x0x->reslx - px;
+
+ if(ft5x0x->ych)
+ y = ft5x0x->resly - py;
+
+ if(ft5x0x->dbg) printk("F%d: Tid=%d,px=%d,py=%d; x=%d,y=%d\n", i, id, px, py, x, y);
+
+#ifdef TOUCH_KEY
+ if(ft5x0x->tskey_used && event->tpoint==1) {
+ if(ft5x0x_read_tskey(ft5x0x,px,py) > 0) return -1;
+ }
+#endif
+ if (ft5x0x->lcd_exchg) {
+ int tmp;
+ tmp = x;
+ x = y;
+ y = ft5x0x->reslx - tmp;
+ }
+ event->x[i] = x;
+ event->y[i] = y;
+ event->tid[i] = id;
+
+ }
+
+ return 0;
+}
+
+static void ft5x0x_report(struct ft5x0x_data *ft5x0x)
+{
+ int i = 0;
+ struct ts_event *event = &ft5x0x->event;
+
+ for (i = 0; i < event->tpoint; i++){
+ input_report_abs(ft5x0x->input_dev, ABS_MT_TRACKING_ID, event->tid[i]);
+ input_report_abs(ft5x0x->input_dev, ABS_MT_POSITION_X, event->x[i]);
+ input_report_abs(ft5x0x->input_dev, ABS_MT_POSITION_Y, event->y[i]);
+ input_mt_sync(ft5x0x->input_dev);
+ }
+ input_sync(ft5x0x->input_dev);
+
+ return;
+}
+
+static void ft5x0x_read_work(struct work_struct *work)
+{
+ int ret = -1;
+ struct ft5x0x_data *ft5x0x = container_of(work, struct ft5x0x_data, read_work);
+
+ mutex_lock(&ft5x0x->ts_mutex);
+ ret = ft5x0x_read_data(ft5x0x);
+
+ if (ret == 0) ft5x0x_report(ft5x0x);
+
+ wmt_gpio_unmask_irq(ft5x0x->irqgpio);
+ mutex_unlock(&ft5x0x->ts_mutex);
+
+ return;
+}
+
+static irqreturn_t ft5x0x_interrupt(int irq, void *dev)
+{
+ struct ft5x0x_data *ft5x0x = dev;
+
+ if (gpio_irqstatus(ft5x0x->irqgpio))
+ {
+ wmt_gpio_ack_irq(ft5x0x->irqgpio);
+ if (is_gpio_irqenable(ft5x0x->irqgpio))
+ {
+ wmt_gpio_mask_irq(ft5x0x->irqgpio);
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ if(!ft5x0x->earlysus) queue_work(ft5x0x->workqueue, &ft5x0x->read_work);
+#else
+ queue_work(ft5x0x->workqueue, &ft5x0x->read_work);
+#endif
+
+ }
+ return IRQ_HANDLED;
+ }
+ return IRQ_NONE;
+}
+
+static void ft5x0x_reset(struct ft5x0x_data *ft5x0x)
+{
+ gpio_set_value(ft5x0x->rstgpio, 1);
+ mdelay(5);
+ gpio_set_value(ft5x0x->rstgpio, 0);
+ mdelay(20);
+ gpio_set_value(ft5x0x->rstgpio, 1);
+ mdelay(5);
+
+ return;
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void ft5x0x_early_suspend(struct early_suspend *handler)
+{
+ struct ft5x0x_data *ft5x0x = container_of(handler, struct ft5x0x_data, early_suspend);
+ ft5x0x->earlysus = 1;
+ wmt_gpio_mask_irq(ft5x0x->irqgpio);
+ return;
+}
+
+static void ft5x0x_late_resume(struct early_suspend *handler)
+{
+ struct ft5x0x_data *ft5x0x = container_of(handler, struct ft5x0x_data, early_suspend);
+
+ ft5x0x_reset(ft5x0x);
+ ft5x0x->earlysus = 0;
+
+ wmt_gpio_set_irq_type(ft5x0x->irqgpio, IRQ_TYPE_EDGE_FALLING);
+ wmt_gpio_unmask_irq(ft5x0x->irqgpio);
+
+ return;
+}
+#endif //CONFIG_HAS_EARLYSUSPEND
+
+#ifdef CONFIG_PM
+static int ft5x0x_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct ft5x0x_data *ft5x0x = dev_get_drvdata(&pdev->dev);
+ ft5x0x->earlysus = 1;
+ wmt_gpio_mask_irq(ft5x0x->irqgpio);
+ return 0;
+}
+
+static int ft5x0x_resume(struct platform_device *pdev)
+{
+ struct ft5x0x_data *ft5x0x = dev_get_drvdata(&pdev->dev);
+ ft5x0x_reset(ft5x0x);
+ ft5x0x->earlysus = 0;
+
+ if (ft5x0x->load_cfg) {
+ msleep(350);
+ ft5402_Init_IC_Param(ft5x0x->client);
+ //msleep(50);
+ ft5402_get_ic_param(ft5x0x->client);
+ }
+ wmt_gpio_set_irq_type(ft5x0x->irqgpio, IRQ_TYPE_EDGE_FALLING);
+ wmt_gpio_unmask_irq(ft5x0x->irqgpio);
+ return 0;
+}
+
+#else
+#define ft5x0x_suspend NULL
+#define ft5x0x_resume NULL
+#endif
+
+static ssize_t cat_dbg(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "dbg \n");
+}
+
+static ssize_t echo_dbg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned int dbg = simple_strtoul(buf, NULL, 10);
+ struct ft5x0x_data *ft5x0x = pContext;
+
+ if(dbg){
+ ft5x0x->dbg = 1;
+ }else{
+ ft5x0x->dbg = 0;
+ }
+
+ return count;
+}
+static DEVICE_ATTR(dbg, S_IRUGO | S_IWUSR, cat_dbg, echo_dbg);
+
+static ssize_t cat_clb(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "calibrate \n");
+}
+
+static ssize_t echo_clb(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned int cal = simple_strtoul(buf, NULL, 10);
+
+ if(cal){
+ if(ft5x0x_auto_clb()) printk("Calibrate Failed.\n");
+ }else{
+ printk("calibrate --echo 1 >clb.\n");
+ }
+
+ return count;
+}
+
+static DEVICE_ATTR(clb, S_IRUGO | S_IWUSR, cat_clb, echo_clb);
+
+static ssize_t cat_fupg(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "fupg \n");
+}
+
+static ssize_t echo_fupg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct ft5x0x_data *ft5x0x = pContext;
+ unsigned int upg = simple_strtoul(buf, NULL, 10);
+
+ wmt_gpio_mask_irq(ft5x0x->irqgpio);
+ if(upg){
+ if(ft5x0x_upg_fw_bin(ft5x0x, 0)) printk("Upgrade Failed.\n");
+ }else{
+ printk("upgrade --echo 1 > fupg.\n");
+ }
+ wmt_gpio_unmask_irq(ft5x0x->irqgpio);
+
+ return count;
+}
+static DEVICE_ATTR(fupg, S_IRUGO | S_IWUSR, cat_fupg, echo_fupg);
+
+
+static ssize_t cat_fver(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int fw_ver = ft5x0x_read_fw_ver();
+ return sprintf(buf, "firmware version:0x%02x \n",fw_ver);
+}
+
+static ssize_t echo_fver(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ return count;
+}
+static DEVICE_ATTR(fver, S_IRUGO | S_IWUSR, cat_fver, echo_fver);
+
+static ssize_t cat_addr(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int ret;
+ u8 addrs[32];
+ int cnt=0;
+ struct i2c_msg msg[2];
+ struct ft5x0x_data *ft5x0x = pContext;
+ u8 ver[1]= {0xa6};
+
+ ft5x0x->addr = 1;
+
+ msg[0].addr = ft5x0x->addr;
+ msg[0].flags = 0;
+ msg[0].len = 1;
+ msg[0].buf = ver;
+
+ msg[1].addr = ft5x0x->addr;
+ msg[1].flags = I2C_M_RD;
+ msg[1].len = 1;
+ msg[1].buf = ver;
+
+ while(ft5x0x->addr < 0x80){
+ ret = i2c_transfer(ft5x0x->client->adapter, msg, 2);
+ if(ret == 2) sprintf(&addrs[5*cnt++], " 0x%02x",ft5x0x->addr);
+
+ ft5x0x->addr++;
+ msg[0].addr = msg[1].addr = ft5x0x->addr;
+ }
+
+ return sprintf(buf, "i2c addr:%s\n",addrs);
+}
+
+static ssize_t echo_addr(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned int addr;
+ struct ft5x0x_data *ft5x0x = pContext;
+
+ sscanf(buf,"%x", &addr);
+ ft5x0x->addr = addr;
+
+ return count;
+}
+static DEVICE_ATTR(addr, S_IRUGO | S_IWUSR, cat_addr, echo_addr);
+
+static struct attribute *ft5x0x_attributes[] = {
+ &dev_attr_clb.attr,
+ &dev_attr_fupg.attr,
+ &dev_attr_fver.attr,
+ &dev_attr_dbg.attr,
+ &dev_attr_addr.attr,
+ NULL
+};
+
+static const struct attribute_group ft5x0x_group = {
+ .attrs = ft5x0x_attributes,
+};
+
+static int ft5x0x_sysfs_create_group(struct ft5x0x_data *ft5x0x, const struct attribute_group *group)
+{
+ int err;
+
+ ft5x0x->kobj = kobject_create_and_add("wmtts", NULL) ;
+ if(!ft5x0x->kobj){
+ dbg_err("kobj create failed.\n");
+ return -ENOMEM;
+ }
+
+ /* Register sysfs hooks */
+ err = sysfs_create_group(ft5x0x->kobj, group);
+ if (err < 0){
+ kobject_del(ft5x0x->kobj);
+ dbg_err("Create sysfs group failed!\n");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static void ft5x0x_sysfs_remove_group(struct ft5x0x_data *ft5x0x, const struct attribute_group *group)
+{
+ sysfs_remove_group(ft5x0x->kobj, group);
+ kobject_del(ft5x0x->kobj);
+ return;
+}
+
+static int bl_notify_irqgpio = -1;
+static int wmt_wakeup_bl_notify(struct notifier_block *nb, unsigned long event,
+ void *dummy)
+{
+ switch (event) {
+ case BL_CLOSE:
+ errlog("ft5x0x: BL_CLOSE, disable irq\n");
+ wmt_gpio_mask_irq(bl_notify_irqgpio);
+ break;
+ case BL_OPEN:
+ errlog("ft5x0x: BL_OPEN, enable irq\n");
+ wmt_gpio_unmask_irq(bl_notify_irqgpio);
+ break;
+ }
+ return NOTIFY_OK;
+}
+
+static struct notifier_block wmt_bl_notify = {
+ .notifier_call = wmt_wakeup_bl_notify,
+};
+
+static int ft5x0x_probe(struct platform_device *pdev)
+{
+ int i,err = 0;
+ u8 value = 0;
+ u8 cfg_name[32];
+ struct ft5x0x_data *ft5x0x = platform_get_drvdata( pdev);
+
+ ft5x0x->client = l_client;
+ INIT_WORK(&ft5x0x->read_work, ft5x0x_read_work);
+ mutex_init(&ft5x0x->ts_mutex);
+
+ ft5x0x->workqueue = create_singlethread_workqueue(ft5x0x->name);
+ if (!ft5x0x->workqueue) {
+ err = -ESRCH;
+ goto exit_create_singlethread;
+ }
+
+ err = ft5x0x_sysfs_create_group(ft5x0x, &ft5x0x_group);
+ if(err < 0){
+ dbg("create sysfs group failed.\n");
+ goto exit_create_group;
+ }
+
+ ft5x0x->input_dev = input_allocate_device();
+ if (!ft5x0x->input_dev) {
+ err = -ENOMEM;
+ dbg("failed to allocate input device\n");
+ goto exit_input_dev_alloc_failed;
+ }
+
+ ft5x0x->input_dev->name = ft5x0x->name;
+ ft5x0x->input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ set_bit(INPUT_PROP_DIRECT, ft5x0x->input_dev->propbit);
+
+ if (ft5x0x->lcd_exchg) {
+ input_set_abs_params(ft5x0x->input_dev,
+ ABS_MT_POSITION_X, 0, ft5x0x->resly, 0, 0);
+ input_set_abs_params(ft5x0x->input_dev,
+ ABS_MT_POSITION_Y, 0, ft5x0x->reslx, 0, 0);
+ } else {
+ input_set_abs_params(ft5x0x->input_dev,
+ ABS_MT_POSITION_X, 0, ft5x0x->reslx, 0, 0);
+ input_set_abs_params(ft5x0x->input_dev,
+ ABS_MT_POSITION_Y, 0, ft5x0x->resly, 0, 0);
+ }
+ input_set_abs_params(ft5x0x->input_dev,
+ ABS_MT_TRACKING_ID, 0, 20, 0, 0);
+#ifdef TOUCH_KEY
+ if(ft5x0x->tskey_used){
+ for (i = 0; i <NUM_KEYS; i++)
+ set_bit(keycodes[i], ft5x0x->input_dev->keybit);
+
+ ft5x0x->input_dev->keycode = keycodes;
+ ft5x0x->input_dev->keycodesize = sizeof(unsigned int);
+ ft5x0x->input_dev->keycodemax = NUM_KEYS;
+ }
+#endif
+
+ err = input_register_device(ft5x0x->input_dev);
+ if (err) {
+ dbg_err("ft5x0x_ts_probe: failed to register input device.\n");
+ goto exit_input_register_device_failed;
+ }
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ ft5x0x->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+ ft5x0x->early_suspend.suspend = ft5x0x_early_suspend;
+ ft5x0x->early_suspend.resume = ft5x0x_late_resume;
+ register_early_suspend(&ft5x0x->early_suspend);
+#endif
+
+ if(ft5x0x->upg){
+ if(ft5x0x_upg_fw_bin(ft5x0x, 1)) printk("Upgrade Failed.\n");
+ else wmt_setsyspara("wmt.io.ts.upg","");
+ ft5x0x->upg = 0x00;
+ }
+
+ if(request_irq(ft5x0x->irq, ft5x0x_interrupt, IRQF_SHARED, ft5x0x->name, ft5x0x) < 0){
+ dbg_err("Could not allocate irq for ts_ft5x0x !\n");
+ err = -1;
+ goto exit_register_irq;
+ }
+
+ { // check if need to load config to IC or not
+ err = ft5402_read_reg(ft5x0x->client, 0xa3, &value);
+ if (err < 0)
+ dbg_err("Read reg 0xa3 failed.\n");
+ else
+ printk("0xa3 reg = %d\n", value);
+ if (value == 3)
+ ft5x0x->load_cfg = 1;
+ else
+ ft5x0x->load_cfg = 0;
+ }
+ ft5x0x_reset(ft5x0x);
+
+ if (ft5x0x->load_cfg) {
+ msleep(350); /*make sure CTP already finish startup process*/
+ sprintf(cfg_name, "%s.ini", ft5x0x->cfg_name);
+ printk("Config file name: %s\n", cfg_name);
+ if (ft5402_Get_Param_From_Ini(cfg_name) >= 0)
+ ft5402_Init_IC_Param(ft5x0x->client);
+ else
+ dbg_err("[FTS]-------Get ft5402 param from INI file failed\n");
+ ft5402_get_ic_param(ft5x0x->client);
+ }
+
+ wmt_gpio_set_irq_type(ft5x0x->irqgpio, IRQ_TYPE_EDGE_FALLING);
+ wmt_gpio_unmask_irq(ft5x0x->irqgpio);
+
+ if(bl_notify_irqgpio < 0){
+ register_bl_notifier(&wmt_bl_notify);
+ bl_notify_irqgpio = ft5x0x->irqgpio;
+ }
+
+ return 0;
+
+exit_register_irq:
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&ft5x0x->early_suspend);
+#endif
+exit_input_register_device_failed:
+ input_free_device(ft5x0x->input_dev);
+exit_input_dev_alloc_failed:
+ ft5x0x_sysfs_remove_group(ft5x0x, &ft5x0x_group);
+exit_create_group:
+ cancel_work_sync(&ft5x0x->read_work);
+ destroy_workqueue(ft5x0x->workqueue);
+exit_create_singlethread:
+ return err;
+}
+
+static int ft5x0x_remove(struct platform_device *pdev)
+{
+ struct ft5x0x_data *ft5x0x = platform_get_drvdata( pdev);
+
+ if( bl_notify_irqgpio > 0){
+ unregister_bl_notifier(&wmt_bl_notify);
+ bl_notify_irqgpio = -1;
+ }
+ cancel_work_sync(&ft5x0x->read_work);
+ flush_workqueue(ft5x0x->workqueue);
+ destroy_workqueue(ft5x0x->workqueue);
+
+ free_irq(ft5x0x->irq, ft5x0x);
+ wmt_gpio_mask_irq(ft5x0x->irqgpio);
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&ft5x0x->early_suspend);
+#endif
+ input_unregister_device(ft5x0x->input_dev);
+
+ ft5x0x_sysfs_remove_group(ft5x0x, &ft5x0x_group);
+
+ mutex_destroy(&ft5x0x->ts_mutex);
+ dbg("remove...\n");
+ return 0;
+}
+
+static void ft5x0x_release(struct device *device)
+{
+ return;
+}
+
+static struct platform_device ft5x0x_device = {
+ .name = DEV_FT5X0X,
+ .id = 0,
+ .dev = {.release = ft5x0x_release},
+};
+
+static struct platform_driver ft5x0x_driver = {
+ .driver = {
+ .name = DEV_FT5X0X,
+ .owner = THIS_MODULE,
+ },
+ .probe = ft5x0x_probe,
+ .remove = ft5x0x_remove,
+ .suspend = ft5x0x_suspend,
+ .resume = ft5x0x_resume,
+};
+
+static int check_touch_env(struct ft5x0x_data *ft5x0x)
+{
+ int i,ret = 0;
+ int len = 96;
+ int Enable;
+ char retval[96] = {0};
+ char *p=NULL;
+ char *s=NULL;
+
+ // Get u-boot parameter
+ ret = wmt_getsyspara("wmt.io.touch", retval, &len);
+ if(ret){
+ //printk("MST FT5x0x:Read wmt.io.touch Failed.\n");
+ return -EIO;
+ }
+ sscanf(retval,"%d:",&Enable);
+ //check touch enable
+ if(Enable == 0){
+ //printk("FT5x0x Touch Screen Is Disabled.\n");
+ return -ENODEV;
+ }
+
+ p = strchr(retval,':');
+ p++;
+ if(strncmp(p,"ft5301",6)==0){//check touch ID
+ ft5x0x->id = FT5301;
+ ft5x0x->name = DEV_FT5301;
+ }else if(strncmp(p,"ft5406",6)==0){
+ ft5x0x->id = FT5406;
+ ft5x0x->name = DEV_FT5406;
+ }else if(strncmp(p,"ft5206",6)==0){
+ ft5x0x->id = FT5206;
+ ft5x0x->name = DEV_FT5206;
+ }else if(strncmp(p,"ft5606",6)==0){
+ ft5x0x->id = FT5606;
+ ft5x0x->name = DEV_FT5606;
+ }else if(strncmp(p,"ft5306",6)==0){
+ ft5x0x->id = FT5306;
+ ft5x0x->name = DEV_FT5306;
+ }else if(strncmp(p,"ft5302",6)==0){
+ ft5x0x->id = FT5302;
+ ft5x0x->name = DEV_FT5302;
+ }else if(strncmp(p,"ft5",3)==0)
+ {
+ ft5x0x->id = FT5X0X;
+ ft5x0x->name = DEV_FT5X0X;
+ }else{
+ printk("FT5x0x touch disabled.\n");
+ return -ENODEV;
+ }
+
+ s = strchr(p,':');
+ strncpy(ft5x0x->cfg_name, p, s-p);
+
+ p = s + 1;
+ sscanf(p,"%d:%d:%d:%d:%d:%d:%d:%d:%x", &ft5x0x->irqgpio, &ft5x0x->reslx, &ft5x0x->resly, &ft5x0x->rstgpio, &ft5x0x->swap, &ft5x0x->xch, &ft5x0x->ych, &ft5x0x->nt, &ft5x0x->addr);
+
+ ft5x0x->irq = IRQ_GPIO;
+ printk("%s irqgpio=%d, reslx=%d, resly=%d, rstgpio=%d, swap=%d, xch=%d, ych=%d, nt=%d, addr=%x\n", ft5x0x->name, ft5x0x->irqgpio, ft5x0x->reslx, ft5x0x->resly, ft5x0x->rstgpio, ft5x0x->swap, ft5x0x->xch, ft5x0x->ych, ft5x0x->nt, ft5x0x->addr);
+
+ memset(retval,0x00,sizeof(retval));
+ ret = wmt_getsyspara("wmt.io.ts.upg", retval, &len);
+ if(!ret){
+ ft5x0x->upg = 1;
+ strncpy(ft5x0x->fw_name, retval, sizeof(ft5x0x->fw_name));
+ }
+
+#ifdef TOUCH_KEY
+ memset(retval,0x00,sizeof(retval));
+ ret = wmt_getsyspara("wmt.io.tskey", retval, &len);
+ if(!ret){
+ sscanf(retval,"%d:", &ft5x0x->nkeys);
+ p = strchr(retval,':');
+ p++;
+ for(i=0; i < ft5x0x->nkeys; i++ ){
+ sscanf(p,"%d:%d", &ft5x0x->tkey.ypos[i].y_lower, &ft5x0x->tkey.ypos[i].y_upper);
+ p = strchr(p,':');
+ p++;
+ p = strchr(p,':');
+ p++;
+ }
+ sscanf(p,"%d:%d:%d", &ft5x0x->tkey.axis, &ft5x0x->tkey.x_lower, &ft5x0x->tkey.x_upper);
+ ft5x0x->tskey_used = 1;
+ }
+#endif
+
+ memset(retval,0x00,sizeof(retval));
+ ret = wmt_getsyspara("wmt.display.fb0", retval, &len);
+ if (!ret) {
+ int tmp[6];
+ p = retval;
+ sscanf(p, "%d:[%d:%d:%d:%d:%d", &tmp[0], &tmp[1], &tmp[2], &tmp[3], &tmp[4], &tmp[5]);
+ if (tmp[4] > tmp[5])
+ ft5x0x->lcd_exchg = 1;
+ }
+
+ return 0;
+}
+
+struct i2c_board_info ts_i2c_board_info = {
+ .type = TS_I2C_NAME,
+ .flags = 0x00,
+ .addr = FT5406_I2C_ADDR,
+ .platform_data = NULL,
+ .archdata = NULL,
+ .irq = -1,
+};
+
+static int ts_i2c_register_device (void)
+{
+ struct i2c_board_info *ts_i2c_bi;
+ struct i2c_adapter *adapter = NULL;
+ //struct i2c_client *client = NULL;
+
+ //ts_i2c_board_info.addr = FT5406_I2C_ADDR;
+ ts_i2c_bi = &ts_i2c_board_info;
+ adapter = i2c_get_adapter(FT5X0X_I2C_BUS);/*in bus 1*/
+
+ if (NULL == adapter) {
+ printk("can not get i2c adapter, client address error\n");
+ return -1;
+ }
+ l_client = i2c_new_device(adapter, ts_i2c_bi);
+ if (l_client == NULL) {
+ printk("allocate i2c client failed\n");
+ return -1;
+ }
+ i2c_put_adapter(adapter);
+ return 0;
+}
+
+static void ts_i2c_unregister_device(void)
+{
+ if (l_client != NULL)
+ {
+ i2c_unregister_device(l_client);
+ l_client = NULL;
+ }
+}
+
+static int __init ft5x0x_init(void)
+{
+ int ret = -ENOMEM;
+ struct ft5x0x_data *ft5x0x=NULL;
+
+ if (ts_i2c_register_device()<0)
+ {
+ dbg("Error to run ts_i2c_register_device()!\n");
+ return -1;
+ }
+
+ ft5x0x = kzalloc(sizeof(struct ft5x0x_data), GFP_KERNEL);
+ if(!ft5x0x){
+ dbg_err("mem alloc failed.\n");
+ return -ENOMEM;
+ }
+
+ pContext = ft5x0x;
+ ret = check_touch_env(ft5x0x);
+ if(ret < 0)
+ goto exit_free_mem;
+
+ ret = gpio_request(ft5x0x->irqgpio, "ts_irq");
+ if (ret < 0) {
+ printk("gpio(%d) touchscreen irq request fail\n", ft5x0x->irqgpio);
+ goto exit_free_mem;
+ }
+ wmt_gpio_setpull(ft5x0x->irqgpio, WMT_GPIO_PULL_UP);
+ gpio_direction_input(ft5x0x->irqgpio);
+
+ ret = gpio_request(ft5x0x->rstgpio, "ts_rst");
+ if (ret < 0) {
+ printk("gpio(%d) touchscreen reset request fail\n", ft5x0x->rstgpio);
+ goto exit_free_irqgpio;
+ }
+ gpio_direction_output(ft5x0x->rstgpio, 1);
+
+
+ ret = platform_device_register(&ft5x0x_device);
+ if(ret){
+ dbg_err("register platform drivver failed!\n");
+ goto exit_free_gpio;
+ }
+ platform_set_drvdata(&ft5x0x_device, ft5x0x);
+
+ ret = platform_driver_register(&ft5x0x_driver);
+ if(ret){
+ dbg_err("register platform device failed!\n");
+ goto exit_unregister_pdev;
+ }
+
+ return ret;
+
+exit_unregister_pdev:
+ platform_device_unregister(&ft5x0x_device);
+exit_free_gpio:
+ gpio_free(ft5x0x->rstgpio);
+exit_free_irqgpio:
+ gpio_free(ft5x0x->irqgpio);
+exit_free_mem:
+ kfree(ft5x0x);
+ pContext = NULL;
+ return ret;
+}
+
+static void ft5x0x_exit(void)
+{
+ if(!pContext) return;
+
+ gpio_free(pContext->rstgpio);
+ gpio_free(pContext->irqgpio);
+ platform_driver_unregister(&ft5x0x_driver);
+ platform_device_unregister(&ft5x0x_device);
+ kfree(pContext);
+ ts_i2c_unregister_device();
+ return;
+}
+
+late_initcall(ft5x0x_init);
+module_exit(ft5x0x_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("FocalTech.Touch");
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/ft5x0x/ft5x0x.h b/ANDROID_3.4.5/drivers/input/touchscreen/ft5x0x/ft5x0x.h
new file mode 100755
index 00000000..03836b49
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/ft5x0x/ft5x0x.h
@@ -0,0 +1,207 @@
+#ifndef __LINUX_FT5X0X_TS_H__
+#define __LINUX_FT5X0X_TS_H__
+
+#define DEV_FT5206 "touch_ft5206"
+#define DEV_FT5301 "touch_ft5301"
+#define DEV_FT5302 "touch_ft5302"
+#define DEV_FT5306 "touch_ft5306"
+#define DEV_FT5406 "touch_ft5406"
+#define DEV_FT5606 "touch_ft5606"
+
+#define DEV_FT5X0X "touch_ft5x0x"
+#define TS_I2C_NAME "ft5x0x-ts"
+#define FT5406_I2C_ADDR 0x38
+#define FT5X0X_I2C_BUS 0x01
+
+enum FT5X0X_ID{
+ FT5206 =1,
+ FT5301,
+ FT5302,
+ FT5306,
+ FT5406,
+ FT5606,
+ FT5X0X,
+};
+
+struct vt1603_ts_cal_info {
+ int a1;
+ int b1;
+ int c1;
+ int a2;
+ int b2;
+ int c2;
+ int delta;
+};
+
+#define SUPPORT_POINT_NUM 10
+struct ts_event {
+ int x[SUPPORT_POINT_NUM];
+ int y[SUPPORT_POINT_NUM];
+ int tid[SUPPORT_POINT_NUM];
+ int tpoint;
+};
+
+#define TOUCH_KEY
+
+#ifdef TOUCH_KEY
+#define NUM_KEYS 4
+struct key_pos{
+ int y_lower;
+ int y_upper;
+};
+
+struct ts_key{
+ int axis;
+ int x_lower;
+ int x_upper;
+ struct key_pos ypos[NUM_KEYS];
+};
+#endif
+
+struct ft5x0x_data {
+ int id;
+ unsigned int addr;
+ const char *name;
+ u8 fw_name[64];
+ u8 cfg_name[32];
+
+ struct i2c_client *client;
+ struct input_dev *input_dev;
+ struct ts_event event;
+ struct work_struct read_work;
+ struct workqueue_struct *workqueue;
+ struct mutex ts_mutex;
+ struct kobject *kobj;
+ #ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend early_suspend;
+#endif
+ int earlysus;
+
+ int reslx;
+ int resly;
+
+ int tw;
+ int th;
+
+ int irq;
+ int irqgpio;
+ int rstgpio;
+/*
+ int igp_idx;
+ int igp_bit;
+
+ int rgp_idx;
+ int rgp_bit;
+*/
+
+ int nt;
+ int nb;
+ int xch;
+ int ych;
+ int swap;
+ int lcd_exchg;
+
+ int upg;
+ int load_cfg;
+ int dbg;
+#ifdef TOUCH_KEY
+ int tskey_used;
+ int tkey_pressed;
+ int nkeys;
+ int tkey_idx;
+ struct ts_key tkey;
+#endif
+
+};
+
+enum ft5x0x_ts_regs {
+ FT5X0X_REG_THGROUP = 0x80, /* touch threshold, related to sensitivity */
+ FT5X0X_REG_THPEAK = 0x81,
+ FT5X0X_REG_THCAL = 0x82,
+ FT5X0X_REG_THWATER = 0x83,
+ FT5X0X_REG_THTEMP = 0x84,
+ FT5X0X_REG_THDIFF = 0x85,
+ FT5X0X_REG_CTRL = 0x86,
+ FT5X0X_REG_TIMEENTERMONITOR = 0x87,
+ FT5X0X_REG_PERIODACTIVE = 0x88, /* report rate */
+ FT5X0X_REG_PERIODMONITOR = 0x89,
+ FT5X0X_REG_HEIGHT_B = 0x8a,
+ FT5X0X_REG_MAX_FRAME = 0x8b,
+ FT5X0X_REG_DIST_MOVE = 0x8c,
+ FT5X0X_REG_DIST_POINT = 0x8d,
+ FT5X0X_REG_FEG_FRAME = 0x8e,
+ FT5X0X_REG_SINGLE_CLICK_OFFSET = 0x8f,
+ FT5X0X_REG_DOUBLE_CLICK_TIME_MIN = 0x90,
+ FT5X0X_REG_SINGLE_CLICK_TIME = 0x91,
+ FT5X0X_REG_LEFT_RIGHT_OFFSET = 0x92,
+ FT5X0X_REG_UP_DOWN_OFFSET = 0x93,
+ FT5X0X_REG_DISTANCE_LEFT_RIGHT = 0x94,
+ FT5X0X_REG_DISTANCE_UP_DOWN = 0x95,
+ FT5X0X_REG_ZOOM_DIS_SQR = 0x96,
+ FT5X0X_REG_RADIAN_VALUE =0x97,
+ FT5X0X_REG_MAX_X_HIGH = 0x98,
+ FT5X0X_REG_MAX_X_LOW = 0x99,
+ FT5X0X_REG_MAX_Y_HIGH = 0x9a,
+ FT5X0X_REG_MAX_Y_LOW = 0x9b,
+ FT5X0X_REG_K_X_HIGH = 0x9c,
+ FT5X0X_REG_K_X_LOW = 0x9d,
+ FT5X0X_REG_K_Y_HIGH = 0x9e,
+ FT5X0X_REG_K_Y_LOW = 0x9f,
+ FT5X0X_REG_AUTO_CLB_MODE = 0xa0,
+ FT5X0X_REG_LIB_VERSION_H = 0xa1,
+ FT5X0X_REG_LIB_VERSION_L = 0xa2,
+ FT5X0X_REG_CIPHER = 0xa3,
+ FT5X0X_REG_MODE = 0xa4,
+ FT5X0X_REG_PMODE = 0xa5, /* Power Consume Mode */
+ FT5X0X_REG_FIRMID = 0xa6, /* Firmware version */
+ FT5X0X_REG_STATE = 0xa7,
+ FT5X0X_REG_FT5201ID = 0xa8,
+ FT5X0X_REG_ERR = 0xa9,
+ FT5X0X_REG_CLB = 0xaa,
+};
+
+//FT5X0X_REG_PMODE
+#define PMODE_ACTIVE 0x00
+#define PMODE_MONITOR 0x01
+#define PMODE_STANDBY 0x02
+#define PMODE_HIBERNATE 0x03
+
+#define DEV_NAME "wmtts"
+#define DEV_MAJOR 11
+
+#define TS_IOC_MAGIC 't'
+#define TS_IOCTL_CAL_START _IO(TS_IOC_MAGIC, 1)
+#define TS_IOCTL_CAL_DONE _IOW(TS_IOC_MAGIC, 2, int*)
+#define TS_IOCTL_GET_RAWDATA _IOR(TS_IOC_MAGIC, 3, int*)
+#define TS_IOCTL_CAL_QUIT _IOW(TS_IOC_MAGIC, 4, int*)
+#define TS_IOCTL_CAL_CAP _IOW(TS_IOC_MAGIC, 5, int*)
+#define TS_IOC_MAXNR 5
+
+extern int wmt_setsyspara(char *varname, unsigned char *varval);
+extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
+extern int wmt_i2c_xfer_continue_if_4(struct i2c_msg *msg, unsigned int num,int bus_id);
+
+//#define FT_DEBUG
+
+#undef dbg
+#ifdef FT_DEBUG
+ #define dbg(fmt,args...) printk("DBG:%s_%d:"fmt,__FUNCTION__,__LINE__,##args)
+#else
+ #define dbg(fmt,args...)
+#endif
+
+#undef dbg_err
+#define dbg_err(fmt,args...) printk("ERR:%s_%d:"fmt,__FUNCTION__,__LINE__,##args)
+
+//#define FTS_DBG
+#ifdef FTS_DBG
+#define DBG(fmt, args...) printk("[FTS]" fmt, ## args)
+#else
+#define DBG(fmt, args...) do{}while(0)
+#endif
+
+#ifndef errlog
+#define errlog(fmt, args...) printk(KERN_ERR "[%s:%d]: " fmt, __FUNCTION__,__LINE__, ## args)
+#endif
+
+#endif
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/ft5x0x/ft5x0x_upg.c b/ANDROID_3.4.5/drivers/input/touchscreen/ft5x0x/ft5x0x_upg.c
new file mode 100755
index 00000000..9db72130
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/ft5x0x/ft5x0x_upg.c
@@ -0,0 +1,506 @@
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/mount.h>
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+#include <linux/syscalls.h>
+#include <asm/unistd.h>
+#include <asm/uaccess.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include "ft5x0x.h"
+
+typedef enum
+{
+ ERR_OK,
+ ERR_MODE,
+ ERR_READID,
+ ERR_ERASE,
+ ERR_STATUS,
+ ERR_ECC,
+ ERR_DL_ERASE_FAIL,
+ ERR_DL_PROGRAM_FAIL,
+ ERR_DL_VERIFY_FAIL,
+ ERR_FMID
+}E_UPGRADE_ERR_TYPE;
+
+#define FT5X_CTPM_ID_L 0X79
+#define FT5X_CTPM_ID_H 0X03
+
+#define FT56_CTPM_ID_L 0X79
+#define FT56_CTPM_ID_H 0X06
+
+#define FTS_PACKET_LENGTH 128
+
+extern struct ft5x0x_data *pContext;
+extern int ft5x0x_i2c_rxdata(char *rxdata, int length);
+extern int ft5x0x_i2c_txdata(char *txdata, int length);
+
+static int ft5x0x_write_reg(u8 addr, u8 para)
+{
+ u8 buf[2];
+ int ret = -1;
+
+ buf[0] = addr;
+ buf[1] = para;
+ ret = ft5x0x_i2c_txdata(buf, 2);
+ if (ret <= 0) {
+ printk("write reg failed! %x ret: %d", buf[0], ret);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int ft5x0x_read_reg(u8 addr, u8 *pdata)
+{
+ int ret;
+ u8 buf[2];
+ struct i2c_msg msgs[2];
+
+ //
+ buf[0] = addr; //register address
+
+ msgs[0].addr = pContext->addr;
+ msgs[0].flags = 0 | I2C_M_NOSTART;
+ msgs[0].len = 1;
+ msgs[0].buf = buf;
+
+ msgs[1].addr = pContext->addr;
+ msgs[1].flags = I2C_M_RD;
+ msgs[1].len = 1;
+ msgs[1].buf = pdata;
+
+ //ret = wmt_i2c_xfer_continue_if_4(msgs, 2, FT5X0X_I2C_BUS);
+ ret = i2c_transfer(pContext->client->adapter, msgs, 2);
+ if (ret <= 0)
+ printk("msg %s i2c read error: %d\n", __func__, ret);
+
+ return ret;
+
+}
+
+
+/*
+[function]:
+ send a command to ctpm.
+[parameters]:
+ btcmd[in] :command code;
+ btPara1[in] :parameter 1;
+ btPara2[in] :parameter 2;
+ btPara3[in] :parameter 3;
+ num[in] :the valid input parameter numbers, if only command code needed and no parameters followed,then the num is 1;
+[return]:
+ FTS_TRUE :success;
+ FTS_FALSE :io fail;
+*/
+static u8 cmd_write(u8 *cmd,u8 num)
+{
+ return ft5x0x_i2c_txdata(cmd, num);
+}
+
+/*
+[function]:
+ write data to ctpm , the destination address is 0.
+[parameters]:
+ pbt_buf[in] :point to data buffer;
+ bt_len[in] :the data numbers;
+[return]:
+ FTS_TRUE :success;
+ FTS_FALSE :io fail;
+*/
+static u8 byte_write(u8* pbt_buf, int dw_len)
+{
+
+ return ft5x0x_i2c_txdata( pbt_buf, dw_len);
+}
+
+/*
+[function]:
+ read out data from ctpm,the destination address is 0.
+[parameters]:
+ pbt_buf[out] :point to data buffer;
+ bt_len[in] :the data numbers;
+[return]:
+ FTS_TRUE :success;
+ FTS_FALSE :io fail;
+*/
+static u8 byte_read(u8* pbt_buf, u8 bt_len)
+{
+ int ret;
+ struct i2c_msg msg[1];
+
+ msg[0].addr = pContext->addr;
+ msg[0].flags = I2C_M_RD;
+ msg[0].len = bt_len;
+ msg[0].buf = pbt_buf;
+
+ ret = i2c_transfer(pContext->client->adapter, msg, 1);
+ //ret = wmt_i2c_xfer_continue_if_4(msg, 1, FT5X0X_I2C_BUS);
+ if (ret <= 0)
+ printk("msg i2c read error: %d\n", ret);
+
+ return ret;
+}
+
+
+/*
+[function]:
+ burn the FW to ctpm.
+[parameters]:(ref. SPEC)
+ pbt_buf[in] :point to Head+FW ;
+ dw_lenth[in]:the length of the FW + 6(the Head length);
+ bt_ecc[in] :the ECC of the FW
+[return]:
+ ERR_OK :no error;
+ ERR_MODE :fail to switch to UPDATE mode;
+ ERR_READID :read id fail;
+ ERR_ERASE :erase chip fail;
+ ERR_STATUS :status error;
+ ERR_ECC :ecc error.
+*/
+static E_UPGRADE_ERR_TYPE ft5x0x_fw_upgrade(struct ft5x0x_data *ft5x0x, u8* pbt_buf, int dw_lenth)
+{
+ int i = 0,j = 0,i_ret;
+ int packet_number;
+ int temp,lenght;
+ u8 packet_buf[FTS_PACKET_LENGTH + 6];
+ u8 auc_i2c_write_buf[10];
+ u8 reg_val[2] = {0};
+ u8 ctpm_id[2] = {0};
+ u8 cmd[4];
+ u8 bt_ecc;
+
+ /*********Step 1:Reset CTPM *****/
+ /*write 0xaa to register 0xfc*/
+ ft5x0x_write_reg(0xfc,0xaa);
+ msleep(50);
+ /*write 0x55 to register 0xfc*/
+ ft5x0x_write_reg(0xfc,0x55);
+ printk("[FTS] Step 1: Reset CTPM.\n");
+ msleep(30);
+
+ /*********Step 2:Enter upgrade mode *****/
+ auc_i2c_write_buf[0] = 0x55;
+ auc_i2c_write_buf[1] = 0xaa;
+ do{
+ i ++;
+ i_ret = byte_write(auc_i2c_write_buf, 2);
+ mdelay(5);
+ }while(i_ret <= 0 && i < 5 );
+ msleep(20);
+
+ /*********Step 3:check READ-ID**********/
+ if(ft5x0x->id == FT5606){
+ ctpm_id[0] = FT56_CTPM_ID_L;
+ ctpm_id[1] = FT56_CTPM_ID_H;
+ }else{
+ ctpm_id[0] = FT5X_CTPM_ID_L;
+ ctpm_id[1] = FT5X_CTPM_ID_H;
+ }
+
+ cmd[0] = 0x90;
+ cmd[1] = 0x00;
+ cmd[2] = 0x00;
+ cmd[3] = 0x00;
+ cmd_write(cmd,4);
+ byte_read(reg_val,2);
+ if (reg_val[0] == ctpm_id[0] && reg_val[1] == ctpm_id[1]){
+ printk("[FTS] Step 3: CTPM ID,ID1 = 0x%x,ID2 = 0x%x\n",reg_val[0],reg_val[1]);
+ }else{
+ printk("[FTS] ID_ERROR: CTPM ID,ID1 = 0x%x,ID2 = 0x%x\n",reg_val[0],reg_val[1]);
+ return ERR_READID;
+ }
+
+ cmd[0] = 0xcd;
+ cmd_write(cmd,1);
+ byte_read(reg_val,1);
+ printk("[FTS] bootloader version = 0x%x\n", reg_val[0]);
+
+ /******Step 4:erase app and panel paramenter area *********/
+ cmd[0] = 0x61;
+ cmd_write(cmd,1); //erase app area
+ msleep(1500);
+ cmd[0] = 0x63;
+ cmd_write(cmd,1); //erase panel parameter area
+ msleep(100);
+ printk("[FTS] Step 4: erase. \n");
+
+ /*********Step 5:write firmware(FW) to ctpm flash*********/
+ bt_ecc = 0;
+ printk("[FTS] Step 5: start upgrade. \n");
+ dw_lenth = dw_lenth - 8;
+ packet_number = (dw_lenth) / FTS_PACKET_LENGTH;
+ packet_buf[0] = 0xbf;
+ packet_buf[1] = 0x00;
+ for (j=0;j<packet_number;j++){
+ temp = j * FTS_PACKET_LENGTH;
+ packet_buf[2] = (u8)(temp>>8);
+ packet_buf[3] = (u8)temp;
+ lenght = FTS_PACKET_LENGTH;
+ packet_buf[4] = (u8)(lenght>>8);
+ packet_buf[5] = (u8)lenght;
+
+ for (i=0;i<FTS_PACKET_LENGTH;i++){
+ packet_buf[6+i] = pbt_buf[j*FTS_PACKET_LENGTH + i];
+ bt_ecc ^= packet_buf[6+i];
+ }
+
+ byte_write(&packet_buf[0],FTS_PACKET_LENGTH + 6);
+ mdelay(FTS_PACKET_LENGTH/6 + 1);
+ if ((j * FTS_PACKET_LENGTH % 1024) == 0){
+ printk("[FTS] upgrade the 0x%x th byte.\n", ((unsigned int)j) * FTS_PACKET_LENGTH);
+ }
+ }
+
+ if ((dw_lenth) % FTS_PACKET_LENGTH > 0){
+ temp = packet_number * FTS_PACKET_LENGTH;
+ packet_buf[2] = (u8)(temp>>8);
+ packet_buf[3] = (u8)temp;
+
+ temp = (dw_lenth) % FTS_PACKET_LENGTH;
+ packet_buf[4] = (u8)(temp>>8);
+ packet_buf[5] = (u8)temp;
+
+ for (i=0;i<temp;i++){
+ packet_buf[6+i] = pbt_buf[ packet_number*FTS_PACKET_LENGTH + i];
+ bt_ecc ^= packet_buf[6+i];
+ }
+
+ byte_write(&packet_buf[0],temp+6);
+ mdelay(20);
+ }
+
+ //send the last six byte
+ for (i = 0; i<6; i++){
+ temp = 0x6ffa + i;
+ packet_buf[2] = (u8)(temp>>8);
+ packet_buf[3] = (u8)temp;
+ temp =1;
+ packet_buf[4] = (u8)(temp>>8);
+ packet_buf[5] = (u8)temp;
+ packet_buf[6] = pbt_buf[ dw_lenth + i];
+ bt_ecc ^= packet_buf[6];
+
+ byte_write(&packet_buf[0],7);
+ mdelay(20);
+ }
+
+ /*********Step 6: read out checksum********************/
+ /*send the opration head*/
+ cmd[0] = 0xcc;
+ cmd_write(cmd,1);
+ byte_read(reg_val,1);
+ printk("[FTS] Step 6:read ECC 0x%x, firmware ECC 0x%x. \n", reg_val[0], bt_ecc);
+ if(reg_val[0] != bt_ecc){
+ return ERR_ECC;
+ }
+
+ /*********Step 7: reset the new FW***********************/
+ cmd[0] = 0x07;
+ cmd_write(cmd,1);
+
+ msleep(300); //make sure CTP startup normally
+
+ return ERR_OK;
+}
+
+int ft5x0x_auto_clb(void)
+{
+ u8 uc_temp;
+ u8 i ;
+
+ printk("[FTS] start auto CLB.\n");
+ msleep(200);
+ ft5x0x_write_reg(0, 0x40);
+ msleep(100); //make sure already enter factory mode
+ ft5x0x_write_reg(2, 0x4); //write command to start calibration
+ msleep(300);
+ for(i=0;i<100;i++){
+ ft5x0x_read_reg(0,&uc_temp);
+ if ( ((uc_temp&0x70)>>4) == 0x0){ //return to normal mode, calibration finish
+ break;
+ }
+ msleep(200);
+ printk("[FTS] waiting calibration %d\n",i);
+ }
+ printk("[FTS] calibration OK.\n");
+
+ msleep(300);
+ ft5x0x_write_reg(0, 0x40); //goto factory mode
+ msleep(100); //make sure already enter factory mode
+ ft5x0x_write_reg(2, 0x5); //store CLB result
+ msleep(300);
+ ft5x0x_write_reg(0, 0x0); //return to normal mode
+ msleep(300);
+ printk("[FTS] store CLB result OK.\n");
+ return 0;
+}
+
+static int ft5x0x_get_bin_ver(const u8 *fw, int fw_szie)
+{
+ if (fw_szie > 2){
+ return fw[fw_szie - 2];
+ }else{
+ return 0xff; //default value
+ }
+ return 0xff;
+}
+
+int ft5x0x_read_fw_ver(void)
+{
+ u8 ver=0;
+ int ret=0;
+
+ ret = ft5x0x_read_reg(FT5X0X_REG_FIRMID, &ver);
+ if(ret > 0)
+ return ver;
+
+ return ret;
+}
+
+
+static int ft5x0x_get_fw_szie(const char *fw_name)
+{
+ struct file *pfile = NULL;
+ struct inode *inode;
+ unsigned long magic;
+ off_t fsize = 0;
+
+ if(fw_name == NULL){
+ dbg_err("Firmware name error.\n");
+ return -EFAULT;
+ }
+
+ if (NULL == pfile)
+ pfile = filp_open(fw_name, O_RDONLY, 0);
+
+ if (IS_ERR(pfile)) {
+ dbg_err("File open error: %s.\n", fw_name);
+ return -EIO;
+ }
+
+ inode = pfile->f_dentry->d_inode;
+ magic = inode->i_sb->s_magic;
+ fsize = inode->i_size;
+ filp_close(pfile, NULL);
+ return fsize;
+}
+
+static int ft5x0x_read_fw(const char *fw_name, u8 *buf)
+{
+ struct file *pfile = NULL;
+ struct inode *inode;
+ unsigned long magic;
+ off_t fsize;
+ loff_t pos;
+ mm_segment_t fs;
+
+ if(fw_name == NULL){
+ dbg_err("Firmware name error.\n");
+ return -EFAULT;
+ }
+
+ if (NULL == pfile)
+ pfile = filp_open(fw_name, O_RDONLY, 0);
+ if (IS_ERR(pfile)) {
+ dbg_err("File open error: %s.\n", fw_name);
+ return -EIO;
+ }
+
+ inode = pfile->f_dentry->d_inode;
+ magic = inode->i_sb->s_magic;
+ fsize = inode->i_size;
+ fs = get_fs();
+ set_fs(KERNEL_DS);
+ pos = 0;
+ vfs_read(pfile, buf, fsize, &pos);
+ filp_close(pfile, NULL);
+ set_fs(fs);
+
+ return 0;
+}
+
+#define FW_SUFFFIX ".bin"
+#define SD_UPG_BIN_PATH "/sdcard/_wmt_ft5x0x_fw_app.bin"
+#define FS_UPG_BIN_PATH "/lib/firmware/"
+
+int ft5x0x_upg_fw_bin(struct ft5x0x_data *ft5x0x, int check_ver)
+{
+ int i_ret = 0;
+ int fwsize = 0;
+ int hw_fw_ver;
+ int bin_fw_ver;
+ int do_upg;
+ u8 *pbt_buf = NULL;
+ u8 fw_path[128] = {0};
+
+ if(ft5x0x->upg)
+ sprintf(fw_path,"%s%s%s", FS_UPG_BIN_PATH, ft5x0x->fw_name,FW_SUFFFIX);//get fw binary file from filesystem
+ else
+ strcpy(fw_path,SD_UPG_BIN_PATH); //get fw binary file from SD card
+
+ fwsize = ft5x0x_get_fw_szie(fw_path);
+ if (fwsize <= 0) {
+ dbg_err("Get firmware size failed\n");
+ return -EIO;
+ }
+
+ if (fwsize < 8 || fwsize > 32 * 1024) {
+ dbg_err("FW length error\n");
+ return -EIO;
+ }
+
+ pbt_buf = kmalloc(fwsize + 1, GFP_KERNEL);
+ if (ft5x0x_read_fw(fw_path, pbt_buf)) {
+ dbg_err("Request_firmware failed\n");
+ i_ret = -EIO;
+ goto exit;
+ }
+
+ hw_fw_ver =ft5x0x_read_fw_ver();
+ if(hw_fw_ver <= 0){
+ dbg_err("Read firmware version failed\n");
+ i_ret = hw_fw_ver;
+ goto exit;
+ }
+
+ bin_fw_ver = ft5x0x_get_bin_ver(pbt_buf, fwsize);
+ printk("[FTS] hardware fw ver 0x%0x, binary ver 0x%0x\n",hw_fw_ver, bin_fw_ver);
+
+ if(check_ver){
+ if(hw_fw_ver == 0xa6 || hw_fw_ver < bin_fw_ver)
+ do_upg = 1;
+ else
+ do_upg = 0;
+ }else{
+ do_upg = 1;
+ }
+
+ if(do_upg){
+ if ((pbt_buf[fwsize - 8] ^ pbt_buf[fwsize - 6]) == 0xFF &&
+ (pbt_buf[fwsize - 7] ^ pbt_buf[fwsize - 5]) == 0xFF &&
+ (pbt_buf[fwsize - 3] ^ pbt_buf[fwsize - 4]) == 0xFF) {
+ i_ret = ft5x0x_fw_upgrade(ft5x0x, pbt_buf, fwsize);
+ if (i_ret)
+ dbg_err("Upgrade failed, i_ret=%d\n",i_ret);
+ else {
+ hw_fw_ver = ft5x0x_read_fw_ver();
+ printk("[FTS] upgrade to new version 0x%x\n", hw_fw_ver);
+ }
+ } else {
+ dbg_err("FW format error\n");
+ }
+ }
+
+ ft5x0x_auto_clb();/*start auto CLB*/
+
+exit:
+ kfree(pbt_buf);
+ return i_ret;
+}
+
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/ft5x0x/ini.c b/ANDROID_3.4.5/drivers/input/touchscreen/ft5x0x/ini.c
new file mode 100755
index 00000000..a4f8dc38
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/ft5x0x/ini.c
@@ -0,0 +1,406 @@
+#include <linux/string.h>
+#include <asm/unistd.h>
+#include <linux/slab.h>
+
+#include "ini.h"
+
+
+char CFG_SSL = '['; /* Ïî±êÖ¾·ûSection Symbol --¿É¸ù¾ÝÌØÊâÐèÒª½øÐж¨Òå¸ü¸Ä£¬Èç { }µÈ*/
+char CFG_SSR = ']'; /* Ïî±êÖ¾·ûSection Symbol --¿É¸ù¾ÝÌØÊâÐèÒª½øÐж¨Òå¸ü¸Ä£¬Èç { }µÈ*/
+char CFG_NIS = ':'; /* name Óë index Ö®¼äµÄ·Ö¸ô·û */
+char CFG_NTS = '#'; /* ×¢ÊÍ·û*/
+
+static char * ini_str_trim_r(char * buf);
+static char * ini_str_trim_l(char * buf);
+static int ini_file_get_line(char *filedata, char *buffer, int maxlen);
+static int ini_split_key_value(char *buf, char **key, char **val);
+static long atol(char *nptr);
+
+
+/*************************************************************
+Function: »ñµÃkeyµÄÖµ
+Input: char * filedata¡¡Îļþ£»char * section¡¡ÏîÖµ£»char * key¡¡¼üÖµ
+Output: char * value¡¡keyµÄÖµ
+Return: 0 SUCCESS
+ -1 δÕÒµ½section
+ -2 δÕÒµ½key
+ -10 Îļþ´ò¿ªÊ§°Ü
+ -12 ¶ÁÈ¡Îļþʧ°Ü
+ -14 Îļþ¸ñʽ´íÎó
+ -22 ³¬³ö»º³åÇø´óС
+Note:
+*************************************************************/
+int ini_get_key(char *filedata, char * section, char * key, char * value)
+{
+ //char buf1[MAX_CFG_BUF + 1], buf2[MAX_CFG_BUF + 1];
+ char *buf1, *buf2;
+ char *key_ptr, *val_ptr;
+ int n, ret;
+ int dataoff = 0;
+
+ *value='\0';
+
+ buf1 = kzalloc(MAX_CFG_BUF + 1, GFP_KERNEL);
+ if(!buf1){
+ printk("buf1: mem alloc failed.\n");
+ return -ENOMEM;
+ }
+ buf2 = kzalloc(MAX_CFG_BUF + 1, GFP_KERNEL);
+ if(!buf2){
+ printk("buf2: mem alloc failed.\n");
+ kfree(buf1);
+ return -ENOMEM;
+ }
+
+ while(1) { /* ËÑÕÒÏîsection */
+ ret = CFG_ERR_READ_FILE;
+ n = ini_file_get_line(filedata+dataoff, buf1, MAX_CFG_BUF);
+ dataoff += n;
+ if(n < -1)
+ goto r_cfg_end;
+ ret = CFG_SECTION_NOT_FOUND;
+ if(n < 0)
+ goto r_cfg_end; /* Îļþβ£¬Î´·¢ÏÖ */
+
+ n = strlen(ini_str_trim_l(ini_str_trim_r(buf1)));
+ if(n == 0 || buf1[0] == CFG_NTS)
+ continue; /* ¿ÕÐÐ »ò ×¢ÊÍÐÐ */
+
+ ret = CFG_ERR_FILE_FORMAT;
+ if(n > 2 && ((buf1[0] == CFG_SSL && buf1[n-1] != CFG_SSR)))
+ goto r_cfg_end;
+ if(buf1[0] == CFG_SSL) {
+ buf1[n-1] = 0x00;
+ if(strcmp(buf1+1, section) == 0)
+ break; /* ÕÒµ½Ïîsection */
+ }
+ }
+
+ while(1){ /* ËÑÕÒkey */
+ ret = CFG_ERR_READ_FILE;
+ n = ini_file_get_line(filedata+dataoff, buf1, MAX_CFG_BUF);
+ dataoff += n;
+ if(n < -1)
+ goto r_cfg_end;
+ ret = CFG_KEY_NOT_FOUND;
+ if(n < 0)
+ goto r_cfg_end;/* Îļþβ£¬Î´·¢ÏÖkey */
+
+ n = strlen(ini_str_trim_l(ini_str_trim_r(buf1)));
+ if(n == 0 || buf1[0] == CFG_NTS)
+ continue; /* ¿ÕÐÐ »ò ×¢ÊÍÐÐ */
+ ret = CFG_KEY_NOT_FOUND;
+ if(buf1[0] == CFG_SSL)
+ goto r_cfg_end;
+ if(buf1[n-1] == '+') { /* Óö+ºÅ±íʾÏÂÒ»ÐмÌÐø */
+ buf1[n-1] = 0x00;
+ while(1) {
+ ret = CFG_ERR_READ_FILE;
+ n = ini_file_get_line(filedata+dataoff, buf2, MAX_CFG_BUF);
+ dataoff += n;
+ if(n < -1)
+ goto r_cfg_end;
+ if(n < 0)
+ break;/* Îļþ½áÊø */
+
+ n = strlen(ini_str_trim_r(buf2));
+ ret = CFG_ERR_EXCEED_BUF_SIZE;
+ if(n > 0 && buf2[n-1] == '+'){/* Óö+ºÅ±íʾÏÂÒ»ÐмÌÐø */
+ buf2[n-1] = 0x00;
+ if( (strlen(buf1) + strlen(buf2)) > MAX_CFG_BUF)
+ goto r_cfg_end;
+ strcat(buf1, buf2);
+ continue;
+ }
+ if(strlen(buf1) + strlen(buf2) > MAX_CFG_BUF)
+ goto r_cfg_end;
+ strcat(buf1, buf2);
+ break;
+ }
+ }
+ ret = CFG_ERR_FILE_FORMAT;
+ if(ini_split_key_value(buf1, &key_ptr, &val_ptr) != 1)
+ goto r_cfg_end;
+ ini_str_trim_l(ini_str_trim_r(key_ptr));
+ if(strcmp(key_ptr, key) != 0)
+ continue; /* ºÍkeyÖµ²»Æ¥Åä */
+ strcpy(value, val_ptr);
+ break;
+ }
+ ret = CFG_OK;
+r_cfg_end:
+ //if(fp != NULL) fclose(fp);
+ kfree(buf1);
+ kfree(buf2);
+ return ret;
+}
+/*************************************************************
+Function: »ñµÃËùÓÐsection
+Input: char *filename¡¡Îļþ,int max ×î´ó¿É·µ»ØµÄsectionµÄ¸öÊý
+Output: char *sections[]¡¡´æ·ÅsectionÃû×Ö
+Return: ·µ»Øsection¸öÊý¡£Èô³ö´í£¬·µ»Ø¸ºÊý¡£
+ -10 Îļþ´ò¿ª³ö´í
+ -12 Îļþ¶ÁÈ¡´íÎó
+ -14 Îļþ¸ñʽ´íÎó
+Note:
+*************************************************************/
+int ini_get_sections(char *filedata, unsigned char * sections[], int max)
+{
+ //FILE *fp;
+ char buf1[MAX_CFG_BUF + 1];
+ int n, n_sections = 0, ret;
+ int dataoff = 0;
+
+// if((fp = fopen(filename, "rb")) == NULL)
+// return CFG_ERR_OPEN_FILE;
+
+ while(1) {/*ËÑÕÒÏîsection */
+ ret = CFG_ERR_READ_FILE;
+ n = ini_file_get_line(filedata+dataoff, buf1, MAX_CFG_BUF);
+ dataoff += n;
+ if(n < -1)
+ goto cfg_scts_end;
+ if(n < 0)
+ break;/* Îļþβ */
+ n = strlen(ini_str_trim_l(ini_str_trim_r(buf1)));
+ if(n == 0 || buf1[0] == CFG_NTS)
+ continue; /* ¿ÕÐÐ »ò ×¢ÊÍÐÐ */
+ ret = CFG_ERR_FILE_FORMAT;
+ if(n > 2 && ((buf1[0] == CFG_SSL && buf1[n-1] != CFG_SSR)))
+ goto cfg_scts_end;
+ if(buf1[0] == CFG_SSL) {
+ if (max!=0){
+ buf1[n-1] = 0x00;
+ strcpy((char *)sections[n_sections], buf1+1);
+ if (n_sections>=max)
+ break; /* ³¬¹ý¿É·µ»Ø×î´ó¸öÊý */
+ }
+ n_sections++;
+ }
+
+ }
+ ret = n_sections;
+cfg_scts_end:
+// if(fp != NULL)
+// fclose(fp);
+ return ret;
+}
+
+
+/*************************************************************
+Function: È¥³ý×Ö·û´®ÓұߵĿÕ×Ö·û
+Input: char * buf ×Ö·û´®Ö¸Õë
+Output:
+Return: ×Ö·û´®Ö¸Õë
+Note:
+*************************************************************/
+static char * ini_str_trim_r(char * buf)
+{
+ int len,i;
+ char tmp[128];
+
+ memset(tmp, 0, sizeof(tmp));
+ len = strlen(buf);
+// tmp = (char *)malloc(len);
+
+ memset(tmp,0x00,len);
+ for(i = 0;i < len;i++) {
+ if (buf[i] !=' ')
+ break;
+ }
+ if (i < len) {
+ strncpy(tmp,(buf+i),(len-i));
+ }
+ strncpy(buf,tmp,len);
+// free(tmp);
+ return buf;
+}
+
+/*************************************************************
+Function: È¥³ý×Ö·û´®×ó±ßµÄ¿Õ×Ö·û
+Input: char * buf ×Ö·û´®Ö¸Õë
+Output:
+Return: ×Ö·û´®Ö¸Õë
+Note:
+*************************************************************/
+static char * ini_str_trim_l(char * buf)
+{
+ int len,i;
+ char tmp[128];
+
+ memset(tmp, 0, sizeof(tmp));
+ len = strlen(buf);
+ //tmp = (char *)malloc(len);
+
+ memset(tmp,0x00,len);
+
+ for(i = 0;i < len;i++) {
+ if (buf[len-i-1] !=' ')
+ break;
+ }
+ if (i < len) {
+ strncpy(tmp,buf,len-i);
+ }
+ strncpy(buf,tmp,len);
+ //free(tmp);
+ return buf;
+}
+/*************************************************************
+Function: ´ÓÎļþÖжÁÈ¡Ò»ÐÐ
+Input: FILE *fp Îļþ¾ä±ú£»int maxlen »º³åÇø×î´ó³¤¶È
+Output: char *buffer Ò»ÐÐ×Ö·û´®
+Return: >0 ʵ¼Ê¶ÁµÄ³¤¶È
+ -1 Îļþ½áÊø
+ -2 ¶ÁÎļþ³ö´í
+Note:
+*************************************************************/
+static int ini_file_get_line(char *filedata, char *buffer, int maxlen)
+{
+ int i, j;
+ char ch1;
+
+ for(i=0, j=0; i<maxlen; j++) {
+ ch1 = filedata[j];
+ if(ch1 == '\n' || ch1 == 0x00)
+ break; /* »»ÐÐ */
+ if(ch1 == '\f' || ch1 == 0x1A) { /* '\f':»»Ò³·ûÒ²ËãÓÐЧ×Ö·û */
+ buffer[i++] = ch1;
+ break;
+ }
+ if(ch1 != '\r') buffer[i++] = ch1; /* ºöÂԻسµ·û */
+ }
+ buffer[i] = '\0';
+ return i+2;
+}
+/*************************************************************
+Function: ·ÖÀëkeyºÍvalue
+ key=val
+ jack = liaoyuewang
+ | | |
+ k1 k2 i
+Input: char *buf
+Output: char **key, char **val
+Return: 1 --- ok
+ 0 --- blank line
+ -1 --- no key, "= val"
+ -2 --- only key, no '='
+Note:
+*************************************************************/
+static int ini_split_key_value(char *buf, char **key, char **val)
+{
+ int i, k1, k2, n;
+
+ if((n = strlen((char *)buf)) < 1)
+ return 0;
+ for(i = 0; i < n; i++)
+ if(buf[i] != ' ' && buf[i] != '\t')
+ break;
+
+ if(i >= n)
+ return 0;
+
+ if(buf[i] == '=')
+ return -1;
+
+ k1 = i;
+ for(i++; i < n; i++)
+ if(buf[i] == '=')
+ break;
+
+ if(i >= n)
+ return -2;
+ k2 = i;
+
+ for(i++; i < n; i++)
+ if(buf[i] != ' ' && buf[i] != '\t')
+ break;
+
+ buf[k2] = '\0';
+
+ *key = buf + k1;
+ *val = buf + i;
+ return 1;
+}
+
+int my_atoi(const char *str)
+{
+ int result = 0;
+ int signal = 1; /* ĬÈÏΪÕýÊý */
+ if((*str>='0'&&*str<='9')||*str=='-'||*str=='+') {
+ if(*str=='-'||*str=='+') {
+ if(*str=='-')
+ signal = -1; /*ÊäÈ븺Êý*/
+ str++;
+ }
+ }
+ else
+ return 0;
+ /*¿ªÊ¼×ª»»*/
+ while(*str>='0' && *str<='9')
+ result = result*10 + (*str++ - '0' );
+
+ return signal*result;
+}
+
+int isspace(int x)
+{
+ if(x==' '||x=='\t'||x=='\n'||x=='\f'||x=='\b'||x=='\r')
+ return 1;
+ else
+ return 0;
+}
+
+int isdigit(int x)
+{
+ if(x<='9' && x>='0')
+ return 1;
+ else
+ return 0;
+
+}
+
+static long atol(char *nptr)
+{
+ int c; /* current char */
+ long total; /* current total */
+ int sign; /* if ''-'', then negative, otherwise positive */
+ /* skip whitespace */
+ while ( isspace((int)(unsigned char)*nptr) )
+ ++nptr;
+ c = (int)(unsigned char)*nptr++;
+ sign = c; /* save sign indication */
+ if (c == '-' || c == '+')
+ c = (int)(unsigned char)*nptr++; /* skip sign */
+ total = 0;
+ while (isdigit(c)) {
+ total = 10 * total + (c - '0'); /* accumulate digit */
+ c = (int)(unsigned char)*nptr++; /* get next char */
+ }
+ if (sign == '-')
+ return -total;
+ else
+ return total; /* return result, negated if necessary */
+}
+/***
+*int atoi(char *nptr) - Convert string to long
+*
+*Purpose:
+* Converts ASCII string pointed to by nptr to binary.
+* Overflow is not detected. Because of this, we can just use
+* atol().
+*
+*Entry:
+* nptr = ptr to string to convert
+*
+*Exit:
+* return int value of the string
+*
+*Exceptions:
+* None - overflow is not detected.
+*
+*******************************************************************************/
+int atoi(char *nptr)
+{
+ return (int)atol(nptr);
+}
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/ft5x0x/ini.h b/ANDROID_3.4.5/drivers/input/touchscreen/ft5x0x/ini.h
new file mode 100755
index 00000000..72434b53
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/ft5x0x/ini.h
@@ -0,0 +1,43 @@
+#ifndef INI_H
+#define INI_H
+
+#define MAX_CFG_BUF 512
+#define SUCCESS 0
+/* return value */
+#define CFG_OK SUCCESS
+#define CFG_SECTION_NOT_FOUND -1
+#define CFG_KEY_NOT_FOUND -2
+#define CFG_ERR -10
+
+#define CFG_ERR_OPEN_FILE -10
+#define CFG_ERR_CREATE_FILE -11
+#define CFG_ERR_READ_FILE -12
+#define CFG_ERR_WRITE_FILE -13
+#define CFG_ERR_FILE_FORMAT -14
+
+
+#define CFG_ERR_EXCEED_BUF_SIZE -22
+
+#define COPYF_OK SUCCESS
+#define COPYF_ERR_OPEN_FILE -10
+#define COPYF_ERR_CREATE_FILE -11
+#define COPYF_ERR_READ_FILE -12
+#define COPYF_ERR_WRITE_FILE -13
+
+
+struct ini_key_location {
+ int ini_section_line_no;
+ int ini_key_line_no;
+ int ini_key_lines;
+};
+
+
+int ini_get_key(char *filedata, char * section, char * key, char * value);
+int ini_get_sections(char *filedata, unsigned char * sections[], int max);
+
+int ini_split_section(char *section, char **name, char **index);
+//int ini_join_section(char **section, char *name, char *index);
+
+int atoi(char *nptr);
+
+#endif
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/Kconfig b/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/Kconfig
new file mode 100755
index 00000000..eb11a558
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/Kconfig
@@ -0,0 +1,11 @@
+config TOUCHSCREEN_FT6X0X
+ tristate "FT5X0X Capacity Touchscreen Device Support"
+ default y
+ depends on ARCH_WMT
+ ---help---
+ Say Y here if you have an WMT based board with touchscreen
+ attached to it.
+ If unsure, say N.
+ To compile this driver as a module, choose M here: the
+ module will be called ft5x0x.
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/Makefile b/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/Makefile
new file mode 100755
index 00000000..859008b8
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/Makefile
@@ -0,0 +1,34 @@
+KERNELDIR=../../../../
+CROSS = arm_1103_le-
+CC= $(CROSS)gcc
+LD= $(CROSS)ld
+STRIP = $(CROSS)strip
+
+DEBUG = n
+
+# Add your debugging flag (or not) to EXTRA_CFLAGS
+ifeq ($(DEBUG),y)
+# DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+DEBFLAGS = -O0 -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+
+else
+ DEBFLAGS = -O2 -Wall
+endif
+
+EXTRA_CFLAGS += $(DEBFLAGS)
+
+
+MY_MODULE_NAME=s_wmt_ts_ft6x0x
+
+#obj-$(CONFIG_TOUCHSCREEN_FT5X0X) := $(MY_MODULE_NAME).o
+obj-m := $(MY_MODULE_NAME).o
+$(MY_MODULE_NAME)-objs := ft5x0x.o ft5x0x_upg.o ft5402_config.o ft6x06_ex_fun.o ini.o ft6x06_ts.o
+
+default:
+ $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules
+ $(STRIP) --strip-debug $(MY_MODULE_NAME).ko
+ @rm -rf *.o *~ core .depend .*.cmd *.mod.c .tmp_versions *.order *.symvers
+
+clean:
+ @rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.order *.symvers
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/focaltech_ctl.h b/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/focaltech_ctl.h
new file mode 100755
index 00000000..7c58a15a
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/focaltech_ctl.h
@@ -0,0 +1,27 @@
+#ifndef __FOCALTECH_CTL_H__
+#define __FOCALTECH_CTL_H__
+
+#define FT_RW_IIC_DRV "ft_rw_iic_drv"
+#define FT_RW_IIC_DRV_MAJOR 210 /*Ô¤ÉèµÄft_rw_iic_drvµÄÖ÷É豸ºÅ*/
+
+#define FT_I2C_RDWR_MAX_QUEUE 36
+#define FT_I2C_SLAVEADDR 11
+#define FT_I2C_RW 12
+#define FT_RESET_TP 13
+
+typedef struct ft_rw_i2c
+{
+ u8 *buf;
+ u8 flag; /*0-write 1-read*/
+ __u16 length; //the length of data
+}*pft_rw_i2c;
+
+typedef struct ft_rw_i2c_queue
+{
+ struct ft_rw_i2c __user *i2c_queue;
+ int queuenum;
+}*pft_rw_i2c_queue;
+
+int ft_rw_iic_drv_init(struct i2c_client *client);
+void ft_rw_iic_drv_exit(void);
+#endif \ No newline at end of file
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ft5402_config.c b/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ft5402_config.c
new file mode 100755
index 00000000..58683ebd
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ft5402_config.c
@@ -0,0 +1,2295 @@
+#include "ft5402_config.h"
+//#include <linux/i2c/ft5402_ts.h>
+
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/semaphore.h>
+#include <linux/mutex.h>
+#include <linux/interrupt.h>
+#include <mach/irqs.h>
+
+#include <linux/syscalls.h>
+#include <asm/unistd.h>
+#include <asm/uaccess.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+
+#include "ini.h"
+#include "ft5402_ini_config.h"
+#include "ft5x0x.h"
+
+
+extern int ft5x0x_i2c_txdata(char *txdata, int length);
+
+int ft5402_write_reg(struct i2c_client * client, u8 regaddr, u8 regvalue)
+{
+ unsigned char buf[2] = {0};
+ buf[0] = regaddr;
+ buf[1] = regvalue;
+
+ return ft5x0x_i2c_txdata(buf, 2);
+}
+
+int ft5402_read_reg(struct i2c_client * client, u8 regaddr, u8 * regvalue)
+{
+ int ret;
+
+ struct i2c_msg msgs[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = 1,
+ .buf = &regaddr,
+ },
+ {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = 1,
+ .buf = regvalue,
+ },
+ };
+ ret = i2c_transfer(client->adapter, msgs, 2);
+ if (ret < 0)
+ pr_err("function:%s. i2c read error: %d\n", __func__, ret);
+ return ret;
+}
+
+/*set tx order
+*@txNO: offset from tx order start
+*@txNO1: tx NO.
+*/
+static int ft5402_set_tx_order(struct i2c_client * client, u8 txNO, u8 txNO1)
+{
+ unsigned char ReCode = 0;
+ if (txNO < FT5402_TX_TEST_MODE_1)
+ ReCode = ft5402_write_reg(client, FT5402_REG_TX_ORDER_START + txNO,
+ txNO1);
+ else {
+ ReCode = ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE_2<<4); /*enter Test mode 2*/
+ if (ReCode >= 0)
+ ReCode = ft5402_write_reg(client,
+ FT5402_REG_TX_ORDER_START + txNO - FT5402_TX_TEST_MODE_1,
+ txNO1);
+ ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE<<4); /*enter Test mode*/
+ }
+ return ReCode;
+}
+
+/*set tx order
+*@txNO: offset from tx order start
+*@pTxNo: return value of tx NO.
+*/
+static int ft5402_get_tx_order(struct i2c_client * client, u8 txNO, u8 *pTxNo)
+{
+ unsigned char ReCode = 0;
+ if (txNO < FT5402_TX_TEST_MODE_1)
+ ReCode = ft5402_read_reg(client, FT5402_REG_TX_ORDER_START + txNO,
+ pTxNo);
+ else {
+ ReCode = ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE_2<<4); /*enter Test mode 2*/
+ if(ReCode >= 0)
+ ReCode = ft5402_read_reg(client,
+ FT5402_REG_TX_ORDER_START + txNO - FT5402_TX_TEST_MODE_1,
+ pTxNo);
+ ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE<<4); /*enter Test mode*/
+ }
+ return ReCode;
+}
+
+/*set tx cap
+*@txNO: tx NO.
+*@cap_value: value of cap
+*/
+static int ft5402_set_tx_cap(struct i2c_client * client, u8 txNO, u8 cap_value)
+{
+ unsigned char ReCode = 0;
+ if (txNO < FT5402_TX_TEST_MODE_1)
+ ReCode = ft5402_write_reg(client, FT5402_REG_TX_CAP_START + txNO,
+ cap_value);
+ else {
+ ReCode = ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE_2<<4); /*enter Test mode 2*/
+ if (ReCode >= 0)
+ ReCode = ft5402_write_reg(client,
+ FT5402_REG_TX_CAP_START + txNO - FT5402_TX_TEST_MODE_1,
+ cap_value);
+ ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE<<4); /*enter Test mode*/
+ }
+ return ReCode;
+}
+
+/*get tx cap*/
+static int ft5402_get_tx_cap(struct i2c_client * client, u8 txNO, u8 *pCap)
+{
+ unsigned char ReCode = 0;
+ if (txNO < FT5402_TX_TEST_MODE_1)
+ ReCode = ft5402_read_reg(client, FT5402_REG_TX_CAP_START + txNO,
+ pCap);
+ else {
+ ReCode = ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE_2<<4); /*enter Test mode 2*/
+ if (ReCode >= 0)
+ ReCode = ft5402_read_reg(client,
+ FT5402_REG_TX_CAP_START + txNO - FT5402_TX_TEST_MODE_1,
+ pCap);
+ ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE<<4); /*enter Test mode*/
+ }
+ return ReCode;
+}
+
+/*set tx offset*/
+static int ft5402_set_tx_offset(struct i2c_client * client, u8 txNO, u8 offset_value)
+{
+ unsigned char temp=0;
+ unsigned char ReCode = 0;
+ if (txNO < FT5402_TX_TEST_MODE_1) {
+ ReCode = ft5402_read_reg(client,
+ FT5402_REG_TX_OFFSET_START + (txNO>>1), &temp);
+ if (ReCode >= 0) {
+ if (txNO%2 == 0)
+ ReCode = ft5402_write_reg(client,
+ FT5402_REG_TX_OFFSET_START + (txNO>>1),
+ (temp&0xf0) + (offset_value&0x0f));
+ else
+ ReCode = ft5402_write_reg(client,
+ FT5402_REG_TX_OFFSET_START + (txNO>>1),
+ (temp&0x0f) + (offset_value<<4));
+ }
+ } else {
+ ReCode = ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE_2<<4); /*enter Test mode 2*/
+ if (ReCode >= 0) {
+ ReCode = ft5402_read_reg(client,
+ FT5402_REG_DEVICE_MODE+((txNO-FT5402_TX_TEST_MODE_1)>>1),
+ &temp); /*enter Test mode 2*/
+ if (ReCode >= 0) {
+ if(txNO%2 == 0)
+ ReCode = ft5402_write_reg(client,
+ FT5402_REG_TX_OFFSET_START+((txNO-FT5402_TX_TEST_MODE_1)>>1),
+ (temp&0xf0)+(offset_value&0x0f));
+ else
+ ReCode = ft5402_write_reg(client,
+ FT5402_REG_TX_OFFSET_START+((txNO-FT5402_TX_TEST_MODE_1)>>1),
+ (temp&0xf0)+(offset_value<<4));
+ }
+ }
+ ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE<<4); /*enter Test mode*/
+ }
+
+ return ReCode;
+}
+
+/*get tx offset*/
+static int ft5402_get_tx_offset(struct i2c_client * client, u8 txNO, u8 *pOffset)
+{
+ unsigned char temp=0;
+ unsigned char ReCode = 0;
+ if (txNO < FT5402_TX_TEST_MODE_1)
+ ReCode = ft5402_read_reg(client,
+ FT5402_REG_TX_OFFSET_START + (txNO>>1), &temp);
+ else {
+ ReCode = ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE_2<<4); /*enter Test mode 2*/
+ if (ReCode >= 0)
+ ReCode = ft5402_read_reg(client,
+ FT5402_REG_TX_OFFSET_START+((txNO-FT5402_TX_TEST_MODE_1)>>1),
+ &temp);
+ ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE<<4); /*enter Test mode*/
+ }
+
+ if (ReCode >= 0)
+ (txNO%2 == 0) ? (*pOffset = (temp&0x0f)) : (*pOffset = (temp>>4));
+ return ReCode;
+}
+
+/*set rx order*/
+static int ft5402_set_rx_order(struct i2c_client * client, u8 rxNO, u8 rxNO1)
+{
+ unsigned char ReCode = 0;
+ ReCode = ft5402_write_reg(client, FT5402_REG_RX_ORDER_START + rxNO,
+ rxNO1);
+ return ReCode;
+}
+
+/*get rx order*/
+static int ft5402_get_rx_order(struct i2c_client * client, u8 rxNO, u8 *prxNO1)
+{
+ unsigned char ReCode = 0;
+ ReCode = ft5402_read_reg(client, FT5402_REG_RX_ORDER_START + rxNO,
+ prxNO1);
+ return ReCode;
+}
+
+/*set rx cap*/
+static int ft5402_set_rx_cap(struct i2c_client * client, u8 rxNO, u8 cap_value)
+{
+ unsigned char ReCode = 0;
+ if (rxNO < FT5402_RX_TEST_MODE_1)
+ ReCode = ft5402_write_reg(client, FT5402_REG_RX_CAP_START + rxNO,
+ cap_value);
+ else {
+ ReCode = ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE_2<<4); /*enter Test mode 2*/
+ if(ReCode >= 0)
+ ReCode = ft5402_write_reg(client,
+ FT5402_REG_RX_CAP_START + rxNO - FT5402_RX_TEST_MODE_1,
+ cap_value);
+ ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE<<4); /*enter Test mode*/
+ }
+
+ return ReCode;
+}
+
+/*get rx cap*/
+static int ft5402_get_rx_cap(struct i2c_client * client, u8 rxNO, u8 *pCap)
+{
+ unsigned char ReCode = 0;
+ if (rxNO < FT5402_RX_TEST_MODE_1)
+ ReCode = ft5402_read_reg(client, FT5402_REG_RX_CAP_START + rxNO,
+ pCap);
+ else {
+ ReCode = ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE_2<<4); /*enter Test mode 2*/
+ if(ReCode >= 0)
+ ReCode = ft5402_read_reg(client,
+ FT5402_REG_RX_CAP_START + rxNO - FT5402_RX_TEST_MODE_1,
+ pCap);
+ ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE<<4); /*enter Test mode*/
+ }
+
+ return ReCode;
+}
+
+/*set rx offset*/
+static int ft5402_set_rx_offset(struct i2c_client * client, u8 rxNO, u8 offset_value)
+{
+ unsigned char temp=0;
+ unsigned char ReCode = 0;
+ if (rxNO < FT5402_RX_TEST_MODE_1) {
+ ReCode = ft5402_read_reg(client,
+ FT5402_REG_RX_OFFSET_START + (rxNO>>1), &temp);
+ if (ReCode >= 0) {
+ if (rxNO%2 == 0)
+ ReCode = ft5402_write_reg(client,
+ FT5402_REG_RX_OFFSET_START + (rxNO>>1),
+ (temp&0xf0) + (offset_value&0x0f));
+ else
+ ReCode = ft5402_write_reg(client,
+ FT5402_REG_RX_OFFSET_START + (rxNO>>1),
+ (temp&0x0f) + (offset_value<<4));
+ }
+ }
+ else {
+ ReCode = ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE_2<<4); /*enter Test mode 2*/
+ if (ReCode >= 0) {
+ ReCode = ft5402_read_reg(client,
+ FT5402_REG_DEVICE_MODE+((rxNO-FT5402_RX_TEST_MODE_1)>>1),
+ &temp); /*enter Test mode 2*/
+ if (ReCode >= 0) {
+ if (rxNO%2 == 0)
+ ReCode = ft5402_write_reg(client,
+ FT5402_REG_RX_OFFSET_START+((rxNO-FT5402_RX_TEST_MODE_1)>>1),
+ (temp&0xf0)+(offset_value&0x0f));
+ else
+ ReCode = ft5402_write_reg(client,
+ FT5402_REG_RX_OFFSET_START+((rxNO-FT5402_RX_TEST_MODE_1)>>1),
+ (temp&0xf0)+(offset_value<<4));
+ }
+ }
+ ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE<<4); /*enter Test mode*/
+ }
+
+ return ReCode;
+}
+
+/*get rx offset*/
+static int ft5402_get_rx_offset(struct i2c_client * client, u8 rxNO, u8 *pOffset)
+{
+ unsigned char temp = 0;
+ unsigned char ReCode = 0;
+ if (rxNO < FT5402_RX_TEST_MODE_1)
+ ReCode = ft5402_read_reg(client,
+ FT5402_REG_RX_OFFSET_START + (rxNO>>1), &temp);
+ else {
+ ReCode = ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE_2<<4); /*enter Test mode 2*/
+ if (ReCode >= 0)
+ ReCode = ft5402_read_reg(client,
+ FT5402_REG_RX_OFFSET_START+((rxNO-FT5402_RX_TEST_MODE_1)>>1),
+ &temp);
+
+ ft5402_write_reg(client, FT5402_REG_DEVICE_MODE,
+ FT5402_REG_TEST_MODE<<4); /*enter Test mode*/
+ }
+
+ if (ReCode >= 0) {
+ if (0 == (rxNO%2))
+ *pOffset = (temp&0x0f);
+ else
+ *pOffset = (temp>>4);
+ }
+
+ return ReCode;
+}
+
+/*set tx num*/
+static int ft5402_set_tx_num(struct i2c_client *client, u8 txnum)
+{
+ return ft5402_write_reg(client, FT5402_REG_TX_NUM, txnum);
+}
+
+/*get tx num*/
+static int ft5402_get_tx_num(struct i2c_client *client, u8 *ptxnum)
+{
+ return ft5402_read_reg(client, FT5402_REG_TX_NUM, ptxnum);
+}
+
+/*set rx num*/
+static int ft5402_set_rx_num(struct i2c_client *client, u8 rxnum)
+{
+ return ft5402_write_reg(client, FT5402_REG_RX_NUM, rxnum);
+}
+
+/*get rx num*/
+static int ft5402_get_rx_num(struct i2c_client *client, u8 *prxnum)
+{
+ return ft5402_read_reg(client, FT5402_REG_RX_NUM, prxnum);
+}
+
+/*set resolution*/
+static int ft5402_set_Resolution(struct i2c_client *client, u16 x, u16 y)
+{
+ unsigned char cRet = 0;
+ cRet &= ft5402_write_reg(client,
+ FT5402_REG_RESOLUTION_X_H, ((unsigned char)(x>>8)));
+ cRet &= ft5402_write_reg(client,
+ FT5402_REG_RESOLUTION_X_L, ((unsigned char)(x&0x00ff)));
+
+ cRet &= ft5402_write_reg(client,
+ FT5402_REG_RESOLUTION_Y_H, ((unsigned char)(y>>8)));
+ cRet &= ft5402_write_reg(client,
+ FT5402_REG_RESOLUTION_Y_L, ((unsigned char)(y&0x00ff)));
+
+ return cRet;
+}
+
+/*get resolution*/
+static int ft5402_get_Resolution(struct i2c_client *client,
+ u16 *px, u16 *py)
+{
+ unsigned char cRet = 0, temp1 = 0, temp2 = 0;
+ cRet &= ft5402_read_reg(client,
+ FT5402_REG_RESOLUTION_X_H, &temp1);
+ cRet &= ft5402_read_reg(client,
+ FT5402_REG_RESOLUTION_X_L, &temp2);
+ (*px) = (((u16)temp1) << 8) | ((u16)temp2);
+
+ cRet &= ft5402_read_reg(client,
+ FT5402_REG_RESOLUTION_Y_H, &temp1);
+ cRet &= ft5402_read_reg(client,
+ FT5402_REG_RESOLUTION_Y_L, &temp2);
+ (*py) = (((u16)temp1) << 8) | ((u16)temp2);
+
+ return cRet;
+}
+
+
+/*set voltage*/
+static int ft5402_set_vol(struct i2c_client *client, u8 Vol)
+{
+ return ft5402_write_reg(client, FT5402_REG_VOLTAGE, Vol);
+}
+
+/*get voltage*/
+static int ft5402_get_vol(struct i2c_client *client, u8 *pVol)
+{
+ return ft5402_read_reg(client, FT5402_REG_VOLTAGE, pVol);
+}
+
+/*set gain*/
+static int ft5402_set_gain(struct i2c_client *client, u8 Gain)
+{
+ return ft5402_write_reg(client, FT5402_REG_GAIN, Gain);
+}
+
+/*get gain*/
+static int ft5402_get_gain(struct i2c_client *client, u8 *pGain)
+{
+ return ft5402_read_reg(client, FT5402_REG_GAIN, pGain);
+}
+
+/*get start rx*/
+static int ft5402_get_start_rx(struct i2c_client *client, u8 *pRx)
+{
+ return ft5402_read_reg(client, FT5402_REG_START_RX, pRx);
+}
+
+
+/*get adc target*/
+static int ft5402_get_adc_target(struct i2c_client *client, u16 *pvalue)
+{
+ int err = 0;
+ u8 tmp1, tmp2;
+ err = ft5402_read_reg(client, FT5402_REG_ADC_TARGET_HIGH,
+ &tmp1);
+ if (err < 0)
+ dev_err(&client->dev, "%s:get adc target high failed\n",
+ __func__);
+ err = ft5402_read_reg(client, FT5402_REG_ADC_TARGET_LOW,
+ &tmp2);
+ if (err < 0)
+ dev_err(&client->dev, "%s:get adc target low failed\n",
+ __func__);
+
+ *pvalue = ((u16)tmp1<<8) + (u16)tmp2;
+ return err;
+}
+
+static int ft5402_set_face_detect_statistics_tx_num(struct i2c_client *client, u8 prevalue)
+{
+ return ft5402_write_reg(client, FT5402_REG_FACE_DETECT_STATISTICS_TX_NUM,
+ prevalue);
+}
+
+static int ft5402_get_face_detect_statistics_tx_num(struct i2c_client *client, u8 *pprevalue)
+{
+ return ft5402_read_reg(client, FT5402_REG_FACE_DETECT_STATISTICS_TX_NUM,
+ pprevalue);
+}
+
+static int ft5402_set_face_detect_pre_value(struct i2c_client *client, u8 prevalue)
+{
+ return ft5402_write_reg(client, FT5402_REG_FACE_DETECT_PRE_VALUE,
+ prevalue);
+}
+
+static int ft5402_get_face_detect_pre_value(struct i2c_client *client, u8 *pprevalue)
+{
+ return ft5402_read_reg(client, FT5402_REG_FACE_DETECT_PRE_VALUE,
+ pprevalue);
+}
+
+static int ft5402_set_face_detect_num(struct i2c_client *client, u8 num)
+{
+ return ft5402_write_reg(client, FT5402_REG_FACE_DETECT_NUM,
+ num);
+}
+
+static int ft5402_get_face_detect_num(struct i2c_client *client, u8 *pnum)
+{
+ return ft5402_read_reg(client, FT5402_REG_FACE_DETECT_NUM,
+ pnum);
+}
+
+
+static int ft5402_set_peak_value_min(struct i2c_client *client, u8 min)
+{
+ return ft5402_write_reg(client, FT5402_REG_BIGAREA_PEAK_VALUE_MIN,
+ min);
+}
+
+static int ft5402_get_peak_value_min(struct i2c_client *client, u8 *pmin)
+{
+ return ft5402_read_reg(client, FT5402_REG_BIGAREA_PEAK_VALUE_MIN,
+ pmin);
+}
+
+static int ft5402_set_diff_value_over_num(struct i2c_client *client, u8 num)
+{
+ return ft5402_write_reg(client, FT5402_REG_BIGAREA_DIFF_VALUE_OVER_NUM,
+ num);
+}
+static int ft5402_get_diff_value_over_num(struct i2c_client *client, u8 *pnum)
+{
+ return ft5402_read_reg(client, FT5402_REG_BIGAREA_DIFF_VALUE_OVER_NUM,
+ pnum);
+}
+
+
+static int ft5402_set_customer_id(struct i2c_client *client, u8 num)
+{
+ return ft5402_write_reg(client, FT5402_REG_CUSTOMER_ID,
+ num);
+}
+static int ft5402_get_customer_id(struct i2c_client *client, u8 *pnum)
+{
+ return ft5402_read_reg(client, FT5402_REG_CUSTOMER_ID,
+ pnum);
+}
+
+static int ft5402_set_kx(struct i2c_client *client, u16 value)
+{
+ int err = 0;
+ err = ft5402_write_reg(client, FT5402_REG_KX_H,
+ value >> 8);
+ if (err < 0)
+ dev_err(&client->dev, "%s:set kx high failed\n",
+ __func__);
+ err = ft5402_write_reg(client, FT5402_REG_KX_L,
+ value);
+ if (err < 0)
+ dev_err(&client->dev, "%s:set kx low failed\n",
+ __func__);
+
+ return err;
+}
+
+static int ft5402_get_kx(struct i2c_client *client, u16 *pvalue)
+{
+ int err = 0;
+ u8 tmp1, tmp2;
+ err = ft5402_read_reg(client, FT5402_REG_KX_H,
+ &tmp1);
+ if (err < 0)
+ dev_err(&client->dev, "%s:get kx high failed\n",
+ __func__);
+ err = ft5402_read_reg(client, FT5402_REG_KX_L,
+ &tmp2);
+ if (err < 0)
+ dev_err(&client->dev, "%s:get kx low failed\n",
+ __func__);
+
+ *pvalue = ((u16)tmp1<<8) + (u16)tmp2;
+ return err;
+}
+static int ft5402_set_ky(struct i2c_client *client, u16 value)
+{
+ int err = 0;
+ err = ft5402_write_reg(client, FT5402_REG_KY_H,
+ value >> 8);
+ if (err < 0)
+ dev_err(&client->dev, "%s:set ky high failed\n",
+ __func__);
+ err = ft5402_write_reg(client, FT5402_REG_KY_L,
+ value);
+ if (err < 0)
+ dev_err(&client->dev, "%s:set ky low failed\n",
+ __func__);
+
+ return err;
+}
+
+static int ft5402_get_ky(struct i2c_client *client, u16 *pvalue)
+{
+ int err = 0;
+ u8 tmp1, tmp2;
+ err = ft5402_read_reg(client, FT5402_REG_KY_H,
+ &tmp1);
+ if (err < 0)
+ dev_err(&client->dev, "%s:get ky high failed\n",
+ __func__);
+ err = ft5402_read_reg(client, FT5402_REG_KY_L,
+ &tmp2);
+ if (err < 0)
+ dev_err(&client->dev, "%s:get ky low failed\n",
+ __func__);
+
+ *pvalue = ((u16)tmp1<<8) + (u16)tmp2;
+ return err;
+}
+static int ft5402_set_lemda_x(struct i2c_client *client, u8 value)
+{
+ return ft5402_write_reg(client, FT5402_REG_LEMDA_X,
+ value);
+}
+
+static int ft5402_get_lemda_x(struct i2c_client *client, u8 *pvalue)
+{
+ return ft5402_read_reg(client, FT5402_REG_LEMDA_X,
+ pvalue);
+}
+static int ft5402_set_lemda_y(struct i2c_client *client, u8 value)
+{
+ return ft5402_write_reg(client, FT5402_REG_LEMDA_Y,
+ value);
+}
+
+static int ft5402_get_lemda_y(struct i2c_client *client, u8 *pvalue)
+{
+ return ft5402_read_reg(client, FT5402_REG_LEMDA_Y,
+ pvalue);
+}
+static int ft5402_set_pos_x(struct i2c_client *client, u8 value)
+{
+ return ft5402_write_reg(client, FT5402_REG_DIRECTION,
+ value);
+}
+
+static int ft5402_get_pos_x(struct i2c_client *client, u8 *pvalue)
+{
+ return ft5402_read_reg(client, FT5402_REG_DIRECTION,
+ pvalue);
+}
+
+static int ft5402_set_scan_select(struct i2c_client *client, u8 value)
+{
+ return ft5402_write_reg(client, FT5402_REG_SCAN_SELECT,
+ value);
+}
+
+static int ft5402_get_scan_select(struct i2c_client *client, u8 *pvalue)
+{
+ return ft5402_read_reg(client, FT5402_REG_SCAN_SELECT,
+ pvalue);
+}
+
+static int ft5402_set_other_param(struct i2c_client *client)
+{
+ int err = 0;
+ err = ft5402_write_reg(client, FT5402_REG_THGROUP, (u8)(g_param_ft5402.ft5402_THGROUP));
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write THGROUP failed.\n", __func__);
+ return err;
+ }
+ err = ft5402_write_reg(client, FT5402_REG_THPEAK, g_param_ft5402.ft5402_THPEAK);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write THPEAK failed.\n",
+ __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_PWMODE_CTRL,
+ g_param_ft5402.ft5402_PWMODE_CTRL);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write PERIOD_CTRL failed.\n", __func__);
+ return err;
+ }
+ err = ft5402_write_reg(client, FT5402_REG_PERIOD_ACTIVE,
+ g_param_ft5402.ft5402_PERIOD_ACTIVE);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write PERIOD_ACTIVE failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FACE_DETECT_STATISTICS_TX_NUM,
+ g_param_ft5402.ft5402_FACE_DETECT_STATISTICS_TX_NUM);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FACE_DETECT_STATISTICS_TX_NUM failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_MAX_TOUCH_VALUE_HIGH,
+ g_param_ft5402.ft5402_MAX_TOUCH_VALUE>>8);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write MAX_TOUCH_VALUE_HIGH failed.\n", __func__);
+ return err;
+ }
+ err = ft5402_write_reg(client, FT5402_REG_MAX_TOUCH_VALUE_LOW,
+ g_param_ft5402.ft5402_MAX_TOUCH_VALUE);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write MAX_TOUCH_VALUE_LOW failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FACE_DETECT_MODE,
+ g_param_ft5402.ft5402_FACE_DETECT_MODE);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FACE_DETECT_MODE failed.\n", __func__);
+ return err;
+ }
+ err = ft5402_write_reg(client, FT5402_REG_DRAW_LINE_TH,
+ g_param_ft5402.ft5402_DRAW_LINE_TH);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write DRAW_LINE_TH failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_POINTS_SUPPORTED,
+ g_param_ft5402.ft5402_POINTS_SUPPORTED);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write POINTS_SUPPORTED failed.\n", __func__);
+ return err;
+ }
+ err = ft5402_write_reg(client, FT5402_REG_ESD_FILTER_FRAME,
+ g_param_ft5402.ft5402_ESD_FILTER_FRAME);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_ESD_FILTER_FRAME failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_POINTS_STABLE_MACRO,
+ g_param_ft5402.ft5402_POINTS_STABLE_MACRO);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_POINTS_STABLE_MACRO failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_MIN_DELTA_X,
+ g_param_ft5402.ft5402_MIN_DELTA_X);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_MIN_DELTA_X failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_MIN_DELTA_Y,
+ g_param_ft5402.ft5402_MIN_DELTA_Y);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_MIN_DELTA_Y failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_MIN_DELTA_STEP,
+ g_param_ft5402.ft5402_MIN_DELTA_STEP);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_MIN_DELTA_STEP failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_ESD_NOISE_MACRO,
+ g_param_ft5402.ft5402_ESD_NOISE_MACRO);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_ESD_NOISE_MACRO failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_ESD_DIFF_VAL,
+ g_param_ft5402.ft5402_ESD_DIFF_VAL);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_ESD_DIFF_VAL failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_ESD_NEGTIVE,
+ g_param_ft5402.ft5402_ESD_NEGTIVE);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_ESD_NEGTIVE failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_ESD_FILTER_FRAMES,
+ g_param_ft5402.ft5402_ESD_FILTER_FRAMES);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_ESD_FILTER_FRAMES failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_IO_LEVEL_SELECT,
+ g_param_ft5402.ft5402_IO_LEVEL_SELECT);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_IO_LEVEL_SELECT failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_POINTID_DELAY_COUNT,
+ g_param_ft5402.ft5402_POINTID_DELAY_COUNT);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_POINTID_DELAY_COUNT failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_LIFTUP_FILTER_MACRO,
+ g_param_ft5402.ft5402_LIFTUP_FILTER_MACRO);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_LIFTUP_FILTER_MACRO failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_DIFF_HANDLE_MACRO,
+ g_param_ft5402.ft5402_DIFF_HANDLE_MACRO);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_DIFF_HANDLE_MACRO failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_MIN_WATER,
+ g_param_ft5402.ft5402_MIN_WATER);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_MIN_WATER failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_MAX_NOISE,
+ g_param_ft5402.ft5402_MAX_NOISE);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_MAX_NOISE failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_WATER_START_RX,
+ g_param_ft5402.ft5402_WATER_START_RX);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_WATER_START_RX failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_WATER_START_TX,
+ g_param_ft5402.ft5402_WATER_START_TX);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_WATER_START_TX failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_HOST_NUMBER_SUPPORTED_MACRO,
+ g_param_ft5402.ft5402_HOST_NUMBER_SUPPORTED_MACRO);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_HOST_NUMBER_SUPPORTED_MACRO failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_RAISE_THGROUP,
+ g_param_ft5402.ft5402_RAISE_THGROUP);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_RAISE_THGROUP failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_CHARGER_STATE,
+ g_param_ft5402.ft5402_CHARGER_STATE);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_CHARGER_STATE failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_FILTERID_START,
+ g_param_ft5402.ft5402_FILTERID_START);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_FILTERID_START failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_FRAME_FILTER_EN_MACRO,
+ g_param_ft5402.ft5402_FRAME_FILTER_EN_MACRO);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_FRAME_FILTER_EN_MACRO failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_FRAME_FILTER_SUB_MAX_TH,
+ g_param_ft5402.ft5402_FRAME_FILTER_SUB_MAX_TH);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_FRAME_FILTER_SUB_MAX_TH failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_FRAME_FILTER_ADD_MAX_TH,
+ g_param_ft5402.ft5402_FRAME_FILTER_ADD_MAX_TH);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_FRAME_FILTER_ADD_MAX_TH failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_FRAME_FILTER_SKIP_START_FRAME,
+ g_param_ft5402.ft5402_FRAME_FILTER_SKIP_START_FRAME);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_FRAME_FILTER_SKIP_START_FRAME failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_FRAME_FILTER_BAND_EN,
+ g_param_ft5402.ft5402_FRAME_FILTER_BAND_EN);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_FRAME_FILTER_BAND_EN failed.\n", __func__);
+ return err;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_FT5402_FRAME_FILTER_BAND_WIDTH,
+ g_param_ft5402.ft5402_FRAME_FILTER_BAND_WIDTH);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_FRAME_FILTER_BAND_WIDTH failed.\n", __func__);
+ return err;
+ }
+
+ return err;
+}
+
+static int ft5402_get_other_param(struct i2c_client *client)
+{
+ int err = 0;
+ u8 value = 0x00;
+ err = ft5402_read_reg(client, FT5402_REG_THGROUP, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write THGROUP failed.\n", __func__);
+ return err;
+ } else
+ DBG("THGROUP=%02x\n", value);
+ err = ft5402_read_reg(client, FT5402_REG_THPEAK, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write THPEAK failed.\n",
+ __func__);
+ return err;
+ } else
+ DBG("THPEAK=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_PWMODE_CTRL, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write PWMODE_CTRL failed.\n", __func__);
+ return err;
+ } else
+ DBG("CTRL=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_PERIOD_ACTIVE,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write PERIOD_ACTIVE failed.\n", __func__);
+ return err;
+ } else
+ DBG("PERIOD_ACTIVE=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_MAX_TOUCH_VALUE_HIGH,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write MAX_TOUCH_VALUE_HIGH failed.\n", __func__);
+ return err;
+ } else
+ DBG("MAX_TOUCH_VALUE_HIGH=%02x\n", value);
+ err = ft5402_read_reg(client, FT5402_REG_MAX_TOUCH_VALUE_LOW,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write MAX_TOUCH_VALUE_LOW failed.\n", __func__);
+ return err;
+ } else
+ DBG("MAX_TOUCH_VALUE_LOW=%02x\n", value);
+ err = ft5402_read_reg(client, FT5402_REG_FACE_DETECT_MODE,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FACE_DETECT_MODE failed.\n", __func__);
+ return err;
+ } else
+ DBG("FACE_DEC_MODE=%02x\n", value);
+ err = ft5402_read_reg(client, FT5402_REG_DRAW_LINE_TH,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write DRAW_LINE_TH failed.\n", __func__);
+ return err;
+ } else
+ DBG("DRAW_LINE_TH=%02x\n", value);
+ err = ft5402_read_reg(client, FT5402_REG_POINTS_SUPPORTED,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ft5402_POINTS_SUPPORTED failed.\n", __func__);
+ return err;
+ } else
+ DBG("ft5402_POINTS_SUPPORTED=%02x\n", value);
+ err = ft5402_read_reg(client, FT5402_REG_ESD_FILTER_FRAME,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_ESD_FILTER_FRAME failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_ESD_FILTER_FRAME=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_POINTS_STABLE_MACRO,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_POINTS_STABLE_MACRO failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_POINTS_STABLE_MACRO=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_MIN_DELTA_X,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_MIN_DELTA_X failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_MIN_DELTA_X=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_MIN_DELTA_Y,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_MIN_DELTA_Y failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_MIN_DELTA_Y=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_MIN_DELTA_STEP,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_MIN_DELTA_STEP failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_MIN_DELTA_STEP=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_ESD_NOISE_MACRO,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_ESD_NOISE_MACRO failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_ESD_NOISE_MACRO=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_ESD_DIFF_VAL,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_ESD_DIFF_VAL failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_ESD_DIFF_VAL=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_ESD_NEGTIVE,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_ESD_NEGTIVE failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_ESD_NEGTIVE=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_ESD_FILTER_FRAMES,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_ESD_FILTER_FRAMES failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_ESD_FILTER_FRAMES=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_IO_LEVEL_SELECT,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_IO_LEVEL_SELECT failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_IO_LEVEL_SELECT=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_POINTID_DELAY_COUNT,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_POINTID_DELAY_COUNT failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_POINTID_DELAY_COUNT=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_LIFTUP_FILTER_MACRO,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_LIFTUP_FILTER_MACRO failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_LIFTUP_FILTER_MACRO=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_DIFF_HANDLE_MACRO,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_DIFF_HANDLE_MACRO failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_DIFF_HANDLE_MACRO=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_MIN_WATER,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_MIN_WATER failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_MIN_WATER=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_MAX_NOISE,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_MAX_NOISE failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_MAX_NOISE=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_WATER_START_RX,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_WATER_START_RX failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_WATER_START_RX=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_WATER_START_TX,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_WATER_START_TX failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_WATER_START_TX=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_HOST_NUMBER_SUPPORTED_MACRO,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_HOST_NUMBER_SUPPORTED_MACRO failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_HOST_NUMBER_SUPPORTED_MACRO=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_RAISE_THGROUP,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_RAISE_THGROUP failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_RAISE_THGROUP=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_CHARGER_STATE,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_CHARGER_STATE failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_CHARGER_STATE=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_FILTERID_START,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_FILTERID_START failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_FILTERID_START=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_FRAME_FILTER_EN_MACRO,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_FRAME_FILTER_EN_MACRO failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_FRAME_FILTER_EN_MACRO=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_FRAME_FILTER_SUB_MAX_TH,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_FRAME_FILTER_SUB_MAX_TH failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_FRAME_FILTER_SUB_MAX_TH=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_FRAME_FILTER_ADD_MAX_TH,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_FRAME_FILTER_ADD_MAX_TH failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_FRAME_FILTER_ADD_MAX_TH=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_FRAME_FILTER_SKIP_START_FRAME,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_FRAME_FILTER_SKIP_START_FRAME failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_FRAME_FILTER_SKIP_START_FRAME=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_FRAME_FILTER_BAND_EN,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_FRAME_FILTER_BAND_EN failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_FRAME_FILTER_BAND_EN=%02x\n", value);
+
+ err = ft5402_read_reg(client, FT5402_REG_FT5402_FRAME_FILTER_BAND_WIDTH,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write FT5402_REG_FT5402_FRAME_FILTER_BAND_WIDTH failed.\n", __func__);
+ return err;
+ } else
+ DBG("FT5402_REG_FT5402_FRAME_FILTER_BAND_WIDTH=%02x\n", value);
+
+ return err;
+}
+int ft5402_get_ic_param(struct i2c_client *client)
+{
+ int err = 0;
+ int i = 0;
+ u8 value = 0x00;
+ u16 xvalue = 0x0000, yvalue = 0x0000;
+
+ /*enter factory mode*/
+ err = ft5402_write_reg(client, FT5402_REG_DEVICE_MODE, FT5402_FACTORYMODE_VALUE);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:enter factory mode failed.\n", __func__);
+ goto RETURN_WORK;
+ }
+
+ for (i = 0; i < g_ft5402_tx_num; i++) {
+ DBG("tx%d:", i);
+ /*get tx order*/
+ err = ft5402_get_tx_order(client, i, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get tx%d order.\n",
+ __func__, i);
+ goto RETURN_WORK;
+ }
+ DBG("order=%d ", value);
+ /*get tx cap*/
+ err = ft5402_get_tx_cap(client, i, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get tx%d cap.\n",
+ __func__, i);
+ goto RETURN_WORK;
+ }
+ DBG("cap=%02x\n", value);
+ }
+ /*get tx offset*/
+ err = ft5402_get_tx_offset(client, 0, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get tx 0 offset.\n",
+ __func__);
+ goto RETURN_WORK;
+ } else
+ DBG("tx offset = %02x\n", value);
+
+ /*get rx offset and cap*/
+ for (i = 0; i < g_ft5402_rx_num; i++) {
+ /*get rx order*/
+ DBG("rx%d:", i);
+ err = ft5402_get_rx_order(client, i, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get rx%d order.\n",
+ __func__, i);
+ goto RETURN_WORK;
+ }
+ DBG("order=%d ", value);
+ /*get rx cap*/
+ err = ft5402_get_rx_cap(client, i, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get rx%d cap.\n",
+ __func__, i);
+ goto RETURN_WORK;
+ }
+ DBG("cap=%02x ", value);
+ err = ft5402_get_rx_offset(client, i, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get rx offset.\n",
+ __func__);
+ goto RETURN_WORK;
+ }
+ DBG("offset=%02x\n", value);
+ }
+
+ /*get scan select*/
+ err = ft5402_get_scan_select(client, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get scan select.\n",
+ __func__);
+ goto RETURN_WORK;
+ } else
+ DBG("scan select = %02x\n", value);
+
+ /*get tx number*/
+ err = ft5402_get_tx_num(client, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get tx num.\n",
+ __func__);
+ goto RETURN_WORK;
+ } else
+ DBG("tx num = %02x\n", value);
+ /*get rx number*/
+ err = ft5402_get_rx_num(client, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get rx num.\n",
+ __func__);
+ goto RETURN_WORK;
+ } else
+ DBG("rx num = %02x\n", value);
+
+ /*get gain*/
+ err = ft5402_get_gain(client, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get gain.\n",
+ __func__);
+ goto RETURN_WORK;
+ } else
+ DBG("gain = %02x\n", value);
+ /*get voltage*/
+ err = ft5402_get_vol(client, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get voltage.\n",
+ __func__);
+ goto RETURN_WORK;
+ } else
+ DBG("voltage = %02x\n", value);
+ /*get start rx*/
+ err = ft5402_get_start_rx(client, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get start rx.\n",
+ __func__);
+ goto RETURN_WORK;
+ } else
+ DBG("start rx = %02x\n", value);
+ /*get adc target*/
+ err = ft5402_get_adc_target(client, &xvalue);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get adc target.\n",
+ __func__);
+ goto ERR_EXIT;
+ } else
+ DBG("ADC target = %02x\n", xvalue);
+
+
+RETURN_WORK:
+ /*enter work mode*/
+ err = ft5402_write_reg(client, FT5402_REG_DEVICE_MODE, FT5402_WORKMODE_VALUE);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:enter work mode failed.\n", __func__);
+ goto ERR_EXIT;
+ }
+
+ /*get resolution*/
+ err = ft5402_get_Resolution(client, &xvalue, &yvalue);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get resolution.\n",
+ __func__);
+ goto ERR_EXIT;
+ } else
+ DBG("resolution X = %d Y = %d\n", xvalue, yvalue);
+
+
+ /*get face detect statistics tx num*/
+ err = ft5402_get_face_detect_statistics_tx_num(client,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev,
+ "%s:could not get face detect statistics tx num.\n",
+ __func__);
+ goto ERR_EXIT;
+ } else
+ DBG("FT5402_FACE_DETECT_STATISTICS_TX_NUM = %02x\n", value);
+ /*get face detect pre value*/
+ err = ft5402_get_face_detect_pre_value(client,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev,
+ "%s:could not get face detect pre value.\n",
+ __func__);
+ goto ERR_EXIT;
+ } else
+ DBG("FT5402_FACE_DETECT_PRE_VALUE = %02x\n", value);
+ /*get face detect num*/
+ err = ft5402_get_face_detect_num(client, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get face detect num.\n",
+ __func__);
+ goto ERR_EXIT;
+ } else
+ DBG("face detect num = %02x\n", value);
+
+ /*get min peak value*/
+ err = ft5402_get_peak_value_min(client,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get min peak value.\n",
+ __func__);
+ goto ERR_EXIT;
+ } else
+ DBG("FT5402_BIGAREA_PEAK_VALUE_MIN = %02x\n", value);
+ /*get diff value over num*/
+ err = ft5402_get_diff_value_over_num(client,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get diff value over num.\n",
+ __func__);
+ goto ERR_EXIT;
+ } else
+ DBG("FT5402_BIGAREA_DIFF_VALUE_OVER_NUM = %02x\n", value);
+ /*get customer id*/
+ err = ft5402_get_customer_id(client,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get customer id.\n",
+ __func__);
+ goto ERR_EXIT;
+ } else
+ DBG("FT5402_CUSTOMER_ID = %02x\n", value);
+ /*get kx*/
+ err = ft5402_get_kx(client, &xvalue);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get kx.\n",
+ __func__);
+ goto ERR_EXIT;
+ } else
+ DBG("kx = %02x\n", xvalue);
+ /*get ky*/
+ err = ft5402_get_ky(client, &xvalue);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get ky.\n",
+ __func__);
+ goto ERR_EXIT;
+ } else
+ DBG("ky = %02x\n", xvalue);
+ /*get lemda x*/
+ err = ft5402_get_lemda_x(client,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get lemda x.\n",
+ __func__);
+ goto ERR_EXIT;
+ } else
+ DBG("lemda x = %02x\n", value);
+ /*get lemda y*/
+ err = ft5402_get_lemda_y(client,
+ &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get lemda y.\n",
+ __func__);
+ goto ERR_EXIT;
+ } else
+ DBG("lemda y = %02x\n", value);
+ /*get pos x*/
+ err = ft5402_get_pos_x(client, &value);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not get pos x.\n",
+ __func__);
+ goto ERR_EXIT;
+ } else
+ DBG("pos x = %02x\n", value);
+
+ err = ft5402_get_other_param(client);
+
+ERR_EXIT:
+ return err;
+}
+
+int ft5402_Init_IC_Param(struct i2c_client *client)
+{
+ int err = 0;
+ int i = 0;
+
+ /*enter factory mode*/
+ err = ft5402_write_reg(client, FT5402_REG_DEVICE_MODE, FT5402_FACTORYMODE_VALUE);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:enter factory mode failed.\n", __func__);
+ goto RETURN_WORK;
+ }
+
+ for (i = 0; i < g_ft5402_tx_num; i++) {
+ if (g_ft5402_tx_order[i] != 0xFF) {
+ /*set tx order*/
+ err = ft5402_set_tx_order(client, i, g_ft5402_tx_order[i]);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set tx%d order.\n",
+ __func__, i);
+ goto RETURN_WORK;
+ }
+ }
+ /*set tx cap*/
+ err = ft5402_set_tx_cap(client, i, g_ft5402_tx_cap[i]);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set tx%d cap.\n",
+ __func__, i);
+ goto RETURN_WORK;
+ }
+ }
+ /*set tx offset*/
+ err = ft5402_set_tx_offset(client, 0, g_ft5402_tx_offset);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set tx 0 offset.\n",
+ __func__);
+ goto RETURN_WORK;
+ }
+
+ /*set rx offset and cap*/
+ for (i = 0; i < g_ft5402_rx_num; i++) {
+ /*set rx order*/
+ err = ft5402_set_rx_order(client, i, g_ft5402_rx_order[i]);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set rx%d order.\n",
+ __func__, i);
+ goto RETURN_WORK;
+ }
+ /*set rx cap*/
+ err = ft5402_set_rx_cap(client, i, g_ft5402_rx_cap[i]);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set rx%d cap.\n",
+ __func__, i);
+ goto RETURN_WORK;
+ }
+ }
+ for (i = 0; i < g_ft5402_rx_num/2; i++) {
+ err = ft5402_set_rx_offset(client, i*2, g_ft5402_rx_offset[i]>>4);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set rx offset.\n",
+ __func__);
+ goto RETURN_WORK;
+ }
+ err = ft5402_set_rx_offset(client, i*2+1, g_ft5402_rx_offset[i]&0x0F);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set rx offset.\n",
+ __func__);
+ goto RETURN_WORK;
+ }
+ }
+
+ /*set scan select*/
+ err = ft5402_set_scan_select(client, g_ft5402_scanselect);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set scan select.\n",
+ __func__);
+ goto RETURN_WORK;
+ }
+
+ /*set tx number*/
+ err = ft5402_set_tx_num(client, g_ft5402_tx_num);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set tx num.\n",
+ __func__);
+ goto RETURN_WORK;
+ }
+ /*set rx number*/
+ err = ft5402_set_rx_num(client, g_ft5402_rx_num);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set rx num.\n",
+ __func__);
+ goto RETURN_WORK;
+ }
+
+ /*set gain*/
+ err = ft5402_set_gain(client, g_ft5402_gain);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set gain.\n",
+ __func__);
+ goto RETURN_WORK;
+ }
+ /*set voltage*/
+ err = ft5402_set_vol(client, g_ft5402_voltage);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set voltage.\n",
+ __func__);
+ goto RETURN_WORK;
+ }
+
+ err = ft5402_write_reg(client, FT5402_REG_ADC_TARGET_HIGH,
+ g_param_ft5402.ft5402_ADC_TARGET>>8);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ADC_TARGET_HIGH failed.\n", __func__);
+ return err;
+ }
+ err = ft5402_write_reg(client, FT5402_REG_ADC_TARGET_LOW,
+ g_param_ft5402.ft5402_ADC_TARGET);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:write ADC_TARGET_LOW failed.\n", __func__);
+ return err;
+ }
+
+RETURN_WORK:
+ /*enter work mode*/
+ err = ft5402_write_reg(client, FT5402_REG_DEVICE_MODE, FT5402_WORKMODE_VALUE);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:enter work mode failed.\n", __func__);
+ goto ERR_EXIT;
+ }
+
+ /*set resolution*/
+ err = ft5402_set_Resolution(client, g_param_ft5402.ft5402_RESOLUTION_X,
+ g_param_ft5402.ft5402_RESOLUTION_Y);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set resolution.\n",
+ __func__);
+ goto ERR_EXIT;
+ }
+
+ /*set face detect statistics tx num*/
+ err = ft5402_set_face_detect_statistics_tx_num(client,
+ g_param_ft5402.ft5402_FACE_DETECT_STATISTICS_TX_NUM);
+ if (err < 0) {
+ dev_err(&client->dev,
+ "%s:could not set face detect statistics tx num.\n",
+ __func__);
+ goto ERR_EXIT;
+ }
+ /*set face detect pre value*/
+ err = ft5402_set_face_detect_pre_value(client,
+ g_param_ft5402.ft5402_FACE_DETECT_PRE_VALUE);
+ if (err < 0) {
+ dev_err(&client->dev,
+ "%s:could not set face detect pre value.\n",
+ __func__);
+ goto ERR_EXIT;
+ }
+ /*set face detect num*/
+ err = ft5402_set_face_detect_num(client,
+ g_param_ft5402.ft5402_FACE_DETECT_NUM);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set face detect num.\n",
+ __func__);
+ goto ERR_EXIT;
+ }
+
+ /*set min peak value*/
+ err = ft5402_set_peak_value_min(client,
+ g_param_ft5402.ft5402_BIGAREA_PEAK_VALUE_MIN);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set min peak value.\n",
+ __func__);
+ goto ERR_EXIT;
+ }
+ /*set diff value over num*/
+ err = ft5402_set_diff_value_over_num(client,
+ g_param_ft5402.ft5402_BIGAREA_DIFF_VALUE_OVER_NUM);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set diff value over num.\n",
+ __func__);
+ goto ERR_EXIT;
+ }
+ /*set customer id*/
+ err = ft5402_set_customer_id(client,
+ g_param_ft5402.ft5402_CUSTOMER_ID);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set customer id.\n",
+ __func__);
+ goto ERR_EXIT;
+ }
+ /*set kx*/
+ err = ft5402_set_kx(client, g_param_ft5402.ft5402_KX);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set kx.\n",
+ __func__);
+ goto ERR_EXIT;
+ }
+ /*set ky*/
+ err = ft5402_set_ky(client, g_param_ft5402.ft5402_KY);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set ky.\n",
+ __func__);
+ goto ERR_EXIT;
+ }
+ /*set lemda x*/
+ err = ft5402_set_lemda_x(client,
+ g_param_ft5402.ft5402_LEMDA_X);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set lemda x.\n",
+ __func__);
+ goto ERR_EXIT;
+ }
+ /*set lemda y*/
+ err = ft5402_set_lemda_y(client,
+ g_param_ft5402.ft5402_LEMDA_Y);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set lemda y.\n",
+ __func__);
+ goto ERR_EXIT;
+ }
+ /*set pos x*/
+ err = ft5402_set_pos_x(client, g_param_ft5402.ft5402_DIRECTION);
+ if (err < 0) {
+ dev_err(&client->dev, "%s:could not set pos x.\n",
+ __func__);
+ goto ERR_EXIT;
+ }
+
+ err = ft5402_set_other_param(client);
+
+ERR_EXIT:
+ return err;
+}
+
+
+char dst[512];
+static char * ft5402_sub_str(char * src, int n)
+{
+ char *p = src;
+ int i;
+ int m = 0;
+ int len = strlen(src);
+
+ while (n >= 1 && m <= len) {
+ i = 0;
+ dst[10] = ' ';
+ n--;
+ while ( *p != ',' && *p != ' ') {
+ dst[i++] = *(p++);
+ m++;
+ if (i >= len)
+ break;
+ }
+ dst[i++] = '\0';
+ p++;
+ }
+ return dst;
+}
+static int ft5402_GetInISize(char *config_name)
+{
+ struct file *pfile = NULL;
+ struct inode *inode;
+ unsigned long magic;
+ off_t fsize = 0;
+ char filepath[128];
+ memset(filepath, 0, sizeof(filepath));
+
+ sprintf(filepath, "%s%s", FT5402_INI_FILEPATH, config_name);
+
+ if (NULL == pfile)
+ pfile = filp_open(filepath, O_RDONLY, 0);
+
+ if (IS_ERR(pfile)) {
+ pr_err("error occured while opening file %s.\n", filepath);
+ return -EIO;
+ }
+
+ inode = pfile->f_dentry->d_inode;
+ magic = inode->i_sb->s_magic;
+ fsize = inode->i_size;
+ filp_close(pfile, NULL);
+ return fsize;
+}
+
+static int ft5x0x_ReadInIData(char *config_name,
+ char *config_buf)
+{
+ struct file *pfile = NULL;
+ struct inode *inode;
+ unsigned long magic;
+ off_t fsize;
+ char filepath[128];
+ loff_t pos;
+ mm_segment_t old_fs;
+
+ memset(filepath, 0, sizeof(filepath));
+ sprintf(filepath, "%s%s", FT5402_INI_FILEPATH, config_name);
+ if (NULL == pfile)
+ pfile = filp_open(filepath, O_RDONLY, 0);
+ if (IS_ERR(pfile)) {
+ pr_err("error occured while opening file %s.\n", filepath);
+ return -EIO;
+ }
+
+ inode = pfile->f_dentry->d_inode;
+ magic = inode->i_sb->s_magic;
+ fsize = inode->i_size;
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ pos = 0;
+ vfs_read(pfile, config_buf, fsize, &pos);
+ filp_close(pfile, NULL);
+ set_fs(old_fs);
+
+ return 0;
+}
+
+int ft5402_Get_Param_From_Ini(char *config_name)
+{
+ char key[64];
+ char value[512];
+ char section[64];
+ int i = 0;//,ret=0;
+ int j = 0;
+ char *filedata = NULL;
+ unsigned char legal_byte1 = 0x00;
+ unsigned char legal_byte2 = 0x00;
+
+ int inisize = ft5402_GetInISize(config_name);
+
+ if (inisize <= 0) {
+ pr_err("%s ERROR:Get firmware size failed\n",
+ __func__);
+ return -EIO;
+ }
+
+ filedata = kmalloc(inisize + 1, GFP_ATOMIC);
+
+ if (ft5x0x_ReadInIData(config_name, filedata)) {
+ pr_err("%s() - ERROR: request_firmware failed\n",
+ __func__);
+ kfree(filedata);
+ return -EIO;
+ }
+
+ /*check ini if it is illegal*/
+ sprintf(section, "%s", FT5402_APP_LEGAL);
+ sprintf(key, "%s", FT5402_APP_LEGAL_BYTE_1_STR);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ legal_byte1 = atoi(value);
+ DBG("legal_byte1=%s\n", value);
+ sprintf(key, "%s", FT5402_APP_LEGAL_BYTE_2_STR);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ legal_byte2 = atoi(value);
+ DBG("lega2_byte1=%s\n", value);
+ if(FT5402_APP_LEGAL_BYTE_1_VALUE == legal_byte1 &&
+ FT5402_APP_LEGAL_BYTE_2_VALUE == legal_byte2)
+ DBG("the ini file is valid\n");
+ else {
+ pr_err("[FTS]-----the ini file is invalid!please check it.\n");
+ goto ERROR_RETURN;
+ }
+
+ /*get ini param*/
+ sprintf(section, "%s", FT5402_APP_NAME);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_KX = atoi(value);
+ DBG("ft5402_KX=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_KY = atoi(value);
+ DBG("ft5402_KY=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_LEMDA_X = atoi(value);
+ DBG("ft5402_LEMDA_X=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_LEMDA_Y = atoi(value);
+ DBG("ft5402_LEMDA_Y=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_RESOLUTION_X = atoi(value);
+ DBG("ft5402_RESOLUTION_X=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_RESOLUTION_Y = atoi(value);
+ DBG("ft5402_RESOLUTION_Y=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_DIRECTION= atoi(value);
+ DBG("ft5402_DIRECTION=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_FACE_DETECT_PRE_VALUE = atoi(value);
+ DBG("ft5402_FACE_DETECT_PRE_VALUE=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_FACE_DETECT_NUM = atoi(value);
+ DBG("ft5402_FACE_DETECT_NUM=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_BIGAREA_PEAK_VALUE_MIN = atoi(value);/*The min value to be decided as the big point*/
+ DBG("ft5402_BIGAREA_PEAK_VALUE_MIN=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_BIGAREA_DIFF_VALUE_OVER_NUM = atoi(value);/*The min big points of the big area*/
+ DBG("ft5402_BIGAREA_DIFF_VALUE_OVER_NUM=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_CUSTOMER_ID = atoi(value);
+ DBG("ft5402_CUSTOM_ID=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_PERIOD_ACTIVE = atoi(value);
+ DBG("ft5402_PERIOD_ACTIVE=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_FACE_DETECT_STATISTICS_TX_NUM = atoi(value);
+ DBG("ft5402_FACE_DETECT_STATISTICS_TX_NUM=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_THGROUP = atoi(value);
+ DBG("ft5402_THGROUP=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_THPEAK = atoi(value);
+ DBG("ft5402_THPEAK=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_FACE_DETECT_MODE = atoi(value);
+ DBG("ft5402_FACE_DETECT_MODE=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_MAX_TOUCH_VALUE = atoi(value);
+ DBG("ft5402_MAX_TOUCH_VALUE=%s\n", value);
+
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_PWMODE_CTRL= atoi(value);
+ DBG("ft5402_PWMODE_CTRL=%s\n", value);
+
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+
+ i++;
+ g_param_ft5402.ft5402_DRAW_LINE_TH = atoi(value);
+ DBG("ft5402_DRAW_LINE_TH=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_POINTS_SUPPORTED= atoi(value);
+ DBG("ft5402_POINTS_SUPPORTED=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_START_RX = atoi(value);
+ DBG("ft5402_START_RX=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+
+ g_param_ft5402.ft5402_ADC_TARGET = atoi(value);
+ DBG("ft5402_ADC_TARGET=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+
+ g_param_ft5402.ft5402_ESD_FILTER_FRAME = atoi(value);
+ DBG("ft5402_ESD_FILTER_FRAME=%s\n", value);
+
+/*********************************************************************/
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_ft5402_tx_num = atoi(value);
+ DBG("ft5402_tx_num=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_ft5402_rx_num = atoi(value);
+ DBG("ft5402_rx_num=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_ft5402_gain = atoi(value);
+ DBG("ft5402_gain=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_ft5402_voltage = atoi(value);
+ DBG("ft5402_voltage=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_ft5402_scanselect = atoi(value);
+ DBG("ft5402_scanselect=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ for(j = 0; j < g_ft5402_tx_num; j++)
+ {
+ char * psrc = value;
+ g_ft5402_tx_order[j] = atoi(ft5402_sub_str(psrc, j+1));
+ }
+ DBG("ft5402_tx_order=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_ft5402_tx_offset = atoi(value);
+ DBG("ft5402_tx_offset=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ for(j = 0; j < g_ft5402_tx_num; j++)
+ {
+ char * psrc = value;
+ g_ft5402_tx_cap[j] = atoi(ft5402_sub_str(psrc, j+1));
+ }
+ DBG("ft5402_tx_cap=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ for(j = 0; j < g_ft5402_rx_num; j++)
+ {
+ char * psrc = value;
+ g_ft5402_rx_order[j] = atoi(ft5402_sub_str(psrc, j+1));
+ }
+ DBG("ft5402_rx_order=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ for(j = 0; j < g_ft5402_rx_num/2; j++)
+ {
+ char * psrc = value;
+ g_ft5402_rx_offset[j] = atoi(ft5402_sub_str(psrc, j+1));
+ }
+ DBG("ft5402_rx_offset=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ for(j = 0; j < g_ft5402_rx_num; j++)
+ {
+ char * psrc = value;
+ g_ft5402_rx_cap[j] = atoi(ft5402_sub_str(psrc, j+1));
+ }
+ DBG("ft5402_rx_cap=%s\n", value);
+
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_POINTS_STABLE_MACRO = atoi(value);
+ DBG("ft5402_POINTS_STABLE_MACRO=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_MIN_DELTA_X = atoi(value);
+ DBG("ft5402_MIN_DELTA_X=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_MIN_DELTA_Y = atoi(value);
+ DBG("ft5402_MIN_DELTA_Y=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_MIN_DELTA_STEP = atoi(value);
+ DBG("ft5402_MIN_DELTA_STEP=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_ESD_NOISE_MACRO = atoi(value);
+ DBG("ft5402_ESD_NOISE_MACRO=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_ESD_DIFF_VAL = atoi(value);
+ DBG("ft5402_ESD_DIFF_VAL=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_ESD_NEGTIVE = atoi(value);
+ DBG("ft5402_ESD_NEGTIVE=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_ESD_FILTER_FRAMES = atoi(value);
+ DBG("ft5402_ESD_FILTER_FRAMES=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_IO_LEVEL_SELECT = atoi(value);
+ DBG("ft5402_IO_LEVEL_SELECT=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_POINTID_DELAY_COUNT = atoi(value);
+ DBG("ft5402_POINTID_DELAY_COUNT=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_LIFTUP_FILTER_MACRO = atoi(value);
+ DBG("ft5402_LIFTUP_FILTER_MACRO=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_DIFF_HANDLE_MACRO = atoi(value);
+ DBG("ft5402_DIFF_HANDLE_MACRO=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_MIN_WATER = atoi(value);
+ DBG("ft5402_MIN_WATER=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_MAX_NOISE = atoi(value);
+ DBG("ft5402_MAX_NOISE=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_WATER_START_RX = atoi(value);
+ DBG("ft5402_WATER_START_RX=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_WATER_START_TX = atoi(value);
+ DBG("ft5402_WATER_START_TX=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_HOST_NUMBER_SUPPORTED_MACRO = atoi(value);
+ DBG("ft5402_HOST_NUMBER_SUPPORTED_MACRO=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_RAISE_THGROUP = atoi(value);
+ DBG("ft5402_RAISE_THGROUP=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_CHARGER_STATE = atoi(value);
+ DBG("ft5402_CHARGER_STATE=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_FILTERID_START = atoi(value);
+ DBG("ft5402_FILTERID_START=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_FRAME_FILTER_EN_MACRO = atoi(value);
+ DBG("ft5402_FRAME_FILTER_EN_MACRO=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_FRAME_FILTER_SUB_MAX_TH = atoi(value);
+ DBG("ft5402_FRAME_FILTER_SUB_MAX_TH=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_FRAME_FILTER_ADD_MAX_TH = atoi(value);
+ DBG("ft5402_FRAME_FILTER_ADD_MAX_TH=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_FRAME_FILTER_SKIP_START_FRAME = atoi(value);
+ DBG("ft5402_FRAME_FILTER_SKIP_START_FRAME=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_FRAME_FILTER_BAND_EN = atoi(value);
+ DBG("ft5402_FRAME_FILTER_BAND_EN=%s\n", value);
+
+ sprintf(key, "%s", String_Param_FT5402[i]);
+ if (ini_get_key(filedata,section,key,value)<0)
+ goto ERROR_RETURN;
+ i++;
+ g_param_ft5402.ft5402_FRAME_FILTER_BAND_WIDTH = atoi(value);
+ DBG("ft5402_FRAME_FILTER_BAND_WIDTH=%s\n", value);
+
+
+ if (filedata)
+ kfree(filedata);
+ return 0;
+ERROR_RETURN:
+ if (filedata)
+ kfree(filedata);
+ return -1;
+}
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ft5402_config.h b/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ft5402_config.h
new file mode 100755
index 00000000..4d4935ed
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ft5402_config.h
@@ -0,0 +1,71 @@
+#ifndef __FT5402_CONFIG_H__
+#define __FT5402_CONFIG_H__
+/*FT5402 config*/
+
+
+#define FT5402_START_RX 0
+#define FT5402_ADC_TARGET 8500
+#define FT5402_KX 120
+#define FT5402_KY 120
+#define FT5402_RESOLUTION_X 480
+#define FT5402_RESOLUTION_Y 800
+#define FT5402_LEMDA_X 0
+#define FT5402_LEMDA_Y 0
+#define FT5402_PWMODE_CTRL 1
+#define FT5402_POINTS_SUPPORTED 5
+#define FT5402_DRAW_LINE_TH 150
+#define FT5402_FACE_DETECT_MODE 0
+#define FT5402_FACE_DETECT_STATISTICS_TX_NUM 3
+#define FT5402_FACE_DETECT_PRE_VALUE 20
+#define FT5402_FACE_DETECT_NUM 10
+#define FT5402_THGROUP 25
+#define FT5402_THPEAK 60
+#define FT5402_BIGAREA_PEAK_VALUE_MIN 100
+#define FT5402_BIGAREA_DIFF_VALUE_OVER_NUM 50
+#define FT5402_MIN_DELTA_X 2
+#define FT5402_MIN_DELTA_Y 2
+#define FT5402_MIN_DELTA_STEP 2
+#define FT5402_ESD_DIFF_VAL 20
+#define FT5402_ESD_NEGTIVE -50
+#define FT5402_ESD_FILTER_FRAME 10
+#define FT5402_MAX_TOUCH_VALUE 600
+#define FT5402_CUSTOMER_ID 121
+#define FT5402_IO_LEVEL_SELECT 0
+#define FT5402_DIRECTION 1
+#define FT5402_POINTID_DELAY_COUNT 3
+#define FT5402_LIFTUP_FILTER_MACRO 1
+#define FT5402_POINTS_STABLE_MACRO 1
+#define FT5402_ESD_NOISE_MACRO 1
+#define FT5402_RV_G_PERIOD_ACTIVE 16
+#define FT5402_DIFFDATA_HANDLE 1
+#define FT5402_MIN_WATER_VAL -50
+#define FT5402_MAX_NOISE_VAL 10
+#define FT5402_WATER_HANDLE_START_RX 0
+#define FT5402_WATER_HANDLE_START_TX 0
+#define FT5402_HOST_NUMBER_SUPPORTED 1
+#define FT5402_RV_G_RAISE_THGROUP 30
+#define FT5402_RV_G_CHARGER_STATE 0
+#define FT5402_RV_G_FILTERID_START 2
+#define FT5402_FRAME_FILTER_EN 1
+#define FT5402_FRAME_FILTER_SUB_MAX_TH 2
+#define FT5402_FRAME_FILTER_ADD_MAX_TH 2
+#define FT5402_FRAME_FILTER_SKIP_START_FRAME 6
+#define FT5402_FRAME_FILTER_BAND_EN 1
+#define FT5402_FRAME_FILTER_BAND_WIDTH 128
+#define FT5402_OTP_PARAM_ID 0
+
+
+unsigned char g_ft5402_tx_num = 27;
+unsigned char g_ft5402_rx_num = 16;
+unsigned char g_ft5402_gain = 10;
+unsigned char g_ft5402_voltage = 3;
+unsigned char g_ft5402_scanselect = 8;
+unsigned char g_ft5402_tx_order[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26};
+unsigned char g_ft5402_tx_offset = 2;
+unsigned char g_ft5402_tx_cap[] = {42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42};
+unsigned char g_ft5402_rx_order[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+unsigned char g_ft5402_rx_offset[] = {68,68,68,68,68,68,68,68};
+unsigned char g_ft5402_rx_cap[] = {84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84};
+
+
+#endif \ No newline at end of file
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ft5402_ini_config.h b/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ft5402_ini_config.h
new file mode 100755
index 00000000..138f42e2
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ft5402_ini_config.h
@@ -0,0 +1,411 @@
+#ifndef __LINUX_FT5402_INI_CONFIG_H__
+#define __LINUX_FT5402_INI_CONFIG_H
+
+
+/*Init param register address*/
+/*factory mode register from 14-131*/
+#define FT5402_REG_TX_NUM 0x03
+#define FT5402_REG_RX_NUM 0x04
+#define FT5402_REG_VOLTAGE 0x05
+#define FT5402_REG_GAIN 0x07
+#define FT5402_REG_SCAN_SELECT 0x4E
+#define FT5402_REG_TX_ORDER_START 0x50
+#define FT5402_REG_TX_CAP_START 0x78
+#define FT5402_REG_TX_OFFSET_START 0xBF
+#define FT5402_REG_RX_ORDER_START 0xeb
+#define FT5402_REG_RX_CAP_START 0xA0
+#define FT5402_REG_RX_OFFSET_START 0xD3
+#define FT5402_REG_START_RX 0x06
+#define FT5402_REG_ADC_TARGET_HIGH 0x08
+#define FT5402_REG_ADC_TARGET_LOW 0x09
+
+
+#define FT5402_REG_DEVICE_MODE 0x00
+
+
+/*work mode register from 0-13(0,1,12,13verify or Reserved)and 132-177(159 Reserved)*/
+#define FT5402_REG_THGROUP (0x00+0x80)
+#define FT5402_REG_THPEAK (0x01+0x80)
+#define FT5402_REG_PWMODE_CTRL (0x06+0x80)
+#define FT5402_REG_PERIOD_ACTIVE (0x59+0x80)
+#define FT5402_REG_POINTS_SUPPORTED (0x0A+0x80)
+#define FT5402_REG_ESD_FILTER_FRAME (0x4F+0x80)
+
+#define FT5402_REG_RESOLUTION_X_H (0x18+0x80)
+#define FT5402_REG_RESOLUTION_X_L (0x19+0x80)
+#define FT5402_REG_RESOLUTION_Y_H (0x1a+0x80)
+#define FT5402_REG_RESOLUTION_Y_L (0x1b+0x80)
+#define FT5402_REG_KX_H (0x1c+0x80)
+#define FT5402_REG_KX_L (0x9d)
+#define FT5402_REG_KY_H (0x9e)
+#define FT5402_REG_KY_L (0x1f+0x80)
+#define FT5402_REG_CUSTOMER_ID (0xA8)
+#define FT5402_REG_DRAW_LINE_TH (0xAe)
+#define FT5402_REG_FACE_DETECT_MODE (0xB0)
+#define FT5402_REG_MAX_TOUCH_VALUE_HIGH (0xD0)
+#define FT5402_REG_MAX_TOUCH_VALUE_LOW (0xD1)
+
+#define FT5402_REG_DIRECTION (0x53+0x80)
+#define FT5402_REG_LEMDA_X (0x41+0x80)
+#define FT5402_REG_LEMDA_Y (0x42+0x80)
+#define FT5402_REG_FACE_DETECT_STATISTICS_TX_NUM (0x43+0x80)
+#define FT5402_REG_FACE_DETECT_PRE_VALUE (0x44+0x80)
+#define FT5402_REG_FACE_DETECT_NUM (0x45+0x80)
+#define FT5402_REG_BIGAREA_PEAK_VALUE_MIN (0x33+0x80)
+#define FT5402_REG_BIGAREA_DIFF_VALUE_OVER_NUM (0x34+0x80)
+
+/**************************************************************************/
+#define FT5402_REG_FT5402_POINTS_STABLE_MACRO (0x57+0x80)
+#define FT5402_REG_FT5402_MIN_DELTA_X (0x4a+0x80)
+#define FT5402_REG_FT5402_MIN_DELTA_Y (0x4b+0x80)
+#define FT5402_REG_FT5402_MIN_DELTA_STEP (0x4c+0x80)
+
+#define FT5402_REG_FT5402_ESD_NOISE_MACRO (0x58+0x80)
+#define FT5402_REG_FT5402_ESD_DIFF_VAL (0x4d+0x80)
+#define FT5402_REG_FT5402_ESD_NEGTIVE (0xCe)
+#define FT5402_REG_FT5402_ESD_FILTER_FRAMES (0x4f+0x80)
+
+#define FT5402_REG_FT5402_IO_LEVEL_SELECT (0x52+0x80)
+
+#define FT5402_REG_FT5402_POINTID_DELAY_COUNT (0x54+0x80)
+
+#define FT5402_REG_FT5402_LIFTUP_FILTER_MACRO (0x55+0x80)
+
+#define FT5402_REG_FT5402_DIFF_HANDLE_MACRO (0x5A+0x80)
+#define FT5402_REG_FT5402_MIN_WATER (0x5B+0x80)
+#define FT5402_REG_FT5402_MAX_NOISE (0x5C+0x80)
+#define FT5402_REG_FT5402_WATER_START_RX (0x5D+0x80)
+#define FT5402_REG_FT5402_WATER_START_TX (0xDE)
+
+#define FT5402_REG_FT5402_HOST_NUMBER_SUPPORTED_MACRO (0x38+0x80)
+#define FT5402_REG_FT5402_RAISE_THGROUP (0x36+0x80)
+#define FT5402_REG_FT5402_CHARGER_STATE (0x35+0x80)
+
+#define FT5402_REG_FT5402_FILTERID_START (0x37+0x80)
+
+#define FT5402_REG_FT5402_FRAME_FILTER_EN_MACRO (0x5F+0x80)
+#define FT5402_REG_FT5402_FRAME_FILTER_SUB_MAX_TH (0x60+0x80)
+#define FT5402_REG_FT5402_FRAME_FILTER_ADD_MAX_TH (0x61+0x80)
+#define FT5402_REG_FT5402_FRAME_FILTER_SKIP_START_FRAME (0x62+0x80)
+#define FT5402_REG_FT5402_FRAME_FILTER_BAND_EN (0x63+0x80)
+#define FT5402_REG_FT5402_FRAME_FILTER_BAND_WIDTH (0x64+0x80)
+/**************************************************************************/
+
+#define FT5402_REG_TEST_MODE 0x04
+#define FT5402_REG_TEST_MODE_2 0x05
+#define FT5402_TX_TEST_MODE_1 0x28
+#define FT5402_RX_TEST_MODE_1 0x1E
+#define FT5402_FACTORYMODE_VALUE 0x40
+#define FT5402_WORKMODE_VALUE 0x00
+
+/************************************************************************/
+/* string */
+/************************************************************************/
+#define STRING_FT5402_KX "FT5X02_KX"
+#define STRING_FT5402_KY "FT5X02_KY"
+#define STRING_FT5402_LEMDA_X "FT5X02_LEMDA_X"
+#define STRING_FT5402_LEMDA_Y "FT5X02_LEMDA_Y"
+#define STRING_FT5402_RESOLUTION_X "FT5X02_RESOLUTION_X"
+#define STRING_FT5402_RESOLUTION_Y "FT5X02_RESOLUTION_Y"
+#define STRING_FT5402_DIRECTION "FT5X02_DIRECTION"
+
+
+
+#define STRING_FT5402_FACE_DETECT_PRE_VALUE "FT5X02_FACE_DETECT_PRE_VALUE"
+#define STRING_FT5402_FACE_DETECT_NUM "FT5X02_FACE_DETECT_NUM"
+#define STRING_FT5402_BIGAREA_PEAK_VALUE_MIN "FT5X02_BIGAREA_PEAK_VALUE_MIN"
+#define STRING_FT5402_BIGAREA_DIFF_VALUE_OVER_NUM "FT5X02_BIGAREA_DIFF_VALUE_OVER_NUM"
+#define STRING_FT5402_CUSTOMER_ID "FT5X02_CUSTOMER_ID"
+#define STRING_FT5402_PERIOD_ACTIVE "FT5X02_RV_G_PERIOD_ACTIVE"
+#define STRING_FT5402_FACE_DETECT_STATISTICS_TX_NUM "FT5X02_FACE_DETECT_STATISTICS_TX_NUM"
+
+#define STRING_FT5402_THGROUP "FT5X02_THGROUP"
+#define STRING_FT5402_THPEAK "FT5X02_THPEAK"
+#define STRING_FT5402_FACE_DETECT_MODE "FT5X02_FACE_DETECT_MODE"
+#define STRING_FT5402_MAX_TOUCH_VALUE "FT5X02_MAX_TOUCH_VALUE"
+
+#define STRING_FT5402_PWMODE_CTRL "FT5X02_PWMODE_CTRL"
+#define STRING_FT5402_DRAW_LINE_TH "FT5X02_DRAW_LINE_TH"
+
+#define STRING_FT5402_POINTS_SUPPORTED "FT5X02_POINTS_SUPPORTED"
+
+#define STRING_FT5402_START_RX "FT5X02_START_RX"
+#define STRING_FT5402_ADC_TARGET "FT5X02_ADC_TARGET"
+#define STRING_FT5402_ESD_FILTER_FRAME "FT5X02_ESD_FILTER_FRAME"
+
+#define STRING_FT5402_POINTS_STABLE_MACRO "FT5X02_POINTS_STABLE_MACRO"
+#define STRING_FT5402_MIN_DELTA_X "FT5X02_MIN_DELTA_X"
+#define STRING_FT5402_MIN_DELTA_Y "FT5X02_MIN_DELTA_Y"
+#define STRING_FT5402_MIN_DELTA_STEP "FT5X02_MIN_DELTA_STEP"
+
+#define STRING_FT5402_ESD_NOISE_MACRO "FT5X02_ESD_NOISE_MACRO"
+#define STRING_FT5402_ESD_DIFF_VAL "FT5X02_ESD_DIFF_VAL"
+#define STRING_FT5402_ESD_NEGTIVE "FT5X02_ESD_NEGTIVE"
+#define STRING_FT5402_ESD_FILTER_FRAME "FT5X02_ESD_FILTER_FRAME"
+
+#define STRING_FT5402_IO_LEVEL_SELECT "FT5X02_IO_LEVEL_SELECT"
+#define STRING_FT5402_POINTID_DELAY_COUNT "FT5X02_POINTID_DELAY_COUNT"
+
+#define STRING_FT5402_LIFTUP_FILTER_MACRO "FT5X02_LIFTUP_FILTER_MACRO"
+
+#define STRING_FT5402_DIFFDATA_HANDLE "FT5X02_DIFFDATA_HANDLE" //_MACRO
+#define STRING_FT5402_MIN_WATER_VAL "FT5X02_MIN_WATER_VAL"
+#define STRING_FT5402_MAX_NOISE_VAL "FT5X02_MAX_NOISE_VAL"
+#define STRING_FT5402_WATER_HANDLE_START_RX "FT5X02_WATER_HANDLE_START_RX"
+#define STRING_FT5402_WATER_HANDLE_START_TX "FT5X02_WATER_HANDLE_START_TX"
+
+#define STRING_FT5402_HOST_NUMBER_SUPPORTED "FT5X02_HOST_NUMBER_SUPPORTED"
+#define STRING_FT5402_RV_G_RAISE_THGROUP "FT5X02_RV_G_RAISE_THGROUP"
+#define STRING_FT5402_RV_G_CHARGER_STATE "FT5X02_RV_G_CHARGER_STATE"
+
+#define STRING_FT5402_RV_G_FILTERID_START "FT5X02_RV_G_FILTERID_START"
+
+#define STRING_FT5402_FRAME_FILTER_EN "FT5X02_FRAME_FILTER_EN"
+#define STRING_FT5402_FRAME_FILTER_SUB_MAX_TH "FT5X02_FRAME_FILTER_SUB_MAX_TH"
+#define STRING_FT5402_FRAME_FILTER_ADD_MAX_TH "FT5X02_FRAME_FILTER_ADD_MAX_TH"
+#define STRING_FT5402_FRAME_FILTER_SKIP_START_FRAME "FT5X02_FRAME_FILTER_SKIP_START_FRAME"
+#define STRING_FT5402_FRAME_FILTER_BAND_EN "FT5X02_FRAME_FILTER_BAND_EN"
+#define STRING_FT5402_FRAME_FILTER_BAND_WIDTH "FT5X02_FRAME_FILTER_BAND_WIDTH"
+
+
+#define STRING_ft5402_tx_num "FT5X02_tx_num"
+#define STRING_ft5402_rx_num "FT5X02_rx_num"
+#define STRING_ft5402_gain "FT5X02_gain"
+#define STRING_ft5402_voltage "FT5X02_voltage"
+#define STRING_ft5402_scanselect "FT5X02_scanselect"
+
+#define STRING_ft5402_tx_order "FT5X02_tx_order"
+#define STRING_ft5402_tx_offset "FT5X02_tx_offset"
+#define STRING_ft5402_tx_cap "FT5X02_tx_cap"
+
+#define STRING_ft5402_rx_order "FT5X02_rx_order"
+#define STRING_ft5402_rx_offset "FT5X02_rx_offset"
+#define STRING_ft5402_rx_cap "FT5X02_rx_cap"
+
+struct Struct_Param_FT5402 {
+ short ft5402_KX;
+ short ft5402_KY;
+ unsigned char ft5402_LEMDA_X;
+ unsigned char ft5402_LEMDA_Y;
+ short ft5402_RESOLUTION_X;
+ short ft5402_RESOLUTION_Y;
+ unsigned char ft5402_DIRECTION;
+ unsigned char ft5402_FACE_DETECT_PRE_VALUE;
+ unsigned char ft5402_FACE_DETECT_NUM;
+
+ unsigned char ft5402_BIGAREA_PEAK_VALUE_MIN;
+ unsigned char ft5402_BIGAREA_DIFF_VALUE_OVER_NUM;
+ unsigned char ft5402_CUSTOMER_ID;
+ unsigned char ft5402_PERIOD_ACTIVE;
+ unsigned char ft5402_FACE_DETECT_STATISTICS_TX_NUM;
+
+ short ft5402_THGROUP;
+ unsigned char ft5402_THPEAK;
+ unsigned char ft5402_FACE_DETECT_MODE;
+ short ft5402_MAX_TOUCH_VALUE;
+
+ unsigned char ft5402_PWMODE_CTRL;
+ unsigned char ft5402_DRAW_LINE_TH;
+ unsigned char ft5402_POINTS_SUPPORTED;
+
+ unsigned char ft5402_START_RX;
+ short ft5402_ADC_TARGET;
+ unsigned char ft5402_ESD_FILTER_FRAME;
+
+ unsigned char ft5402_POINTS_STABLE_MACRO;
+ unsigned char ft5402_MIN_DELTA_X;
+ unsigned char ft5402_MIN_DELTA_Y;
+ unsigned char ft5402_MIN_DELTA_STEP;
+
+ unsigned char ft5402_ESD_NOISE_MACRO;
+ unsigned char ft5402_ESD_DIFF_VAL;
+ char ft5402_ESD_NEGTIVE; //negtive
+ unsigned char ft5402_ESD_FILTER_FRAMES;
+
+ unsigned char ft5402_IO_LEVEL_SELECT;
+
+ unsigned char ft5402_POINTID_DELAY_COUNT;
+
+ unsigned char ft5402_LIFTUP_FILTER_MACRO;
+
+ unsigned char ft5402_DIFF_HANDLE_MACRO;
+ char ft5402_MIN_WATER; //negtive
+ unsigned char ft5402_MAX_NOISE;
+ unsigned char ft5402_WATER_START_RX;
+ unsigned char ft5402_WATER_START_TX;
+
+ unsigned char ft5402_HOST_NUMBER_SUPPORTED_MACRO;
+ unsigned char ft5402_RAISE_THGROUP;
+ unsigned char ft5402_CHARGER_STATE;
+
+ unsigned char ft5402_FILTERID_START;
+
+ unsigned char ft5402_FRAME_FILTER_EN_MACRO;
+ unsigned char ft5402_FRAME_FILTER_SUB_MAX_TH;
+ unsigned char ft5402_FRAME_FILTER_ADD_MAX_TH;
+ unsigned char ft5402_FRAME_FILTER_SKIP_START_FRAME;
+ unsigned char ft5402_FRAME_FILTER_BAND_EN;
+ unsigned char ft5402_FRAME_FILTER_BAND_WIDTH;
+
+};
+
+struct Struct_Param_FT5402 g_param_ft5402 = {
+ FT5402_KX,
+ FT5402_KY,
+ FT5402_LEMDA_X,
+ FT5402_LEMDA_Y,
+ FT5402_RESOLUTION_X,
+ FT5402_RESOLUTION_Y,
+ FT5402_DIRECTION,
+
+ FT5402_FACE_DETECT_PRE_VALUE,
+ FT5402_FACE_DETECT_NUM,
+ FT5402_BIGAREA_PEAK_VALUE_MIN,
+ FT5402_BIGAREA_DIFF_VALUE_OVER_NUM,
+ FT5402_CUSTOMER_ID,
+ FT5402_RV_G_PERIOD_ACTIVE,
+ FT5402_FACE_DETECT_STATISTICS_TX_NUM,
+
+ FT5402_THGROUP,
+ FT5402_THPEAK,
+ FT5402_FACE_DETECT_MODE,
+ FT5402_MAX_TOUCH_VALUE,
+
+ FT5402_PWMODE_CTRL,
+ FT5402_DRAW_LINE_TH,
+ FT5402_POINTS_SUPPORTED,
+
+ FT5402_START_RX,
+ FT5402_ADC_TARGET,
+ FT5402_ESD_FILTER_FRAME,
+
+ FT5402_POINTS_STABLE_MACRO,
+ FT5402_MIN_DELTA_X,
+ FT5402_MIN_DELTA_Y,
+ FT5402_MIN_DELTA_STEP,
+
+ FT5402_ESD_NOISE_MACRO,
+ FT5402_ESD_DIFF_VAL,
+ FT5402_ESD_NEGTIVE,
+ FT5402_ESD_FILTER_FRAME,
+
+ FT5402_IO_LEVEL_SELECT,
+
+ FT5402_POINTID_DELAY_COUNT,
+
+ FT5402_LIFTUP_FILTER_MACRO,
+
+ FT5402_DIFFDATA_HANDLE,
+ FT5402_MIN_WATER_VAL,
+ FT5402_MAX_NOISE_VAL,
+ FT5402_WATER_HANDLE_START_RX,
+ FT5402_WATER_HANDLE_START_TX,
+
+ FT5402_HOST_NUMBER_SUPPORTED,
+ FT5402_RV_G_RAISE_THGROUP,
+ FT5402_RV_G_CHARGER_STATE,
+
+ FT5402_RV_G_FILTERID_START,
+
+ FT5402_FRAME_FILTER_EN,
+ FT5402_FRAME_FILTER_SUB_MAX_TH,
+ FT5402_FRAME_FILTER_ADD_MAX_TH,
+ FT5402_FRAME_FILTER_SKIP_START_FRAME,
+ FT5402_FRAME_FILTER_BAND_EN,
+ FT5402_FRAME_FILTER_BAND_WIDTH,
+};
+
+char String_Param_FT5402[][64] = {
+ STRING_FT5402_KX,
+ STRING_FT5402_KY,
+ STRING_FT5402_LEMDA_X,
+ STRING_FT5402_LEMDA_Y,
+ STRING_FT5402_RESOLUTION_X,
+ STRING_FT5402_RESOLUTION_Y,
+ STRING_FT5402_DIRECTION,
+ STRING_FT5402_FACE_DETECT_PRE_VALUE,
+ STRING_FT5402_FACE_DETECT_NUM,
+ STRING_FT5402_BIGAREA_PEAK_VALUE_MIN,
+ STRING_FT5402_BIGAREA_DIFF_VALUE_OVER_NUM,
+ STRING_FT5402_CUSTOMER_ID,
+ STRING_FT5402_PERIOD_ACTIVE,
+ STRING_FT5402_FACE_DETECT_STATISTICS_TX_NUM,
+
+ STRING_FT5402_THGROUP,
+ STRING_FT5402_THPEAK,
+ STRING_FT5402_FACE_DETECT_MODE,
+ STRING_FT5402_MAX_TOUCH_VALUE,
+
+ STRING_FT5402_PWMODE_CTRL,
+ STRING_FT5402_DRAW_LINE_TH,
+ STRING_FT5402_POINTS_SUPPORTED,
+
+ STRING_FT5402_START_RX,
+ STRING_FT5402_ADC_TARGET,
+ STRING_FT5402_ESD_FILTER_FRAME,
+
+
+ STRING_ft5402_tx_num,
+ STRING_ft5402_rx_num,
+ STRING_ft5402_gain,
+ STRING_ft5402_voltage ,
+ STRING_ft5402_scanselect,
+
+ STRING_ft5402_tx_order,
+ STRING_ft5402_tx_offset,
+ STRING_ft5402_tx_cap,
+
+ STRING_ft5402_rx_order,
+ STRING_ft5402_rx_offset,
+ STRING_ft5402_rx_cap,
+
+ STRING_FT5402_POINTS_STABLE_MACRO,
+ STRING_FT5402_MIN_DELTA_X,
+ STRING_FT5402_MIN_DELTA_Y,
+ STRING_FT5402_MIN_DELTA_STEP,
+
+ STRING_FT5402_ESD_NOISE_MACRO,
+ STRING_FT5402_ESD_DIFF_VAL,
+ STRING_FT5402_ESD_NEGTIVE,
+ STRING_FT5402_ESD_FILTER_FRAME,
+
+ STRING_FT5402_IO_LEVEL_SELECT,
+
+ STRING_FT5402_POINTID_DELAY_COUNT,
+
+ STRING_FT5402_LIFTUP_FILTER_MACRO,
+
+ STRING_FT5402_DIFFDATA_HANDLE,
+ STRING_FT5402_MIN_WATER_VAL,
+ STRING_FT5402_MAX_NOISE_VAL,
+ STRING_FT5402_WATER_HANDLE_START_RX,
+ STRING_FT5402_WATER_HANDLE_START_TX,
+
+ STRING_FT5402_HOST_NUMBER_SUPPORTED,
+ STRING_FT5402_RV_G_RAISE_THGROUP,
+ STRING_FT5402_RV_G_CHARGER_STATE,
+
+ STRING_FT5402_RV_G_FILTERID_START,
+
+ STRING_FT5402_FRAME_FILTER_EN,
+ STRING_FT5402_FRAME_FILTER_SUB_MAX_TH,
+ STRING_FT5402_FRAME_FILTER_ADD_MAX_TH,
+ STRING_FT5402_FRAME_FILTER_SKIP_START_FRAME,
+ STRING_FT5402_FRAME_FILTER_BAND_EN,
+ STRING_FT5402_FRAME_FILTER_BAND_WIDTH,
+
+};
+
+#define FT5402_APP_NAME "FT5X02_param"
+
+#define FT5402_APP_LEGAL "Legal_File"
+#define FT5402_APP_LEGAL_BYTE_1_STR "BYTE_1"
+#define FT5402_APP_LEGAL_BYTE_2_STR "BYTE_2"
+
+#define FT5402_APP_LEGAL_BYTE_1_VALUE 107
+#define FT5402_APP_LEGAL_BYTE_2_VALUE 201
+
+
+#define FT5402_INI_FILEPATH "/system/etc/firmware/"
+
+#endif
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ft5x0x.c b/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ft5x0x.c
new file mode 100755
index 00000000..a3f6c4c9
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ft5x0x.c
@@ -0,0 +1,896 @@
+/*
+ * drivers/input/touchscreen/ft5x0x/ft5x0x.c
+ *
+ * FocalTech ft5x0x TouchScreen driver.
+ *
+ * Copyright (c) 2010 Focal tech Ltd.
+ *
+ * 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.
+ *
+ *
+ * note: only support mulititouch Wenfs 2010-10-01
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <mach/hardware.h>
+#include <linux/platform_device.h>
+#include <linux/suspend.h>
+#include <linux/wait.h>
+#include <asm/uaccess.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <mach/wmt_iomux.h>
+#include <linux/slab.h>
+#include "ft5x0x.h"
+
+struct ft5x0x_data *pContext=NULL;
+static struct i2c_client *l_client=NULL;
+
+#ifdef TOUCH_KEY
+static int keycodes[NUM_KEYS] ={
+ KEY_MENU,
+ KEY_HOME,
+ KEY_BACK,
+ KEY_SEARCH
+};
+#endif
+
+#define FT5402_CONFIG_NAME "fttpconfig_5402public.ini"
+extern int ft5x0x_read_fw_ver(void);
+extern int ft5x0x_auto_clb(void);
+extern int ft5x0x_upg_fw_bin(struct ft5x0x_data *ft5x0x, int check_ver);
+extern int ft5402_Get_Param_From_Ini(char *config_name);
+extern int ft5402_Init_IC_Param(struct i2c_client *client);
+extern int ft5402_get_ic_param(struct i2c_client *client);
+extern int ft5402_read_reg(struct i2c_client * client, u8 regaddr, u8 * regvalue);
+static unsigned char ft5x0x_debug = 0;
+
+extern int fts_ctpm_fw_upgrade_with_i_file(struct i2c_client * client);
+int ft5x0x_i2c_rxdata(char *rxdata, int length)
+{
+ int ret;
+ struct i2c_msg msg[2];
+
+ msg[0].addr = pContext->addr;
+ msg[0].flags = 0 | I2C_M_NOSTART;
+ msg[0].len = 1;
+ msg[0].buf = rxdata;
+
+ msg[1].addr = pContext->addr;
+ msg[1].flags = I2C_M_RD;
+ msg[1].len = length;
+ msg[1].buf = rxdata;
+
+ ret = i2c_transfer(pContext->client->adapter, msg, 2);
+ if (ret <= 0)
+ dbg_err("msg i2c read error: %d\n", ret);
+
+ return ret;
+}
+
+
+int ft5x0x_i2c_txdata(char *txdata, int length)
+{
+ int ret;
+ struct i2c_msg msg[1];
+
+ msg[0].addr = pContext->addr;
+ msg[0].flags = 0;
+ msg[0].len = length;
+ msg[0].buf = txdata;
+
+ ret = i2c_transfer(pContext->client->adapter, msg, 1);
+ if (ret <= 0)
+ dbg_err("msg i2c read error: %d\n", ret);
+
+ return ret;
+}
+
+static void ft5x0x_penup(struct ft5x0x_data *ft5x0x)
+{
+ input_mt_sync(ft5x0x->input_dev);
+ input_sync(ft5x0x->input_dev);
+#ifdef TOUCH_KEY
+ if(ft5x0x->tskey_used && ft5x0x->tkey_pressed && ft5x0x->tkey_idx < NUM_KEYS ){
+ input_report_key(ft5x0x->input_dev, keycodes[ft5x0x->tkey_idx], 1);
+ input_sync(ft5x0x->input_dev);
+ input_report_key(ft5x0x->input_dev, keycodes[ft5x0x->tkey_idx], 0);
+ input_sync(ft5x0x->input_dev);
+ dbg("report as key event %d \n",ft5x0x->tkey_idx);
+ }
+#endif
+
+ dbg("pen up\n");
+ return;
+}
+
+#ifdef TOUCH_KEY
+static int ft5x0x_read_tskey(struct ft5x0x_data *ft5x0x,int x,int y)
+{
+ int px,py;
+
+ if(ft5x0x->tkey.axis){
+ px = y;
+ py = x;
+ }else{
+ px = x;
+ py = y;
+ }
+
+ if(px >= ft5x0x->tkey.x_lower && px<=ft5x0x->tkey.x_upper){
+ ft5x0x->tkey_pressed = 1;
+ if(py>= ft5x0x->tkey.ypos[0].y_lower && py<= ft5x0x->tkey.ypos[0].y_upper){
+ ft5x0x->tkey_idx= 0;
+ }else if(py>= ft5x0x->tkey.ypos[1].y_lower && py<= ft5x0x->tkey.ypos[1].y_upper){
+ ft5x0x->tkey_idx = 1;
+ }else if(py>= ft5x0x->tkey.ypos[2].y_lower && py<= ft5x0x->tkey.ypos[2].y_upper){
+ ft5x0x->tkey_idx = 2;
+ }else if(py>= ft5x0x->tkey.ypos[3].y_lower && py<= ft5x0x->tkey.ypos[3].y_upper){
+ ft5x0x->tkey_idx = 3;
+ }else{
+ ft5x0x->tkey_idx = NUM_KEYS;
+ }
+
+ return 1;
+ }
+
+ ft5x0x->tkey_pressed = 0;
+ return 0;
+}
+#endif
+
+static int ft5x0x_read_data(struct ft5x0x_data *ft5x0x)
+{
+ int ret = -1;
+ int i = 0;
+ u16 x,y,px,py;
+ u8 buf[64] = {0}, id;
+ struct ts_event *event = &ft5x0x->event;
+
+ if(ft5x0x->nt == 10)
+ ret = ft5x0x_i2c_rxdata(buf, 64);
+ else if(ft5x0x->nt == 5)
+ ret = ft5x0x_i2c_rxdata(buf, 31);
+
+ if (ret <= 0) {
+ dbg_err("read_data i2c_rxdata failed: %d\n", ret);
+ return ret;
+ }
+
+ memset(event, 0, sizeof(struct ts_event));
+ //event->tpoint = buf[2] & 0x03;// 0000 0011
+ //event->tpoint = buf[2] & 0x07;// 000 0111
+ event->tpoint = buf[2]&0x0F;
+ if (event->tpoint == 0) {
+ ft5x0x_penup(ft5x0x);
+ return 1;
+ }
+
+ if (event->tpoint > ft5x0x->nt){
+ dbg_err("tounch pointnum=%d > max:%d\n", event->tpoint,ft5x0x->nt);
+ return -1;
+ }
+
+ for (i = 0; i < event->tpoint; i++){
+ id = (buf[5+i*6] >>4) & 0x0F;//get track id
+ if(ft5x0x->swap){
+ px = (buf[3+i*6] & 0x0F)<<8 |buf[4+i*6];
+ py = (buf[5+i*6] & 0x0F)<<8 |buf[6+i*6];
+ }else{
+ px = (buf[5+i*6] & 0x0F)<<8 |buf[6+i*6];
+ py = (buf[3+i*6] & 0x0F)<<8 |buf[4+i*6];
+ }
+
+ x = px;
+ y = py;
+
+ if(ft5x0x->xch)
+ x = ft5x0x->reslx - px;
+
+ if(ft5x0x->ych)
+ y = ft5x0x->resly - py;
+
+ if(ft5x0x->dbg) printk("F%d: Tid=%d,px=%d,py=%d; x=%d,y=%d\n", i, id, px, py, x, y);
+
+#ifdef TOUCH_KEY
+ if(ft5x0x->tskey_used && event->tpoint==1) {
+ if(ft5x0x_read_tskey(ft5x0x,px,py) > 0) return -1;
+ }
+#endif
+ event->x[i] = x;
+ event->y[i] = y;
+ event->tid[i] = id;
+
+ }
+
+ return 0;
+}
+
+static void ft5x0x_report(struct ft5x0x_data *ft5x0x)
+{
+ int i = 0;
+ struct ts_event *event = &ft5x0x->event;
+
+ for (i = 0; i < event->tpoint; i++){
+ input_report_abs(ft5x0x->input_dev, ABS_MT_TRACKING_ID, event->tid[i]);
+ input_report_abs(ft5x0x->input_dev, ABS_MT_POSITION_X, event->x[i]);
+ input_report_abs(ft5x0x->input_dev, ABS_MT_POSITION_Y, event->y[i]);
+ input_mt_sync(ft5x0x->input_dev);
+ }
+ input_sync(ft5x0x->input_dev);
+
+ return;
+}
+
+static void ft5x0x_read_work(struct work_struct *work)
+{
+ int ret = -1;
+ struct ft5x0x_data *ft5x0x = container_of(work, struct ft5x0x_data, read_work);
+
+ mutex_lock(&ft5x0x->ts_mutex);
+ ret = ft5x0x_read_data(ft5x0x);
+
+ if (ret == 0) ft5x0x_report(ft5x0x);
+
+ wmt_gpio_unmask_irq(ft5x0x->irqgpio);
+ mutex_unlock(&ft5x0x->ts_mutex);
+
+ return;
+}
+
+static irqreturn_t ft5x0x_interrupt(int irq, void *dev)
+{
+ struct ft5x0x_data *ft5x0x = dev;
+
+ if (gpio_irqstatus(ft5x0x->irqgpio))
+ {
+
+ if(ft5x0x_debug == 1)
+ {
+ printk("++++++++++++%s\n",__func__);
+ }
+ wmt_gpio_ack_irq(ft5x0x->irqgpio);
+ if (is_gpio_irqenable(ft5x0x->irqgpio))
+ {
+ wmt_gpio_mask_irq(ft5x0x->irqgpio);
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ if(!ft5x0x->earlysus) queue_work(ft5x0x->workqueue, &ft5x0x->read_work);
+#else
+ queue_work(ft5x0x->workqueue, &ft5x0x->read_work);
+#endif
+
+ }
+ return IRQ_HANDLED;
+ }
+ return IRQ_NONE;
+}
+
+static void ft5x0x_reset(struct ft5x0x_data *ft5x0x)
+{
+ gpio_set_value(ft5x0x->rstgpio, 1);
+ mdelay(5);
+ gpio_set_value(ft5x0x->rstgpio, 0);
+ mdelay(20);
+ gpio_set_value(ft5x0x->rstgpio, 1);
+ mdelay(5);
+
+ return;
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void ft5x0x_early_suspend(struct early_suspend *handler)
+{
+ struct ft5x0x_data *ft5x0x = container_of(handler, struct ft5x0x_data, early_suspend);
+ ft5x0x->earlysus = 1;
+ wmt_gpio_mask_irq(ft5x0x->irqgpio);
+ return;
+}
+
+static void ft5x0x_late_resume(struct early_suspend *handler)
+{
+ struct ft5x0x_data *ft5x0x = container_of(handler, struct ft5x0x_data, early_suspend);
+
+ ft5x0x_reset(ft5x0x);
+ ft5x0x->earlysus = 0;
+
+ wmt_gpio_set_irq_type(ft5x0x->irqgpio, IRQ_TYPE_EDGE_FALLING);
+ wmt_gpio_unmask_irq(ft5x0x->irqgpio);
+
+ return;
+}
+#endif //CONFIG_HAS_EARLYSUSPEND
+
+#ifdef CONFIG_PM
+static int ft5x0x_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct ft5x0x_data *ft5x0x = dev_get_drvdata(&pdev->dev);
+ ft5x0x->earlysus = 1;
+ wmt_gpio_mask_irq(ft5x0x->irqgpio);
+ return 0;
+}
+
+static int ft5x0x_resume(struct platform_device *pdev)
+{
+ struct ft5x0x_data *ft5x0x = dev_get_drvdata(&pdev->dev);
+ ft5x0x_reset(ft5x0x);
+ ft5x0x->earlysus = 0;
+
+ if (ft5x0x->load_cfg) {
+ msleep(350);
+ ft5402_Init_IC_Param(ft5x0x->client);
+ //msleep(50);
+ ft5402_get_ic_param(ft5x0x->client);
+ }
+ wmt_gpio_set_irq_type(ft5x0x->irqgpio, IRQ_TYPE_EDGE_FALLING);
+ wmt_gpio_unmask_irq(ft5x0x->irqgpio);
+ return 0;
+}
+
+#else
+#define ft5x0x_suspend NULL
+#define ft5x0x_resume NULL
+#endif
+
+static ssize_t cat_dbg(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "dbg \n");
+}
+
+static ssize_t echo_dbg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned int dbg = simple_strtoul(buf, NULL, 10);
+ struct ft5x0x_data *ft5x0x = pContext;
+
+ if(dbg){
+ ft5x0x->dbg = 1;
+ }else{
+ ft5x0x->dbg = 0;
+ }
+
+ return count;
+}
+static DEVICE_ATTR(dbg, S_IRUGO | S_IWUSR, cat_dbg, echo_dbg);
+
+static ssize_t cat_clb(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "calibrate \n");
+}
+
+static ssize_t echo_clb(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned int cal = simple_strtoul(buf, NULL, 10);
+
+ if(cal){
+ if(ft5x0x_auto_clb()) printk("Calibrate Failed.\n");
+ }else{
+ printk("calibrate --echo 1 >clb.\n");
+ }
+
+ return count;
+}
+
+static DEVICE_ATTR(clb, S_IRUGO | S_IWUSR, cat_clb, echo_clb);
+
+static ssize_t cat_fupg(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "fupg \n");
+}
+
+static ssize_t echo_fupg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct ft5x0x_data *ft5x0x = pContext;
+ unsigned int upg = simple_strtoul(buf, NULL, 10);
+
+ wmt_gpio_mask_irq(ft5x0x->irqgpio);
+ if(upg){
+ if(ft5x0x_upg_fw_bin(ft5x0x, 0)) printk("Upgrade Failed.\n");
+ }else{
+ printk("upgrade --echo 1 > fupg.\n");
+ }
+ wmt_gpio_unmask_irq(ft5x0x->irqgpio);
+
+ return count;
+}
+static DEVICE_ATTR(fupg, S_IRUGO | S_IWUSR, cat_fupg, echo_fupg);
+
+
+static ssize_t cat_fver(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int fw_ver = ft5x0x_read_fw_ver();
+ return sprintf(buf, "firmware version:0x%02x \n",fw_ver);
+}
+
+static ssize_t echo_fver(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ return count;
+}
+static DEVICE_ATTR(fver, S_IRUGO | S_IWUSR, cat_fver, echo_fver);
+
+static ssize_t cat_addr(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int ret;
+ u8 addrs[32];
+ int cnt=0;
+ struct i2c_msg msg[2];
+ struct ft5x0x_data *ft5x0x = pContext;
+ u8 ver[1]= {0xa6};
+
+ ft5x0x->addr = 1;
+
+ msg[0].addr = ft5x0x->addr;
+ msg[0].flags = 0;
+ msg[0].len = 1;
+ msg[0].buf = ver;
+
+ msg[1].addr = ft5x0x->addr;
+ msg[1].flags = I2C_M_RD;
+ msg[1].len = 1;
+ msg[1].buf = ver;
+
+ while(ft5x0x->addr < 0x80){
+ ret = i2c_transfer(ft5x0x->client->adapter, msg, 2);
+ if(ret == 2) sprintf(&addrs[5*cnt++], " 0x%02x",ft5x0x->addr);
+
+ ft5x0x->addr++;
+ msg[0].addr = msg[1].addr = ft5x0x->addr;
+ }
+
+ return sprintf(buf, "i2c addr:%s\n",addrs);
+}
+
+static ssize_t echo_addr(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned int addr;
+ struct ft5x0x_data *ft5x0x = pContext;
+
+ sscanf(buf,"%x", &addr);
+ ft5x0x->addr = addr;
+
+ return count;
+}
+static DEVICE_ATTR(addr, S_IRUGO | S_IWUSR, cat_addr, echo_addr);
+
+static struct attribute *ft5x0x_attributes[] = {
+ &dev_attr_clb.attr,
+ &dev_attr_fupg.attr,
+ &dev_attr_fver.attr,
+ &dev_attr_dbg.attr,
+ &dev_attr_addr.attr,
+ NULL
+};
+
+static const struct attribute_group ft5x0x_group = {
+ .attrs = ft5x0x_attributes,
+};
+
+static int ft5x0x_sysfs_create_group(struct ft5x0x_data *ft5x0x, const struct attribute_group *group)
+{
+ int err;
+
+ ft5x0x->kobj = kobject_create_and_add("wmtts", NULL) ;
+ if(!ft5x0x->kobj){
+ dbg_err("kobj create failed.\n");
+ return -ENOMEM;
+ }
+
+ /* Register sysfs hooks */
+ err = sysfs_create_group(ft5x0x->kobj, group);
+ if (err < 0){
+ kobject_del(ft5x0x->kobj);
+ dbg_err("Create sysfs group failed!\n");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static void ft5x0x_sysfs_remove_group(struct ft5x0x_data *ft5x0x, const struct attribute_group *group)
+{
+ sysfs_remove_group(ft5x0x->kobj, group);
+ kobject_del(ft5x0x->kobj);
+ return;
+}
+
+static int ft5x0x_probe(struct platform_device *pdev)
+{
+ int i,err = 0;
+ u8 value = 0;
+ u8 cfg_name[32];
+ struct ft5x0x_data *ft5x0x = platform_get_drvdata( pdev);
+
+ ft5x0x->client = l_client;
+ INIT_WORK(&ft5x0x->read_work, ft5x0x_read_work);
+ mutex_init(&ft5x0x->ts_mutex);
+
+ ft5x0x->workqueue = create_singlethread_workqueue(ft5x0x->name);
+ if (!ft5x0x->workqueue) {
+ err = -ESRCH;
+ goto exit_create_singlethread;
+ }
+
+ err = ft5x0x_sysfs_create_group(ft5x0x, &ft5x0x_group);
+ if(err < 0){
+ dbg("create sysfs group failed.\n");
+ goto exit_create_group;
+ }
+
+ ft5x0x->input_dev = input_allocate_device();
+ if (!ft5x0x->input_dev) {
+ err = -ENOMEM;
+ dbg("failed to allocate input device\n");
+ goto exit_input_dev_alloc_failed;
+ }
+
+ ft5x0x->input_dev->name = ft5x0x->name;
+ ft5x0x->input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ set_bit(INPUT_PROP_DIRECT, ft5x0x->input_dev->propbit);
+
+ input_set_abs_params(ft5x0x->input_dev,
+ ABS_MT_POSITION_X, 0, ft5x0x->reslx, 0, 0);
+ input_set_abs_params(ft5x0x->input_dev,
+ ABS_MT_POSITION_Y, 0, ft5x0x->resly, 0, 0);
+ input_set_abs_params(ft5x0x->input_dev,
+ ABS_MT_TRACKING_ID, 0, 20, 0, 0);
+#ifdef TOUCH_KEY
+ if(ft5x0x->tskey_used){
+ for (i = 0; i <NUM_KEYS; i++)
+ set_bit(keycodes[i], ft5x0x->input_dev->keybit);
+
+ ft5x0x->input_dev->keycode = keycodes;
+ ft5x0x->input_dev->keycodesize = sizeof(unsigned int);
+ ft5x0x->input_dev->keycodemax = NUM_KEYS;
+ }
+#endif
+
+ err = input_register_device(ft5x0x->input_dev);
+ if (err) {
+ dbg_err("ft5x0x_ts_probe: failed to register input device.\n");
+ goto exit_input_register_device_failed;
+ }
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ ft5x0x->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+ ft5x0x->early_suspend.suspend = ft5x0x_early_suspend;
+ ft5x0x->early_suspend.resume = ft5x0x_late_resume;
+ register_early_suspend(&ft5x0x->early_suspend);
+#endif
+
+ if(ft5x0x->upg){
+ if (fts_ctpm_fw_upgrade_with_i_file(ft5x0x->client) < 0) {
+ printk("ft5x0x_probe -----upgrade failed!-\n");
+ }
+ else
+ {
+ printk("ft5x0x_probe -----upgrade successful!-\n");
+ wmt_setsyspara("wmt.io.ts.upg","");
+ ft5x0x_reset(ft5x0x);
+ }
+ ft5x0x->upg = 0x00;
+ }
+
+ if(request_irq(ft5x0x->irq, ft5x0x_interrupt, IRQF_SHARED, ft5x0x->name, ft5x0x) < 0){
+ dbg_err("Could not allocate irq for ts_ft5x0x !\n");
+ err = -1;
+ goto exit_register_irq;
+ }
+
+ { // check if need to load config to IC or not
+ err = ft5402_read_reg(ft5x0x->client, 0xa3, &value);
+ if (err < 0)
+ dbg_err("Read reg 0xa3 failed.\n");
+ else
+ printk("0xa3 reg = %d\n", value);
+ if (value == 3)
+ ft5x0x->load_cfg = 1;
+ else
+ ft5x0x->load_cfg = 0;
+ }
+ ft5x0x_reset(ft5x0x);
+
+ if (ft5x0x->load_cfg) {
+ msleep(350); /*make sure CTP already finish startup process*/
+ sprintf(cfg_name, "%s.ini", ft5x0x->cfg_name);
+ printk("Config file name: %s\n", cfg_name);
+ if (ft5402_Get_Param_From_Ini(cfg_name) >= 0)
+ ft5402_Init_IC_Param(ft5x0x->client);
+ else
+ dbg_err("[FTS]-------Get ft5402 param from INI file failed\n");
+ ft5402_get_ic_param(ft5x0x->client);
+ }
+
+ wmt_gpio_set_irq_type(ft5x0x->irqgpio, IRQ_TYPE_EDGE_FALLING);
+ wmt_gpio_unmask_irq(ft5x0x->irqgpio);
+
+
+ return 0;
+
+exit_register_irq:
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&ft5x0x->early_suspend);
+#endif
+exit_input_register_device_failed:
+ input_free_device(ft5x0x->input_dev);
+exit_input_dev_alloc_failed:
+ ft5x0x_sysfs_remove_group(ft5x0x, &ft5x0x_group);
+exit_create_group:
+ cancel_work_sync(&ft5x0x->read_work);
+ destroy_workqueue(ft5x0x->workqueue);
+exit_create_singlethread:
+ return err;
+}
+
+static int ft5x0x_remove(struct platform_device *pdev)
+{
+ struct ft5x0x_data *ft5x0x = platform_get_drvdata( pdev);
+
+ cancel_work_sync(&ft5x0x->read_work);
+ flush_workqueue(ft5x0x->workqueue);
+ destroy_workqueue(ft5x0x->workqueue);
+
+ free_irq(ft5x0x->irq, ft5x0x);
+ wmt_gpio_mask_irq(ft5x0x->irqgpio);
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&ft5x0x->early_suspend);
+#endif
+ input_unregister_device(ft5x0x->input_dev);
+
+ ft5x0x_sysfs_remove_group(ft5x0x, &ft5x0x_group);
+
+ mutex_destroy(&ft5x0x->ts_mutex);
+ dbg("remove...\n");
+ return 0;
+}
+
+static void ft5x0x_release(struct device *device)
+{
+ return;
+}
+
+static struct platform_device ft5x0x_device = {
+ .name = DEV_FT5X0X,
+ .id = 0,
+ .dev = {.release = ft5x0x_release},
+};
+
+static struct platform_driver ft5x0x_driver = {
+ .driver = {
+ .name = DEV_FT5X0X,
+ .owner = THIS_MODULE,
+ },
+ .probe = ft5x0x_probe,
+ .remove = ft5x0x_remove,
+ .suspend = ft5x0x_suspend,
+ .resume = ft5x0x_resume,
+};
+
+static int check_touch_env(struct ft5x0x_data *ft5x0x)
+{
+ int i,ret = 0;
+ int len = 96;
+ int Enable;
+ char retval[96] = {0};
+ char *p=NULL;
+ char *s=NULL;
+
+ // Get u-boot parameter
+ ret = wmt_getsyspara("wmt.io.touch", retval, &len);
+ if(ret){
+ //printk("MST FT5x0x:Read wmt.io.touch Failed.\n");
+ return -EIO;
+ }
+ sscanf(retval,"%d:",&Enable);
+ //check touch enable
+ if(Enable == 0){
+ //printk("FT5x0x Touch Screen Is Disabled.\n");
+ return -ENODEV;
+ }
+
+ p = strchr(retval,':');
+ p++;
+ if(strncmp(p,"ft5301",6)==0){//check touch ID
+ ft5x0x->id = FT5301;
+ ft5x0x->name = DEV_FT5301;
+ }else if(strncmp(p,"ft5406",6)==0){
+ ft5x0x->id = FT5406;
+ ft5x0x->name = DEV_FT5406;
+ }else if(strncmp(p,"ft6336",6)==0){
+ ft5x0x->id = FT6336;
+ ft5x0x->name = DEV_FT6336;
+ }else if(strncmp(p,"ft5206",6)==0){
+ ft5x0x->id = FT5206;
+ ft5x0x->name = DEV_FT5206;
+ }else if(strncmp(p,"ft5606",6)==0){
+ ft5x0x->id = FT5606;
+ ft5x0x->name = DEV_FT5606;
+ }else if(strncmp(p,"ft5306",6)==0){
+ ft5x0x->id = FT5306;
+ ft5x0x->name = DEV_FT5306;
+ }else if(strncmp(p,"ft5302",6)==0){
+ ft5x0x->id = FT5302;
+ ft5x0x->name = DEV_FT5302;
+ }else if(strncmp(p,"ft5",3)==0)
+ {
+ ft5x0x->id = FT5X0X;
+ ft5x0x->name = DEV_FT5X0X;
+ }else{
+ printk("FT5x0x touch disabled.\n");
+ return -ENODEV;
+ }
+
+ s = strchr(p,':');
+ strncpy(ft5x0x->cfg_name, p, s-p);
+
+ p = s + 1;
+ sscanf(p,"%d:%d:%d:%d:%d:%d:%d:%d:%x", &ft5x0x->irqgpio, &ft5x0x->reslx, &ft5x0x->resly, &ft5x0x->rstgpio, &ft5x0x->swap, &ft5x0x->xch, &ft5x0x->ych, &ft5x0x->nt, &ft5x0x->addr);
+
+ ft5x0x->irq = IRQ_GPIO;
+ printk("%s irqgpio=%d, reslx=%d, resly=%d, rstgpio=%d, swap=%d, xch=%d, ych=%d, nt=%d, addr=%x\n", ft5x0x->name, ft5x0x->irqgpio, ft5x0x->reslx, ft5x0x->resly, ft5x0x->rstgpio, ft5x0x->swap, ft5x0x->xch, ft5x0x->ych, ft5x0x->nt, ft5x0x->addr);
+
+ memset(retval,0x00,sizeof(retval));
+ ret = wmt_getsyspara("wmt.io.ts.upg", retval, &len);
+ if(!ret){
+ ft5x0x->upg = 1;
+ strncpy(ft5x0x->fw_name, retval, sizeof(ft5x0x->fw_name));
+ }
+
+#ifdef TOUCH_KEY
+ memset(retval,0x00,sizeof(retval));
+ ret = wmt_getsyspara("wmt.io.tskey", retval, &len);
+ if(!ret){
+ sscanf(retval,"%d:", &ft5x0x->nkeys);
+ p = strchr(retval,':');
+ p++;
+ for(i=0; i < ft5x0x->nkeys; i++ ){
+ sscanf(p,"%d:%d", &ft5x0x->tkey.ypos[i].y_lower, &ft5x0x->tkey.ypos[i].y_upper);
+ p = strchr(p,':');
+ p++;
+ p = strchr(p,':');
+ p++;
+ }
+ sscanf(p,"%d:%d:%d", &ft5x0x->tkey.axis, &ft5x0x->tkey.x_lower, &ft5x0x->tkey.x_upper);
+ ft5x0x->tskey_used = 1;
+ }
+#endif
+ return 0;
+}
+
+struct i2c_board_info ts_i2c_board_info = {
+ .type = TS_I2C_NAME,
+ .flags = 0x00,
+ .addr = FT5406_I2C_ADDR,
+ .platform_data = NULL,
+ .archdata = NULL,
+ .irq = -1,
+};
+
+static int ts_i2c_register_device (void)
+{
+ struct i2c_board_info *ts_i2c_bi;
+ struct i2c_adapter *adapter = NULL;
+ //struct i2c_client *client = NULL;
+
+ //ts_i2c_board_info.addr = FT5406_I2C_ADDR;
+ ts_i2c_bi = &ts_i2c_board_info;
+ adapter = i2c_get_adapter(FT5X0X_I2C_BUS);/*in bus 1*/
+
+ if (NULL == adapter) {
+ printk("can not get i2c adapter, client address error\n");
+ return -1;
+ }
+ l_client = i2c_new_device(adapter, ts_i2c_bi);
+ if (l_client == NULL) {
+ printk("allocate i2c client failed\n");
+ return -1;
+ }
+ i2c_put_adapter(adapter);
+ return 0;
+}
+
+static void ts_i2c_unregister_device(void)
+{
+ if (l_client != NULL)
+ {
+ i2c_unregister_device(l_client);
+ l_client = NULL;
+ }
+}
+
+static int __init ft5x0x_init(void)
+{
+ int ret = -ENOMEM;
+ struct ft5x0x_data *ft5x0x=NULL;
+
+ if (ts_i2c_register_device()<0)
+ {
+ dbg("Error to run ts_i2c_register_device()!\n");
+ return -1;
+ }
+
+ ft5x0x = kzalloc(sizeof(struct ft5x0x_data), GFP_KERNEL);
+ if(!ft5x0x){
+ dbg_err("mem alloc failed.\n");
+ return -ENOMEM;
+ }
+
+ pContext = ft5x0x;
+ ret = check_touch_env(ft5x0x);
+ if(ret < 0)
+ goto exit_free_mem;
+
+ ret = gpio_request(ft5x0x->irqgpio, "ts_irq");
+ if (ret < 0) {
+ printk("gpio(%d) touchscreen irq request fail\n", ft5x0x->irqgpio);
+ goto exit_free_mem;
+ }
+ wmt_gpio_setpull(ft5x0x->irqgpio, WMT_GPIO_PULL_UP);
+ gpio_direction_input(ft5x0x->irqgpio);
+
+ ret = gpio_request(ft5x0x->rstgpio, "ts_rst");
+ if (ret < 0) {
+ printk("gpio(%d) touchscreen reset request fail\n", ft5x0x->rstgpio);
+ goto exit_free_irqgpio;
+ }
+ gpio_direction_output(ft5x0x->rstgpio, 1);
+
+
+ ret = platform_device_register(&ft5x0x_device);
+ if(ret){
+ dbg_err("register platform drivver failed!\n");
+ goto exit_free_gpio;
+ }
+ platform_set_drvdata(&ft5x0x_device, ft5x0x);
+
+ ret = platform_driver_register(&ft5x0x_driver);
+ if(ret){
+ dbg_err("register platform device failed!\n");
+ goto exit_unregister_pdev;
+ }
+
+ return ret;
+
+exit_unregister_pdev:
+ platform_device_unregister(&ft5x0x_device);
+exit_free_gpio:
+ gpio_free(ft5x0x->rstgpio);
+exit_free_irqgpio:
+ gpio_free(ft5x0x->irqgpio);
+exit_free_mem:
+ kfree(ft5x0x);
+ pContext = NULL;
+ return ret;
+}
+
+static void ft5x0x_exit(void)
+{
+ if(!pContext) return;
+
+ gpio_free(pContext->rstgpio);
+ gpio_free(pContext->irqgpio);
+ platform_driver_unregister(&ft5x0x_driver);
+ platform_device_unregister(&ft5x0x_device);
+ kfree(pContext);
+ ts_i2c_unregister_device();
+ return;
+}
+
+late_initcall(ft5x0x_init);
+module_exit(ft5x0x_exit);
+module_param (ft5x0x_debug, byte, 0644);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("FocalTech.Touch");
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ft5x0x.h b/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ft5x0x.h
new file mode 100755
index 00000000..417af1f5
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ft5x0x.h
@@ -0,0 +1,205 @@
+#ifndef __LINUX_FT5X0X_TS_H__
+#define __LINUX_FT5X0X_TS_H__
+
+#define DEV_FT5206 "touch_ft5206"
+#define DEV_FT5301 "touch_ft5301"
+#define DEV_FT5302 "touch_ft5302"
+#define DEV_FT5306 "touch_ft5306"
+#define DEV_FT5406 "touch_ft5406"
+#define DEV_FT5606 "touch_ft5606"
+#define DEV_FT6336 "touch_ft6336"
+
+
+#define DEV_FT5X0X "touch_ft5x0x"
+#define TS_I2C_NAME "ft5x0x-ts"
+#define FT5406_I2C_ADDR 0x38
+#define FT5X0X_I2C_BUS 0x01
+
+enum FT5X0X_ID{
+ FT5206 =1,
+ FT5301,
+ FT5302,
+ FT5306,
+ FT5406,
+ FT5606,
+ FT6336,
+ FT5X0X,
+};
+
+struct vt1603_ts_cal_info {
+ int a1;
+ int b1;
+ int c1;
+ int a2;
+ int b2;
+ int c2;
+ int delta;
+};
+
+#define SUPPORT_POINT_NUM 5//10
+struct ts_event {
+ int x[SUPPORT_POINT_NUM];
+ int y[SUPPORT_POINT_NUM];
+ int tid[SUPPORT_POINT_NUM];
+ int tpoint;
+};
+
+#define TOUCH_KEY
+
+#ifdef TOUCH_KEY
+#define NUM_KEYS 4
+struct key_pos{
+ int y_lower;
+ int y_upper;
+};
+
+struct ts_key{
+ int axis;
+ int x_lower;
+ int x_upper;
+ struct key_pos ypos[NUM_KEYS];
+};
+#endif
+
+struct ft5x0x_data {
+ int id;
+ unsigned int addr;
+ const char *name;
+ u8 fw_name[64];
+ u8 cfg_name[32];
+
+ struct i2c_client *client;
+ struct input_dev *input_dev;
+ struct ts_event event;
+ struct work_struct read_work;
+ struct workqueue_struct *workqueue;
+ struct mutex ts_mutex;
+ struct kobject *kobj;
+ #ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend early_suspend;
+#endif
+ int earlysus;
+
+ int reslx;
+ int resly;
+
+ int tw;
+ int th;
+
+ int irq;
+ int irqgpio;
+ int rstgpio;
+/*
+ int igp_idx;
+ int igp_bit;
+
+ int rgp_idx;
+ int rgp_bit;
+*/
+
+ int nt;
+ int nb;
+ int xch;
+ int ych;
+ int swap;
+
+ int upg;
+ int load_cfg;
+ int dbg;
+#ifdef TOUCH_KEY
+ int tskey_used;
+ int tkey_pressed;
+ int nkeys;
+ int tkey_idx;
+ struct ts_key tkey;
+#endif
+
+};
+
+enum ft5x0x_ts_regs {
+ FT5X0X_REG_THGROUP = 0x80, /* touch threshold, related to sensitivity */
+ FT5X0X_REG_THPEAK = 0x81,
+ FT5X0X_REG_THCAL = 0x82,
+ FT5X0X_REG_THWATER = 0x83,
+ FT5X0X_REG_THTEMP = 0x84,
+ FT5X0X_REG_THDIFF = 0x85,
+ FT5X0X_REG_CTRL = 0x86,
+ FT5X0X_REG_TIMEENTERMONITOR = 0x87,
+ FT5X0X_REG_PERIODACTIVE = 0x88, /* report rate */
+ FT5X0X_REG_PERIODMONITOR = 0x89,
+ FT5X0X_REG_HEIGHT_B = 0x8a,
+ FT5X0X_REG_MAX_FRAME = 0x8b,
+ FT5X0X_REG_DIST_MOVE = 0x8c,
+ FT5X0X_REG_DIST_POINT = 0x8d,
+ FT5X0X_REG_FEG_FRAME = 0x8e,
+ FT5X0X_REG_SINGLE_CLICK_OFFSET = 0x8f,
+ FT5X0X_REG_DOUBLE_CLICK_TIME_MIN = 0x90,
+ FT5X0X_REG_SINGLE_CLICK_TIME = 0x91,
+ FT5X0X_REG_LEFT_RIGHT_OFFSET = 0x92,
+ FT5X0X_REG_UP_DOWN_OFFSET = 0x93,
+ FT5X0X_REG_DISTANCE_LEFT_RIGHT = 0x94,
+ FT5X0X_REG_DISTANCE_UP_DOWN = 0x95,
+ FT5X0X_REG_ZOOM_DIS_SQR = 0x96,
+ FT5X0X_REG_RADIAN_VALUE =0x97,
+ FT5X0X_REG_MAX_X_HIGH = 0x98,
+ FT5X0X_REG_MAX_X_LOW = 0x99,
+ FT5X0X_REG_MAX_Y_HIGH = 0x9a,
+ FT5X0X_REG_MAX_Y_LOW = 0x9b,
+ FT5X0X_REG_K_X_HIGH = 0x9c,
+ FT5X0X_REG_K_X_LOW = 0x9d,
+ FT5X0X_REG_K_Y_HIGH = 0x9e,
+ FT5X0X_REG_K_Y_LOW = 0x9f,
+ FT5X0X_REG_AUTO_CLB_MODE = 0xa0,
+ FT5X0X_REG_LIB_VERSION_H = 0xa1,
+ FT5X0X_REG_LIB_VERSION_L = 0xa2,
+ FT5X0X_REG_CIPHER = 0xa3,
+ FT5X0X_REG_MODE = 0xa4,
+ FT5X0X_REG_PMODE = 0xa5, /* Power Consume Mode */
+ FT5X0X_REG_FIRMID = 0xa6, /* Firmware version */
+ FT5X0X_REG_STATE = 0xa7,
+ FT5X0X_REG_FT5201ID = 0xa8,
+ FT5X0X_REG_ERR = 0xa9,
+ FT5X0X_REG_CLB = 0xaa,
+};
+
+//FT5X0X_REG_PMODE
+#define PMODE_ACTIVE 0x00
+#define PMODE_MONITOR 0x01
+#define PMODE_STANDBY 0x02
+#define PMODE_HIBERNATE 0x03
+
+#define DEV_NAME "wmtts"
+#define DEV_MAJOR 11
+
+#define TS_IOC_MAGIC 't'
+#define TS_IOCTL_CAL_START _IO(TS_IOC_MAGIC, 1)
+#define TS_IOCTL_CAL_DONE _IOW(TS_IOC_MAGIC, 2, int*)
+#define TS_IOCTL_GET_RAWDATA _IOR(TS_IOC_MAGIC, 3, int*)
+#define TS_IOCTL_CAL_QUIT _IOW(TS_IOC_MAGIC, 4, int*)
+#define TS_IOCTL_CAL_CAP _IOW(TS_IOC_MAGIC, 5, int*)
+#define TS_IOC_MAXNR 5
+
+extern int wmt_setsyspara(char *varname, unsigned char *varval);
+extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
+extern int wmt_i2c_xfer_continue_if_4(struct i2c_msg *msg, unsigned int num,int bus_id);
+
+//#define FT_DEBUG
+
+#undef dbg
+#ifdef FT_DEBUG
+ #define dbg(fmt,args...) printk("DBG:%s_%d:"fmt,__FUNCTION__,__LINE__,##args)
+#else
+ #define dbg(fmt,args...)
+#endif
+
+#undef dbg_err
+#define dbg_err(fmt,args...) printk("ERR:%s_%d:"fmt,__FUNCTION__,__LINE__,##args)
+
+//#define FTS_DBG
+#ifdef FTS_DBG
+#define DBG(fmt, args...) printk("[FTS]" fmt, ## args)
+#else
+#define DBG(fmt, args...) do{}while(0)
+#endif
+
+#endif
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ft5x0x_upg.c b/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ft5x0x_upg.c
new file mode 100755
index 00000000..9db72130
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ft5x0x_upg.c
@@ -0,0 +1,506 @@
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/mount.h>
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+#include <linux/syscalls.h>
+#include <asm/unistd.h>
+#include <asm/uaccess.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include "ft5x0x.h"
+
+typedef enum
+{
+ ERR_OK,
+ ERR_MODE,
+ ERR_READID,
+ ERR_ERASE,
+ ERR_STATUS,
+ ERR_ECC,
+ ERR_DL_ERASE_FAIL,
+ ERR_DL_PROGRAM_FAIL,
+ ERR_DL_VERIFY_FAIL,
+ ERR_FMID
+}E_UPGRADE_ERR_TYPE;
+
+#define FT5X_CTPM_ID_L 0X79
+#define FT5X_CTPM_ID_H 0X03
+
+#define FT56_CTPM_ID_L 0X79
+#define FT56_CTPM_ID_H 0X06
+
+#define FTS_PACKET_LENGTH 128
+
+extern struct ft5x0x_data *pContext;
+extern int ft5x0x_i2c_rxdata(char *rxdata, int length);
+extern int ft5x0x_i2c_txdata(char *txdata, int length);
+
+static int ft5x0x_write_reg(u8 addr, u8 para)
+{
+ u8 buf[2];
+ int ret = -1;
+
+ buf[0] = addr;
+ buf[1] = para;
+ ret = ft5x0x_i2c_txdata(buf, 2);
+ if (ret <= 0) {
+ printk("write reg failed! %x ret: %d", buf[0], ret);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int ft5x0x_read_reg(u8 addr, u8 *pdata)
+{
+ int ret;
+ u8 buf[2];
+ struct i2c_msg msgs[2];
+
+ //
+ buf[0] = addr; //register address
+
+ msgs[0].addr = pContext->addr;
+ msgs[0].flags = 0 | I2C_M_NOSTART;
+ msgs[0].len = 1;
+ msgs[0].buf = buf;
+
+ msgs[1].addr = pContext->addr;
+ msgs[1].flags = I2C_M_RD;
+ msgs[1].len = 1;
+ msgs[1].buf = pdata;
+
+ //ret = wmt_i2c_xfer_continue_if_4(msgs, 2, FT5X0X_I2C_BUS);
+ ret = i2c_transfer(pContext->client->adapter, msgs, 2);
+ if (ret <= 0)
+ printk("msg %s i2c read error: %d\n", __func__, ret);
+
+ return ret;
+
+}
+
+
+/*
+[function]:
+ send a command to ctpm.
+[parameters]:
+ btcmd[in] :command code;
+ btPara1[in] :parameter 1;
+ btPara2[in] :parameter 2;
+ btPara3[in] :parameter 3;
+ num[in] :the valid input parameter numbers, if only command code needed and no parameters followed,then the num is 1;
+[return]:
+ FTS_TRUE :success;
+ FTS_FALSE :io fail;
+*/
+static u8 cmd_write(u8 *cmd,u8 num)
+{
+ return ft5x0x_i2c_txdata(cmd, num);
+}
+
+/*
+[function]:
+ write data to ctpm , the destination address is 0.
+[parameters]:
+ pbt_buf[in] :point to data buffer;
+ bt_len[in] :the data numbers;
+[return]:
+ FTS_TRUE :success;
+ FTS_FALSE :io fail;
+*/
+static u8 byte_write(u8* pbt_buf, int dw_len)
+{
+
+ return ft5x0x_i2c_txdata( pbt_buf, dw_len);
+}
+
+/*
+[function]:
+ read out data from ctpm,the destination address is 0.
+[parameters]:
+ pbt_buf[out] :point to data buffer;
+ bt_len[in] :the data numbers;
+[return]:
+ FTS_TRUE :success;
+ FTS_FALSE :io fail;
+*/
+static u8 byte_read(u8* pbt_buf, u8 bt_len)
+{
+ int ret;
+ struct i2c_msg msg[1];
+
+ msg[0].addr = pContext->addr;
+ msg[0].flags = I2C_M_RD;
+ msg[0].len = bt_len;
+ msg[0].buf = pbt_buf;
+
+ ret = i2c_transfer(pContext->client->adapter, msg, 1);
+ //ret = wmt_i2c_xfer_continue_if_4(msg, 1, FT5X0X_I2C_BUS);
+ if (ret <= 0)
+ printk("msg i2c read error: %d\n", ret);
+
+ return ret;
+}
+
+
+/*
+[function]:
+ burn the FW to ctpm.
+[parameters]:(ref. SPEC)
+ pbt_buf[in] :point to Head+FW ;
+ dw_lenth[in]:the length of the FW + 6(the Head length);
+ bt_ecc[in] :the ECC of the FW
+[return]:
+ ERR_OK :no error;
+ ERR_MODE :fail to switch to UPDATE mode;
+ ERR_READID :read id fail;
+ ERR_ERASE :erase chip fail;
+ ERR_STATUS :status error;
+ ERR_ECC :ecc error.
+*/
+static E_UPGRADE_ERR_TYPE ft5x0x_fw_upgrade(struct ft5x0x_data *ft5x0x, u8* pbt_buf, int dw_lenth)
+{
+ int i = 0,j = 0,i_ret;
+ int packet_number;
+ int temp,lenght;
+ u8 packet_buf[FTS_PACKET_LENGTH + 6];
+ u8 auc_i2c_write_buf[10];
+ u8 reg_val[2] = {0};
+ u8 ctpm_id[2] = {0};
+ u8 cmd[4];
+ u8 bt_ecc;
+
+ /*********Step 1:Reset CTPM *****/
+ /*write 0xaa to register 0xfc*/
+ ft5x0x_write_reg(0xfc,0xaa);
+ msleep(50);
+ /*write 0x55 to register 0xfc*/
+ ft5x0x_write_reg(0xfc,0x55);
+ printk("[FTS] Step 1: Reset CTPM.\n");
+ msleep(30);
+
+ /*********Step 2:Enter upgrade mode *****/
+ auc_i2c_write_buf[0] = 0x55;
+ auc_i2c_write_buf[1] = 0xaa;
+ do{
+ i ++;
+ i_ret = byte_write(auc_i2c_write_buf, 2);
+ mdelay(5);
+ }while(i_ret <= 0 && i < 5 );
+ msleep(20);
+
+ /*********Step 3:check READ-ID**********/
+ if(ft5x0x->id == FT5606){
+ ctpm_id[0] = FT56_CTPM_ID_L;
+ ctpm_id[1] = FT56_CTPM_ID_H;
+ }else{
+ ctpm_id[0] = FT5X_CTPM_ID_L;
+ ctpm_id[1] = FT5X_CTPM_ID_H;
+ }
+
+ cmd[0] = 0x90;
+ cmd[1] = 0x00;
+ cmd[2] = 0x00;
+ cmd[3] = 0x00;
+ cmd_write(cmd,4);
+ byte_read(reg_val,2);
+ if (reg_val[0] == ctpm_id[0] && reg_val[1] == ctpm_id[1]){
+ printk("[FTS] Step 3: CTPM ID,ID1 = 0x%x,ID2 = 0x%x\n",reg_val[0],reg_val[1]);
+ }else{
+ printk("[FTS] ID_ERROR: CTPM ID,ID1 = 0x%x,ID2 = 0x%x\n",reg_val[0],reg_val[1]);
+ return ERR_READID;
+ }
+
+ cmd[0] = 0xcd;
+ cmd_write(cmd,1);
+ byte_read(reg_val,1);
+ printk("[FTS] bootloader version = 0x%x\n", reg_val[0]);
+
+ /******Step 4:erase app and panel paramenter area *********/
+ cmd[0] = 0x61;
+ cmd_write(cmd,1); //erase app area
+ msleep(1500);
+ cmd[0] = 0x63;
+ cmd_write(cmd,1); //erase panel parameter area
+ msleep(100);
+ printk("[FTS] Step 4: erase. \n");
+
+ /*********Step 5:write firmware(FW) to ctpm flash*********/
+ bt_ecc = 0;
+ printk("[FTS] Step 5: start upgrade. \n");
+ dw_lenth = dw_lenth - 8;
+ packet_number = (dw_lenth) / FTS_PACKET_LENGTH;
+ packet_buf[0] = 0xbf;
+ packet_buf[1] = 0x00;
+ for (j=0;j<packet_number;j++){
+ temp = j * FTS_PACKET_LENGTH;
+ packet_buf[2] = (u8)(temp>>8);
+ packet_buf[3] = (u8)temp;
+ lenght = FTS_PACKET_LENGTH;
+ packet_buf[4] = (u8)(lenght>>8);
+ packet_buf[5] = (u8)lenght;
+
+ for (i=0;i<FTS_PACKET_LENGTH;i++){
+ packet_buf[6+i] = pbt_buf[j*FTS_PACKET_LENGTH + i];
+ bt_ecc ^= packet_buf[6+i];
+ }
+
+ byte_write(&packet_buf[0],FTS_PACKET_LENGTH + 6);
+ mdelay(FTS_PACKET_LENGTH/6 + 1);
+ if ((j * FTS_PACKET_LENGTH % 1024) == 0){
+ printk("[FTS] upgrade the 0x%x th byte.\n", ((unsigned int)j) * FTS_PACKET_LENGTH);
+ }
+ }
+
+ if ((dw_lenth) % FTS_PACKET_LENGTH > 0){
+ temp = packet_number * FTS_PACKET_LENGTH;
+ packet_buf[2] = (u8)(temp>>8);
+ packet_buf[3] = (u8)temp;
+
+ temp = (dw_lenth) % FTS_PACKET_LENGTH;
+ packet_buf[4] = (u8)(temp>>8);
+ packet_buf[5] = (u8)temp;
+
+ for (i=0;i<temp;i++){
+ packet_buf[6+i] = pbt_buf[ packet_number*FTS_PACKET_LENGTH + i];
+ bt_ecc ^= packet_buf[6+i];
+ }
+
+ byte_write(&packet_buf[0],temp+6);
+ mdelay(20);
+ }
+
+ //send the last six byte
+ for (i = 0; i<6; i++){
+ temp = 0x6ffa + i;
+ packet_buf[2] = (u8)(temp>>8);
+ packet_buf[3] = (u8)temp;
+ temp =1;
+ packet_buf[4] = (u8)(temp>>8);
+ packet_buf[5] = (u8)temp;
+ packet_buf[6] = pbt_buf[ dw_lenth + i];
+ bt_ecc ^= packet_buf[6];
+
+ byte_write(&packet_buf[0],7);
+ mdelay(20);
+ }
+
+ /*********Step 6: read out checksum********************/
+ /*send the opration head*/
+ cmd[0] = 0xcc;
+ cmd_write(cmd,1);
+ byte_read(reg_val,1);
+ printk("[FTS] Step 6:read ECC 0x%x, firmware ECC 0x%x. \n", reg_val[0], bt_ecc);
+ if(reg_val[0] != bt_ecc){
+ return ERR_ECC;
+ }
+
+ /*********Step 7: reset the new FW***********************/
+ cmd[0] = 0x07;
+ cmd_write(cmd,1);
+
+ msleep(300); //make sure CTP startup normally
+
+ return ERR_OK;
+}
+
+int ft5x0x_auto_clb(void)
+{
+ u8 uc_temp;
+ u8 i ;
+
+ printk("[FTS] start auto CLB.\n");
+ msleep(200);
+ ft5x0x_write_reg(0, 0x40);
+ msleep(100); //make sure already enter factory mode
+ ft5x0x_write_reg(2, 0x4); //write command to start calibration
+ msleep(300);
+ for(i=0;i<100;i++){
+ ft5x0x_read_reg(0,&uc_temp);
+ if ( ((uc_temp&0x70)>>4) == 0x0){ //return to normal mode, calibration finish
+ break;
+ }
+ msleep(200);
+ printk("[FTS] waiting calibration %d\n",i);
+ }
+ printk("[FTS] calibration OK.\n");
+
+ msleep(300);
+ ft5x0x_write_reg(0, 0x40); //goto factory mode
+ msleep(100); //make sure already enter factory mode
+ ft5x0x_write_reg(2, 0x5); //store CLB result
+ msleep(300);
+ ft5x0x_write_reg(0, 0x0); //return to normal mode
+ msleep(300);
+ printk("[FTS] store CLB result OK.\n");
+ return 0;
+}
+
+static int ft5x0x_get_bin_ver(const u8 *fw, int fw_szie)
+{
+ if (fw_szie > 2){
+ return fw[fw_szie - 2];
+ }else{
+ return 0xff; //default value
+ }
+ return 0xff;
+}
+
+int ft5x0x_read_fw_ver(void)
+{
+ u8 ver=0;
+ int ret=0;
+
+ ret = ft5x0x_read_reg(FT5X0X_REG_FIRMID, &ver);
+ if(ret > 0)
+ return ver;
+
+ return ret;
+}
+
+
+static int ft5x0x_get_fw_szie(const char *fw_name)
+{
+ struct file *pfile = NULL;
+ struct inode *inode;
+ unsigned long magic;
+ off_t fsize = 0;
+
+ if(fw_name == NULL){
+ dbg_err("Firmware name error.\n");
+ return -EFAULT;
+ }
+
+ if (NULL == pfile)
+ pfile = filp_open(fw_name, O_RDONLY, 0);
+
+ if (IS_ERR(pfile)) {
+ dbg_err("File open error: %s.\n", fw_name);
+ return -EIO;
+ }
+
+ inode = pfile->f_dentry->d_inode;
+ magic = inode->i_sb->s_magic;
+ fsize = inode->i_size;
+ filp_close(pfile, NULL);
+ return fsize;
+}
+
+static int ft5x0x_read_fw(const char *fw_name, u8 *buf)
+{
+ struct file *pfile = NULL;
+ struct inode *inode;
+ unsigned long magic;
+ off_t fsize;
+ loff_t pos;
+ mm_segment_t fs;
+
+ if(fw_name == NULL){
+ dbg_err("Firmware name error.\n");
+ return -EFAULT;
+ }
+
+ if (NULL == pfile)
+ pfile = filp_open(fw_name, O_RDONLY, 0);
+ if (IS_ERR(pfile)) {
+ dbg_err("File open error: %s.\n", fw_name);
+ return -EIO;
+ }
+
+ inode = pfile->f_dentry->d_inode;
+ magic = inode->i_sb->s_magic;
+ fsize = inode->i_size;
+ fs = get_fs();
+ set_fs(KERNEL_DS);
+ pos = 0;
+ vfs_read(pfile, buf, fsize, &pos);
+ filp_close(pfile, NULL);
+ set_fs(fs);
+
+ return 0;
+}
+
+#define FW_SUFFFIX ".bin"
+#define SD_UPG_BIN_PATH "/sdcard/_wmt_ft5x0x_fw_app.bin"
+#define FS_UPG_BIN_PATH "/lib/firmware/"
+
+int ft5x0x_upg_fw_bin(struct ft5x0x_data *ft5x0x, int check_ver)
+{
+ int i_ret = 0;
+ int fwsize = 0;
+ int hw_fw_ver;
+ int bin_fw_ver;
+ int do_upg;
+ u8 *pbt_buf = NULL;
+ u8 fw_path[128] = {0};
+
+ if(ft5x0x->upg)
+ sprintf(fw_path,"%s%s%s", FS_UPG_BIN_PATH, ft5x0x->fw_name,FW_SUFFFIX);//get fw binary file from filesystem
+ else
+ strcpy(fw_path,SD_UPG_BIN_PATH); //get fw binary file from SD card
+
+ fwsize = ft5x0x_get_fw_szie(fw_path);
+ if (fwsize <= 0) {
+ dbg_err("Get firmware size failed\n");
+ return -EIO;
+ }
+
+ if (fwsize < 8 || fwsize > 32 * 1024) {
+ dbg_err("FW length error\n");
+ return -EIO;
+ }
+
+ pbt_buf = kmalloc(fwsize + 1, GFP_KERNEL);
+ if (ft5x0x_read_fw(fw_path, pbt_buf)) {
+ dbg_err("Request_firmware failed\n");
+ i_ret = -EIO;
+ goto exit;
+ }
+
+ hw_fw_ver =ft5x0x_read_fw_ver();
+ if(hw_fw_ver <= 0){
+ dbg_err("Read firmware version failed\n");
+ i_ret = hw_fw_ver;
+ goto exit;
+ }
+
+ bin_fw_ver = ft5x0x_get_bin_ver(pbt_buf, fwsize);
+ printk("[FTS] hardware fw ver 0x%0x, binary ver 0x%0x\n",hw_fw_ver, bin_fw_ver);
+
+ if(check_ver){
+ if(hw_fw_ver == 0xa6 || hw_fw_ver < bin_fw_ver)
+ do_upg = 1;
+ else
+ do_upg = 0;
+ }else{
+ do_upg = 1;
+ }
+
+ if(do_upg){
+ if ((pbt_buf[fwsize - 8] ^ pbt_buf[fwsize - 6]) == 0xFF &&
+ (pbt_buf[fwsize - 7] ^ pbt_buf[fwsize - 5]) == 0xFF &&
+ (pbt_buf[fwsize - 3] ^ pbt_buf[fwsize - 4]) == 0xFF) {
+ i_ret = ft5x0x_fw_upgrade(ft5x0x, pbt_buf, fwsize);
+ if (i_ret)
+ dbg_err("Upgrade failed, i_ret=%d\n",i_ret);
+ else {
+ hw_fw_ver = ft5x0x_read_fw_ver();
+ printk("[FTS] upgrade to new version 0x%x\n", hw_fw_ver);
+ }
+ } else {
+ dbg_err("FW format error\n");
+ }
+ }
+
+ ft5x0x_auto_clb();/*start auto CLB*/
+
+exit:
+ kfree(pbt_buf);
+ return i_ret;
+}
+
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ft6x06_ex_fun.c b/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ft6x06_ex_fun.c
new file mode 100755
index 00000000..08fc6069
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ft6x06_ex_fun.c
@@ -0,0 +1,1021 @@
+/*
+ *drivers/input/touchscreen/ft5x06_ex_fun.c
+ *
+ *FocalTech ft6x06 expand function for debug.
+ *
+ *Copyright (c) 2010 Focal tech Ltd.
+ *
+ *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.
+ *
+ *Note:the error code of EIO is the general error in this file.
+ */
+
+
+#include "ft6x06_ex_fun.h"
+#include "ft6x06_ts.h"
+
+#include <linux/mount.h>
+#include <linux/netdevice.h>
+#include <linux/proc_fs.h>
+
+struct Upgrade_Info {
+ u16 delay_aa; /*delay of write FT_UPGRADE_AA */
+ u16 delay_55; /*delay of write FT_UPGRADE_55 */
+ u8 upgrade_id_1; /*upgrade id 1 */
+ u8 upgrade_id_2; /*upgrade id 2 */
+ u16 delay_readid; /*delay of read id */
+ u16 delay_earse_flash; /*delay of earse flash*/
+};
+
+
+int fts_ctpm_fw_upgrade(struct i2c_client *client, u8 *pbt_buf,
+ u32 dw_lenth);
+
+static unsigned char CTPM_FW[] = {
+ #include "FT5406.i"
+};
+
+static struct mutex g_device_mutex;
+
+int ft6x06_write_reg(struct i2c_client *client, u8 regaddr, u8 regvalue)
+{
+ unsigned char buf[2] = {0};
+ buf[0] = regaddr;
+ buf[1] = regvalue;
+
+ return ft6x06_i2c_Write(client, buf, sizeof(buf));
+}
+
+
+int ft6x06_read_reg(struct i2c_client *client, u8 regaddr, u8 *regvalue)
+{
+ return ft6x06_i2c_Read(client, &regaddr, 1, regvalue, 1);
+}
+
+
+int fts_ctpm_auto_clb(struct i2c_client *client)
+{
+ unsigned char uc_temp = 0x00;
+ unsigned char i = 0;
+
+ /*start auto CLB */
+ msleep(200);
+
+ ft6x06_write_reg(client, 0, FTS_FACTORYMODE_VALUE);
+ /*make sure already enter factory mode */
+ msleep(100);
+ /*write command to start calibration */
+ ft6x06_write_reg(client, 2, 0x4);
+ msleep(300);
+ for (i = 0; i < 100; i++) {
+ ft6x06_read_reg(client, 0, &uc_temp);
+ /*return to normal mode, calibration finish */
+ if (0x0 == ((uc_temp & 0x70) >> 4))
+ break;
+ }
+
+ msleep(200);
+ /*calibration OK */
+ msleep(300);
+ ft6x06_write_reg(client, 0, FTS_FACTORYMODE_VALUE); /*goto factory mode for store */
+ msleep(100); /*make sure already enter factory mode */
+ ft6x06_write_reg(client, 2, 0x5); /*store CLB result */
+ msleep(300);
+ ft6x06_write_reg(client, 0, FTS_WORKMODE_VALUE); /*return to normal mode */
+ msleep(300);
+
+ /*store CLB result OK */
+ return 0;
+}
+
+/*
+upgrade with *.i file
+*/
+int fts_ctpm_fw_upgrade_with_i_file(struct i2c_client *client)
+{
+ u8 *pbt_buf = NULL;
+ int i_ret;
+ int fw_len = sizeof(CTPM_FW);
+
+ /*judge the fw that will be upgraded
+ * if illegal, then stop upgrade and return.
+ */
+
+ if (fw_len < 8 || fw_len > 32 * 1024) {
+ dev_err(&client->dev, "%s:FW length error\n", __func__);
+ return -EIO;
+ }
+
+ /*FW upgrade */
+ pbt_buf = CTPM_FW;
+ /*call the upgrade function */
+
+ i_ret = fts_ctpm_fw_upgrade(client, pbt_buf, sizeof(CTPM_FW));
+ if (i_ret != 0)
+ dev_err(&client->dev, "%s:upgrade failed. err.\n",
+ __func__);
+
+ return i_ret;
+}
+
+u8 fts_ctpm_get_i_file_ver(void)
+{
+ u16 ui_sz;
+ ui_sz = sizeof(CTPM_FW);
+ if (ui_sz > 2)
+ return CTPM_FW[0x10a];
+
+ return 0x00; /*default value */
+}
+
+/*update project setting
+*only update these settings for COB project, or for some special case
+*/
+int fts_ctpm_update_project_setting(struct i2c_client *client)
+{
+ u8 uc_i2c_addr; /*I2C slave address (7 bit address)*/
+ u8 uc_io_voltage; /*IO Voltage 0---3.3v; 1----1.8v*/
+ u8 uc_panel_factory_id; /*TP panel factory ID*/
+ u8 buf[FTS_SETTING_BUF_LEN];
+ u8 reg_val[2] = {0};
+ u8 auc_i2c_write_buf[10] = {0};
+ u8 packet_buf[FTS_SETTING_BUF_LEN + 6];
+ u32 i = 0;
+ int i_ret;
+
+ uc_i2c_addr = client->addr;
+ uc_io_voltage = 0x0;
+ uc_panel_factory_id = 0x5a;
+
+
+ /*Step 1:Reset CTPM
+ *write 0xaa to register 0xfc
+ */
+ ft6x06_write_reg(client, 0xfc, 0xaa);
+ msleep(50);
+
+ /*write 0x55 to register 0xfc */
+ ft6x06_write_reg(client, 0xfc, 0x55);
+ msleep(30);
+
+ /*********Step 2:Enter upgrade mode *****/
+ auc_i2c_write_buf[0] = 0x55;
+ auc_i2c_write_buf[1] = 0xaa;
+ do {
+ i++;
+ i_ret = ft6x06_i2c_Write(client, auc_i2c_write_buf, 2);
+ msleep(5);
+ } while (i_ret <= 0 && i < 5);
+
+
+ /*********Step 3:check READ-ID***********************/
+ auc_i2c_write_buf[0] = 0x90;
+ auc_i2c_write_buf[1] = auc_i2c_write_buf[2] = auc_i2c_write_buf[3] =
+ 0x00;
+
+ ft6x06_i2c_Read(client, auc_i2c_write_buf, 4, reg_val, 2);
+
+ if (reg_val[0] == 0x79 && reg_val[1] == 0x3)
+ dev_dbg(&client->dev, "[FTS] Step 3: CTPM ID,ID1 = 0x%x,ID2 = 0x%x\n",
+ reg_val[0], reg_val[1]);
+ else
+ return -EIO;
+
+ auc_i2c_write_buf[0] = 0xcd;
+ ft6x06_i2c_Read(client, auc_i2c_write_buf, 1, reg_val, 1);
+ dev_dbg(&client->dev, "bootloader version = 0x%x\n", reg_val[0]);
+
+ /*--------- read current project setting ---------- */
+ /*set read start address */
+ buf[0] = 0x3;
+ buf[1] = 0x0;
+ buf[2] = 0x78;
+ buf[3] = 0x0;
+
+ ft6x06_i2c_Read(client, buf, 4, buf, FTS_SETTING_BUF_LEN);
+ dev_dbg(&client->dev, "[FTS] old setting: uc_i2c_addr = 0x%x,\
+ uc_io_voltage = %d, uc_panel_factory_id = 0x%x\n",
+ buf[0], buf[2], buf[4]);
+
+ /*--------- Step 4:erase project setting --------------*/
+ auc_i2c_write_buf[0] = 0x63;
+ ft6x06_i2c_Write(client, auc_i2c_write_buf, 1);
+ msleep(100);
+
+ /*---------- Set new settings ---------------*/
+ buf[0] = uc_i2c_addr;
+ buf[1] = ~uc_i2c_addr;
+ buf[2] = uc_io_voltage;
+ buf[3] = ~uc_io_voltage;
+ buf[4] = uc_panel_factory_id;
+ buf[5] = ~uc_panel_factory_id;
+ packet_buf[0] = 0xbf;
+ packet_buf[1] = 0x00;
+ packet_buf[2] = 0x78;
+ packet_buf[3] = 0x0;
+ packet_buf[4] = 0;
+ packet_buf[5] = FTS_SETTING_BUF_LEN;
+
+ for (i = 0; i < FTS_SETTING_BUF_LEN; i++)
+ packet_buf[6 + i] = buf[i];
+
+ ft6x06_i2c_Write(client, packet_buf, FTS_SETTING_BUF_LEN + 6);
+ msleep(100);
+
+ /********* reset the new FW***********************/
+ auc_i2c_write_buf[0] = 0x07;
+ ft6x06_i2c_Write(client, auc_i2c_write_buf, 1);
+
+ msleep(200);
+ return 0;
+}
+
+int fts_ctpm_auto_upgrade(struct i2c_client *client)
+{
+ u8 uc_host_fm_ver = FT6x06_REG_FW_VER;
+ u8 uc_tp_fm_ver;
+ int i_ret;
+
+ ft6x06_read_reg(client, FT6x06_REG_FW_VER, &uc_tp_fm_ver);
+ uc_host_fm_ver = fts_ctpm_get_i_file_ver();
+
+ if (/*the firmware in touch panel maybe corrupted */
+ uc_tp_fm_ver == FT6x06_REG_FW_VER ||
+ /*the firmware in host flash is new, need upgrade */
+ uc_tp_fm_ver < uc_host_fm_ver
+ ) {
+ msleep(100);
+ dev_dbg(&client->dev, "[FTS] uc_tp_fm_ver = 0x%x, uc_host_fm_ver = 0x%x\n",
+ uc_tp_fm_ver, uc_host_fm_ver);
+ i_ret = fts_ctpm_fw_upgrade_with_i_file(client);
+ if (i_ret == 0) {
+ msleep(300);
+ uc_host_fm_ver = fts_ctpm_get_i_file_ver();
+ dev_dbg(&client->dev, "[FTS] upgrade to new version 0x%x\n",
+ uc_host_fm_ver);
+ } else {
+ pr_err("[FTS] upgrade failed ret=%d.\n", i_ret);
+ return -EIO;
+ }
+ }
+
+ return 0;
+}
+
+void delay_qt_ms(unsigned long w_ms)
+{
+ unsigned long i;
+ unsigned long j;
+
+ for (i = 0; i < w_ms; i++)
+ {
+ for (j = 0; j < 1000; j++)
+ {
+ udelay(1);
+ }
+ }
+}
+
+int fts_ctpm_fw_upgrade(struct i2c_client *client, u8 *pbt_buf,
+ u32 dw_lenth)
+{
+ u8 reg_val[2] = {0};
+ u32 i = 0;
+ u32 packet_number;
+ u32 j;
+ u32 temp;
+ u32 lenght;
+ u32 fw_length;
+ u8 packet_buf[FTS_PACKET_LENGTH + 6];
+ u8 auc_i2c_write_buf[10];
+ u8 bt_ecc;
+ int i_ret;
+
+
+ if(pbt_buf[0] != 0x02)
+ {
+ DBG("[FTS] FW first byte is not 0x02. so it is invalid \n");
+ return -1;
+ }
+
+ if(dw_lenth > 0x11f)
+ {
+ fw_length = ((u32)pbt_buf[0x100]<<8) + pbt_buf[0x101];
+ if(dw_lenth < fw_length)
+ {
+ DBG("[FTS] Fw length is invalid \n");
+ return -1;
+ }
+ }
+ else
+ {
+ DBG("[FTS] Fw length is invalid \n");
+ return -1;
+ }
+
+ //DBG("[FTS] Step 3: CTPM ID,ID1 = 0x%x,ID2 = 0x%x\n", reg_val[0], reg_val[1]);
+
+ for (i = 0; i < FTS_UPGRADE_LOOP; i++) {
+ /*********Step 1:Reset CTPM *****/
+ /*write 0xaa to register 0xbc */
+
+ ft6x06_write_reg(client, 0xbc, FT_UPGRADE_AA);
+ msleep(FT6X06_UPGRADE_AA_DELAY);
+
+ /*write 0x55 to register 0xbc */
+ ft6x06_write_reg(client, 0xbc, FT_UPGRADE_55);
+
+ msleep(FT6X06_UPGRADE_55_DELAY);
+
+ /*********Step 2:Enter upgrade mode *****/
+ auc_i2c_write_buf[0] = FT_UPGRADE_55;
+ ft6x06_i2c_Write(client, auc_i2c_write_buf, 1);
+
+ auc_i2c_write_buf[0] = FT_UPGRADE_AA;
+ ft6x06_i2c_Write(client, auc_i2c_write_buf, 1);
+ msleep(FT6X06_UPGRADE_READID_DELAY);
+
+ /*********Step 3:check READ-ID***********************/
+ auc_i2c_write_buf[0] = 0x90;
+ auc_i2c_write_buf[1] = auc_i2c_write_buf[2] = auc_i2c_write_buf[3] =
+ 0x00;
+ reg_val[0] = 0x00;
+ reg_val[1] = 0x00;
+ ft6x06_i2c_Read(client, auc_i2c_write_buf, 4, reg_val, 2);
+
+
+ if (reg_val[0] == FT6X06_UPGRADE_ID_1
+ && reg_val[1] == FT6X06_UPGRADE_ID_2) {
+ //dev_dbg(&client->dev, "[FTS] Step 3: CTPM ID,ID1 = 0x%x,ID2 = 0x%x\n",
+ //reg_val[0], reg_val[1]);
+ DBG("[FTS] Step 3: GET CTPM ID OK,ID1 = 0x%x,ID2 = 0x%x\n",
+ reg_val[0], reg_val[1]);
+ break;
+ } else {
+ dev_err(&client->dev, "[FTS] Step 3: GET CTPM ID FAIL,ID1 = 0x%x,ID2 = 0x%x\n",
+ reg_val[0], reg_val[1]);
+ }
+ }
+ if (i >= FTS_UPGRADE_LOOP)
+ return -EIO;
+
+ auc_i2c_write_buf[0] = 0x90;
+ auc_i2c_write_buf[1] = 0x00;
+ auc_i2c_write_buf[2] = 0x00;
+ auc_i2c_write_buf[3] = 0x00;
+ auc_i2c_write_buf[4] = 0x00;
+ ft6x06_i2c_Write(client, auc_i2c_write_buf, 5);
+
+ //auc_i2c_write_buf[0] = 0xcd;
+ //ft6x06_i2c_Read(client, auc_i2c_write_buf, 1, reg_val, 1);
+
+
+ /*Step 4:erase app and panel paramenter area*/
+ DBG("Step 4:erase app and panel paramenter area\n");
+ auc_i2c_write_buf[0] = 0x61;
+ ft6x06_i2c_Write(client, auc_i2c_write_buf, 1); /*erase app area */
+ msleep(FT6X06_UPGRADE_EARSE_DELAY);
+
+ for(i = 0;i < 200;i++)
+ {
+ auc_i2c_write_buf[0] = 0x6a;
+ auc_i2c_write_buf[1] = 0x00;
+ auc_i2c_write_buf[2] = 0x00;
+ auc_i2c_write_buf[3] = 0x00;
+ reg_val[0] = 0x00;
+ reg_val[1] = 0x00;
+ ft6x06_i2c_Read(client, auc_i2c_write_buf, 4, reg_val, 2);
+ if(0xb0 == reg_val[0] && 0x02 == reg_val[1])
+ {
+ DBG("[FTS] erase app finished \n");
+ break;
+ }
+ msleep(50);
+ }
+
+ /*********Step 5:write firmware(FW) to ctpm flash*********/
+ bt_ecc = 0;
+ DBG("Step 5:write firmware(FW) to ctpm flash\n");
+
+ dw_lenth = fw_length;
+ packet_number = (dw_lenth) / FTS_PACKET_LENGTH;
+ packet_buf[0] = 0xbf;
+ packet_buf[1] = 0x00;
+
+ for (j = 0; j < packet_number; j++) {
+ temp = j * FTS_PACKET_LENGTH;
+ packet_buf[2] = (u8) (temp >> 8);
+ packet_buf[3] = (u8) temp;
+ lenght = FTS_PACKET_LENGTH;
+ packet_buf[4] = (u8) (lenght >> 8);
+ packet_buf[5] = (u8) lenght;
+
+ for (i = 0; i < FTS_PACKET_LENGTH; i++) {
+ packet_buf[6 + i] = pbt_buf[j * FTS_PACKET_LENGTH + i];
+ bt_ecc ^= packet_buf[6 + i];
+ }
+
+ ft6x06_i2c_Write(client, packet_buf, FTS_PACKET_LENGTH + 6);
+
+ for(i = 0;i < 30;i++)
+ {
+ auc_i2c_write_buf[0] = 0x6a;
+ auc_i2c_write_buf[1] = 0x00;
+ auc_i2c_write_buf[2] = 0x00;
+ auc_i2c_write_buf[3] = 0x00;
+ reg_val[0] = 0x00;
+ reg_val[1] = 0x00;
+ ft6x06_i2c_Read(client, auc_i2c_write_buf, 4, reg_val, 2);
+ if(0xb0 == (reg_val[0] & 0xf0) && (0x03 + (j % 0x0ffd)) == (((reg_val[0] & 0x0f) << 8) |reg_val[1]))
+ {
+ DBG("[FTS] write a block data finished \n");
+ break;
+ }
+ msleep(1);
+ }
+ //msleep(FTS_PACKET_LENGTH / 6 + 1);
+ //DBG("write bytes:0x%04x\n", (j+1) * FTS_PACKET_LENGTH);
+ //delay_qt_ms(FTS_PACKET_LENGTH / 6 + 1);
+ }
+
+ if ((dw_lenth) % FTS_PACKET_LENGTH > 0) {
+ temp = packet_number * FTS_PACKET_LENGTH;
+ packet_buf[2] = (u8) (temp >> 8);
+ packet_buf[3] = (u8) temp;
+ temp = (dw_lenth) % FTS_PACKET_LENGTH;
+ packet_buf[4] = (u8) (temp >> 8);
+ packet_buf[5] = (u8) temp;
+
+ for (i = 0; i < temp; i++) {
+ packet_buf[6 + i] = pbt_buf[packet_number * FTS_PACKET_LENGTH + i];
+ bt_ecc ^= packet_buf[6 + i];
+ }
+
+ ft6x06_i2c_Write(client, packet_buf, temp + 6);
+
+ for(i = 0;i < 30;i++)
+ {
+ auc_i2c_write_buf[0] = 0x6a;
+ auc_i2c_write_buf[1] = 0x00;
+ auc_i2c_write_buf[2] = 0x00;
+ auc_i2c_write_buf[3] = 0x00;
+ reg_val[0] = 0x00;
+ reg_val[1] = 0x00;
+ ft6x06_i2c_Read(client, auc_i2c_write_buf, 4, reg_val, 2);
+ if(0xb0 == (reg_val[0] & 0xf0) && (0x03 + (j % 0x0ffd)) == (((reg_val[0] & 0x0f) << 8) |reg_val[1]))
+ {
+ DBG("[FTS] write a block data finished \n");
+ break;
+ }
+ msleep(1);
+ }
+ //msleep(20);
+ }
+
+
+ /*********Step 6: read out checksum***********************/
+ /*send the opration head */
+ DBG("Step 6: read out checksum\n");
+ auc_i2c_write_buf[0] = 0xcc;
+ ft6x06_i2c_Read(client, auc_i2c_write_buf, 1, reg_val, 1);
+ if (reg_val[0] != bt_ecc) {
+ dev_err(&client->dev, "[FTS]--ecc error! FW=%02x bt_ecc=%02x\n",
+ reg_val[0],
+ bt_ecc);
+ return -EIO;
+ }
+
+ /*********Step 7: reset the new FW***********************/
+ DBG("Step 7: reset the new FW\n");
+ auc_i2c_write_buf[0] = 0x07;
+ ft6x06_i2c_Write(client, auc_i2c_write_buf, 1);
+ msleep(300); /*make sure CTP startup normally */
+
+ return 0;
+}
+
+/*sysfs debug*/
+
+/*
+*get firmware size
+
+@firmware_name:firmware name
+*note:the firmware default path is sdcard.
+ if you want to change the dir, please modify by yourself.
+*/
+static int ft6x06_GetFirmwareSize(char *firmware_name)
+{
+ struct file *pfile = NULL;
+ struct inode *inode;
+ unsigned long magic;
+ off_t fsize = 0;
+ char filepath[128];
+ memset(filepath, 0, sizeof(filepath));
+
+ sprintf(filepath, "/sdcard/%s", firmware_name);
+
+ if (NULL == pfile)
+ pfile = filp_open(filepath, O_RDONLY, 0);
+
+ if (IS_ERR(pfile)) {
+ pr_err("error occured while opening file %s.\n", filepath);
+ return -EIO;
+ }
+
+ inode = pfile->f_dentry->d_inode;
+ magic = inode->i_sb->s_magic;
+ fsize = inode->i_size;
+ filp_close(pfile, NULL);
+ return fsize;
+}
+
+
+
+/*
+*read firmware buf for .bin file.
+
+@firmware_name: fireware name
+@firmware_buf: data buf of fireware
+
+note:the firmware default path is sdcard.
+ if you want to change the dir, please modify by yourself.
+*/
+static int ft6x06_ReadFirmware(char *firmware_name,
+ unsigned char *firmware_buf)
+{
+ struct file *pfile = NULL;
+ struct inode *inode;
+ unsigned long magic;
+ off_t fsize;
+ char filepath[128];
+ loff_t pos;
+ mm_segment_t old_fs;
+
+ memset(filepath, 0, sizeof(filepath));
+ sprintf(filepath, "/sdcard/%s", firmware_name);
+ if (NULL == pfile)
+ pfile = filp_open(filepath, O_RDONLY, 0);
+ if (IS_ERR(pfile)) {
+ pr_err("error occured while opening file %s.\n", filepath);
+ return -EIO;
+ }
+
+ inode = pfile->f_dentry->d_inode;
+ magic = inode->i_sb->s_magic;
+ fsize = inode->i_size;
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ pos = 0;
+ vfs_read(pfile, firmware_buf, fsize, &pos);
+ filp_close(pfile, NULL);
+ set_fs(old_fs);
+
+ return 0;
+}
+
+
+
+/*
+upgrade with *.bin file
+*/
+
+int fts_ctpm_fw_upgrade_with_app_file(struct i2c_client *client,
+ char *firmware_name)
+{
+ u8 *pbt_buf = NULL;
+ int i_ret;
+ int fwsize = ft6x06_GetFirmwareSize(firmware_name);
+
+ if (fwsize <= 0) {
+ dev_err(&client->dev, "%s ERROR:Get firmware size failed\n",
+ __func__);
+ return -EIO;
+ }
+
+ if (fwsize < 8 || fwsize > 32 * 1024) {
+ dev_dbg(&client->dev, "%s:FW length error\n", __func__);
+ return -EIO;
+ }
+
+ /*=========FW upgrade========================*/
+ pbt_buf = kmalloc(fwsize + 1, GFP_ATOMIC);
+
+ if (ft6x06_ReadFirmware(firmware_name, pbt_buf)) {
+ dev_err(&client->dev, "%s() - ERROR: request_firmware failed\n",
+ __func__);
+ kfree(pbt_buf);
+ return -EIO;
+ }
+
+ /*call the upgrade function */
+ i_ret = fts_ctpm_fw_upgrade(client, pbt_buf, fwsize);
+ if (i_ret != 0)
+ dev_err(&client->dev, "%s() - ERROR:[FTS] upgrade failed..\n",
+ __func__);
+ //else
+ //fts_ctpm_auto_clb(client);
+ kfree(pbt_buf);
+
+ return i_ret;
+}
+
+static ssize_t ft6x06_tpfwver_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ ssize_t num_read_chars = 0;
+ u8 fwver = 0;
+ struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+ mutex_lock(&g_device_mutex);
+
+ if (ft6x06_read_reg(client, FT6x06_REG_FW_VER, &fwver) < 0)
+ num_read_chars = snprintf(buf, PAGE_SIZE,
+ "get tp fw version fail!\n");
+ else
+ num_read_chars = snprintf(buf, PAGE_SIZE, "%02X\n", fwver);
+
+ mutex_unlock(&g_device_mutex);
+
+ return num_read_chars;
+}
+
+static ssize_t ft6x06_tpfwver_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ /*place holder for future use*/
+ return -EPERM;
+}
+
+
+
+static ssize_t ft6x06_tprwreg_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ /*place holder for future use*/
+ return -EPERM;
+}
+
+static ssize_t ft6x06_tprwreg_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+ ssize_t num_read_chars = 0;
+ int retval;
+ long unsigned int wmreg = 0;
+ u8 regaddr = 0xff, regvalue = 0xff;
+ u8 valbuf[5] = {0};
+
+ memset(valbuf, 0, sizeof(valbuf));
+ mutex_lock(&g_device_mutex);
+ num_read_chars = count - 1;
+
+ if (num_read_chars != 2) {
+ if (num_read_chars != 4) {
+ pr_info("please input 2 or 4 character\n");
+ goto error_return;
+ }
+ }
+
+ memcpy(valbuf, buf, num_read_chars);
+ retval = strict_strtoul(valbuf, 16, &wmreg);
+
+ if (0 != retval) {
+ dev_err(&client->dev, "%s() - ERROR: Could not convert the "\
+ "given input to a number." \
+ "The given input was: \"%s\"\n",
+ __func__, buf);
+ goto error_return;
+ }
+
+ if (2 == num_read_chars) {
+ /*read register*/
+ regaddr = wmreg;
+ if (ft6x06_read_reg(client, regaddr, &regvalue) < 0)
+ dev_err(&client->dev, "Could not read the register(0x%02x)\n",
+ regaddr);
+ else
+ pr_info("the register(0x%02x) is 0x%02x\n",
+ regaddr, regvalue);
+ } else {
+ regaddr = wmreg >> 8;
+ regvalue = wmreg;
+ if (ft6x06_write_reg(client, regaddr, regvalue) < 0)
+ dev_err(&client->dev, "Could not write the register(0x%02x)\n",
+ regaddr);
+ else
+ dev_err(&client->dev, "Write 0x%02x into register(0x%02x) successful\n",
+ regvalue, regaddr);
+ }
+
+error_return:
+ mutex_unlock(&g_device_mutex);
+
+ return count;
+}
+
+static ssize_t ft6x06_fwupdate_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ /* place holder for future use */
+ return -EPERM;
+}
+
+/*upgrade from *.i*/
+static ssize_t ft6x06_fwupdate_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ft6x06_ts_data *data = NULL;
+ u8 uc_host_fm_ver;
+ int i_ret;
+ struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+ data = (struct ft6x06_ts_data *)i2c_get_clientdata(client);
+
+ mutex_lock(&g_device_mutex);
+
+ disable_irq(client->irq);
+ i_ret = fts_ctpm_fw_upgrade_with_i_file(client);
+ if (i_ret == 0) {
+ msleep(300);
+ uc_host_fm_ver = fts_ctpm_get_i_file_ver();
+ pr_info("%s [FTS] upgrade to new version 0x%x\n", __func__,
+ uc_host_fm_ver);
+ } else
+ dev_err(&client->dev, "%s ERROR:[FTS] upgrade failed.\n",
+ __func__);
+
+ enable_irq(client->irq);
+ mutex_unlock(&g_device_mutex);
+
+ return count;
+}
+
+static ssize_t ft6x06_fwupgradeapp_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ /*place holder for future use*/
+ return -EPERM;
+}
+
+
+/*upgrade from app.bin*/
+static ssize_t ft6x06_fwupgradeapp_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ char fwname[128];
+ struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+ memset(fwname, 0, sizeof(fwname));
+ sprintf(fwname, "%s", buf);
+ fwname[count - 1] = '\0';
+
+ mutex_lock(&g_device_mutex);
+ disable_irq(client->irq);
+
+ fts_ctpm_fw_upgrade_with_app_file(client, fwname);
+
+ enable_irq(client->irq);
+ mutex_unlock(&g_device_mutex);
+
+ return count;
+}
+
+
+/*sysfs */
+/*get the fw version
+*example:cat ftstpfwver
+*/
+static DEVICE_ATTR(ftstpfwver, S_IRUGO | S_IWUSR, ft6x06_tpfwver_show,
+ ft6x06_tpfwver_store);
+
+/*upgrade from *.i
+*example: echo 1 > ftsfwupdate
+*/
+static DEVICE_ATTR(ftsfwupdate, S_IRUGO | S_IWUSR, ft6x06_fwupdate_show,
+ ft6x06_fwupdate_store);
+
+/*read and write register
+*read example: echo 88 > ftstprwreg ---read register 0x88
+*write example:echo 8807 > ftstprwreg ---write 0x07 into register 0x88
+*
+*note:the number of input must be 2 or 4.if it not enough,please fill in the 0.
+*/
+static DEVICE_ATTR(ftstprwreg, S_IRUGO | S_IWUSR, ft6x06_tprwreg_show,
+ ft6x06_tprwreg_store);
+
+
+/*upgrade from app.bin
+*example:echo "*_app.bin" > ftsfwupgradeapp
+*/
+static DEVICE_ATTR(ftsfwupgradeapp, S_IRUGO | S_IWUSR, ft6x06_fwupgradeapp_show,
+ ft6x06_fwupgradeapp_store);
+
+
+/*add your attr in here*/
+static struct attribute *ft6x06_attributes[] = {
+ &dev_attr_ftstpfwver.attr,
+ &dev_attr_ftsfwupdate.attr,
+ &dev_attr_ftstprwreg.attr,
+ &dev_attr_ftsfwupgradeapp.attr,
+ NULL
+};
+
+static struct attribute_group ft6x06_attribute_group = {
+ .attrs = ft6x06_attributes
+};
+
+/*create sysfs for debug*/
+int ft6x06_create_sysfs(struct i2c_client *client)
+{
+ int err;
+ err = sysfs_create_group(&client->dev.kobj, &ft6x06_attribute_group);
+ if (0 != err) {
+ dev_err(&client->dev,
+ "%s() - ERROR: sysfs_create_group() failed.\n",
+ __func__);
+ sysfs_remove_group(&client->dev.kobj, &ft6x06_attribute_group);
+ return -EIO;
+ } else {
+ mutex_init(&g_device_mutex);
+ pr_info("ft6x06:%s() - sysfs_create_group() succeeded.\n",
+ __func__);
+ }
+ return err;
+}
+
+void ft6x06_release_sysfs(struct i2c_client *client)
+{
+ sysfs_remove_group(&client->dev.kobj, &ft6x06_attribute_group);
+ mutex_destroy(&g_device_mutex);
+}
+
+/*create apk debug channel*/
+#define PROC_UPGRADE 0
+#define PROC_READ_REGISTER 1
+#define PROC_WRITE_REGISTER 2
+#define PROC_AUTOCLB 4
+#define PROC_UPGRADE_INFO 5
+#define PROC_WRITE_DATA 6
+#define PROC_READ_DATA 7
+
+
+#define PROC_NAME "ft5x0x-debug"
+static unsigned char proc_operate_mode = PROC_UPGRADE;
+static struct proc_dir_entry *ft6x06_proc_entry;
+/*interface of write proc*/
+static int ft6x06_debug_write(struct file *filp,
+ const char __user *buff, unsigned long len, void *data)
+{
+ struct i2c_client *client = (struct i2c_client *)ft6x06_proc_entry->data;
+ unsigned char writebuf[FTS_PACKET_LENGTH];
+ int buflen = len;
+ int writelen = 0;
+ int ret = 0;
+
+ if (copy_from_user(&writebuf, buff, buflen)) {
+ dev_err(&client->dev, "%s:copy from user error\n", __func__);
+ return -EFAULT;
+ }
+ proc_operate_mode = writebuf[0];
+
+ switch (proc_operate_mode) {
+ case PROC_UPGRADE:
+ {
+ char upgrade_file_path[128];
+ memset(upgrade_file_path, 0, sizeof(upgrade_file_path));
+ sprintf(upgrade_file_path, "%s", writebuf + 1);
+ upgrade_file_path[buflen-1] = '\0';
+ DBG("%s\n", upgrade_file_path);
+ disable_irq(client->irq);
+
+ ret = fts_ctpm_fw_upgrade_with_app_file(client, upgrade_file_path);
+
+ enable_irq(client->irq);
+ if (ret < 0) {
+ dev_err(&client->dev, "%s:upgrade failed.\n", __func__);
+ return ret;
+ }
+ }
+ break;
+ case PROC_READ_REGISTER:
+ writelen = 1;
+ ret = ft6x06_i2c_Write(client, writebuf + 1, writelen);
+ if (ret < 0) {
+ dev_err(&client->dev, "%s:write iic error\n", __func__);
+ return ret;
+ }
+ break;
+ case PROC_WRITE_REGISTER:
+ writelen = 2;
+ ret = ft6x06_i2c_Write(client, writebuf + 1, writelen);
+ if (ret < 0) {
+ dev_err(&client->dev, "%s:write iic error\n", __func__);
+ return ret;
+ }
+ break;
+ case PROC_AUTOCLB:
+ DBG("%s: autoclb\n", __func__);
+ fts_ctpm_auto_clb(client);
+ break;
+ case PROC_READ_DATA:
+ case PROC_WRITE_DATA:
+ writelen = len - 1;
+ ret = ft6x06_i2c_Write(client, writebuf + 1, writelen);
+ if (ret < 0) {
+ dev_err(&client->dev, "%s:write iic error\n", __func__);
+ return ret;
+ }
+ break;
+ default:
+ break;
+ }
+
+
+ return len;
+}
+
+/*interface of read proc*/
+static int ft6x06_debug_read( char *page, char **start,
+ off_t off, int count, int *eof, void *data )
+{
+ struct i2c_client *client = (struct i2c_client *)ft6x06_proc_entry->data;
+ int ret = 0;
+ unsigned char buf[PAGE_SIZE];
+ int num_read_chars = 0;
+ int readlen = 0;
+ u8 regvalue = 0x00, regaddr = 0x00;
+
+ switch (proc_operate_mode) {
+ case PROC_UPGRADE:
+ /*after calling ft5x0x_debug_write to upgrade*/
+ regaddr = 0xA6;
+ ret = ft6x06_read_reg(client, regaddr, &regvalue);
+ if (ret < 0)
+ num_read_chars = sprintf(buf, "%s", "get fw version failed.\n");
+ else
+ num_read_chars = sprintf(buf, "current fw version:0x%02x\n", regvalue);
+ break;
+ case PROC_READ_REGISTER:
+ readlen = 1;
+ ret = ft6x06_i2c_Read(client, NULL, 0, buf, readlen);
+ if (ret < 0) {
+ dev_err(&client->dev, "%s:read iic error\n", __func__);
+ return ret;
+ }
+ num_read_chars = 1;
+ break;
+ case PROC_READ_DATA:
+ readlen = count;
+ ret = ft6x06_i2c_Read(client, NULL, 0, buf, readlen);
+ if (ret < 0) {
+ dev_err(&client->dev, "%s:read iic error\n", __func__);
+ return ret;
+ }
+
+ num_read_chars = readlen;
+ break;
+ case PROC_WRITE_DATA:
+ break;
+ default:
+ break;
+ }
+
+ memcpy(page, buf, num_read_chars);
+ return num_read_chars;
+}
+int ft6x06_create_apk_debug_channel(struct i2c_client * client)
+{
+ ft6x06_proc_entry = create_proc_entry(PROC_NAME, 0777, NULL);
+ if (NULL == ft6x06_proc_entry) {
+ dev_err(&client->dev, "Couldn't create proc entry!\n");
+ return -ENOMEM;
+ } else {
+ dev_info(&client->dev, "Create proc entry success!\n");
+ ft6x06_proc_entry->data = client;
+ ft6x06_proc_entry->write_proc = ft6x06_debug_write;
+ ft6x06_proc_entry->read_proc = ft6x06_debug_read;
+ }
+ return 0;
+}
+
+void ft6x06_release_apk_debug_channel(void)
+{
+ if (ft6x06_proc_entry)
+ remove_proc_entry(PROC_NAME, NULL);
+}
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ft6x06_ex_fun.h b/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ft6x06_ex_fun.h
new file mode 100755
index 00000000..e25675c0
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ft6x06_ex_fun.h
@@ -0,0 +1,79 @@
+#ifndef __LINUX_FT6X06_EX_FUN_H__
+#define __LINUX_FT6X06_EX_FUN_H__
+
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/semaphore.h>
+#include <linux/mutex.h>
+#include <linux/interrupt.h>
+#include <mach/irqs.h>
+
+#include <linux/syscalls.h>
+#include <asm/unistd.h>
+#include <asm/uaccess.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+
+
+
+#define FT_UPGRADE_AA 0xAA
+#define FT_UPGRADE_55 0x55
+
+
+//upgrade config of FT6X06
+/*
+#define FT6X06_UPGRADE_AA_DELAY 100
+#define FT6X06_UPGRADE_55_DELAY 10
+#define FT6X06_UPGRADE_ID_1 0x79
+#define FT6X06_UPGRADE_ID_2 0x08
+#define FT6X06_UPGRADE_READID_DELAY 10
+#define FT6X06_UPGRADE_EARSE_DELAY 2000
+*/
+
+/*upgrade config of FT6X36*/
+#define FT6X06_UPGRADE_AA_DELAY 10
+#define FT6X06_UPGRADE_55_DELAY 10
+#define FT6X06_UPGRADE_ID_1 0x79
+#define FT6X06_UPGRADE_ID_2 0x18
+#define FT6X06_UPGRADE_READID_DELAY 10
+#define FT6X06_UPGRADE_EARSE_DELAY 2000
+
+#define FTS_PACKET_LENGTH 128
+#define FTS_SETTING_BUF_LEN 128
+
+#define FTS_UPGRADE_LOOP 20
+
+#define FTS_FACTORYMODE_VALUE 0x40
+#define FTS_WORKMODE_VALUE 0x00
+
+//#define AUTO_CLB
+#define FTS_DBG
+#ifdef FTS_DBG
+#define DBG(fmt, args...) printk("[FTS]" fmt, ## args)
+#else
+#define DBG(fmt, args...) do{}while(0)
+#endif
+
+/*create sysfs for debug*/
+int ft6x06_create_sysfs(struct i2c_client * client);
+
+void ft6x06_release_sysfs(struct i2c_client * client);
+
+int ft6x06_create_apk_debug_channel(struct i2c_client *client);
+
+void ft6x06_release_apk_debug_channel(void);
+
+/*
+*ft6x06_write_reg- write register
+*@client: handle of i2c
+*@regaddr: register address
+*@regvalue: register value
+*
+*/
+int ft6x06_write_reg(struct i2c_client * client,u8 regaddr, u8 regvalue);
+
+int ft6x06_read_reg(struct i2c_client * client,u8 regaddr, u8 *regvalue);
+
+#endif
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ft6x06_ts.c b/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ft6x06_ts.c
new file mode 100755
index 00000000..56148177
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ft6x06_ts.c
@@ -0,0 +1,511 @@
+/* drivers/input/touchscreen/ft5x06_ts.c
+ *
+ * FocalTech ft6x06 TouchScreen driver.
+ *
+ * Copyright (c) 2010 Focal tech Ltd.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/input/mt.h>
+#include "ft6x06_ts.h"
+//#include <linux/earlysuspend.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <mach/irqs.h>
+#include <linux/kernel.h>
+#include <linux/semaphore.h>
+#include <linux/mutex.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/syscalls.h>
+#include <linux/unistd.h>
+#include <linux/uaccess.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+
+//#define FTS_CTL_FACE_DETECT
+#define FTS_CTL_IIC
+#define SYSFS_DEBUG
+#define FTS_APK_DEBUG
+//#define FT6X06_DOWNLOAD
+
+#ifdef FTS_CTL_IIC
+#include "focaltech_ctl.h"
+#endif
+#ifdef FTS_CTL_FACE_DETECT
+#include "ft_psensor_drv.h"
+#endif
+#ifdef SYSFS_DEBUG
+#include "ft6x06_ex_fun.h"
+#endif
+
+#if 0
+struct ts_event {
+ u16 au16_x[CFG_MAX_TOUCH_POINTS]; /*x coordinate */
+ u16 au16_y[CFG_MAX_TOUCH_POINTS]; /*y coordinate */
+ u8 au8_touch_event[CFG_MAX_TOUCH_POINTS]; /*touch event:
+ 0 -- down; 1-- up; 2 -- contact */
+ u8 au8_finger_id[CFG_MAX_TOUCH_POINTS]; /*touch ID */
+ u16 pressure;
+ u8 touch_point;
+};
+
+struct ft6x06_ts_data {
+ unsigned int irq;
+ unsigned int x_max;
+ unsigned int y_max;
+ struct i2c_client *client;
+ struct input_dev *input_dev;
+ struct ts_event event;
+ struct ft6x06_platform_data *pdata;
+#ifdef CONFIG_PM
+ struct early_suspend *early_suspend;
+#endif
+};
+
+#define FTS_POINT_UP 0x01
+#define FTS_POINT_DOWN 0x00
+#define FTS_POINT_CONTACT 0x02
+#endif
+
+/*
+*ft6x06_i2c_Read-read data and write data by i2c
+*@client: handle of i2c
+*@writebuf: Data that will be written to the slave
+*@writelen: How many bytes to write
+*@readbuf: Where to store data read from slave
+*@readlen: How many bytes to read
+*
+*Returns negative errno, else the number of messages executed
+*
+*
+*/
+int ft6x06_i2c_Read(struct i2c_client *client, char *writebuf,
+ int writelen, char *readbuf, int readlen)
+{
+ int ret;
+
+ if (writelen > 0) {
+ struct i2c_msg msgs[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = writelen,
+ .buf = writebuf,
+ },
+ {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = readlen,
+ .buf = readbuf,
+ },
+ };
+ ret = i2c_transfer(client->adapter, msgs, 2);
+ if (ret < 0)
+ dev_err(&client->dev, "f%s: i2c read error.\n",
+ __func__);
+ } else {
+ struct i2c_msg msgs[] = {
+ {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = readlen,
+ .buf = readbuf,
+ },
+ };
+ ret = i2c_transfer(client->adapter, msgs, 1);
+ if (ret < 0)
+ dev_err(&client->dev, "%s:i2c read error.\n", __func__);
+ }
+ return ret;
+}
+/*write data by i2c*/
+int ft6x06_i2c_Write(struct i2c_client *client, char *writebuf, int writelen)
+{
+ int ret;
+
+ struct i2c_msg msg[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = writelen,
+ .buf = writebuf,
+ },
+ };
+
+ ret = i2c_transfer(client->adapter, msg, 1);
+ if (ret < 0)
+ dev_err(&client->dev, "%s i2c write error.\n", __func__);
+
+ return ret;
+}
+
+#if 0
+/*Read touch point information when the interrupt is asserted.*/
+static int ft6x06_read_Touchdata(struct ft6x06_ts_data *data)
+{
+ struct ts_event *event = &data->event;
+ u8 buf[POINT_READ_BUF] = { 0 };
+ int ret = -1;
+ int i = 0;
+ u8 pointid = FT_MAX_ID;
+
+ ret = ft6x06_i2c_Read(data->client, buf, 1, buf, POINT_READ_BUF);
+ if (ret < 0) {
+ dev_err(&data->client->dev, "%s read touchdata failed.\n",
+ __func__);
+ return ret;
+ }
+ memset(event, 0, sizeof(struct ts_event));
+
+ //event->touch_point = buf[2] & 0x0F;
+
+ //event->touch_point = 0;
+
+ for (i = 0; i < CFG_MAX_TOUCH_POINTS; i++)
+ {
+ pointid = (buf[FT_TOUCH_ID_POS + FT_TOUCH_STEP * i]) >> 4;
+ if (pointid >= FT_MAX_ID)
+ break;
+ else
+ event->touch_point++;
+ event->au16_x[i] =
+ (s16) (buf[FT_TOUCH_X_H_POS + FT_TOUCH_STEP * i] & 0x0F) <<
+ 8 | (s16) buf[FT_TOUCH_X_L_POS + FT_TOUCH_STEP * i];
+ event->au16_y[i] =
+ (s16) (buf[FT_TOUCH_Y_H_POS + FT_TOUCH_STEP * i] & 0x0F) <<
+ 8 | (s16) buf[FT_TOUCH_Y_L_POS + FT_TOUCH_STEP * i];
+ event->au8_touch_event[i] =
+ buf[FT_TOUCH_EVENT_POS + FT_TOUCH_STEP * i] >> 6;
+ event->au8_finger_id[i] =
+ (buf[FT_TOUCH_ID_POS + FT_TOUCH_STEP * i]) >> 4;
+ }
+
+ //event->pressure = FT_PRESS;
+
+ return 0;
+}
+
+/*
+*report the point information
+*/
+static void ft6x06_report_value(struct ft6x06_ts_data *data)
+{
+ struct ts_event *event = &data->event;
+ int i = 0;
+ int up_point = 0;
+
+ for (i = 0; i < event->touch_point; i++)
+ {
+ input_mt_slot(data->input_dev, event->au8_finger_id[i]);
+
+ if (event->au8_touch_event[i]== 0 || event->au8_touch_event[i] == 2)
+ {
+ input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER,
+ true);
+ //input_report_abs(data->input_dev, ABS_MT_TRACKING_ID,
+ //event->au8_finger_id[i]);
+ input_report_abs(data->input_dev, ABS_MT_PRESSURE,
+ 0x3f);
+ input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR,
+ 0x05);
+ input_report_abs(data->input_dev, ABS_MT_POSITION_X,
+ event->au16_x[i]);
+ input_report_abs(data->input_dev, ABS_MT_POSITION_Y,
+ event->au16_y[i]);
+
+ }
+ else
+ {
+ up_point++;
+ input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER,
+ false);
+ }
+
+ }
+
+ if(event->touch_point == up_point)
+ input_report_key(data->input_dev, BTN_TOUCH, 0);
+ else
+ input_report_key(data->input_dev, BTN_TOUCH, 1);
+
+ input_sync(data->input_dev);
+
+}
+
+/*The ft6x06 device will signal the host about TRIGGER_FALLING.
+*Processed when the interrupt is asserted.
+*/
+static irqreturn_t ft6x06_ts_interrupt(int irq, void *dev_id)
+{
+ struct ft6x06_ts_data *ft6x06_ts = dev_id;
+ int ret = 0;
+ disable_irq_nosync(ft6x06_ts->irq);
+
+ ret = ft6x06_read_Touchdata(ft6x06_ts);
+ if (ret == 0)
+ ft6x06_report_value(ft6x06_ts);
+
+ enable_irq(ft6x06_ts->irq);
+
+ //printk(KERN_WARNING "interrupt \n");
+
+ return IRQ_HANDLED;
+}
+
+static int ft6x06_ts_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct ft6x06_platform_data *pdata =
+ (struct ft6x06_platform_data *)client->dev.platform_data;
+ struct ft6x06_ts_data *ft6x06_ts;
+ struct input_dev *input_dev;
+ int err = 0;
+ unsigned char uc_reg_value;
+ unsigned char uc_reg_addr;
+
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ err = -ENODEV;
+ goto exit_check_functionality_failed;
+ }
+
+ ft6x06_ts = kzalloc(sizeof(struct ft6x06_ts_data), GFP_KERNEL);
+
+ if (!ft6x06_ts) {
+ err = -ENOMEM;
+ goto exit_alloc_data_failed;
+ }
+
+ i2c_set_clientdata(client, ft6x06_ts);
+ ft6x06_ts->irq = client->irq;
+ ft6x06_ts->client = client;
+ ft6x06_ts->pdata = pdata;
+ ft6x06_ts->x_max = pdata->x_max - 1;
+ ft6x06_ts->y_max = pdata->y_max - 1;
+ ft6x06_ts->pdata->irq = ft6x06_ts->irq;
+ client->irq = ft6x06_ts->irq;
+ pr_info("irq = %d\n", client->irq);
+
+#ifdef CONFIG_PM
+ #if 0
+ err = gpio_request(pdata->reset, "ft6x06 reset");
+ if (err < 0) {
+ dev_err(&client->dev, "%s:failed to set gpio reset.\n",
+ __func__);
+ goto exit_request_reset;
+ }
+ #endif
+#endif
+
+ err = request_threaded_irq(client->irq, NULL, ft6x06_ts_interrupt,
+ IRQF_TRIGGER_FALLING, client->dev.driver->name,
+ ft6x06_ts);
+
+ if (err < 0) {
+ dev_err(&client->dev, "ft6x06_probe: request irq failed\n");
+ goto exit_irq_request_failed;
+ }
+ disable_irq(client->irq);
+
+ input_dev = input_allocate_device();
+ if (!input_dev) {
+ err = -ENOMEM;
+ dev_err(&client->dev, "failed to allocate input device\n");
+ goto exit_input_dev_alloc_failed;
+ }
+
+ ft6x06_ts->input_dev = input_dev;
+
+ __set_bit(EV_ABS, input_dev->evbit);
+ __set_bit(EV_KEY, input_dev->evbit);
+ __set_bit(BTN_TOUCH, input_dev->keybit);
+ __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+
+ input_mt_init_slots(input_dev, MT_MAX_TOUCH_POINTS);
+ input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
+ 0, PRESS_MAX, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_POSITION_X,
+ 0, ft6x06_ts->x_max, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
+ 0, ft6x06_ts->y_max, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_PRESSURE,
+ 0, PRESS_MAX, 0, 0);
+
+ input_dev->name = FT6X06_NAME;
+ err = input_register_device(input_dev);
+ if (err) {
+ dev_err(&client->dev,
+ "ft6x06_ts_probe: failed to register input device: %s\n",
+ dev_name(&client->dev));
+ goto exit_input_register_device_failed;
+ }
+ /*make sure CTP already finish startup process */
+ msleep(150);
+
+ /*get some register information */
+ uc_reg_addr = FT6x06_REG_FW_VER;
+ ft6x06_i2c_Read(client, &uc_reg_addr, 1, &uc_reg_value, 1);
+ dev_dbg(&client->dev, "[FTS] Firmware version = 0x%x\n", uc_reg_value);
+
+ uc_reg_addr = FT6x06_REG_POINT_RATE;
+ ft6x06_i2c_Read(client, &uc_reg_addr, 1, &uc_reg_value, 1);
+ dev_dbg(&client->dev, "[FTS] report rate is %dHz.\n",
+ uc_reg_value * 10);
+
+ uc_reg_addr = FT6x06_REG_THGROUP;
+ ft6x06_i2c_Read(client, &uc_reg_addr, 1, &uc_reg_value, 1);
+ dev_dbg(&client->dev, "[FTS] touch threshold is %d.\n",
+ uc_reg_value * 4);
+
+#ifdef SYSFS_DEBUG
+ ft6x06_create_sysfs(client);
+#endif
+
+#ifdef FTS_CTL_IIC
+ if (ft_rw_iic_drv_init(client) < 0)
+ dev_err(&client->dev, "%s:[FTS] create fts control iic driver failed\n",
+ __func__);
+#endif
+
+#ifdef FTS_APK_DEBUG
+ ft6x06_create_apk_debug_channel(client);
+#endif
+
+#ifdef FTS_CTL_FACE_DETECT
+ if (ft_psensor_drv_init(client) < 0)
+ dev_err(&client->dev, "%s:[FTS] create fts control psensor driver failed\n",
+ __func__);
+#endif
+
+ enable_irq(client->irq);
+ return 0;
+
+exit_input_register_device_failed:
+ input_free_device(input_dev);
+
+exit_input_dev_alloc_failed:
+ free_irq(client->irq, ft6x06_ts);
+#ifdef CONFIG_PM
+exit_request_reset:
+ gpio_free(ft6x06_ts->pdata->reset);
+#endif
+
+exit_irq_request_failed:
+ i2c_set_clientdata(client, NULL);
+ kfree(ft6x06_ts);
+
+exit_alloc_data_failed:
+exit_check_functionality_failed:
+ return err;
+}
+
+#ifdef CONFIG_PM
+static void ft6x06_ts_suspend(struct early_suspend *handler)
+{
+ struct ft6x06_ts_data *ts = container_of(handler, struct ft6x06_ts_data,
+ early_suspend);
+
+ dev_dbg(&ts->client->dev, "[FTS]ft6x06 suspend\n");
+ disable_irq(ts->pdata->irq);
+}
+
+static void ft6x06_ts_resume(struct early_suspend *handler)
+{
+ struct ft6x06_ts_data *ts = container_of(handler, struct ft6x06_ts_data,
+ early_suspend);
+
+ dev_dbg(&ts->client->dev, "[FTS]ft6x06 resume.\n");
+ gpio_set_value(ts->pdata->reset, 0);
+ msleep(20);
+ gpio_set_value(ts->pdata->reset, 1);
+ enable_irq(ts->pdata->irq);
+}
+#else
+#define ft6x06_ts_suspend NULL
+#define ft6x06_ts_resume NULL
+#endif
+
+static int __devexit ft6x06_ts_remove(struct i2c_client *client)
+{
+ struct ft6x06_ts_data *ft6x06_ts;
+ ft6x06_ts = i2c_get_clientdata(client);
+ input_unregister_device(ft6x06_ts->input_dev);
+ #ifdef CONFIG_PM
+ gpio_free(ft6x06_ts->pdata->reset);
+ #endif
+
+ #ifdef SYSFS_DEBUG
+ ft6x06_release_sysfs(client);
+ #endif
+ #ifdef FTS_CTL_IIC
+ ft_rw_iic_drv_exit();
+ #endif
+ #ifdef FTS_CTL_FACE_DETECT
+ ft_psensor_drv_exit();
+ #endif
+ free_irq(client->irq, ft6x06_ts);
+ kfree(ft6x06_ts);
+ i2c_set_clientdata(client, NULL);
+ return 0;
+}
+
+static const struct i2c_device_id ft6x06_ts_id[] = {
+ {FT6X06_NAME, 0},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, ft6x06_ts_id);
+
+static struct i2c_driver ft6x06_ts_driver = {
+ .probe = ft6x06_ts_probe,
+ .remove = __devexit_p(ft6x06_ts_remove),
+ .id_table = ft6x06_ts_id,
+ .suspend = ft6x06_ts_suspend,
+ .resume = ft6x06_ts_resume,
+ .driver = {
+ .name = FT6X06_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init ft6x06_ts_init(void)
+{
+ int ret;
+ ret = i2c_add_driver(&ft6x06_ts_driver);
+ if (ret) {
+ printk(KERN_WARNING "Adding ft6x06 driver failed "
+ "(errno = %d)\n", ret);
+ } else {
+ pr_info("Successfully added driver %s\n",
+ ft6x06_ts_driver.driver.name);
+ }
+ return ret;
+}
+
+static void __exit ft6x06_ts_exit(void)
+{
+ i2c_del_driver(&ft6x06_ts_driver);
+}
+
+module_init(ft6x06_ts_init);
+module_exit(ft6x06_ts_exit);
+
+MODULE_AUTHOR("<luowj>");
+MODULE_DESCRIPTION("FocalTech ft6x06 TouchScreen driver");
+MODULE_LICENSE("GPL");
+
+#endif
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ft6x06_ts.h b/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ft6x06_ts.h
new file mode 100755
index 00000000..83859c05
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ft6x06_ts.h
@@ -0,0 +1,52 @@
+#ifndef __LINUX_FT6X06_TS_H__
+#define __LINUX_FT6X06_TS_H__
+
+/* -- dirver configure -- */
+#define CFG_MAX_TOUCH_POINTS 2
+#define MT_MAX_TOUCH_POINTS 9
+
+#define PRESS_MAX 0xFF
+#define FT_PRESS 0x7F
+
+#define Proximity_Max 32
+
+#define FT_FACE_DETECT_ON 0xc0
+#define FT_FACE_DETECT_OFF 0xe0
+
+#define FT_FACE_DETECT_ENABLE 1
+#define FT_FACE_DETECT_DISABLE 0
+#define FT_FACE_DETECT_REG 0xB0
+
+#define FT6X06_NAME "ft6x06_ts"
+
+#define FT_MAX_ID 0x0F
+#define FT_TOUCH_STEP 6
+#define FT_FACE_DETECT_POS 1
+#define FT_TOUCH_X_H_POS 3
+#define FT_TOUCH_X_L_POS 4
+#define FT_TOUCH_Y_H_POS 5
+#define FT_TOUCH_Y_L_POS 6
+#define FT_TOUCH_EVENT_POS 3
+#define FT_TOUCH_ID_POS 5
+
+#define POINT_READ_BUF (3 + FT_TOUCH_STEP * CFG_MAX_TOUCH_POINTS)
+
+/*register address*/
+#define FT6x06_REG_FW_VER 0xA6
+#define FT6x06_REG_POINT_RATE 0x88
+#define FT6x06_REG_THGROUP 0x80
+
+int ft6x06_i2c_Read(struct i2c_client *client, char *writebuf, int writelen,
+ char *readbuf, int readlen);
+int ft6x06_i2c_Write(struct i2c_client *client, char *writebuf, int writelen);
+
+/* The platform data for the Focaltech ft6x06 touchscreen driver */
+struct ft6x06_platform_data {
+ unsigned int x_max;
+ unsigned int y_max;
+ unsigned long irqflags;
+ unsigned int irq;
+ unsigned int reset;
+};
+
+#endif
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ini.c b/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ini.c
new file mode 100755
index 00000000..a4f8dc38
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ini.c
@@ -0,0 +1,406 @@
+#include <linux/string.h>
+#include <asm/unistd.h>
+#include <linux/slab.h>
+
+#include "ini.h"
+
+
+char CFG_SSL = '['; /* Ïî±êÖ¾·ûSection Symbol --¿É¸ù¾ÝÌØÊâÐèÒª½øÐж¨Òå¸ü¸Ä£¬Èç { }µÈ*/
+char CFG_SSR = ']'; /* Ïî±êÖ¾·ûSection Symbol --¿É¸ù¾ÝÌØÊâÐèÒª½øÐж¨Òå¸ü¸Ä£¬Èç { }µÈ*/
+char CFG_NIS = ':'; /* name Óë index Ö®¼äµÄ·Ö¸ô·û */
+char CFG_NTS = '#'; /* ×¢ÊÍ·û*/
+
+static char * ini_str_trim_r(char * buf);
+static char * ini_str_trim_l(char * buf);
+static int ini_file_get_line(char *filedata, char *buffer, int maxlen);
+static int ini_split_key_value(char *buf, char **key, char **val);
+static long atol(char *nptr);
+
+
+/*************************************************************
+Function: »ñµÃkeyµÄÖµ
+Input: char * filedata¡¡Îļþ£»char * section¡¡ÏîÖµ£»char * key¡¡¼üÖµ
+Output: char * value¡¡keyµÄÖµ
+Return: 0 SUCCESS
+ -1 δÕÒµ½section
+ -2 δÕÒµ½key
+ -10 Îļþ´ò¿ªÊ§°Ü
+ -12 ¶ÁÈ¡Îļþʧ°Ü
+ -14 Îļþ¸ñʽ´íÎó
+ -22 ³¬³ö»º³åÇø´óС
+Note:
+*************************************************************/
+int ini_get_key(char *filedata, char * section, char * key, char * value)
+{
+ //char buf1[MAX_CFG_BUF + 1], buf2[MAX_CFG_BUF + 1];
+ char *buf1, *buf2;
+ char *key_ptr, *val_ptr;
+ int n, ret;
+ int dataoff = 0;
+
+ *value='\0';
+
+ buf1 = kzalloc(MAX_CFG_BUF + 1, GFP_KERNEL);
+ if(!buf1){
+ printk("buf1: mem alloc failed.\n");
+ return -ENOMEM;
+ }
+ buf2 = kzalloc(MAX_CFG_BUF + 1, GFP_KERNEL);
+ if(!buf2){
+ printk("buf2: mem alloc failed.\n");
+ kfree(buf1);
+ return -ENOMEM;
+ }
+
+ while(1) { /* ËÑÕÒÏîsection */
+ ret = CFG_ERR_READ_FILE;
+ n = ini_file_get_line(filedata+dataoff, buf1, MAX_CFG_BUF);
+ dataoff += n;
+ if(n < -1)
+ goto r_cfg_end;
+ ret = CFG_SECTION_NOT_FOUND;
+ if(n < 0)
+ goto r_cfg_end; /* Îļþβ£¬Î´·¢ÏÖ */
+
+ n = strlen(ini_str_trim_l(ini_str_trim_r(buf1)));
+ if(n == 0 || buf1[0] == CFG_NTS)
+ continue; /* ¿ÕÐÐ »ò ×¢ÊÍÐÐ */
+
+ ret = CFG_ERR_FILE_FORMAT;
+ if(n > 2 && ((buf1[0] == CFG_SSL && buf1[n-1] != CFG_SSR)))
+ goto r_cfg_end;
+ if(buf1[0] == CFG_SSL) {
+ buf1[n-1] = 0x00;
+ if(strcmp(buf1+1, section) == 0)
+ break; /* ÕÒµ½Ïîsection */
+ }
+ }
+
+ while(1){ /* ËÑÕÒkey */
+ ret = CFG_ERR_READ_FILE;
+ n = ini_file_get_line(filedata+dataoff, buf1, MAX_CFG_BUF);
+ dataoff += n;
+ if(n < -1)
+ goto r_cfg_end;
+ ret = CFG_KEY_NOT_FOUND;
+ if(n < 0)
+ goto r_cfg_end;/* Îļþβ£¬Î´·¢ÏÖkey */
+
+ n = strlen(ini_str_trim_l(ini_str_trim_r(buf1)));
+ if(n == 0 || buf1[0] == CFG_NTS)
+ continue; /* ¿ÕÐÐ »ò ×¢ÊÍÐÐ */
+ ret = CFG_KEY_NOT_FOUND;
+ if(buf1[0] == CFG_SSL)
+ goto r_cfg_end;
+ if(buf1[n-1] == '+') { /* Óö+ºÅ±íʾÏÂÒ»ÐмÌÐø */
+ buf1[n-1] = 0x00;
+ while(1) {
+ ret = CFG_ERR_READ_FILE;
+ n = ini_file_get_line(filedata+dataoff, buf2, MAX_CFG_BUF);
+ dataoff += n;
+ if(n < -1)
+ goto r_cfg_end;
+ if(n < 0)
+ break;/* Îļþ½áÊø */
+
+ n = strlen(ini_str_trim_r(buf2));
+ ret = CFG_ERR_EXCEED_BUF_SIZE;
+ if(n > 0 && buf2[n-1] == '+'){/* Óö+ºÅ±íʾÏÂÒ»ÐмÌÐø */
+ buf2[n-1] = 0x00;
+ if( (strlen(buf1) + strlen(buf2)) > MAX_CFG_BUF)
+ goto r_cfg_end;
+ strcat(buf1, buf2);
+ continue;
+ }
+ if(strlen(buf1) + strlen(buf2) > MAX_CFG_BUF)
+ goto r_cfg_end;
+ strcat(buf1, buf2);
+ break;
+ }
+ }
+ ret = CFG_ERR_FILE_FORMAT;
+ if(ini_split_key_value(buf1, &key_ptr, &val_ptr) != 1)
+ goto r_cfg_end;
+ ini_str_trim_l(ini_str_trim_r(key_ptr));
+ if(strcmp(key_ptr, key) != 0)
+ continue; /* ºÍkeyÖµ²»Æ¥Åä */
+ strcpy(value, val_ptr);
+ break;
+ }
+ ret = CFG_OK;
+r_cfg_end:
+ //if(fp != NULL) fclose(fp);
+ kfree(buf1);
+ kfree(buf2);
+ return ret;
+}
+/*************************************************************
+Function: »ñµÃËùÓÐsection
+Input: char *filename¡¡Îļþ,int max ×î´ó¿É·µ»ØµÄsectionµÄ¸öÊý
+Output: char *sections[]¡¡´æ·ÅsectionÃû×Ö
+Return: ·µ»Øsection¸öÊý¡£Èô³ö´í£¬·µ»Ø¸ºÊý¡£
+ -10 Îļþ´ò¿ª³ö´í
+ -12 Îļþ¶ÁÈ¡´íÎó
+ -14 Îļþ¸ñʽ´íÎó
+Note:
+*************************************************************/
+int ini_get_sections(char *filedata, unsigned char * sections[], int max)
+{
+ //FILE *fp;
+ char buf1[MAX_CFG_BUF + 1];
+ int n, n_sections = 0, ret;
+ int dataoff = 0;
+
+// if((fp = fopen(filename, "rb")) == NULL)
+// return CFG_ERR_OPEN_FILE;
+
+ while(1) {/*ËÑÕÒÏîsection */
+ ret = CFG_ERR_READ_FILE;
+ n = ini_file_get_line(filedata+dataoff, buf1, MAX_CFG_BUF);
+ dataoff += n;
+ if(n < -1)
+ goto cfg_scts_end;
+ if(n < 0)
+ break;/* Îļþβ */
+ n = strlen(ini_str_trim_l(ini_str_trim_r(buf1)));
+ if(n == 0 || buf1[0] == CFG_NTS)
+ continue; /* ¿ÕÐÐ »ò ×¢ÊÍÐÐ */
+ ret = CFG_ERR_FILE_FORMAT;
+ if(n > 2 && ((buf1[0] == CFG_SSL && buf1[n-1] != CFG_SSR)))
+ goto cfg_scts_end;
+ if(buf1[0] == CFG_SSL) {
+ if (max!=0){
+ buf1[n-1] = 0x00;
+ strcpy((char *)sections[n_sections], buf1+1);
+ if (n_sections>=max)
+ break; /* ³¬¹ý¿É·µ»Ø×î´ó¸öÊý */
+ }
+ n_sections++;
+ }
+
+ }
+ ret = n_sections;
+cfg_scts_end:
+// if(fp != NULL)
+// fclose(fp);
+ return ret;
+}
+
+
+/*************************************************************
+Function: È¥³ý×Ö·û´®ÓұߵĿÕ×Ö·û
+Input: char * buf ×Ö·û´®Ö¸Õë
+Output:
+Return: ×Ö·û´®Ö¸Õë
+Note:
+*************************************************************/
+static char * ini_str_trim_r(char * buf)
+{
+ int len,i;
+ char tmp[128];
+
+ memset(tmp, 0, sizeof(tmp));
+ len = strlen(buf);
+// tmp = (char *)malloc(len);
+
+ memset(tmp,0x00,len);
+ for(i = 0;i < len;i++) {
+ if (buf[i] !=' ')
+ break;
+ }
+ if (i < len) {
+ strncpy(tmp,(buf+i),(len-i));
+ }
+ strncpy(buf,tmp,len);
+// free(tmp);
+ return buf;
+}
+
+/*************************************************************
+Function: È¥³ý×Ö·û´®×ó±ßµÄ¿Õ×Ö·û
+Input: char * buf ×Ö·û´®Ö¸Õë
+Output:
+Return: ×Ö·û´®Ö¸Õë
+Note:
+*************************************************************/
+static char * ini_str_trim_l(char * buf)
+{
+ int len,i;
+ char tmp[128];
+
+ memset(tmp, 0, sizeof(tmp));
+ len = strlen(buf);
+ //tmp = (char *)malloc(len);
+
+ memset(tmp,0x00,len);
+
+ for(i = 0;i < len;i++) {
+ if (buf[len-i-1] !=' ')
+ break;
+ }
+ if (i < len) {
+ strncpy(tmp,buf,len-i);
+ }
+ strncpy(buf,tmp,len);
+ //free(tmp);
+ return buf;
+}
+/*************************************************************
+Function: ´ÓÎļþÖжÁÈ¡Ò»ÐÐ
+Input: FILE *fp Îļþ¾ä±ú£»int maxlen »º³åÇø×î´ó³¤¶È
+Output: char *buffer Ò»ÐÐ×Ö·û´®
+Return: >0 ʵ¼Ê¶ÁµÄ³¤¶È
+ -1 Îļþ½áÊø
+ -2 ¶ÁÎļþ³ö´í
+Note:
+*************************************************************/
+static int ini_file_get_line(char *filedata, char *buffer, int maxlen)
+{
+ int i, j;
+ char ch1;
+
+ for(i=0, j=0; i<maxlen; j++) {
+ ch1 = filedata[j];
+ if(ch1 == '\n' || ch1 == 0x00)
+ break; /* »»ÐÐ */
+ if(ch1 == '\f' || ch1 == 0x1A) { /* '\f':»»Ò³·ûÒ²ËãÓÐЧ×Ö·û */
+ buffer[i++] = ch1;
+ break;
+ }
+ if(ch1 != '\r') buffer[i++] = ch1; /* ºöÂԻسµ·û */
+ }
+ buffer[i] = '\0';
+ return i+2;
+}
+/*************************************************************
+Function: ·ÖÀëkeyºÍvalue
+ key=val
+ jack = liaoyuewang
+ | | |
+ k1 k2 i
+Input: char *buf
+Output: char **key, char **val
+Return: 1 --- ok
+ 0 --- blank line
+ -1 --- no key, "= val"
+ -2 --- only key, no '='
+Note:
+*************************************************************/
+static int ini_split_key_value(char *buf, char **key, char **val)
+{
+ int i, k1, k2, n;
+
+ if((n = strlen((char *)buf)) < 1)
+ return 0;
+ for(i = 0; i < n; i++)
+ if(buf[i] != ' ' && buf[i] != '\t')
+ break;
+
+ if(i >= n)
+ return 0;
+
+ if(buf[i] == '=')
+ return -1;
+
+ k1 = i;
+ for(i++; i < n; i++)
+ if(buf[i] == '=')
+ break;
+
+ if(i >= n)
+ return -2;
+ k2 = i;
+
+ for(i++; i < n; i++)
+ if(buf[i] != ' ' && buf[i] != '\t')
+ break;
+
+ buf[k2] = '\0';
+
+ *key = buf + k1;
+ *val = buf + i;
+ return 1;
+}
+
+int my_atoi(const char *str)
+{
+ int result = 0;
+ int signal = 1; /* ĬÈÏΪÕýÊý */
+ if((*str>='0'&&*str<='9')||*str=='-'||*str=='+') {
+ if(*str=='-'||*str=='+') {
+ if(*str=='-')
+ signal = -1; /*ÊäÈ븺Êý*/
+ str++;
+ }
+ }
+ else
+ return 0;
+ /*¿ªÊ¼×ª»»*/
+ while(*str>='0' && *str<='9')
+ result = result*10 + (*str++ - '0' );
+
+ return signal*result;
+}
+
+int isspace(int x)
+{
+ if(x==' '||x=='\t'||x=='\n'||x=='\f'||x=='\b'||x=='\r')
+ return 1;
+ else
+ return 0;
+}
+
+int isdigit(int x)
+{
+ if(x<='9' && x>='0')
+ return 1;
+ else
+ return 0;
+
+}
+
+static long atol(char *nptr)
+{
+ int c; /* current char */
+ long total; /* current total */
+ int sign; /* if ''-'', then negative, otherwise positive */
+ /* skip whitespace */
+ while ( isspace((int)(unsigned char)*nptr) )
+ ++nptr;
+ c = (int)(unsigned char)*nptr++;
+ sign = c; /* save sign indication */
+ if (c == '-' || c == '+')
+ c = (int)(unsigned char)*nptr++; /* skip sign */
+ total = 0;
+ while (isdigit(c)) {
+ total = 10 * total + (c - '0'); /* accumulate digit */
+ c = (int)(unsigned char)*nptr++; /* get next char */
+ }
+ if (sign == '-')
+ return -total;
+ else
+ return total; /* return result, negated if necessary */
+}
+/***
+*int atoi(char *nptr) - Convert string to long
+*
+*Purpose:
+* Converts ASCII string pointed to by nptr to binary.
+* Overflow is not detected. Because of this, we can just use
+* atol().
+*
+*Entry:
+* nptr = ptr to string to convert
+*
+*Exit:
+* return int value of the string
+*
+*Exceptions:
+* None - overflow is not detected.
+*
+*******************************************************************************/
+int atoi(char *nptr)
+{
+ return (int)atol(nptr);
+}
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ini.h b/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ini.h
new file mode 100755
index 00000000..72434b53
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/ft6x0x/ini.h
@@ -0,0 +1,43 @@
+#ifndef INI_H
+#define INI_H
+
+#define MAX_CFG_BUF 512
+#define SUCCESS 0
+/* return value */
+#define CFG_OK SUCCESS
+#define CFG_SECTION_NOT_FOUND -1
+#define CFG_KEY_NOT_FOUND -2
+#define CFG_ERR -10
+
+#define CFG_ERR_OPEN_FILE -10
+#define CFG_ERR_CREATE_FILE -11
+#define CFG_ERR_READ_FILE -12
+#define CFG_ERR_WRITE_FILE -13
+#define CFG_ERR_FILE_FORMAT -14
+
+
+#define CFG_ERR_EXCEED_BUF_SIZE -22
+
+#define COPYF_OK SUCCESS
+#define COPYF_ERR_OPEN_FILE -10
+#define COPYF_ERR_CREATE_FILE -11
+#define COPYF_ERR_READ_FILE -12
+#define COPYF_ERR_WRITE_FILE -13
+
+
+struct ini_key_location {
+ int ini_section_line_no;
+ int ini_key_line_no;
+ int ini_key_lines;
+};
+
+
+int ini_get_key(char *filedata, char * section, char * key, char * value);
+int ini_get_sections(char *filedata, unsigned char * sections[], int max);
+
+int ini_split_section(char *section, char **name, char **index);
+//int ini_join_section(char **section, char *name, char *index);
+
+int atoi(char *nptr);
+
+#endif
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/gsl1680_ts/Kconfig b/ANDROID_3.4.5/drivers/input/touchscreen/gsl1680_ts/Kconfig
new file mode 100755
index 00000000..0f47c8bc
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/gsl1680_ts/Kconfig
@@ -0,0 +1,16 @@
+#
+# GSL1680 capacity touch screen driver configuration
+#
+config TOUCHSCREEN_GSL1680
+ tristate "ilead GSL1680 I2C Touchscreen Input Driver Support"
+ depends on ARCH_WMT
+ default y
+ help
+ Say Y here if you have an WMT based board with touchscreen
+ attached to it.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called s_wmt_ts_gsl1680.
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/gsl1680_ts/Makefile b/ANDROID_3.4.5/drivers/input/touchscreen/gsl1680_ts/Makefile
new file mode 100755
index 00000000..372a0fce
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/gsl1680_ts/Makefile
@@ -0,0 +1,33 @@
+#KERNELDIR=/home/hangyan/android8850/kernel/ANDROID_3.0.8
+KERNELDIR=../../../../
+CROSS = arm_1103_le-
+CC= $(CROSS)gcc
+LD= $(CROSS)ld
+STRIP = $(CROSS)strip
+
+DEBUG = n
+
+# Add your debugging flag (or not) to EXTRA_CFLAGS
+ifeq ($(DEBUG),y)
+# DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+DEBFLAGS = -O0 -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+
+else
+ DEBFLAGS = -O2 -Wall
+endif
+
+EXTRA_CFLAGS += $(DEBFLAGS)
+
+
+MY_MODULE_NAME=s_wmt_ts_gsl1680
+
+obj-m := $(MY_MODULE_NAME).o
+$(MY_MODULE_NAME)-objs := gslX680.o wmt_ts.o gsl_point_id.b
+
+default:
+ $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules
+ $(STRIP) --strip-debug $(MY_MODULE_NAME).ko
+ rm -rf *.o *~ core .depend .*.cmd *.mod.c .tmp_versions *.order *.symvers
+
+clean:
+ rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.order *.symvers
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/gsl1680_ts/gslX680.c b/ANDROID_3.4.5/drivers/input/touchscreen/gsl1680_ts/gslX680.c
new file mode 100755
index 00000000..bcb252a5
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/gsl1680_ts/gslX680.c
@@ -0,0 +1,1416 @@
+/*
+ * drivers/input/touchscreen/gslX680.c
+ *
+ * Copyright (c) 2012 Shanghai Basewin
+ * Guan Yuwei<guanyuwei@basewin.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+//#include <mach/gpio.h>
+//#include <mach/gpio_data.h>
+#include <linux/jiffies.h>
+#include <linux/cdev.h>
+#include <asm/uaccess.h>
+#include <linux/pm_runtime.h>
+
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+#include <linux/earlysuspend.h>
+#endif
+#include <linux/input/mt.h>
+
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/async.h>
+#include <linux/hrtimer.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/irq.h>
+#include <linux/kthread.h>
+#include <linux/wakelock.h>
+
+
+#include <linux/gpio.h>
+#include <mach/wmt_iomux.h>
+
+
+//#include <asm/irq.h>
+//#include <asm/io.h>
+
+//#include <mach/irqs.h>
+//#include <mach/system.h>
+//#include <mach/hardware.h>
+#include "gslX680.h"
+#include "wmt_ts.h"
+#include "../../../video/backlight/wmt_bl.h"
+
+//#define GSL_DEBUG
+//#define GSL_TIMER
+//#define REPORT_DATA_ANDROID_4_0
+
+#define HAVE_TOUCH_KEY
+
+#define SCREEN_MAX_X 480
+#define SCREEN_MAX_Y 800
+
+
+#define GSLX680_I2C_NAME "touch_gslX680"
+#define GSLX680_I2C_ADDR 0x40
+#define IRQ_PORT INT_GPIO_0
+
+#define GSL_DATA_REG 0x80
+#define GSL_STATUS_REG 0xe0
+#define GSL_PAGE_REG 0xf0
+
+#define PRESS_MAX 255
+#define MAX_FINGERS 5
+#define MAX_CONTACTS 10
+#define DMA_TRANS_LEN 0x20
+
+#ifdef GSL_NOID_VERSION
+int gsl_noid_ver = 0;
+unsigned int gsl_config_data_id[512] = {0};
+#endif
+
+#ifdef HAVE_TOUCH_KEY
+static u16 key = 0;
+static int key_state_flag = 0;
+struct key_data {
+ u16 key;
+ u16 x_min;
+ u16 x_max;
+ u16 y_min;
+ u16 y_max;
+};
+
+const u16 key_array[]={
+ KEY_BACK,
+ KEY_HOME,
+ KEY_MENU,
+ KEY_SEARCH,
+ };
+#define MAX_KEY_NUM (sizeof(key_array)/sizeof(key_array[0]))
+
+struct key_data gsl_key_data[MAX_KEY_NUM] = {
+ {KEY_BACK, 2048, 2048, 2048, 2048},
+ {KEY_HOME, 2048, 2048, 2048, 2048},
+ {KEY_MENU, 2048, 2048, 2048, 2048},
+ {KEY_SEARCH, 2048, 2048, 2048, 2048},
+};
+#endif
+
+struct gsl_ts_data {
+ u8 x_index;
+ u8 y_index;
+ u8 z_index;
+ u8 id_index;
+ u8 touch_index;
+ u8 data_reg;
+ u8 status_reg;
+ u8 data_size;
+ u8 touch_bytes;
+ u8 update_data;
+ u8 touch_meta_data;
+ u8 finger_size;
+};
+
+static struct gsl_ts_data devices[] = {
+ {
+ .x_index = 6,
+ .y_index = 4,
+ .z_index = 5,
+ .id_index = 7,
+ .data_reg = GSL_DATA_REG,
+ .status_reg = GSL_STATUS_REG,
+ .update_data = 0x4,
+ .touch_bytes = 4,
+ .touch_meta_data = 4,
+ .finger_size = 70,
+ },
+};
+
+struct gsl_ts {
+ struct i2c_client *client;
+ struct input_dev *input;
+ struct work_struct work;
+ struct workqueue_struct *wq;
+ struct gsl_ts_data *dd;
+ u8 *touch_data;
+ u8 device_id;
+ u8 prev_touches;
+ bool is_suspended;
+ bool int_pending;
+ struct mutex sus_lock;
+// uint32_t gpio_irq;
+ int irq;
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+ struct early_suspend early_suspend;
+#endif
+#ifdef GSL_TIMER
+ struct timer_list gsl_timer;
+#endif
+
+ struct workqueue_struct *timeout_queue;
+ struct delayed_work timeout_work;
+ struct mutex timeout_mutex;
+ int timeout_count;
+};
+
+#define DELAY_TIMEOUT 1000
+#define DELAY_TIMEOUT_MAX 3
+
+
+
+struct gsl_ts *l_ts=NULL;
+
+static u32 id_sign[MAX_CONTACTS+1] = {0};
+static u8 id_state_flag[MAX_CONTACTS+1] = {0};
+static u8 id_state_old_flag[MAX_CONTACTS+1] = {0};
+static u16 x_old[MAX_CONTACTS+1] = {0};
+static u16 y_old[MAX_CONTACTS+1] = {0};
+static u16 x_new = 0;
+static u16 y_new = 0;
+
+static struct fw_data* GSLX680_FW = NULL;
+static int l_fwlen = 0;
+static struct task_struct *resume_download_task;
+static struct wake_lock downloadWakeLock;
+static int is_delay = 0;
+
+extern int tp_led_gpio;
+extern int tp_led_gpio_active;
+
+extern int sel_reg_bit;
+extern int sel_reg_active;
+
+
+extern int register_bl_notifier(struct notifier_block *nb);
+
+extern int unregister_bl_notifier(struct notifier_block *nb);
+
+extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
+
+////////////////////////////////////////////////////////////////////
+static int wmt_get_fwdata(void);
+
+////////////////////////////////////////////////////////////////////
+static int gslX680_chip_init(void)
+{
+ //gpio_set_status(PAD_GPIOA_6, gpio_status_out);
+ //gpio_out(PAD_GPIOA_6, 1);
+ // shutdown pin
+ wmt_rst_output(1);
+ // irq pin
+ //gpio_set_status(PAD_GPIOA_16, gpio_status_in);
+ //gpio_irq_set(PAD_GPIOA_16, GPIO_IRQ(INT_GPIO_0-INT_GPIO_0, GPIO_IRQ_RISING));
+ wmt_set_gpirq(IRQ_TYPE_EDGE_RISING);//GIRQ_FALLING);
+ wmt_disable_gpirq();
+ msleep(20);
+ return 0;
+}
+
+static int gslX680_shutdown_low(void)
+{
+ //gpio_set_status(PAD_GPIOA_6, gpio_status_out);
+ //gpio_out(PAD_GPIOA_6, 0);
+ wmt_rst_output(0);
+ return 0;
+}
+
+static int gslX680_shutdown_high(void)
+{
+ //gpio_set_status(PAD_GPIOA_6, gpio_status_out);
+ //gpio_out(PAD_GPIOA_6, 1);
+ wmt_rst_output(1);
+ return 0;
+}
+
+static inline u16 join_bytes(u8 a, u8 b)
+{
+ u16 ab = 0;
+ ab = ab | a;
+ ab = ab << 8 | b;
+ return ab;
+}
+
+#if 0
+static u32 gsl_read_interface(struct i2c_client *client, u8 reg, u8 *buf, u32 num)
+{
+ struct i2c_msg xfer_msg[2];
+
+ xfer_msg[0].addr = client->addr;
+ xfer_msg[0].len = 1;
+ xfer_msg[0].flags = client->flags & I2C_M_TEN;
+ xfer_msg[0].buf = &reg;
+
+ xfer_msg[1].addr = client->addr;
+ xfer_msg[1].len = num;
+ xfer_msg[1].flags |= I2C_M_RD;
+ xfer_msg[1].buf = buf;
+
+ if (reg < 0x80) {
+ i2c_transfer(client->adapter, xfer_msg, ARRAY_SIZE(xfer_msg));
+ msleep(5);
+ }
+
+ return i2c_transfer(client->adapter, xfer_msg, ARRAY_SIZE(xfer_msg)) == ARRAY_SIZE(xfer_msg) ? 0 : -EFAULT;
+}
+#endif
+
+static u32 gsl_write_interface(struct i2c_client *client, const u8 reg, u8 *buf, u32 num)
+{
+ struct i2c_msg xfer_msg[1];
+
+ buf[0] = reg;
+
+ xfer_msg[0].addr = client->addr;
+ xfer_msg[0].len = num + 1;
+ xfer_msg[0].flags = client->flags & I2C_M_TEN;
+ xfer_msg[0].buf = buf;
+
+ return i2c_transfer(client->adapter, xfer_msg, 1) == 1 ? 0 : -EFAULT;
+}
+
+static __inline__ void fw2buf(u8 *buf, const u32 *fw)
+{
+ u32 *u32_buf = (int *)buf;
+ *u32_buf = *fw;
+}
+
+static int wmt_get_fwdata(void)
+{
+ char fwname[128];
+
+ // get the firmware file name
+ memset(fwname,0,sizeof(fwname));
+ wmt_ts_get_firmwfilename(fwname);
+ // load the data into GSLX680_FW
+ l_fwlen = read_firmwfile(fwname, &GSLX680_FW, gsl_config_data_id);
+ return ((l_fwlen>0)?0:-1);
+}
+
+static void gsl_load_fw(struct i2c_client *client)
+{
+ u8 buf[DMA_TRANS_LEN*4 + 1] = {0};
+ u8 send_flag = 1;
+ u8 *cur = buf + 1;
+ u32 source_line = 0;
+ u32 source_len = l_fwlen;//ARRAY_SIZE(GSLX680_FW);
+
+ printk("=============gsl_load_fw start==============\n");
+
+ for (source_line = 0; source_line < source_len; source_line++)
+ {
+ /* init page trans, set the page val */
+ if (GSL_PAGE_REG == GSLX680_FW[source_line].offset)
+ {
+ fw2buf(cur, &GSLX680_FW[source_line].val);
+ gsl_write_interface(client, GSL_PAGE_REG, buf, 4);
+ send_flag = 1;
+ }
+ else
+ {
+ if (1 == send_flag % (DMA_TRANS_LEN < 0x20 ? DMA_TRANS_LEN : 0x20))
+ buf[0] = (u8)GSLX680_FW[source_line].offset;
+
+ fw2buf(cur, &GSLX680_FW[source_line].val);
+ cur += 4;
+
+ if (0 == send_flag % (DMA_TRANS_LEN < 0x20 ? DMA_TRANS_LEN : 0x20))
+ {
+ gsl_write_interface(client, buf[0], buf, cur - buf - 1);
+ cur = buf + 1;
+ }
+
+ send_flag++;
+ }
+ }
+
+ printk("=============gsl_load_fw end==============\n");
+
+}
+
+
+static int gsl_ts_write(struct i2c_client *client, u8 addr, u8 *pdata, int datalen)
+{
+ int ret = 0;
+ u8 tmp_buf[128];
+ unsigned int bytelen = 0;
+ if (datalen > 125)
+ {
+ dbg("%s too big datalen = %d!\n", __func__, datalen);
+ return -1;
+ }
+
+ tmp_buf[0] = addr;
+ bytelen++;
+
+ if (datalen != 0 && pdata != NULL)
+ {
+ memcpy(&tmp_buf[bytelen], pdata, datalen);
+ bytelen += datalen;
+ }
+
+ ret = i2c_master_send(client, tmp_buf, bytelen);
+ return ret;
+}
+
+static int gsl_ts_read(struct i2c_client *client, u8 addr, u8 *pdata, unsigned int datalen)
+{
+ int ret = 0;
+
+ if (datalen > 126)
+ {
+ dbg("%s too big datalen = %d!\n", __func__, datalen);
+ return -1;
+ }
+
+ ret = gsl_ts_write(client, addr, NULL, 0);
+ if (ret < 0)
+ {
+ dbg("%s set data address fail!\n", __func__);
+ return ret;
+ }
+
+ return i2c_master_recv(client, pdata, datalen);
+}
+
+#if 0
+static void test_i2c(struct i2c_client *client)
+{
+ u8 read_buf = 0;
+ u8 write_buf = 0x12;
+ int ret;
+ ret = gsl_ts_read( client, 0xf0, &read_buf, sizeof(read_buf) );
+ if (ret < 0)
+ {
+ pr_info("I2C transfer error!\n");
+ }
+ else
+ {
+ pr_info("I read reg 0xf0 is %x\n", read_buf);
+ }
+ msleep(10);
+
+ ret = gsl_ts_write(client, 0xf0, &write_buf, sizeof(write_buf));
+ if (ret < 0)
+ {
+ pr_info("I2C transfer error!\n");
+ }
+ else
+ {
+ pr_info("I write reg 0xf0 0x12\n");
+ }
+ msleep(10);
+
+ ret = gsl_ts_read( client, 0xf0, &read_buf, sizeof(read_buf) );
+ if (ret < 0 )
+ {
+ pr_info("I2C transfer error!\n");
+ }
+ else
+ {
+ pr_info("I read reg 0xf0 is 0x%x\n", read_buf);
+ }
+ msleep(10);
+
+}
+#endif
+
+static int test_i2c(struct i2c_client *client)
+{
+ u8 read_buf = 0;
+ u8 write_buf = 0x12;
+ int ret, rc = 1;
+
+ ret = gsl_ts_read( client, 0xf0, &read_buf, sizeof(read_buf) );
+ if (ret < 0)
+ rc --;
+ else
+ dbg("I read reg 0xf0 is %x\n", read_buf);
+
+ msleep(2);
+ ret = gsl_ts_write(client, 0xf0, &write_buf, sizeof(write_buf));
+ if(ret >= 0 )
+ dbg("I write reg 0xf0 0x12\n");
+
+ msleep(2);
+ ret = gsl_ts_read( client, 0xf0, &read_buf, sizeof(read_buf) );
+ if(ret < 0 )
+ rc --;
+ else
+ dbg("I read reg 0xf0 is 0x%x\n", read_buf);
+
+ return rc;
+}
+
+static void startup_chip(struct i2c_client *client)
+{
+ u8 tmp = 0x00;
+#ifdef GSL_NOID_VERSION
+ if (gsl_noid_ver)
+ gsl_DataInit(gsl_config_data_id);
+#endif
+ gsl_ts_write(client, 0xe0, &tmp, 1);
+ msleep(10);
+}
+
+static void reset_chip(struct i2c_client *client)
+{
+ u8 buf[4] = {0x00};
+ u8 tmp = 0x88;
+ gsl_ts_write(client, 0xe0, &tmp, sizeof(tmp));
+ msleep(10);
+
+ tmp = 0x04;
+ gsl_ts_write(client, 0xe4, &tmp, sizeof(tmp));
+ msleep(10);
+
+ gsl_ts_write(client, 0xbc, buf, sizeof(buf));
+ msleep(10);
+}
+
+static void clr_reg(struct i2c_client *client)
+{
+ u8 write_buf[4] = {0};
+
+ write_buf[0] = 0x88;
+ gsl_ts_write(client, 0xe0, &write_buf[0], 1);
+ msleep(20);
+ write_buf[0] = 0x03;
+ gsl_ts_write(client, 0x80, &write_buf[0], 1);
+ msleep(5);
+ write_buf[0] = 0x04;
+ gsl_ts_write(client, 0xe4, &write_buf[0], 1);
+ msleep(5);
+ write_buf[0] = 0x00;
+ gsl_ts_write(client, 0xe0, &write_buf[0], 1);
+ msleep(20);
+}
+
+static void init_chip(struct i2c_client *client)
+{
+ int rc;
+
+ gslX680_shutdown_low();
+ msleep(20);
+ gslX680_shutdown_high();
+ msleep(20);
+ rc = test_i2c(client);
+ if(rc < 0)
+ {
+ printk("------gslX680 test_i2c error------\n");
+ return;
+ }
+ clr_reg(client);
+ reset_chip(client);
+ gsl_load_fw(client);
+ startup_chip(client);
+ reset_chip(client);
+ startup_chip(client);
+}
+
+static void check_mem_data(struct i2c_client *client)
+{
+ /*char write_buf;
+ char read_buf[4] = {0};
+
+ msleep(30);
+ write_buf = 0x00;
+ gsl_ts_write(client,0xf0, &write_buf, sizeof(write_buf));
+ gsl_ts_read(client,0x00, read_buf, sizeof(read_buf));
+ gsl_ts_read(client,0x00, read_buf, sizeof(read_buf));
+ if (read_buf[3] != 0x1 || read_buf[2] != 0 || read_buf[1] != 0 || read_buf[0] != 0)
+ {
+ dbg("!!!!!!!!!!!page: %x offset: %x val: %x %x %x %x\n",0x0, 0x0, read_buf[3], read_buf[2], read_buf[1], read_buf[0]);
+ init_chip(client);
+ }*/
+
+ u8 read_buf[4] = {0};
+
+ msleep(30);
+ gsl_ts_read(client,0xb0, read_buf, sizeof(read_buf));
+
+ if (read_buf[3] != 0x5a || read_buf[2] != 0x5a || read_buf[1] != 0x5a || read_buf[0] != 0x5a)
+ {
+ printk("#########check mem read 0xb0 = %x %x %x %x #########\n", read_buf[3], read_buf[2], read_buf[1], read_buf[0]);
+ init_chip(client);
+ }
+
+}
+
+static void record_point(u16 x, u16 y , u8 id)
+{
+ u16 x_err =0;
+ u16 y_err =0;
+
+ id_sign[id]=id_sign[id]+1;
+
+ if(id_sign[id]==1){
+ x_old[id]=x;
+ y_old[id]=y;
+ }
+
+ x = (x_old[id] + x)/2;
+ y = (y_old[id] + y)/2;
+
+ if(x>x_old[id]){
+ x_err=x -x_old[id];
+ }
+ else{
+ x_err=x_old[id]-x;
+ }
+
+ if(y>y_old[id]){
+ y_err=y -y_old[id];
+ }
+ else{
+ y_err=y_old[id]-y;
+ }
+
+ if( (x_err > 3 && y_err > 1) || (x_err > 1 && y_err > 3) ){
+ x_new = x; x_old[id] = x;
+ y_new = y; y_old[id] = y;
+ }
+ else{
+ if(x_err > 3){
+ x_new = x; x_old[id] = x;
+ }
+ else
+ x_new = x_old[id];
+ if(y_err> 3){
+ y_new = y; y_old[id] = y;
+ }
+ else
+ y_new = y_old[id];
+ }
+
+ if(id_sign[id]==1){
+ x_new= x_old[id];
+ y_new= y_old[id];
+ }
+
+}
+
+void wmt_set_keypos(int index,int xmin,int xmax,int ymin,int ymax)
+{
+ gsl_key_data[index].x_min = xmin;
+ gsl_key_data[index].x_max = xmax;
+ gsl_key_data[index].y_min = ymin;
+ gsl_key_data[index].y_max = ymax;
+}
+
+#ifdef HAVE_TOUCH_KEY
+static void report_key(struct gsl_ts *ts, u16 x, u16 y)
+{
+ u16 i = 0;
+
+ for(i = 0; i < MAX_KEY_NUM; i++)
+ {
+ if((gsl_key_data[i].x_min <= x) && (x <= gsl_key_data[i].x_max)&&(gsl_key_data[i].y_min <= y) && (y <= gsl_key_data[i].y_max))
+ {
+ key = gsl_key_data[i].key;
+ input_report_key(ts->input, key, 1);
+ input_sync(ts->input);
+ key_state_flag = 1;
+ dbg("rport key:%d\n",key);
+
+ if( tp_led_gpio >= 0 ){
+ gpio_set_value(tp_led_gpio,tp_led_gpio_active);
+
+ mutex_lock(&ts->timeout_mutex);
+ if( ts->timeout_count < 0 ){
+ queue_delayed_work(ts->timeout_queue, &ts->timeout_work, msecs_to_jiffies(DELAY_TIMEOUT));
+ }
+ ts->timeout_count = DELAY_TIMEOUT_MAX;
+ mutex_unlock(&ts->timeout_mutex);
+ }
+ break;
+ }
+ }
+}
+#endif
+
+static void report_data(struct gsl_ts *ts, u16 x, u16 y, u8 pressure, u8 id)
+{
+ //swap(x, y);
+ int tx,ty;
+ int keyx,keyy;
+
+ dbg("#####id=%d,x=%d,y=%d######\n",id,x,y);
+
+
+ tx = x;
+ ty = y;
+ keyx = x;
+ keyy = y;
+
+ if( (x>=wmt_ts_get_resolvX()&&x>=wmt_ts_get_resolvY())
+ || (y>= wmt_ts_get_resolvX()&&y>= wmt_ts_get_resolvY()))
+ {
+ #ifdef HAVE_TOUCH_KEY
+ if (wmt_ts_if_tskey())
+ {
+ report_key(ts,keyx,keyy);
+ }
+ #endif
+ return;
+ }
+
+
+ if (wmt_ts_get_xaxis()==1)
+ {
+ tx = y;
+ ty = x;
+ }
+ if (wmt_ts_get_xdir()==-1)
+ {
+ tx = wmt_ts_get_resolvX() - tx - 1;
+ }
+ if (wmt_ts_get_ydir()==-1)
+ {
+ ty = wmt_ts_get_resolvY() - ty - 1;
+ }
+ /*if ((tx < 0) || (tx >= wmt_ts_get_resolvX()) ||
+ (ty < 0) || (ty >= wmt_ts_get_resolvY()))
+ {
+ dbg("Invalid point(%d,%d)\n");
+ return;
+ }*/
+ x = tx;
+ y = ty;
+
+
+ if (wmt_ts_get_lcdexchg()) {
+ int tmp;
+ tmp = x;
+ x = y;
+ y = wmt_ts_get_resolvX() - tmp;
+ }
+
+ dbg("rpt%d(%d,%d)\n",id,x,y);
+#ifdef REPORT_DATA_ANDROID_4_0
+ input_mt_slot(ts->input, id);
+ input_report_abs(ts->input, ABS_MT_TRACKING_ID, id);
+ //input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR, pressure);
+ input_report_abs(ts->input, ABS_MT_POSITION_X, x);
+ input_report_abs(ts->input, ABS_MT_POSITION_Y, y);
+ //input_report_abs(ts->input, ABS_MT_WIDTH_MAJOR, 1);
+#else
+ //add for cross finger 2013-1-10
+ input_report_key(ts->input, BTN_TOUCH, 1);
+ input_report_abs(ts->input, ABS_MT_TRACKING_ID, id);
+ //input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR, pressure);
+ input_report_abs(ts->input, ABS_MT_POSITION_X,x);
+ input_report_abs(ts->input, ABS_MT_POSITION_Y, y);
+ //input_report_abs(ts->input, ABS_MT_WIDTH_MAJOR, 1);
+ input_mt_sync(ts->input);
+#endif
+}
+
+static void process_gslX680_data(struct gsl_ts *ts)
+{
+ u8 id, touches;
+ u16 x, y;
+ int i = 0;
+#ifdef GSL_NOID_VERSION
+ u32 tmp1;
+ u8 buf[4] = {0};
+ struct gsl_touch_info cinfo;
+#endif
+ touches = ts->touch_data[ts->dd->touch_index];
+
+#ifdef GSL_NOID_VERSION
+ if (gsl_noid_ver) {
+ cinfo.finger_num = touches;
+ dbg("tp-gsl finger_num = %d\n",cinfo.finger_num);
+ for(i = 0; i < (touches < MAX_CONTACTS ? touches : MAX_CONTACTS); i ++) {
+ cinfo.x[i] = join_bytes( ( ts->touch_data[ts->dd->x_index + 4 * i + 1] & 0xf),
+ ts->touch_data[ts->dd->x_index + 4 * i]);
+ cinfo.y[i] = join_bytes(ts->touch_data[ts->dd->y_index + 4 * i + 1],
+ ts->touch_data[ts->dd->y_index + 4 * i ]);
+ cinfo.id[i] = ((ts->touch_data[ts->dd->x_index + 4 * i + 1] & 0xf0)>>4);
+ dbg("tp-gsl x = %d y = %d \n",cinfo.x[i],cinfo.y[i]);
+ }
+ cinfo.finger_num=(ts->touch_data[3]<<24)|(ts->touch_data[2]<<16)
+ |(ts->touch_data[1]<<8)|(ts->touch_data[0]);
+ gsl_alg_id_main(&cinfo);
+ tmp1=gsl_mask_tiaoping();
+ dbg("[tp-gsl] tmp1=%x\n",tmp1);
+ if(tmp1>0&&tmp1<0xffffffff) {
+ buf[0]=0xa;buf[1]=0;buf[2]=0;buf[3]=0;
+ gsl_ts_write(ts->client,0xf0,buf,4);
+ buf[0]=(u8)(tmp1 & 0xff);
+ buf[1]=(u8)((tmp1>>8) & 0xff);
+ buf[2]=(u8)((tmp1>>16) & 0xff);
+ buf[3]=(u8)((tmp1>>24) & 0xff);
+ dbg("tmp1=%08x,buf[0]=%02x,buf[1]=%02x,buf[2]=%02x,buf[3]=%02x\n",
+ tmp1,buf[0],buf[1],buf[2],buf[3]);
+ gsl_ts_write(ts->client,0x8,buf,4);
+ }
+ touches = cinfo.finger_num;
+ }
+#endif
+
+ for(i=1;i<=MAX_CONTACTS;i++)
+ {
+ if(touches == 0)
+ id_sign[i] = 0;
+ id_state_flag[i] = 0;
+ }
+ for(i= 0;i < (touches > MAX_FINGERS ? MAX_FINGERS : touches);i ++)
+ {
+ #ifdef GSL_NOID_VERSION
+ if (gsl_noid_ver) {
+ id = cinfo.id[i];
+ x = cinfo.x[i];
+ y = cinfo.y[i];
+ }
+ else {
+ x = join_bytes( ( ts->touch_data[ts->dd->x_index + 4 * i + 1] & 0xf),
+ ts->touch_data[ts->dd->x_index + 4 * i]);
+ y = join_bytes(ts->touch_data[ts->dd->y_index + 4 * i + 1],
+ ts->touch_data[ts->dd->y_index + 4 * i ]);
+ id = ts->touch_data[ts->dd->id_index + 4 * i] >> 4;
+ }
+ #endif
+
+ if(1 <=id && id <= MAX_CONTACTS)
+ {
+ dbg("raw%d(%d,%d)\n", id, x, y);
+ record_point(x, y , id);
+ dbg("new%d(%d,%d)\n", id, x_new, y_new);
+ report_data(ts, x_new, y_new, 10, id);
+ id_state_flag[id] = 1;
+ }
+ }
+ for(i=1;i<=MAX_CONTACTS;i++)
+ {
+ if( (0 == touches) || ((0 != id_state_old_flag[i]) && (0 == id_state_flag[i])) )
+ {
+ #ifdef REPORT_DATA_ANDROID_4_0
+ input_mt_slot(ts->input, i);
+ input_report_abs(ts->input, ABS_MT_TRACKING_ID, -1);
+ input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, false);
+ #endif
+ id_sign[i]=0;
+ }
+ id_state_old_flag[i] = id_state_flag[i];
+ }
+#ifndef REPORT_DATA_ANDROID_4_0
+ if(0 == touches)
+ {
+ //add 2013-1-10 cross fingers
+ //input_report_abs(ts->input, ABS_MT_TRACKING_ID, -1);
+ input_report_key(ts->input, BTN_TOUCH, 0);
+ //**********************
+ input_mt_sync(ts->input);
+ #ifdef HAVE_TOUCH_KEY
+ if (wmt_ts_if_tskey())
+ {
+ if(key_state_flag)
+ {
+ input_report_key(ts->input, key, 0);
+ input_sync(ts->input);
+ key_state_flag = 0;
+ }
+ }
+ #endif
+ }
+#endif
+ input_sync(ts->input);
+ ts->prev_touches = touches;
+}
+
+
+static void gsl_ts_xy_worker(struct work_struct *work)
+{
+ int rc;
+ u8 read_buf[4] = {0};
+
+ struct gsl_ts *ts = container_of(work, struct gsl_ts,work);
+
+ dbg("---gsl_ts_xy_worker---\n");
+
+ if (ts->is_suspended == true) {
+ dev_dbg(&ts->client->dev, "TS is supended\n");
+ ts->int_pending = true;
+ goto schedule;
+ }
+
+ /* read data from DATA_REG */
+ rc = gsl_ts_read(ts->client, 0x80, ts->touch_data, ts->dd->data_size);
+ dbg("---touches: %d ---\n",ts->touch_data[0]);
+
+ if (rc < 0)
+ {
+ dev_err(&ts->client->dev, "read failed\n");
+ goto schedule;
+ }
+
+ if (ts->touch_data[ts->dd->touch_index] == 0xff) {
+ goto schedule;
+ }
+
+ rc = gsl_ts_read( ts->client, 0xbc, read_buf, sizeof(read_buf));
+ if (rc < 0)
+ {
+ dev_err(&ts->client->dev, "read 0xbc failed\n");
+ goto schedule;
+ }
+ dbg("//////// reg %x : %x %x %x %x\n",0xbc, read_buf[3], read_buf[2], read_buf[1], read_buf[0]);
+
+ if (read_buf[3] == 0 && read_buf[2] == 0 && read_buf[1] == 0 && read_buf[0] == 0)
+ {
+ process_gslX680_data(ts);
+ }
+ else
+ {
+ reset_chip(ts->client);
+ startup_chip(ts->client);
+ }
+
+schedule:
+ //enable_irq(ts->irq);
+ wmt_enable_gpirq();
+
+}
+
+static irqreturn_t gsl_ts_irq(int irq, void *dev_id)
+{
+ struct gsl_ts *ts = dev_id;
+
+ if (wmt_is_tsint())
+ {
+ wmt_clr_int();
+ if (wmt_is_tsirq_enable() && ts->is_suspended == false)
+ {
+ wmt_disable_gpirq();
+ dbg("begin..\n");
+ //if (!work_pending(&l_tsdata.pen_event_work))
+ {
+ queue_work(ts->wq, &ts->work);
+ }
+ }
+ return IRQ_HANDLED;
+ }
+ return IRQ_NONE;
+
+
+ /*disable_irq_nosync(ts->irq);
+
+ if (!work_pending(&ts->work))
+ {
+ queue_work(ts->wq, &ts->work);
+ }
+
+ return IRQ_HANDLED;*/
+
+}
+
+#ifdef GSL_TIMER
+static void gsl_timer_handle(unsigned long data)
+{
+ struct gsl_ts *ts = (struct gsl_ts *)data;
+
+#ifdef GSL_DEBUG
+ dbg("----------------gsl_timer_handle-----------------\n");
+#endif
+
+ disable_irq_nosync(ts->irq);
+ check_mem_data(ts->client);
+ ts->gsl_timer.expires = jiffies + 3 * HZ;
+ add_timer(&ts->gsl_timer);
+ enable_irq(ts->irq);
+
+}
+#endif
+
+static int gsl_ts_init_ts(struct i2c_client *client, struct gsl_ts *ts)
+{
+ struct input_dev *input_device;
+ int i;
+ int rc = 0;
+
+ dbg("[GSLX680] Enter %s\n", __func__);
+
+
+ ts->dd = &devices[ts->device_id];
+
+ if (ts->device_id == 0) {
+ ts->dd->data_size = MAX_FINGERS * ts->dd->touch_bytes + ts->dd->touch_meta_data;
+ ts->dd->touch_index = 0;
+ }
+
+ ts->touch_data = kzalloc(ts->dd->data_size, GFP_KERNEL);
+ if (!ts->touch_data) {
+ pr_err("%s: Unable to allocate memory\n", __func__);
+ return -ENOMEM;
+ }
+
+ ts->prev_touches = 0;
+
+ input_device = input_allocate_device();
+ if (!input_device) {
+ rc = -ENOMEM;
+ goto error_alloc_dev;
+ }
+
+ ts->input = input_device;
+ input_device->name = GSLX680_I2C_NAME;
+ input_device->id.bustype = BUS_I2C;
+ input_device->dev.parent = &client->dev;
+ input_set_drvdata(input_device, ts);
+
+#ifdef REPORT_DATA_ANDROID_4_0
+ __set_bit(EV_ABS, input_device->evbit);
+ __set_bit(EV_KEY, input_device->evbit);
+ __set_bit(EV_REP, input_device->evbit);
+ __set_bit(INPUT_PROP_DIRECT, input_device->propbit);
+ input_mt_init_slots(input_device, (MAX_CONTACTS+1));
+#else
+ //input_set_abs_params(input_device,ABS_MT_TRACKING_ID, 0, (MAX_CONTACTS+1), 0, 0);
+ set_bit(EV_ABS, input_device->evbit);
+ set_bit(EV_KEY, input_device->evbit);
+ __set_bit(INPUT_PROP_DIRECT, input_device->propbit);
+#endif
+
+ input_device->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+#ifdef HAVE_TOUCH_KEY
+ //input_device->evbit[0] = BIT_MASK(EV_KEY);
+ if (wmt_ts_if_tskey())
+ {
+ for (i = 0; i < MAX_KEY_NUM; i++)
+ set_bit(key_array[i], input_device->keybit);
+ }
+#endif
+
+ set_bit(ABS_MT_POSITION_X, input_device->absbit);
+ set_bit(ABS_MT_POSITION_Y, input_device->absbit);
+ //set_bit(ABS_MT_TOUCH_MAJOR, input_device->absbit);
+ //set_bit(ABS_MT_WIDTH_MAJOR, input_device->absbit);
+ //****************add 2013-1-10
+ set_bit(BTN_TOUCH, input_device->keybit);
+ set_bit(ABS_MT_TRACKING_ID, input_device->absbit);
+
+ dbg("regsister:x=%d,y=%d\n",wmt_ts_get_resolvX(),wmt_ts_get_resolvY());
+ if (wmt_ts_get_lcdexchg()) {
+ input_set_abs_params(input_device,ABS_MT_POSITION_X, 0, wmt_ts_get_resolvY(), 0, 0);
+ input_set_abs_params(input_device,ABS_MT_POSITION_Y, 0, wmt_ts_get_resolvX(), 0, 0);
+ } else {
+ input_set_abs_params(input_device,ABS_MT_POSITION_X, 0, wmt_ts_get_resolvX(), 0, 0);
+ input_set_abs_params(input_device,ABS_MT_POSITION_Y, 0, wmt_ts_get_resolvY(), 0, 0);
+ }
+ //input_set_abs_params(input_device,ABS_MT_TOUCH_MAJOR, 0, PRESS_MAX, 0, 0);
+ //input_set_abs_params(input_device,ABS_MT_WIDTH_MAJOR, 0, 200, 0, 0);
+
+ //client->irq = IRQ_PORT,
+ //ts->irq = client->irq;
+
+ ts->wq = create_singlethread_workqueue("kworkqueue_ts");
+ if (!ts->wq) {
+ dev_err(&client->dev, "Could not create workqueue\n");
+ goto error_wq_create;
+ }
+ flush_workqueue(ts->wq);
+
+ INIT_WORK(&ts->work, gsl_ts_xy_worker);
+
+ rc = input_register_device(input_device);
+ if (rc)
+ goto error_unreg_device;
+
+
+
+ return 0;
+
+error_unreg_device:
+ destroy_workqueue(ts->wq);
+error_wq_create:
+ input_free_device(input_device);
+error_alloc_dev:
+ kfree(ts->touch_data);
+ return rc;
+}
+
+static int gsl_ts_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct gsl_ts *ts = l_ts; //dev_get_drvdata(dev);
+ //int rc = 0;
+
+ printk("I'am in gsl_ts_suspend() start\n");
+ ts->is_suspended = true;
+
+#ifdef GSL_TIMER
+ printk( "gsl_ts_suspend () : delete gsl_timer\n");
+
+ del_timer(&ts->gsl_timer);
+#endif
+ //disable_irq_nosync(ts->irq);
+ wmt_disable_gpirq();
+
+ reset_chip(ts->client);
+ gslX680_shutdown_low();
+ msleep(10);
+
+ return 0;
+}
+
+int resume_download_thread(void *arg)
+{
+ wake_lock(&downloadWakeLock);
+ gslX680_chip_init();
+ gslX680_shutdown_high();
+ msleep(20);
+ reset_chip(l_ts->client);
+ startup_chip(l_ts->client);
+ //check_mem_data(l_ts->client);
+ init_chip(l_ts->client);
+
+ l_ts->is_suspended = false;
+ if (!earlysus_en)
+ wmt_enable_gpirq();
+ wake_unlock(&downloadWakeLock);
+ return 0;
+}
+
+static int gsl_ts_resume(struct platform_device *pdev)
+{
+
+ gpio_direction_output(tp_led_gpio, !tp_led_gpio_active);
+#ifdef GSL_TIMER
+ dbg( "gsl_ts_resume () : add gsl_timer\n");
+
+ init_timer(&ts->gsl_timer);
+ ts->gsl_timer.expires = jiffies + 3 * HZ;
+ ts->gsl_timer.function = &gsl_timer_handle;
+ ts->gsl_timer.data = (unsigned long)ts;
+ add_timer(&ts->gsl_timer);
+#endif
+ if (is_delay) {
+ resume_download_task = kthread_create(resume_download_thread, NULL , "resume_download");
+ if(IS_ERR(resume_download_task)) {
+ errlog("cread thread failed\n");
+ }
+ wake_up_process(resume_download_task);
+ } else
+ resume_download_thread(NULL);
+
+ return 0;
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void gsl_ts_early_suspend(struct early_suspend *h)
+{
+ //struct gsl_ts *ts = container_of(h, struct gsl_ts, early_suspend);
+ dbg("[GSL1680] Enter %s\n", __func__);
+ //gsl_ts_suspend(&ts->client->dev);
+ wmt_disable_gpirq();
+}
+
+static void gsl_ts_late_resume(struct early_suspend *h)
+{
+ //struct gsl_ts *ts = container_of(h, struct gsl_ts, early_suspend);
+ dbg("[GSL1680] Enter %s\n", __func__);
+ //gsl_ts_resume(&ts->client->dev);
+ wmt_enable_gpirq();
+}
+#endif
+
+static void check_Backlight_delay(void)
+{
+ int ret;
+ int len = 7;
+ char retval[8];
+
+ ret = wmt_getsyspara("wmt.backlight.delay", retval, &len);
+ if(ret) {
+ dbg("Read wmt.backlight.delay Failed.\n");
+ is_delay = 0;
+ } else
+ is_delay = 1;
+}
+
+static void timeout_func(struct work_struct *work){
+ struct gsl_ts *ts =
+ container_of(work, struct gsl_ts, timeout_work.work);
+ int button_up = -1;
+
+ mutex_lock(&ts->timeout_mutex);
+ button_up = --ts->timeout_count;
+ mutex_unlock(&ts->timeout_mutex);
+
+ if( button_up < 0){
+ gpio_set_value(tp_led_gpio,!tp_led_gpio_active);
+ }else{
+ queue_delayed_work(ts->timeout_queue, &ts->timeout_work, msecs_to_jiffies(DELAY_TIMEOUT));
+ }
+
+}
+
+
+static int gsl_ts_probe(struct i2c_client *client)
+{
+ struct gsl_ts *ts;
+ int rc;
+
+ dbg("GSLX680 Enter %s\n", __func__);
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ dev_err(&client->dev, "I2C functionality not supported\n");
+ return -ENODEV;
+ }
+ if (wmt_get_fwdata())
+ {
+ errlog("Failed to load the firmware data!\n");
+ return -1;
+ }
+ ts = kzalloc(sizeof(*ts), GFP_KERNEL);
+ if (!ts) {
+ rc = -ENOMEM;
+ goto error_kfree_fw;
+ }
+ dbg("==kzalloc success=\n");
+ l_ts = ts;
+
+ ts->client = client;
+ i2c_set_clientdata(client, ts);
+ ts->device_id = 0;//id->driver_data;
+
+ ts->is_suspended = false;
+ ts->int_pending = false;
+ wake_lock_init(&downloadWakeLock, WAKE_LOCK_SUSPEND, "resume_download");
+ mutex_init(&ts->sus_lock);
+
+ rc = gsl_ts_init_ts(client, ts);
+ if (rc < 0) {
+ dev_err(&client->dev, "GSLX680 init failed\n");
+ goto error_mutex_destroy;
+ }
+
+ gslX680_chip_init();
+ init_chip(ts->client);
+ check_mem_data(ts->client);
+
+ ts->irq = wmt_get_tsirqnum();
+ rc= request_irq(wmt_get_tsirqnum(), gsl_ts_irq, IRQF_SHARED, client->name, ts);
+ if (rc < 0) {
+ dbg( "gsl_probe: request irq failed\n");
+ goto error_req_irq_fail;
+ }
+
+ if( tp_led_gpio >= 0 ){
+ if(gpio_request(tp_led_gpio, "tp_led_gpio") >= 0){
+ wmt_gpio_setpull(tp_led_gpio, tp_led_gpio_active ? WMT_GPIO_PULL_UP : WMT_GPIO_PULL_DOWN);
+ gpio_direction_output(tp_led_gpio, !tp_led_gpio_active);
+ #if 0
+ errlog("sel_reg_bit:%d sel_reg_active:%d\n",sel_reg_bit,sel_reg_active);
+ if(sel_reg_bit >= 0 && sel_reg_active >= 0){
+ if(sel_reg_active == 0){
+ REG32_VAL(__GPIO_BASE+PIN_SHARING_SEL_OFFSET) &= ~(1<<sel_reg_bit);
+ }else {
+ REG32_VAL(__GPIO_BASE+PIN_SHARING_SEL_OFFSET) |= (1<<sel_reg_bit);
+ }
+ }
+ #endif
+ }else{
+ errlog(" touch panel led gpio request failed !! \n");
+ goto error_req_irq_fail;
+ }
+
+ mutex_init(&ts->timeout_mutex);
+ ts->timeout_count = -1;
+ ts->timeout_queue= create_singlethread_workqueue("timeout_queue");
+ INIT_DELAYED_WORK(&ts->timeout_work,timeout_func);
+
+ }
+
+
+
+
+#ifdef GSL_TIMER
+ dbg( "gsl_ts_probe () : add gsl_timer\n");
+
+ init_timer(&ts->gsl_timer);
+ ts->gsl_timer.expires = jiffies + 3 * HZ; //¶¨Ê±3 ÃëÖÓ
+ ts->gsl_timer.function = &gsl_timer_handle;
+ ts->gsl_timer.data = (unsigned long)ts;
+ add_timer(&ts->gsl_timer);
+#endif
+
+ /* create debug attribute */
+ //rc = device_create_file(&ts->input->dev, &dev_attr_debug_enable);
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+ ts->early_suspend.suspend = gsl_ts_early_suspend;
+ ts->early_suspend.resume = gsl_ts_late_resume;
+ register_early_suspend(&ts->early_suspend);
+#endif
+
+ dbg("[GSLX680] End %s\n", __func__);
+ wmt_enable_gpirq();
+
+ check_Backlight_delay();
+ return 0;
+
+
+
+error_req_irq_fail:
+ free_irq(ts->irq, ts);
+
+error_mutex_destroy:
+ mutex_destroy(&ts->sus_lock);
+ wake_lock_destroy(&downloadWakeLock);
+ input_free_device(ts->input);
+ kfree(ts);
+error_kfree_fw:
+ kfree(GSLX680_FW);
+ return rc;
+}
+
+static int gsl_ts_remove(struct i2c_client *client)
+{
+
+
+ struct gsl_ts *ts = i2c_get_clientdata(client);
+ dbg("==gsl_ts_remove=\n");
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&ts->early_suspend);
+#endif
+
+ //device_init_wakeup(&client->dev, 0);
+ cancel_work_sync(&ts->work);
+
+ if( tp_led_gpio >= 0 ){
+ mutex_destroy(&ts->timeout_mutex);
+ gpio_free(tp_led_gpio);
+ tp_led_gpio = -1;
+ tp_led_gpio_active = -1;
+ }
+
+ free_irq(ts->irq, ts);
+ destroy_workqueue(ts->wq);
+ input_unregister_device(ts->input);
+ mutex_destroy(&ts->sus_lock);
+ wake_lock_destroy(&downloadWakeLock);
+
+ //device_remove_file(&ts->input->dev, &dev_attr_debug_enable);
+
+ if(GSLX680_FW){
+ kfree(GSLX680_FW);
+ GSLX680_FW = NULL;
+ }
+
+ kfree(ts->touch_data);
+ kfree(ts);
+
+ return 0;
+}
+
+/*
+static const struct i2c_device_id gsl_ts_id[] = {
+ {GSLX680_I2C_NAME, 0},
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, gsl_ts_id);
+
+
+static struct i2c_driver gsl_ts_driver = {
+ .driver = {
+ .name = GSLX680_I2C_NAME,
+ .owner = THIS_MODULE,
+ },
+#ifndef CONFIG_HAS_EARLYSUSPEND
+ .suspend = gsl_ts_suspend,
+ .resume = gsl_ts_resume,
+#endif
+ .probe = gsl_ts_probe,
+ .remove = __devexit_p(gsl_ts_remove),
+ .id_table = gsl_ts_id,
+};
+*/
+static int wmt_wakeup_bl_notify(struct notifier_block *nb, unsigned long event,
+ void *dummy)
+{
+ //printk("get notify\n");
+ switch (event) {
+ case BL_CLOSE:
+ l_ts->is_suspended = true;
+ //printk("\nclose backlight\n\n");
+ //printk("disable irq\n\n");
+ wmt_disable_gpirq();
+ break;
+ case BL_OPEN:
+ l_ts->is_suspended = false;
+ //printk("\nopen backlight\n\n");
+ //printk("enable irq\n\n");
+ wmt_enable_gpirq();
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block wmt_bl_notify = {
+ .notifier_call = wmt_wakeup_bl_notify,
+};
+
+static int gsl_ts_init(void)
+{
+ int ret = 0;
+ ret = gsl_ts_probe(ts_get_i2c_client());
+ if (ret)
+ {
+ dbg("Can't load gsl1680 ts driver!\n");
+ }
+ //dbg("ret=%d\n",ret);
+ if (earlysus_en)
+ register_bl_notifier(&wmt_bl_notify);
+ return ret;
+}
+static void gsl_ts_exit(void)
+{
+ dbg("==gsl_ts_exit==\n");
+ //i2c_del_driver(&gsl_ts_driver);
+ gsl_ts_remove(ts_get_i2c_client());
+ if (earlysus_en)
+ unregister_bl_notifier(&wmt_bl_notify);
+ return;
+}
+
+struct wmtts_device gslx680_tsdev = {
+ .driver_name = WMT_TS_I2C_NAME,
+ .ts_id = "GSL1680",
+ .init = gsl_ts_init,
+ .exit = gsl_ts_exit,
+ .suspend = gsl_ts_suspend,
+ .resume = gsl_ts_resume,
+};
+
+
+//module_init(gsl_ts_init);
+//module_exit(gsl_ts_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("GSLX680 touchscreen controller driver");
+MODULE_AUTHOR("Guan Yuwei, guanyuwei@basewin.com");
+MODULE_ALIAS("platform:gsl_ts");
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/gsl1680_ts/gslX680.h b/ANDROID_3.4.5/drivers/input/touchscreen/gsl1680_ts/gslX680.h
new file mode 100755
index 00000000..c146127c
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/gsl1680_ts/gslX680.h
@@ -0,0 +1,35 @@
+#ifndef _GSLX680_H_
+#define _GSLX680_H_
+
+
+
+#define GSL_NOID_VERSION
+#ifdef GSL_NOID_VERSION
+struct gsl_touch_info
+{
+ int x[10];
+ int y[10];
+ int id[10];
+ int finger_num;
+};
+extern unsigned int gsl_mask_tiaoping(void);
+extern unsigned int gsl_version_id(void);
+extern void gsl_alg_id_main(struct gsl_touch_info *cinfo);
+extern void gsl_DataInit(int *ret);
+
+extern int gsl_noid_ver;
+extern unsigned int gsl_config_data_id[512];
+#endif
+
+struct fw_data
+{
+ //u32 offset : 8;
+ //u32 : 0;
+ u32 offset;
+ u32 val;
+};
+
+extern void wmt_set_keypos(int index,int xmin,int xmax,int ymin,int ymax);
+
+
+#endif
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/gsl1680_ts/gsl_point_id.b b/ANDROID_3.4.5/drivers/input/touchscreen/gsl1680_ts/gsl_point_id.b
new file mode 100755
index 00000000..f25fccd3
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/gsl1680_ts/gsl_point_id.b
Binary files differ
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/gsl1680_ts/wmt_ts.c b/ANDROID_3.4.5/drivers/input/touchscreen/gsl1680_ts/wmt_ts.c
new file mode 100755
index 00000000..e0ddf9e7
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/gsl1680_ts/wmt_ts.c
@@ -0,0 +1,1102 @@
+#include <linux/unistd.h>
+#include <linux/time.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+//#include <asm/semaphore.h>
+#include <linux/proc_fs.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/suspend.h>
+#include <linux/input.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <mach/hardware.h>
+#include <linux/i2c.h>
+#include <linux/irq.h>
+
+#include <asm/uaccess.h>
+#include <linux/fs.h>
+#include <linux/syscalls.h>
+
+#include "gslX680.h"
+#include "wmt_ts.h"
+
+/////////////////////////////////////////////////////////////////
+
+// commands for ui
+#define TS_IOC_MAGIC 't'
+
+#define TS_IOCTL_CAL_START _IO(TS_IOC_MAGIC, 1)
+#define TS_IOCTL_CAL_DONE _IOW(TS_IOC_MAGIC, 2, int*)
+#define TS_IOCTL_GET_RAWDATA _IOR(TS_IOC_MAGIC, 3, int*)
+#define TS_IOCTL_CAL_QUIT _IOW(TS_IOC_MAGIC, 4, int*)
+#define TS_IOCTL_AUTO_CALIBRATION _IOW(TS_IOC_MAGIC, 5, int*)
+#define TS_IOC_MAXNR 5
+
+//
+#define TS_MAJOR 11
+#define TS_DRIVER_NAME "wmtts_touch"
+#define TS_NAME "wmtts"
+#define WMTTS_PROC_NAME "wmtts_config"
+
+#define EXT_GPIO0 0
+#define EXT_GPIO1 1
+#define EXT_GPIO2 2
+#define EXT_GPIO3 3
+#define EXT_GPIO4 4
+#define EXT_GPIO5 5
+#define EXT_GPIO6 6
+#define EXT_GPIO7 7
+
+typedef struct {
+ int a1;
+ int b1;
+ int c1;
+ int a2;
+ int b2;
+ int c2;
+ int delta;
+}CALIBRATION_PARAMETER, *PCALIBRATION_PARAMETER;
+
+
+static int irq_gpio;
+static int rst_gpio;
+static int panelres_x;
+static int panelres_y;
+static int lcd_exchg = 0;
+static DECLARE_WAIT_QUEUE_HEAD(queue);
+static CALIBRATION_PARAMETER g_CalcParam;
+static TS_EVENT g_evLast;
+static struct mutex cal_mutex;
+static DECLARE_WAIT_QUEUE_HEAD(ts_penup_wait_queue);
+
+static struct class* l_dev_class = NULL;
+static struct device *l_clsdevice = NULL;
+extern struct wmtts_device gslx680_tsdev;
+static struct wmtts_device* l_tsdev = &gslx680_tsdev;
+struct proc_dir_entry* l_tsproc = NULL;
+static struct i2c_client *l_client=NULL;
+static int l_penup = 0; // 1-pen up,0-pen down
+static int l_iftskey = -1; // 1:have ts key
+int earlysus_en = 0;
+
+int tp_led_gpio;
+int tp_led_gpio_active;
+
+int sel_reg_bit;
+int sel_reg_active;
+
+
+struct tp_infor
+{
+ //enum tp_type type;
+ char name[64];
+ int i2caddr;
+ int xaxis; //0: x,1: x swap with y
+ int xdir; // 1: positive,-1: revert
+ int ydir; // 1: positive,-1: revert
+ int finger_num;
+};
+
+static int l_tpindex = -1;
+static struct tp_infor l_tpinfor[1];
+
+
+/////////////////////////////////////////////////////
+// function declare
+/////////////////////////////////////////////////////
+extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
+extern int wmt_setsyspara(char *varname, unsigned char *varval);
+static int ts_writeproc( struct file *file,
+ const char *buffer,
+ unsigned long count,
+ void *data );
+static int ts_readproc(char *page, char **start, off_t off,
+ int count, int *eof, void *data);
+///////////////////////////////////////////////////////////////////////
+void TouchPanelCalibrateAPoint(
+ int UncalX, //@PARM The uncalibrated X coordinate
+ int UncalY, //@PARM The uncalibrated Y coordinate
+ int *pCalX, //@PARM The calibrated X coordinate
+ int *pCalY //@PARM The calibrated Y coordinate
+ )
+{
+ int x, y;
+ mutex_lock(&cal_mutex);
+ x = (g_CalcParam.a1 * UncalX + g_CalcParam.b1 * UncalY +
+ g_CalcParam.c1) / g_CalcParam.delta;
+ y = (g_CalcParam.a2 * UncalX + g_CalcParam.b2 * UncalY +
+ g_CalcParam.c2) / g_CalcParam.delta;
+
+//klog("afer(%d,%d)(%d,%d)\n", x,y,panelres_x,panelres_y);
+ if ( x < 0 )
+ x = 0;
+
+ if ( y < 0 )
+ y = 0;
+ if (x >= panelres_x)
+ x = panelres_x-1;
+ if (y >= panelres_y)
+ y = panelres_y-1;
+
+ *pCalX = x;
+ *pCalY = y;
+ mutex_unlock(&cal_mutex);
+ return;
+}
+
+int wmt_ts_if_tskey(void)
+{
+ return ((l_iftskey==1) ? 1: 0);
+}
+
+int wmt_ts_get_firmwfilename(char* fname)
+{
+ sprintf(fname,"%s_fw.tpf",l_tpinfor[l_tpindex].name);
+ return 0;
+}
+
+
+static struct device* get_tp_device(void){
+ if(l_client == NULL){
+ errlog("l_client is NULL\n");
+ }
+ return &l_client->dev;
+}
+
+
+unsigned int wmt_ts_get_xaxis(void)
+{
+ return l_tpinfor[l_tpindex].xaxis;
+}
+
+unsigned int wmt_ts_get_xdir(void)
+{
+ return l_tpinfor[l_tpindex].xdir;
+}
+
+unsigned int wmt_ts_get_ydir(void)
+{
+ return l_tpinfor[l_tpindex].ydir;
+}
+
+static int parse_firmwarefile(const char* filedata, struct fw_data** firmarr, unsigned int* id_config)
+{
+ char endflag[]="/* End flag */";
+ const char *p = filedata;
+ u32 val[2];
+ int i = 0;
+ int j = 0;
+ int k = 0;
+ const char *s = NULL;
+ int hex = 0;
+
+#ifdef GSL_NOID_VERSION
+ if (gsl_noid_ver) {
+ while (*p != '{') p++;
+ p++;
+ s = p;
+ while (*s != '}') {
+ if (*s == '0' && *(s+1) == 'x') {
+ hex = 1;
+ break;
+ }
+ s++;
+ }
+ while (*p != '}') {
+ sscanf(p,hex ? "%x" : "%u,",&(id_config[k++]));
+ p = strchr(p,',');p++;
+ }
+ }
+#endif
+
+ // the first {
+ while (*p!='{') p++;
+ p++;
+ s = p;
+ // calculate the number of array
+ while (strncmp(p,endflag,strlen(endflag)))
+ {
+ if (*p=='{')
+ {
+ i++;
+ }
+ p++;
+ };
+ dbg("the number of arry:0x%x\n", i);
+ // alloc the memory for array
+ *firmarr = kzalloc(sizeof(struct fw_data)*i, GFP_KERNEL);
+ // parse the value of array
+ p = s;
+ j = 0;
+ while (strncmp(p,endflag,strlen(endflag)))
+ {
+ if (*p=='{')
+ {
+ memset(val,0,sizeof(val));
+ sscanf(p,"{%x,%x}",val,val+1);
+ (*firmarr)[j].offset = val[0]&0x00FF;
+ (*firmarr)[j].val= val[1];
+ //dbg("data%x{%x,%x}\n",j,(*firmarr)[j].offset,(*firmarr)[j].val);
+ j++;
+ }
+ //p = strchr(p,'}');
+ p++;
+ if (j>=i-2)
+ {
+ dbg("%s",p);
+ }
+
+ };
+ if (i != j)
+ {
+ errlog("Error parsing file(the number of arry not match)!\n");
+ errlog("i=0x%x,j=0x%x\n", i,j);
+ kfree(*firmarr);
+ return -1;
+ };
+ dbg("paring firmware file end.\n");
+ return i;
+}
+
+
+
+//filepath:the path of firmware file;
+//firmdata:store the data from firmware file;
+//id_config:config data for some ICs whitch have no id;
+//return:the lengthen of firmware data,negative-parsing error.
+int read_firmwfile(char* filepath, struct fw_data** firmdata, unsigned int* id_config)
+{
+ const u8 *data = NULL;
+ int i = 0;
+ int ret = -1;
+ const struct firmware* tpfirmware = NULL;
+
+ klog("ts firmware file:%s\n",filepath);
+ ret = request_firmware(&tpfirmware, filepath, get_tp_device());
+ if (ret < 0) {
+ errlog("Failed load tp firmware: %s ret=%d\n", filepath,ret);
+ goto err_end;
+ }
+ data = tpfirmware->data;
+
+ i = parse_firmwarefile(data,firmdata,id_config);
+
+ if (i <= 0){
+ dbg("Failed to pare firmware file!\n");
+ ret = -1;
+ goto error_parse_fw;
+ }
+ dbg("firmware arry len=0x%x\n", i);
+ ret = i;
+ dbg("success to read firmware file!\n");;
+error_parse_fw:
+ if(tpfirmware){
+ release_firmware(tpfirmware);
+ tpfirmware = NULL;
+ }
+err_end:
+ return ret;
+}
+
+
+
+ int wmt_ts_get_gpionum(void)
+{
+ return irq_gpio;
+}
+
+int wmt_ts_get_resetgpnum(void)
+{
+ return rst_gpio;
+}
+
+int wmt_ts_get_lcdexchg(void)
+{
+ return lcd_exchg;
+}
+
+int wmt_ts_get_resolvX(void)
+{
+ return panelres_x;
+}
+
+int wmt_ts_get_resolvY(void)
+{
+ return panelres_y;
+}
+
+//up:1-pen up,0-pen down
+void wmt_ts_set_penup(int up)
+{
+ l_penup = up;
+}
+
+//
+int wmt_ts_wait_penup(void)
+{
+ int ret = wait_event_interruptible(
+ ts_penup_wait_queue,
+ (1==l_penup));
+ return ret;
+}
+
+// return:1-pen up,0-pen dwon
+int wmt_ts_ispenup(void)
+{
+ return l_penup;
+}
+
+
+void wmt_ts_wakeup_penup(void)
+{
+ wake_up(&ts_penup_wait_queue);
+}
+
+int wmt_is_tsirq_enable(void)
+{
+ int val = 0;
+ int num = irq_gpio;
+
+ if(num > 11)
+ return 0;
+
+ if(num<4)
+ val = REG32_VAL(__GPIO_BASE+0x0300) & (1<<(num*8+7));
+ else if(num >= 4 && num < 8)
+ val = REG32_VAL(__GPIO_BASE+0x0304) & (1<<((num-4)*8+7));
+ else
+ val = REG32_VAL(__GPIO_BASE+0x0308) & (1<<((num-8)*8+7));
+
+ return val?1:0;
+
+}
+
+int wmt_is_tsint(void)
+{
+ int num = irq_gpio;
+
+ if (num > 11)
+ {
+ return 0;
+ }
+ return (REG32_VAL(__GPIO_BASE+0x0360) & (1<<num)) ? 1: 0;
+}
+
+void wmt_clr_int(void)
+{
+ int num = irq_gpio;
+
+ if (num > 11)
+ {
+ return;
+ }
+ REG32_VAL(__GPIO_BASE+0x0360) = 1<<num;
+}
+
+void wmt_tsreset_init(void)
+{
+ int num = rst_gpio;
+
+ REG32_VAL(__GPIO_BASE+0x0040) |= (1<<num);//&= ~(1<<num); //enable gpio
+ REG32_VAL(__GPIO_BASE+0x00C0) &= ~(1<<num); // out low
+ REG32_VAL(__GPIO_BASE+0x0080) |= (1<<num); //output enable
+ msleep(10);
+ REG32_VAL(__GPIO_BASE+0x00C0) |= (1<<num); // out high
+}
+
+// enable:0-disable,1-enable
+void wmt_enable_rst_pull(int enable)
+{
+ if (enable)
+ {
+ REG32_VAL(__GPIO_BASE+0x0480) |= (1<<rst_gpio); //enable pull up/down
+ } else {
+ REG32_VAL(__GPIO_BASE+0x0480) &= ~(1<<rst_gpio); //disable pull up/down
+ }
+}
+
+// up:0-pull down,1-pull up
+void wmt_set_rst_pull(int up)
+{
+ if (up)
+ {
+ REG32_VAL(__GPIO_BASE+0x04c0) |= (1<<rst_gpio); //pull up
+ } else {
+ REG32_VAL(__GPIO_BASE+0x04c0) &= ~(1<<rst_gpio); //pull down
+ }
+}
+
+// high:0-low level,1-high level
+void wmt_rst_output(int high)
+{
+ REG32_VAL(__GPIO_BASE+0x0040) |= (1<<rst_gpio); //enable gpio
+ if (high)
+ {
+ REG32_VAL(__GPIO_BASE+0x00C0) |= (1<<rst_gpio); // high
+ } else {
+ REG32_VAL(__GPIO_BASE+0x00C0) &= ~(1<<rst_gpio); // low
+ }
+ REG32_VAL(__GPIO_BASE+0x0080) |= (1<<rst_gpio); //set output
+}
+
+void wmt_rst_input(void)
+{
+ REG32_VAL(__GPIO_BASE+0x0040) |= (1<<rst_gpio); //enable gpio
+ REG32_VAL(__GPIO_BASE+0x0080) &= ~(1<<rst_gpio); //set input
+}
+
+void wmt_set_intasgp(void)
+{
+ REG32_VAL(__GPIO_BASE+0x0040) |= (1<<irq_gpio); //enable gpio
+}
+
+// val:1--high,0-low
+void wmt_intgp_out(int val)
+{
+ if (val)
+ {
+ REG32_VAL(__GPIO_BASE+0x00C0) |= (1<<irq_gpio); // high
+ } else {
+ REG32_VAL(__GPIO_BASE+0x00C0) &= ~(1<<irq_gpio); // low
+ }
+ REG32_VAL(__GPIO_BASE+0x0080) |= (1<<irq_gpio); //set output
+}
+
+void wmt_ts_set_irqinput(void)
+{
+ int num = irq_gpio;
+
+ REG32_VAL(__GPIO_BASE+0x0040) |= (1<<num); //enable gpio
+ REG32_VAL(__GPIO_BASE+0x0080) &= ~(1<<num); //set input
+}
+
+unsigned int wmt_ts_irqinval(void)
+{
+ REG32_VAL(__GPIO_BASE+0x0040) &= ~(1<<irq_gpio); //enable gpio
+ REG32_VAL(__GPIO_BASE+0x0080) &= ~(1<<irq_gpio); //set input
+ return REG32_VAL(__GPIO_BASE+0x0000)&(1<<irq_gpio);
+}
+
+int wmt_set_gpirq(int type)
+{
+ int shift;
+ int offset;
+ unsigned long reg;
+ int num = irq_gpio;
+
+ if(num >11)
+ return -1;
+ //if (num > 9)
+ //GPIO_PIN_SHARING_SEL_4BYTE_VAL &= ~BIT4; // gpio10,11 as gpio
+ REG32_VAL(__GPIO_BASE+0x0040) &= ~(1<<num); //enable gpio
+ REG32_VAL(__GPIO_BASE+0x0080) &= ~(1<<num); //set input
+ REG32_VAL(__GPIO_BASE+0x04c0) |= (1<<num); //pull down
+ REG32_VAL(__GPIO_BASE+0x0480) |= (1<<num); //enable pull up/down
+
+ //set gpio irq triger type
+ if(num < 4){//[0,3]
+ shift = num;
+ offset = 0x0300;
+ }else if(num >= 4 && num < 8){//[4,7]
+ shift = num-4;
+ offset = 0x0304;
+ }else{// [8,11]
+ shift = num-8;
+ offset = 0x0308;
+ }
+
+ reg = REG32_VAL(__GPIO_BASE + offset);
+
+ switch(type){
+ case IRQ_TYPE_LEVEL_LOW:
+ reg &= ~(1<<(shift*8+2));
+ reg &= ~(1<<(shift*8+1));
+ reg &= ~(1<<(shift*8));
+ break;
+ case IRQ_TYPE_LEVEL_HIGH:
+ reg &= ~(1<<(shift*8+2));
+ reg &= ~(1<<(shift*8+1));
+ reg |= (1<<(shift*8));
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ reg &= ~(1<<(shift*8+2));
+ reg |= (1<<(shift*8+1));
+ reg &= ~(1<<(shift*8));
+ break;
+ case IRQ_TYPE_EDGE_RISING:
+ reg &= ~(1<<(shift*8+2));
+ reg |= (1<<(shift*8+1));
+ reg |= (1<<(shift*8));
+ break;
+ default://both edge
+ reg |= (1<<(shift*8+2));
+ reg &= ~(1<<(shift*8+1));
+ reg &= ~(1<<(shift*8));
+ break;
+
+ }
+ //reg |= 1<<(shift*8+7);//enable interrupt
+ reg &= ~(1<<(shift*8+7)); //disable int
+
+ REG32_VAL(__GPIO_BASE + offset) = reg;
+ REG32_VAL(__GPIO_BASE+0x0360) = 1<<num; //clear interrupt status
+ msleep(5);
+ return 0;
+}
+
+int wmt_enable_gpirq(void)
+{
+ int num = irq_gpio;
+
+ if(num > 11)
+ return -1;
+
+ if(num<4)
+ REG32_VAL(__GPIO_BASE+0x0300) |= 1<<(num*8+7); //enable interrupt
+ else if(num >= 4 && num < 8)
+ REG32_VAL(__GPIO_BASE+0x0304) |= 1<<((num-4)*8+7); //enable interrupt
+ else
+ REG32_VAL(__GPIO_BASE+0x0308) |= 1<<((num-8)*8+7); //enable interrupt
+
+ return 0;
+}
+
+int wmt_disable_gpirq(void)
+{
+ int num = irq_gpio;
+
+ if(num > 11)
+ return -1;
+
+ if(num<4)
+ REG32_VAL(__GPIO_BASE+0x0300) &= ~(1<<(num*8+7)); //enable interrupt
+ else if(num >= 4 && num < 8)
+ REG32_VAL(__GPIO_BASE+0x0304) &= ~(1<<((num-4)*8+7)); //enable interrupt
+ else
+ REG32_VAL(__GPIO_BASE+0x0308) &= ~(1<<((num-8)*8+7)); //enable interrupt
+
+ return 0;
+}
+
+
+int wmt_get_tsirqnum(void)
+{
+ return IRQ_GPIO;
+}
+
+
+int wmt_ts_set_rawcoord(unsigned short x, unsigned short y)
+{
+ g_evLast.x = x;
+ g_evLast.y = y;
+ //dbg("raw(%d,%d)*\n", x, y);
+ return 0;
+}
+
+static void wmt_ts_platform_release(struct device *device)
+{
+ return;
+}
+
+static struct platform_device wmt_ts_plt_device = {
+ .name = TS_DRIVER_NAME,
+ .id = 0,
+ .dev = {
+ .release = wmt_ts_platform_release,
+ },
+// .num_resources = ARRAY_SIZE(wm9715_ts_resources),
+// .resource = wm9715_ts_resources,
+};
+
+static int wmt_ts_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ dbg("ts suspend....\n");
+ if (l_tsdev->suspend != NULL)
+ {
+ return l_tsdev->suspend(pdev, state);
+ }
+ return 0;
+}
+static int wmt_ts_resume(struct platform_device *pdev)
+{
+ dbg("ts resume....\n");
+ if (l_tsdev->resume != NULL)
+ {
+ return l_tsdev->resume(pdev);
+ }
+ klog("...\n");
+ return 0;
+}
+
+static int wmt_ts_probe(struct platform_device *pdev)
+{
+ l_tsproc= create_proc_entry(WMTTS_PROC_NAME, 0666, NULL/*&proc_root*/);
+ if (l_tsproc != NULL)
+ {
+ l_tsproc->read_proc = ts_readproc;
+ l_tsproc->write_proc = ts_writeproc;
+ }
+
+ if (l_tsdev->probe != NULL)
+ return l_tsdev->probe(pdev);
+ else
+ return 0;
+}
+
+static int wmt_ts_remove(struct platform_device *pdev)
+{
+ if (l_tsproc != NULL)
+ {
+ remove_proc_entry(WMTTS_PROC_NAME, NULL);
+ l_tsproc = NULL;
+ }
+
+ if (l_tsdev->remove != NULL)
+ return l_tsdev->remove(pdev);
+ else
+ return 0;
+}
+
+static struct platform_driver wmt_ts_plt_driver = {
+ .driver = {
+ .name = TS_DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = wmt_ts_probe,
+ .remove = wmt_ts_remove,
+ .suspend = wmt_ts_suspend,
+ .resume = wmt_ts_resume,
+};
+
+static int wmt_ts_open(struct inode *inode, struct file *filp)
+{
+ int ret = 0;
+
+ klog("wmt ts driver opening...\n");
+
+ //ts_clear();
+ //try_module_get(THIS_MODULE);
+
+ return ret;
+}
+
+static int wmt_ts_close(struct inode *inode, struct file *filp)
+{
+ klog("wmt ts driver closing...\n");
+ //ts_clear();
+ //module_put(THIS_MODULE);
+
+ return 0;
+}
+
+static unsigned int wmt_ts_poll(struct file *filp, struct poll_table_struct *wait)
+{
+#if 0
+ poll_wait(filp, &queue, wait);
+ if ( head != tail )
+ return (POLLIN | POLLRDNORM);
+#endif
+ return 0;
+}
+
+static long wmt_ts_ioctl(/*struct inode * node,*/ struct file *dev, unsigned int cmd, unsigned long arg)
+{
+ int nBuff[7];
+ char env_val[96]={0};
+ //dbg("wmt_ts_ioctl(node=0x%p, dev=0x%p, cmd=0x%08x, arg=0x%08lx)\n", node, dev, cmd, arg);
+
+ if (_IOC_TYPE(cmd) != TS_IOC_MAGIC){
+ dbg("CMD ERROR!");
+ return -ENOTTY;
+ }
+
+ if (_IOC_NR(cmd) > TS_IOC_MAXNR){
+ dbg("NO SUCH IO CMD!\n");
+ return -ENOTTY;
+ }
+
+ switch (cmd) {
+
+ case TS_IOCTL_CAL_DONE:
+ klog("wmt_ts_ioctl: TS_IOCTL_CAL_DONE\n");
+ copy_from_user(nBuff, (unsigned int*)arg, 7*sizeof(int));
+
+ mutex_lock(&cal_mutex);
+ g_CalcParam.a1 = nBuff[0];
+ g_CalcParam.b1 = nBuff[1];
+ g_CalcParam.c1 = nBuff[2];
+ g_CalcParam.a2 = nBuff[3];
+ g_CalcParam.b2 = nBuff[4];
+ g_CalcParam.c2 = nBuff[5];
+ g_CalcParam.delta = nBuff[6];
+
+ if(g_CalcParam.delta == 0)
+ g_CalcParam.delta =1;//avoid divide by zero
+
+ mutex_unlock(&cal_mutex);
+
+ sprintf(env_val,"%d %d %d %d %d %d %d",nBuff[0],nBuff[1],nBuff[2],nBuff[3],nBuff[4],nBuff[5],nBuff[6]);
+ wmt_setsyspara("wmt.io.ts.2dcal", env_val);
+ klog("Tsc calibrate done data: [%s]\n",env_val);
+
+ return 0;
+
+
+ case TS_IOCTL_GET_RAWDATA:
+ // wait for point up
+ dbg("test wait_penup\n");
+ //l_tsdev->wait_penup(&gt811_tsdev);
+ klog("wmt_ts_ioctl: TS_IOCTL_GET_RAWDATA\n");
+ wmt_ts_wait_penup();
+
+ nBuff[0] = g_evLast.x;
+ nBuff[1] = g_evLast.y;
+ copy_to_user((unsigned int*)arg, nBuff, 2*sizeof(int));
+ klog("raw data: x=%d, y=%d\n", nBuff[0], nBuff[1]);
+
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static ssize_t wmt_ts_read(struct file *filp, char *buf, size_t count, loff_t *l)
+{
+ // read firmware file
+
+ return 0;
+}
+
+
+static struct file_operations wmt_ts_fops = {
+ .read = wmt_ts_read,
+ .poll = wmt_ts_poll,
+ .unlocked_ioctl = wmt_ts_ioctl,
+ .open = wmt_ts_open,
+ .release = wmt_ts_close,
+};
+
+static int ts_writeproc( struct file *file,
+ const char *buffer,
+ unsigned long count,
+ void *data )
+{
+ int calibrate = 0;
+ int val = 0;
+
+ if (sscanf(buffer, "calibrate=%d\n", &calibrate))
+ {
+ if (1 == calibrate)
+ {
+ if((l_tsdev->capacitance_calibrate != NULL) &&
+ (0 == l_tsdev->capacitance_calibrate()))
+ {
+ printk(KERN_ALERT "%s calibration successfully!\n", l_tsdev->ts_id);
+ } else {
+ printk(KERN_ALERT "%s calibration failed!\n", l_tsdev->ts_id);
+ }
+ }
+ } else if (sscanf(buffer, "reset=%d\n", &val))
+ {
+
+ }
+ return count;
+}
+
+static int ts_readproc(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int len = 0;
+
+ len = sprintf(page,
+ "echo calibrate=1 > /proc/wmtts_config to calibrate ts.\n");
+ return len;
+}
+
+static int wmt_check_touch_env(void)
+{
+ int ret = 0;
+ int len = 127, i = 0;
+ char retval[128] = {0},*p=NULL,*s=NULL;
+ int Enable=0;
+ int keypos[4][4];
+
+ // Get u-boot parameter
+ ret = wmt_getsyspara("wmt.io.touch", retval, &len);
+ if(ret){
+ errlog("Read wmt.io.touch Failed.\n");
+ return -EIO;
+ }
+ memset(l_tpinfor,0,sizeof(l_tpinfor[0]));
+ p = retval;
+ sscanf(p,"%d:", &Enable);
+ p = strchr(p,':');p++;
+ s = strchr(p,':');
+ strncpy(l_tpinfor[0].name,p, (s-p));
+ p = s+1;
+ dbg("ts_name=%s\n", l_tpinfor[0].name);
+
+ ret = sscanf(p,"%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
+ &irq_gpio,&panelres_x,&panelres_y,&rst_gpio,
+ &(l_tpinfor[0].xaxis),&(l_tpinfor[0].xdir),&(l_tpinfor[0].ydir),
+ &(l_tpinfor[0].finger_num),
+ &(l_tpinfor[0].i2caddr),&gsl_noid_ver);
+ if (ret < 9)
+ {
+ dbg("Wrong format ts u-boot param(%d)!\n",ret);
+ return -ENODEV;
+ }
+ //check touch enable
+ if(Enable == 0){
+ errlog("Touch Screen Is Disabled.\n");
+ return -ENODEV;
+ }
+
+ /*if (strstr(l_tpinfor[0].name, l_tsdev->ts_id) == NULL)
+ {
+ dbg("Can't find %s!\n", l_tsdev->ts_id);
+ return -ENODEV;
+ }*/
+ l_tpindex = 0;
+
+ klog("p.x = %d, p.y = %d, gpio=%d, resetgpio=%d,xaxis=%d,xdir=%d,ydri=%d,i2caddr=%d,gsl_noid_ver=%d\n",
+ panelres_x, panelres_y, irq_gpio, rst_gpio,
+ l_tpinfor[0].xaxis,l_tpinfor[0].xdir,l_tpinfor[0].ydir,
+ l_tpinfor[0].i2caddr, gsl_noid_ver);
+
+
+ memset(retval,0,sizeof(retval));
+ ret = wmt_getsyspara("wmt.io.tskey", retval, &len);
+ if(ret)
+ {
+ l_iftskey = 0;
+ } else {
+ // get touch key
+ p = retval;
+ sscanf(p,"%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d", \
+ keypos[0],keypos[0]+1,keypos[0]+2,keypos[0]+3, \
+ keypos[1],keypos[1]+1,keypos[1]+2,keypos[1]+3, \
+ keypos[2],keypos[2]+1,keypos[2]+2,keypos[2]+3, \
+ keypos[3],keypos[3]+1,keypos[3]+2,keypos[3]+3);
+ for (i = 0; i < 4; i++)
+ {
+ wmt_set_keypos(i,keypos[i][0],keypos[i][1],keypos[i][2],keypos[i][3]);
+ dbg("%d:%d,%d,%d,%d\n",i,keypos[i][0],keypos[i][1],keypos[i][2],keypos[i][3]);
+ };
+ l_iftskey = 1;
+ }
+
+ memset(retval,0,sizeof(retval));
+ ret = wmt_getsyspara("wmt.touch.earlysus", retval, &len);
+ if(!ret) {
+ p = retval;
+ sscanf(p, "%d", &earlysus_en);
+ }
+
+ ret = wmt_getsyspara("wmt.display.fb0", retval, &len);
+ if (!ret) {
+ int tmp[6];
+ p = retval;
+ sscanf(p, "%d:[%d:%d:%d:%d:%d", &tmp[0], &tmp[1], &tmp[2], &tmp[3], &tmp[4], &tmp[5]);
+ if (tmp[4] > tmp[5])
+ lcd_exchg = 1;
+ }
+
+ //wmt.tpkey.led 141:1
+ tp_led_gpio = -1;
+ tp_led_gpio_active = -1;
+ sel_reg_bit = -1;
+ sel_reg_active = -1;
+ ret = wmt_getsyspara("wmt.tpkey.led", retval, &len);
+
+ errlog("wmt.tpkey.led: %s \n",retval);
+
+ if (!ret) {
+ int tmp[4] = {0};
+ p = retval;
+ ret = sscanf(p, "%d:%d:%d:%d", &tmp[0], &tmp[1], &tmp[2], &tmp[3]);
+ if(ret == 2){
+ tp_led_gpio = tmp[0];
+ tp_led_gpio_active = tmp[1];
+ }
+ if(ret == 4){
+ tp_led_gpio = tmp[0];
+ tp_led_gpio_active = tmp[1];
+ sel_reg_bit = tmp[2];
+ sel_reg_active = tmp[3];
+ }
+ errlog("tp_led_gpio:%d tp_led_gpio_active:%d sel_reg_bit:%d sel_reg_active:%d \n"
+ ,tp_led_gpio,tp_led_gpio_active,sel_reg_bit,sel_reg_active);
+ }
+
+/*
+ memset(retval,0,sizeof(retval));
+ ret = wmt_getsyspara("wmt.io.ts.2dcal", retval, &len);
+ if(ret){
+ errlog("Read env wmt.io.ts.2dcal Failed.\n ");
+ //return -EIO;
+ }
+ i = 0;
+ while(i < sizeof(retval)){
+ if(retval[i]==' ' || retval[i]==',' || retval[i]==':')
+ retval[i] = '\0';
+ i++;
+ }
+
+ i = 0;
+ p = retval;
+ while(i<7 && p < (retval + sizeof(retval))){
+ if(*p == '\0')
+ p++;
+ else{
+ sscanf(p,"%d",&nBuff[i]);
+ //printk("%d\n",nBuff[i]);
+ p=p+strlen(p);
+ i++;
+ }
+ }
+ //sscanf(retval,"%d %d %d %d %d %d %d %d",&nBuff[0],&nBuff[1],&nBuff[2],&nBuff[3],&nBuff[4],&nBuff[5],&nBuff[6]);
+ printk("Tsc calibrate init data: [%d %d %d %d %d %d %d]\n",nBuff[0],nBuff[1],nBuff[2],nBuff[3],nBuff[4],nBuff[5],nBuff[6]);
+
+ g_CalcParam.a1 = nBuff[0];
+ g_CalcParam.b1 = nBuff[1];
+ g_CalcParam.c1 = nBuff[2];
+ g_CalcParam.a2 = nBuff[3];
+ g_CalcParam.b2 = nBuff[4];
+ g_CalcParam.c2 = nBuff[5];
+ g_CalcParam.delta = nBuff[6];
+
+ if(g_CalcParam.delta == 0)
+ g_CalcParam.delta =1;//avoid divide by zero
+*/
+ return 0;
+}
+
+struct i2c_board_info ts_i2c_board_info = {
+ .type = WMT_TS_I2C_NAME,
+ .flags = 0x00,
+ //.addr = WMT_TS_I2C_ADDR,
+ .platform_data = NULL,
+ .archdata = NULL,
+ .irq = -1,
+};
+
+static int ts_i2c_register_device (void)
+{
+ struct i2c_board_info *ts_i2c_bi;
+ struct i2c_adapter *adapter = NULL;
+ //struct i2c_client *client = NULL;
+
+ ts_i2c_board_info.addr = l_tpinfor[0].i2caddr;
+ ts_i2c_bi = &ts_i2c_board_info;
+ adapter = i2c_get_adapter(1);/*in bus 1*/
+
+ if (NULL == adapter) {
+ printk("can not get i2c adapter, client address error\n");
+ return -1;
+ }
+ l_client = i2c_new_device(adapter, ts_i2c_bi);
+ if (l_client == NULL) {
+ printk("allocate i2c client failed\n");
+ return -1;
+ }
+ i2c_put_adapter(adapter);
+ return 0;
+}
+
+static void ts_i2c_unregister_device(void)
+{
+ if (l_client != NULL)
+ {
+ i2c_unregister_device(l_client);
+ l_client = NULL;
+ }
+}
+
+struct i2c_client* ts_get_i2c_client(void)
+{
+ return l_client;
+}
+
+static int __init wmt_ts_init(void)
+{
+ int ret = 0;
+
+ if(wmt_check_touch_env())
+ return -ENODEV;
+
+ if (ts_i2c_register_device()<0)
+ {
+ dbg("Error to run ts_i2c_register_device()!\n");
+ return -1;
+ }
+ mutex_init(&cal_mutex);
+
+ if (l_tsdev->init() < 0){
+ dbg("Errors to init %s ts IC!!!\n", l_tsdev->ts_id);
+ ret = -1;
+ goto err_init;
+ }
+ // Create device node
+ if (register_chrdev (TS_MAJOR, TS_NAME, &wmt_ts_fops)) {
+ printk (KERN_ERR "wmt touch: unable to get major %d\n", TS_MAJOR);
+ return -EIO;
+ }
+
+ l_dev_class = class_create(THIS_MODULE, TS_NAME);
+ if (IS_ERR(l_dev_class)){
+ ret = PTR_ERR(l_dev_class);
+ printk(KERN_ERR "Can't class_create touch device !!\n");
+ return ret;
+ }
+ l_clsdevice = device_create(l_dev_class, NULL, MKDEV(TS_MAJOR, 0), NULL, TS_NAME);
+ if (IS_ERR(l_clsdevice)){
+ ret = PTR_ERR(l_clsdevice);
+ printk(KERN_ERR "Failed to create device %s !!!",TS_NAME);
+ return ret;
+ }
+
+ // register device and driver of platform
+ ret = platform_device_register(&wmt_ts_plt_device);
+ if(ret){
+ errlog("wmt ts plat device register failed!\n");
+ return ret;
+ }
+ ret = platform_driver_register(&wmt_ts_plt_driver);
+ if(ret){
+ errlog("can not register platform_driver_register\n");
+ platform_device_unregister(&wmt_ts_plt_device);
+ return ret;
+ }
+
+ klog("%s driver init ok!\n",l_tsdev->ts_id);
+ return 0;
+err_init:
+ ts_i2c_unregister_device();
+ return ret;
+}
+
+static void __exit wmt_ts_exit(void)
+{
+ dbg("%s\n",__FUNCTION__);
+
+ l_tsdev->exit();
+ platform_driver_unregister(&wmt_ts_plt_driver);
+ platform_device_unregister(&wmt_ts_plt_device);
+ device_destroy(l_dev_class, MKDEV(TS_MAJOR, 0));
+ unregister_chrdev(TS_MAJOR, TS_NAME);
+ class_destroy(l_dev_class);
+ mutex_destroy(&cal_mutex);
+ ts_i2c_unregister_device();
+}
+
+
+module_init(wmt_ts_init);
+module_exit(wmt_ts_exit);
+
+MODULE_LICENSE("GPL");
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/gsl1680_ts/wmt_ts.h b/ANDROID_3.4.5/drivers/input/touchscreen/gsl1680_ts/wmt_ts.h
new file mode 100755
index 00000000..ea764fd4
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/gsl1680_ts/wmt_ts.h
@@ -0,0 +1,117 @@
+
+#ifndef WMT_TSH_201010191758
+#define WMT_TSH_201010191758
+
+#include <linux/platform_device.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/suspend.h>
+#include <linux/i2c.h>
+#include <linux/firmware.h>
+#include <mach/hardware.h>
+
+
+//#define DEBUG_WMT_TS // kinseyli
+#ifdef DEBUG_WMT_TS
+#undef dbg
+#define dbg(fmt, args...) printk(KERN_ALERT "[%s]: " fmt, __FUNCTION__ , ## args)
+
+//#define dbg(fmt, args...) if (kpadall_isrundbg()) printk(KERN_ALERT "[%s]: " fmt, __FUNCTION__, ## args)
+
+#else
+#define dbg(fmt, args...)
+#endif
+
+#undef errlog
+#undef klog
+#define errlog(fmt, args...) printk("[%s]: " fmt, __FUNCTION__, ## args)
+#define klog(fmt, args...) printk("[%s]: " fmt, __FUNCTION__, ## args)
+
+#define WMT_TS_I2C_NAME "gsl1680-ts"
+//#define WMT_TS_I2C_ADDR 0x15
+
+#define PIN_SHARING_SEL_OFFSET 0x200
+
+
+#define FW_BINARYFILE_SIZE 0x8000
+
+extern int earlysus_en;
+
+//////////////////////////////data type///////////////////////////
+typedef struct {
+ short pressure;
+ short x;
+ short y;
+ //short millisecs;
+} TS_EVENT;
+
+struct wmtts_device
+{
+ //data
+ char* driver_name;
+ char* ts_id;
+ //function
+ int (*init)(void);
+ int (*probe)(struct platform_device *platdev);
+ int (*remove)(struct platform_device *pdev);
+ void (*exit)(void);
+ int (*suspend)(struct platform_device *pdev, pm_message_t state);
+ int (*resume)(struct platform_device *pdev);
+ int (*capacitance_calibrate)(void);
+ int (*wait_penup)(struct wmtts_device*tsdev); // waiting untill penup
+ int penup; // 0--pendown;1--penup
+
+};
+
+
+//////////////////////////function interface/////////////////////////
+extern int wmt_ts_get_gpionum(void);
+extern int wmt_ts_iscalibrating(void);
+extern int wmt_ts_get_resolvX(void);
+extern int wmt_ts_get_resolvY(void);
+extern int wmt_ts_set_rawcoord(unsigned short x, unsigned short y);
+extern int wmt_set_gpirq(int type);
+extern int wmt_get_tsirqnum(void);
+extern int wmt_disable_gpirq(void);
+extern int wmt_enable_gpirq(void);
+extern int wmt_is_tsirq_enable(void);
+extern int wmt_is_tsint(void);
+extern void wmt_clr_int(void);
+extern void wmt_tsreset_init(void);
+extern int wmt_ts_get_resetgpnum(void);
+extern int wmt_ts_get_lcdexchg(void);
+extern void wmt_enable_rst_pull(int enable);
+extern void wmt_set_rst_pull(int up);
+extern void wmt_rst_output(int high);
+extern void wmt_rst_input(void);
+extern void wmt_set_intasgp(void);
+extern void wmt_intgp_out(int val);
+extern void wmt_ts_set_irqinput(void);
+extern unsigned int wmt_ts_irqinval(void);
+extern void wmt_ts_set_penup(int up);
+extern int wmt_ts_wait_penup(void);
+extern void wmt_ts_wakeup_penup(void);
+extern struct i2c_client* ts_get_i2c_client(void);
+extern int wmt_ts_ispenup(void);
+extern unsigned int wmt_ts_get_xaxis(void);
+extern unsigned int wmt_ts_get_xdir(void);
+extern unsigned int wmt_ts_get_ydir(void);
+extern int wmt_ts_if_tskey(void);
+
+extern void TouchPanelCalibrateAPoint(
+ int UncalX, //@PARM The uncalibrated X coordinate
+ int UncalY, //@PARM The uncalibrated Y coordinate
+ int *pCalX, //@PARM The calibrated X coordinate
+ int *pCalY //@PARM The calibrated Y coordinate
+ );
+
+//filepath:the path of firmware file;
+//firmdata:store the data from firmware file;
+//return:the lengthen of firmware data,negative-parsing error.
+extern int read_firmwfile(char* filepath, struct fw_data** firmdata, unsigned int* id_config);
+extern int wmt_ts_get_firmwfilename(char* fname);
+
+#endif
+
+
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/gt9xx_ts/Kconfig b/ANDROID_3.4.5/drivers/input/touchscreen/gt9xx_ts/Kconfig
new file mode 100755
index 00000000..d5d6a394
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/gt9xx_ts/Kconfig
@@ -0,0 +1,11 @@
+config TOUCHSCREEN_GT9XX
+ tristate "GT9XX Capacity Touchscreen Device Support"
+ default y
+ depends on ARCH_WMT
+ ---help---
+ Say Y here if you have an WMT based board with touchscreen
+ attached to it.
+ If unsure, say N.
+ To compile this driver as a module, choose M here: the
+ module will be called gt9xx.
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/gt9xx_ts/Makefile b/ANDROID_3.4.5/drivers/input/touchscreen/gt9xx_ts/Makefile
new file mode 100755
index 00000000..642b1271
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/gt9xx_ts/Makefile
@@ -0,0 +1,34 @@
+KERNELDIR=../../../../
+CROSS = arm_1103_le-
+CC= $(CROSS)gcc
+LD= $(CROSS)ld
+STRIP = $(CROSS)strip
+
+DEBUG = n
+
+# Add your debugging flag (or not) to EXTRA_CFLAGS
+ifeq ($(DEBUG),y)
+# DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+DEBFLAGS = -O0 -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+
+else
+ DEBFLAGS = -O2 -Wall
+endif
+
+EXTRA_CFLAGS += $(DEBFLAGS)
+
+
+MY_MODULE_NAME=s_wmt_ts_gt9xx
+
+#obj-$(CONFIG_TOUCHSCREEN_FT5X0X) := $(MY_MODULE_NAME).o
+obj-m := $(MY_MODULE_NAME).o
+$(MY_MODULE_NAME)-objs := gt9xx.o gt9xx_update.o goodix_tool.o
+
+default:
+ $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules
+ $(STRIP) --strip-debug $(MY_MODULE_NAME).ko
+ @rm -rf *.o *~ core .depend .*.cmd *.mod.c .tmp_versions *.order *.symvers
+
+clean:
+ @rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.order *.symvers
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/gt9xx_ts/goodix_tool.c b/ANDROID_3.4.5/drivers/input/touchscreen/gt9xx_ts/goodix_tool.c
new file mode 100755
index 00000000..3dfe4e1d
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/gt9xx_ts/goodix_tool.c
@@ -0,0 +1,615 @@
+/* drivers/input/touchscreen/goodix_tool.c
+ *
+ * 2010 - 2012 Goodix Technology.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be a reference
+ * to you, when you are integrating the GOODiX's CTP IC into your system,
+ * 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:1.6
+ * V1.0:2012/05/01,create file.
+ * V1.2:2012/06/08,modify some warning.
+ * V1.4:2012/08/28,modified to support GT9XX
+ * V1.6:new proc name
+ */
+
+#include "gt9xx.h"
+
+#define DATA_LENGTH_UINT 512
+#define CMD_HEAD_LENGTH (sizeof(st_cmd_head) - sizeof(u8*))
+static char procname[20] = {0};
+
+#define UPDATE_FUNCTIONS
+
+#ifdef UPDATE_FUNCTIONS
+extern s32 gup_enter_update_mode(struct i2c_client *client);
+extern void gup_leave_update_mode(void);
+extern s32 gup_update_proc(void *dir);
+#endif
+
+extern void gtp_irq_disable(struct goodix_ts_data *);
+extern void gtp_irq_enable(struct goodix_ts_data *);
+
+#pragma pack(1)
+typedef struct{
+ u8 wr; //write read flag£¬0:R 1:W 2:PID 3:
+ u8 flag; //0:no need flag/int 1: need flag 2:need int
+ u8 flag_addr[2]; //flag address
+ u8 flag_val; //flag val
+ u8 flag_relation; //flag_val:flag 0:not equal 1:equal 2:> 3:<
+ u16 circle; //polling cycle
+ u8 times; //plling times
+ u8 retry; //I2C retry times
+ u16 delay; //delay befor read or after write
+ u16 data_len; //data length
+ u8 addr_len; //address length
+ u8 addr[2]; //address
+ u8 res[3]; //reserved
+ u8* data; //data pointer
+}st_cmd_head;
+#pragma pack()
+st_cmd_head cmd_head;
+
+static struct i2c_client *gt_client = NULL;
+
+static struct proc_dir_entry *goodix_proc_entry;
+
+static s32 goodix_tool_write(struct file *filp, const char __user *buff, unsigned long len, void *data);
+static s32 goodix_tool_read( char *page, char **start, off_t off, int count, int *eof, void *data );
+static s32 (*tool_i2c_read)(u8 *, u16);
+static s32 (*tool_i2c_write)(u8 *, u16);
+
+#if GTP_ESD_PROTECT
+extern void gtp_esd_switch(struct i2c_client *, s32);
+#endif
+s32 DATA_LENGTH = 0;
+s8 IC_TYPE[16] = {0};
+
+static void tool_set_proc_name(char * procname)
+{
+ char *months[12] = {"Jan", "Feb", "Mar", "Apr", "May",
+ "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
+ char date[20] = {0};
+ char month[4] = {0};
+ int i = 0, n_month = 1, n_day = 0, n_year = 0;
+
+ sprintf(date, "%s", __DATE__);
+
+ //GTP_DEBUG("compile date: %s", date);
+
+ sscanf(date, "%s %d %d", month, &n_day, &n_year);
+
+ for (i = 0; i < 12; ++i)
+ {
+ if (!memcmp(months[i], month, 3))
+ {
+ n_month = i+1;
+ break;
+ }
+ }
+
+ sprintf(procname, "gmnode%04d%02d%02d", n_year, n_month, n_day);
+
+ //GTP_DEBUG("procname = %s", procname);
+}
+
+
+static s32 tool_i2c_read_no_extra(u8* buf, u16 len)
+{
+ s32 ret = -1;
+ s32 i = 0;
+ struct i2c_msg msgs[2];
+
+ msgs[0].flags = !I2C_M_RD;
+ msgs[0].addr = gt_client->addr;
+ msgs[0].len = cmd_head.addr_len;
+ msgs[0].buf = &buf[0];
+
+ msgs[1].flags = I2C_M_RD;
+ msgs[1].addr = gt_client->addr;
+ msgs[1].len = len;
+ msgs[1].buf = &buf[GTP_ADDR_LENGTH];
+
+ for (i = 0; i < cmd_head.retry; i++)
+ {
+ ret=i2c_transfer(gt_client->adapter, msgs, 2);
+ if (ret > 0)
+ {
+ break;
+ }
+ }
+ return ret;
+}
+
+static s32 tool_i2c_write_no_extra(u8* buf, u16 len)
+{
+ s32 ret = -1;
+ s32 i = 0;
+ struct i2c_msg msg;
+
+ msg.flags = !I2C_M_RD;
+ msg.addr = gt_client->addr;
+ msg.len = len;
+ msg.buf = buf;
+
+ for (i = 0; i < cmd_head.retry; i++)
+ {
+ ret=i2c_transfer(gt_client->adapter, &msg, 1);
+ if (ret > 0)
+ {
+ break;
+ }
+ }
+ return ret;
+}
+
+static s32 tool_i2c_read_with_extra(u8* buf, u16 len)
+{
+ s32 ret = -1;
+ u8 pre[2] = {0x0f, 0xff};
+ u8 end[2] = {0x80, 0x00};
+
+ tool_i2c_write_no_extra(pre, 2);
+ ret = tool_i2c_read_no_extra(buf, len);
+ tool_i2c_write_no_extra(end, 2);
+
+ return ret;
+}
+
+static s32 tool_i2c_write_with_extra(u8* buf, u16 len)
+{
+ s32 ret = -1;
+ u8 pre[2] = {0x0f, 0xff};
+ u8 end[2] = {0x80, 0x00};
+
+ tool_i2c_write_no_extra(pre, 2);
+ ret = tool_i2c_write_no_extra(buf, len);
+ tool_i2c_write_no_extra(end, 2);
+
+ return ret;
+}
+
+static void register_i2c_func(void)
+{
+// if (!strncmp(IC_TYPE, "GT818", 5) || !strncmp(IC_TYPE, "GT816", 5)
+// || !strncmp(IC_TYPE, "GT811", 5) || !strncmp(IC_TYPE, "GT818F", 6)
+// || !strncmp(IC_TYPE, "GT827", 5) || !strncmp(IC_TYPE,"GT828", 5)
+// || !strncmp(IC_TYPE, "GT813", 5))
+ if (strncmp(IC_TYPE, "GT8110", 6) && strncmp(IC_TYPE, "GT8105", 6)
+ && strncmp(IC_TYPE, "GT801", 5) && strncmp(IC_TYPE, "GT800", 5)
+ && strncmp(IC_TYPE, "GT801PLUS", 9) && strncmp(IC_TYPE, "GT811", 5)
+ && strncmp(IC_TYPE, "GTxxx", 5))
+ {
+ tool_i2c_read = tool_i2c_read_with_extra;
+ tool_i2c_write = tool_i2c_write_with_extra;
+ GTP_DEBUG("I2C function: with pre and end cmd!");
+ }
+ else
+ {
+ tool_i2c_read = tool_i2c_read_no_extra;
+ tool_i2c_write = tool_i2c_write_no_extra;
+ GTP_INFO("I2C function: without pre and end cmd!");
+ }
+}
+
+static void unregister_i2c_func(void)
+{
+ tool_i2c_read = NULL;
+ tool_i2c_write = NULL;
+ GTP_INFO("I2C function: unregister i2c transfer function!");
+}
+
+
+s32 init_wr_node(struct i2c_client *client)
+{
+ s32 i;
+
+ gt_client = client;
+ memset(&cmd_head, 0, sizeof(cmd_head));
+ cmd_head.data = NULL;
+
+ i = 5;
+ while ((!cmd_head.data) && i)
+ {
+ cmd_head.data = kzalloc(i * DATA_LENGTH_UINT, GFP_KERNEL);
+ if (NULL != cmd_head.data)
+ {
+ break;
+ }
+ i--;
+ }
+ if (i)
+ {
+ DATA_LENGTH = i * DATA_LENGTH_UINT + GTP_ADDR_LENGTH;
+ GTP_INFO("Applied memory size:%d.", DATA_LENGTH);
+ }
+ else
+ {
+ GTP_ERROR("Apply for memory failed.");
+ return FAIL;
+ }
+
+ cmd_head.addr_len = 2;
+ cmd_head.retry = 5;
+
+ register_i2c_func();
+
+ tool_set_proc_name(procname);
+ goodix_proc_entry = create_proc_entry(procname, 0666, NULL);
+ if (goodix_proc_entry == NULL)
+ {
+ GTP_ERROR("Couldn't create proc entry!");
+ return FAIL;
+ }
+ else
+ {
+ GTP_INFO("Create proc entry success!");
+ goodix_proc_entry->write_proc = goodix_tool_write;
+ goodix_proc_entry->read_proc = goodix_tool_read;
+ }
+
+ return SUCCESS;
+}
+
+void uninit_wr_node(void)
+{
+ kfree(cmd_head.data);
+ cmd_head.data = NULL;
+ unregister_i2c_func();
+ remove_proc_entry(procname, NULL);
+}
+
+static u8 relation(u8 src, u8 dst, u8 rlt)
+{
+ u8 ret = 0;
+
+ switch (rlt)
+ {
+ case 0:
+ ret = (src != dst) ? true : false;
+ break;
+
+ case 1:
+ ret = (src == dst) ? true : false;
+ GTP_DEBUG("equal:src:0x%02x dst:0x%02x ret:%d.", src, dst, (s32)ret);
+ break;
+
+ case 2:
+ ret = (src > dst) ? true : false;
+ break;
+
+ case 3:
+ ret = (src < dst) ? true : false;
+ break;
+
+ case 4:
+ ret = (src & dst) ? true : false;
+ break;
+
+ case 5:
+ ret = (!(src | dst)) ? true : false;
+ break;
+
+ default:
+ ret = false;
+ break;
+ }
+
+ return ret;
+}
+
+/*******************************************************
+Function:
+ Comfirm function.
+Input:
+ None.
+Output:
+ Return write length.
+********************************************************/
+static u8 comfirm(void)
+{
+ s32 i = 0;
+ u8 buf[32];
+
+// memcpy(&buf[GTP_ADDR_LENGTH - cmd_head.addr_len], &cmd_head.flag_addr, cmd_head.addr_len);
+// memcpy(buf, &cmd_head.flag_addr, cmd_head.addr_len);//Modified by Scott, 2012-02-17
+ memcpy(buf, cmd_head.flag_addr, cmd_head.addr_len);
+
+ for (i = 0; i < cmd_head.times; i++)
+ {
+ if (tool_i2c_read(buf, 1) <= 0)
+ {
+ GTP_ERROR("Read flag data failed!");
+ return FAIL;
+ }
+ if (true == relation(buf[GTP_ADDR_LENGTH], cmd_head.flag_val, cmd_head.flag_relation))
+ {
+ GTP_DEBUG("value at flag addr:0x%02x.", buf[GTP_ADDR_LENGTH]);
+ GTP_DEBUG("flag value:0x%02x.", cmd_head.flag_val);
+ break;
+ }
+
+ msleep(cmd_head.circle);
+ }
+
+ if (i >= cmd_head.times)
+ {
+ GTP_ERROR("Didn't get the flag to continue!");
+ return FAIL;
+ }
+
+ return SUCCESS;
+}
+
+/*******************************************************
+Function:
+ Goodix tool write function.
+Input:
+ standard proc write function param.
+Output:
+ Return write length.
+********************************************************/
+static s32 goodix_tool_write(struct file *filp, const char __user *buff, unsigned long len, void *data)
+{
+ s32 ret = 0;
+ GTP_DEBUG_FUNC();
+ GTP_DEBUG_ARRAY((u8*)buff, len);
+
+ ret = copy_from_user(&cmd_head, buff, CMD_HEAD_LENGTH);
+ if(ret)
+ {
+ GTP_ERROR("copy_from_user failed.");
+ }
+
+ GTP_DEBUG("wr :0x%02x.", cmd_head.wr);
+ GTP_DEBUG("flag:0x%02x.", cmd_head.flag);
+ GTP_DEBUG("flag addr:0x%02x%02x.", cmd_head.flag_addr[0], cmd_head.flag_addr[1]);
+ GTP_DEBUG("flag val:0x%02x.", cmd_head.flag_val);
+ GTP_DEBUG("flag rel:0x%02x.", cmd_head.flag_relation);
+ GTP_DEBUG("circle :%d.", (s32)cmd_head.circle);
+ GTP_DEBUG("times :%d.", (s32)cmd_head.times);
+ GTP_DEBUG("retry :%d.", (s32)cmd_head.retry);
+ GTP_DEBUG("delay :%d.", (s32)cmd_head.delay);
+ GTP_DEBUG("data len:%d.", (s32)cmd_head.data_len);
+ GTP_DEBUG("addr len:%d.", (s32)cmd_head.addr_len);
+ GTP_DEBUG("addr:0x%02x%02x.", cmd_head.addr[0], cmd_head.addr[1]);
+ GTP_DEBUG("len:%d.", (s32)len);
+ GTP_DEBUG("buf[20]:0x%02x.", buff[CMD_HEAD_LENGTH]);
+
+ if (1 == cmd_head.wr)
+ {
+ // copy_from_user(&cmd_head.data[cmd_head.addr_len], &buff[CMD_HEAD_LENGTH], cmd_head.data_len);
+ ret = copy_from_user(&cmd_head.data[GTP_ADDR_LENGTH], &buff[CMD_HEAD_LENGTH], cmd_head.data_len);
+ if(ret)
+ {
+ GTP_ERROR("copy_from_user failed.");
+ }
+ memcpy(&cmd_head.data[GTP_ADDR_LENGTH - cmd_head.addr_len], cmd_head.addr, cmd_head.addr_len);
+
+ GTP_DEBUG_ARRAY(cmd_head.data, cmd_head.data_len + cmd_head.addr_len);
+ GTP_DEBUG_ARRAY((u8*)&buff[CMD_HEAD_LENGTH], cmd_head.data_len);
+
+ if (1 == cmd_head.flag)
+ {
+ if (FAIL == comfirm())
+ {
+ GTP_ERROR("[WRITE]Comfirm fail!");
+ return FAIL;
+ }
+ }
+ else if (2 == cmd_head.flag)
+ {
+ //Need interrupt!
+ }
+ if (tool_i2c_write(&cmd_head.data[GTP_ADDR_LENGTH - cmd_head.addr_len],
+ cmd_head.data_len + cmd_head.addr_len) <= 0)
+ {
+ GTP_ERROR("[WRITE]Write data failed!");
+ return FAIL;
+ }
+
+ GTP_DEBUG_ARRAY(&cmd_head.data[GTP_ADDR_LENGTH - cmd_head.addr_len],cmd_head.data_len + cmd_head.addr_len);
+ if (cmd_head.delay)
+ {
+ msleep(cmd_head.delay);
+ }
+
+ return cmd_head.data_len + CMD_HEAD_LENGTH;
+ }
+ else if (3 == cmd_head.wr) //Write ic type
+ {
+ ret = copy_from_user(&cmd_head.data[0], &buff[CMD_HEAD_LENGTH], cmd_head.data_len);
+ if(ret)
+ {
+ GTP_ERROR("copy_from_user failed.");
+ }
+ memcpy(IC_TYPE, cmd_head.data, cmd_head.data_len);
+
+ register_i2c_func();
+
+ return cmd_head.data_len + CMD_HEAD_LENGTH;
+ }
+ else if (5 == cmd_head.wr)
+ {
+ //memcpy(IC_TYPE, cmd_head.data, cmd_head.data_len);
+
+ return cmd_head.data_len + CMD_HEAD_LENGTH;
+ }
+ else if (7 == cmd_head.wr)//disable irq!
+ {
+ gtp_irq_disable(i2c_get_clientdata(gt_client));
+
+ #if GTP_ESD_PROTECT
+ gtp_esd_switch(gt_client, SWITCH_OFF);
+ #endif
+ return CMD_HEAD_LENGTH;
+ }
+ else if (9 == cmd_head.wr) //enable irq!
+ {
+ gtp_irq_enable(i2c_get_clientdata(gt_client));
+
+ #if GTP_ESD_PROTECT
+ gtp_esd_switch(gt_client, SWITCH_ON);
+ #endif
+ return CMD_HEAD_LENGTH;
+ }
+ else if(17 == cmd_head.wr)
+ {
+ struct goodix_ts_data *ts = i2c_get_clientdata(gt_client);
+ ret = copy_from_user(&cmd_head.data[GTP_ADDR_LENGTH], &buff[CMD_HEAD_LENGTH], cmd_head.data_len);
+ if(ret)
+ {
+ GTP_DEBUG("copy_from_user failed.");
+ }
+ if(cmd_head.data[GTP_ADDR_LENGTH])
+ {
+ GTP_DEBUG("gtp enter rawdiff.");
+ ts->gtp_rawdiff_mode = true;
+ }
+ else
+ {
+ ts->gtp_rawdiff_mode = false;
+ GTP_DEBUG("gtp leave rawdiff.");
+ }
+ return CMD_HEAD_LENGTH;
+ }
+#ifdef UPDATE_FUNCTIONS
+ else if (11 == cmd_head.wr)//Enter update mode!
+ {
+ if (FAIL == gup_enter_update_mode(gt_client))
+ {
+ return FAIL;
+ }
+ }
+ else if (13 == cmd_head.wr)//Leave update mode!
+ {
+ gup_leave_update_mode();
+ }
+ else if (15 == cmd_head.wr) //Update firmware!
+ {
+ show_len = 0;
+ total_len = 0;
+ memset(cmd_head.data, 0, cmd_head.data_len + 1);
+ memcpy(cmd_head.data, &buff[CMD_HEAD_LENGTH], cmd_head.data_len);
+
+ if (FAIL == gup_update_proc((void*)cmd_head.data))
+ {
+ return FAIL;
+ }
+ }
+#endif
+
+ return CMD_HEAD_LENGTH;
+}
+
+/*******************************************************
+Function:
+ Goodix tool read function.
+Input:
+ standard proc read function param.
+Output:
+ Return read length.
+********************************************************/
+static s32 goodix_tool_read( char *page, char **start, off_t off, int count, int *eof, void *data )
+{
+ GTP_DEBUG_FUNC();
+
+ if (cmd_head.wr % 2)
+ {
+ return FAIL;
+ }
+ else if (!cmd_head.wr)
+ {
+ u16 len = 0;
+ s16 data_len = 0;
+ u16 loc = 0;
+
+ if (1 == cmd_head.flag)
+ {
+ if (FAIL == comfirm())
+ {
+ GTP_ERROR("[READ]Comfirm fail!");
+ return FAIL;
+ }
+ }
+ else if (2 == cmd_head.flag)
+ {
+ //Need interrupt!
+ }
+
+ memcpy(cmd_head.data, cmd_head.addr, cmd_head.addr_len);
+
+ GTP_DEBUG("[CMD HEAD DATA] ADDR:0x%02x%02x.", cmd_head.data[0], cmd_head.data[1]);
+ GTP_DEBUG("[CMD HEAD ADDR] ADDR:0x%02x%02x.", cmd_head.addr[0], cmd_head.addr[1]);
+
+ if (cmd_head.delay)
+ {
+ msleep(cmd_head.delay);
+ }
+
+ data_len = cmd_head.data_len;
+ while(data_len > 0)
+ {
+ if (data_len > DATA_LENGTH)
+ {
+ len = DATA_LENGTH;
+ }
+ else
+ {
+ len = data_len;
+ }
+ data_len -= DATA_LENGTH;
+
+ if (tool_i2c_read(cmd_head.data, len) <= 0)
+ {
+ GTP_ERROR("[READ]Read data failed!");
+ return FAIL;
+ }
+ memcpy(&page[loc], &cmd_head.data[GTP_ADDR_LENGTH], len);
+ loc += len;
+
+ GTP_DEBUG_ARRAY(&cmd_head.data[GTP_ADDR_LENGTH], len);
+ GTP_DEBUG_ARRAY(page, len);
+ }
+ }
+ else if (2 == cmd_head.wr)
+ {
+ // memcpy(page, "gt8", cmd_head.data_len);
+ // memcpy(page, "GT818", 5);
+ // page[5] = 0;
+
+ GTP_DEBUG("Return ic type:%s len:%d.", page, (s32)cmd_head.data_len);
+ return cmd_head.data_len;
+ //return sizeof(IC_TYPE_NAME);
+ }
+ else if (4 == cmd_head.wr)
+ {
+ page[0] = show_len >> 8;
+ page[1] = show_len & 0xff;
+ page[2] = total_len >> 8;
+ page[3] = total_len & 0xff;
+
+ return cmd_head.data_len;
+ }
+ else if (6 == cmd_head.wr)
+ {
+ //Read error code!
+ }
+ else if (8 == cmd_head.wr) //Read driver version
+ {
+ // memcpy(page, GTP_DRIVER_VERSION, strlen(GTP_DRIVER_VERSION));
+ s32 tmp_len;
+ tmp_len = strlen(GTP_DRIVER_VERSION);
+ memcpy(page, GTP_DRIVER_VERSION, tmp_len);
+ page[tmp_len] = 0;
+ }
+
+ return cmd_head.data_len;
+}
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/gt9xx_ts/gt9xx.c b/ANDROID_3.4.5/drivers/input/touchscreen/gt9xx_ts/gt9xx.c
new file mode 100755
index 00000000..cc02513e
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/gt9xx_ts/gt9xx.c
@@ -0,0 +1,2163 @@
+/* drivers/input/touchscreen/gt9xx.c
+ *
+ * 2010 - 2013 Goodix Technology.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be a reference
+ * to you, when you are integrating the GOODiX's CTP IC into your system,
+ * 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: 1.8
+ * Authors: andrew@goodix.com, meta@goodix.com
+ * Release Date: 2013/04/25
+ * Revision record:
+ * V1.0:
+ * first Release. By Andrew, 2012/08/31
+ * V1.2:
+ * modify gtp_reset_guitar,slot report,tracking_id & 0x0F. By Andrew, 2012/10/15
+ * V1.4:
+ * modify gt9xx_update.c. By Andrew, 2012/12/12
+ * V1.6:
+ * 1. new heartbeat/esd_protect mechanism(add external watchdog)
+ * 2. doze mode, sliding wakeup
+ * 3. 3 more cfg_group(GT9 Sensor_ID: 0~5)
+ * 3. config length verification
+ * 4. names & comments
+ * By Meta, 2013/03/11
+ * V1.8:
+ * 1. pen/stylus identification
+ * 2. read double check & fixed config support
+ * 2. new esd & slide wakeup optimization
+ * By Meta, 2013/06/08
+ */
+
+#include <linux/irq.h>
+#include <linux/firmware.h>
+#include "gt9xx.h"
+
+#if GTP_ICS_SLOT_REPORT
+ #include <linux/input/mt.h>
+#endif
+
+static const char *goodix_ts_name = "Goodix Capacitive TouchScreen";
+static struct workqueue_struct *goodix_wq;
+struct goodix_ts_data *l_ts;
+int l_suspend = 0;
+struct i2c_client * i2c_connect_client = NULL;
+u8 config[GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH]
+ = {GTP_REG_CONFIG_DATA >> 8, GTP_REG_CONFIG_DATA & 0xff};
+
+#if GTP_HAVE_TOUCH_KEY
+ static const u16 touch_key_array[] = GTP_KEY_TAB;
+ #define GTP_MAX_KEY_NUM (sizeof(touch_key_array)/sizeof(touch_key_array[0]))
+
+#if GTP_DEBUG_ON
+ static const int key_codes[] = {KEY_HOME, KEY_BACK, KEY_MENU, KEY_SEARCH};
+ static const char *key_names[] = {"Key_Home", "Key_Back", "Key_Menu", "Key_Search"};
+#endif
+
+#endif
+
+static s8 gtp_i2c_test(struct i2c_client *client);
+void gtp_reset_guitar(struct i2c_client *client, s32 ms);
+void gtp_int_sync(s32 ms);
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void goodix_ts_early_suspend(struct early_suspend *h);
+static void goodix_ts_late_resume(struct early_suspend *h);
+#endif
+
+#if GTP_CREATE_WR_NODE
+extern s32 init_wr_node(struct i2c_client*);
+extern void uninit_wr_node(void);
+#endif
+
+#if GTP_AUTO_UPDATE
+extern u8 gup_init_update_proc(struct goodix_ts_data *);
+#endif
+
+#if GTP_ESD_PROTECT
+static struct delayed_work gtp_esd_check_work;
+static struct workqueue_struct * gtp_esd_check_workqueue = NULL;
+static void gtp_esd_check_func(struct work_struct *);
+static s32 gtp_init_ext_watchdog(struct i2c_client *client);
+void gtp_esd_switch(struct goodix_ts_data *, s32);
+#endif
+
+
+#if GTP_SLIDE_WAKEUP
+typedef enum
+{
+ DOZE_DISABLED = 0,
+ DOZE_ENABLED = 1,
+ DOZE_WAKEUP = 2,
+}DOZE_T;
+static DOZE_T doze_status = DOZE_DISABLED;
+static s8 gtp_enter_doze(struct goodix_ts_data *ts);
+#endif
+
+static u8 chip_gt9xxs = 0; // true if ic is gt9xxs, like gt915s
+u8 grp_cfg_version = 0;
+
+/*******************************************************
+Function:
+ Read data from the i2c slave device.
+Input:
+ client: i2c device.
+ buf[0~1]: read start address.
+ buf[2~len-1]: read data buffer.
+ len: GTP_ADDR_LENGTH + read bytes count
+Output:
+ numbers of i2c_msgs to transfer:
+ 2: succeed, otherwise: failed
+*********************************************************/
+s32 gtp_i2c_read(struct i2c_client *client, u8 *buf, s32 len)
+{
+ struct i2c_msg msgs[2];
+ s32 ret=-1;
+ s32 retries = 0;
+
+ GTP_DEBUG_FUNC();
+
+ //msgs[0].flags = !I2C_M_RD;
+ msgs[0].flags = 0 | I2C_M_NOSTART;
+ msgs[0].addr = client->addr;
+ msgs[0].len = GTP_ADDR_LENGTH;
+ msgs[0].buf = &buf[0];
+ //msgs[0].scl_rate = 300 * 1000; // for Rockchip
+
+ msgs[1].flags = I2C_M_RD;
+ msgs[1].addr = client->addr;
+ msgs[1].len = len - GTP_ADDR_LENGTH;
+ msgs[1].buf = &buf[GTP_ADDR_LENGTH];
+ //msgs[1].scl_rate = 300 * 1000;
+
+ while(retries < 5)
+ {
+ ret = i2c_transfer(client->adapter, msgs, 2);
+ if(ret == 2)break;
+ retries++;
+ }
+ if((retries >= 5))
+ {
+ #if GTP_SLIDE_WAKEUP
+ // reset chip would quit doze mode
+ if (DOZE_ENABLED == doze_status)
+ {
+ return ret;
+ }
+ #endif
+ GTP_DEBUG("I2C communication timeout, resetting chip...");
+ gtp_reset_guitar(client, 10);
+ }
+ return ret;
+}
+
+/*******************************************************
+Function:
+ Write data to the i2c slave device.
+Input:
+ client: i2c device.
+ buf[0~1]: write start address.
+ buf[2~len-1]: data buffer
+ len: GTP_ADDR_LENGTH + write bytes count
+Output:
+ numbers of i2c_msgs to transfer:
+ 1: succeed, otherwise: failed
+*********************************************************/
+s32 gtp_i2c_write(struct i2c_client *client,u8 *buf,s32 len)
+{
+ struct i2c_msg msg;
+ s32 ret = -1;
+ s32 retries = 0;
+
+ GTP_DEBUG_FUNC();
+
+ msg.flags = !I2C_M_RD;
+ msg.addr = client->addr;
+ msg.len = len;
+ msg.buf = buf;
+ //msg.scl_rate = 300 * 1000; // for Rockchip
+
+ while(retries < 5)
+ {
+ ret = i2c_transfer(client->adapter, &msg, 1);
+ if (ret == 1)break;
+ retries++;
+ }
+ if((retries >= 5))
+ {
+ #if GTP_SLIDE_WAKEUP
+ if (DOZE_ENABLED == doze_status)
+ {
+ return ret;
+ }
+ #endif
+ GTP_DEBUG("I2C communication timeout, resetting chip...");
+ gtp_reset_guitar(client, 10);
+ }
+ return ret;
+}
+/*******************************************************
+Function:
+ i2c read twice, compare the results
+Input:
+ client: i2c device
+ addr: operate address
+ rxbuf: read data to store, if compare successful
+ len: bytes to read
+Output:
+ FAIL: read failed
+ SUCCESS: read successful
+*********************************************************/
+s32 gtp_i2c_read_dbl_check(struct i2c_client *client, u16 addr, u8 *rxbuf, int len)
+{
+ u8 buf[16] = {0};
+ u8 confirm_buf[16] = {0};
+ u8 retry = 0;
+
+ while (retry++ < 3)
+ {
+ memset(buf, 0xAA, 16);
+ buf[0] = (u8)(addr >> 8);
+ buf[1] = (u8)(addr & 0xFF);
+ gtp_i2c_read(client, buf, len + 2);
+
+ memset(confirm_buf, 0xAB, 16);
+ confirm_buf[0] = (u8)(addr >> 8);
+ confirm_buf[1] = (u8)(addr & 0xFF);
+ gtp_i2c_read(client, confirm_buf, len + 2);
+
+ if (!memcmp(buf, confirm_buf, len+2))
+ {
+ break;
+ }
+ }
+ if (retry < 3)
+ {
+ memcpy(rxbuf, confirm_buf+2, len);
+ return SUCCESS;
+ }
+ else
+ {
+ GTP_ERROR("i2c read 0x%04X, %d bytes, double check failed!", addr, len);
+ return FAIL;
+ }
+}
+
+/*******************************************************
+Function:
+ Send config.
+Input:
+ client: i2c device.
+Output:
+ result of i2c write operation.
+ 1: succeed, otherwise: failed
+*********************************************************/
+s32 gtp_send_cfg(struct goodix_ts_data * ts)
+{
+ s32 ret = 2;
+
+#if GTP_DRIVER_SEND_CFG
+ s32 retry = 0;
+
+ if (ts->fixed_cfg)
+ {
+ GTP_INFO("Ic fixed config, no config sent!");
+ return 2;
+ }
+ GTP_INFO("driver send config");
+ for (retry = 0; retry < 5; retry++)
+ {
+ ret = gtp_i2c_write(ts->client, config , GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH);
+ if (ret > 0)
+ {
+ break;
+ }
+ }
+#endif
+
+ return ret;
+}
+
+/*******************************************************
+Function:
+ Disable irq function
+Input:
+ ts: goodix i2c_client private data
+Output:
+ None.
+*********************************************************/
+void gtp_irq_disable(struct goodix_ts_data *ts)
+{
+ //unsigned long irqflags;
+
+ GTP_DEBUG_FUNC();
+
+ //spin_lock_irqsave(&ts->irq_lock, irqflags);
+ if (!ts->irq_is_disable)
+ {
+ ts->irq_is_disable = 1;
+ //disable_irq_nosync(ts->client->irq);
+ wmt_gpio_mask_irq(ts->irq_gpio);
+ }
+ //spin_unlock_irqrestore(&ts->irq_lock, irqflags);
+}
+
+/*******************************************************
+Function:
+ Enable irq function
+Input:
+ ts: goodix i2c_client private data
+Output:
+ None.
+*********************************************************/
+void gtp_irq_enable(struct goodix_ts_data *ts)
+{
+ //unsigned long irqflags = 0;
+
+ GTP_DEBUG_FUNC();
+
+ //spin_lock_irqsave(&ts->irq_lock, irqflags);
+ if (ts->irq_is_disable)
+ {
+ //enable_irq(ts->client->irq);
+ wmt_gpio_unmask_irq(ts->irq_gpio);
+ ts->irq_is_disable = 0;
+ }
+ //spin_unlock_irqrestore(&ts->irq_lock, irqflags);
+}
+
+
+/*******************************************************
+Function:
+ Report touch point event
+Input:
+ ts: goodix i2c_client private data
+ id: trackId
+ x: input x coordinate
+ y: input y coordinate
+ w: input pressure
+Output:
+ None.
+*********************************************************/
+static void gtp_touch_down(struct goodix_ts_data* ts,s32 id,s32 x,s32 y,s32 w)
+{
+ s32 px = 0, py = 0;
+#if GTP_CHANGE_X2Y
+ GTP_SWAP(x, y);
+#endif
+
+ if (ts->swap) {
+ px = y;
+ py = x;
+ } else {
+ px = x;
+ py = y;
+ }
+ if (ts->xdir == -1)
+ px = ts->abs_x_max - px;
+ if (ts->ydir == -1)
+ py = ts->abs_y_max - py;
+
+ if (ts->lcd_exchg) {
+ int tmp;
+ tmp = px;
+ px = py;
+ py = ts->abs_x_max - tmp;
+ }
+
+#if GTP_ICS_SLOT_REPORT
+ input_mt_slot(ts->input_dev, id);
+ input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, id);
+ 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_TOUCH_MAJOR, w);
+ input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, w);
+#else
+ input_report_abs(ts->input_dev, ABS_MT_POSITION_X, px);
+ input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, py);
+ //input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, w);
+ //input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, w);
+ input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, id);
+ input_mt_sync(ts->input_dev);
+#endif
+
+ GTP_DEBUG("ID:%d, X:%d, Y:%d, W:%d", id, px, py, w);
+}
+
+/*******************************************************
+Function:
+ Report touch release event
+Input:
+ ts: goodix i2c_client private data
+Output:
+ None.
+*********************************************************/
+static void gtp_touch_up(struct goodix_ts_data* ts, s32 id)
+{
+#if GTP_ICS_SLOT_REPORT
+ input_mt_slot(ts->input_dev, id);
+ input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, -1);
+ GTP_DEBUG("Touch id[%2d] release!", id);
+#else
+ //input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0);
+ //input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0);
+ input_mt_sync(ts->input_dev);
+#endif
+}
+
+
+/*******************************************************
+Function:
+ Goodix touchscreen work function
+Input:
+ work: work struct of goodix_workqueue
+Output:
+ None.
+*********************************************************/
+static void goodix_ts_work_func(struct work_struct *work)
+{
+ u8 end_cmd[3] = {GTP_READ_COOR_ADDR >> 8, GTP_READ_COOR_ADDR & 0xFF, 0};
+ u8 point_data[2 + 1 + 8 * GTP_MAX_TOUCH + 1]={GTP_READ_COOR_ADDR >> 8, GTP_READ_COOR_ADDR & 0xFF};
+ u8 touch_num = 0;
+ u8 finger = 0;
+ static u16 pre_touch = 0;
+ static u8 pre_key = 0;
+#if GTP_WITH_PEN
+ static u8 pre_pen = 0;
+#endif
+ u8 key_value = 0;
+ u8* coor_data = NULL;
+ s32 input_x = 0;
+ s32 input_y = 0;
+ s32 input_w = 0;
+ s32 id = 0;
+ s32 i = 0;
+ s32 ret = -1;
+ struct goodix_ts_data *ts = NULL;
+
+#if GTP_SLIDE_WAKEUP
+ u8 doze_buf[3] = {0x81, 0x4B};
+#endif
+
+ GTP_DEBUG_FUNC();
+ ts = container_of(work, struct goodix_ts_data, work);
+ if (ts->enter_update)
+ {
+ return;
+ }
+#if GTP_SLIDE_WAKEUP
+ if (DOZE_ENABLED == doze_status)
+ {
+ ret = gtp_i2c_read(i2c_connect_client, doze_buf, 3);
+ GTP_DEBUG("0x814B = 0x%02X", doze_buf[2]);
+ if (ret > 0)
+ {
+ if (doze_buf[2] == 0xAA)
+ {
+ GTP_INFO("Slide(0xAA) To Light up the screen!");
+ doze_status = DOZE_WAKEUP;
+ input_report_key(ts->input_dev, KEY_POWER, 1);
+ input_sync(ts->input_dev);
+ input_report_key(ts->input_dev, KEY_POWER, 0);
+ input_sync(ts->input_dev);
+ // clear 0x814B
+ doze_buf[2] = 0x00;
+ gtp_i2c_write(i2c_connect_client, doze_buf, 3);
+ }
+ else if (doze_buf[2] == 0xBB)
+ {
+ GTP_INFO("Slide(0xBB) To Light up the screen!");
+ doze_status = DOZE_WAKEUP;
+ input_report_key(ts->input_dev, KEY_POWER, 1);
+ input_sync(ts->input_dev);
+ input_report_key(ts->input_dev, KEY_POWER, 0);
+ input_sync(ts->input_dev);
+ // clear 0x814B
+ doze_buf[2] = 0x00;
+ gtp_i2c_write(i2c_connect_client, doze_buf, 3);
+ }
+ else if (0xC0 == (doze_buf[2] & 0xC0))
+ {
+ GTP_INFO("double click to light up the screen!");
+ doze_status = DOZE_WAKEUP;
+ input_report_key(ts->input_dev, KEY_POWER, 1);
+ input_sync(ts->input_dev);
+ input_report_key(ts->input_dev, KEY_POWER, 0);
+ input_sync(ts->input_dev);
+ // clear 0x814B
+ doze_buf[2] = 0x00;
+ gtp_i2c_write(i2c_connect_client, doze_buf, 3);
+ }
+ else
+ {
+ gtp_enter_doze(ts);
+ }
+ }
+ if (ts->use_irq)
+ {
+ gtp_irq_enable(ts);
+ }
+ return;
+ }
+#endif
+
+ ret = gtp_i2c_read(ts->client, point_data, 12);
+ if (ret < 0)
+ {
+ GTP_ERROR("I2C transfer error. errno:%d\n ", ret);
+ goto exit_work_func;
+ }
+
+ finger = point_data[GTP_ADDR_LENGTH];
+ if((finger & 0x80) == 0)
+ {
+ goto exit_work_func;
+ }
+
+ touch_num = finger & 0x0f;
+ if (touch_num > GTP_MAX_TOUCH)
+ {
+ goto exit_work_func;
+ }
+
+ if (touch_num > 1)
+ {
+ u8 buf[8 * GTP_MAX_TOUCH] = {(GTP_READ_COOR_ADDR + 10) >> 8, (GTP_READ_COOR_ADDR + 10) & 0xff};
+
+ ret = gtp_i2c_read(ts->client, buf, 2 + 8 * (touch_num - 1));
+ memcpy(&point_data[12], &buf[2], 8 * (touch_num - 1));
+ }
+
+#if GTP_HAVE_TOUCH_KEY
+ key_value = point_data[3 + 8 * touch_num];
+
+ if(key_value || pre_key)
+ {
+ for (i = 0; i < GTP_MAX_KEY_NUM; i++)
+ {
+ #if GTP_DEBUG_ON
+ for (ret = 0; ret < 4; ++ret)
+ {
+ if (key_codes[ret] == touch_key_array[i])
+ {
+ GTP_DEBUG("Key: %s %s", key_names[ret], (key_value & (0x01 << i)) ? "Down" : "Up");
+ break;
+ }
+ }
+ #endif
+ input_report_key(ts->input_dev, touch_key_array[i], key_value & (0x01<<i));
+ }
+ touch_num = 0;
+ pre_touch = 0;
+ }
+#endif
+ pre_key = key_value;
+
+ GTP_DEBUG("pre_touch:%02x, finger:%02x.", pre_touch, finger);
+
+#if GTP_ICS_SLOT_REPORT
+
+#if GTP_WITH_PEN
+ if (pre_pen && (touch_num == 0))
+ {
+ GTP_DEBUG("Pen touch UP(Slot)!");
+ input_report_key(ts->input_dev, BTN_TOOL_PEN, 0);
+ input_mt_slot(ts->input_dev, 5);
+ input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, -1);
+ pre_pen = 0;
+ }
+#endif
+ if (pre_touch || touch_num)
+ {
+ s32 pos = 0;
+ u16 touch_index = 0;
+
+ coor_data = &point_data[3];
+
+ if(touch_num)
+ {
+ id = coor_data[pos] & 0x0F;
+
+ #if GTP_WITH_PEN
+ id = coor_data[pos];
+ if ((id == 128))
+ {
+ GTP_DEBUG("Pen touch DOWN(Slot)!");
+ input_x = coor_data[pos + 1] | (coor_data[pos + 2] << 8);
+ input_y = coor_data[pos + 3] | (coor_data[pos + 4] << 8);
+ input_w = coor_data[pos + 5] | (coor_data[pos + 6] << 8);
+
+ input_report_key(ts->input_dev, BTN_TOOL_PEN, 1);
+ input_mt_slot(ts->input_dev, 5);
+ input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, 5);
+ input_report_abs(ts->input_dev, ABS_MT_POSITION_X, input_x);
+ input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, input_y);
+ input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, input_w);
+ GTP_DEBUG("Pen/Stylus: (%d, %d)[%d]", input_x, input_y, input_w);
+ pre_pen = 1;
+ pre_touch = 0;
+ }
+ #endif
+
+ touch_index |= (0x01<<id);
+ }
+
+ GTP_DEBUG("id = %d,touch_index = 0x%x, pre_touch = 0x%x\n",id, touch_index,pre_touch);
+ for (i = 0; i < GTP_MAX_TOUCH; i++)
+ {
+ #if GTP_WITH_PEN
+ if (pre_pen == 1)
+ {
+ break;
+ }
+ #endif
+
+ if (touch_index & (0x01<<i))
+ {
+ input_x = coor_data[pos + 1] | (coor_data[pos + 2] << 8);
+ input_y = coor_data[pos + 3] | (coor_data[pos + 4] << 8);
+ input_w = coor_data[pos + 5] | (coor_data[pos + 6] << 8);
+
+ gtp_touch_down(ts, id, input_x, input_y, input_w);
+ pre_touch |= 0x01 << i;
+
+ pos += 8;
+ id = coor_data[pos] & 0x0F;
+ touch_index |= (0x01<<id);
+ }
+ else
+ {
+ gtp_touch_up(ts, i);
+ pre_touch &= ~(0x01 << i);
+ }
+ }
+ }
+#else
+ //input_report_key(ts->input_dev, BTN_TOUCH, (touch_num || key_value));
+ if (touch_num)
+ {
+ for (i = 0; i < touch_num; i++)
+ {
+ coor_data = &point_data[i * 8 + 3];
+
+ id = coor_data[0]; // & 0x0F;
+ input_x = coor_data[1] | (coor_data[2] << 8);
+ input_y = coor_data[3] | (coor_data[4] << 8);
+ input_w = coor_data[5] | (coor_data[6] << 8);
+
+ #if GTP_WITH_PEN
+ if (id == 128)
+ {
+ GTP_DEBUG("Pen touch DOWN!");
+ input_report_key(ts->input_dev, BTN_TOOL_PEN, 1);
+ pre_pen = 1;
+ id = 0;
+ }
+ #endif
+
+ gtp_touch_down(ts, id, input_x, input_y, input_w);
+ }
+ }
+ else if (pre_touch)
+ {
+ #if GTP_WITH_PEN
+ if (pre_pen == 1)
+ {
+ GTP_DEBUG("Pen touch UP!");
+ input_report_key(ts->input_dev, BTN_TOOL_PEN, 0);
+ pre_pen = 0;
+ }
+ #endif
+
+ GTP_DEBUG("Touch Release!");
+ gtp_touch_up(ts, 0);
+ }
+
+ pre_touch = touch_num;
+#endif
+
+ input_sync(ts->input_dev);
+
+exit_work_func:
+ if(!ts->gtp_rawdiff_mode)
+ {
+ ret = gtp_i2c_write(ts->client, end_cmd, 3);
+ if (ret < 0)
+ {
+ GTP_INFO("I2C write end_cmd error!");
+ }
+ }
+ if (ts->use_irq)
+ {
+ gtp_irq_enable(ts);
+ }
+}
+
+/*******************************************************
+Function:
+ Timer interrupt service routine for polling mode.
+Input:
+ timer: timer struct pointer
+Output:
+ Timer work mode.
+ HRTIMER_NORESTART: no restart mode
+*********************************************************/
+static enum hrtimer_restart goodix_ts_timer_handler(struct hrtimer *timer)
+{
+ struct goodix_ts_data *ts = container_of(timer, struct goodix_ts_data, timer);
+
+ GTP_DEBUG_FUNC();
+
+ queue_work(goodix_wq, &ts->work);
+ hrtimer_start(&ts->timer, ktime_set(0, (GTP_POLL_TIME+6)*1000000), HRTIMER_MODE_REL);
+ return HRTIMER_NORESTART;
+}
+
+/*******************************************************
+Function:
+ External interrupt service routine for interrupt mode.
+Input:
+ irq: interrupt number.
+ dev_id: private data pointer
+Output:
+ Handle Result.
+ IRQ_HANDLED: interrupt handled successfully
+*********************************************************/
+static irqreturn_t goodix_ts_irq_handler(int irq, void *dev_id)
+{
+ struct goodix_ts_data *ts = dev_id;
+
+ GTP_DEBUG_FUNC();
+
+ if (gpio_irqstatus(ts->irq_gpio))
+ {
+ wmt_gpio_ack_irq(ts->irq_gpio);
+ if (is_gpio_irqenable(ts->irq_gpio) && l_suspend == 0)
+ {
+ gtp_irq_disable(ts);
+ queue_work(goodix_wq, &ts->work);
+ }
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_NONE;
+}
+/*******************************************************
+Function:
+ Synchronization.
+Input:
+ ms: synchronization time in millisecond.
+Output:
+ None.
+*******************************************************/
+void gtp_int_sync(s32 ms)
+{
+ GTP_GPIO_OUTPUT(l_ts->irq_gpio, 0);
+ msleep(ms);
+ GTP_GPIO_AS_INPUT(l_ts->irq_gpio);
+ //GTP_GPIO_AS_INT(ts->irq_gpio);
+}
+
+/*******************************************************
+Function:
+ Reset chip.
+Input:
+ ms: reset time in millisecond
+Output:
+ None.
+*******************************************************/
+void gtp_reset_guitar(struct i2c_client *client, s32 ms)
+{
+ GTP_DEBUG_FUNC();
+
+ GTP_GPIO_OUTPUT(l_ts->rst_gpio, 0); // begin select I2C slave addr
+ msleep(ms); // T2: > 10ms
+ // HIGH: 0x28/0x29, LOW: 0xBA/0xBB
+ GTP_GPIO_OUTPUT(l_ts->irq_gpio, client->addr == 0x14);
+
+ msleep(2); // T3: > 100us
+ GTP_GPIO_OUTPUT(l_ts->rst_gpio, 1);
+
+ msleep(6); // T4: > 5ms
+
+ GTP_GPIO_AS_INPUT(l_ts->rst_gpio); // end select I2C slave addr
+
+ gtp_int_sync(50);
+
+#if GTP_ESD_PROTECT
+ gtp_init_ext_watchdog(client);
+#endif
+}
+
+#if GTP_SLIDE_WAKEUP
+/*******************************************************
+Function:
+ Enter doze mode for sliding wakeup.
+Input:
+ ts: goodix tp private data
+Output:
+ 1: succeed, otherwise failed
+*******************************************************/
+static s8 gtp_enter_doze(struct goodix_ts_data *ts)
+{
+ s8 ret = -1;
+ s8 retry = 0;
+ u8 i2c_control_buf[3] = {(u8)(GTP_REG_SLEEP >> 8), (u8)GTP_REG_SLEEP, 8};
+
+ GTP_DEBUG_FUNC();
+
+#if GTP_DBL_CLK_WAKEUP
+ i2c_control_buf[2] = 0x09;
+#endif
+
+ gtp_irq_disable(ts);
+
+ GTP_DEBUG("entering doze mode...");
+ while(retry++ < 5)
+ {
+ i2c_control_buf[0] = 0x80;
+ i2c_control_buf[1] = 0x46;
+ ret = gtp_i2c_write(ts->client, i2c_control_buf, 3);
+ if (ret < 0)
+ {
+ GTP_DEBUG("failed to set doze flag into 0x8046, %d", retry);
+ continue;
+ }
+ i2c_control_buf[0] = 0x80;
+ i2c_control_buf[1] = 0x40;
+ ret = gtp_i2c_write(ts->client, i2c_control_buf, 3);
+ if (ret > 0)
+ {
+ doze_status = DOZE_ENABLED;
+ GTP_INFO("GTP has been working in doze mode!");
+ gtp_irq_enable(ts);
+ return ret;
+ }
+ msleep(10);
+ }
+ GTP_ERROR("GTP send doze cmd failed.");
+ gtp_irq_enable(ts);
+ return ret;
+}
+#else
+/*******************************************************
+Function:
+ Enter sleep mode.
+Input:
+ ts: private data.
+Output:
+ Executive outcomes.
+ 1: succeed, otherwise failed.
+*******************************************************/
+#if 0
+static s8 gtp_enter_sleep(struct goodix_ts_data * ts)
+{
+ s8 ret = -1;
+ s8 retry = 0;
+ u8 i2c_control_buf[3] = {(u8)(GTP_REG_SLEEP >> 8), (u8)GTP_REG_SLEEP, 5};
+
+ GTP_DEBUG_FUNC();
+
+ GTP_GPIO_OUTPUT(ts->irq_gpio, 0);
+ msleep(5);
+
+ while(retry++ < 5)
+ {
+ ret = gtp_i2c_write(ts->client, i2c_control_buf, 3);
+ if (ret > 0)
+ {
+ GTP_INFO("GTP enter sleep!");
+
+ return ret;
+ }
+ msleep(10);
+ }
+ GTP_ERROR("GTP send sleep cmd failed.");
+ return ret;
+}
+#endif
+#endif
+/*******************************************************
+Function:
+ Wakeup from sleep.
+Input:
+ ts: private data.
+Output:
+ Executive outcomes.
+ >0: succeed, otherwise: failed.
+*******************************************************/
+#if 0
+static s8 gtp_wakeup_sleep(struct goodix_ts_data * ts)
+{
+ u8 retry = 0;
+ s8 ret = -1;
+
+ GTP_DEBUG_FUNC();
+
+#if GTP_POWER_CTRL_SLEEP
+ while(retry++ < 5)
+ {
+ gtp_reset_guitar(ts->client, 20);
+
+ ret = gtp_send_cfg(ts);
+ if (ret < 0)
+ {
+ GTP_INFO("Wakeup sleep send config failed!");
+ continue;
+ }
+ GTP_INFO("GTP wakeup sleep");
+ return 1;
+ }
+#else
+ while(retry++ < 10)
+ {
+ #if GTP_SLIDE_WAKEUP
+ if (DOZE_WAKEUP != doze_status) // wakeup not by slide
+ {
+ gtp_reset_guitar(ts->client, 10);
+ }
+ else // wakeup by slide
+ {
+ doze_status = DOZE_DISABLED;
+ }
+ #else
+ if (chip_gt9xxs == 1)
+ {
+ gtp_reset_guitar(ts->client, 10);
+ }
+ else
+ {
+ GTP_GPIO_OUTPUT(ts->irq_gpio, 1);
+ msleep(5);
+ }
+ #endif
+ ret = gtp_i2c_test(ts->client);
+ if (ret > 0)
+ {
+ GTP_INFO("GTP wakeup sleep.");
+
+ #if (!GTP_SLIDE_WAKEUP)
+ if (chip_gt9xxs == 0)
+ {
+ gtp_int_sync(25);
+ msleep(20);
+ #if GTP_ESD_PROTECT
+ gtp_init_ext_watchdog(ts->client);
+ #endif
+ }
+ #endif
+ return ret;
+ }
+ gtp_reset_guitar(ts->client, 20);
+ }
+#endif
+
+ GTP_ERROR("GTP wakeup sleep failed.");
+ return ret;
+}
+#endif
+
+static int wmt_ts_load_firmware(char* firmwarename, unsigned char* firmdata)
+{
+ struct file *fp;
+ mm_segment_t fs;
+ loff_t pos;
+ long fsize;
+ int alloclen;
+ char filepath[64];
+
+ sprintf(filepath, "/system/etc/firmware/%s", firmwarename);
+ printk("ts firmware file:%s\n",filepath);
+
+ fp = filp_open(filepath, O_RDONLY, 0);
+ if (IS_ERR(fp)) {
+ printk("create file error\n");
+ return -1;
+ }
+ fs = get_fs();
+ set_fs(KERNEL_DS);
+ alloclen = fp->f_op->llseek(fp, 0, SEEK_END);
+ printk("firmware file lengh:0x%x,\n", alloclen);
+ alloclen += alloclen%4;
+
+ fp->f_op->llseek(fp,0,0);
+ pos = 0;
+ fsize = vfs_read(fp, firmdata, alloclen, &pos);
+ printk("filesize:0x%ld,alloclen:0x%d\n",fsize,alloclen);
+ if (fsize <= 0)
+ {
+ printk("alloc size is too small.\n");
+ goto error_vfs_read;
+ }
+ filp_close(fp, NULL);
+ set_fs(fs);
+ printk("success to read firmware file!\n");;
+
+ return 0;
+error_vfs_read:
+ filp_close(fp, NULL);
+ set_fs(fs);
+ return -1;
+}
+
+static int read_cfg(char* cfgname, u8* cfg, int len_max)
+{
+ char endflag[]="/* End flag */";
+ unsigned char* p;
+ int val;
+ int i = 0;
+ unsigned char *rawdata;
+
+ rawdata = kzalloc(1024, GFP_KERNEL);
+ if (rawdata == NULL)
+ {
+ printk("Error when alloc memory for firmware file!\n");
+ return -ENOMEM;
+ }
+
+ if (wmt_ts_load_firmware(cfgname, rawdata))
+ return -1;
+
+ p = rawdata;
+ while (*p!='{') p++;
+ p++;
+
+ while (strncmp(p,endflag,strlen(endflag)))
+ {
+ if (!strncmp(p,"0x",strlen("0x")))
+ {
+ sscanf(p,"%x,",&val);
+ *(cfg++) = val&0x00FF;
+ i++;
+ }
+ if (i == len_max)
+ break;
+ p++;
+
+ };
+
+ kfree(rawdata);
+
+ return i;
+}
+
+/*******************************************************
+Function:
+ Initialize gtp.
+Input:
+ ts: goodix private data
+Output:
+ Executive outcomes.
+ 0: succeed, otherwise: failed
+*******************************************************/
+static s32 gtp_init_panel(struct goodix_ts_data *ts)
+{
+ s32 ret = -1;
+
+#if GTP_DRIVER_SEND_CFG
+ s32 i;
+ u8 check_sum = 0;
+ u8 opr_buf[16];
+ u8 sensor_id = 0;
+
+ u8 send_cfg_buf[256] = {0};
+ char cfgname[32] = {0};
+
+ ret = gtp_i2c_read_dbl_check(ts->client, 0x41E4, opr_buf, 1);
+ if (SUCCESS == ret)
+ {
+ if (opr_buf[0] != 0xBE)
+ {
+ ts->fw_error = 1;
+ GTP_ERROR("Firmware error, no config sent!");
+ return -1;
+ }
+ }
+
+ ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_SENSOR_ID, &sensor_id, 1);
+ if (SUCCESS == ret)
+ {
+ if (sensor_id >= 0x06)
+ {
+ //GTP_ERROR("Invalid sensor_id(0x%02X), No Config Sent!", sensor_id);
+ //return -1;
+ GTP_ERROR("Invalid sensor_id(0x%02X), Force set id to 0!", sensor_id);
+ sensor_id = 0;
+ }
+ }
+ else
+ {
+ GTP_ERROR("Failed to get sensor_id, No config sent!");
+ return -1;
+ }
+ GTP_DEBUG("Sensor_ID: %d", sensor_id);
+
+ sprintf(cfgname, "%s_id%d.cfg", ts->fw_name, sensor_id);
+ GTP_INFO("config file name: %s.", cfgname);
+ ret = read_cfg(cfgname, send_cfg_buf, 256);
+ if (ret < 0)
+ return -1;
+ ts->gtp_cfg_len = ret;
+
+ if (ts->gtp_cfg_len < GTP_CONFIG_MIN_LENGTH)
+ {
+ GTP_ERROR("INVALID CONFIG GROUP! NO Config Sent! You need to check you header file CFG_GROUP section!");
+ return -1;
+ }
+
+ ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_CONFIG_DATA, &opr_buf[0], 1);
+
+ if (ret == SUCCESS)
+ {
+ GTP_DEBUG("Config Version: %d, 0x%02X; IC Config Version: %d, 0x%02X",
+ send_cfg_buf[0], send_cfg_buf[0], opr_buf[0], opr_buf[0]);
+
+ if (opr_buf[0] < 90)
+ {
+ grp_cfg_version = send_cfg_buf[0]; // backup group config version
+ send_cfg_buf[0] = 0x00;
+ ts->fixed_cfg = 0;
+ }
+ else // treated as fixed config, not send config
+ {
+ GTP_INFO("Ic fixed config with config version(%d, 0x%02X)", opr_buf[0], opr_buf[0]);
+ ts->fixed_cfg = 1;
+ }
+ }
+ else
+ {
+ GTP_ERROR("Failed to get ic config version!No config sent!");
+ return -1;
+ }
+
+ memset(&config[GTP_ADDR_LENGTH], 0, GTP_CONFIG_MAX_LENGTH);
+ memcpy(&config[GTP_ADDR_LENGTH], send_cfg_buf, ts->gtp_cfg_len);
+
+#if GTP_CUSTOM_CFG
+ config[RESOLUTION_LOC] = (u8)GTP_MAX_WIDTH;
+ config[RESOLUTION_LOC + 1] = (u8)(GTP_MAX_WIDTH>>8);
+ config[RESOLUTION_LOC + 2] = (u8)GTP_MAX_HEIGHT;
+ config[RESOLUTION_LOC + 3] = (u8)(GTP_MAX_HEIGHT>>8);
+
+ if (GTP_INT_TRIGGER == 0) //RISING
+ {
+ config[TRIGGER_LOC] &= 0xfe;
+ }
+ else if (GTP_INT_TRIGGER == 1) //FALLING
+ {
+ config[TRIGGER_LOC] |= 0x01;
+ }
+#endif // GTP_CUSTOM_CFG
+
+ check_sum = 0;
+ for (i = GTP_ADDR_LENGTH; i < ts->gtp_cfg_len; i++)
+ {
+ check_sum += config[i];
+ }
+ config[ts->gtp_cfg_len] = (~check_sum) + 1;
+
+#else // DRIVER NOT SEND CONFIG
+ ts->gtp_cfg_len = GTP_CONFIG_MAX_LENGTH;
+ ret = gtp_i2c_read(ts->client, config, ts->gtp_cfg_len + GTP_ADDR_LENGTH);
+ if (ret < 0)
+ {
+ GTP_ERROR("Read Config Failed, Using Default Resolution & INT Trigger!");
+ ts->abs_x_max = GTP_MAX_WIDTH;
+ ts->abs_y_max = GTP_MAX_HEIGHT;
+ ts->int_trigger_type = GTP_INT_TRIGGER;
+ }
+#endif // GTP_DRIVER_SEND_CFG
+
+ GTP_DEBUG_FUNC();
+ if ((ts->abs_x_max == 0) && (ts->abs_y_max == 0))
+ {
+ ts->abs_x_max = (config[RESOLUTION_LOC + 1] << 8) + config[RESOLUTION_LOC];
+ ts->abs_y_max = (config[RESOLUTION_LOC + 3] << 8) + config[RESOLUTION_LOC + 2];
+ ts->int_trigger_type = (config[TRIGGER_LOC]) & 0x03;
+ }
+
+ ret = gtp_send_cfg(ts);
+ if (ret < 0)
+ {
+ GTP_ERROR("Send config error.");
+ }
+ //GTP_DEBUG("X_MAX = %d, Y_MAX = %d, TRIGGER = 0x%02x",
+ //ts->abs_x_max,ts->abs_y_max,ts->int_trigger_type);
+ GTP_INFO("X_MAX = %d, Y_MAX = %d, TRIGGER = 0x%02x(%s).",
+ ts->abs_x_max,ts->abs_y_max,ts->int_trigger_type, ts->int_trigger_type?"Falling":"Rising");
+
+ msleep(10);
+ return 0;
+}
+
+/*******************************************************
+Function:
+ Read chip version.
+Input:
+ client: i2c device
+ version: buffer to keep ic firmware version
+Output:
+ read operation return.
+ 2: succeed, otherwise: failed
+*******************************************************/
+s32 gtp_read_version(struct i2c_client *client, u16* version)
+{
+ s32 ret = -1;
+ u8 buf[8] = {GTP_REG_VERSION >> 8, GTP_REG_VERSION & 0xff};
+
+ GTP_DEBUG_FUNC();
+
+ ret = gtp_i2c_read(client, buf, sizeof(buf));
+ if (ret < 0)
+ {
+ GTP_ERROR("GTP read version failed");
+ return ret;
+ }
+
+ if (version)
+ {
+ *version = (buf[7] << 8) | buf[6];
+ }
+
+ if (buf[5] == 0x00)
+ {
+ GTP_INFO("IC Version: %c%c%c_%02x%02x", buf[2], buf[3], buf[4], buf[7], buf[6]);
+ }
+ else
+ {
+ if (buf[5] == 'S' || buf[5] == 's')
+ {
+ chip_gt9xxs = 1;
+ }
+ GTP_INFO("IC Version: %c%c%c%c_%02x%02x", buf[2], buf[3], buf[4], buf[5], buf[7], buf[6]);
+ }
+ return ret;
+}
+
+/*******************************************************
+Function:
+ I2c test Function.
+Input:
+ client:i2c client.
+Output:
+ Executive outcomes.
+ 2: succeed, otherwise failed.
+*******************************************************/
+static s8 gtp_i2c_test(struct i2c_client *client)
+{
+ u8 test[3] = {GTP_REG_CONFIG_DATA >> 8, GTP_REG_CONFIG_DATA & 0xff};
+ u8 retry = 0;
+ s8 ret = -1;
+
+ GTP_DEBUG_FUNC();
+
+ while(retry++ < 5)
+ {
+ ret = gtp_i2c_read(client, test, 3);
+ if (ret > 0)
+ {
+ return ret;
+ }
+ GTP_ERROR("GTP i2c test failed time %d.",retry);
+ msleep(10);
+ }
+ return ret;
+}
+
+/*******************************************************
+Function:
+ Request gpio(INT & RST) ports.
+Input:
+ ts: private data.
+Output:
+ Executive outcomes.
+ >= 0: succeed, < 0: failed
+*******************************************************/
+static s8 gtp_request_io_port(struct goodix_ts_data *ts)
+{
+ s32 ret = 0;
+
+ ret = GTP_GPIO_REQUEST(ts->irq_gpio, "GTP_INT_IRQ");
+ if (ret < 0)
+ {
+ GTP_ERROR("Failed to request GPIO:%d, ERRNO:%d", (s32)ts->irq_gpio, ret);
+ ret = -ENODEV;
+ }
+ else
+ {
+ GTP_GPIO_AS_INPUT(ts->irq_gpio);
+ //GTP_GPIO_AS_INT(ts->irq_gpio);
+ //ts->client->irq = IRQ_GPIO;
+ }
+
+ ret = GTP_GPIO_REQUEST(ts->rst_gpio, "GTP_RST_PORT");
+ if (ret < 0)
+ {
+ GTP_ERROR("Failed to request GPIO:%d, ERRNO:%d",(s32)ts->rst_gpio,ret);
+ ret = -ENODEV;
+ }
+
+ GTP_GPIO_AS_INPUT(ts->rst_gpio);
+ gtp_reset_guitar(ts->client, 20);
+
+
+ if(ret < 0)
+ {
+ GTP_GPIO_FREE(ts->rst_gpio);
+ GTP_GPIO_FREE(ts->irq_gpio);
+ }
+
+ return ret;
+}
+
+/*******************************************************
+Function:
+ Request interrupt.
+Input:
+ ts: private data.
+Output:
+ Executive outcomes.
+ 0: succeed, -1: failed.
+*******************************************************/
+static s8 gtp_request_irq(struct goodix_ts_data *ts)
+{
+ s32 ret = -1;
+ //const u8 irq_table[] = GTP_IRQ_TAB;
+
+ GTP_DEBUG("INT trigger type:%x", ts->int_trigger_type);
+
+ ret = request_irq(ts->client->irq,
+ goodix_ts_irq_handler,
+ IRQF_SHARED,
+ ts->client->name,
+ ts);
+ if (ret)
+ {
+ GTP_ERROR("Request IRQ failed!ERRNO:%d.", ret);
+ GTP_GPIO_AS_INPUT(ts->irq_gpio);
+ GTP_GPIO_FREE(ts->irq_gpio);
+
+ hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ ts->timer.function = goodix_ts_timer_handler;
+ hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
+ return -1;
+ }
+ else
+ {
+ gtp_irq_disable(ts);
+ ts->use_irq = 1;
+ return 0;
+ }
+}
+
+/*******************************************************
+Function:
+ Request input device Function.
+Input:
+ ts:private data.
+Output:
+ Executive outcomes.
+ 0: succeed, otherwise: failed.
+*******************************************************/
+static s8 gtp_request_input_dev(struct goodix_ts_data *ts)
+{
+ s8 ret = -1;
+ s8 phys[32];
+#if GTP_HAVE_TOUCH_KEY
+ u8 index = 0;
+#endif
+
+ GTP_DEBUG_FUNC();
+
+ ts->input_dev = input_allocate_device();
+ if (ts->input_dev == NULL)
+ {
+ GTP_ERROR("Failed to allocate input device.");
+ return -ENOMEM;
+ }
+
+ ts->input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) ;
+ set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit);
+#if GTP_ICS_SLOT_REPORT
+ __set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit);
+ input_mt_init_slots(ts->input_dev, 10); // in case of "out of memory"
+#else
+ //ts->input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+#endif
+
+#if GTP_HAVE_TOUCH_KEY
+ for (index = 0; index < GTP_MAX_KEY_NUM; index++)
+ {
+ input_set_capability(ts->input_dev, EV_KEY, touch_key_array[index]);
+ }
+#endif
+
+#if GTP_SLIDE_WAKEUP
+ input_set_capability(ts->input_dev, EV_KEY, KEY_POWER);
+#endif
+
+#if GTP_WITH_PEN
+ // pen support
+ __set_bit(BTN_TOOL_PEN, ts->input_dev->keybit);
+ __set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit);
+ __set_bit(INPUT_PROP_POINTER, ts->input_dev->propbit);
+#endif
+
+#if GTP_CHANGE_X2Y
+ GTP_SWAP(ts->abs_x_max, ts->abs_y_max);
+#endif
+
+ if (ts->swap) {
+ s32 temp;
+ temp = ts->abs_x_max;
+ ts->abs_x_max = ts->abs_y_max;
+ ts->abs_y_max = temp;
+ }
+
+ if (ts->lcd_exchg) {
+ input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, 0, ts->abs_y_max, 0, 0);
+ input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, 0, ts->abs_x_max, 0, 0);
+ } else {
+ input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, 0, ts->abs_x_max, 0, 0);
+ input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, 0, ts->abs_y_max, 0, 0);
+ }
+ //input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0);
+ //input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
+ input_set_abs_params(ts->input_dev, ABS_MT_TRACKING_ID, 0, 255, 0, 0);
+
+ sprintf(phys, "input/ts");
+ ts->input_dev->name = goodix_ts_name;
+ ts->input_dev->phys = phys;
+ ts->input_dev->id.bustype = BUS_I2C;
+ ts->input_dev->id.vendor = 0xDEAD;
+ ts->input_dev->id.product = 0xBEEF;
+ ts->input_dev->id.version = 10427;
+
+ ret = input_register_device(ts->input_dev);
+ if (ret)
+ {
+ GTP_ERROR("Register %s input device failed", ts->input_dev->name);
+ return -ENODEV;
+ }
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+ ts->early_suspend.suspend = goodix_ts_early_suspend;
+ ts->early_suspend.resume = goodix_ts_late_resume;
+ register_early_suspend(&ts->early_suspend);
+#endif
+
+ return 0;
+}
+
+
+static int wmt_check_touch_env(struct goodix_ts_data *ts)
+{
+ int ret = 0;
+ int len = 127;
+ char retval[128] = {0},*p=NULL,*s=NULL;
+ int Enable=0;
+ int x,y;
+
+ // Get u-boot parameter
+ ret = wmt_getsyspara("wmt.io.touch", retval, &len);
+ if(ret){
+ GTP_ERROR("Read wmt.io.touch Failed.\n");
+ return -EIO;
+ }
+
+ //check touch enable
+ p = retval;
+ sscanf(p,"%d:", &Enable);
+ if(Enable == 0){
+ GTP_ERROR("Touch Screen Is Disabled.\n");
+ return -ENODEV;
+ }
+
+ //check touch IC name
+ p = strchr(p,':');p++;
+ if (strncmp(p, "gt9xx", strlen("gt9xx"))) {
+ GTP_ERROR("Can't find gt9xx!\n");
+ return -ENODEV;
+ }
+
+ //get firmware file name
+ s = strchr(p,':');
+ //p = p + strlen(fw_name) + 1;
+ if (s > (p + strlen("gt9xx") + 1)) {
+ memset(ts->fw_name,0x00,sizeof(ts->fw_name));
+ strncpy(ts->fw_name, p, (s-p));
+ GTP_DEBUG("ts_fwname=%s\n", ts->fw_name);
+ } else
+ GTP_DEBUG("needn't firmware\n");
+
+ //get other needed args
+ p = s + 1;
+ ret = sscanf(p,"%d:%d:%d:%d:%d:%d:%d:%d:%x",
+ &ts->irq_gpio,&x,&y,&ts->rst_gpio,
+ &ts->swap,&ts->xdir,&ts->ydir,
+ &ts->max_touch_num,
+ &ts->i2c_addr);
+ if (ret != 9)
+ {
+ GTP_ERROR("Wrong format ts u-boot param(%d)!\n",ret);
+ return -ENODEV;
+ }
+
+ ret = wmt_getsyspara("wmt.display.fb0", retval, &len);
+ if (!ret) {
+ int tmp[6];
+ p = retval;
+ sscanf(p, "%d:[%d:%d:%d:%d:%d", &tmp[0], &tmp[1], &tmp[2], &tmp[3], &tmp[4], &tmp[5]);
+ if (tmp[4] > tmp[5])
+ ts->lcd_exchg = 1;
+ }
+
+ return 0;
+}
+
+/*******************************************************
+Function:
+ I2c probe.
+Input:
+ client: i2c device struct.
+ id: device id.
+Output:
+ Executive outcomes.
+ 0: succeed.
+*******************************************************/
+static int goodix_ts_probe(struct platform_device *pdev)
+{
+ s32 ret = -1;
+ struct goodix_ts_data *ts;
+ u16 version_info;
+
+ GTP_DEBUG_FUNC();
+
+ //do NOT remove these logs
+ GTP_INFO("GTP Driver Version: %s", GTP_DRIVER_VERSION);
+ GTP_INFO("GTP Driver Built@%s, %s", __TIME__, __DATE__);
+ GTP_INFO("GTP I2C Address: 0x%02x", i2c_connect_client->addr);
+
+ //i2c_connect_client = client;
+
+ if (!i2c_check_functionality(i2c_connect_client->adapter, I2C_FUNC_I2C))
+ {
+ GTP_ERROR("I2C check functionality failed.");
+ return -ENODEV;
+ }
+ ts = kzalloc(sizeof(*ts), GFP_KERNEL);
+ if (ts == NULL)
+ {
+ GTP_ERROR("Alloc GFP_KERNEL memory failed.");
+ return -ENOMEM;
+ }
+ memset(ts, 0, sizeof(*ts));
+ l_ts = ts;
+
+ ret = wmt_check_touch_env(ts);
+ if (ret < 0)
+ {
+ GTP_ERROR("GTP get touch env failed.");
+ kfree(ts);
+ return ret;
+ }
+
+ i2c_connect_client->addr = ts->i2c_addr;
+ INIT_WORK(&ts->work, goodix_ts_work_func);
+ ts->client = i2c_connect_client;
+ //spin_lock_init(&ts->irq_lock); // 2.6.39 later
+ // ts->irq_lock = SPIN_LOCK_UNLOCKED; // 2.6.39 & before
+ platform_set_drvdata(pdev, ts);
+
+ ts->gtp_rawdiff_mode = 0;
+
+ ret = gtp_request_io_port(ts);
+ if (ret < 0)
+ {
+ GTP_ERROR("GTP request IO port failed.");
+ kfree(ts);
+ return ret;
+ }
+
+ ret = gtp_i2c_test(ts->client);
+ if (ret < 0)
+ {
+ GTP_ERROR("I2C communication ERROR!");
+ }
+
+#if GTP_AUTO_UPDATE
+ ret = gup_init_update_proc(ts);
+ if (ret < 0)
+ {
+ GTP_ERROR("Create update thread error.");
+ }
+#endif
+
+ ret = gtp_init_panel(ts);
+ if (ret < 0)
+ {
+ GTP_ERROR("GTP init panel failed.");
+ ts->abs_x_max = GTP_MAX_WIDTH;
+ ts->abs_y_max = GTP_MAX_HEIGHT;
+ ts->int_trigger_type = GTP_INT_TRIGGER;
+ }
+
+ ret = gtp_request_input_dev(ts);
+ if (ret < 0)
+ {
+ GTP_ERROR("GTP request input dev failed");
+ }
+ GTP_GPIO_AS_INT(ts->irq_gpio,IRQ_TYPE_EDGE_FALLING);
+ ts->client->irq = IRQ_GPIO;
+ ret = gtp_request_irq(ts);
+ if (ret < 0)
+ {
+ GTP_INFO("GTP works in polling mode.");
+ }
+ else
+ {
+ GTP_INFO("GTP works in interrupt mode.");
+ }
+
+ ret = gtp_read_version(ts->client, &version_info);
+ if (ret < 0)
+ {
+ GTP_ERROR("Read version failed.");
+ }
+ if (ts->use_irq)
+ {
+ gtp_irq_enable(ts);
+ }
+
+#if GTP_CREATE_WR_NODE
+ init_wr_node(ts->client);
+#endif
+
+#if GTP_ESD_PROTECT
+ gtp_esd_switch(ts, SWITCH_ON);
+#endif
+ return 0;
+}
+
+
+/*******************************************************
+Function:
+ Goodix touchscreen driver release function.
+Input:
+ client: i2c device struct.
+Output:
+ Executive outcomes. 0---succeed.
+*******************************************************/
+static int goodix_ts_remove(struct platform_device *pdev)
+{
+ struct goodix_ts_data *ts = platform_get_drvdata(pdev);
+
+ GTP_DEBUG_FUNC();
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&ts->early_suspend);
+#endif
+
+#if GTP_CREATE_WR_NODE
+ uninit_wr_node();
+#endif
+
+#if GTP_ESD_PROTECT
+ destroy_workqueue(gtp_esd_check_workqueue);
+#endif
+
+ if (ts)
+ {
+ if (ts->use_irq)
+ {
+ GTP_GPIO_AS_INPUT(ts->irq_gpio);
+ GTP_GPIO_FREE(ts->irq_gpio);
+ free_irq(ts->client->irq, ts);
+ }
+ else
+ {
+ hrtimer_cancel(&ts->timer);
+ }
+ }
+
+ GTP_GPIO_FREE(ts->rst_gpio);
+ GTP_INFO("GTP driver removing...");
+ input_unregister_device(ts->input_dev);
+ kfree(ts);
+
+ return 0;
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+/*******************************************************
+Function:
+ Early suspend function.
+Input:
+ h: early_suspend struct.
+Output:
+ None.
+*******************************************************/
+static void goodix_ts_early_suspend(struct early_suspend *h)
+{
+ struct goodix_ts_data *ts;
+ s8 ret = -1;
+ ts = container_of(h, struct goodix_ts_data, early_suspend);
+
+ GTP_DEBUG_FUNC();
+
+#if GTP_ESD_PROTECT
+ ts->gtp_is_suspend = 1;
+ gtp_esd_switch(ts, SWITCH_OFF);
+#endif
+
+#if GTP_SLIDE_WAKEUP
+ ret = gtp_enter_doze(ts);
+#else
+ if (ts->use_irq)
+ {
+ gtp_irq_disable(ts);
+ }
+ else
+ {
+ hrtimer_cancel(&ts->timer);
+ }
+ ret = gtp_enter_sleep(ts);
+#endif
+ if (ret < 0)
+ {
+ GTP_ERROR("GTP early suspend failed.");
+ }
+ // to avoid waking up while not sleeping
+ // delay 48 + 10ms to ensure reliability
+ msleep(58);
+}
+
+/*******************************************************
+Function:
+ Late resume function.
+Input:
+ h: early_suspend struct.
+Output:
+ None.
+*******************************************************/
+static void goodix_ts_late_resume(struct early_suspend *h)
+{
+ struct goodix_ts_data *ts;
+ s8 ret = -1;
+ ts = container_of(h, struct goodix_ts_data, early_suspend);
+
+ GTP_DEBUG_FUNC();
+
+ ret = gtp_wakeup_sleep(ts);
+
+#if GTP_SLIDE_WAKEUP
+ doze_status = DOZE_DISABLED;
+#endif
+
+ if (ret < 0)
+ {
+ GTP_ERROR("GTP later resume failed.");
+ }
+
+ if (ts->use_irq)
+ {
+ gtp_irq_enable(ts);
+ }
+ else
+ {
+ hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
+ }
+
+#if GTP_ESD_PROTECT
+ ts->gtp_is_suspend = 0;
+ gtp_esd_switch(ts, SWITCH_ON);
+#endif
+}
+#endif
+
+#if 1
+/*******************************************************
+Function:
+ Suspend function.
+Input:
+ client: i2c_client struct.
+ mesg: pm_message_t struct.
+Output:
+ None.
+*******************************************************/
+static int goodix_ts_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct goodix_ts_data *ts;
+ ts = dev_get_drvdata(&pdev->dev);
+
+ GTP_DEBUG_FUNC();
+
+#if GTP_ESD_PROTECT
+ ts->gtp_is_suspend = 1;
+ gtp_esd_switch(ts, SWITCH_OFF);
+#endif
+
+#if GTP_SLIDE_WAKEUP
+ ret = gtp_enter_doze(ts);
+#else
+ if (ts->use_irq)
+ {
+ gtp_irq_disable(ts);
+ }
+ else
+ {
+ hrtimer_cancel(&ts->timer);
+ }
+#endif
+ // to avoid waking up while not sleeping
+ // delay 48 + 10ms to ensure reliability
+ l_suspend = 1;
+ return 0;
+}
+
+
+/*******************************************************
+Function:
+ Late resume function.
+Input:
+ client: i2c_client struct.
+Output:
+ None.
+*******************************************************/
+static int goodix_ts_resume(struct platform_device *pdev)
+{
+ struct goodix_ts_data *ts;
+ s8 ret = -1;
+ ts = dev_get_drvdata(&pdev->dev);
+
+ GTP_DEBUG_FUNC();
+
+ GTP_GPIO_AS_INPUT(ts->irq_gpio);
+ GTP_GPIO_AS_INPUT(ts->rst_gpio);
+ gtp_reset_guitar(ts->client, 20);
+
+ ret = gtp_i2c_test(ts->client);
+ if (ret < 0)
+ {
+ GTP_ERROR("I2C communication ERROR!");
+ }
+
+#if GTP_SLIDE_WAKEUP
+ doze_status = DOZE_DISABLED;
+#endif
+
+ if (ts->use_irq)
+ {
+ GTP_GPIO_AS_INT(ts->irq_gpio,IRQ_TYPE_EDGE_FALLING);
+ gtp_irq_enable(ts);
+ }
+ else
+ {
+ hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
+ }
+
+#if GTP_ESD_PROTECT
+ ts->gtp_is_suspend = 0;
+ gtp_esd_switch(ts, SWITCH_ON);
+#endif
+ l_suspend = 0;
+ return 0;
+}
+#endif
+
+#if GTP_ESD_PROTECT
+/*******************************************************
+Function:
+ switch on & off esd delayed work
+Input:
+ client: i2c device
+ on: SWITCH_ON / SWITCH_OFF
+Output:
+ void
+*********************************************************/
+void gtp_esd_switch(struct goodix_ts_data * ts, s32 on)
+{
+
+ if (SWITCH_ON == on) // switch on esd
+ {
+ if (!ts->esd_running)
+ {
+ ts->esd_running = 1;
+ GTP_INFO("Esd started");
+ queue_delayed_work(gtp_esd_check_workqueue, &gtp_esd_check_work, GTP_ESD_CHECK_CIRCLE);
+ }
+ }
+ else // switch off esd
+ {
+ if (ts->esd_running)
+ {
+ ts->esd_running = 0;
+ GTP_INFO("Esd cancelled");
+ cancel_delayed_work_sync(&gtp_esd_check_work);
+ }
+ }
+}
+
+/*******************************************************
+Function:
+ Initialize external watchdog for esd protect
+Input:
+ client: i2c device.
+Output:
+ result of i2c write operation.
+ 1: succeed, otherwise: failed
+*********************************************************/
+static s32 gtp_init_ext_watchdog(struct i2c_client *client)
+{
+ u8 opr_buffer[4] = {0x80, 0x40, 0xAA, 0xAA};
+
+ struct i2c_msg msg; // in case of recursively reset by calling gtp_i2c_write
+ s32 ret = -1;
+ s32 retries = 0;
+
+ GTP_DEBUG("Init external watchdog...");
+ GTP_DEBUG_FUNC();
+
+ msg.flags = !I2C_M_RD;
+ msg.addr = client->addr;
+ msg.len = 4;
+ msg.buf = opr_buffer;
+
+ while(retries < 5)
+ {
+ ret = i2c_transfer(client->adapter, &msg, 1);
+ if (ret == 1)
+ {
+ return 1;
+ }
+ retries++;
+ }
+ if (retries >= 5)
+ {
+ GTP_ERROR("init external watchdog failed!");
+ }
+ return 0;
+}
+
+/*******************************************************
+Function:
+ Esd protect function.
+ Added external watchdog by meta, 2013/03/07
+Input:
+ work: delayed work
+Output:
+ None.
+*******************************************************/
+static void gtp_esd_check_func(struct work_struct *work)
+{
+ s32 i;
+ s32 ret = -1;
+ struct goodix_ts_data *ts = NULL;
+ u8 test[4] = {0x80, 0x40};
+
+ GTP_DEBUG_FUNC();
+
+ ts = container_of(work, struct goodix_ts_data, work);
+
+ if (ts->gtp_is_suspend)
+ {
+ ts->esd_running = 0;
+ GTP_INFO("Esd terminated!");
+ return;
+ }
+
+ for (i = 0; i < 3; i++)
+ {
+ ret = gtp_i2c_read(ts->client, test, 4);
+
+ GTP_DEBUG("0x8040 = 0x%02X, 0x8041 = 0x%02X", test[2], test[3]);
+ if ((ret < 0))
+ {
+ // IIC communication problem
+ continue;
+ }
+ else
+ {
+ if ((test[2] == 0xAA) || (test[3] != 0xAA))
+ {
+ // IC works abnormally..
+ i = 3;
+ break;
+ }
+ else
+ {
+ // IC works normally, Write 0x8040 0xAA, feed the dog
+ test[2] = 0xAA;
+ gtp_i2c_write(ts->client, test, 3);
+ break;
+ }
+ }
+ }
+ if (i >= 3)
+ {
+ GTP_ERROR("IC Working ABNORMALLY, Resetting Guitar...");
+ gtp_reset_guitar(ts->client, 50);
+ }
+
+ if(!ts->gtp_is_suspend)
+ {
+ queue_delayed_work(gtp_esd_check_workqueue, &gtp_esd_check_work, GTP_ESD_CHECK_CIRCLE);
+ }
+ else
+ {
+ GTP_INFO("Esd terminated!");
+ ts->esd_running = 0;
+ }
+ return;
+}
+#endif
+
+static void gt9xx_release(struct device *device)
+{
+ return;
+}
+
+
+static struct platform_device gt9xx_device = {
+ .name = GTP_I2C_NAME,
+ .id = 0,
+ .dev = {.release = gt9xx_release},
+};
+
+static struct platform_driver gt9xx_driver = {
+ .driver = {
+ .name = GTP_I2C_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = goodix_ts_probe,
+ .remove = goodix_ts_remove,
+ .suspend = goodix_ts_suspend,
+ .resume = goodix_ts_resume,
+};
+
+
+struct i2c_board_info ts_i2c_board_info = {
+ .type = GTP_I2C_NAME,
+ .flags = 0x00,
+ .addr = GTP_I2C_ADDR,
+ .platform_data = NULL,
+ .archdata = NULL,
+ .irq = -1,
+};
+
+static int ts_i2c_register_device (void)
+{
+ struct i2c_board_info *ts_i2c_bi;
+ struct i2c_adapter *adapter = NULL;
+
+ ts_i2c_bi = &ts_i2c_board_info;
+ adapter = i2c_get_adapter(0x01);/*in bus 1*/
+ if (NULL == adapter) {
+ GTP_ERROR("can not get i2c adapter, client address error.");
+ return -1;
+ }
+ i2c_connect_client = i2c_new_device(adapter, ts_i2c_bi);
+ if (i2c_connect_client == NULL) {
+ GTP_ERROR("allocate i2c client failed.");
+ return -1;
+ }
+ i2c_put_adapter(adapter);
+ return 0;
+}
+
+static void ts_i2c_unregister_device(void)
+{
+ if (i2c_connect_client != NULL)
+ {
+ i2c_unregister_device(i2c_connect_client);
+ i2c_connect_client = NULL;
+ }
+}
+
+/*******************************************************
+Function:
+ Driver Install function.
+Input:
+ None.
+Output:
+ Executive Outcomes. 0---succeed.
+********************************************************/
+static int __devinit goodix_ts_init(void)
+{
+ s32 ret;
+
+ GTP_DEBUG_FUNC();
+ GTP_INFO("GTP driver installing...");
+ goodix_wq = create_singlethread_workqueue("goodix_wq");
+ if (!goodix_wq)
+ {
+ GTP_ERROR("Creat workqueue failed.");
+ return -ENOMEM;
+ }
+#if GTP_ESD_PROTECT
+ INIT_DELAYED_WORK(&gtp_esd_check_work, gtp_esd_check_func);
+ gtp_esd_check_workqueue = create_workqueue("gtp_esd_check");
+#endif
+ if (ts_i2c_register_device()<0)
+ {
+ destroy_workqueue(goodix_wq);
+ GTP_ERROR("Error to run ts_i2c_register_device()!\n");
+ return -1;
+ }
+
+ ret = platform_device_register(&gt9xx_device);
+ if(ret){
+ GTP_ERROR("register platform drivver failed!\n");
+ goto err_register_platdev;
+ }
+
+ ret = platform_driver_register(&gt9xx_driver);
+ if(ret){
+ GTP_ERROR("register platform device failed!\n");
+ goto err_register_platdriver;
+ }
+ return 0;
+err_register_platdriver:
+ platform_device_unregister(&gt9xx_device);
+err_register_platdev:
+ destroy_workqueue(goodix_wq);
+ ts_i2c_unregister_device();
+
+ return ret;
+}
+
+/*******************************************************
+Function:
+ Driver uninstall function.
+Input:
+ None.
+Output:
+ Executive Outcomes. 0---succeed.
+********************************************************/
+static void __exit goodix_ts_exit(void)
+{
+ GTP_DEBUG_FUNC();
+ GTP_INFO("GTP driver exited.");
+ ts_i2c_unregister_device();
+ platform_driver_unregister(&gt9xx_driver);
+ platform_device_unregister(&gt9xx_device);
+ if (goodix_wq)
+ {
+ destroy_workqueue(goodix_wq);
+ }
+}
+
+late_initcall(goodix_ts_init);
+module_exit(goodix_ts_exit);
+
+MODULE_DESCRIPTION("GTP Series Driver");
+MODULE_LICENSE("GPL");
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/gt9xx_ts/gt9xx.h b/ANDROID_3.4.5/drivers/input/touchscreen/gt9xx_ts/gt9xx.h
new file mode 100755
index 00000000..c58b4800
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/gt9xx_ts/gt9xx.h
@@ -0,0 +1,278 @@
+/* drivers/input/touchscreen/gt9xx.h
+ *
+ * 2010 - 2013 Goodix Technology.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be a reference
+ * to you, when you are integrating the GOODiX's CTP IC into your system,
+ * 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.
+ *
+ */
+
+#ifndef _GOODIX_GT9XX_H_
+#define _GOODIX_GT9XX_H_
+
+#include <linux/kernel.h>
+#include <linux/hrtimer.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/proc_fs.h>
+#include <linux/string.h>
+#include <asm/uaccess.h>
+#include <linux/vmalloc.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <mach/gpio.h>
+#include <linux/gpio.h>
+#include <mach/wmt_iomux.h>
+#include <linux/platform_device.h>
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+
+struct goodix_ts_data {
+ //spinlock_t irq_lock;
+ struct i2c_client *client;
+ struct input_dev *input_dev;
+ struct hrtimer timer;
+ struct work_struct work;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend early_suspend;
+#endif
+ char fw_name[20];
+ s32 i2c_addr;
+ s32 irq_is_disable;
+ s32 use_irq;
+ s32 irq_gpio;
+ s32 rst_gpio;
+ s32 abs_x_max;
+ s32 abs_y_max;
+ s32 max_touch_num;
+ u8 int_trigger_type;
+ s32 swap;
+ s32 xdir;
+ s32 ydir;
+ s32 lcd_exchg;
+ u8 green_wake_mode;
+ u8 chip_type;
+ u8 enter_update;
+ u8 gtp_is_suspend;
+ u8 gtp_rawdiff_mode;
+ u8 gtp_cfg_len;
+ u8 fixed_cfg;
+ u8 esd_running;
+ u8 fw_error;
+};
+
+extern u16 show_len;
+extern u16 total_len;
+extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
+
+//***************************PART1:ON/OFF define*******************************
+#define GTP_CUSTOM_CFG 0
+#define GTP_CHANGE_X2Y 0
+#define GTP_DRIVER_SEND_CFG 1
+#define GTP_HAVE_TOUCH_KEY 0
+#define GTP_POWER_CTRL_SLEEP 0
+#define GTP_ICS_SLOT_REPORT 0
+
+#define GTP_AUTO_UPDATE 1 // auto updated by .bin file as default
+#define GTP_HEADER_FW_UPDATE 0 // auto updated by head_fw_array in gt9xx_firmware.h, function together with GTP_AUTO_UPDATE
+
+#define GTP_CREATE_WR_NODE 1
+#define GTP_ESD_PROTECT 0
+#define GTP_WITH_PEN 0
+
+#define GTP_SLIDE_WAKEUP 0
+#define GTP_DBL_CLK_WAKEUP 0 // double-click wakeup, function together with GTP_SLIDE_WAKEUP
+
+#define GTP_DEBUG_ON 0
+#define GTP_DEBUG_ARRAY_ON 0
+#define GTP_DEBUG_FUNC_ON 0
+
+//*************************** PART2:TODO define **********************************
+// STEP_1(REQUIRED): Define Configuration Information Group(s)
+// Sensor_ID Map:
+/* sensor_opt1 sensor_opt2 Sensor_ID
+ GND GND 0
+ VDDIO GND 1
+ NC GND 2
+ GND NC/300K 3
+ VDDIO NC/300K 4
+ NC NC/300K 5
+*/
+// TODO: define your own default or for Sensor_ID == 0 config here.
+// The predefined one is just a sample config, which is not suitable for your tp in most cases.
+#define CTP_CFG_GROUP1 {\
+ 0x42,0x00,0x03,0x00,0x04,0x0A,0x34,0x00,0x01,0x3F,\
+ 0x28,0x0F,0x50,0x3C,0x03,0x05,0x00,0x00,0x00,0x00,\
+ 0x00,0x00,0x00,0x16,0x18,0x1C,0x14,0x8B,0x2A,0x0E,\
+ 0x2D,0x3D,0x12,0x0C,0x00,0x00,0x00,0x01,0x03,0x1D,\
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
+ 0x00,0x20,0x3D,0x94,0xC5,0x02,0x08,0x00,0x00,0x04,\
+ 0x9A,0x22,0x00,0x8F,0x26,0x00,0x81,0x2C,0x00,0x77,\
+ 0x32,0x00,0x6E,0x39,0x00,0x6E,0x00,0x00,0x00,0x00,\
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
+ 0x00,0x00,0x0A,0x08,0x06,0x04,0x02,0x0C,0x0E,0x10,\
+ 0x12,0x14,0x16,0x18,0x1A,0x1C,0x00,0x00,0x00,0x00,\
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
+ 0x00,0x00,0x00,0x02,0x04,0x06,0x08,0x0A,0x0C,0x0F,\
+ 0x10,0x12,0x13,0x16,0x18,0x1C,0x1D,0x1E,0x1F,0x20,\
+ 0x21,0x22,0x24,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,\
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
+ 0x00,0x00,0x00,0x00,0x9D,0x01\
+ }
+
+/*
+#define CTP_CFG_GROUP1 {\
+ 0x00,0x00,0x03,0x00,0x04,0x0A,0x35,0x00,0x01,0x08,\
+ 0x14,0x05,0x37,0x28,0x03,0x05,0x00,0x00,0x00,0x00,\
+ 0x00,0x00,0x00,0x16,0x18,0x1A,0x14,0x8B,0x2A,0x0E,\
+ 0x63,0x5E,0x31,0x0D,0x00,0x00,0x02,0xB9,0x02,0x2D,\
+ 0x00,0x00,0x00,0x00,0x00,0x03,0x64,0x32,0x00,0x00,\
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
+ 0x00,0x00,0x0A,0x08,0x06,0x04,0x02,0x0C,0x0E,0x10,\
+ 0x12,0x14,0x16,0x18,0x1A,0x1C,0xFF,0xFF,0xFF,0xFF,\
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,\
+ 0xFF,0xFF,0x00,0x02,0x04,0x06,0x08,0x0A,0x0C,0x0F,\
+ 0x10,0x12,0x13,0x16,0x18,0x1C,0x1D,0x1E,0x1F,0x20,\
+ 0x21,0x22,0x24,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,\
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,\
+ 0xFF,0xFF,0xFF,0xFF,0x4A,0x01\
+ }
+*/
+
+// TODO: define your config for Sensor_ID == 1 here, if needed
+#define CTP_CFG_GROUP2 {\
+ }
+// TODO: define your config for Sensor_ID == 2 here, if needed
+#define CTP_CFG_GROUP3 {\
+ }
+
+// TODO: define your config for Sensor_ID == 3 here, if needed
+#define CTP_CFG_GROUP4 {\
+ }
+
+// TODO: define your config for Sensor_ID == 4 here, if needed
+#define CTP_CFG_GROUP5 {\
+ }
+
+// TODO: define your config for Sensor_ID == 5 here, if needed
+#define CTP_CFG_GROUP6 {\
+ }
+
+// STEP_2(REQUIRED): Customize your I/O ports & I/O operations
+#define GTP_RST_PORT S5PV210_GPJ3(6)
+#define GTP_INT_PORT S5PV210_GPH1(3)
+#define GTP_INT_IRQ gpio_to_irq(GTP_INT_PORT)
+#define GTP_INT_CFG S3C_GPIO_SFN(0xF)
+
+#define GTP_GPIO_AS_INPUT(pin) do{\
+ gpio_direction_input(pin);\
+ wmt_gpio_setpull(pin, WMT_GPIO_PULL_NONE);\
+ }while(0)
+#define GTP_GPIO_AS_INT(pin,type) do{\
+ GTP_GPIO_AS_INPUT(pin);\
+ wmt_gpio_set_irq_type(pin,type);\
+ }while(0)
+#define GTP_GPIO_GET_VALUE(pin) gpio_get_value(pin)
+#define GTP_GPIO_OUTPUT(pin,level) gpio_direction_output(pin,level)
+#define GTP_GPIO_REQUEST(pin, label) gpio_request(pin, label)
+#define GTP_GPIO_FREE(pin) gpio_free(pin)
+#define GTP_IRQ_TAB {IRQ_TYPE_EDGE_RISING, IRQ_TYPE_EDGE_FALLING, IRQ_TYPE_LEVEL_LOW, IRQ_TYPE_LEVEL_HIGH}
+
+// STEP_3(optional): Specify your special config info if needed
+#if GTP_CUSTOM_CFG
+ #define GTP_MAX_HEIGHT 800
+ #define GTP_MAX_WIDTH 480
+ #define GTP_INT_TRIGGER 0 // 0: Rising 1: Falling
+#else
+ #define GTP_MAX_HEIGHT 4096
+ #define GTP_MAX_WIDTH 4096
+ #define GTP_INT_TRIGGER 1
+#endif
+#define GTP_MAX_TOUCH 5
+#define GTP_ESD_CHECK_CIRCLE 2000 // jiffy: ms
+
+// STEP_4(optional): If keys are available and reported as keys, config your key info here
+#if GTP_HAVE_TOUCH_KEY
+ #define GTP_KEY_TAB {KEY_MENU, KEY_HOME, KEY_BACK}
+#endif
+
+//***************************PART3:OTHER define*********************************
+#define GTP_DRIVER_VERSION "V1.8<2013/06/08>"
+#define GTP_I2C_NAME "Goodix-TS"
+#define GTP_I2C_ADDR 0x5d
+#define GTP_POLL_TIME 10 // jiffy: ms
+#define GTP_ADDR_LENGTH 2
+#define GTP_CONFIG_MIN_LENGTH 186
+#define GTP_CONFIG_MAX_LENGTH 240
+#define FAIL 0
+#define SUCCESS 1
+#define SWITCH_OFF 0
+#define SWITCH_ON 1
+
+// Registers define
+#define GTP_READ_COOR_ADDR 0x814E
+#define GTP_REG_SLEEP 0x8040
+#define GTP_REG_SENSOR_ID 0x814A
+#define GTP_REG_CONFIG_DATA 0x8047
+#define GTP_REG_VERSION 0x8140
+
+#define RESOLUTION_LOC 3
+#define TRIGGER_LOC 8
+
+#define CFG_GROUP_LEN(p_cfg_grp) (sizeof(p_cfg_grp) / sizeof(p_cfg_grp[0]))
+// Log define
+#define GTP_INFO(fmt,arg...) printk("<<-GTP-INFO->> "fmt"\n",##arg)
+#define GTP_ERROR(fmt,arg...) printk("<<-GTP-ERROR->> "fmt"\n",##arg)
+#define GTP_DEBUG(fmt,arg...) do{\
+ if(GTP_DEBUG_ON)\
+ printk("<<-GTP-DEBUG->> [%d]"fmt"\n",__LINE__, ##arg);\
+ }while(0)
+#define GTP_DEBUG_ARRAY(array, num) do{\
+ s32 i;\
+ u8* a = array;\
+ if(GTP_DEBUG_ARRAY_ON)\
+ {\
+ printk("<<-GTP-DEBUG-ARRAY->>\n");\
+ for (i = 0; i < (num); i++)\
+ {\
+ printk("%02x ", (a)[i]);\
+ if ((i + 1 ) %10 == 0)\
+ {\
+ printk("\n");\
+ }\
+ }\
+ printk("\n");\
+ }\
+ }while(0)
+#define GTP_DEBUG_FUNC() do{\
+ if(GTP_DEBUG_FUNC_ON)\
+ printk("<<-GTP-FUNC->> Func:%s@Line:%d\n",__func__,__LINE__);\
+ }while(0)
+#define GTP_SWAP(x, y) do{\
+ typeof(x) z = x;\
+ x = y;\
+ y = z;\
+ }while (0)
+
+//*****************************End of Part III********************************
+
+#endif /* _GOODIX_GT9XX_H_ */
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/gt9xx_ts/gt9xx_firmware.h b/ANDROID_3.4.5/drivers/input/touchscreen/gt9xx_ts/gt9xx_firmware.h
new file mode 100755
index 00000000..3998bf00
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/gt9xx_ts/gt9xx_firmware.h
@@ -0,0 +1,6 @@
+// make sense only when GTP_HEADER_FW_UPDATE & GTP_AUTO_UPDATE are enabled
+// define your own firmware array here
+const unsigned char header_fw_array[] =
+{
+
+}; \ No newline at end of file
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/gt9xx_ts/gt9xx_update.c b/ANDROID_3.4.5/drivers/input/touchscreen/gt9xx_ts/gt9xx_update.c
new file mode 100755
index 00000000..88daf209
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/gt9xx_ts/gt9xx_update.c
@@ -0,0 +1,1939 @@
+/* drivers/input/touchscreen/gt9xx_update.c
+ *
+ * 2010 - 2012 Goodix Technology.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be a reference
+ * to you, when you are integrating the GOODiX's CTP IC into your system,
+ * 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.
+ *
+ * Latest Version:1.6
+ * Author: andrew@goodix.com
+ * Revision Record:
+ * V1.0:
+ * first release. By Andrew, 2012/08/31
+ * V1.2:
+ * add force update,GT9110P pid map. By Andrew, 2012/10/15
+ * V1.4:
+ * 1. add config auto update function;
+ * 2. modify enter_update_mode;
+ * 3. add update file cal checksum.
+ * By Andrew, 2012/12/12
+ * V1.6:
+ * 1. replace guitar_client with i2c_connect_client;
+ * 2. support firmware header array update.
+ * By Meta, 2013/03/11
+ */
+#include <linux/kthread.h>
+#include "gt9xx.h"
+
+#if GTP_HEADER_FW_UPDATE
+#include <linux/namei.h>
+#include <linux/mount.h>
+#include "gt9xx_firmware.h"
+#endif
+
+#define GUP_REG_HW_INFO 0x4220
+#define GUP_REG_FW_MSG 0x41E4
+#define GUP_REG_PID_VID 0x8140
+
+#define GUP_SEARCH_FILE_TIMES 2
+#define UPDATE_FILE_PATH_2 "/system/etc/firmware/_goodix_update_.bin"
+#define UPDATE_FILE_PATH_1 "/extsdcard/_goodix_update_.bin"
+
+#define CONFIG_FILE_PATH_1 "/extsdcard/_goodix_config_.cfg"
+#define CONFIG_FILE_PATH_2 "/system/etc/firmware/_goodix_config_.cfg"
+
+#define FW_HEAD_LENGTH 14
+#define FW_SECTION_LENGTH 0x2000
+#define FW_DSP_ISP_LENGTH 0x1000
+#define FW_DSP_LENGTH 0x1000
+#define FW_BOOT_LENGTH 0x800
+
+#define PACK_SIZE 256
+#define MAX_FRAME_CHECK_TIME 5
+
+#define _bRW_MISCTL__SRAM_BANK 0x4048
+#define _bRW_MISCTL__MEM_CD_EN 0x4049
+#define _bRW_MISCTL__CACHE_EN 0x404B
+#define _bRW_MISCTL__TMR0_EN 0x40B0
+#define _rRW_MISCTL__SWRST_B0_ 0x4180
+#define _bWO_MISCTL__CPU_SWRST_PULSE 0x4184
+#define _rRW_MISCTL__BOOTCTL_B0_ 0x4190
+#define _rRW_MISCTL__BOOT_OPT_B0_ 0x4218
+#define _rRW_MISCTL__BOOT_CTL_ 0x5094
+
+#define FAIL 0
+#define SUCCESS 1
+
+#pragma pack(1)
+typedef struct
+{
+ u8 hw_info[4]; //hardware info//
+ u8 pid[8]; //product id //
+ u16 vid; //version id //
+}st_fw_head;
+#pragma pack()
+
+typedef struct
+{
+ u8 force_update;
+ u8 fw_flag;
+ struct file *file;
+ struct file *cfg_file;
+ st_fw_head ic_fw_msg;
+ mm_segment_t old_fs;
+}st_update_msg;
+
+st_update_msg update_msg;
+u16 show_len;
+u16 total_len;
+u8 got_file_flag = 0;
+u8 searching_file = 0;
+extern u8 config[GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH];
+extern void gtp_reset_guitar(struct i2c_client *client, s32 ms);
+extern s32 gtp_send_cfg(struct goodix_ts_data * ts);
+extern struct i2c_client * i2c_connect_client;
+extern struct goodix_ts_data *l_ts;
+extern void gtp_irq_enable(struct goodix_ts_data *ts);
+extern void gtp_irq_disable(struct goodix_ts_data *ts);
+extern s32 gtp_i2c_read_dbl_check(struct i2c_client *, u16, u8 *, int);
+#if GTP_ESD_PROTECT
+extern void gtp_esd_switch(struct i2c_client *, s32);
+#endif
+/*******************************************************
+Function:
+ Read data from the i2c slave device.
+Input:
+ client: i2c device.
+ buf[0~1]: read start address.
+ buf[2~len-1]: read data buffer.
+ len: GTP_ADDR_LENGTH + read bytes count
+Output:
+ numbers of i2c_msgs to transfer:
+ 2: succeed, otherwise: failed
+*********************************************************/
+s32 gup_i2c_read(struct i2c_client *client, u8 *buf, s32 len)
+{
+ struct i2c_msg msgs[2];
+ s32 ret=-1;
+ s32 retries = 0;
+
+ GTP_DEBUG_FUNC();
+
+ msgs[0].flags = !I2C_M_RD;
+ msgs[0].addr = client->addr;
+ msgs[0].len = GTP_ADDR_LENGTH;
+ msgs[0].buf = &buf[0];
+ //msgs[0].scl_rate = 300 * 1000; // for Rockchip
+
+ msgs[1].flags = I2C_M_RD;
+ msgs[1].addr = client->addr;
+ msgs[1].len = len - GTP_ADDR_LENGTH;
+ msgs[1].buf = &buf[GTP_ADDR_LENGTH];
+ //msgs[1].scl_rate = 300 * 1000;
+
+ while(retries < 5)
+ {
+ ret = i2c_transfer(client->adapter, msgs, 2);
+ if(ret == 2)break;
+ retries++;
+ }
+
+ return ret;
+}
+
+/*******************************************************
+Function:
+ Write data to the i2c slave device.
+Input:
+ client: i2c device.
+ buf[0~1]: write start address.
+ buf[2~len-1]: data buffer
+ len: GTP_ADDR_LENGTH + write bytes count
+Output:
+ numbers of i2c_msgs to transfer:
+ 1: succeed, otherwise: failed
+*********************************************************/
+s32 gup_i2c_write(struct i2c_client *client,u8 *buf,s32 len)
+{
+ struct i2c_msg msg;
+ s32 ret=-1;
+ s32 retries = 0;
+
+ GTP_DEBUG_FUNC();
+
+ msg.flags = !I2C_M_RD;
+ msg.addr = client->addr;
+ msg.len = len;
+ msg.buf = buf;
+ //msg.scl_rate = 300 * 1000; // for Rockchip
+
+ while(retries < 5)
+ {
+ ret = i2c_transfer(client->adapter, &msg, 1);
+ if (ret == 1)break;
+ retries++;
+ }
+
+ return ret;
+}
+
+static s32 gup_init_panel(struct goodix_ts_data *ts)
+{
+ s32 ret = 0;
+ s32 i = 0;
+ u8 check_sum = 0;
+ u8 opr_buf[16];
+ u8 sensor_id = 0;
+
+ u8 cfg_info_group1[] = CTP_CFG_GROUP1;
+ u8 cfg_info_group2[] = CTP_CFG_GROUP2;
+ u8 cfg_info_group3[] = CTP_CFG_GROUP3;
+ u8 cfg_info_group4[] = CTP_CFG_GROUP4;
+ u8 cfg_info_group5[] = CTP_CFG_GROUP5;
+ u8 cfg_info_group6[] = CTP_CFG_GROUP6;
+ u8 *send_cfg_buf[] = {cfg_info_group1, cfg_info_group2, cfg_info_group3,
+ cfg_info_group4, cfg_info_group5, cfg_info_group6};
+ u8 cfg_info_len[] = { CFG_GROUP_LEN(cfg_info_group1),
+ CFG_GROUP_LEN(cfg_info_group2),
+ CFG_GROUP_LEN(cfg_info_group3),
+ CFG_GROUP_LEN(cfg_info_group4),
+ CFG_GROUP_LEN(cfg_info_group5),
+ CFG_GROUP_LEN(cfg_info_group6)};
+
+ if ((!cfg_info_len[1]) && (!cfg_info_len[2]) &&
+ (!cfg_info_len[3]) && (!cfg_info_len[4]) &&
+ (!cfg_info_len[5]))
+ {
+ sensor_id = 0;
+ }
+ else
+ {
+ ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_SENSOR_ID, &sensor_id, 1);
+ if (SUCCESS == ret)
+ {
+ if (sensor_id >= 0x06)
+ {
+ GTP_ERROR("Invalid sensor_id(0x%02X), No Config Sent!", sensor_id);
+ return -1;
+ }
+ }
+ else
+ {
+ GTP_ERROR("Failed to get sensor_id, No config sent!");
+ return -1;
+ }
+ }
+
+ GTP_DEBUG("Sensor_ID: %d", sensor_id);
+
+ ts->gtp_cfg_len = cfg_info_len[sensor_id];
+
+ if (ts->gtp_cfg_len < GTP_CONFIG_MIN_LENGTH)
+ {
+ GTP_ERROR("Sensor_ID(%d) matches with NULL or INVALID CONFIG GROUP! NO Config Sent! You need to check you header file CFG_GROUP section!", sensor_id);
+ return -1;
+ }
+
+ ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_CONFIG_DATA, &opr_buf[0], 1);
+
+ if (ret == SUCCESS)
+ {
+ GTP_DEBUG("CFG_GROUP%d Config Version: %d, IC Config Version: %d", sensor_id+1,
+ send_cfg_buf[sensor_id][0], opr_buf[0]);
+
+ send_cfg_buf[sensor_id][0] = opr_buf[0];
+ ts->fixed_cfg = 0;
+ /*
+ if (opr_buf[0] < 90)
+ {
+ grp_cfg_version = send_cfg_buf[sensor_id][0]; // backup group config version
+ send_cfg_buf[sensor_id][0] = 0x00;
+ ts->fixed_cfg = 0;
+ }
+ else // treated as fixed config, not send config
+ {
+ GTP_INFO("Ic fixed config with config version(%d)", opr_buf[0]);
+ ts->fixed_cfg = 1;
+ }*/
+ }
+ else
+ {
+ GTP_ERROR("Failed to get ic config version!No config sent!");
+ return -1;
+ }
+
+ memset(&config[GTP_ADDR_LENGTH], 0, GTP_CONFIG_MAX_LENGTH);
+ memcpy(&config[GTP_ADDR_LENGTH], send_cfg_buf[sensor_id], ts->gtp_cfg_len);
+
+ GTP_DEBUG("X_MAX = %d, Y_MAX = %d, TRIGGER = 0x%02x",
+ ts->abs_x_max, ts->abs_y_max, ts->int_trigger_type);
+
+ config[RESOLUTION_LOC] = (u8)GTP_MAX_WIDTH;
+ config[RESOLUTION_LOC + 1] = (u8)(GTP_MAX_WIDTH>>8);
+ config[RESOLUTION_LOC + 2] = (u8)GTP_MAX_HEIGHT;
+ config[RESOLUTION_LOC + 3] = (u8)(GTP_MAX_HEIGHT>>8);
+
+ if (GTP_INT_TRIGGER == 0) //RISING
+ {
+ config[TRIGGER_LOC] &= 0xfe;
+ }
+ else if (GTP_INT_TRIGGER == 1) //FALLING
+ {
+ config[TRIGGER_LOC] |= 0x01;
+ }
+
+ check_sum = 0;
+ for (i = GTP_ADDR_LENGTH; i < ts->gtp_cfg_len; i++)
+ {
+ check_sum += config[i];
+ }
+ config[ts->gtp_cfg_len] = (~check_sum) + 1;
+
+ GTP_DEBUG_FUNC();
+ ret = gtp_send_cfg(ts);
+ if (ret < 0)
+ {
+ GTP_ERROR("Send config error.");
+ }
+
+ msleep(10);
+ return 0;
+}
+
+
+static u8 gup_get_ic_msg(struct i2c_client *client, u16 addr, u8* msg, s32 len)
+{
+ s32 i = 0;
+
+ msg[0] = (addr >> 8) & 0xff;
+ msg[1] = addr & 0xff;
+
+ for (i = 0; i < 5; i++)
+ {
+ if (gup_i2c_read(client, msg, GTP_ADDR_LENGTH + len) > 0)
+ {
+ break;
+ }
+ }
+
+ if (i >= 5)
+ {
+ GTP_ERROR("Read data from 0x%02x%02x failed!", msg[0], msg[1]);
+ return FAIL;
+ }
+
+ return SUCCESS;
+}
+
+static u8 gup_set_ic_msg(struct i2c_client *client, u16 addr, u8 val)
+{
+ s32 i = 0;
+ u8 msg[3];
+
+ msg[0] = (addr >> 8) & 0xff;
+ msg[1] = addr & 0xff;
+ msg[2] = val;
+
+ for (i = 0; i < 5; i++)
+ {
+ if (gup_i2c_write(client, msg, GTP_ADDR_LENGTH + 1) > 0)
+ {
+ break;
+ }
+ }
+
+ if (i >= 5)
+ {
+ GTP_ERROR("Set data to 0x%02x%02x failed!", msg[0], msg[1]);
+ return FAIL;
+ }
+
+ return SUCCESS;
+}
+
+static u8 gup_get_ic_fw_msg(struct i2c_client *client)
+{
+ s32 ret = -1;
+ u8 retry = 0;
+ u8 buf[16];
+ u8 i;
+
+ // step1:get hardware info
+ ret = gtp_i2c_read_dbl_check(client, GUP_REG_HW_INFO, &buf[GTP_ADDR_LENGTH], 4);
+ if (FAIL == ret)
+ {
+ GTP_ERROR("[get_ic_fw_msg]get hw_info failed,exit");
+ return FAIL;
+ }
+
+ // buf[2~5]: 00 06 90 00
+ // hw_info: 00 90 06 00
+ for(i=0; i<4; i++)
+ {
+ update_msg.ic_fw_msg.hw_info[i] = buf[GTP_ADDR_LENGTH + 3 - i];
+ }
+ GTP_DEBUG("IC Hardware info:%02x%02x%02x%02x", update_msg.ic_fw_msg.hw_info[0], update_msg.ic_fw_msg.hw_info[1],
+ update_msg.ic_fw_msg.hw_info[2], update_msg.ic_fw_msg.hw_info[3]);
+ // step2:get firmware message
+ for(retry=0; retry<2; retry++)
+ {
+ ret = gup_get_ic_msg(client, GUP_REG_FW_MSG, buf, 1);
+ if(FAIL == ret)
+ {
+ GTP_ERROR("Read firmware message fail.");
+ return ret;
+ }
+
+ update_msg.force_update = buf[GTP_ADDR_LENGTH];
+ if((0xBE != update_msg.force_update)&&(!retry))
+ {
+ GTP_INFO("The check sum in ic is error.");
+ GTP_INFO("The IC will be updated by force.");
+ continue;
+ }
+ break;
+ }
+ GTP_DEBUG("IC force update flag:0x%x", update_msg.force_update);
+
+ // step3:get pid & vid
+ ret = gtp_i2c_read_dbl_check(client, GUP_REG_PID_VID, &buf[GTP_ADDR_LENGTH], 6);
+ if (FAIL == ret)
+ {
+ GTP_ERROR("[get_ic_fw_msg]get pid & vid failed,exit");
+ return FAIL;
+ }
+
+ memset(update_msg.ic_fw_msg.pid, 0, sizeof(update_msg.ic_fw_msg.pid));
+ memcpy(update_msg.ic_fw_msg.pid, &buf[GTP_ADDR_LENGTH], 4);
+ GTP_DEBUG("IC Product id:%s", update_msg.ic_fw_msg.pid);
+
+ //GT9XX PID MAPPING
+ /*|-----FLASH-----RAM-----|
+ |------918------918-----|
+ |------968------968-----|
+ |------913------913-----|
+ |------913P-----913P----|
+ |------927------927-----|
+ |------927P-----927P----|
+ |------9110-----9110----|
+ |------9110P----9111----|*/
+ if(update_msg.ic_fw_msg.pid[0] != 0)
+ {
+ if(!memcmp(update_msg.ic_fw_msg.pid, "9111", 4))
+ {
+ GTP_DEBUG("IC Mapping Product id:%s", update_msg.ic_fw_msg.pid);
+ memcpy(update_msg.ic_fw_msg.pid, "9110P", 5);
+ }
+ }
+
+ update_msg.ic_fw_msg.vid = buf[GTP_ADDR_LENGTH+4] + (buf[GTP_ADDR_LENGTH+5]<<8);
+ GTP_DEBUG("IC version id:%04x", update_msg.ic_fw_msg.vid);
+
+ return SUCCESS;
+}
+
+s32 gup_enter_update_mode(struct goodix_ts_data *ts)
+{
+ s32 ret = -1;
+ s32 retry = 0;
+ u8 rd_buf[3];
+
+ //step1:RST output low last at least 2ms
+ GTP_GPIO_OUTPUT(ts->rst_gpio, 0);
+ msleep(2);
+
+ //step2:select I2C slave addr,INT:0--0xBA;1--0x28.
+ GTP_GPIO_OUTPUT(ts->irq_gpio, (ts->client->addr == 0x14));
+ msleep(2);
+
+ //step3:RST output high reset guitar
+ GTP_GPIO_OUTPUT(ts->rst_gpio, 1);
+
+ //20121211 modify start
+ msleep(5);
+ while(retry++ < 200)
+ {
+ //step4:Hold ss51 & dsp
+ ret = gup_set_ic_msg(ts->client, _rRW_MISCTL__SWRST_B0_, 0x0C);
+ if(ret <= 0)
+ {
+ GTP_DEBUG("Hold ss51 & dsp I2C error,retry:%d", retry);
+ continue;
+ }
+
+ //step5:Confirm hold
+ ret = gup_get_ic_msg(ts->client, _rRW_MISCTL__SWRST_B0_, rd_buf, 1);
+ if(ret <= 0)
+ {
+ GTP_DEBUG("Hold ss51 & dsp I2C error,retry:%d", retry);
+ continue;
+ }
+ if(0x0C == rd_buf[GTP_ADDR_LENGTH])
+ {
+ GTP_DEBUG("Hold ss51 & dsp confirm SUCCESS");
+ break;
+ }
+ GTP_DEBUG("Hold ss51 & dsp confirm 0x4180 failed,value:%d", rd_buf[GTP_ADDR_LENGTH]);
+ }
+ if(retry >= 200)
+ {
+ GTP_ERROR("Enter update Hold ss51 failed.");
+ return FAIL;
+ }
+
+ //step6:DSP_CK and DSP_ALU_CK PowerOn
+ ret = gup_set_ic_msg(ts->client, 0x4010, 0x00);
+
+ //20121211 modify end
+ return ret;
+}
+
+void gup_leave_update_mode(struct goodix_ts_data *ts)
+{
+ //GTP_GPIO_AS_INT(ts->irq_gpio,IRQ_TYPE_EDGE_FALLING);
+
+ GTP_DEBUG("[leave_update_mode]reset chip.");
+ gtp_reset_guitar(i2c_connect_client, 20);
+}
+
+// Get the correct nvram data
+// The correct conditions:
+// 1. the hardware info is the same
+// 2. the product id is the same
+// 3. the firmware version in update file is greater than the firmware version in ic
+// or the check sum in ic is wrong
+/* Update Conditions:
+ 1. Same hardware info
+ 2. Same PID
+ 3. File PID > IC PID
+ Force Update Conditions:
+ 1. Wrong ic firmware checksum
+ 2. INVALID IC PID or VID
+ 3. IC PID == 91XX || File PID == 91XX
+*/
+
+static u8 gup_enter_update_judge(st_fw_head *fw_head)
+{
+ u16 u16_tmp;
+ s32 i = 0;
+
+ u16_tmp = fw_head->vid;
+ fw_head->vid = (u16)(u16_tmp>>8) + (u16)(u16_tmp<<8);
+
+ GTP_DEBUG("FILE HARDWARE INFO:%02x%02x%02x%02x", fw_head->hw_info[0], fw_head->hw_info[1], fw_head->hw_info[2], fw_head->hw_info[3]);
+ GTP_DEBUG("FILE PID:%s", fw_head->pid);
+ GTP_DEBUG("FILE VID:%04x", fw_head->vid);
+
+ GTP_DEBUG("IC HARDWARE INFO:%02x%02x%02x%02x", update_msg.ic_fw_msg.hw_info[0], update_msg.ic_fw_msg.hw_info[1],
+ update_msg.ic_fw_msg.hw_info[2], update_msg.ic_fw_msg.hw_info[3]);
+ GTP_DEBUG("IC PID:%s", update_msg.ic_fw_msg.pid);
+ GTP_DEBUG("IC VID:%04x", update_msg.ic_fw_msg.vid);
+
+ //First two conditions
+ if ( !memcmp(fw_head->hw_info, update_msg.ic_fw_msg.hw_info, sizeof(update_msg.ic_fw_msg.hw_info)))
+ {
+ GTP_DEBUG("Get the same hardware info.");
+ if( update_msg.force_update != 0xBE )
+ {
+ GTP_INFO("FW chksum error,need enter update.");
+ return SUCCESS;
+ }
+
+ // 20130523 start
+ if (strlen(update_msg.ic_fw_msg.pid) < 3)
+ {
+ GTP_INFO("Illegal IC pid, need enter update");
+ return SUCCESS;
+ }
+ else
+ {
+ for (i = 0; i < 3; i++)
+ {
+ if ((update_msg.ic_fw_msg.pid[i] < 0x30) || (update_msg.ic_fw_msg.pid[i] > 0x39))
+ {
+ GTP_INFO("Illegal IC pid, out of bound, need enter update");
+ return SUCCESS;
+ }
+ }
+ }
+ // 20130523 end
+
+
+ if (( !memcmp(fw_head->pid, update_msg.ic_fw_msg.pid, (strlen(fw_head->pid)<3?3:strlen(fw_head->pid))))||
+ (!memcmp(update_msg.ic_fw_msg.pid, "91XX", 4))||
+ (!memcmp(fw_head->pid, "91XX", 4)))
+ {
+ if(!memcmp(fw_head->pid, "91XX", 4))
+ {
+ GTP_DEBUG("Force none same pid update mode.");
+ }
+ else
+ {
+ GTP_DEBUG("Get the same pid.");
+ }
+ //The third condition
+ if (fw_head->vid > update_msg.ic_fw_msg.vid)
+ {
+
+ GTP_INFO("Need enter update.");
+ return SUCCESS;
+ }
+ GTP_ERROR("Don't meet the third condition.");
+ GTP_ERROR("File VID <= Ic VID, update aborted!");
+ }
+ else
+ {
+ GTP_ERROR("File PID != Ic PID, update aborted!");
+ }
+ }
+ else
+ {
+ GTP_ERROR("Different Hardware, update aborted!");
+ }
+ return FAIL;
+}
+
+static u8 ascii2hex(u8 a)
+{
+ s8 value = 0;
+
+ if(a >= '0' && a <= '9')
+ {
+ value = a - '0';
+ }
+ else if(a >= 'A' && a <= 'F')
+ {
+ value = a - 'A' + 0x0A;
+ }
+ else if(a >= 'a' && a <= 'f')
+ {
+ value = a - 'a' + 0x0A;
+ }
+ else
+ {
+ value = 0xff;
+ }
+
+ return value;
+}
+
+static s8 gup_update_config(struct i2c_client *client)
+{
+ s32 file_len = 0;
+ s32 ret = 0;
+ s32 i = 0;
+ s32 file_cfg_len = 0;
+ s32 chip_cfg_len = 0;
+ s32 count = 0;
+ u8 *buf;
+ u8 *pre_buf;
+ u8 *file_config;
+ //u8 checksum = 0;
+ u8 pid[8];
+
+ if(NULL == update_msg.cfg_file)
+ {
+ GTP_ERROR("[update_cfg]No need to upgrade config!");
+ return FAIL;
+ }
+ file_len = update_msg.cfg_file->f_op->llseek(update_msg.cfg_file, 0, SEEK_END);
+
+ ret = gup_get_ic_msg(client, GUP_REG_PID_VID, pid, 6);
+ if(FAIL == ret)
+ {
+ GTP_ERROR("[update_cfg]Read product id & version id fail.");
+ return FAIL;
+ }
+ pid[5] = '\0';
+ GTP_DEBUG("update cfg get pid:%s", &pid[GTP_ADDR_LENGTH]);
+
+ chip_cfg_len = 186;
+ if(!memcmp(&pid[GTP_ADDR_LENGTH], "968", 3) ||
+ !memcmp(&pid[GTP_ADDR_LENGTH], "910", 3) ||
+ !memcmp(&pid[GTP_ADDR_LENGTH], "960", 3))
+ {
+ chip_cfg_len = 228;
+ }
+ GTP_DEBUG("[update_cfg]config file len:%d", file_len);
+ GTP_DEBUG("[update_cfg]need config len:%d",chip_cfg_len);
+ if((file_len+5) < chip_cfg_len*5)
+ {
+ GTP_ERROR("Config length error");
+ return -1;
+ }
+
+ buf = (u8*)kzalloc(file_len, GFP_KERNEL);
+ pre_buf = (u8*)kzalloc(file_len, GFP_KERNEL);
+ file_config = (u8*)kzalloc(chip_cfg_len + GTP_ADDR_LENGTH, GFP_KERNEL);
+ update_msg.cfg_file->f_op->llseek(update_msg.cfg_file, 0, SEEK_SET);
+
+ GTP_DEBUG("[update_cfg]Read config from file.");
+ ret = update_msg.cfg_file->f_op->read(update_msg.cfg_file, (char*)pre_buf, file_len, &update_msg.cfg_file->f_pos);
+ if(ret<0)
+ {
+ GTP_ERROR("[update_cfg]Read config file failed.");
+ goto update_cfg_file_failed;
+ }
+
+ GTP_DEBUG("[update_cfg]Delete illgal charactor.");
+ for(i=0,count=0; i<file_len; i++)
+ {
+ if (pre_buf[i] == ' ' || pre_buf[i] == '\r' || pre_buf[i] == '\n')
+ {
+ continue;
+ }
+ buf[count++] = pre_buf[i];
+ }
+
+ GTP_DEBUG("[update_cfg]Ascii to hex.");
+ file_config[0] = GTP_REG_CONFIG_DATA >> 8;
+ file_config[1] = GTP_REG_CONFIG_DATA & 0xff;
+ for(i=0,file_cfg_len=GTP_ADDR_LENGTH; i<count; i+=5)
+ {
+ if((buf[i]=='0') && ((buf[i+1]=='x') || (buf[i+1]=='X')))
+ {
+ u8 high,low;
+ high = ascii2hex(buf[i+2]);
+ low = ascii2hex(buf[i+3]);
+
+ if((high == 0xFF) || (low == 0xFF))
+ {
+ ret = 0;
+ GTP_ERROR("[update_cfg]Illegal config file.");
+ goto update_cfg_file_failed;
+ }
+ file_config[file_cfg_len++] = (high<<4) + low;
+ }
+ else
+ {
+ ret = 0;
+ GTP_ERROR("[update_cfg]Illegal config file.");
+ goto update_cfg_file_failed;
+ }
+ }
+
+// //cal checksum
+// for(i=GTP_ADDR_LENGTH; i<chip_cfg_len; i++)
+// {
+// checksum += file_config[i];
+// }
+// file_config[chip_cfg_len] = (~checksum) + 1;
+// file_config[chip_cfg_len+1] = 0x01;
+
+ GTP_DEBUG("config:");
+ GTP_DEBUG_ARRAY(file_config+2, file_cfg_len);
+
+ i = 0;
+ while(i++ < 5)
+ {
+ ret = gup_i2c_write(client, file_config, file_cfg_len);
+ if(ret > 0)
+ {
+ GTP_INFO("[update_cfg]Send config SUCCESS.");
+ break;
+ }
+ GTP_ERROR("[update_cfg]Send config i2c error.");
+ }
+
+update_cfg_file_failed:
+ kfree(pre_buf);
+ kfree(buf);
+ kfree(file_config);
+ return ret;
+}
+
+#if GTP_HEADER_FW_UPDATE
+static u8 gup_check_fs_mounted(char *path_name)
+{
+ struct path root_path;
+ struct path path;
+ int err;
+ err = kern_path("/", LOOKUP_FOLLOW, &root_path);
+
+ if (err)
+ {
+ GTP_DEBUG("\"/\" NOT Mounted: %d", err);
+ return FAIL;
+ }
+ err = kern_path(path_name, LOOKUP_FOLLOW, &path);
+
+ if (err)
+ {
+ GTP_DEBUG("/data/ NOT Mounted: %d", err);
+ return FAIL;
+ }
+
+ return SUCCESS;
+
+ /*
+ if (path.mnt->mnt_sb == root_path.mnt->mnt_sb)
+ {
+ //-- not mounted
+ return FAIL;
+ }
+ else
+ {
+ return SUCCESS;
+ }*/
+
+}
+#endif
+static u8 gup_check_update_file(struct i2c_client *client, st_fw_head* fw_head, u8* path)
+{
+ s32 ret = 0;
+ s32 i = 0;
+ s32 fw_checksum = 0;
+ u8 buf[FW_HEAD_LENGTH];
+
+ char fwname[64] = {0};
+ struct goodix_ts_data *ts = l_ts;
+ sprintf(fwname, "/system/etc/firmware/%s.bin", ts->fw_name);
+ GTP_INFO("firmware file name: %s.", fwname);
+ if (path)
+ {
+ GTP_DEBUG("Update File path:%s, %d", path, strlen(path));
+ update_msg.file = filp_open(path, O_RDONLY, 0);
+
+ if (IS_ERR(update_msg.file))
+ {
+ GTP_ERROR("Open update file(%s) error!", path);
+ return FAIL;
+ }
+ }
+ else
+ {
+#if GTP_HEADER_FW_UPDATE
+ for (i = 0; i < (GUP_SEARCH_FILE_TIMES); i++)
+ {
+ GTP_DEBUG("Waiting for /data mounted [%d]", i);
+
+ if (gup_check_fs_mounted("/data") == SUCCESS)
+ {
+ GTP_DEBUG("/data Mounted!");
+ break;
+ }
+ msleep(3000);
+ }
+ if (i >= (GUP_SEARCH_FILE_TIMES))
+ {
+ GTP_ERROR("Wait for /data mounted timeout!");
+ return FAIL;
+ }
+
+ // update config
+ update_msg.cfg_file = filp_open(CONFIG_FILE_PATH_1, O_RDONLY, 0);
+ if (IS_ERR(update_msg.cfg_file))
+ {
+ GTP_DEBUG("%s is unavailable", CONFIG_FILE_PATH_1);
+ }
+ else
+ {
+ GTP_INFO("Update Config File: %s", CONFIG_FILE_PATH_1);
+ ret = gup_update_config(client);
+ if(ret <= 0)
+ {
+ GTP_ERROR("Update config failed.");
+ }
+ filp_close(update_msg.cfg_file, NULL);
+ }
+
+ if (sizeof(header_fw_array) < (FW_HEAD_LENGTH+FW_SECTION_LENGTH*4+FW_DSP_ISP_LENGTH+FW_DSP_LENGTH+FW_BOOT_LENGTH))
+ {
+ GTP_ERROR("INVALID header_fw_array, check your gt9xx_firmware.h file!");
+ return FAIL;
+ }
+ update_msg.file = filp_open(UPDATE_FILE_PATH_2, O_CREAT | O_RDWR, 0666);
+ if ((IS_ERR(update_msg.file)))
+ {
+ GTP_ERROR("Failed to Create file: %s for fw_header!", UPDATE_FILE_PATH_2);
+ return FAIL;
+ }
+ update_msg.file->f_op->llseek(update_msg.file, 0, SEEK_SET);
+ update_msg.file->f_op->write(update_msg.file, (char *)header_fw_array, sizeof(header_fw_array), &update_msg.file->f_pos);
+ filp_close(update_msg.file, NULL);
+ update_msg.file = filp_open(UPDATE_FILE_PATH_2, O_RDONLY, 0);
+#else
+ //u8 fp_len = max(sizeof(UPDATE_FILE_PATH_1), sizeof(UPDATE_FILE_PATH_2));
+ u8 fp_len = max(sizeof(UPDATE_FILE_PATH_1), sizeof(fwname));
+ u8 cfp_len = max(sizeof(CONFIG_FILE_PATH_1), sizeof(CONFIG_FILE_PATH_2));
+ u8 *search_update_path = (u8*)kzalloc(fp_len, GFP_KERNEL);
+ u8 *search_cfg_path = (u8*)kzalloc(cfp_len, GFP_KERNEL);
+ //Begin to search update file,the config file & firmware file must be in the same path,single or double.
+ searching_file = 1;
+ for (i = 0; i < GUP_SEARCH_FILE_TIMES; i++)
+ {
+ if (searching_file == 0)
+ {
+ kfree(search_update_path);
+ kfree(search_cfg_path);
+ GTP_INFO(".bin/.cfg update file search forcely terminated!");
+ return FAIL;
+ }
+ if(i%2)
+ {
+ memcpy(search_update_path, UPDATE_FILE_PATH_1, sizeof(UPDATE_FILE_PATH_1));
+ memcpy(search_cfg_path, CONFIG_FILE_PATH_1, sizeof(CONFIG_FILE_PATH_1));
+ }
+ else
+ {
+ //memcpy(search_update_path, UPDATE_FILE_PATH_2, sizeof(UPDATE_FILE_PATH_2));
+ memcpy(search_update_path, fwname, sizeof(fwname));
+ memcpy(search_cfg_path, CONFIG_FILE_PATH_2, sizeof(CONFIG_FILE_PATH_2));
+ }
+
+ if(!(got_file_flag&0x0F))
+ {
+ update_msg.file = filp_open(search_update_path, O_RDONLY, 0);
+ if(!IS_ERR(update_msg.file))
+ {
+ GTP_DEBUG("Find the bin file");
+ got_file_flag |= 0x0F;
+ }
+ }
+ if(!(got_file_flag&0xF0))
+ {
+ update_msg.cfg_file = filp_open(search_cfg_path, O_RDONLY, 0);
+ if(!IS_ERR(update_msg.cfg_file))
+ {
+ GTP_DEBUG("Find the cfg file");
+ got_file_flag |= 0xF0;
+ }
+ }
+
+ if(got_file_flag)
+ {
+ if(got_file_flag == 0xFF)
+ {
+ break;
+ }
+ else
+ {
+ i += 4;
+ }
+ }
+ GTP_DEBUG("%3d:Searching %s %s file...", i, (got_file_flag&0x0F)?"":"bin", (got_file_flag&0xF0)?"":"cfg");
+ //msleep(3000);
+ }
+ searching_file = 0;
+ kfree(search_update_path);
+ kfree(search_cfg_path);
+
+ if(!got_file_flag)
+ {
+ GTP_ERROR("Can't find update file.");
+ goto load_failed;
+ }
+
+ if(got_file_flag&0xF0)
+ {
+ GTP_DEBUG("Got the update config file.");
+ ret = gup_update_config(client);
+ if(ret <= 0)
+ {
+ GTP_ERROR("Update config failed.");
+ }
+ filp_close(update_msg.cfg_file, NULL);
+ msleep(500); //waiting config to be stored in FLASH.
+ }
+ if(got_file_flag&0x0F)
+ {
+ GTP_DEBUG("Got the update firmware file.");
+ }
+ else
+ {
+ GTP_ERROR("No need to upgrade firmware.");
+ goto load_failed;
+ }
+#endif
+ }
+
+ update_msg.old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ update_msg.file->f_op->llseek(update_msg.file, 0, SEEK_SET);
+ //update_msg.file->f_pos = 0;
+
+ ret = update_msg.file->f_op->read(update_msg.file, (char*)buf, FW_HEAD_LENGTH, &update_msg.file->f_pos);
+ if (ret < 0)
+ {
+ GTP_ERROR("Read firmware head in update file error.");
+ goto load_failed;
+ }
+ memcpy(fw_head, buf, FW_HEAD_LENGTH);
+
+ //check firmware legality
+ fw_checksum = 0;
+ for(i=0; i<FW_SECTION_LENGTH*4+FW_DSP_ISP_LENGTH+FW_DSP_LENGTH+FW_BOOT_LENGTH; i+=2)
+ {
+ u16 temp;
+ ret = update_msg.file->f_op->read(update_msg.file, (char*)buf, 2, &update_msg.file->f_pos);
+ if (ret < 0)
+ {
+ GTP_ERROR("Read firmware file error.");
+ goto load_failed;
+ }
+ //GTP_DEBUG("BUF[0]:%x", buf[0]);
+ temp = (buf[0]<<8) + buf[1];
+ fw_checksum += temp;
+ }
+
+ GTP_DEBUG("firmware checksum:%x", fw_checksum&0xFFFF);
+ if(fw_checksum&0xFFFF)
+ {
+ GTP_ERROR("Illegal firmware file.");
+ goto load_failed;
+ }
+
+ return SUCCESS;
+
+load_failed:
+ set_fs(update_msg.old_fs);
+ return FAIL;
+}
+
+#if 0
+static u8 gup_check_update_header(struct i2c_client *client, st_fw_head* fw_head)
+{
+ const u8* pos;
+ int i = 0;
+ u8 mask_num = 0;
+ s32 ret = 0;
+
+ pos = HEADER_UPDATE_DATA;
+
+ memcpy(fw_head, pos, FW_HEAD_LENGTH);
+ pos += FW_HEAD_LENGTH;
+
+ ret = gup_enter_update_judge(fw_head);
+ if(SUCCESS == ret)
+ {
+ return SUCCESS;
+ }
+ return FAIL;
+}
+#endif
+
+static u8 gup_burn_proc(struct i2c_client *client, u8 *burn_buf, u16 start_addr, u16 total_length)
+{
+ s32 ret = 0;
+ u16 burn_addr = start_addr;
+ u16 frame_length = 0;
+ u16 burn_length = 0;
+ u8 wr_buf[PACK_SIZE + GTP_ADDR_LENGTH];
+ u8 rd_buf[PACK_SIZE + GTP_ADDR_LENGTH];
+ u8 retry = 0;
+
+ GTP_DEBUG("Begin burn %dk data to addr 0x%x", (total_length/1024), start_addr);
+ while(burn_length < total_length)
+ {
+ GTP_DEBUG("B/T:%04d/%04d", burn_length, total_length);
+ frame_length = ((total_length - burn_length) > PACK_SIZE) ? PACK_SIZE : (total_length - burn_length);
+ wr_buf[0] = (u8)(burn_addr>>8);
+ rd_buf[0] = wr_buf[0];
+ wr_buf[1] = (u8)burn_addr;
+ rd_buf[1] = wr_buf[1];
+ memcpy(&wr_buf[GTP_ADDR_LENGTH], &burn_buf[burn_length], frame_length);
+
+ for(retry = 0; retry < MAX_FRAME_CHECK_TIME; retry++)
+ {
+ ret = gup_i2c_write(client, wr_buf, GTP_ADDR_LENGTH + frame_length);
+ if(ret <= 0)
+ {
+ GTP_ERROR("Write frame data i2c error.");
+ continue;
+ }
+ ret = gup_i2c_read(client, rd_buf, GTP_ADDR_LENGTH + frame_length);
+ if(ret <= 0)
+ {
+ GTP_ERROR("Read back frame data i2c error.");
+ continue;
+ }
+
+ if(memcmp(&wr_buf[GTP_ADDR_LENGTH], &rd_buf[GTP_ADDR_LENGTH], frame_length))
+ {
+ GTP_ERROR("Check frame data fail,not equal.");
+ GTP_DEBUG("write array:");
+ GTP_DEBUG_ARRAY(&wr_buf[GTP_ADDR_LENGTH], frame_length);
+ GTP_DEBUG("read array:");
+ GTP_DEBUG_ARRAY(&rd_buf[GTP_ADDR_LENGTH], frame_length);
+ continue;
+ }
+ else
+ {
+ //GTP_DEBUG("Check frame data success.");
+ break;
+ }
+ }
+ if(retry >= MAX_FRAME_CHECK_TIME)
+ {
+ GTP_ERROR("Burn frame data time out,exit.");
+ return FAIL;
+ }
+ burn_length += frame_length;
+ burn_addr += frame_length;
+ }
+ return SUCCESS;
+}
+
+static u8 gup_load_section_file(u8* buf, u16 offset, u16 length)
+{
+ s32 ret = 0;
+
+ if(update_msg.file == NULL)
+ {
+ GTP_ERROR("cannot find update file,load section file fail.");
+ return FAIL;
+ }
+ update_msg.file->f_pos = FW_HEAD_LENGTH + offset;
+
+ ret = update_msg.file->f_op->read(update_msg.file, (char*)buf, length, &update_msg.file->f_pos);
+ if(ret < 0)
+ {
+ GTP_ERROR("Read update file fail.");
+ return FAIL;
+ }
+
+ return SUCCESS;
+}
+
+static u8 gup_recall_check(struct i2c_client *client, u8* chk_src, u16 start_rd_addr, u16 chk_length)
+{
+ u8 rd_buf[PACK_SIZE + GTP_ADDR_LENGTH];
+ s32 ret = 0;
+ u16 recall_addr = start_rd_addr;
+ u16 recall_length = 0;
+ u16 frame_length = 0;
+
+ while(recall_length < chk_length)
+ {
+ frame_length = ((chk_length - recall_length) > PACK_SIZE) ? PACK_SIZE : (chk_length - recall_length);
+ ret = gup_get_ic_msg(client, recall_addr, rd_buf, frame_length);
+ if(ret <= 0)
+ {
+ GTP_ERROR("recall i2c error,exit");
+ return FAIL;
+ }
+
+ if(memcmp(&rd_buf[GTP_ADDR_LENGTH], &chk_src[recall_length], frame_length))
+ {
+ GTP_ERROR("Recall frame data fail,not equal.");
+ GTP_DEBUG("chk_src array:");
+ GTP_DEBUG_ARRAY(&chk_src[recall_length], frame_length);
+ GTP_DEBUG("recall array:");
+ GTP_DEBUG_ARRAY(&rd_buf[GTP_ADDR_LENGTH], frame_length);
+ return FAIL;
+ }
+
+ recall_length += frame_length;
+ recall_addr += frame_length;
+ }
+ GTP_DEBUG("Recall check %dk firmware success.", (chk_length/1024));
+
+ return SUCCESS;
+}
+
+static u8 gup_burn_fw_section(struct i2c_client *client, u8 *fw_section, u16 start_addr, u8 bank_cmd )
+{
+ s32 ret = 0;
+ u8 rd_buf[5];
+
+ //step1:hold ss51 & dsp
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C);
+ if(ret <= 0)
+ {
+ GTP_ERROR("[burn_fw_section]hold ss51 & dsp fail.");
+ return FAIL;
+ }
+
+ //step2:set scramble
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00);
+ if(ret <= 0)
+ {
+ GTP_ERROR("[burn_fw_section]set scramble fail.");
+ return FAIL;
+ }
+
+ //step3:select bank
+ ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, (bank_cmd >> 4)&0x0F);
+ if(ret <= 0)
+ {
+ GTP_ERROR("[burn_fw_section]select bank %d fail.", (bank_cmd >> 4)&0x0F);
+ return FAIL;
+ }
+
+ //step4:enable accessing code
+ ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x01);
+ if(ret <= 0)
+ {
+ GTP_ERROR("[burn_fw_section]enable accessing code fail.");
+ return FAIL;
+ }
+
+ //step5:burn 8k fw section
+ ret = gup_burn_proc(client, fw_section, start_addr, FW_SECTION_LENGTH);
+ if(FAIL == ret)
+ {
+ GTP_ERROR("[burn_fw_section]burn fw_section fail.");
+ return FAIL;
+ }
+
+ //step6:hold ss51 & release dsp
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x04);
+ if(ret <= 0)
+ {
+ GTP_ERROR("[burn_fw_section]hold ss51 & release dsp fail.");
+ return FAIL;
+ }
+ //must delay
+ msleep(1);
+
+ //step7:send burn cmd to move data to flash from sram
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, bank_cmd&0x0f);
+ if(ret <= 0)
+ {
+ GTP_ERROR("[burn_fw_section]send burn cmd fail.");
+ return FAIL;
+ }
+ GTP_DEBUG("[burn_fw_section]Wait for the burn is complete......");
+ do{
+ ret = gup_get_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, rd_buf, 1);
+ if(ret <= 0)
+ {
+ GTP_ERROR("[burn_fw_section]Get burn state fail");
+ return FAIL;
+ }
+ msleep(10);
+ //GTP_DEBUG("[burn_fw_section]Get burn state:%d.", rd_buf[GTP_ADDR_LENGTH]);
+ }while(rd_buf[GTP_ADDR_LENGTH]);
+
+ //step8:select bank
+ ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, (bank_cmd >> 4)&0x0F);
+ if(ret <= 0)
+ {
+ GTP_ERROR("[burn_fw_section]select bank %d fail.", (bank_cmd >> 4)&0x0F);
+ return FAIL;
+ }
+
+ //step9:enable accessing code
+ ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x01);
+ if(ret <= 0)
+ {
+ GTP_ERROR("[burn_fw_section]enable accessing code fail.");
+ return FAIL;
+ }
+
+ //step10:recall 8k fw section
+ ret = gup_recall_check(client, fw_section, start_addr, FW_SECTION_LENGTH);
+ if(FAIL == ret)
+ {
+ GTP_ERROR("[burn_fw_section]recall check 8k firmware fail.");
+ return FAIL;
+ }
+
+ //step11:disable accessing code
+ ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x00);
+ if(ret <= 0)
+ {
+ GTP_ERROR("[burn_fw_section]disable accessing code fail.");
+ return FAIL;
+ }
+
+ return SUCCESS;
+}
+
+static u8 gup_burn_dsp_isp(struct i2c_client *client)
+{
+ s32 ret = 0;
+ u8* fw_dsp_isp = NULL;
+ u8 retry = 0;
+
+ GTP_DEBUG("[burn_dsp_isp]Begin burn dsp isp---->>");
+
+ //step1:alloc memory
+ GTP_DEBUG("[burn_dsp_isp]step1:alloc memory");
+ while(retry++ < 5)
+ {
+ fw_dsp_isp = (u8*)kzalloc(FW_DSP_ISP_LENGTH, GFP_KERNEL);
+ if(fw_dsp_isp == NULL)
+ {
+ continue;
+ }
+ else
+ {
+ GTP_INFO("[burn_dsp_isp]Alloc %dk byte memory success.", (FW_DSP_ISP_LENGTH/1024));
+ break;
+ }
+ }
+ if(retry >= 5)
+ {
+ GTP_ERROR("[burn_dsp_isp]Alloc memory fail,exit.");
+ return FAIL;
+ }
+
+ //step2:load dsp isp file data
+ GTP_DEBUG("[burn_dsp_isp]step2:load dsp isp file data");
+ ret = gup_load_section_file(fw_dsp_isp, (4*FW_SECTION_LENGTH+FW_DSP_LENGTH+FW_BOOT_LENGTH), FW_DSP_ISP_LENGTH);
+ if(FAIL == ret)
+ {
+ GTP_ERROR("[burn_dsp_isp]load firmware dsp_isp fail.");
+ goto exit_burn_dsp_isp;
+ }
+
+ //step3:disable wdt,clear cache enable
+ GTP_DEBUG("[burn_dsp_isp]step3:disable wdt,clear cache enable");
+ ret = gup_set_ic_msg(client, _bRW_MISCTL__TMR0_EN, 0x00);
+ if(ret <= 0)
+ {
+ GTP_ERROR("[burn_dsp_isp]disable wdt fail.");
+ ret = FAIL;
+ goto exit_burn_dsp_isp;
+ }
+ ret = gup_set_ic_msg(client, _bRW_MISCTL__CACHE_EN, 0x00);
+ if(ret <= 0)
+ {
+ GTP_ERROR("[burn_dsp_isp]clear cache enable fail.");
+ ret = FAIL;
+ goto exit_burn_dsp_isp;
+ }
+
+ //step4:hold ss51 & dsp
+ GTP_DEBUG("[burn_dsp_isp]step4:hold ss51 & dsp");
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C);
+ if(ret <= 0)
+ {
+ GTP_ERROR("[burn_dsp_isp]hold ss51 & dsp fail.");
+ ret = FAIL;
+ goto exit_burn_dsp_isp;
+ }
+
+ //step5:set boot from sram
+ GTP_DEBUG("[burn_dsp_isp]step5:set boot from sram");
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOTCTL_B0_, 0x02);
+ if(ret <= 0)
+ {
+ GTP_ERROR("[burn_dsp_isp]set boot from sram fail.");
+ ret = FAIL;
+ goto exit_burn_dsp_isp;
+ }
+
+ //step6:software reboot
+ GTP_DEBUG("[burn_dsp_isp]step6:software reboot");
+ ret = gup_set_ic_msg(client, _bWO_MISCTL__CPU_SWRST_PULSE, 0x01);
+ if(ret <= 0)
+ {
+ GTP_ERROR("[burn_dsp_isp]software reboot fail.");
+ ret = FAIL;
+ goto exit_burn_dsp_isp;
+ }
+
+ //step7:select bank2
+ GTP_DEBUG("[burn_dsp_isp]step7:select bank2");
+ ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, 0x02);
+ if(ret <= 0)
+ {
+ GTP_ERROR("[burn_dsp_isp]select bank2 fail.");
+ ret = FAIL;
+ goto exit_burn_dsp_isp;
+ }
+
+ //step8:enable accessing code
+ GTP_DEBUG("[burn_dsp_isp]step8:enable accessing code");
+ ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x01);
+ if(ret <= 0)
+ {
+ GTP_ERROR("[burn_dsp_isp]enable accessing code fail.");
+ ret = FAIL;
+ goto exit_burn_dsp_isp;
+ }
+
+ //step9:burn 4k dsp_isp
+ GTP_DEBUG("[burn_dsp_isp]step9:burn 4k dsp_isp");
+ ret = gup_burn_proc(client, fw_dsp_isp, 0xC000, FW_DSP_ISP_LENGTH);
+ if(FAIL == ret)
+ {
+ GTP_ERROR("[burn_dsp_isp]burn dsp_isp fail.");
+ goto exit_burn_dsp_isp;
+ }
+
+ //step10:set scramble
+ GTP_DEBUG("[burn_dsp_isp]step10:set scramble");
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00);
+ if(ret <= 0)
+ {
+ GTP_ERROR("[burn_dsp_isp]set scramble fail.");
+ ret = FAIL;
+ goto exit_burn_dsp_isp;
+ }
+ ret = SUCCESS;
+
+exit_burn_dsp_isp:
+ kfree(fw_dsp_isp);
+ return ret;
+}
+
+static u8 gup_burn_fw_ss51(struct i2c_client *client)
+{
+ u8* fw_ss51 = NULL;
+ u8 retry = 0;
+ s32 ret = 0;
+
+ GTP_DEBUG("[burn_fw_ss51]Begin burn ss51 firmware---->>");
+
+ //step1:alloc memory
+ GTP_DEBUG("[burn_fw_ss51]step1:alloc memory");
+ while(retry++ < 5)
+ {
+ fw_ss51 = (u8*)kzalloc(FW_SECTION_LENGTH, GFP_KERNEL);
+ if(fw_ss51 == NULL)
+ {
+ continue;
+ }
+ else
+ {
+ GTP_INFO("[burn_fw_ss51]Alloc %dk byte memory success.", (FW_SECTION_LENGTH/1024));
+ break;
+ }
+ }
+ if(retry >= 5)
+ {
+ GTP_ERROR("[burn_fw_ss51]Alloc memory fail,exit.");
+ return FAIL;
+ }
+
+ //step2:load ss51 firmware section 1 file data
+ GTP_DEBUG("[burn_fw_ss51]step2:load ss51 firmware section 1 file data");
+ ret = gup_load_section_file(fw_ss51, 0, FW_SECTION_LENGTH);
+ if(FAIL == ret)
+ {
+ GTP_ERROR("[burn_fw_ss51]load ss51 firmware section 1 fail.");
+ goto exit_burn_fw_ss51;
+ }
+
+ //step3:clear control flag
+ GTP_DEBUG("[burn_fw_ss51]step3:clear control flag");
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x00);
+ if(ret <= 0)
+ {
+ GTP_ERROR("[burn_fw_ss51]clear control flag fail.");
+ ret = FAIL;
+ goto exit_burn_fw_ss51;
+ }
+
+ //step4:burn ss51 firmware section 1
+ GTP_DEBUG("[burn_fw_ss51]step4:burn ss51 firmware section 1");
+ ret = gup_burn_fw_section(client, fw_ss51, 0xC000, 0x01);
+ if(FAIL == ret)
+ {
+ GTP_ERROR("[burn_fw_ss51]burn ss51 firmware section 1 fail.");
+ goto exit_burn_fw_ss51;
+ }
+
+ //step5:load ss51 firmware section 2 file data
+ GTP_DEBUG("[burn_fw_ss51]step5:load ss51 firmware section 2 file data");
+ ret = gup_load_section_file(fw_ss51, FW_SECTION_LENGTH, FW_SECTION_LENGTH);
+ if(FAIL == ret)
+ {
+ GTP_ERROR("[burn_fw_ss51]load ss51 firmware section 2 fail.");
+ goto exit_burn_fw_ss51;
+ }
+
+ //step6:burn ss51 firmware section 2
+ GTP_DEBUG("[burn_fw_ss51]step6:burn ss51 firmware section 2");
+ ret = gup_burn_fw_section(client, fw_ss51, 0xE000, 0x02);
+ if(FAIL == ret)
+ {
+ GTP_ERROR("[burn_fw_ss51]burn ss51 firmware section 2 fail.");
+ goto exit_burn_fw_ss51;
+ }
+
+ //step7:load ss51 firmware section 3 file data
+ GTP_DEBUG("[burn_fw_ss51]step7:load ss51 firmware section 3 file data");
+ ret = gup_load_section_file(fw_ss51, 2*FW_SECTION_LENGTH, FW_SECTION_LENGTH);
+ if(FAIL == ret)
+ {
+ GTP_ERROR("[burn_fw_ss51]load ss51 firmware section 3 fail.");
+ goto exit_burn_fw_ss51;
+ }
+
+ //step8:burn ss51 firmware section 3
+ GTP_DEBUG("[burn_fw_ss51]step8:burn ss51 firmware section 3");
+ ret = gup_burn_fw_section(client, fw_ss51, 0xC000, 0x13);
+ if(FAIL == ret)
+ {
+ GTP_ERROR("[burn_fw_ss51]burn ss51 firmware section 3 fail.");
+ goto exit_burn_fw_ss51;
+ }
+
+ //step9:load ss51 firmware section 4 file data
+ GTP_DEBUG("[burn_fw_ss51]step9:load ss51 firmware section 4 file data");
+ ret = gup_load_section_file(fw_ss51, 3*FW_SECTION_LENGTH, FW_SECTION_LENGTH);
+ if(FAIL == ret)
+ {
+ GTP_ERROR("[burn_fw_ss51]load ss51 firmware section 4 fail.");
+ goto exit_burn_fw_ss51;
+ }
+
+ //step10:burn ss51 firmware section 4
+ GTP_DEBUG("[burn_fw_ss51]step10:burn ss51 firmware section 4");
+ ret = gup_burn_fw_section(client, fw_ss51, 0xE000, 0x14);
+ if(FAIL == ret)
+ {
+ GTP_ERROR("[burn_fw_ss51]burn ss51 firmware section 4 fail.");
+ goto exit_burn_fw_ss51;
+ }
+
+ ret = SUCCESS;
+
+exit_burn_fw_ss51:
+ kfree(fw_ss51);
+ return ret;
+}
+
+static u8 gup_burn_fw_dsp(struct i2c_client *client)
+{
+ s32 ret = 0;
+ u8* fw_dsp = NULL;
+ u8 retry = 0;
+ u8 rd_buf[5];
+
+ GTP_DEBUG("[burn_fw_dsp]Begin burn dsp firmware---->>");
+ //step1:alloc memory
+ GTP_DEBUG("[burn_fw_dsp]step1:alloc memory");
+ while(retry++ < 5)
+ {
+ fw_dsp = (u8*)kzalloc(FW_DSP_LENGTH, GFP_KERNEL);
+ if(fw_dsp == NULL)
+ {
+ continue;
+ }
+ else
+ {
+ GTP_INFO("[burn_fw_dsp]Alloc %dk byte memory success.", (FW_SECTION_LENGTH/1024));
+ break;
+ }
+ }
+ if(retry >= 5)
+ {
+ GTP_ERROR("[burn_fw_dsp]Alloc memory fail,exit.");
+ return FAIL;
+ }
+
+ //step2:load firmware dsp
+ GTP_DEBUG("[burn_fw_dsp]step2:load firmware dsp");
+ ret = gup_load_section_file(fw_dsp, 4*FW_SECTION_LENGTH, FW_DSP_LENGTH);
+ if(FAIL == ret)
+ {
+ GTP_ERROR("[burn_fw_dsp]load firmware dsp fail.");
+ goto exit_burn_fw_dsp;
+ }
+
+ //step3:select bank3
+ GTP_DEBUG("[burn_fw_dsp]step3:select bank3");
+ ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, 0x03);
+ if(ret <= 0)
+ {
+ GTP_ERROR("[burn_fw_dsp]select bank3 fail.");
+ ret = FAIL;
+ goto exit_burn_fw_dsp;
+ }
+
+ //step4:hold ss51 & dsp
+ GTP_DEBUG("[burn_fw_dsp]step4:hold ss51 & dsp");
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C);
+ if(ret <= 0)
+ {
+ GTP_ERROR("[burn_fw_dsp]hold ss51 & dsp fail.");
+ ret = FAIL;
+ goto exit_burn_fw_dsp;
+ }
+
+ //step5:set scramble
+ GTP_DEBUG("[burn_fw_dsp]step5:set scramble");
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00);
+ if(ret <= 0)
+ {
+ GTP_ERROR("[burn_fw_dsp]set scramble fail.");
+ ret = FAIL;
+ goto exit_burn_fw_dsp;
+ }
+
+ //step6:release ss51 & dsp
+ GTP_DEBUG("[burn_fw_dsp]step6:release ss51 & dsp");
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x04); //20121211
+ if(ret <= 0)
+ {
+ GTP_ERROR("[burn_fw_dsp]release ss51 & dsp fail.");
+ ret = FAIL;
+ goto exit_burn_fw_dsp;
+ }
+ //must delay
+ msleep(1);
+
+ //step7:burn 4k dsp firmware
+ GTP_DEBUG("[burn_fw_dsp]step7:burn 4k dsp firmware");
+ ret = gup_burn_proc(client, fw_dsp, 0x9000, FW_DSP_LENGTH);
+ if(FAIL == ret)
+ {
+ GTP_ERROR("[burn_fw_dsp]burn fw_section fail.");
+ goto exit_burn_fw_dsp;
+ }
+
+ //step8:send burn cmd to move data to flash from sram
+ GTP_DEBUG("[burn_fw_dsp]step8:send burn cmd to move data to flash from sram");
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x05);
+ if(ret <= 0)
+ {
+ GTP_ERROR("[burn_fw_dsp]send burn cmd fail.");
+ goto exit_burn_fw_dsp;
+ }
+ GTP_DEBUG("[burn_fw_dsp]Wait for the burn is complete......");
+ do{
+ ret = gup_get_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, rd_buf, 1);
+ if(ret <= 0)
+ {
+ GTP_ERROR("[burn_fw_dsp]Get burn state fail");
+ goto exit_burn_fw_dsp;
+ }
+ msleep(10);
+ //GTP_DEBUG("[burn_fw_dsp]Get burn state:%d.", rd_buf[GTP_ADDR_LENGTH]);
+ }while(rd_buf[GTP_ADDR_LENGTH]);
+
+ //step9:recall check 4k dsp firmware
+ GTP_DEBUG("[burn_fw_dsp]step9:recall check 4k dsp firmware");
+ ret = gup_recall_check(client, fw_dsp, 0x9000, FW_DSP_LENGTH);
+ if(FAIL == ret)
+ {
+ GTP_ERROR("[burn_fw_dsp]recall check 4k dsp firmware fail.");
+ goto exit_burn_fw_dsp;
+ }
+
+ ret = SUCCESS;
+
+exit_burn_fw_dsp:
+ kfree(fw_dsp);
+ return ret;
+}
+
+static u8 gup_burn_fw_boot(struct i2c_client *client)
+{
+ s32 ret = 0;
+ u8* fw_boot = NULL;
+ u8 retry = 0;
+ u8 rd_buf[5];
+
+ GTP_DEBUG("[burn_fw_boot]Begin burn bootloader firmware---->>");
+
+ //step1:Alloc memory
+ GTP_DEBUG("[burn_fw_boot]step1:Alloc memory");
+ while(retry++ < 5)
+ {
+ fw_boot = (u8*)kzalloc(FW_BOOT_LENGTH, GFP_KERNEL);
+ if(fw_boot == NULL)
+ {
+ continue;
+ }
+ else
+ {
+ GTP_INFO("[burn_fw_boot]Alloc %dk byte memory success.", (FW_BOOT_LENGTH/1024));
+ break;
+ }
+ }
+ if(retry >= 5)
+ {
+ GTP_ERROR("[burn_fw_boot]Alloc memory fail,exit.");
+ return FAIL;
+ }
+
+ //step2:load firmware bootloader
+ GTP_DEBUG("[burn_fw_boot]step2:load firmware bootloader");
+ ret = gup_load_section_file(fw_boot, (4*FW_SECTION_LENGTH+FW_DSP_LENGTH), FW_BOOT_LENGTH);
+ if(FAIL == ret)
+ {
+ GTP_ERROR("[burn_fw_boot]load firmware dsp fail.");
+ goto exit_burn_fw_boot;
+ }
+
+ //step3:hold ss51 & dsp
+ GTP_DEBUG("[burn_fw_boot]step3:hold ss51 & dsp");
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C);
+ if(ret <= 0)
+ {
+ GTP_ERROR("[burn_fw_boot]hold ss51 & dsp fail.");
+ ret = FAIL;
+ goto exit_burn_fw_boot;
+ }
+
+ //step4:set scramble
+ GTP_DEBUG("[burn_fw_boot]step4:set scramble");
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00);
+ if(ret <= 0)
+ {
+ GTP_ERROR("[burn_fw_boot]set scramble fail.");
+ ret = FAIL;
+ goto exit_burn_fw_boot;
+ }
+
+ //step5:release ss51 & dsp
+ GTP_DEBUG("[burn_fw_boot]step5:release ss51 & dsp");
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x04); //20121211
+ if(ret <= 0)
+ {
+ GTP_ERROR("[burn_fw_boot]release ss51 & dsp fail.");
+ ret = FAIL;
+ goto exit_burn_fw_boot;
+ }
+ //must delay
+ msleep(1);
+
+ //step6:select bank3
+ GTP_DEBUG("[burn_fw_boot]step6:select bank3");
+ ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, 0x03);
+ if(ret <= 0)
+ {
+ GTP_ERROR("[burn_fw_boot]select bank3 fail.");
+ ret = FAIL;
+ goto exit_burn_fw_boot;
+ }
+
+ //step7:burn 2k bootloader firmware
+ GTP_DEBUG("[burn_fw_boot]step7:burn 2k bootloader firmware");
+ ret = gup_burn_proc(client, fw_boot, 0x9000, FW_BOOT_LENGTH);
+ if(FAIL == ret)
+ {
+ GTP_ERROR("[burn_fw_boot]burn fw_section fail.");
+ goto exit_burn_fw_boot;
+ }
+
+ //step7:send burn cmd to move data to flash from sram
+ GTP_DEBUG("[burn_fw_boot]step7:send burn cmd to move data to flash from sram");
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x06);
+ if(ret <= 0)
+ {
+ GTP_ERROR("[burn_fw_boot]send burn cmd fail.");
+ goto exit_burn_fw_boot;
+ }
+ GTP_DEBUG("[burn_fw_boot]Wait for the burn is complete......");
+ do{
+ ret = gup_get_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, rd_buf, 1);
+ if(ret <= 0)
+ {
+ GTP_ERROR("[burn_fw_boot]Get burn state fail");
+ goto exit_burn_fw_boot;
+ }
+ msleep(10);
+ //GTP_DEBUG("[burn_fw_boot]Get burn state:%d.", rd_buf[GTP_ADDR_LENGTH]);
+ }while(rd_buf[GTP_ADDR_LENGTH]);
+
+ //step8:recall check 2k bootloader firmware
+ GTP_DEBUG("[burn_fw_boot]step8:recall check 2k bootloader firmware");
+ ret = gup_recall_check(client, fw_boot, 0x9000, FW_BOOT_LENGTH);
+ if(FAIL == ret)
+ {
+ GTP_ERROR("[burn_fw_boot]recall check 4k dsp firmware fail.");
+ goto exit_burn_fw_boot;
+ }
+
+ //step9:enable download DSP code
+ GTP_DEBUG("[burn_fw_boot]step9:enable download DSP code ");
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x99);
+ if(ret <= 0)
+ {
+ GTP_ERROR("[burn_fw_boot]enable download DSP code fail.");
+ ret = FAIL;
+ goto exit_burn_fw_boot;
+ }
+
+ //step10:release ss51 & hold dsp
+ GTP_DEBUG("[burn_fw_boot]step10:release ss51 & hold dsp");
+ ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x08);
+ if(ret <= 0)
+ {
+ GTP_ERROR("[burn_fw_boot]release ss51 & hold dsp fail.");
+ ret = FAIL;
+ goto exit_burn_fw_boot;
+ }
+
+ ret = SUCCESS;
+
+exit_burn_fw_boot:
+ kfree(fw_boot);
+ return ret;
+}
+
+s32 gup_update_proc(void *dir)
+{
+ s32 ret = 0;
+ u8 retry = 0;
+ st_fw_head fw_head;
+ struct goodix_ts_data *ts = NULL;
+
+ GTP_DEBUG("[update_proc]Begin update ......");
+
+ show_len = 1;
+ total_len = 100;
+ if(dir == NULL)
+ {
+ //msleep(3000); //wait main thread to be completed
+ }
+
+ ts = l_ts;
+
+ if (searching_file)
+ {
+ searching_file = 0; // exit .bin update file searching
+ GTP_INFO("Exiting searching .bin update file...");
+ while ((show_len != 200) && (show_len != 100)) // wait for auto update quitted completely
+ {
+ msleep(100);
+ }
+ }
+
+ update_msg.file = NULL;
+ ret = gup_check_update_file(i2c_connect_client, &fw_head, (u8*)dir); //20121211
+ if(FAIL == ret)
+ {
+ GTP_ERROR("[update_proc]check update file fail.");
+ goto file_fail;
+ }
+
+ //gtp_reset_guitar(i2c_connect_client, 20);
+ ret = gup_get_ic_fw_msg(i2c_connect_client);
+ if(FAIL == ret)
+ {
+ GTP_ERROR("[update_proc]get ic message fail.");
+ goto file_fail;
+ }
+
+ ret = gup_enter_update_judge(&fw_head);
+ if(FAIL == ret)
+ {
+ GTP_ERROR("[update_proc]Check *.bin file fail.");
+ goto file_fail;
+ }
+
+ ts->enter_update = 1;
+ gtp_irq_disable(ts);
+#if GTP_ESD_PROTECT
+ gtp_esd_switch(ts->client, SWITCH_OFF);
+#endif
+ ret = gup_enter_update_mode(ts);
+ if(FAIL == ret)
+ {
+ GTP_ERROR("[update_proc]enter update mode fail.");
+ goto update_fail;
+ }
+
+ while(retry++ < 5)
+ {
+ show_len = 10;
+ total_len = 100;
+ ret = gup_burn_dsp_isp(i2c_connect_client);
+ if(FAIL == ret)
+ {
+ GTP_ERROR("[update_proc]burn dsp isp fail.");
+ continue;
+ }
+
+ show_len += 10;
+ ret = gup_burn_fw_ss51(i2c_connect_client);
+ if(FAIL == ret)
+ {
+ GTP_ERROR("[update_proc]burn ss51 firmware fail.");
+ continue;
+ }
+
+ show_len += 40;
+ ret = gup_burn_fw_dsp(i2c_connect_client);
+ if(FAIL == ret)
+ {
+ GTP_ERROR("[update_proc]burn dsp firmware fail.");
+ continue;
+ }
+
+ show_len += 20;
+ ret = gup_burn_fw_boot(i2c_connect_client);
+ if(FAIL == ret)
+ {
+ GTP_ERROR("[update_proc]burn bootloader firmware fail.");
+ continue;
+ }
+ show_len += 10;
+ GTP_INFO("[update_proc]UPDATE SUCCESS.");
+ break;
+ }
+ if(retry >= 5)
+ {
+ GTP_ERROR("[update_proc]retry timeout,UPDATE FAIL.");
+ goto update_fail;
+ }
+
+ GTP_DEBUG("[update_proc]leave update mode.");
+ gup_leave_update_mode(ts);
+
+ msleep(100);
+// GTP_DEBUG("[update_proc]send config.");
+// ret = gtp_send_cfg(i2c_connect_client);
+// if(ret < 0)
+// {
+// GTP_ERROR("[update_proc]send config fail.");
+// }
+ if (ts->fw_error)
+ {
+ GTP_INFO("firmware error auto update, resent config!");
+ gup_init_panel(ts);
+ }
+ show_len = 100;
+ total_len = 100;
+ ts->enter_update = 0;
+ gtp_irq_enable(ts);
+
+#if GTP_ESD_PROTECT
+ gtp_esd_switch(ts->client, SWITCH_ON);
+#endif
+ filp_close(update_msg.file, NULL);
+ return SUCCESS;
+
+update_fail:
+ ts->enter_update = 0;
+ gtp_irq_enable(ts);
+
+#if GTP_ESD_PROTECT
+ gtp_esd_switch(ts->client, SWITCH_ON);
+#endif
+
+file_fail:
+ if(update_msg.file && !IS_ERR(update_msg.file))
+ {
+ filp_close(update_msg.file, NULL);
+ }
+ show_len = 200;
+ total_len = 100;
+ return FAIL;
+}
+
+#if GTP_AUTO_UPDATE
+u8 gup_init_update_proc(struct goodix_ts_data *ts)
+{
+ //struct task_struct *thread = NULL;
+
+ GTP_INFO("Ready to run update thread.");
+ if(!gup_update_proc(NULL))
+ GTP_ERROR("fail to update.");
+ /*thread = kthread_run(gup_update_proc, (void*)NULL, "guitar_update");
+ if (IS_ERR(thread))
+ {
+ GTP_ERROR("Failed to create update thread.\n");
+ return -1;
+ }*/
+
+ return 0;
+}
+#endif
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/icn83xx_ts/Kconfig b/ANDROID_3.4.5/drivers/input/touchscreen/icn83xx_ts/Kconfig
new file mode 100755
index 00000000..dbd6a729
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/icn83xx_ts/Kconfig
@@ -0,0 +1,16 @@
+#
+# ICN83XX capacity touch screen driver configuration
+#
+config TOUCHSCREEN_ICN83XX
+ tristate "ICN83XX I2C Capacitive Touchscreen Input Driver Support"
+ depends on ARCH_WMT
+ default y
+ help
+ Say Y here if you have an WMT based board with touchscreen
+ attached to it.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called s_wmt_ts_icn83xx
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/icn83xx_ts/Makefile b/ANDROID_3.4.5/drivers/input/touchscreen/icn83xx_ts/Makefile
new file mode 100755
index 00000000..e1070854
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/icn83xx_ts/Makefile
@@ -0,0 +1,32 @@
+KERNELDIR=../../../../
+CROSS = arm_1103_le-
+CC= $(CROSS)gcc
+LD= $(CROSS)ld
+STRIP = $(CROSS)strip
+
+DEBUG = n
+
+# Add your debugging flag (or not) to EXTRA_CFLAGS
+ifeq ($(DEBUG),y)
+# DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+DEBFLAGS = -O0 -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+
+else
+ DEBFLAGS = -O2 -Wall
+endif
+
+EXTRA_CFLAGS += $(DEBFLAGS)
+
+
+MY_MODULE_NAME=s_wmt_ts_icn83xx
+
+obj-m := $(MY_MODULE_NAME).o
+$(MY_MODULE_NAME)-objs := icn83xx.o flash.o
+
+default:
+ $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules
+ $(STRIP) --strip-debug $(MY_MODULE_NAME).ko
+ rm -rf *.o *~ core .depend .*.cmd *.mod.c .tmp_versions *.order *.symvers modules.builtin
+
+clean:
+ rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.order *.symvers modules.builtin
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/icn83xx_ts/flash.c b/ANDROID_3.4.5/drivers/input/touchscreen/icn83xx_ts/flash.c
new file mode 100755
index 00000000..595545d8
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/icn83xx_ts/flash.c
@@ -0,0 +1,973 @@
+/*++
+
+ Copyright (c) 2012-2022 ChipOne Technology (Beijing) Co., Ltd. All Rights Reserved.
+ This PROPRIETARY SOFTWARE is the property of ChipOne Technology (Beijing) Co., Ltd.
+ and may contains trade secrets and/or other confidential information of ChipOne
+ Technology (Beijing) Co., Ltd. This file shall not be disclosed to any third party,
+ in whole or in part, without prior written consent of ChipOne.
+ THIS PROPRIETARY SOFTWARE & ANY RELATED DOCUMENTATION ARE PROVIDED AS IS,
+ WITH ALL FAULTS, & WITHOUT WARRANTY OF ANY KIND. CHIPONE DISCLAIMS ALL EXPRESS OR
+ IMPLIED WARRANTIES.
+
+ File Name: flash.c
+ Abstract:
+ flash operation, read write etc.
+ Author: Zhimin Tian
+ Date : 10 30,2012
+ Version: 0.1[.revision]
+ History :
+ Change logs.
+ --*/
+#include "icn83xx.h"
+
+struct file *fp;
+int g_status = R_OK;
+static char fw_mode = 0;
+static int fw_size = 0;
+static unsigned char *fw_buf;
+
+void icn83xx_rawdatadump(short *mem, int size, char br)
+{
+ int i;
+ for(i=0;i<size; i++)
+ {
+ if((i!=0)&&(i%br == 0))
+ printk("\n");
+ printk(" %5d", mem[i]);
+ }
+ printk("\n");
+}
+
+void icn83xx_memdump(char *mem, int size)
+{
+ int i;
+ for(i=0;i<size; i++)
+ {
+ if(i%16 == 0)
+ printk("\n");
+ printk(" 0x%2x", mem[i]);
+ }
+ printk("\n");
+}
+
+int icn83xx_checksum(int sum, char *buf, unsigned int size)
+{
+ int i;
+ for(i=0; i<size; i++)
+ {
+ sum = sum + buf[i];
+ }
+ return sum;
+}
+
+
+int icn83xx_update_status(int status)
+{
+// flash_info("icn83xx_update_status: %d\n", status);
+ g_status = status;
+ return 0;
+}
+
+int icn83xx_get_status(void)
+{
+ return g_status;
+}
+
+void icn83xx_set_fw(int size, unsigned char *buf)
+{
+ fw_size = size;
+ fw_buf = buf;
+
+}
+
+/***********************************************************************************************
+Name : icn83xx_writeInfo
+Input : addr, value
+Output :
+function : write Flash Info
+***********************************************************************************************/
+
+int icn83xx_writeInfo(unsigned short addr, char value)
+{
+ int ret = -1;
+ char temp_buf[3];
+
+ temp_buf[0] = U16HIBYTE(addr);
+ temp_buf[1] = U16LOBYTE(addr);
+ ret = icn83xx_i2c_txdata(230, temp_buf, 2);
+ if (ret < 0) {
+ op_error("%s failed! ret: %d\n", __func__, ret);
+ return -1;
+ }
+ mdelay(2);
+ temp_buf[0] = value;
+ ret = icn83xx_i2c_txdata(232, temp_buf, 1);
+ if (ret < 0) {
+ op_error("%s failed! ret: %d\n", __func__, ret);
+ return -1;
+ }
+ mdelay(5);
+ return 0;
+}
+/***********************************************************************************************
+Name : icn83xx_readInfo
+Input :
+Output :
+function : read Flash info
+***********************************************************************************************/
+
+int icn83xx_readInfo(unsigned short addr, char *value)
+{
+ int ret = -1;
+ char temp_buf[3];
+
+ temp_buf[0] = U16HIBYTE(addr);
+ temp_buf[1] = U16LOBYTE(addr);
+ ret = icn83xx_i2c_txdata(230, temp_buf, 2);
+ if (ret < 0) {
+ op_error("%s failed! ret: %d\n", __func__, ret);
+ return -1;
+ }
+ mdelay(2);
+ ret = icn83xx_i2c_rxdata(232, value, 1);
+ if (ret < 0) {
+ op_error("%s failed! ret: %d\n", __func__, ret);
+ return -1;
+ }
+ mdelay(2);
+ return 0;
+}
+
+/***********************************************************************************************
+Name : icn83xx_writeReg
+Input : addr, value
+Output :
+function : write MCU xdata and reg
+***********************************************************************************************/
+
+int icn83xx_writeReg(unsigned short addr, char value)
+{
+ int ret = -1;
+ char temp_buf[3];
+
+ temp_buf[0] = U16HIBYTE(addr);
+ temp_buf[1] = U16LOBYTE(addr);
+ ret = icn83xx_i2c_txdata(224, temp_buf, 2);
+ if (ret < 0) {
+ op_error("%s failed! ret: %d\n", __func__, ret);
+ return -1;
+ }
+ mdelay(2);
+ temp_buf[0] = value;
+ ret = icn83xx_i2c_txdata(226, temp_buf, 1);
+ if (ret < 0) {
+ op_error("%s failed! ret: %d\n", __func__, ret);
+ return -1;
+ }
+ mdelay(5);
+ return 0;
+}
+/***********************************************************************************************
+Name : icn83xx_readReg
+Input :
+Output :
+function : read MCU xdata and reg
+***********************************************************************************************/
+
+int icn83xx_readReg(unsigned short addr, char *value)
+{
+ int ret = -1;
+ char temp_buf[3];
+
+ temp_buf[0] = U16HIBYTE(addr);
+ temp_buf[1] = U16LOBYTE(addr);
+ ret = icn83xx_i2c_txdata(224, temp_buf, 2);
+ if (ret < 0) {
+ op_error("%s failed! ret: %d\n", __func__, ret);
+ return -1;
+ }
+ mdelay(2);
+
+ ret = icn83xx_i2c_rxdata(226, value, 1);
+ if (ret < 0) {
+ op_error("%s failed! ret: %d\n", __func__, ret);
+ return -1;
+ }
+ mdelay(2);
+ return 0;
+}
+
+/***********************************************************************************************
+Name : icn83xx_open_fw
+Input : *fw
+
+Output : file size
+function : open the fw file, and return total size
+***********************************************************************************************/
+int icn83xx_open_fw( char *fw)
+{
+ int file_size;
+ mm_segment_t fs;
+ struct inode *inode = NULL;
+ if(strcmp(fw, "icn83xx_firmware") == 0)
+ {
+ fw_mode = 1; //use inner array
+ return fw_size;
+ }
+ else
+ {
+ fw_mode = 0; //use file in file system
+ }
+
+ fp = filp_open(fw, O_RDONLY, 0);
+ if (IS_ERR(fp)) {
+ flash_error("read fw file error\n");
+ return -1;
+ }
+ else
+ flash_info("open fw file ok\n");
+
+ inode = fp->f_dentry->d_inode;
+ file_size = inode->i_size;
+ flash_info("file size: %d\n", file_size);
+
+ fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ return file_size;
+
+}
+
+/***********************************************************************************************
+Name : icn83xx_read_fw
+Input : offset
+ length, read length
+ buf, return buffer
+Output :
+function : read data to buffer
+***********************************************************************************************/
+int icn83xx_read_fw(int offset, int length, char *buf)
+{
+ loff_t pos = offset;
+ if(fw_mode == 1)
+ {
+ memcpy(buf, fw_buf+offset, length);
+ }
+ else
+ {
+ vfs_read(fp, buf, length, &pos);
+ }
+// icn83xx_memdump(buf, length);
+ return 0;
+}
+
+
+/***********************************************************************************************
+Name : icn83xx_close_fw
+Input :
+Output :
+function : close file
+***********************************************************************************************/
+int icn83xx_close_fw(void)
+{
+ if(fw_mode == 0)
+ {
+ filp_close(fp, NULL);
+ }
+
+ return 0;
+}
+/***********************************************************************************************
+Name : icn83xx_readVersion
+Input : void
+Output :
+function : return version
+***********************************************************************************************/
+int icn83xx_readVersion(void)
+{
+ int err = 0;
+ char tmp[2];
+ short CurVersion;
+ err = icn83xx_i2c_rxdata(12, tmp, 2);
+ if (err < 0) {
+ calib_error("%s failed: %d\n", __func__, err);
+ return err;
+ }
+ CurVersion = (tmp[0]<<8) | tmp[1];
+ return CurVersion;
+}
+
+/***********************************************************************************************
+Name : icn83xx_changemode
+Input : normal/factory/config
+Output :
+function : change work mode
+***********************************************************************************************/
+int icn83xx_changemode(char mode)
+{
+ char value = 0x0;
+ icn83xx_write_reg(0, mode);
+ mdelay(1);
+ icn83xx_read_reg(1, &value);
+ while(value != 0)
+ {
+ mdelay(1);
+ icn83xx_read_reg(1, &value);
+ }
+// calib_info("icn83xx_changemode ok\n");
+ return 0;
+}
+
+
+/***********************************************************************************************
+Name : icn83xx_readrawdata
+Input : rownum and length
+Output :
+function : read one row rawdata
+***********************************************************************************************/
+
+int icn83xx_readrawdata(char *buffer, char row, char length)
+{
+ int err = 0;
+ int i;
+// calib_info("readrawdata: %d, length: %d\n", row, length);
+ icn83xx_write_reg(3, row);
+ mdelay(1);
+ err = icn83xx_i2c_rxdata(160, buffer, length);
+ if (err < 0) {
+ calib_error("%s failed: %d\n", __func__, err);
+ return err;
+ }
+
+ for(i=0; i<length; i=i+2)
+ {
+ swap_ab(buffer[i], buffer[i+1]);
+ }
+ return err;
+}
+
+/***********************************************************************************************
+Name : icn83xx_scanTP
+Input :
+Output :
+function : scan one frame rawdata
+***********************************************************************************************/
+
+int icn83xx_scanTP(void)
+{
+ char value = 0;
+ icn83xx_write_reg(2, 0x0);
+ mdelay(1);
+ icn83xx_read_reg(2, &value);
+ while(value != 1)
+ {
+ mdelay(1);
+ icn83xx_read_reg(2, &value);
+ }
+// calib_info("icn83xx_scanTP ok\n");
+ return 0;
+}
+
+/***********************************************************************************************
+Name : icn83xx_readTP
+Input : rownum and columnnum
+Output :
+function : read one frame rawdata
+***********************************************************************************************/
+
+int icn83xx_readTP(char row_num, char column_num, char *buffer)
+{
+ int err = 0;
+ int i;
+// calib_info("icn83xx_readTP\n");
+ icn83xx_changemode(1);
+ icn83xx_scanTP();
+ for(i=0; i<row_num; i++)
+ {
+ icn83xx_readrawdata(&buffer[i*16*2], i, column_num*2);
+ }
+ icn83xx_changemode(0);
+ return err;
+}
+
+
+/***********************************************************************************************
+Name : icn83xx_goto_progmode
+Input :
+Output :
+function : change MCU to progmod
+***********************************************************************************************/
+int icn83xx_goto_progmode(void)
+{
+ int ret = -1;
+// char value[64];
+ char regValue = 0;
+
+ flash_info("icn83xx_goto_progmode\n");
+
+ ret = icn83xx_readReg(0x009, &regValue);
+ if(ret != 0)
+ return ret;
+ flash_info("[0x009]: 0x%x\n", regValue);
+
+// open clock
+ if(regValue != 0xDF)
+ {
+ icn83xx_changemode(2);
+ ret = icn83xx_writeReg(0x002, 0x00);
+ if(ret != 0)
+ return ret;
+ ret = icn83xx_writeReg(0x009, 0xDF);
+ if(ret != 0)
+ return ret;
+ ret = icn83xx_writeReg(0x010, 0x00);
+ if(ret != 0)
+ return ret;
+
+ }
+
+/*
+ addr = 0x0;
+ temp_buf[0] = U16HIBYTE(addr);
+ temp_buf[1] = U16LOBYTE(addr);
+ ret = icn83xx_i2c_txdata(230, temp_buf, 2);
+ if (ret < 0) {
+ pr_err("write reg failed! ret: %d\n", ret);
+ return -1;
+ }
+
+ temp_buf[0] = 0xff;
+ ret = icn83xx_i2c_txdata(232, temp_buf, 1);
+ if (ret < 0) {
+ pr_err("write reg failed! ret: %d\n", ret);
+ return -1;
+ }
+*/
+ ret = icn83xx_writeInfo(0x0, 0xff);
+ if(ret != 0)
+ return ret;
+
+/*
+ addr = 0x1;
+ temp_buf[0] = U16HIBYTE(addr);
+ temp_buf[1] = U16LOBYTE(addr);
+ ret = icn83xx_i2c_txdata(230, temp_buf, 2);
+ if (ret < 0) {
+ pr_err("write reg failed! ret: %d\n", ret);
+ return -1;
+ }
+
+ temp_buf[0] = 0xff;
+ ret = icn83xx_i2c_txdata(232, temp_buf, 1);
+ if (ret < 0) {
+ pr_err("write reg failed! ret: %d\n", ret);
+ return -1;
+ }
+*/
+ ret = icn83xx_writeInfo(0x1, 0xff);
+ if(ret != 0)
+ return ret;
+
+ ret = icn83xx_writeInfo(0x10, 0xff);
+ if(ret != 0)
+ return ret;
+
+ ret = icn83xx_writeInfo(0x11, 0xff);
+ if(ret != 0)
+ return ret;
+/*
+ addr = 0xf00;
+ temp_buf[0] = U16HIBYTE(addr);
+ temp_buf[1] = U16LOBYTE(addr);
+ ret = icn83xx_i2c_txdata(224, temp_buf, 2);
+ if (ret < 0) {
+ pr_err("write reg failed! ret: %d\n", ret);
+ return -1;
+ }
+ temp_buf[0] = 0x1;
+ ret = icn83xx_i2c_txdata(226, temp_buf, 1);
+ if (ret < 0) {
+ pr_err("write reg failed! ret: %d\n", ret);
+ return -1;
+ }
+*/
+ ret = icn83xx_writeReg(0xf00, 1);
+ if(ret != 0)
+ return ret;
+ icn83xx_ts_reset();
+ //mdelay(100);
+ msleep(100);
+ return 0;
+}
+
+/***********************************************************************************************
+Name : icn83xx_check_progmod
+Input :
+Output :
+function : check if MCU at progmode or not
+***********************************************************************************************/
+int icn83xx_check_progmod(void)
+{
+ int ret;
+ unsigned char ucTemp = 0x0;
+ ret = icn83xx_prog_i2c_rxdata(0x0, &ucTemp, 1);
+ flash_info("icn83xx_check_progmod: 0x%x\n", ucTemp);
+ if(ret < 0)
+ {
+ flash_error("icn83xx_check_progmod error, ret: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+
+/***********************************************************************************************
+Name : icn83xx_uu
+Input :
+Output :
+function : unlock flash
+***********************************************************************************************/
+int icn83xx_uu(void)
+{
+ unsigned char ucTemp = 0x0;
+ ucTemp = 0x1e;
+ icn83xx_prog_i2c_txdata(0x050a, &ucTemp, 1);
+ ucTemp = 0x10;
+ icn83xx_prog_i2c_txdata(0x050b, &ucTemp, 1);
+ return 0;
+}
+/***********************************************************************************************
+Name : icn83xx_ll
+Input :
+Output :
+function : lock flash
+***********************************************************************************************/
+void icn83xx_ll(void)
+{
+ unsigned char ucTemp = 0x0;
+ ucTemp = 0xcc;
+ icn83xx_prog_i2c_txdata(0x050a, &ucTemp, 1);
+ ucTemp = 0xcc;
+ icn83xx_prog_i2c_txdata(0x050b, &ucTemp, 1);
+}
+
+/***********************************************************************************************
+Name : icn83xx_op1
+Input :
+Output :
+function : erase flash
+***********************************************************************************************/
+
+int icn83xx_op1(char info, unsigned short offset, unsigned int size)
+{
+ int count = 0;
+ unsigned char ucTemp = 0x0;
+ unsigned short uiAddress = 0x0;
+ int i;
+
+ icn83xx_uu();
+ for(i=0; i<size; )
+ {
+ uiAddress = offset + i;
+// flash_info("uiAddress: 0x%x\n", uiAddress);
+ ucTemp = U16LOBYTE(uiAddress);
+ icn83xx_prog_i2c_txdata(0x0502, &ucTemp, 1);
+ ucTemp = U16HIBYTE(uiAddress);
+ icn83xx_prog_i2c_txdata(0x0503, &ucTemp, 1);
+
+ ucTemp = 0x02;
+ icn83xx_prog_i2c_txdata(0x0500, &ucTemp, 1);
+ ucTemp = 0x01;
+ count = 0;
+ while(ucTemp)
+ {
+ icn83xx_prog_i2c_rxdata(0x0501, &ucTemp, 1);
+ count++;
+ if(count > 5000)
+ {
+ flash_error("op1 ucTemp: 0x%x\n", ucTemp);
+ return 1;
+ }
+ }
+ i = i+1024;
+ }
+ icn83xx_ll();
+ return 0;
+}
+
+/***********************************************************************************************
+Name : icn83xx_op2
+Input :
+Output :
+function : progm flash
+***********************************************************************************************/
+int icn83xx_op2(char info, unsigned short offset, unsigned char * buffer, unsigned int size)
+{
+ int count = 0;
+ unsigned int flash_size;
+ unsigned char ucTemp;
+ unsigned short uiAddress;
+ ucTemp = 0x00;
+ uiAddress = 0x1000;
+
+ icn83xx_prog_i2c_txdata(uiAddress, buffer, size);
+
+ icn83xx_uu();
+
+ ucTemp = U16LOBYTE(offset);
+ icn83xx_prog_i2c_txdata(0x0502, &ucTemp, 1);
+ ucTemp = U16HIBYTE(offset);
+ icn83xx_prog_i2c_txdata(0x0503, &ucTemp, 1);
+
+ icn83xx_prog_i2c_txdata(0x0504, (char *)&uiAddress, 2);
+
+
+//ensure size is even
+ if(size%2 != 0)
+ {
+ flash_info("write op size: %d\n", size);
+ flash_size = size+1;
+ }
+ else
+ flash_size = size;
+
+ ucTemp = U16LOBYTE(flash_size);
+ icn83xx_prog_i2c_txdata(0x0506, &ucTemp, 1);
+ ucTemp = U16HIBYTE(flash_size);
+ icn83xx_prog_i2c_txdata(0x0507, &ucTemp, 1);
+ ucTemp = 0x01;
+
+ if(info > 0)
+ ucTemp = 0x01 | (1<<3);
+
+ icn83xx_prog_i2c_txdata(0x0500, &ucTemp, 1); //
+ while(ucTemp)
+ {
+ icn83xx_prog_i2c_rxdata(0x0501, &ucTemp, 1);
+ count++;
+ if(count > 5000)
+ {
+ flash_error("op2 ucTemp: 0x%x\n", ucTemp);
+ return 1;
+ }
+
+ }
+ icn83xx_ll();
+ return 0;
+}
+
+/***********************************************************************************************
+Name : icn83xx_op3
+Input :
+Output :
+function : read flash
+***********************************************************************************************/
+int icn83xx_op3(char info, unsigned short offset, unsigned char * buffer, unsigned int size)
+{
+ int count = 0;
+ unsigned int flash_size;
+ unsigned char ucTemp;
+ unsigned short uiAddress;
+ ucTemp = 0x00;
+ uiAddress = 0x1000;
+ icn83xx_uu();
+ ucTemp = U16LOBYTE(offset);
+ icn83xx_prog_i2c_txdata(0x0502, &ucTemp, 1);
+ ucTemp = U16HIBYTE(offset);
+ icn83xx_prog_i2c_txdata(0x0503, &ucTemp, 1);
+
+ icn83xx_prog_i2c_txdata(0x0504, (unsigned char*)&uiAddress, 2);
+
+//ensure size is even
+ if(size%2 != 0)
+ {
+ flash_info("read op size: %d\n", size);
+ flash_size = size+1;
+ }
+ else
+ flash_size = size;
+
+ ucTemp = U16LOBYTE(flash_size);
+ icn83xx_prog_i2c_txdata(0x0506, &ucTemp, 1);
+
+ ucTemp = U16HIBYTE(flash_size);
+ icn83xx_prog_i2c_txdata(0x0507, &ucTemp, 1);
+ ucTemp = 0x40;
+
+ if(info > 0)
+ ucTemp = 0x40 | (1<<3);
+
+ icn83xx_prog_i2c_txdata(0x0500, &ucTemp, 1);
+ ucTemp = 0x01;
+ while(ucTemp)
+ {
+ icn83xx_prog_i2c_rxdata(0x0501, &ucTemp, 1);
+ count++;
+ if(count > 5000)
+ {
+ flash_error("op3 ucTemp: 0x%x\n", ucTemp);
+ return 1;
+ }
+
+ }
+ icn83xx_ll();
+ icn83xx_prog_i2c_rxdata(uiAddress, buffer, size);
+ return 0;
+}
+
+
+/***********************************************************************************************
+Name : icn83xx_goto_nomalmode
+Input :
+Output :
+function : when prog flash ok, change flash info flag
+***********************************************************************************************/
+int icn83xx_goto_nomalmode(void)
+{
+ int ret = -1;
+ //unsigned short addr = 0;
+ char temp_buf[3];
+
+ flash_info("icn83xx_goto_nomalmode\n");
+ temp_buf[0] = 0x03;
+ icn83xx_prog_i2c_txdata(0x0f00, temp_buf, 1);
+
+ msleep(100);
+/*
+ addr = 0;
+ temp_buf[0] = U16HIBYTE(addr);
+ temp_buf[1] = U16LOBYTE(addr);
+ temp_buf[2] = 0;
+ ret = icn83xx_i2c_txdata(230, temp_buf, 2);
+ if (ret < 0) {
+ pr_err("write reg failed! ret: %d\n", ret);
+ return -1;
+ }
+
+ icn83xx_i2c_rxdata(232, &temp_buf[2], 1);
+ flash_info("temp_buf[2]: 0x%x\n", temp_buf[2]);
+*/
+ ret = icn83xx_readInfo(0, &temp_buf[2]);
+ if(ret != 0)
+ return ret;
+ flash_info("temp_buf[2]: 0x%x\n", temp_buf[2]);
+ if(temp_buf[2] == 0xff)
+ {
+/*
+ addr = 0;
+ temp_buf[0] = U16HIBYTE(addr);
+ temp_buf[1] = U16LOBYTE(addr);
+ ret = icn83xx_i2c_txdata(230, temp_buf, 2);
+ if (ret < 0) {
+ pr_err("write reg failed! ret: %d\n", ret);
+ return -1;
+ }
+ temp_buf[0] = 0x11;
+ ret = icn83xx_i2c_txdata(232, temp_buf, 1);
+ if (ret < 0) {
+ pr_err("write reg failed! ret: %d\n", ret);
+ return -1;
+ }
+*/
+ ret = icn83xx_writeInfo(0, 0x11);
+ if(ret != 0)
+ return ret;
+
+ }
+ return 0;
+}
+
+/***********************************************************************************************
+Name : icn83xx_read_fw_Ver
+Input : fw
+Output :
+function : read fw version
+***********************************************************************************************/
+
+short icn83xx_read_fw_Ver(char *fw)
+{
+ short FWversion;
+ char tmp[2];
+ int file_size;
+ file_size = icn83xx_open_fw(fw);
+ if(file_size < 0)
+ {
+ return -1;
+ }
+ icn83xx_read_fw(0x4000, 2, &tmp[0]);
+
+ icn83xx_close_fw();
+ FWversion = (tmp[0]<<8)|tmp[1];
+// flash_info("FWversion: 0x%x\n", FWversion);
+ return FWversion;
+}
+
+
+
+
+/***********************************************************************************************
+Name : icn83xx_fw_update
+Input : fw
+Output :
+function : upgrade fw
+***********************************************************************************************/
+
+E_UPGRADE_ERR_TYPE icn83xx_fw_update(char *fw)
+{
+ int file_size, last_length;
+ int j, num;
+ int checksum_bak = 0;
+ int checksum = 0;
+ char temp_buf[B_SIZE];
+#ifdef ENABLE_BYTE_CHECK
+ char temp_buf1[B_SIZE];
+#endif
+
+ file_size = icn83xx_open_fw(fw);
+ if(file_size < 0)
+ {
+ icn83xx_update_status(R_FILE_ERR);
+ return R_FILE_ERR;
+ }
+
+ if(icn83xx_goto_progmode() != 0)
+ {
+ if(icn83xx_check_progmod() < 0)
+ {
+ icn83xx_update_status(R_STATE_ERR);
+ icn83xx_close_fw();
+ return R_STATE_ERR;
+ }
+ }
+// msleep(50);
+
+ if(icn83xx_op1(0, 0, file_size) != 0)
+ {
+ flash_error("icn83xx_op1 error\n");
+ icn83xx_update_status(R_ERASE_ERR);
+ icn83xx_close_fw();
+ return R_ERASE_ERR;
+ }
+ icn83xx_update_status(5);
+
+ num = file_size/B_SIZE;
+ for(j=0; j < num; j++)
+ {
+ icn83xx_read_fw(j*B_SIZE, B_SIZE, temp_buf);
+
+// icn83xx_op3(0, j*B_SIZE, temp_buf1, B_SIZE);
+// icn83xx_memdump(temp_buf1, B_SIZE);
+
+ if(icn83xx_op2(0, j*B_SIZE, temp_buf, B_SIZE) != 0)
+ {
+ icn83xx_update_status(R_PROGRAM_ERR);
+ icn83xx_close_fw();
+ return R_PROGRAM_ERR;
+ }
+ checksum_bak = icn83xx_checksum(checksum_bak, temp_buf, B_SIZE);
+
+ icn83xx_update_status(5+(int)(60*j/num));
+ }
+ last_length = file_size - B_SIZE*j;
+ if(last_length > 0)
+ {
+ icn83xx_read_fw(j*B_SIZE, last_length, temp_buf);
+
+// icn83xx_op3(0, j*B_SIZE, temp_buf1, B_SIZE);
+// icn83xx_memdump(temp_buf1, B_SIZE);
+
+ if(icn83xx_op2(0, j*B_SIZE, temp_buf, last_length) != 0)
+ {
+ icn83xx_update_status(R_PROGRAM_ERR);
+ icn83xx_close_fw();
+ return R_PROGRAM_ERR;
+ }
+ checksum_bak = icn83xx_checksum(checksum_bak, temp_buf, last_length);
+ }
+
+ icn83xx_close_fw();
+ icn83xx_update_status(65);
+
+#ifdef ENABLE_BYTE_CHECK
+ file_size = icn83xx_open_fw(fw);
+ num = file_size/B_SIZE;
+#endif
+
+ for(j=0; j < num; j++)
+ {
+
+#ifdef ENABLE_BYTE_CHECK
+ icn83xx_read_fw(j*B_SIZE, B_SIZE, temp_buf1);
+#endif
+ icn83xx_op3(0, j*B_SIZE, temp_buf, B_SIZE);
+ checksum = icn83xx_checksum(checksum, temp_buf, B_SIZE);
+
+#ifdef ENABLE_BYTE_CHECK
+ if(memcmp(temp_buf1, temp_buf, B_SIZE) != 0)
+ {
+ flash_error("cmp error, %d\n", j);
+ icn83xx_memdump(temp_buf1, B_SIZE);
+ icn83xx_memdump(temp_buf, B_SIZE);
+ icn83xx_update_status(R_VERIFY_ERR);
+#ifdef ENABLE_BYTE_CHECK
+ icn83xx_close_fw();
+#endif
+ return R_VERIFY_ERR;
+ //while(1);
+ }
+#endif
+ icn83xx_update_status(65+(int)(30*j/num));
+ }
+
+#ifdef ENABLE_BYTE_CHECK
+ last_length = file_size - B_SIZE*j;
+#endif
+ if(last_length > 0)
+ {
+#ifdef ENABLE_BYTE_CHECK
+ icn83xx_read_fw(j*B_SIZE, last_length, temp_buf1);
+#endif
+ icn83xx_op3(0, j*B_SIZE, temp_buf, last_length);
+ checksum = icn83xx_checksum(checksum, temp_buf, last_length);
+
+#ifdef ENABLE_BYTE_CHECK
+ if(memcmp(temp_buf1, temp_buf, last_length) != 0)
+ {
+ flash_error("cmp error, %d\n", j);
+ icn83xx_memdump(temp_buf1, last_length);
+ icn83xx_memdump(temp_buf, last_length);
+ icn83xx_update_status(R_VERIFY_ERR);
+#ifdef ENABLE_BYTE_CHECK
+ icn83xx_close_fw();
+#endif
+ return R_VERIFY_ERR;
+ //while(1);
+ }
+#endif
+
+ }
+
+#ifdef ENABLE_BYTE_CHECK
+ icn83xx_close_fw();
+#endif
+
+ flash_info("checksum_bak: 0x%x, checksum: 0x%x\n", checksum_bak, checksum);
+ if(checksum_bak != checksum)
+ {
+ flash_error("upgrade checksum error\n");
+ icn83xx_update_status(R_VERIFY_ERR);
+ return R_VERIFY_ERR;
+ }
+
+ if(icn83xx_goto_nomalmode() != 0)
+ {
+ flash_error("icn83xx_goto_nomalmode error\n");
+ icn83xx_update_status(R_STATE_ERR);
+ return R_STATE_ERR;
+ }
+
+ icn83xx_update_status(R_OK);
+ flash_info("upgrade ok\n");
+ return R_OK;
+}
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/icn83xx_ts/icn83xx.c b/ANDROID_3.4.5/drivers/input/touchscreen/icn83xx_ts/icn83xx.c
new file mode 100755
index 00000000..60e42e50
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/icn83xx_ts/icn83xx.c
@@ -0,0 +1,2034 @@
+/*++
+
+ Copyright (c) 2012-2022 ChipOne Technology (Beijing) Co., Ltd. All Rights Reserved.
+ This PROPRIETARY SOFTWARE is the property of ChipOne Technology (Beijing) Co., Ltd.
+ and may contains trade secrets and/or other confidential information of ChipOne
+ Technology (Beijing) Co., Ltd. This file shall not be disclosed to any third party,
+ in whole or in part, without prior written consent of ChipOne.
+ THIS PROPRIETARY SOFTWARE & ANY RELATED DOCUMENTATION ARE PROVIDED AS IS,
+ WITH ALL FAULTS, & WITHOUT WARRANTY OF ANY KIND. CHIPONE DISCLAIMS ALL EXPRESS OR
+ IMPLIED WARRANTIES.
+
+ File Name: icn83xx.c
+Abstract:
+input driver.
+Author: Zhimin Tian
+Date : 01,17,2013
+Version: 1.0
+History :
+2012,10,30, V0.1 first version
+--*/
+
+#include "icn83xx.h"
+
+#if COMPILE_FW_WITH_DRIVER
+#include "icn83xx_fw.h"
+#endif
+
+static struct touch_param g_param;
+static struct i2c_client *this_client;
+short log_rawdata[28][16];// = {0,};
+short log_diffdata[28][16];// = {0,};
+static int l_suspend = 0; // 1:suspend, 0:normal state
+
+#if SUPPORT_ROCKCHIP
+//if file system not ready,you can use inner array
+//static char firmware[128] = "icn83xx_firmware";
+#endif
+static char firmware[128] = {"/system/etc/firmware/fw.bin"};
+
+//static void icn_delayedwork_fun(struct work_struct *work);
+extern int register_bl_notifier(struct notifier_block *nb);
+extern int unregister_bl_notifier(struct notifier_block *nb);
+extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
+
+#define dbg(fmt, args...) do{if (g_param.dbg) printk(KERN_ALERT "[%s]: " fmt, __FUNCTION__ , ## args);}while(0)
+
+static ssize_t cat_dbg(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "echo 1 > dbg : print debug message.\necho 0 > dbg : Do not print debug message.\n");
+}
+static ssize_t echo_dbg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ g_param.dbg = simple_strtoul(buf, NULL, 10) ? 1 : 0;
+ return count;
+}
+static DEVICE_ATTR(dbg, S_IRUGO | S_IWUSR, cat_dbg, echo_dbg);
+
+#if SUPPORT_SYSFS
+static enum hrtimer_restart chipone_timer_func(struct hrtimer *timer);
+static ssize_t icn83xx_show_update(struct device* cd,struct device_attribute *attr, char* buf);
+static ssize_t icn83xx_store_update(struct device* cd, struct device_attribute *attr, const char* buf, size_t len);
+static ssize_t icn83xx_show_process(struct device* cd,struct device_attribute *attr, char* buf);
+static ssize_t icn83xx_store_process(struct device* cd, struct device_attribute *attr,const char* buf, size_t len);
+
+static DEVICE_ATTR(update, S_IRUGO | S_IWUSR, icn83xx_show_update, icn83xx_store_update);
+static DEVICE_ATTR(process, S_IRUGO | S_IWUSR, icn83xx_show_process, icn83xx_store_process);
+
+static ssize_t icn83xx_show_process(struct device* cd,struct device_attribute *attr, char* buf)
+{
+ ssize_t ret = 0;
+ sprintf(buf, "icn83xx process\n");
+ ret = strlen(buf) + 1;
+ return ret;
+}
+
+static ssize_t icn83xx_store_process(struct device* cd, struct device_attribute *attr,
+ const char* buf, size_t len)
+{
+ struct icn83xx_ts_data *icn83xx_ts = i2c_get_clientdata(this_client);
+ unsigned long on_off = simple_strtoul(buf, NULL, 10);
+ if(on_off == 0)
+ {
+ icn83xx_ts->work_mode = on_off;
+ }
+ else if((on_off == 1) || (on_off == 2))
+ {
+ if((icn83xx_ts->work_mode == 0) && (icn83xx_ts->use_irq == 1))
+ {
+ hrtimer_init(&icn83xx_ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ icn83xx_ts->timer.function = chipone_timer_func;
+ hrtimer_start(&icn83xx_ts->timer, ktime_set(CTP_START_TIMER/1000, (CTP_START_TIMER%1000)*1000000), HRTIMER_MODE_REL);
+ }
+ icn83xx_ts->work_mode = on_off;
+ }
+ return len;
+}
+
+static ssize_t icn83xx_show_update(struct device* cd,
+ struct device_attribute *attr, char* buf)
+{
+ ssize_t ret = 0;
+ sprintf(buf, "icn83xx firmware\n");
+ ret = strlen(buf) + 1;
+ return ret;
+}
+
+static ssize_t icn83xx_store_update(struct device* cd, struct device_attribute *attr, const char* buf, size_t len)
+{
+ //int err=0;
+ //unsigned long on_off = simple_strtoul(buf, NULL, 10);
+ return len;
+}
+
+static int icn83xx_create_sysfs(struct i2c_client *client)
+{
+ int err;
+ struct device *dev = &(client->dev);
+ icn83xx_trace("%s: \n",__func__);
+ err = device_create_file(dev, &dev_attr_update);
+ err = device_create_file(dev, &dev_attr_process);
+ return err;
+}
+
+#endif
+
+#if SUPPORT_PROC_FS
+
+pack_head cmd_head;
+static struct proc_dir_entry *icn83xx_proc_entry;
+int DATA_LENGTH = 0;
+static int icn83xx_tool_write(struct file *filp, const char __user *buff, unsigned long len, void *data)
+{
+ int ret = 0;
+
+ struct icn83xx_ts_data *icn83xx_ts = i2c_get_clientdata(this_client);
+ proc_info("%s \n",__func__);
+ if(down_interruptible(&icn83xx_ts->sem))
+ {
+ return -1;
+ }
+ ret = copy_from_user(&cmd_head, buff, CMD_HEAD_LENGTH);
+ if(ret)
+ {
+ proc_error("copy_from_user failed.\n");
+ goto write_out;
+ }
+ else
+ {
+ ret = CMD_HEAD_LENGTH;
+ }
+
+ proc_info("wr :0x%02x.\n", cmd_head.wr);
+ proc_info("flag:0x%02x.\n", cmd_head.flag);
+ proc_info("circle :%d.\n", (int)cmd_head.circle);
+ proc_info("times :%d.\n", (int)cmd_head.times);
+ proc_info("retry :%d.\n", (int)cmd_head.retry);
+ proc_info("data len:%d.\n", (int)cmd_head.data_len);
+ proc_info("addr len:%d.\n", (int)cmd_head.addr_len);
+ proc_info("addr:0x%02x%02x.\n", cmd_head.addr[0], cmd_head.addr[1]);
+ proc_info("len:%d.\n", (int)len);
+ proc_info("data:0x%02x%02x.\n", buff[CMD_HEAD_LENGTH], buff[CMD_HEAD_LENGTH+1]);
+ if (1 == cmd_head.wr) // write iic
+ {
+ if(1 == cmd_head.addr_len)
+ {
+ ret = copy_from_user(&cmd_head.data[0], &buff[CMD_HEAD_LENGTH], cmd_head.data_len);
+ if(ret)
+ {
+ proc_error("copy_from_user failed.\n");
+ goto write_out;
+ }
+ ret = icn83xx_i2c_txdata(cmd_head.addr[0], &cmd_head.data[0], cmd_head.data_len);
+ if (ret < 0) {
+ proc_error("write iic failed! ret: %d\n", ret);
+ goto write_out;
+ }
+ ret = cmd_head.data_len + CMD_HEAD_LENGTH;
+ goto write_out;
+ }
+ }
+ else if(3 == cmd_head.wr)
+ {
+ ret = copy_from_user(&cmd_head.data[0], &buff[CMD_HEAD_LENGTH], cmd_head.data_len);
+ if(ret)
+ {
+ proc_error("copy_from_user failed.\n");
+ goto write_out;
+ }
+ ret = cmd_head.data_len + CMD_HEAD_LENGTH;
+ memset(firmware, 0, 128);
+ memcpy(firmware, &cmd_head.data[0], cmd_head.data_len);
+ proc_info("firmware : %s\n", firmware);
+ }
+ else if(5 == cmd_head.wr)
+ {
+ icn83xx_update_status(1);
+ ret = kernel_thread((int (*)(void *))icn83xx_fw_update,firmware,CLONE_KERNEL);
+ icn83xx_trace("the kernel_thread result is:%d\n", ret);
+ }
+ else if(7 == cmd_head.wr) //write reg
+ {
+ if(2 == cmd_head.addr_len)
+ {
+ ret = copy_from_user(&cmd_head.data[0], &buff[CMD_HEAD_LENGTH], cmd_head.data_len);
+ if(ret)
+ {
+ proc_error("copy_from_user failed.\n");
+ goto write_out;
+ }
+ ret = icn83xx_writeReg((cmd_head.addr[0]<<8)|cmd_head.addr[1], cmd_head.data[0]);
+ if (ret < 0) {
+ proc_error("write reg failed! ret: %d\n", ret);
+ goto write_out;
+ }
+ ret = cmd_head.data_len + CMD_HEAD_LENGTH;
+ goto write_out;
+
+ }
+ }
+
+write_out:
+ up(&icn83xx_ts->sem);
+ return len;
+
+}
+static int icn83xx_tool_read( char *page, char **start, off_t off, int count, int *eof, void *data )
+{
+ int i;
+ int ret = 0;
+ int data_len = 0;
+ int len = 0;
+ int loc = 0;
+ char retvalue;
+ struct icn83xx_ts_data *icn83xx_ts = i2c_get_clientdata(this_client);
+ if(down_interruptible(&icn83xx_ts->sem))
+ {
+ return -1;
+ }
+ proc_info("%s: count:%d, off:%d, cmd_head.data_len: %d\n",__func__, count, (int)off, cmd_head.data_len);
+ if (cmd_head.wr % 2)
+ {
+ ret = 0;
+ goto read_out;
+ }
+ else if (0 == cmd_head.wr) //read iic
+ {
+ if(1 == cmd_head.addr_len)
+ {
+ data_len = cmd_head.data_len;
+ if(cmd_head.addr[0] == 0xff)
+ {
+ page[0] = 83;
+ proc_info("read ic type: %d\n", page[0]);
+ }
+ else
+ {
+ while(data_len>0)
+ {
+ if (data_len > DATA_LENGTH)
+ {
+ len = DATA_LENGTH;
+ }
+ else
+ {
+ len = data_len;
+ }
+ data_len -= len;
+ memset(&cmd_head.data[0], 0, len+1);
+ ret = icn83xx_i2c_rxdata(cmd_head.addr[0]+loc, &cmd_head.data[0], len);
+ //proc_info("cmd_head.data[0]: 0x%02x\n", cmd_head.data[0]);
+ //proc_info("cmd_head.data[1]: 0x%02x\n", cmd_head.data[1]);
+ if(ret < 0)
+ {
+ icn83xx_error("read iic failed: %d\n", ret);
+ goto read_out;
+ }
+ else
+ {
+ //proc_info("iic read out %d bytes, loc: %d\n", len, loc);
+ memcpy(&page[loc], &cmd_head.data[0], len);
+ }
+ loc += len;
+ }
+ proc_info("page[0]: 0x%02x\n", page[0]);
+ proc_info("page[1]: 0x%02x\n", page[1]);
+ }
+ }
+ }
+ else if(2 == cmd_head.wr) //read rawdata
+ {
+ //scan tp rawdata
+ icn83xx_write_reg(4, 0x20);
+ mdelay(cmd_head.times);
+ icn83xx_read_reg(2, &retvalue);
+ while(retvalue != 1)
+ {
+ mdelay(cmd_head.times);
+ icn83xx_read_reg(2, &retvalue);
+ }
+
+ if(2 == cmd_head.addr_len)
+ {
+ for(i=0; i<cmd_head.addr[1]; i++)
+ {
+ icn83xx_write_reg(3, i);
+ mdelay(cmd_head.times);
+ ret = icn83xx_i2c_rxdata(128, &cmd_head.data[0], cmd_head.addr[0]*2);
+ if (ret < 0)
+ {
+ icn83xx_error("read rawdata failed: %d\n", ret);
+ goto read_out;
+ }
+ else
+ {
+ //proc_info("read rawdata out %d bytes, loc: %d\n", cmd_head.addr[0]*2, loc);
+ memcpy(&page[loc], &cmd_head.data[0], cmd_head.addr[0]*2);
+ }
+ loc += cmd_head.addr[0]*2;
+ }
+ for(i=0; i<cmd_head.data_len; i=i+2)
+ {
+ swap_ab(page[i], page[i+1]);
+ }
+ //icn83xx_rawdatadump(&page[0], cmd_head.data_len/2, cmd_head.addr[0]);
+ }
+
+ //finish scan tp rawdata
+ icn83xx_write_reg(2, 0x0);
+
+ }
+ else if(4 == cmd_head.wr) //get update status
+ {
+ page[0] = icn83xx_get_status();
+ }
+ else if(6 == cmd_head.wr) //read reg
+ {
+ if(2 == cmd_head.addr_len)
+ {
+ ret = icn83xx_readReg((cmd_head.addr[0]<<8)|cmd_head.addr[1], &cmd_head.data[0]);
+ if (ret < 0) {
+ proc_error("reg reg failed! ret: %d\n", ret);
+ goto read_out;
+ }
+ page[0] = cmd_head.data[0];
+ goto read_out;
+ }
+ }
+read_out:
+ up(&icn83xx_ts->sem);
+ proc_info("%s out: %d, cmd_head.data_len: %d\n\n",__func__, count, cmd_head.data_len);
+ return cmd_head.data_len;
+}
+
+int init_proc_node(void)
+{
+ int i;
+ memset(&cmd_head, 0, sizeof(cmd_head));
+ cmd_head.data = NULL;
+
+ i = 5;
+ while ((!cmd_head.data) && i)
+ {
+ cmd_head.data = kzalloc(i * DATA_LENGTH_UINT, GFP_KERNEL);
+ if (NULL != cmd_head.data)
+ {
+ break;
+ }
+ i--;
+ }
+ if (i)
+ {
+ //DATA_LENGTH = i * DATA_LENGTH_UINT + GTP_ADDR_LENGTH;
+ DATA_LENGTH = i * DATA_LENGTH_UINT;
+ icn83xx_trace("alloc memory size:%d.\n", DATA_LENGTH);
+ }
+ else
+ {
+ proc_error("alloc for memory failed.\n");
+ return 0;
+ }
+
+ icn83xx_proc_entry = create_proc_entry(ICN83XX_ENTRY_NAME, 0666, NULL);
+ if (icn83xx_proc_entry == NULL)
+ {
+ proc_error("Couldn't create proc entry!\n");
+ return 0;
+ }
+ else
+ {
+ icn83xx_trace("Create proc entry success!\n");
+ icn83xx_proc_entry->write_proc = icn83xx_tool_write;
+ icn83xx_proc_entry->read_proc = icn83xx_tool_read;
+ }
+
+ return 1;
+}
+
+void uninit_proc_node(void)
+{
+ kfree(cmd_head.data);
+ cmd_head.data = NULL;
+ remove_proc_entry(ICN83XX_ENTRY_NAME, NULL);
+}
+
+#endif
+
+
+#if TOUCH_VIRTUAL_KEYS
+static ssize_t virtual_keys_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ return sprintf(buf,
+ __stringify(EV_KEY) ":" __stringify(KEY_MENU) ":100:1030:50:60"
+ ":" __stringify(EV_KEY) ":" __stringify(KEY_HOME) ":280:1030:50:60"
+ ":" __stringify(EV_KEY) ":" __stringify(KEY_BACK) ":470:1030:50:60"
+ ":" __stringify(EV_KEY) ":" __stringify(KEY_SEARCH) ":900:1030:50:60"
+ "\n");
+}
+
+static struct kobj_attribute virtual_keys_attr = {
+ .attr = {
+ .name = "virtualkeys.chipone-ts",
+ .mode = S_IRUGO,
+ },
+ .show = &virtual_keys_show,
+};
+
+static struct attribute *properties_attrs[] = {
+ &virtual_keys_attr.attr,
+ NULL
+};
+
+static struct attribute_group properties_attr_group = {
+ .attrs = properties_attrs,
+};
+
+static void icn83xx_ts_virtual_keys_init(void)
+{
+ int ret = 0;
+ struct kobject *properties_kobj;
+ properties_kobj = kobject_create_and_add("board_properties", NULL);
+ if (properties_kobj)
+ ret = sysfs_create_group(properties_kobj,
+ &properties_attr_group);
+ if (!properties_kobj || ret)
+ pr_err("failed to create board_properties\n");
+}
+#endif
+
+
+/* ---------------------------------------------------------------------
+ *
+ * Chipone panel related driver
+ *
+ *
+ ----------------------------------------------------------------------*/
+/***********************************************************************************************
+Name : icn83xx_ts_wakeup
+Input : void
+Output : ret
+function : this function is used to wakeup tp
+ ***********************************************************************************************/
+void icn83xx_ts_wakeup(void)
+{
+ //#if def TOUCH_RESET_PIN
+
+}
+
+/***********************************************************************************************
+Name : icn83xx_ts_reset
+Input : void
+Output : ret
+function : this function is used to reset tp, you should not delete it
+ ***********************************************************************************************/
+void icn83xx_ts_reset(void)
+{
+ int rst = g_param.rstgpio;
+ gpio_direction_output(rst, 0);
+ //mdelay(30);
+ msleep(50);
+ gpio_direction_output(rst, 1);
+ //mdelay(50);
+ msleep(50);
+
+}
+
+/***********************************************************************************************
+Name : icn83xx_irq_disable
+Input : void
+Output : ret
+function : this function is used to disable irq
+ ***********************************************************************************************/
+void icn83xx_irq_disable(void)
+{
+ unsigned long irqflags;
+ struct icn83xx_ts_data *icn83xx_ts = i2c_get_clientdata(this_client);
+
+ spin_lock_irqsave(&icn83xx_ts->irq_lock, irqflags);
+ if (!icn83xx_ts->irq_is_disable)
+ {
+ icn83xx_ts->irq_is_disable = 1;
+ wmt_gpio_mask_irq(g_param.irqgpio);
+ //disable_irq_nosync(icn83xx_ts->irq);
+ //disable_irq(icn83xx_ts->irq);
+ }
+ spin_unlock_irqrestore(&icn83xx_ts->irq_lock, irqflags);
+}
+
+/***********************************************************************************************
+Name : icn83xx_irq_enable
+Input : void
+Output : ret
+function : this function is used to enable irq
+ ***********************************************************************************************/
+void icn83xx_irq_enable(void)
+{
+ unsigned long irqflags = 0;
+ struct icn83xx_ts_data *icn83xx_ts = i2c_get_clientdata(this_client);
+
+ spin_lock_irqsave(&icn83xx_ts->irq_lock, irqflags);
+ if (icn83xx_ts->irq_is_disable)
+ {
+ wmt_gpio_unmask_irq(g_param.irqgpio);
+ //enable_irq(icn83xx_ts->irq);
+ icn83xx_ts->irq_is_disable = 0;
+ }
+ spin_unlock_irqrestore(&icn83xx_ts->irq_lock, irqflags);
+
+}
+
+/***********************************************************************************************
+Name : icn83xx_prog_i2c_rxdata
+Input : addr
+ *rxdata
+ length
+Output : ret
+function : read data from icn83xx, prog mode
+ ***********************************************************************************************/
+int icn83xx_prog_i2c_rxdata(unsigned short addr, char *rxdata, int length)
+{
+ int ret = -1;
+ int retries = 0;
+#if 0
+ struct i2c_msg msgs[] = {
+ {
+ .addr = ICN83XX_PROG_IIC_ADDR,//this_client->addr,
+ .flags = I2C_M_RD,
+ .len = length,
+ .buf = rxdata,
+#if SUPPORT_ROCKCHIP
+ .scl_rate = ICN83XX_I2C_SCL,
+#endif
+ },
+ };
+
+ icn83xx_prog_i2c_txdata(addr, NULL, 0);
+ while(retries < IIC_RETRY_NUM)
+ {
+ ret = i2c_transfer(this_client->adapter, msgs, 1);
+ if(ret == 1)break;
+ retries++;
+ }
+ if (retries >= IIC_RETRY_NUM)
+ {
+ icn83xx_error("%s i2c read error: %d\n", __func__, ret);
+ // icn83xx_ts_reset();
+ }
+#else
+ unsigned char tmp_buf[2];
+ struct i2c_msg msgs[] = {
+ {
+ .addr = ICN83XX_PROG_IIC_ADDR,//this_client->addr,
+ .flags = 0,
+ .len = 2,
+ .buf = tmp_buf,
+#if SUPPORT_ROCKCHIP
+ .scl_rate = ICN83XX_I2C_SCL,
+#endif
+ },
+ {
+ .addr = ICN83XX_PROG_IIC_ADDR,//this_client->addr,
+ .flags = I2C_M_RD,
+ .len = length,
+ .buf = rxdata,
+#if SUPPORT_ROCKCHIP
+ .scl_rate = ICN83XX_I2C_SCL,
+#endif
+ },
+ };
+ tmp_buf[0] = U16HIBYTE(addr);
+ tmp_buf[1] = U16LOBYTE(addr);
+
+ while(retries < IIC_RETRY_NUM)
+ {
+ ret = i2c_transfer(this_client->adapter, msgs, 2);
+ if(ret == 2)break;
+ retries++;
+ }
+
+ if (retries >= IIC_RETRY_NUM)
+ {
+ icn83xx_error("%s i2c read error: %d\n", __func__, ret);
+ // icn83xx_ts_reset();
+ }
+#endif
+ return ret;
+}
+/***********************************************************************************************
+Name : icn83xx_prog_i2c_txdata
+Input : addr
+ *rxdata
+ length
+Output : ret
+function : send data to icn83xx , prog mode
+ ***********************************************************************************************/
+int icn83xx_prog_i2c_txdata(unsigned short addr, char *txdata, int length)
+{
+ int ret = -1;
+ char tmp_buf[128];
+ int retries = 0;
+ struct i2c_msg msg[] = {
+ {
+ .addr = ICN83XX_PROG_IIC_ADDR,//this_client->addr,
+ .flags = 0,
+ .len = length + 2,
+ .buf = tmp_buf,
+#if SUPPORT_ROCKCHIP
+ .scl_rate = ICN83XX_I2C_SCL,
+#endif
+ },
+ };
+
+ if (length > 125)
+ {
+ icn83xx_error("%s too big datalen = %d!\n", __func__, length);
+ return -1;
+ }
+
+ tmp_buf[0] = U16HIBYTE(addr);
+ tmp_buf[1] = U16LOBYTE(addr);
+
+ if (length != 0 && txdata != NULL)
+ {
+ memcpy(&tmp_buf[2], txdata, length);
+ }
+
+ while(retries < IIC_RETRY_NUM)
+ {
+ ret = i2c_transfer(this_client->adapter, msg, 1);
+ if(ret == 1)break;
+ retries++;
+ }
+
+ if (retries >= IIC_RETRY_NUM)
+ {
+ icn83xx_error("%s i2c write error: %d\n", __func__, ret);
+ // icn83xx_ts_reset();
+ }
+ return ret;
+}
+/***********************************************************************************************
+Name : icn83xx_prog_write_reg
+Input : addr -- address
+para -- parameter
+Output :
+function : write register of icn83xx, prog mode
+ ***********************************************************************************************/
+int icn83xx_prog_write_reg(unsigned short addr, char para)
+{
+ char buf[3];
+ int ret = -1;
+
+ buf[0] = para;
+ ret = icn83xx_prog_i2c_txdata(addr, buf, 1);
+ if (ret < 0) {
+ icn83xx_error("write reg failed! %#x ret: %d\n", buf[0], ret);
+ return -1;
+ }
+
+ return ret;
+}
+
+
+/***********************************************************************************************
+Name : icn83xx_prog_read_reg
+Input : addr
+pdata
+Output :
+function : read register of icn83xx, prog mode
+ ***********************************************************************************************/
+int icn83xx_prog_read_reg(unsigned short addr, char *pdata)
+{
+ int ret = -1;
+ ret = icn83xx_prog_i2c_rxdata(addr, pdata, 1);
+ return ret;
+}
+
+/***********************************************************************************************
+Name : icn83xx_i2c_rxdata
+Input : addr
+ *rxdata
+ length
+Output : ret
+function : read data from icn83xx, normal mode
+ ***********************************************************************************************/
+int icn83xx_i2c_rxdata(unsigned char addr, char *rxdata, int length)
+{
+ int ret = -1;
+ int retries = 0;
+#if 0
+ struct i2c_msg msgs[] = {
+ {
+ .addr = this_client->addr,
+ .flags = I2C_M_RD,
+ .len = length,
+ .buf = rxdata,
+#if SUPPORT_ROCKCHIP
+ .scl_rate = ICN83XX_I2C_SCL,
+#endif
+ },
+ };
+
+ icn83xx_i2c_txdata(addr, NULL, 0);
+ while(retries < IIC_RETRY_NUM)
+ {
+
+ ret = i2c_transfer(this_client->adapter, msgs, 1);
+ if(ret == 1)break;
+ retries++;
+ }
+
+ if (retries >= IIC_RETRY_NUM)
+ {
+ icn83xx_error("%s i2c read error: %d\n", __func__, ret);
+ // icn83xx_ts_reset();
+ }
+
+#else
+ unsigned char tmp_buf[1];
+ struct i2c_msg msgs[] = {
+ {
+ .addr = this_client->addr,
+ .flags = 0,
+ .len = 1,
+ .buf = tmp_buf,
+#if SUPPORT_ROCKCHIP
+ .scl_rate = ICN83XX_I2C_SCL,
+#endif
+ },
+ {
+ .addr = this_client->addr,
+ .flags = I2C_M_RD,
+ .len = length,
+ .buf = rxdata,
+#if SUPPORT_ROCKCHIP
+ .scl_rate = ICN83XX_I2C_SCL,
+#endif
+ },
+ };
+ tmp_buf[0] = addr;
+
+ while(retries < IIC_RETRY_NUM)
+ {
+ ret = i2c_transfer(this_client->adapter, msgs, 2);
+ if(ret == 2)break;
+ retries++;
+ }
+
+ if (retries >= IIC_RETRY_NUM)
+ {
+ icn83xx_error("%s i2c read error: %d\n", __func__, ret);
+ icn83xx_ts_reset();
+ }
+#endif
+
+ return ret;
+}
+/***********************************************************************************************
+Name : icn83xx_i2c_txdata
+Input : addr
+ *rxdata
+ length
+Output : ret
+function : send data to icn83xx , normal mode
+ ***********************************************************************************************/
+int icn83xx_i2c_txdata(unsigned char addr, char *txdata, int length)
+{
+ int ret = -1;
+ unsigned char tmp_buf[128];
+ int retries = 0;
+
+ struct i2c_msg msg[] = {
+ {
+ .addr = this_client->addr,
+ .flags = 0,
+ .len = length + 1,
+ .buf = tmp_buf,
+#if SUPPORT_ROCKCHIP
+ .scl_rate = ICN83XX_I2C_SCL,
+#endif
+ },
+ };
+
+ if (length > 125)
+ {
+ icn83xx_error("%s too big datalen = %d!\n", __func__, length);
+ return -1;
+ }
+
+ tmp_buf[0] = addr;
+
+ if (length != 0 && txdata != NULL)
+ {
+ memcpy(&tmp_buf[1], txdata, length);
+ }
+
+ while(retries < IIC_RETRY_NUM)
+ {
+ ret = i2c_transfer(this_client->adapter, msg, 1);
+ if(ret == 1)break;
+ retries++;
+ }
+
+ if (retries >= IIC_RETRY_NUM)
+ {
+ icn83xx_error("%s i2c write error: %d\n", __func__, ret);
+ icn83xx_ts_reset();
+ }
+
+ return ret;
+}
+
+/***********************************************************************************************
+Name : icn83xx_write_reg
+Input : addr -- address
+para -- parameter
+Output :
+function : write register of icn83xx, normal mode
+ ***********************************************************************************************/
+int icn83xx_write_reg(unsigned char addr, char para)
+{
+ char buf[3];
+ int ret = -1;
+
+ buf[0] = para;
+ ret = icn83xx_i2c_txdata(addr, buf, 1);
+ if (ret < 0) {
+ icn83xx_error("write reg failed! %#x ret: %d\n", buf[0], ret);
+ return -1;
+ }
+
+ return ret;
+}
+
+
+/***********************************************************************************************
+Name : icn83xx_read_reg
+Input : addr
+pdata
+Output :
+function : read register of icn83xx, normal mode
+ ***********************************************************************************************/
+int icn83xx_read_reg(unsigned char addr, char *pdata)
+{
+ int ret = -1;
+ ret = icn83xx_i2c_rxdata(addr, pdata, 1);
+ return ret;
+}
+
+#if SUPPORT_FW_UPDATE
+/***********************************************************************************************
+Name : icn83xx_log
+Input : 0: rawdata, 1: diff data
+Output : err type
+function : calibrate param
+ ***********************************************************************************************/
+void icn83xx_log(char diff)
+{
+ char row = 0;
+ char column = 0;
+ int i, j;
+ icn83xx_read_reg(160, &row);
+ icn83xx_read_reg(161, &column);
+
+ if(diff == 1)
+ {
+ icn83xx_readTP(row, column, (char *)&log_diffdata[0][0]);
+
+ for(i=0; i<row; i++)
+ {
+ for(j=0; j<column; j++)
+ {
+ log_diffdata[i][j] = log_diffdata[i][j] - log_rawdata[i][j];
+ }
+ }
+ icn83xx_rawdatadump(&log_diffdata[0][0], row*16, 16);
+ }
+ else
+ {
+ icn83xx_readTP(row, column, (char *)&log_rawdata[0][0]);
+ icn83xx_rawdatadump(&log_rawdata[0][0], row*16, 16);
+ }
+}
+#endif
+
+/***********************************************************************************************
+Name : icn83xx_iic_test
+Input : void
+Output :
+function : 0 success,
+ ***********************************************************************************************/
+static int icn83xx_iic_test(void)
+{
+ int ret = -1;
+ char value = 0;
+ int retry = 0;
+ while(retry++ < 3)
+ {
+ ret = icn83xx_read_reg(0, &value);
+ if(ret > 0)
+ {
+ return ret;
+ }
+ icn83xx_error("iic test error! %d\n", retry);
+ msleep(3);
+ }
+ return ret;
+}
+
+/***********************************************************************************************
+Name : icn83xx_report_value_B
+Input : void
+Output :
+function : reprot touch ponit
+ ***********************************************************************************************/
+#if CTP_REPORT_PROTOCOL
+static int icn83xx_report_value_B(void)
+{
+ struct icn83xx_ts_data *icn83xx_ts = i2c_get_clientdata(this_client);
+ char buf[POINT_NUM*POINT_SIZE+3]={0};
+ static unsigned char finger_last[POINT_NUM + 1]={0};
+ unsigned char finger_current[POINT_NUM + 1] = {0};
+ unsigned int position = 0;
+ int temp = 0;
+ int ret = -1;
+ int x,y;
+ icn83xx_info("==icn83xx_report_value_B ==\n");
+ // icn83xx_trace("==icn83xx_report_value_B ==\n");
+ ret = icn83xx_i2c_rxdata(16, buf, POINT_NUM*POINT_SIZE+2);
+ if (ret < 0) {
+ icn83xx_error("%s read_data i2c_rxdata failed: %d\n", __func__, ret);
+ return ret;
+ }
+
+ icn83xx_ts->point_num = buf[1];
+ if (icn83xx_ts->point_num > 5) {
+ printk("error point_num : %d\n",icn83xx_ts->point_num);
+ return -1;
+ }
+ if(icn83xx_ts->point_num > 0)
+ {
+ for(position = 0; position<icn83xx_ts->point_num; position++)
+ {
+ temp = buf[2 + POINT_SIZE*position] + 1;
+ finger_current[temp] = 1;
+ icn83xx_ts->point_info[temp].u8ID = buf[2 + POINT_SIZE*position];
+ icn83xx_ts->point_info[temp].u16PosX = (buf[3 + POINT_SIZE*position]<<8) + buf[4 + POINT_SIZE*position];
+ icn83xx_ts->point_info[temp].u16PosY = (buf[5 + POINT_SIZE*position]<<8) + buf[6 + POINT_SIZE*position];
+ icn83xx_ts->point_info[temp].u8Pressure = buf[7 + POINT_SIZE*position];
+ icn83xx_ts->point_info[temp].u8EventId = buf[8 + POINT_SIZE*position];
+
+ if(icn83xx_ts->point_info[temp].u8EventId == 4)
+ finger_current[temp] = 0;
+
+ if(1 == icn83xx_ts->revert_x_flag)
+ {
+ icn83xx_ts->point_info[temp].u16PosX = icn83xx_ts->screen_max_x- icn83xx_ts->point_info[temp].u16PosX;
+ }
+ if(1 == icn83xx_ts->revert_y_flag)
+ {
+ icn83xx_ts->point_info[temp].u16PosY = icn83xx_ts->screen_max_y- icn83xx_ts->point_info[temp].u16PosY;
+ }
+ icn83xx_info("temp %d\n", temp);
+ icn83xx_info("u8ID %d\n", icn83xx_ts->point_info[temp].u8ID);
+ icn83xx_info("u16PosX %d\n", icn83xx_ts->point_info[temp].u16PosX);
+ icn83xx_info("u16PosY %d\n", icn83xx_ts->point_info[temp].u16PosY);
+ icn83xx_info("u8Pressure %d\n", icn83xx_ts->point_info[temp].u8Pressure);
+ icn83xx_info("u8EventId %d\n", icn83xx_ts->point_info[temp].u8EventId);
+ //icn83xx_info("u8Pressure %d\n", icn83xx_ts->point_info[temp].u8Pressure*16);
+ }
+ }
+ else
+ {
+ for(position = 1; position < POINT_NUM+1; position++)
+ {
+ finger_current[position] = 0;
+ }
+ icn83xx_info("no touch\n");
+ }
+
+ for(position = 1; position < POINT_NUM + 1; position++)
+ {
+ if((finger_current[position] == 0) && (finger_last[position] != 0))
+ {
+ input_mt_slot(icn83xx_ts->input_dev, position-1);
+ input_mt_report_slot_state(icn83xx_ts->input_dev, MT_TOOL_FINGER, false);
+ icn83xx_point_info("one touch up: %d\n", position);
+ }
+ else if(finger_current[position])
+ {
+ if (g_param.xyswap == 0)
+ {
+ x = icn83xx_ts->point_info[position].u16PosX;
+ y = icn83xx_ts->point_info[position].u16PosY;
+ } else {
+ y = icn83xx_ts->point_info[position].u16PosX;
+ x = icn83xx_ts->point_info[position].u16PosY;
+ }
+ if (g_param.xdir == -1)
+ {
+ x = g_param.panelres_x - x;
+ }
+ if (g_param.ydir == -1)
+ {
+ y = g_param.panelres_y - y;
+ }
+
+ if (g_param.lcd_exchg) {
+ int tmp;
+ tmp = x;
+ x = y;
+ y = g_param.panelres_x - tmp;
+ }
+
+ input_mt_slot(icn83xx_ts->input_dev, position-1);
+ input_mt_report_slot_state(icn83xx_ts->input_dev, MT_TOOL_FINGER, true);
+ input_report_abs(icn83xx_ts->input_dev, ABS_MT_TOUCH_MAJOR, 1);
+ //input_report_abs(icn83xx_ts->input_dev, ABS_MT_PRESSURE, icn83xx_ts->point_info[position].u8Pressure);
+ input_report_abs(icn83xx_ts->input_dev, ABS_MT_PRESSURE, 200);
+ input_report_abs(icn83xx_ts->input_dev, ABS_MT_POSITION_X, x);
+ input_report_abs(icn83xx_ts->input_dev, ABS_MT_POSITION_Y, y);
+ icn83xx_point_info("===position: %d, x = %d,y = %d, press = %d ====\n", position, icn83xx_ts->point_info[position].u16PosX,icn83xx_ts->point_info[position].u16PosY, icn83xx_ts->point_info[position].u8Pressure);
+ // icn83xx_trace("===position: %d, x = %d,y = %d, press = %d ====\n", position, icn83xx_ts->point_info[position].u16PosX,icn83xx_ts->point_info[position].u16PosY, icn83xx_ts->point_info[position].u8Pressure);
+ dbg("raw%d(%d,%d), rpt%d(%d,%d)\n", position, icn83xx_ts->point_info[position].u16PosX, icn83xx_ts->point_info[position].u16PosY, position, x, y);
+ }
+
+ }
+ input_sync(icn83xx_ts->input_dev);
+
+ for(position = 1; position < POINT_NUM + 1; position++)
+ {
+ finger_last[position] = finger_current[position];
+ }
+ return 0;
+}
+
+#else
+
+/***********************************************************************************************
+Name : icn83xx_ts_release
+Input : void
+Output :
+function : touch release
+ ***********************************************************************************************/
+static void icn83xx_ts_release(void)
+{
+ struct icn83xx_ts_data *icn83xx_ts = i2c_get_clientdata(this_client);
+ icn83xx_info("==icn83xx_ts_release ==\n");
+ input_report_abs(icn83xx_ts->input_dev, ABS_MT_TOUCH_MAJOR, 0);
+ input_sync(icn83xx_ts->input_dev);
+}
+
+/***********************************************************************************************
+Name : icn83xx_report_value_A
+Input : void
+Output :
+function : reprot touch ponit
+ ***********************************************************************************************/
+static int icn83xx_report_value_A(void)
+{
+ struct icn83xx_ts_data *icn83xx_ts = i2c_get_clientdata(this_client);
+ char buf[POINT_NUM*POINT_SIZE+3]={0};
+ int ret = -1;
+ int i;
+#if TOUCH_VIRTUAL_KEYS
+ unsigned char button;
+ static unsigned char button_last;
+#endif
+ icn83xx_info("==icn83xx_report_value_A ==\n");
+
+ ret = icn83xx_i2c_rxdata(16, buf, POINT_NUM*POINT_SIZE+2);
+ if (ret < 0) {
+ icn83xx_error("%s read_data i2c_rxdata failed: %d\n", __func__, ret);
+ return ret;
+ }
+#if TOUCH_VIRTUAL_KEYS
+ button = buf[0];
+ icn83xx_info("%s: button=%d\n",__func__, button);
+
+ if((button_last != 0) && (button == 0))
+ {
+ icn83xx_ts_release();
+ button_last = button;
+ return 1;
+ }
+ if(button != 0)
+ {
+ switch(button)
+ {
+ case ICN_VIRTUAL_BUTTON_HOME:
+ icn83xx_info("ICN_VIRTUAL_BUTTON_HOME down\n");
+ input_report_abs(icn83xx_ts->input_dev, ABS_MT_TOUCH_MAJOR, 200);
+ input_report_abs(icn83xx_ts->input_dev, ABS_MT_POSITION_X, 280);
+ input_report_abs(icn83xx_ts->input_dev, ABS_MT_POSITION_Y, 1030);
+ input_report_abs(icn83xx_ts->input_dev, ABS_MT_WIDTH_MAJOR, 1);
+ input_mt_sync(icn83xx_ts->input_dev);
+ input_sync(icn83xx_ts->input_dev);
+ break;
+ case ICN_VIRTUAL_BUTTON_BACK:
+ icn83xx_info("ICN_VIRTUAL_BUTTON_BACK down\n");
+ input_report_abs(icn83xx_ts->input_dev, ABS_MT_TOUCH_MAJOR, 200);
+ input_report_abs(icn83xx_ts->input_dev, ABS_MT_POSITION_X, 470);
+ input_report_abs(icn83xx_ts->input_dev, ABS_MT_POSITION_Y, 1030);
+ input_report_abs(icn83xx_ts->input_dev, ABS_MT_WIDTH_MAJOR, 1);
+ input_mt_sync(icn83xx_ts->input_dev);
+ input_sync(icn83xx_ts->input_dev);
+ break;
+ case ICN_VIRTUAL_BUTTON_MENU:
+ icn83xx_info("ICN_VIRTUAL_BUTTON_MENU down\n");
+ input_report_abs(icn83xx_ts->input_dev, ABS_MT_TOUCH_MAJOR, 200);
+ input_report_abs(icn83xx_ts->input_dev, ABS_MT_POSITION_X, 100);
+ input_report_abs(icn83xx_ts->input_dev, ABS_MT_POSITION_Y, 1030);
+ input_report_abs(icn83xx_ts->input_dev, ABS_MT_WIDTH_MAJOR, 1);
+ input_mt_sync(icn83xx_ts->input_dev);
+ input_sync(icn83xx_ts->input_dev);
+ break;
+ default:
+ icn83xx_info("other gesture\n");
+ break;
+ }
+ button_last = button;
+ return 1;
+ }
+#endif
+
+ icn83xx_ts->point_num = buf[1];
+ if (icn83xx_ts->point_num == 0) {
+ icn83xx_ts_release();
+ return 1;
+ }
+ for(i=0;i<icn83xx_ts->point_num;i++){
+ if(buf[8 + POINT_SIZE*i] != 4) break ;
+ }
+
+ if(i == icn83xx_ts->point_num) {
+ icn83xx_ts_release();
+ return 1;
+ }
+
+ for(i=0; i<icn83xx_ts->point_num; i++)
+ {
+ icn83xx_ts->point_info[i].u8ID = buf[2 + POINT_SIZE*i];
+ icn83xx_ts->point_info[i].u16PosX = (buf[3 + POINT_SIZE*i]<<8) + buf[4 + POINT_SIZE*i];
+ icn83xx_ts->point_info[i].u16PosY = (buf[5 + POINT_SIZE*i]<<8) + buf[6 + POINT_SIZE*i];
+ icn83xx_ts->point_info[i].u8Pressure = 200;//buf[7 + POINT_SIZE*i];
+ icn83xx_ts->point_info[i].u8EventId = buf[8 + POINT_SIZE*i];
+
+ if(1 == icn83xx_ts->revert_x_flag)
+ {
+ icn83xx_ts->point_info[i].u16PosX = icn83xx_ts->screen_max_x- icn83xx_ts->point_info[i].u16PosX;
+ }
+ if(1 == icn83xx_ts->revert_y_flag)
+ {
+ icn83xx_ts->point_info[i].u16PosY = icn83xx_ts->screen_max_y- icn83xx_ts->point_info[i].u16PosY;
+ }
+
+ icn83xx_info("u8ID %d\n", icn83xx_ts->point_info[i].u8ID);
+ icn83xx_info("u16PosX %d\n", icn83xx_ts->point_info[i].u16PosX);
+ icn83xx_info("u16PosY %d\n", icn83xx_ts->point_info[i].u16PosY);
+ icn83xx_info("u8Pressure %d\n", icn83xx_ts->point_info[i].u8Pressure);
+ icn83xx_info("u8EventId %d\n", icn83xx_ts->point_info[i].u8EventId);
+
+
+ input_report_abs(icn83xx_ts->input_dev, ABS_MT_TRACKING_ID, icn83xx_ts->point_info[i].u8ID);
+ input_report_abs(icn83xx_ts->input_dev, ABS_MT_TOUCH_MAJOR, icn83xx_ts->point_info[i].u8Pressure);
+ input_report_abs(icn83xx_ts->input_dev, ABS_MT_POSITION_X, icn83xx_ts->point_info[i].u16PosX);
+ input_report_abs(icn83xx_ts->input_dev, ABS_MT_POSITION_Y, icn83xx_ts->point_info[i].u16PosY);
+ input_report_abs(icn83xx_ts->input_dev, ABS_MT_WIDTH_MAJOR, 1);
+ input_mt_sync(icn83xx_ts->input_dev);
+ icn83xx_point_info("point: %d ===x = %d,y = %d, press = %d ====\n",i, icn83xx_ts->point_info[i].u16PosX,icn83xx_ts->point_info[i].u16PosY, icn83xx_ts->point_info[i].u8Pressure);
+ }
+
+ input_sync(icn83xx_ts->input_dev);
+ return 0;
+}
+#endif
+
+/***********************************************************************************************
+Name : icn83xx_ts_pen_irq_work
+Input : void
+Output :
+function : work_struct
+ ***********************************************************************************************/
+static void icn83xx_ts_pen_irq_work(struct work_struct *work)
+{
+ struct icn83xx_ts_data *icn83xx_ts = i2c_get_clientdata(this_client);
+#if SUPPORT_PROC_FS
+ if(down_interruptible(&icn83xx_ts->sem))
+ {
+ return;
+ }
+#endif
+
+ if(icn83xx_ts->work_mode == 0)
+ {
+#if CTP_REPORT_PROTOCOL
+ icn83xx_report_value_B();
+#else
+ icn83xx_report_value_A();
+#endif
+
+ }
+#if SUPPORT_FW_UPDATE
+ else if(icn83xx_ts->work_mode == 1)
+ {
+ printk("log raw data\n");
+ icn83xx_log(0); //raw data
+ }
+ else if(icn83xx_ts->work_mode == 2)
+ {
+ printk("log diff data\n");
+ icn83xx_log(1); //diff data
+ }
+#endif
+
+#if SUPPORT_PROC_FS
+ up(&icn83xx_ts->sem);
+#endif
+ wmt_gpio_unmask_irq(g_param.irqgpio);
+
+}
+/***********************************************************************************************
+Name : chipone_timer_func
+Input : void
+Output :
+function : Timer interrupt service routine.
+ ***********************************************************************************************/
+static enum hrtimer_restart chipone_timer_func(struct hrtimer *timer)
+{
+ struct icn83xx_ts_data *icn83xx_ts = container_of(timer, struct icn83xx_ts_data, timer);
+ queue_work(icn83xx_ts->ts_workqueue, &icn83xx_ts->pen_event_work);
+
+ if(icn83xx_ts->use_irq == 1)
+ {
+ if((icn83xx_ts->work_mode == 1) || (icn83xx_ts->work_mode == 2))
+ {
+ hrtimer_start(&icn83xx_ts->timer, ktime_set(CTP_POLL_TIMER/1000, (CTP_POLL_TIMER%1000)*1000000), HRTIMER_MODE_REL);
+ }
+ }
+ else
+ {
+ hrtimer_start(&icn83xx_ts->timer, ktime_set(CTP_POLL_TIMER/1000, (CTP_POLL_TIMER%1000)*1000000), HRTIMER_MODE_REL);
+ }
+ return HRTIMER_NORESTART;
+}
+/***********************************************************************************************
+Name : icn83xx_ts_interrupt
+Input : void
+Output :
+function : interrupt service routine
+ ***********************************************************************************************/
+static irqreturn_t icn83xx_ts_interrupt(int irq, void *dev_id)
+{
+ struct icn83xx_ts_data *icn83xx_ts = dev_id;
+ int irqindex = g_param.irqgpio;
+
+ icn83xx_info("==========------icn83xx_ts TS Interrupt-----============\n");
+ if (gpio_irqstatus(irqindex)) {
+ wmt_gpio_ack_irq(irqindex);
+ if (is_gpio_irqenable(irqindex) && l_suspend == 0) {
+ wmt_gpio_mask_irq(irqindex);
+ if(icn83xx_ts->work_mode != 0) {
+ wmt_gpio_unmask_irq(irqindex);
+ return IRQ_HANDLED;
+ }
+ //icn83xx_irq_disable();
+ if (!work_pending(&icn83xx_ts->pen_event_work)) {
+ //icn83xx_info("Enter work\n");
+ queue_work(icn83xx_ts->ts_workqueue, &icn83xx_ts->pen_event_work);
+ }
+ }
+ return IRQ_HANDLED;
+ }
+ return IRQ_NONE;
+}
+
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+/***********************************************************************************************
+Name : icn83xx_ts_suspend
+Input : void
+Output :
+function : tp enter sleep mode
+ ***********************************************************************************************/
+static void icn83xx_ts_early_suspend(struct early_suspend *handler)
+{
+ int retry = 0;
+ struct icn83xx_ts_data *icn83xx_ts = i2c_get_clientdata(this_client);
+ icn83xx_trace("icn83xx_ts_suspend: write ICN83XX_REG_PMODE .\n");
+ if (icn83xx_ts->use_irq)
+ {
+ icn83xx_irq_disable();
+ icn83xx_trace("icn83xx_ts_suspend:disable irq .\n");
+ }
+ else
+ {
+ hrtimer_cancel(&icn83xx_ts->timer);
+ }
+ for(retry = 0;retry <3; retry++ )
+ {
+ icn83xx_write_reg(ICN83XX_REG_PMODE, PMODE_HIBERNATE);
+ }
+}
+
+/***********************************************************************************************
+Name : icn83xx_ts_resume
+Input : void
+Output :
+function : wakeup tp or reset tp
+ ***********************************************************************************************/
+static void icn83xx_ts_late_resume(struct early_suspend *handler)
+{
+ struct icn83xx_ts_data *icn83xx_ts = i2c_get_clientdata(this_client);
+ int i;
+ printk("==icn83xx_ts_resume== \n");
+ // icn83xx_ts_reset();
+ //report touch release
+#if CTP_REPORT_PROTOCOL
+ for(i = 0; i < POINT_NUM; i++)
+ {
+ input_mt_slot(icn83xx_ts->input_dev, i);
+ input_mt_report_slot_state(icn83xx_ts->input_dev, MT_TOOL_FINGER, false);
+ }
+#else
+ icn83xx_ts_release();
+#endif
+ icn83xx_ts_wakeup();
+ icn83xx_ts_reset();
+ if (icn83xx_ts->use_irq)
+ {
+ printk("icn83xx_irq_enable\n");
+ icn83xx_irq_enable();
+ }
+ else
+ { printk("icn83xx_ts_resume hrtimer_start\n");
+ hrtimer_start(&icn83xx_ts->timer, ktime_set(CTP_START_TIMER/1000, (CTP_START_TIMER%1000)*1000000), HRTIMER_MODE_REL);
+ }
+
+}
+#endif
+
+#ifdef CONFIG_PM
+/***********************************************************************************************
+Name : icn83xx_ts_suspend
+Input : void
+Output :
+function : tp enter sleep mode
+ ***********************************************************************************************/
+static int icn83xx_ts_suspend(struct device *pdev)
+{
+ //int retry = 0;
+ struct icn83xx_ts_data *icn83xx_ts = i2c_get_clientdata(this_client);
+ icn83xx_trace("icn83xx_ts_suspend: write ICN83XX_REG_PMODE .\n");
+ if (icn83xx_ts->use_irq)
+ {
+ icn83xx_irq_disable();
+ icn83xx_trace("icn83xx_ts_suspend:disable irq .\n");
+ }
+ else
+ {
+ hrtimer_cancel(&icn83xx_ts->timer);
+ }
+ /*for(retry = 0;retry <3; retry++ )
+ {
+ icn83xx_write_reg(ICN83XX_REG_PMODE, PMODE_HIBERNATE);
+ } */
+ l_suspend = 1;
+ return 0;
+}
+
+/***********************************************************************************************
+Name : icn83xx_ts_resume
+Input : void
+Output :
+function : wakeup tp or reset tp
+ ***********************************************************************************************/
+static int icn83xx_ts_resume(struct device *pdev)
+{
+ struct icn83xx_ts_data *icn83xx_ts = i2c_get_clientdata(this_client);
+ int i;
+ printk("==icn83xx_ts_resume== \n");
+ // icn83xx_ts_reset();
+ //report touch release
+#if CTP_REPORT_PROTOCOL
+ for(i = 0; i < POINT_NUM; i++)
+ {
+ input_mt_slot(icn83xx_ts->input_dev, i);
+ input_mt_report_slot_state(icn83xx_ts->input_dev, MT_TOOL_FINGER, false);
+ }
+#else
+ icn83xx_ts_release();
+#endif
+ //icn83xx_ts_wakeup();
+ icn83xx_ts_reset();
+ l_suspend = 0;
+ if (icn83xx_ts->use_irq)
+ {
+ printk("icn83xx_irq_enable\n");
+ icn83xx_irq_enable();
+ }
+ else
+ { printk("icn83xx_ts_resume hrtimer_start\n");
+ hrtimer_start(&icn83xx_ts->timer, ktime_set(CTP_START_TIMER/1000, (CTP_START_TIMER%1000)*1000000), HRTIMER_MODE_REL);
+ }
+ return 0;
+}
+#else
+#define icn83xx_ts_suspend NULL
+#define icn83xx_ts_resume NULL
+#endif
+
+/***********************************************************************************************
+Name : icn83xx_request_io_port
+Input : void
+Output :
+function : 0 success,
+ ***********************************************************************************************/
+static int icn83xx_request_io_port(struct icn83xx_ts_data *icn83xx_ts)
+{
+#if SUPPORT_ROCKCHIP
+ icn83xx_ts->screen_max_x = SCREEN_MAX_X;
+ icn83xx_ts->screen_max_y = SCREEN_MAX_Y;
+ icn83xx_ts->irq = CTP_IRQ_PORT;
+#endif
+ icn83xx_ts->irq = IRQ_GPIO;
+
+ if (gpio_request(g_param.rstgpio, "ts_rst") < 0) {
+ printk("gpio(%d) touchscreen reset request fail\n", g_param.rstgpio);
+ return -EIO;
+ }
+ gpio_direction_output(g_param.rstgpio, 1);
+
+ if (gpio_request(g_param.irqgpio, "ts_irq") < 0) {
+ printk("gpio(%d) touchscreen interrupt request fail\n", g_param.irqgpio);
+ gpio_free(g_param.rstgpio);
+ return -EIO;
+ }
+ wmt_gpio_setpull(g_param.irqgpio, WMT_GPIO_PULL_UP);
+ gpio_direction_input(g_param.irqgpio);
+
+ return 0;
+}
+
+/***********************************************************************************************
+Name : icn83xx_free_io_port
+Input : void
+Output :
+function : 0 success,
+ ***********************************************************************************************/
+static void icn83xx_free_io_port(void)
+{
+ gpio_free(g_param.rstgpio);
+ gpio_free(g_param.irqgpio);
+}
+
+/***********************************************************************************************
+Name : icn83xx_request_irq
+Input : void
+Output :
+function : 0 success,
+ ***********************************************************************************************/
+static int icn83xx_request_irq(struct icn83xx_ts_data *icn83xx_ts)
+{
+ int err = -1;
+
+ /*err = gpio_request(icn83xx_ts->irq, "TS_INT"); //Request IO
+ if (err < 0)
+ {
+ icn83xx_error("Failed to request GPIO:%d, ERRNO:%d\n", (int)icn83xx_ts->irq, err);
+ return err;
+ }
+ gpio_direction_input(icn83xx_ts->irq);*/
+
+ wmt_gpio_set_irq_type(g_param.irqgpio, IRQ_TYPE_EDGE_FALLING);
+ err = request_irq(icn83xx_ts->irq, icn83xx_ts_interrupt, IRQF_SHARED, "icn83xx_ts", icn83xx_ts);
+ if (err < 0)
+ {
+ icn83xx_error("icn83xx_ts_probe: request irq failed\n");
+ return err;
+ }
+ else
+ {
+ icn83xx_irq_disable();
+ icn83xx_ts->use_irq = 1;
+ }
+
+ return 0;
+}
+
+
+/***********************************************************************************************
+Name : icn83xx_free_irq
+Input : void
+Output :
+function : 0 success,
+ ***********************************************************************************************/
+static void icn83xx_free_irq(struct icn83xx_ts_data *icn83xx_ts)
+{
+ if (icn83xx_ts)
+ {
+ if (icn83xx_ts->use_irq)
+ {
+ free_irq(icn83xx_ts->irq, icn83xx_ts);
+ }
+ else
+ {
+ hrtimer_cancel(&icn83xx_ts->timer);
+ }
+ }
+}
+
+/***********************************************************************************************
+Name : icn83xx_request_input_dev
+Input : void
+Output :
+function : 0 success,
+ ***********************************************************************************************/
+static int icn83xx_request_input_dev(struct icn83xx_ts_data *icn83xx_ts)
+{
+ int ret = -1;
+ struct input_dev *input_dev;
+
+ input_dev = input_allocate_device();
+ if (!input_dev) {
+ icn83xx_error("failed to allocate input device\n");
+ return -ENOMEM;
+ }
+ icn83xx_ts->input_dev = input_dev;
+
+ icn83xx_ts->input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) ;
+#if CTP_REPORT_PROTOCOL
+ __set_bit(INPUT_PROP_DIRECT, icn83xx_ts->input_dev->propbit);
+ input_mt_init_slots(icn83xx_ts->input_dev, 255);
+#else
+ set_bit(ABS_MT_TOUCH_MAJOR, icn83xx_ts->input_dev->absbit);
+ set_bit(ABS_MT_POSITION_X, icn83xx_ts->input_dev->absbit);
+ set_bit(ABS_MT_POSITION_Y, icn83xx_ts->input_dev->absbit);
+ set_bit(ABS_MT_WIDTH_MAJOR, icn83xx_ts->input_dev->absbit);
+#endif
+ if (g_param.lcd_exchg) {
+ input_set_abs_params(icn83xx_ts->input_dev, ABS_MT_POSITION_X, 0, g_param.panelres_y, 0, 0);
+ input_set_abs_params(icn83xx_ts->input_dev, ABS_MT_POSITION_Y, 0, g_param.panelres_x, 0, 0);
+ } else {
+ input_set_abs_params(icn83xx_ts->input_dev, ABS_MT_POSITION_X, 0, g_param.panelres_x, 0, 0);
+ input_set_abs_params(icn83xx_ts->input_dev, ABS_MT_POSITION_Y, 0, g_param.panelres_y, 0, 0);
+ }
+ input_set_abs_params(icn83xx_ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0);
+ input_set_abs_params(icn83xx_ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
+ input_set_abs_params(icn83xx_ts->input_dev, ABS_MT_TRACKING_ID, 0, 255, 0, 0);
+
+ __set_bit(KEY_MENU, input_dev->keybit);
+ __set_bit(KEY_BACK, input_dev->keybit);
+ __set_bit(KEY_HOME, input_dev->keybit);
+ __set_bit(KEY_SEARCH, input_dev->keybit);
+
+ input_dev->name = CTP_NAME;
+ ret = input_register_device(input_dev);
+ if (ret) {
+ icn83xx_error("Register %s input device failed\n", input_dev->name);
+ input_free_device(input_dev);
+ return -ENODEV;
+ }
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ icn83xx_trace("==register_early_suspend =\n");
+ icn83xx_ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+ icn83xx_ts->early_suspend.suspend = icn83xx_ts_early_suspend;
+ icn83xx_ts->early_suspend.resume = icn83xx_ts_late_resume;
+ register_early_suspend(&icn83xx_ts->early_suspend);
+#endif
+
+ return 0;
+}
+
+#if SUPPORT_DELAYED_WORK
+static void icn_delayedwork_fun(struct work_struct *work)
+{
+ int retry;
+ short fwVersion = 0;
+ short curVersion = 0;
+ icn83xx_trace("====%s begin1111=====. \n", __func__);
+
+#if SUPPORT_FW_UPDATE
+ fwVersion = icn83xx_read_fw_Ver(firmware);
+ curVersion = icn83xx_readVersion();
+ icn83xx_trace("fwVersion : 0x%x\n", fwVersion);
+ icn83xx_trace("current version: 0x%x\n", curVersion);
+
+
+#if FORCE_UPDATA_FW
+ retry = 5;
+ while(retry > 0)
+ {
+ if(R_OK == icn83xx_fw_update(firmware))
+ {
+ break;
+ }
+ retry--;
+ icn83xx_error("icn83xx_fw_update failed.\n");
+ }
+#else
+ if(fwVersion > curVersion)
+ {
+ retry = 5;
+ while(retry > 0)
+ {
+ if(R_OK == icn83xx_fw_update(firmware))
+ {
+ break;
+ }
+ retry--;
+ icn83xx_error("icn83xx_fw_update failed.\n");
+ }
+ }
+#endif
+
+#endif
+
+
+ icn83xx_irq_enable();
+ icn83xx_trace("====%s over1111=====. \n", __func__);
+}
+#endif
+
+
+char FbCap[4][16]={
+ {0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14},
+ {0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12},
+ {0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10},
+ {0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08},
+};
+
+static int wmt_wakeup_bl_notify(struct notifier_block *nb, unsigned long event,
+ void *dummy)
+{
+ //printk("get notify\n");
+ switch (event) {
+ case BL_CLOSE:
+ l_suspend = 1;
+ //printk("\nclose backlight\n\n");
+ //printk("disable irq\n\n");
+ wmt_gpio_mask_irq(g_param.irqgpio);
+ break;
+ case BL_OPEN:
+ l_suspend = 0;
+ //printk("\nopen backlight\n\n");
+ //printk("enable irq\n\n");
+ wmt_gpio_unmask_irq(g_param.irqgpio);
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block wmt_bl_notify = {
+ .notifier_call = wmt_wakeup_bl_notify,
+};
+
+static int icn83xx_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+ struct icn83xx_ts_data *icn83xx_ts;
+ short fwVersion = 0;
+ short curVersion = 0;
+ //int average;
+ int err = 0;
+ //char value;
+ int retry;
+
+ icn83xx_trace("====%s begin=====. \n", __func__);
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+ {
+ icn83xx_error("I2C check functionality failed.\n");
+ return -ENODEV;
+ }
+
+ icn83xx_ts = kzalloc(sizeof(*icn83xx_ts), GFP_KERNEL);
+ if (!icn83xx_ts)
+ {
+ icn83xx_error("Alloc icn83xx_ts memory failed.\n");
+ return -ENOMEM;
+ }
+
+ this_client = client;
+ i2c_set_clientdata(client, icn83xx_ts);
+
+ icn83xx_ts->work_mode = 0;
+ spin_lock_init(&icn83xx_ts->irq_lock);
+ // icn83xx_ts->irq_lock = SPIN_LOCK_UNLOCKED;
+
+ err = icn83xx_request_io_port(icn83xx_ts);
+ if (err != 0) {
+ icn83xx_error("icn83xx_request_io_port failed.\n");
+ goto fail1;
+ }
+
+ memset(firmware, 0, 128);
+ sprintf(firmware,"/system/etc/firmware/%s.bin",g_param.fw_name);
+
+ icn83xx_ts_reset();
+ err = icn83xx_iic_test();
+ if (err < 0)
+ {
+ icn83xx_error("icn83xx_iic_test failed.\n");
+#if SUPPORT_FW_UPDATE
+
+#if COMPILE_FW_WITH_DRIVER
+ icn83xx_set_fw(sizeof(icn83xx_fw), &icn83xx_fw[0]);
+#endif
+ if(icn83xx_check_progmod() == 0)
+ {
+
+ retry = 5;
+ icn83xx_trace("in prog mode\n");
+ while(retry > 0)
+ {
+ if(R_OK == icn83xx_fw_update(firmware))
+ {
+ break;
+ }
+ retry--;
+ icn83xx_error("icn83xx_fw_update failed.\n");
+ }
+ }
+ else //
+ {
+ icn83xx_error("I2C communication failed.\n");
+ err = -1;
+ goto fail2;
+ }
+
+#endif
+ }
+ else
+ {
+ icn83xx_trace("iic communication ok\n");
+ }
+
+#if SUPPORT_FW_UPDATE
+ fwVersion = icn83xx_read_fw_Ver(firmware);
+ curVersion = icn83xx_readVersion();
+ icn83xx_trace("fwVersion : 0x%x\n", fwVersion);
+ icn83xx_trace("current version: 0x%x\n", curVersion);
+
+ if (g_param.force_download) {
+ retry = 5;
+ while(retry > 0)
+ {
+ if(R_OK == icn83xx_fw_update(firmware))
+ {
+ break;
+ }
+ retry--;
+ icn83xx_error("icn83xx_fw_update failed.\n");
+ }
+ } else {
+ if(fwVersion > curVersion)
+ {
+ retry = 5;
+ while(retry > 0)
+ {
+ if(R_OK == icn83xx_fw_update(firmware))
+ {
+ break;
+ }
+ retry--;
+ icn83xx_error("icn83xx_fw_update failed.\n");
+ }
+ }
+ }
+
+#endif
+
+#if SUPPORT_FW_CALIB
+ err = icn83xx_read_reg(0, &value);
+ if(err > 0)
+ {
+ //auto calib fw
+ average = icn83xx_calib(0, NULL);
+ //fix FbCap
+ // average = icn83xx_calib(0, FbCap[1]);
+ icn83xx_trace("average : %d\n", average);
+ icn83xx_setPeakGroup(250, 150);
+ icn83xx_setDownUp(400, 300);
+ }
+#endif
+
+ INIT_WORK(&icn83xx_ts->pen_event_work, icn83xx_ts_pen_irq_work);
+ icn83xx_ts->ts_workqueue = create_singlethread_workqueue(dev_name(&client->dev));
+ if (!icn83xx_ts->ts_workqueue) {
+ icn83xx_error("create_singlethread_workqueue failed.\n");
+ err = -ESRCH;
+ goto fail3;
+ }
+
+ err= icn83xx_request_input_dev(icn83xx_ts);
+ if (err < 0)
+ {
+ icn83xx_error("request input dev failed\n");
+ goto fail4;
+ }
+
+#if TOUCH_VIRTUAL_KEYS
+ icn83xx_ts_virtual_keys_init();
+#endif
+ err = icn83xx_request_irq(icn83xx_ts);
+ if (err != 0)
+ {
+ printk("request irq error, use timer\n");
+ icn83xx_ts->use_irq = 0;
+ hrtimer_init(&icn83xx_ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ icn83xx_ts->timer.function = chipone_timer_func;
+ hrtimer_start(&icn83xx_ts->timer, ktime_set(CTP_START_TIMER/1000, (CTP_START_TIMER%1000)*1000000), HRTIMER_MODE_REL);
+ }
+#if SUPPORT_SYSFS
+ icn83xx_create_sysfs(client);
+#endif
+
+#if SUPPORT_PROC_FS
+ sema_init(&icn83xx_ts->sem, 1);
+ init_proc_node();
+#endif
+
+ err = device_create_file(&(client->dev), &dev_attr_dbg);
+ if (err) {
+ printk("Can't create attr file");
+ }
+ if (g_param.earlysus_en)
+ register_bl_notifier(&wmt_bl_notify);
+
+#if SUPPORT_DELAYED_WORK
+ INIT_DELAYED_WORK(&icn83xx_ts->icn_delayed_work, icn_delayedwork_fun);
+ schedule_delayed_work(&icn83xx_ts->icn_delayed_work, msecs_to_jiffies(8000));
+#else
+
+ icn83xx_irq_enable();
+#endif
+ icn83xx_trace("==%s over =\n", __func__);
+ return 0;
+
+fail4:
+ input_unregister_device(icn83xx_ts->input_dev);
+ input_free_device(icn83xx_ts->input_dev);
+fail3:
+ cancel_work_sync(&icn83xx_ts->pen_event_work);
+fail2:
+ icn83xx_free_io_port();
+fail1:
+ kfree(icn83xx_ts);
+ return err;
+}
+
+static int __devexit icn83xx_ts_remove(struct i2c_client *client)
+{
+ struct icn83xx_ts_data *icn83xx_ts = i2c_get_clientdata(client);
+ icn83xx_trace("==icn83xx_ts_remove=\n");
+ icn83xx_irq_disable();
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&icn83xx_ts->early_suspend);
+#endif
+
+ if (g_param.earlysus_en)
+ unregister_bl_notifier(&wmt_bl_notify);
+
+#if SUPPORT_PROC_FS
+ uninit_proc_node();
+#endif
+
+ input_unregister_device(icn83xx_ts->input_dev);
+ input_free_device(icn83xx_ts->input_dev);
+ cancel_work_sync(&icn83xx_ts->pen_event_work);
+ destroy_workqueue(icn83xx_ts->ts_workqueue);
+ icn83xx_free_irq(icn83xx_ts);
+ icn83xx_free_io_port();
+ kfree(icn83xx_ts);
+ i2c_set_clientdata(client, NULL);
+ return 0;
+}
+
+static int wmt_check_touch_env(void)
+{
+ int ret = 0;
+ int len = 96;
+ char retval[200] = {0},*p=NULL,*s=NULL;
+ int Enable=0;
+
+ // Get u-boot parameter
+ /*ret = wmt_getsyspara("wmt.io.zettouch", retval, &len);
+ if(ret){
+ klog("Read wmt.io.zettouch Failed.\n");
+ } else
+ goto paste;*/
+ ret = wmt_getsyspara("wmt.io.touch", retval, &len);
+ if(ret){
+ printk("Read wmt.io.touch Failed.\n");
+ return -EIO;
+ }
+
+//paste:
+ p = retval;
+ Enable = (p[0] - '0' == 1) ? 1 : 0;
+ if(Enable == 0){
+ printk("Touch Screen Is Disabled.\n");
+ return -ENODEV;
+ }
+
+ p = strchr(p,':');p++;
+ s = strchr(p,':');
+ strncpy(g_param.fw_name,p, (s-p));
+ printk("ts_name=%s\n", g_param.fw_name);
+ if (strncmp(g_param.fw_name, "ICN83", 5)) {
+ printk("Wrong firmware name.\n");
+ return -ENODEV;
+ }
+
+ p = s+1;
+ ret = sscanf(p,"%d:%d:%d:%d:%d:%d:%d:%d",
+ &(g_param.irqgpio),&(g_param.panelres_x),&(g_param.panelres_y),&(g_param.rstgpio),
+ &(g_param.xyswap),&(g_param.xdir),&(g_param.ydir),&(g_param.force_download));
+
+ if (ret < 8) {
+ printk("Wrong format ts u-boot param(%d)!\nwmt.io.touch=%s\n",ret,retval);
+ return -ENODEV;
+ }
+
+ printk("p.x = %d, p.y = %d, irqgpio=%d, rstgpio=%d,xyswap=%d,xdir=%d,ydir=%d,force_download=%d\n",
+ g_param.panelres_x,g_param.panelres_y,g_param.irqgpio,g_param.rstgpio,
+ g_param.xyswap,g_param.xdir,g_param.ydir,g_param.force_download);
+
+ memset(retval,0,sizeof(retval));
+ ret = wmt_getsyspara("wmt.touch.earlysus", retval, &len);
+ if(!ret)
+ g_param.earlysus_en = (retval[0] - '0' == 1) ? 1 : 0;
+
+ memset(retval,0,sizeof(retval));
+ ret = wmt_getsyspara("wmt.display.fb0", retval, &len);
+ if (!ret) {
+ int tmp[6];
+ p = retval;
+ sscanf(p, "%d:[%d:%d:%d:%d:%d", &tmp[0], &tmp[1], &tmp[2], &tmp[3], &tmp[4], &tmp[5]);
+ if (tmp[4] > tmp[5])
+ g_param.lcd_exchg = 1;
+ }
+
+ return 0;
+}
+
+static const struct dev_pm_ops icn83xx_pm_ops = {
+ .suspend = icn83xx_ts_suspend,
+ .resume = icn83xx_ts_resume,
+};
+
+static const struct i2c_device_id icn83xx_ts_id[] = {
+ { CTP_NAME, 0 },
+ {},
+};
+MODULE_DEVICE_TABLE(i2c, icn83xx_ts_id);
+
+static struct i2c_driver icn83xx_ts_driver = {
+ .driver = {
+ .name = CTP_NAME,
+ .pm = &icn83xx_pm_ops,
+ },
+ .probe = icn83xx_ts_probe,
+ .remove = __devexit_p(icn83xx_ts_remove),
+ .id_table = icn83xx_ts_id,
+};
+
+static struct i2c_board_info i2c_board_info = {
+ I2C_BOARD_INFO(CTP_NAME, ICN83XX_IIC_ADDR),
+};
+
+static int __init icn83xx_ts_init(void)
+{
+ struct i2c_client *client;
+ struct i2c_adapter *adap;
+ //u8 ts_data[8];
+
+ icn83xx_trace("===========================%s=====================\n", __func__);
+ if(wmt_check_touch_env())
+ return -ENODEV;
+ {//register i2c device
+ adap = i2c_get_adapter(1); //i2c Bus 1
+ if (!adap)
+ return -ENODEV;
+ client = i2c_new_device(adap, &i2c_board_info);
+ i2c_put_adapter(adap);
+ if (!client) {
+ printk("i2c_new_device error\n");
+ return -ENODEV;
+ }
+ }
+ /*{ //check if IC exists
+ if (i2c_read_tsdata(client, ts_data, 8) <= 0) {
+ errlog("Can't find IC!\n");
+ i2c_unregister_device(client);
+ return -ENODEV;
+ }
+ }*/
+ return i2c_add_driver(&icn83xx_ts_driver);
+}
+
+static void __exit icn83xx_ts_exit(void)
+{
+ icn83xx_trace("==icn83xx_ts_exit==\n");
+ i2c_unregister_device(this_client);
+ return i2c_del_driver(&icn83xx_ts_driver);
+}
+
+late_initcall(icn83xx_ts_init);
+module_exit(icn83xx_ts_exit);
+
+MODULE_AUTHOR("<zmtian@chiponeic.com>");
+MODULE_DESCRIPTION("Chipone icn83xx TouchScreen driver");
+MODULE_LICENSE("GPL");
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/icn83xx_ts/icn83xx.h b/ANDROID_3.4.5/drivers/input/touchscreen/icn83xx_ts/icn83xx.h
new file mode 100755
index 00000000..46a7cf21
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/icn83xx_ts/icn83xx.h
@@ -0,0 +1,434 @@
+/*++
+
+ Copyright (c) 2012-2022 ChipOne Technology (Beijing) Co., Ltd. All Rights Reserved.
+ This PROPRIETARY SOFTWARE is the property of ChipOne Technology (Beijing) Co., Ltd.
+ and may contains trade secrets and/or other confidential information of ChipOne
+ Technology (Beijing) Co., Ltd. This file shall not be disclosed to any third party,
+ in whole or in part, without prior written consent of ChipOne.
+ THIS PROPRIETARY SOFTWARE & ANY RELATED DOCUMENTATION ARE PROVIDED AS IS,
+ WITH ALL FAULTS, & WITHOUT WARRANTY OF ANY KIND. CHIPONE DISCLAIMS ALL EXPRESS OR
+ IMPLIED WARRANTIES.
+
+ File Name: icn83xx.h
+ Abstract:
+ input driver.
+Author: Zhimin Tian
+Date : 01,17,2013
+Version: 1.0
+History :
+ 2012,10,30, V0.1 first version
+
+ --*/
+
+#ifndef __LINUX_ICN83XX_H__
+#define __LINUX_ICN83XX_H__
+
+#include <linux/i2c.h>
+#include <linux/input.h>
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ #include <linux/pm.h>
+ #include <linux/earlysuspend.h>
+#endif
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/async.h>
+#include <linux/hrtimer.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <linux/input.h>
+#include <linux/input/mt.h>
+#include <linux/hrtimer.h>
+#include <linux/proc_fs.h>
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+ #include <linux/semaphore.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/ioctl.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/spinlock_types.h>
+#include <linux/workqueue.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <mach/wmt_iomux.h>
+#include "../../../video/backlight/wmt_bl.h"
+
+//-----------------------------------------------------------------------------
+// Pin Declarations
+//-----------------------------------------------------------------------------
+
+#define SUPPORT_ROCKCHIP 0
+
+#if SUPPORT_ROCKCHIP
+#include <linux/irq.h>
+#include <mach/irqs.h>
+//#include <mach/system.h>
+#include <mach/hardware.h>
+//#include <mach/board.h>
+#include <mach/gpio.h>
+
+#define CTP_IRQ_PORT RK30_PIN1_PB7
+#define CTP_IRQ_MODE 0
+#define CTP_RST_PORT RK30_PIN1_PA7
+#define CTP_WAKEUP_PORT 0
+ //1: B protocol
+#define SCREEN_MAX_X (800)
+#define SCREEN_MAX_Y (480)
+#define ICN83XX_I2C_SCL 400*1000
+
+#endif
+
+#define CTP_REPORT_PROTOCOL 1 //0: A protocol
+
+//-----------------------------------------------------------------------------
+// Global CONSTANTS
+//-----------------------------------------------------------------------------
+
+#define TOUCH_VIRTUAL_KEYS 0
+#define SUPPORT_PROC_FS 1
+#define SUPPORT_SYSFS 1
+#define SUPPORT_FW_UPDATE 1
+#define COMPILE_FW_WITH_DRIVER 0
+#define FORCE_UPDATA_FW 0
+#define SUPPORT_FW_CALIB 0
+#define SUPPORT_DELAYED_WORK 0
+
+#define ICN83XX_NAME "chipone-ts"
+#define ICN83XX_PROG_IIC_ADDR (0x60>>1)
+#define ICN83XX_IIC_ADDR (0x80>>1)
+#define CTP_NAME ICN83XX_NAME
+
+#define CTP_RESET_LOW_PERIOD (5)
+#define CTP_RESET_HIGH_PERIOD (100)
+#define CTP_WAKEUP_LOW_PERIOD (20)
+#define CTP_WAKEUP_HIGH_PERIOD (50)
+#define CTP_POLL_TIMER (16) /* ms delay between samples */
+#define CTP_START_TIMER (100) /* ms delay between samples */
+
+#define POINT_NUM 5
+#define POINT_SIZE 7
+
+#define TS_KEY_HOME 102
+#define TS_KEY_MENU 139
+#define TS_KEY_BACK 158
+#define TS_KEY_SEARCH 217
+
+#define ICN_VIRTUAL_BUTTON_HOME 0x02
+#define ICN_VIRTUAL_BUTTON_MENU 0x01
+#define ICN_VIRTUAL_BUTTON_BACK 0x04
+#define ICN_VIRTUAL_BUTTON_SEARCH 0x08
+
+#define IIC_RETRY_NUM 3
+
+//ICN83XX_REG_PMODE
+#define PMODE_ACTIVE 0x00
+#define PMODE_MONITOR 0x01
+#define PMODE_HIBERNATE 0x02
+
+#define B_SIZE 32
+#define ENABLE_BYTE_CHECK
+//#define WAKE_PIN 1
+//-----------------------------------------------------------------------------
+// Macro DEFINITIONS
+//-----------------------------------------------------------------------------
+#define DBG_ICN83XX_TRACE
+//#define DBG_ICN83XX_POINT
+//#define DBG_ICN83XX_INFO
+#define DBG_ICN83XX_ERROR
+#define DBG_FLASH_INFO
+#define DBG_FLASH_ERROR
+#define DBG_OP_INFO
+#define DBG_OP_ERROR
+#define DBG_CALIB_INFO
+#define DBG_CALIB_ERROR
+//#define DBG_PROC_INFO
+#define DBG_PROC_ERROR
+
+
+#ifdef DBG_ICN83XX_TRACE
+#define icn83xx_trace(fmt, args...) \
+ do{ \
+ printk(fmt, ##args); \
+ }while(0)
+#else
+#define icn83xx_trace(fmt, args...) //
+#endif
+
+
+#ifdef DBG_ICN83XX_POINT
+#define icn83xx_point_info(fmt, args...) \
+ do{ \
+ printk(fmt, ##args); \
+ }while(0)
+#else
+#define icn83xx_point_info(fmt, args...) //
+#endif
+
+#ifdef DBG_ICN83XX_INFO
+#define icn83xx_info(fmt, args...) \
+ do{ \
+ printk(fmt, ##args); \
+ }while(0)
+#else
+#define icn83xx_info(fmt, args...) //
+#endif
+
+#ifdef DBG_ICN83XX_ERROR
+#define icn83xx_error(fmt, args...) \
+ do{ \
+ printk(fmt, ##args); \
+ }while(0)
+#else
+#define icn83xx_error(fmt, args...) //
+#endif
+
+#ifdef DBG_FLASH_INFO
+#define flash_info(fmt, args...) \
+ do{ \
+ printk(fmt, ##args); \
+ }while(0)
+#else
+#define flash_info(fmt, args...) //
+#endif
+
+#ifdef DBG_FLASH_ERROR
+#define flash_error(fmt, args...) \
+ do{ \
+ printk(fmt, ##args); \
+ }while(0)
+#else
+#define flash_error(fmt, args...) //
+#endif
+
+
+#ifdef DBG_OP_INFO
+#define op_info(fmt, args...) \
+ do{ \
+ printk(fmt, ##args); \
+ }while(0)
+#else
+#define op_info(fmt, args...) //
+#endif
+#ifdef DBG_OP_ERROR
+#define op_error(fmt, args...) \
+ do{ \
+ printk(fmt, ##args); \
+ }while(0)
+#else
+#define op_error(fmt, args...) //
+#endif
+
+
+#ifdef DBG_CALIB_INFO
+#define calib_info(fmt, args...) \
+ do{ \
+ printk(fmt, ##args); \
+ }while(0)
+#else
+#define calib_info(fmt, args...) //
+#endif
+
+#ifdef DBG_CALIB_ERROR
+#define calib_error(fmt, args...) \
+ do{ \
+ printk(fmt, ##args); \
+ }while(0)
+#else
+#define calib_error(fmt, args...) //
+#endif
+
+
+#ifdef DBG_PROC_INFO
+#define proc_info(fmt, args...) \
+ do{ \
+ printk(fmt, ##args); \
+ }while(0)
+#else
+#define proc_info(fmt, args...) //
+#endif
+
+#ifdef DBG_PROC_ERROR
+#define proc_error(fmt, args...) \
+ do{ \
+ printk(fmt, ##args); \
+ }while(0)
+#else
+#define proc_error(fmt, args...) //
+#endif
+
+#define swap_ab(a,b) {char temp;temp=a;a=b;b=temp;}
+#define U16LOBYTE(var) (*(unsigned char *) &var)
+#define U16HIBYTE(var) (*(unsigned char *)((unsigned char *) &var + 1))
+
+
+
+//-----------------------------------------------------------------------------
+// Struct, Union and Enum DEFINITIONS
+//-----------------------------------------------------------------------------
+typedef struct _POINT_INFO
+{
+ unsigned char u8ID;
+ unsigned short u16PosX; // coordinate X, plus 4 LSBs for precision extension
+ unsigned short u16PosY; // coordinate Y, plus 4 LSBs for precision extension
+ unsigned char u8Pressure;
+ unsigned char u8EventId;
+}POINT_INFO;
+
+struct icn83xx_ts_data {
+ struct i2c_client *client;
+ struct input_dev *input_dev;
+ struct work_struct pen_event_work;
+ struct delayed_work icn_delayed_work;
+ struct workqueue_struct *ts_workqueue;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend early_suspend;
+#endif
+ struct hrtimer timer;
+ spinlock_t irq_lock;
+ struct semaphore sem;
+
+ POINT_INFO point_info[POINT_NUM+1];
+ int point_num;
+ int irq;
+ int irq_is_disable;
+ int use_irq;
+ int work_mode;
+ int screen_max_x;
+ int screen_max_y;
+ int revert_x_flag;
+ int revert_y_flag;
+ int exchange_x_y_flag;
+ int (*init_wakeup_hw)(void);
+};
+
+struct touch_param {
+ char fw_name[32];
+ int irqgpio;
+ int rstgpio;
+ int panelres_x;
+ int panelres_y;
+ int xyswap;
+ int xdir;
+ int ydir;
+ int max_finger_num;
+ int force_download;
+ int earlysus_en;
+ int dbg;
+ int lcd_exchg;
+};
+
+#pragma pack(1)
+typedef struct{
+ unsigned char wr; //write read flag£¬0:R 1:W
+ unsigned char flag; //0:
+ unsigned char circle; //polling cycle
+ unsigned char times; //plling times
+ unsigned char retry; //I2C retry times
+ unsigned int data_len; //data length
+ unsigned char addr_len; //address length
+ unsigned char addr[2]; //address
+ unsigned char* data; //data pointer
+}pack_head;
+#pragma pack()
+
+#define DATA_LENGTH_UINT 512
+#define CMD_HEAD_LENGTH (sizeof(pack_head) - sizeof(unsigned char *))
+#define ICN83XX_ENTRY_NAME "icn83xx_tool"
+enum icn83xx_ts_regs {
+ ICN83XX_REG_PMODE = 0x04, /* Power Consume Mode */
+};
+
+typedef enum
+{
+ R_OK = 100,
+ R_FILE_ERR,
+ R_STATE_ERR,
+ R_ERASE_ERR,
+ R_PROGRAM_ERR,
+ R_VERIFY_ERR,
+}E_UPGRADE_ERR_TYPE;
+
+//-----------------------------------------------------------------------------
+// Global VARIABLES
+//-----------------------------------------------------------------------------
+
+
+//-----------------------------------------------------------------------------
+// Function PROTOTYPES
+//-----------------------------------------------------------------------------
+
+void icn83xx_ts_reset(void);
+int icn83xx_i2c_rxdata(unsigned char addr, char *rxdata, int length);
+int icn83xx_i2c_txdata(unsigned char addr, char *txdata, int length);
+int icn83xx_write_reg(unsigned char addr, char para);
+int icn83xx_read_reg(unsigned char addr, char *pdata);
+int icn83xx_prog_i2c_rxdata(unsigned short addr, char *rxdata, int length);
+int icn83xx_prog_i2c_txdata(unsigned short addr, char *txdata, int length);
+int icn83xx_prog_write_reg(unsigned short addr, char para);
+int icn83xx_prog_read_reg(unsigned short addr, char *pdata);
+#if SUPPORT_FW_UPDATE
+
+int icn83xx_writeInfo(unsigned short addr, char value);
+int icn83xx_readInfo(unsigned short addr, char *value);
+int icn83xx_writeReg(unsigned short addr, char value);
+int icn83xx_readReg(unsigned short addr, char *value);
+int icn83xx_readVersion(void);
+int icn83xx_changemode(char mode);
+int icn83xx_readrawdata(char *buffer, char row, char length);
+int icn83xx_readTP(char row_num, char column_num, char *buffer);
+int icn83xx_scanTP(void);
+void icn83xx_rawdatadump(short *mem, int size, char br);
+void icn83xx_set_fw(int size, unsigned char *buf);
+void icn83xx_memdump(char *mem, int size);
+int icn83xx_checksum(int sum, char *buf, unsigned int size);
+int icn83xx_update_status(int status);
+int icn83xx_get_status(void);
+int icn83xx_open_fw( char *fw);
+int icn83xx_read_fw(int offset, int length, char *buf);
+int icn83xx_close_fw(void);
+int icn83xx_goto_progmode(void);
+int icn83xx_check_progmod(void);
+int icn83xx_uu(void);
+void icn83xx_ll(void);
+int icn83xx_op1(char info, unsigned short offset, unsigned int size);
+int icn83xx_op2(char info, unsigned short offset, unsigned char * buffer, unsigned int size);
+int icn83xx_op3(char info, unsigned short offset, unsigned char * buffer, unsigned int size);
+short icn83xx_read_fw_Ver(char *fw);
+E_UPGRADE_ERR_TYPE icn83xx_fw_update(char *fw);
+#endif
+
+#if SUPPORT_FW_CALIB
+
+int icn83xx_checkrawdata(short *data, char num);
+int icn83xx_readpara(char *TxOrder, char row, char *RxOrder, char column);
+int icn83xx_writepara(char *TxOrder, char row, char *RxOrder, char column);
+int icn83xx_readFB(char *FB, char num);
+int icn83xx_writeFB(char *FB, char num);
+int icn83xx_readDC(char *DC, char num);
+int icn83xx_writeDC(char *DC, char num);
+int icn83xx_readPhaseDelay(char *PD, char row, char length);
+int icn83xx_writePhaseDelay(char *PD, char row, char length);
+int icn83xx_changeDCflag(char flag);
+int icn83xx_readVkmode(char *vkmode, char *vknum);
+int icn83xx_setTarget(short target);
+int icn83xx_setPeakGroup(short peak, short group);
+int icn83xx_setDownUp(short down, short up);
+int icn83xx_average(short *data, char num);
+
+int icn83xx_calib(char index, char *FB);
+#endif
+
+#endif
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/icn83xx_ts/icn83xx_fw.h b/ANDROID_3.4.5/drivers/input/touchscreen/icn83xx_ts/icn83xx_fw.h
new file mode 100755
index 00000000..572bf1f3
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/icn83xx_ts/icn83xx_fw.h
@@ -0,0 +1,3 @@
+static unsigned char icn83xx_fw[] = {
+
+}; \ No newline at end of file
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/icn85xx_ts/Kconfig b/ANDROID_3.4.5/drivers/input/touchscreen/icn85xx_ts/Kconfig
new file mode 100755
index 00000000..593b379b
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/icn85xx_ts/Kconfig
@@ -0,0 +1,16 @@
+#
+# ICN85XX capacity touch screen driver configuration
+#
+config TOUCHSCREEN_ICN85XX
+ tristate "ICN85XX I2C Capacitive Touchscreen Input Driver Support"
+ depends on ARCH_WMT
+ default y
+ help
+ Say Y here if you have an WMT based board with touchscreen
+ attached to it.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called s_wmt_ts_icn85xx
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/icn85xx_ts/Makefile b/ANDROID_3.4.5/drivers/input/touchscreen/icn85xx_ts/Makefile
new file mode 100755
index 00000000..4f2c65ce
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/icn85xx_ts/Makefile
@@ -0,0 +1,32 @@
+KERNELDIR=../../../../
+CROSS = arm_1103_le-
+CC= $(CROSS)gcc
+LD= $(CROSS)ld
+STRIP = $(CROSS)strip
+
+DEBUG = n
+
+# Add your debugging flag (or not) to EXTRA_CFLAGS
+ifeq ($(DEBUG),y)
+# DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+DEBFLAGS = -O0 -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+
+else
+ DEBFLAGS = -O2 -Wall
+endif
+
+EXTRA_CFLAGS += $(DEBFLAGS)
+
+
+MY_MODULE_NAME=s_wmt_ts_icn85xx
+
+obj-m := $(MY_MODULE_NAME).o
+$(MY_MODULE_NAME)-objs := icn85xx.o icn85xx_flash.o
+
+default:
+ $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules
+ $(STRIP) --strip-debug $(MY_MODULE_NAME).ko
+ rm -rf *.o *~ core .depend .*.cmd *.mod.c .tmp_versions *.order *.symvers modules.builtin
+
+clean:
+ rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.order *.symvers modules.builtin
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/icn85xx_ts/icn85xx.c b/ANDROID_3.4.5/drivers/input/touchscreen/icn85xx_ts/icn85xx.c
new file mode 100755
index 00000000..371742fb
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/icn85xx_ts/icn85xx.c
@@ -0,0 +1,2431 @@
+/*++
+
+ Copyright (c) 2012-2022 ChipOne Technology (Beijing) Co., Ltd. All Rights Reserved.
+ This PROPRIETARY SOFTWARE is the property of ChipOne Technology (Beijing) Co., Ltd.
+ and may contains trade secrets and/or other confidential information of ChipOne
+ Technology (Beijing) Co., Ltd. This file shall not be disclosed to any third party,
+ in whole or in part, without prior written consent of ChipOne.
+ THIS PROPRIETARY SOFTWARE & ANY RELATED DOCUMENTATION ARE PROVIDED AS IS,
+ WITH ALL FAULTS, & WITHOUT WARRANTY OF ANY KIND. CHIPONE DISCLAIMS ALL EXPRESS OR
+ IMPLIED WARRANTIES.
+
+ File Name: icn85xx.c
+ Abstract:
+ input driver.
+ Author: Zhimin Tian
+ Date : 08,14,2013
+ Version: 1.0
+ History :
+ 2012,10,30, V0.1 first version
+ --*/
+
+#include "icn85xx.h"
+#include "icn85xx_fw.h"
+//#include "icn85xx_00_ht_0528.h"
+//#include "icn85xx_02_lh_0528.h"
+
+#if COMPILE_FW_WITH_DRIVER
+ static char firmware[128] = "icn85xx_firmware";
+#else
+ #if SUPPORT_SENSOR_ID
+ static char firmware[128] = {0};
+ #else
+ //static char firmware[128] = {"/misc/modules/ICN8505.BIN"};
+ //static char firmware[128] = {"/system/etc/firmware/ICN8505.bin"};
+ static char firmware[128] = {"ICN8505.bin"};
+ #endif
+#endif
+
+#if SUPPORT_SENSOR_ID
+ char cursensor_id,tarsensor_id,id_match;
+ char invalid_id = 0;
+
+ struct sensor_id {
+ char value;
+ const char bin_name[128];
+ unsigned char *fw_name;
+ int size;
+ };
+
+static struct sensor_id sensor_id_table[] = {
+ { 0x00, "/misc/modules/ICN8505_00_name1.BIN",fw_00_ht_0528,sizeof(fw_00_ht_0528)},//default bin or fw
+ { 0x02, "/misc/modules/ICN8505_02_name3.BIN",fw_02_lh_0528,sizeof(fw_02_lh_0528)},
+
+ // if you want support other sensor id value ,please add here
+ };
+#endif
+struct i2c_client *this_client;
+short log_basedata[COL_NUM][ROW_NUM] = {{0,0}};
+short log_rawdata[COL_NUM][ROW_NUM] = {{0,0}};
+short log_diffdata[COL_NUM][ROW_NUM] = {{0,0}};
+unsigned int log_on_off = 0;
+static struct touch_param g_param;
+static struct wake_lock downloadWakeLock;
+static struct task_struct *resume_download_task;
+static int bl_is_delay = 0;
+
+extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
+ //yank added
+ void icn85xx_charge_mode(void)
+ {
+ printk("yank---%s\n",__func__);
+ icn85xx_write_reg(ICN85xx_REG_PMODE, 0x55);
+ }
+ EXPORT_SYMBOL(icn85xx_charge_mode);
+
+ void icn85xx_discharge_mode(void)
+ {
+ printk("yank---%s\n",__func__);
+ icn85xx_write_reg(ICN85xx_REG_PMODE, 0x66);
+ }
+ EXPORT_SYMBOL(icn85xx_discharge_mode);
+
+
+static enum hrtimer_restart chipone_timer_func(struct hrtimer *timer);
+#if SUPPORT_SYSFS
+static ssize_t icn85xx_show_update(struct device* cd,struct device_attribute *attr, char* buf);
+static ssize_t icn85xx_store_update(struct device* cd, struct device_attribute *attr, const char* buf, size_t len);
+static ssize_t icn85xx_show_process(struct device* cd,struct device_attribute *attr, char* buf);
+static ssize_t icn85xx_store_process(struct device* cd, struct device_attribute *attr,const char* buf, size_t len);
+
+static DEVICE_ATTR(update, S_IRUGO | S_IWUSR, icn85xx_show_update, icn85xx_store_update);
+static DEVICE_ATTR(process, S_IRUGO | S_IWUSR, icn85xx_show_process, icn85xx_store_process);
+
+static ssize_t icn85xx_show_process(struct device* cd,struct device_attribute *attr, char* buf)
+{
+ ssize_t ret = 0;
+ sprintf(buf, "icn85xx process\n");
+ ret = strlen(buf) + 1;
+ return ret;
+}
+
+static ssize_t icn85xx_store_process(struct device* cd, struct device_attribute *attr,
+ const char* buf, size_t len)
+{
+ struct icn85xx_ts_data *icn85xx_ts = i2c_get_clientdata(this_client);
+ unsigned long on_off = simple_strtoul(buf, NULL, 10);
+
+ log_on_off = on_off;
+ memset(&log_basedata[0][0], 0, COL_NUM*ROW_NUM*2);
+ if(on_off == 0)
+ {
+ icn85xx_ts->work_mode = 0;
+ }
+ else if((on_off == 1) || (on_off == 2) || (on_off == 3))
+ {
+ if((icn85xx_ts->work_mode == 0) && (icn85xx_ts->use_irq == 1))
+ {
+ hrtimer_init(&icn85xx_ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ icn85xx_ts->timer.function = chipone_timer_func;
+ hrtimer_start(&icn85xx_ts->timer, ktime_set(CTP_START_TIMER/1000, (CTP_START_TIMER%1000)*1000000), HRTIMER_MODE_REL);
+ }
+ icn85xx_ts->work_mode = on_off;
+ }
+ else if(on_off == 10)
+ {
+ icn85xx_ts->work_mode = 4;
+ mdelay(10);
+ printk("update baseline\n");
+ icn85xx_write_reg(4, 0x30);
+ icn85xx_ts->work_mode = 0;
+ }
+ else
+ {
+ icn85xx_ts->work_mode = 0;
+ }
+
+
+ return len;
+}
+
+static ssize_t icn85xx_show_update(struct device* cd,
+ struct device_attribute *attr, char* buf)
+{
+ ssize_t ret = 0;
+ sprintf(buf, firmware);
+ ret = strlen(buf) + 1;
+ printk("firmware: %s, ret: %d\n", firmware, ret);
+
+ return ret;
+}
+
+static ssize_t icn85xx_store_update(struct device* cd, struct device_attribute *attr, const char* buf, size_t len)
+{
+ printk("len: %d, update: %s\n", len, buf);
+ memset(firmware, 0, 128);
+ memcpy(firmware, buf, len-1);
+ if(R_OK == icn85xx_fw_update(firmware))
+ {
+ printk("update ok\n");
+ }
+ else
+ {
+ printk("update error\n");
+ }
+ return len;
+}
+
+static int icn85xx_create_sysfs(struct i2c_client *client)
+{
+ int err;
+ struct device *dev = &(client->dev);
+ icn85xx_trace("%s: \n",__func__);
+ err = device_create_file(dev, &dev_attr_update);
+ err = device_create_file(dev, &dev_attr_process);
+ return err;
+}
+
+static void icn85xx_remove_sysfs(struct i2c_client *client)
+{
+ struct device *dev = &(client->dev);
+ icn85xx_trace("%s: \n",__func__);
+ device_remove_file(dev, &dev_attr_update);
+ device_remove_file(dev, &dev_attr_process);
+}
+#endif
+
+#if SUPPORT_PROC_FS
+
+pack_head cmd_head;
+static struct proc_dir_entry *icn85xx_proc_entry;
+int DATA_LENGTH = 0;
+
+STRUCT_PANEL_PARA_H g_structPanelPara;
+
+static int icn85xx_tool_write(struct file *filp, const char __user *buff, unsigned long len, void *data)
+{
+ int ret = 0;
+ int i;
+ unsigned short addr;
+ char retvalue;
+ struct icn85xx_ts_data *icn85xx_ts = i2c_get_clientdata(this_client);
+ proc_info("%s \n",__func__);
+ if(down_interruptible(&icn85xx_ts->sem))
+ {
+ return -1;
+ }
+ ret = copy_from_user(&cmd_head, buff, CMD_HEAD_LENGTH);
+ if(ret)
+ {
+ proc_error("copy_from_user failed.\n");
+ goto write_out;
+ }
+ else
+ {
+ ret = CMD_HEAD_LENGTH;
+ }
+
+ proc_info("wr :0x%02x.\n", cmd_head.wr);
+ proc_info("flag:0x%02x.\n", cmd_head.flag);
+ proc_info("circle :%d.\n", (int)cmd_head.circle);
+ proc_info("times :%d.\n", (int)cmd_head.times);
+ proc_info("retry :%d.\n", (int)cmd_head.retry);
+ proc_info("data len:%d.\n", (int)cmd_head.data_len);
+ proc_info("addr len:%d.\n", (int)cmd_head.addr_len);
+ proc_info("addr:0x%02x%02x.\n", cmd_head.addr[0], cmd_head.addr[1]);
+ proc_info("len:%d.\n", (int)len);
+ proc_info("data:0x%02x%02x.\n", buff[CMD_HEAD_LENGTH], buff[CMD_HEAD_LENGTH+1]);
+ if (1 == cmd_head.wr) // write para
+ {
+ ret = copy_from_user(&cmd_head.data[0], &buff[CMD_HEAD_LENGTH], cmd_head.data_len);
+ if(ret)
+ {
+ proc_error("copy_from_user failed.\n");
+ goto write_out;
+ }
+ //need copy to g_structPanelPara
+
+ memcpy(&g_structPanelPara, &cmd_head.data[0], cmd_head.data_len);
+ //write para to tp
+ for(i=0; i<cmd_head.data_len; )
+ {
+ int size = ((i+64) > cmd_head.data_len)?(cmd_head.data_len-i):64;
+ ret = icn85xx_i2c_txdata(0x8000+i, &cmd_head.data[i], size);
+ if (ret < 0) {
+ proc_error("write para failed!\n");
+ goto write_out;
+ }
+ i = i + 64;
+ }
+
+ ret = cmd_head.data_len + CMD_HEAD_LENGTH;
+ icn85xx_ts->work_mode = 5; //reinit
+ printk("reinit tp\n");
+ icn85xx_write_reg(0, 1);
+ mdelay(100);
+ icn85xx_write_reg(0, 0);
+ icn85xx_ts->work_mode = 0;
+ goto write_out;
+
+ }
+ else if(3 == cmd_head.wr) //set update file
+ {
+ proc_info("cmd_head_.wr == 3 \n");
+ ret = copy_from_user(&cmd_head.data[0], &buff[CMD_HEAD_LENGTH], cmd_head.data_len);
+ if(ret)
+ {
+ proc_error("copy_from_user failed.\n");
+ goto write_out;
+ }
+ ret = cmd_head.data_len + CMD_HEAD_LENGTH;
+ memset(firmware, 0, 128);
+ memcpy(firmware, &cmd_head.data[0], cmd_head.data_len);
+ proc_info("firmware : %s\n", firmware);
+ }
+ else if(5 == cmd_head.wr) //start update
+ {
+ proc_info("cmd_head_.wr == 5 \n");
+ icn85xx_update_status(1);
+ ret = kernel_thread(icn85xx_fw_update,firmware,CLONE_KERNEL);
+ icn85xx_trace("the kernel_thread result is:%d\n", ret);
+ }
+ else if(11 == cmd_head.wr) //write hostcomm
+ {
+ ret = copy_from_user(&cmd_head.data[0], &buff[CMD_HEAD_LENGTH], cmd_head.data_len);
+ if(ret)
+ {
+ proc_error("copy_from_user failed.\n");
+ goto write_out;
+ }
+ addr = (cmd_head.addr[1]<<8) | cmd_head.addr[0];
+ icn85xx_write_reg(addr, cmd_head.data[0]);
+ }
+ else if(13 == cmd_head.wr) //adc enable
+ {
+ proc_info("cmd_head_.wr == 13 \n");
+ icn85xx_ts->work_mode = 4;
+ mdelay(10);
+ //set col
+ icn85xx_write_reg(0x8000+STRUCT_OFFSET(STRUCT_PANEL_PARA_H, u8ColNum), 1);
+ //u8RXOrder[0] = u8RXOrder[cmd_head.addr[0]];
+ icn85xx_write_reg(0x8000+STRUCT_OFFSET(STRUCT_PANEL_PARA_H, u8RXOrder[0]), g_structPanelPara.u8RXOrder[cmd_head.addr[0]]);
+ //set row
+ icn85xx_write_reg(0x8000+STRUCT_OFFSET(STRUCT_PANEL_PARA_H, u8RowNum), 1);
+ //u8TXOrder[0] = u8TXOrder[cmd_head.addr[1]];
+ icn85xx_write_reg(0x8000+STRUCT_OFFSET(STRUCT_PANEL_PARA_H, u8TXOrder[0]), g_structPanelPara.u8TXOrder[cmd_head.addr[1]]);
+ //scan mode
+ icn85xx_write_reg(0x8000+STRUCT_OFFSET(STRUCT_PANEL_PARA_H, u8ScanMode), 0);
+ //bit
+ icn85xx_write_reg(0x8000+STRUCT_OFFSET(STRUCT_PANEL_PARA_H, u16BitFreq), 0xD0);
+ icn85xx_write_reg(0x8000+STRUCT_OFFSET(STRUCT_PANEL_PARA_H, u16BitFreq)+1, 0x07);
+ //freq
+ icn85xx_write_reg(0x8000+STRUCT_OFFSET(STRUCT_PANEL_PARA_H, u16FreqCycleNum[0]), 0x64);
+ icn85xx_write_reg(0x8000+STRUCT_OFFSET(STRUCT_PANEL_PARA_H, u16FreqCycleNum[0])+1, 0x00);
+ //pga
+ icn85xx_write_reg(0x8000+STRUCT_OFFSET(STRUCT_PANEL_PARA_H, u8PgaGain), 0x0);
+
+ //config mode
+ icn85xx_write_reg(0, 0x2);
+
+ mdelay(1);
+ icn85xx_read_reg(2, &retvalue);
+ printk("retvalue0: %d\n", retvalue);
+ while(retvalue != 1)
+ {
+ printk("retvalue: %d\n", retvalue);
+ mdelay(1);
+ icn85xx_read_reg(2, &retvalue);
+ }
+
+ if(icn85xx_goto_progmode() != 0)
+ {
+ printk("icn85xx_goto_progmode() != 0 error\n");
+ goto write_out;
+ }
+
+ icn85xx_prog_write_reg(0x040870, 1);
+
+ }
+
+write_out:
+ up(&icn85xx_ts->sem);
+ proc_info("icn85xx_tool_write write_out \n");
+ return len;
+
+}
+
+static int icn85xx_tool_read( char *page, char **start, off_t off, int count, int *eof, void *data )
+{
+ int i, j;
+ int ret = 0;
+
+ char row, column, retvalue;
+ unsigned short addr;
+ struct icn85xx_ts_data *icn85xx_ts = i2c_get_clientdata(this_client);
+ if(down_interruptible(&icn85xx_ts->sem))
+ {
+ return -1;
+ }
+ proc_info("%s: count:%d, off:%d, cmd_head.data_len: %d\n",__func__, count,(int)off,(int)cmd_head.data_len);
+ if (cmd_head.wr % 2)
+ {
+ ret = 0;
+ proc_info("cmd_head_.wr == 1111111 \n");
+ goto read_out;
+ }
+ else if (0 == cmd_head.wr) //read para
+ {
+ //read para
+ proc_info("cmd_head_.wr == 0 \n");
+ ret = icn85xx_i2c_rxdata(0x8000, &page[0], cmd_head.data_len);
+ if (ret < 0) {
+ icn85xx_error("%s read_data i2c_rxdata failed: %d\n", __func__, ret);
+ }
+ memcpy(&g_structPanelPara, &page[0], sizeof(g_structPanelPara));
+ goto read_out;
+
+ }
+ else if(2 == cmd_head.wr) //get update status
+ {
+ proc_info("cmd_head_.wr == 2 \n");
+ page[0] = icn85xx_get_status();
+ proc_info("status: %d\n", page[0]);
+ }
+ else if(4 == cmd_head.wr) //read rawdata
+ {
+ //icn85xx_read_reg(0x8004, &row);
+ //icn85xx_read_reg(0x8005, &column);
+ proc_info("cmd_head_.wr == 4 \n");
+ row = cmd_head.addr[1];
+ column = cmd_head.addr[0];
+ //scan tp rawdata
+ icn85xx_write_reg(4, 0x20);
+ mdelay(1);
+ for(i=0; i<1000; i++)
+ {
+ mdelay(1);
+ icn85xx_read_reg(2, &retvalue);
+ if(retvalue == 1)
+ break;
+ }
+
+ for(i=0; i<row; i++)
+ {
+ ret = icn85xx_i2c_rxdata(0x2000 + i*(COL_NUM)*2,(char *) &log_rawdata[i][0], column*2);
+ if (ret < 0) {
+ icn85xx_error("%s read_data i2c_rxdata failed: %d\n", __func__, ret);
+ }
+ //icn85xx_rawdatadump(&log_rawdata[i][0], column, COL_NUM);
+ memcpy(&page[column*2*i], &log_rawdata[i][0], column*2);
+
+ }
+
+ //finish scan tp rawdata
+ icn85xx_write_reg(2, 0x0);
+ icn85xx_write_reg(4, 0x21);
+ goto read_out;
+ }
+ else if(6 == cmd_head.wr) //read diffdata
+ {
+ proc_info("cmd_head_.wr == 6 \n");
+ row = cmd_head.addr[1];
+ column = cmd_head.addr[0];
+
+ //scan tp rawdata
+ icn85xx_write_reg(4, 0x20);
+ mdelay(1);
+
+ for(i=0; i<1000; i++)
+ {
+ mdelay(1);
+ icn85xx_read_reg(2, &retvalue);
+ if(retvalue == 1)
+ break;
+ }
+
+ for(i=0; i<row; i++)
+ {
+ ret = icn85xx_i2c_rxdata(0x3000 + (i+1)*(COL_NUM+2)*2 + 2,(char *) &log_diffdata[i][0], column*2);
+ if (ret < 0) {
+ icn85xx_error("%s read_data i2c_rxdata failed: %d\n", __func__, ret);
+ }
+ //icn85xx_rawdatadump(&log_diffdata[i][0], column, COL_NUM);
+ memcpy(&page[column*2*i], &log_diffdata[i][0], column*2);
+ }
+ //finish scan tp rawdata
+ icn85xx_write_reg(2, 0x0);
+ icn85xx_write_reg(4, 0x21);
+
+ goto read_out;
+ }
+ else if(8 == cmd_head.wr) //change TxVol, read diff
+ {
+ proc_info("cmd_head_.wr == 8 \n");
+ row = cmd_head.addr[1];
+ column = cmd_head.addr[0];
+ //scan tp rawdata
+ icn85xx_write_reg(4, 0x20);
+ mdelay(1);
+ for(i=0; i<1000; i++)
+ {
+ mdelay(1);
+ icn85xx_read_reg(2, &retvalue);
+ if(retvalue == 1)
+ break;
+ }
+
+ for(i=0; i<row; i++)
+ {
+ ret = icn85xx_i2c_rxdata(0x2000 + i*(COL_NUM)*2,(char *) &log_rawdata[i][0], column*2);
+ if (ret < 0) {
+ icn85xx_error("%s read_data i2c_rxdata failed: %d\n", __func__, ret);
+ }
+
+ }
+
+ //finish scan tp rawdata
+ icn85xx_write_reg(2, 0x0);
+ icn85xx_write_reg(4, 0x21);
+
+ icn85xx_write_reg(4, 0x12);
+
+ //scan tp rawdata
+ icn85xx_write_reg(4, 0x20);
+ mdelay(1);
+ for(i=0; i<1000; i++)
+ {
+ mdelay(1);
+ icn85xx_read_reg(2, &retvalue);
+ if(retvalue == 1)
+ break;
+ }
+
+ for(i=0; i<row; i++)
+ {
+ ret = icn85xx_i2c_rxdata(0x2000 + i*(COL_NUM)*2,(char *) &log_diffdata[i][0], column*2);
+ if (ret < 0) {
+ icn85xx_error("%s read_data i2c_rxdata failed: %d\n", __func__, ret);
+ }
+ for(j=0; j<column; j++)
+ {
+ *(short *)&page[2*(column*i +j)] = log_rawdata[i][j] - log_diffdata[i][j];
+ }
+
+ }
+
+ //finish scan tp rawdata
+ icn85xx_write_reg(2, 0x0);
+ icn85xx_write_reg(4, 0x21);
+
+ icn85xx_write_reg(4, 0x10);
+
+ goto read_out;
+ }
+ else if(10 == cmd_head.wr) //read adc data
+ {
+ if(cmd_head.flag == 0)
+ {
+ icn85xx_prog_write_reg(0x040874, 0);
+ }
+ icn85xx_prog_i2c_rxdata(2500*cmd_head.flag ,&page[0], cmd_head.data_len);
+ //icn85xx_rawdatadump(&page[0], 1024, 16);
+ if(cmd_head.flag == 9)
+ {
+ //reload code
+ if(icn85xx_ts->ictype == ICN85XX_WITHOUT_FLASH)
+ {
+ if(R_OK == icn85xx_fw_update(firmware))
+ {
+ icn85xx_ts->code_loaded_flag = 1;
+ icn85xx_trace("ICN85XX_WITHOUT_FLASH, reload code ok\n");
+ }
+ else
+ {
+ icn85xx_ts->code_loaded_flag = 0;
+ icn85xx_trace("ICN85XX_WITHOUT_FLASH, reload code error\n");
+ }
+ }
+ else
+ {
+ icn85xx_bootfrom_flash();
+ msleep(50);
+ }
+ icn85xx_ts->work_mode = 0;
+ }
+ }
+ else if(12 == cmd_head.wr) //read hostcomm
+ {
+ proc_info("cmd_head_.wr == 12 \n");
+ addr = (cmd_head.addr[1]<<8) | cmd_head.addr[0];
+ icn85xx_read_reg(addr, &retvalue);
+ page[0] = retvalue;
+ }
+ else if(14 == cmd_head.wr) //read adc status
+ {
+ proc_info("cmd_head_.wr == 14 \n");
+ icn85xx_prog_read_reg(0x4085E, &retvalue);
+ page[0] = retvalue;
+ printk("0x4085E: 0x%x\n", retvalue);
+ }
+read_out:
+ up(&icn85xx_ts->sem);
+ proc_info("%s out: %d, cmd_head.data_len: %d\n\n",__func__, count, cmd_head.data_len);
+ return cmd_head.data_len;
+}
+
+void init_proc_node(void)
+{
+ int i;
+ memset(&cmd_head, 0, sizeof(cmd_head));
+ cmd_head.data = NULL;
+
+ i = 5;
+ while ((!cmd_head.data) && i)
+ {
+ cmd_head.data = kzalloc(i * DATA_LENGTH_UINT, GFP_KERNEL);
+ if (NULL != cmd_head.data)
+ {
+ break;
+ }
+ i--;
+ }
+ if (i)
+ {
+ //DATA_LENGTH = i * DATA_LENGTH_UINT + GTP_ADDR_LENGTH;
+ DATA_LENGTH = i * DATA_LENGTH_UINT;
+ icn85xx_trace("alloc memory size:%d.\n", DATA_LENGTH);
+ }
+ else
+ {
+ proc_error("alloc for memory failed.\n");
+ return ;
+ }
+
+ icn85xx_proc_entry = create_proc_entry(ICN85xx_ENTRY_NAME, 0666, NULL);
+ if (icn85xx_proc_entry == NULL)
+ {
+ proc_error("Couldn't create proc entry!\n");
+ return ;
+ }
+ else
+ {
+ icn85xx_trace("Create proc entry success!\n");
+ icn85xx_proc_entry->write_proc = icn85xx_tool_write;
+ icn85xx_proc_entry->read_proc = icn85xx_tool_read;
+ }
+
+ return ;
+}
+
+void uninit_proc_node(void)
+{
+ kfree(cmd_head.data);
+ cmd_head.data = NULL;
+ remove_proc_entry(ICN85xx_ENTRY_NAME, NULL);
+}
+
+#endif
+
+
+#if TOUCH_VIRTUAL_KEYS
+static ssize_t virtual_keys_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ return sprintf(buf,
+ __stringify(EV_KEY) ":" __stringify(KEY_MENU) ":100:1030:50:60"
+ ":" __stringify(EV_KEY) ":" __stringify(KEY_HOME) ":280:1030:50:60"
+ ":" __stringify(EV_KEY) ":" __stringify(KEY_BACK) ":470:1030:50:60"
+ ":" __stringify(EV_KEY) ":" __stringify(KEY_SEARCH) ":900:1030:50:60"
+ "\n");
+}
+
+static struct kobj_attribute virtual_keys_attr = {
+ .attr = {
+ .name = "virtualkeys.chipone-ts",
+ .mode = S_IRUGO,
+ },
+ .show = &virtual_keys_show,
+};
+
+static struct attribute *properties_attrs[] = {
+ &virtual_keys_attr.attr,
+ NULL
+};
+
+static struct attribute_group properties_attr_group = {
+ .attrs = properties_attrs,
+};
+
+static void icn85xx_ts_virtual_keys_init(void)
+{
+ int ret;
+ struct kobject *properties_kobj;
+ properties_kobj = kobject_create_and_add("board_properties", NULL);
+ if (properties_kobj)
+ ret = sysfs_create_group(properties_kobj,
+ &properties_attr_group);
+ if (!properties_kobj || ret)
+ pr_err("failed to create board_properties\n");
+}
+#endif
+
+
+
+
+/* ---------------------------------------------------------------------
+*
+* Chipone panel related driver
+*
+*
+----------------------------------------------------------------------*/
+/***********************************************************************************************
+Name : icn85xx_ts_wakeup
+Input : void
+Output : ret
+function : this function is used to wakeup tp
+***********************************************************************************************/
+void icn85xx_ts_wakeup(void)
+{
+
+
+
+}
+
+/***********************************************************************************************
+Name : icn85xx_ts_reset
+Input : void
+Output : ret
+function : this function is used to reset tp, you should not delete it
+***********************************************************************************************/
+void icn85xx_ts_reset(void)
+{
+ //set reset func
+
+ int rst = g_param.rstgpio;
+ gpio_direction_output(rst,0);
+ msleep(50);
+ icn85xx_info("[%s]:>>>>>>>>>>>>>>>>>CTP_RST_PORT = %d;msleep(50);\n",__func__,gpio_get_value(rst));
+ gpio_direction_output(rst,1);
+ msleep(70);
+ icn85xx_info("[%s]:>>>>>>>>>>>>>>>>>CTP_RST_PORT = %d;msleep(70);\n",__func__,gpio_get_value(rst));
+
+}
+
+/***********************************************************************************************
+Name : icn85xx_irq_disable
+Input : void
+Output : ret
+function : this function is used to disable irq
+***********************************************************************************************/
+void icn85xx_irq_disable(void)
+{
+ unsigned long irqflags;
+ struct icn85xx_ts_data *icn85xx_ts = i2c_get_clientdata(this_client);
+
+ spin_lock_irqsave(&icn85xx_ts->irq_lock, irqflags);
+ if (!icn85xx_ts->irq_is_disable)
+ {
+ icn85xx_ts->irq_is_disable = 1;
+ wmt_gpio_mask_irq(g_param.irqgpio);
+ //disable_irq_nosync(icn85xx_ts->irq);
+ //disable_irq(icn85xx_ts->irq);
+ }
+ spin_unlock_irqrestore(&icn85xx_ts->irq_lock, irqflags);
+
+}
+
+/***********************************************************************************************
+Name : icn85xx_irq_enable
+Input : void
+Output : ret
+function : this function is used to enable irq
+***********************************************************************************************/
+void icn85xx_irq_enable(void)
+{
+ unsigned long irqflags = 0;
+ struct icn85xx_ts_data *icn85xx_ts = i2c_get_clientdata(this_client);
+
+ spin_lock_irqsave(&icn85xx_ts->irq_lock, irqflags);
+ if (icn85xx_ts->irq_is_disable)
+ {
+ wmt_gpio_unmask_irq(g_param.irqgpio);
+ //enable_irq(icn85xx_ts->irq);
+ icn85xx_ts->irq_is_disable = 0;
+ }
+ spin_unlock_irqrestore(&icn85xx_ts->irq_lock, irqflags);
+
+}
+
+/***********************************************************************************************
+Name : icn85xx_prog_i2c_rxdata
+Input : addr
+ *rxdata
+ length
+Output : ret
+function : read data from icn85xx, prog mode
+***********************************************************************************************/
+int icn85xx_prog_i2c_rxdata(unsigned int addr, char *rxdata, int length)
+{
+ int ret = -1;
+ int retries = 0;
+#if 0
+ struct i2c_msg msgs[] = {
+ {
+ .addr = ICN85XX_PROG_IIC_ADDR,//this_client->addr,
+ .flags = I2C_M_RD,
+ .len = length,
+ .buf = rxdata,
+#if SUPPORT_ROCKCHIP
+ .scl_rate = ICN85XX_I2C_SCL,
+#endif
+ },
+ };
+
+ icn85xx_prog_i2c_txdata(addr, NULL, 0);
+ while(retries < IIC_RETRY_NUM)
+ {
+ ret = i2c_transfer(this_client->adapter, msgs, 1);
+ if(ret == 1)break;
+ retries++;
+ }
+ if (retries >= IIC_RETRY_NUM)
+ {
+ icn85xx_error("%s i2c read error: %d\n", __func__, ret);
+// icn85xx_ts_reset();
+ }
+#else
+ unsigned char tmp_buf[3];
+ struct i2c_msg msgs[] = {
+ {
+ .addr = ICN85XX_PROG_IIC_ADDR,//this_client->addr,
+ .flags = 0,
+ .len = 3,
+ .buf = tmp_buf,
+#if SUPPORT_ROCKCHIP
+ .scl_rate = ICN85XX_I2C_SCL,
+#endif
+ },
+ {
+ .addr = ICN85XX_PROG_IIC_ADDR,//this_client->addr,
+ .flags = I2C_M_RD,
+ .len = length,
+ .buf = rxdata,
+#if SUPPORT_ROCKCHIP
+ .scl_rate = ICN85XX_I2C_SCL,
+#endif
+ },
+ };
+
+ tmp_buf[0] = (unsigned char)(addr>>16);
+ tmp_buf[1] = (unsigned char)(addr>>8);
+ tmp_buf[2] = (unsigned char)(addr);
+
+
+ while(retries < IIC_RETRY_NUM)
+ {
+ ret = i2c_transfer(this_client->adapter, msgs, 2);
+ if(ret == 2)break;
+ retries++;
+ }
+
+ if (retries >= IIC_RETRY_NUM)
+ {
+ icn85xx_error("%s i2c read error: %d\n", __func__, ret);
+// icn85xx_ts_reset();
+ }
+#endif
+ return ret;
+}
+/***********************************************************************************************
+Name : icn85xx_prog_i2c_txdata
+Input : addr
+ *rxdata
+ length
+Output : ret
+function : send data to icn85xx , prog mode
+***********************************************************************************************/
+int icn85xx_prog_i2c_txdata(unsigned int addr, char *txdata, int length)
+{
+ int ret = -1;
+ char tmp_buf[128];
+ int retries = 0;
+ struct i2c_msg msg[] = {
+ {
+ .addr = ICN85XX_PROG_IIC_ADDR,//this_client->addr,
+ .flags = 0,
+ .len = length + 3,
+ .buf = tmp_buf,
+#if SUPPORT_ROCKCHIP
+ .scl_rate = ICN85XX_I2C_SCL,
+#endif
+ },
+ };
+
+ if (length > 125)
+ {
+ icn85xx_error("%s too big datalen = %d!\n", __func__, length);
+ return -1;
+ }
+
+ tmp_buf[0] = (unsigned char)(addr>>16);
+ tmp_buf[1] = (unsigned char)(addr>>8);
+ tmp_buf[2] = (unsigned char)(addr);
+
+
+ if (length != 0 && txdata != NULL)
+ {
+ memcpy(&tmp_buf[3], txdata, length);
+ }
+
+ while(retries < IIC_RETRY_NUM)
+ {
+ ret = i2c_transfer(this_client->adapter, msg, 1);
+ if(ret == 1)break;
+ retries++;
+ }
+
+ if (retries >= IIC_RETRY_NUM)
+ {
+ icn85xx_error("%s i2c write error: %d\n", __func__, ret);
+// icn85xx_ts_reset();
+ }
+ return ret;
+}
+/***********************************************************************************************
+Name : icn85xx_prog_write_reg
+Input : addr -- address
+ para -- parameter
+Output :
+function : write register of icn85xx, prog mode
+***********************************************************************************************/
+int icn85xx_prog_write_reg(unsigned int addr, char para)
+{
+ char buf[3];
+ int ret = -1;
+
+ buf[0] = para;
+ ret = icn85xx_prog_i2c_txdata(addr, buf, 1);
+ if (ret < 0) {
+ icn85xx_error("%s write reg failed! %#x ret: %d\n", __func__, buf[0], ret);
+ return -1;
+ }
+
+ return ret;
+}
+
+
+/***********************************************************************************************
+Name : icn85xx_prog_read_reg
+Input : addr
+ pdata
+Output :
+function : read register of icn85xx, prog mode
+***********************************************************************************************/
+int icn85xx_prog_read_reg(unsigned int addr, char *pdata)
+{
+ int ret = -1;
+ ret = icn85xx_prog_i2c_rxdata(addr, pdata, 1);
+ return ret;
+}
+
+/***********************************************************************************************
+Name : icn85xx_i2c_rxdata
+Input : addr
+ *rxdata
+ length
+Output : ret
+function : read data from icn85xx, normal mode
+***********************************************************************************************/
+int icn85xx_i2c_rxdata(unsigned short addr, char *rxdata, int length)
+{
+ int ret = -1;
+ int retries = 0;
+ unsigned char tmp_buf[2];
+#if 0
+
+ struct i2c_msg msgs[] = {
+ {
+ .addr = this_client->addr,
+ .flags = 0,
+ .len = 2,
+ .buf = tmp_buf,
+#if SUPPORT_ROCKCHIP
+ .scl_rate = ICN85XX_I2C_SCL,
+#endif
+ },
+ {
+ .addr = this_client->addr,
+ .flags = I2C_M_RD,
+ .len = length,
+ .buf = rxdata,
+#if SUPPORT_ROCKCHIP
+ .scl_rate = ICN85XX_I2C_SCL,
+#endif
+ },
+ };
+
+ tmp_buf[0] = (unsigned char)(addr>>8);
+ tmp_buf[1] = (unsigned char)(addr);
+
+
+ while(retries < IIC_RETRY_NUM)
+ {
+ ret = i2c_transfer(this_client->adapter, msgs, 2);
+ if(ret == 2)break;
+ retries++;
+ }
+
+ if (retries >= IIC_RETRY_NUM)
+ {
+ icn85xx_error("%s i2c read error: %d\n", __func__, ret);
+// icn85xx_ts_reset();
+ }
+#else
+
+ tmp_buf[0] = (unsigned char)(addr>>8);
+ tmp_buf[1] = (unsigned char)(addr);
+
+ while(retries < IIC_RETRY_NUM)
+ {
+ // ret = i2c_transfer(this_client->adapter, msgs, 2);
+ ret = i2c_master_send(this_client, tmp_buf, 2);
+ if (ret < 0)
+ return ret;
+ ret = i2c_master_recv(this_client, rxdata, length);
+ if (ret < 0)
+ return ret;
+ if(ret == length)break;
+ retries++;
+ }
+
+ if (retries >= IIC_RETRY_NUM)
+ {
+ icn85xx_error("%s i2c read error: %d\n", __func__, ret);
+// icn85xx_ts_reset();
+ }
+#endif
+
+ return ret;
+}
+/***********************************************************************************************
+Name : icn85xx_i2c_txdata
+Input : addr
+ *rxdata
+ length
+Output : ret
+function : send data to icn85xx , normal mode
+***********************************************************************************************/
+int icn85xx_i2c_txdata(unsigned short addr, char *txdata, int length)
+{
+ int ret = -1;
+ unsigned char tmp_buf[128];
+ int retries = 0;
+
+ struct i2c_msg msg[] = {
+ {
+ .addr = this_client->addr,
+ .flags = 0,
+ .len = length + 2,
+ .buf = tmp_buf,
+#if SUPPORT_ROCKCHIP
+ .scl_rate = ICN85XX_I2C_SCL,
+#endif
+ },
+ };
+
+ if (length > 125)
+ {
+ icn85xx_error("%s too big datalen = %d!\n", __func__, length);
+ return -1;
+ }
+
+ tmp_buf[0] = (unsigned char)(addr>>8);
+ tmp_buf[1] = (unsigned char)(addr);
+
+ if (length != 0 && txdata != NULL)
+ {
+ memcpy(&tmp_buf[2], txdata, length);
+ }
+
+ while(retries < IIC_RETRY_NUM)
+ {
+ ret = i2c_transfer(this_client->adapter, msg, 1);
+ if(ret == 1)break;
+ retries++;
+ }
+
+ if (retries >= IIC_RETRY_NUM)
+ {
+ icn85xx_error("%s i2c write error: %d\n", __func__, ret);
+// icn85xx_ts_reset();
+ }
+
+ return ret;
+}
+
+/***********************************************************************************************
+Name : icn85xx_write_reg
+Input : addr -- address
+ para -- parameter
+Output :
+function : write register of icn85xx, normal mode
+***********************************************************************************************/
+int icn85xx_write_reg(unsigned short addr, char para)
+{
+ char buf[3];
+ int ret = -1;
+
+ buf[0] = para;
+ ret = icn85xx_i2c_txdata(addr, buf, 1);
+ if (ret < 0) {
+ icn85xx_error("write reg failed! %#x ret: %d\n", buf[0], ret);
+ return -1;
+ }
+
+ return ret;
+}
+
+
+/***********************************************************************************************
+Name : icn85xx_read_reg
+Input : addr
+ pdata
+Output :
+function : read register of icn85xx, normal mode
+***********************************************************************************************/
+int icn85xx_read_reg(unsigned short addr, char *pdata)
+{
+ int ret = -1;
+ ret = icn85xx_i2c_rxdata(addr, pdata, 1);
+ if(ret < 0)
+ {
+ icn85xx_error("addr: 0x%x: 0x%x\n", addr, *pdata);
+ }
+ return ret;
+}
+
+
+/***********************************************************************************************
+Name : icn85xx_log
+Input : 0: rawdata, 1: diff data
+Output : err type
+function : calibrate param
+***********************************************************************************************/
+static void icn85xx_log(char diff)
+{
+ char row = 0;
+ char column = 0;
+ int i, j, ret;
+ char retvalue = 0;
+
+ icn85xx_read_reg(0x8004, &row);
+ icn85xx_read_reg(0x8005, &column);
+
+ //scan tp rawdata
+ icn85xx_write_reg(4, 0x20);
+ mdelay(1);
+ for(i=0; i<1000; i++)
+ {
+ mdelay(1);
+ icn85xx_read_reg(2, &retvalue);
+ if(retvalue == 1)
+ break;
+ }
+ if(diff == 0)
+ {
+ for(i=0; i<row; i++)
+ {
+ ret = icn85xx_i2c_rxdata(0x2000 + i*COL_NUM*2, (char *)&log_rawdata[i][0], column*2);
+ if (ret < 0) {
+ icn85xx_error("%s read_data i2c_rxdata failed: %d\n", __func__, ret);
+ }
+ icn85xx_rawdatadump(&log_rawdata[i][0], column, COL_NUM);
+
+ }
+ }
+ if(diff == 1)
+ {
+ for(i=0; i<row; i++)
+ {
+ ret = icn85xx_i2c_rxdata(0x3000 + (i+1)*(COL_NUM+2)*2 + 2, (char *)&log_diffdata[i][0], column*2);
+ if (ret < 0) {
+ icn85xx_error("%s read_data i2c_rxdata failed: %d\n", __func__, ret);
+ }
+ icn85xx_rawdatadump(&log_diffdata[i][0], column, COL_NUM);
+
+ }
+ }
+ else if(diff == 2)
+ {
+ for(i=0; i<row; i++)
+ {
+ ret = icn85xx_i2c_rxdata(0x2000 + i*COL_NUM*2, (char *)&log_rawdata[i][0], column*2);
+ if (ret < 0) {
+ icn85xx_error("%s read_data i2c_rxdata failed: %d\n", __func__, ret);
+ }
+ if((log_basedata[0][0] != 0) || (log_basedata[0][1] != 0))
+ {
+ for(j=0; j<column; j++)
+ {
+ log_rawdata[i][j] = log_basedata[i][j] - log_rawdata[i][j];
+ }
+ }
+ icn85xx_rawdatadump(&log_rawdata[i][0], column, COL_NUM);
+
+ }
+ if((log_basedata[0][0] == 0) && (log_basedata[0][1] == 0))
+ {
+ memcpy(&log_basedata[0][0], &log_rawdata[0][0], COL_NUM*ROW_NUM*2);
+ }
+
+
+ }
+
+ //finish scan tp rawdata
+ icn85xx_write_reg(2, 0x0);
+ icn85xx_write_reg(4, 0x21);
+}
+
+
+/***********************************************************************************************
+Name : icn85xx_iic_test
+Input : void
+Output :
+function : 0 success,
+***********************************************************************************************/
+static int icn85xx_iic_test(void)
+{
+ struct icn85xx_ts_data *icn85xx_ts = i2c_get_clientdata(this_client);
+ int ret = -1;
+ char value = 0;
+ int retry = 0;
+ int flashid;
+ icn85xx_ts->ictype = 0;
+ icn85xx_trace("====%s begin=====. \n", __func__);
+
+ while(retry++ < 3)
+ {
+ ret = icn85xx_read_reg(0xa, &value);
+ if(ret > 0)
+ {
+ if(value == 0x85)
+ {
+ icn85xx_ts->ictype = ICN85XX_WITH_FLASH;
+ return ret;
+ }
+ }
+
+ icn85xx_info("iic test error! retry = %d\n", retry);
+ msleep(3);
+ }
+ icn85xx_goto_progmode();
+ msleep(10);
+ retry = 0;
+ while(retry++ < 3)
+ {
+ ret = icn85xx_prog_i2c_rxdata(0x040002, &value, 1);
+ icn85xx_info("icn85xx_check_progmod: 0x%x\n", value);
+ if(ret > 0)
+ {
+ if(value == 0x85)
+ {
+ flashid = icn85xx_read_flashid();
+ if((MD25D40_ID1 == flashid) || (MD25D40_ID2 == flashid)
+ ||(MD25D20_ID1 == flashid) || (MD25D20_ID1 == flashid)
+ ||(GD25Q10_ID == flashid) || (MX25L512E_ID == flashid))
+ {
+ icn85xx_ts->ictype = ICN85XX_WITH_FLASH;
+ }
+ else
+ {
+ icn85xx_ts->ictype = ICN85XX_WITHOUT_FLASH;
+ }
+ return ret;
+ }
+ }
+ icn85xx_error("iic2 test error! %d\n", retry);
+ msleep(3);
+ }
+
+ return ret;
+}
+
+#if !CTP_REPORT_PROTOCOL
+/***********************************************************************************************
+Name : icn85xx_ts_release
+Input : void
+Output :
+function : touch release
+***********************************************************************************************/
+static void icn85xx_ts_release(void)
+{
+ struct icn85xx_ts_data *icn85xx_ts = i2c_get_clientdata(this_client);
+ icn85xx_info("==icn85xx_ts_release ==\n");
+ input_report_abs(icn85xx_ts->input_dev, ABS_MT_TOUCH_MAJOR, 0);
+ input_sync(icn85xx_ts->input_dev);
+}
+
+/***********************************************************************************************
+Name : icn85xx_report_value_A
+Input : void
+Output :
+function : reprot touch ponit
+***********************************************************************************************/
+static void icn85xx_report_value_A(void)
+{
+ struct icn85xx_ts_data *icn85xx_ts = i2c_get_clientdata(this_client);
+ char buf[POINT_NUM*POINT_SIZE+3]={0};
+ int ret = -1;
+ int i;
+#if TOUCH_VIRTUAL_KEYS
+ unsigned char button;
+ static unsigned char button_last;
+#endif
+
+ icn85xx_info("==icn85xx_report_value_A ==\n");
+
+ ret = icn85xx_i2c_rxdata(0x1000, buf, POINT_NUM*POINT_SIZE+2);
+ if (ret < 0) {
+ icn85xx_error("%s read_data i2c_rxdata failed: %d\n", __func__, ret);
+ return ;
+ }
+#if TOUCH_VIRTUAL_KEYS
+ button = buf[0];
+ icn85xx_info("%s: button=%d\n",__func__, button);
+
+ if((button_last != 0) && (button == 0))
+ {
+ icn85xx_ts_release();
+ button_last = button;
+ return ;
+ }
+ if(button != 0)
+ {
+ switch(button)
+ {
+ case ICN_VIRTUAL_BUTTON_HOME:
+ icn85xx_info("ICN_VIRTUAL_BUTTON_HOME down\n");
+ input_report_abs(icn85xx_ts->input_dev, ABS_MT_TOUCH_MAJOR, 200);
+ input_report_abs(icn85xx_ts->input_dev, ABS_MT_POSITION_X, 280);
+ input_report_abs(icn85xx_ts->input_dev, ABS_MT_POSITION_Y, 1030);
+ input_report_abs(icn85xx_ts->input_dev, ABS_MT_WIDTH_MAJOR, 1);
+ input_mt_sync(icn85xx_ts->input_dev);
+ input_sync(icn85xx_ts->input_dev);
+ break;
+ case ICN_VIRTUAL_BUTTON_BACK:
+ icn85xx_info("ICN_VIRTUAL_BUTTON_BACK down\n");
+ input_report_abs(icn85xx_ts->input_dev, ABS_MT_TOUCH_MAJOR, 200);
+ input_report_abs(icn85xx_ts->input_dev, ABS_MT_POSITION_X, 470);
+ input_report_abs(icn85xx_ts->input_dev, ABS_MT_POSITION_Y, 1030);
+ input_report_abs(icn85xx_ts->input_dev, ABS_MT_WIDTH_MAJOR, 1);
+ input_mt_sync(icn85xx_ts->input_dev);
+ input_sync(icn85xx_ts->input_dev);
+ break;
+ case ICN_VIRTUAL_BUTTON_MENU:
+ icn85xx_info("ICN_VIRTUAL_BUTTON_MENU down\n");
+ input_report_abs(icn85xx_ts->input_dev, ABS_MT_TOUCH_MAJOR, 200);
+ input_report_abs(icn85xx_ts->input_dev, ABS_MT_POSITION_X, 100);
+ input_report_abs(icn85xx_ts->input_dev, ABS_MT_POSITION_Y, 1030);
+ input_report_abs(icn85xx_ts->input_dev, ABS_MT_WIDTH_MAJOR, 1);
+ input_mt_sync(icn85xx_ts->input_dev);
+ input_sync(icn85xx_ts->input_dev);
+ break;
+ default:
+ icn85xx_info("other gesture\n");
+ break;
+ }
+ button_last = button;
+ return ;
+ }
+#endif
+
+ icn85xx_ts->point_num = buf[1];
+ if (icn85xx_ts->point_num == 0) {
+ icn85xx_ts_release();
+ return ;
+ }
+ for(i=0;i<icn85xx_ts->point_num;i++){
+ if(buf[8 + POINT_SIZE*i] != 4)
+ {
+ break ;
+ }
+ else
+ {
+
+ }
+ }
+
+ if(i == icn85xx_ts->point_num) {
+ icn85xx_ts_release();
+ return ;
+ }
+
+ for(i=0; i<icn85xx_ts->point_num; i++)
+ {
+ icn85xx_ts->point_info[i].u8ID = buf[2 + POINT_SIZE*i];
+ icn85xx_ts->point_info[i].u16PosX = (buf[4 + POINT_SIZE*i]<<8) + buf[3 + POINT_SIZE*i];
+ icn85xx_ts->point_info[i].u16PosY = (buf[6 + POINT_SIZE*i]<<8) + buf[5 + POINT_SIZE*i];
+ icn85xx_ts->point_info[i].u8Pressure = 20;//buf[7 + POINT_SIZE*i];
+ icn85xx_ts->point_info[i].u8EventId = buf[8 + POINT_SIZE*i];
+
+ if(1 == icn85xx_ts->revert_x_flag)
+ {
+ icn85xx_ts->point_info[i].u16PosX = icn85xx_ts->screen_max_x- icn85xx_ts->point_info[i].u16PosX;
+ }
+ if(1 == icn85xx_ts->revert_y_flag)
+ {
+ icn85xx_ts->point_info[i].u16PosY = icn85xx_ts->screen_max_y- icn85xx_ts->point_info[i].u16PosY;
+ }
+
+ icn85xx_info("u8ID %d\n", icn85xx_ts->point_info[i].u8ID);
+ icn85xx_info("u16PosX %d\n", icn85xx_ts->point_info[i].u16PosX);
+ icn85xx_info("u16PosY %d\n", icn85xx_ts->point_info[i].u16PosY);
+ icn85xx_info("u8Pressure %d\n", icn85xx_ts->point_info[i].u8Pressure);
+ icn85xx_info("u8EventId %d\n", icn85xx_ts->point_info[i].u8EventId);
+
+
+ input_report_abs(icn85xx_ts->input_dev, ABS_MT_TRACKING_ID, icn85xx_ts->point_info[i].u8ID);
+ input_report_abs(icn85xx_ts->input_dev, ABS_MT_TOUCH_MAJOR, icn85xx_ts->point_info[i].u8Pressure);
+ input_report_abs(icn85xx_ts->input_dev, ABS_MT_POSITION_X, icn85xx_ts->point_info[i].u16PosX);
+ input_report_abs(icn85xx_ts->input_dev, ABS_MT_POSITION_Y, icn85xx_ts->point_info[i].u16PosY);
+ input_report_abs(icn85xx_ts->input_dev, ABS_MT_WIDTH_MAJOR, 1);
+ input_mt_sync(icn85xx_ts->input_dev);
+ icn85xx_point_info("point: %d ===x = %d,y = %d, press = %d ====\n",i, icn85xx_ts->point_info[i].u16PosX,icn85xx_ts->point_info[i].u16PosY, icn85xx_ts->point_info[i].u8Pressure);
+ }
+
+ input_sync(icn85xx_ts->input_dev);
+
+}
+#endif
+/***********************************************************************************************
+Name : icn85xx_report_value_B
+Input : void
+Output :
+function : reprot touch ponit
+***********************************************************************************************/
+#if CTP_REPORT_PROTOCOL
+static void icn85xx_report_value_B(void)
+{
+ struct icn85xx_ts_data *icn85xx_ts = i2c_get_clientdata(this_client);
+ char buf[POINT_NUM*POINT_SIZE+3]={0};
+ static unsigned char finger_last[POINT_NUM + 1]={0};
+ unsigned char finger_current[POINT_NUM + 1] = {0};
+ unsigned int position = 0;
+ int temp = 0;
+ int ret = -1;
+ int x,y;
+ icn85xx_info("==icn85xx_report_value_B ==\n");
+
+
+
+ ret = icn85xx_i2c_rxdata(0x1000, buf, POINT_NUM*POINT_SIZE+2);
+ if (ret < 0) {
+ icn85xx_error("%s read_data i2c_rxdata failed: %d\n", __func__, ret);
+ return ;
+ }
+ icn85xx_ts->point_num = buf[1];
+ if (icn85xx_ts->point_num > POINT_NUM)
+ {
+ return ;
+ }
+
+ if(icn85xx_ts->point_num > 0)
+ {
+ for(position = 0; position<icn85xx_ts->point_num; position++)
+ {
+ temp = buf[2 + POINT_SIZE*position] + 1;
+ finger_current[temp] = 1;
+ icn85xx_ts->point_info[temp].u8ID = buf[2 + POINT_SIZE*position];
+ icn85xx_ts->point_info[temp].u16PosX = (buf[4 + POINT_SIZE*position]<<8) + buf[3 + POINT_SIZE*position];
+ icn85xx_ts->point_info[temp].u16PosY = (buf[6 + POINT_SIZE*position]<<8) + buf[5 + POINT_SIZE*position];
+ icn85xx_ts->point_info[temp].u8Pressure = buf[7 + POINT_SIZE*position];
+ icn85xx_ts->point_info[temp].u8EventId = buf[8 + POINT_SIZE*position];
+
+ if(icn85xx_ts->point_info[temp].u8EventId == 4)
+ finger_current[temp] = 0;
+
+ if(1 == icn85xx_ts->revert_x_flag)
+ {
+ icn85xx_ts->point_info[temp].u16PosX = icn85xx_ts->screen_max_x- icn85xx_ts->point_info[temp].u16PosX;
+ }
+ if(1 == icn85xx_ts->revert_y_flag)
+ {
+ icn85xx_ts->point_info[temp].u16PosY = icn85xx_ts->screen_max_y- icn85xx_ts->point_info[temp].u16PosY;
+ }
+ icn85xx_info("temp %d\n", temp);
+ icn85xx_info("u8ID %d\n", icn85xx_ts->point_info[temp].u8ID);
+ icn85xx_info("u16PosX %d\n", icn85xx_ts->point_info[temp].u16PosX);
+ icn85xx_info("u16PosY %d\n", icn85xx_ts->point_info[temp].u16PosY);
+ icn85xx_info("u8Pressure %d\n", icn85xx_ts->point_info[temp].u8Pressure);
+ icn85xx_info("u8EventId %d\n", icn85xx_ts->point_info[temp].u8EventId);
+ //icn85xx_info("u8Pressure %d\n", icn85xx_ts->point_info[temp].u8Pressure*16);
+ }
+ }
+ else
+ {
+ for(position = 1; position < POINT_NUM+1; position++)
+ {
+ finger_current[position] = 0;
+ }
+ icn85xx_info("no touch\n");
+ }
+
+ for(position = 1; position < POINT_NUM + 1; position++)
+ {
+ if((finger_current[position] == 0) && (finger_last[position] != 0))
+ {
+ input_mt_slot(icn85xx_ts->input_dev, position-1);
+ input_mt_report_slot_state(icn85xx_ts->input_dev, MT_TOOL_FINGER, false);
+ icn85xx_point_info("one touch up: %d\n", position);
+ }
+ else if(finger_current[position])
+ {
+ if (g_param.xyswap == 0)
+ {
+ x = icn85xx_ts->point_info[position].u16PosX;
+ y = icn85xx_ts->point_info[position].u16PosY;
+ } else {
+ y = icn85xx_ts->point_info[position].u16PosX;
+ x = icn85xx_ts->point_info[position].u16PosY;
+ }
+ if (g_param.xdir == -1)
+ {
+ x = g_param.panelres_x - x;
+ }
+ if (g_param.ydir == -1)
+ {
+ y = g_param.panelres_y - y;
+ }
+
+ if (g_param.lcd_exchg) {
+ int tmp;
+ tmp = x;
+ x = y;
+ y = g_param.panelres_x - tmp;
+ }
+
+ input_mt_slot(icn85xx_ts->input_dev, position-1);
+ input_mt_report_slot_state(icn85xx_ts->input_dev, MT_TOOL_FINGER, true);
+ input_report_abs(icn85xx_ts->input_dev, ABS_MT_TOUCH_MAJOR, 1);
+ //input_report_abs(icn85xx_ts->input_dev, ABS_MT_PRESSURE, icn85xx_ts->point_info[position].u8Pressure);
+ input_report_abs(icn85xx_ts->input_dev, ABS_MT_PRESSURE, 200);
+ input_report_abs(icn85xx_ts->input_dev, ABS_MT_POSITION_X, x);
+ input_report_abs(icn85xx_ts->input_dev, ABS_MT_POSITION_Y, y);
+ //icn85xx_point_info("===position: %d, x = %d,y = %d, press = %d ====\n", position, icn85xx_ts->point_info[position].u16PosX,icn85xx_ts->point_info[position].u16PosY, icn85xx_ts->point_info[position].u8Pressure);
+ icn85xx_point_info("raw%d(%d,%d), rpt%d(%d,%d)\n", position, icn85xx_ts->point_info[position].u16PosX, icn85xx_ts->point_info[position].u16PosY, position, x, y);
+ }
+
+ }
+ input_sync(icn85xx_ts->input_dev);
+
+ for(position = 1; position < POINT_NUM + 1; position++)
+ {
+ finger_last[position] = finger_current[position];
+ }
+
+}
+#endif
+
+/***********************************************************************************************
+Name : icn85xx_ts_pen_irq_work
+Input : void
+Output :
+function : work_struct
+***********************************************************************************************/
+static void icn85xx_ts_pen_irq_work(struct work_struct *work)
+{
+ struct icn85xx_ts_data *icn85xx_ts = i2c_get_clientdata(this_client);
+#if SUPPORT_PROC_FS
+ if(down_interruptible(&icn85xx_ts->sem))
+ {
+ return ;
+ }
+#endif
+
+ if(icn85xx_ts->work_mode == 0)
+ {
+#if CTP_REPORT_PROTOCOL
+ icn85xx_report_value_B();
+#else
+ icn85xx_report_value_A();
+#endif
+
+
+ if(icn85xx_ts->use_irq)
+ {
+ icn85xx_irq_enable();
+ }
+ if(log_on_off == 4)
+ {
+ printk("normal raw data\n");
+ icn85xx_log(0); //raw data
+ }
+ else if(log_on_off == 5)
+ {
+ printk("normal diff data\n");
+ icn85xx_log(1); //diff data
+ }
+ else if(log_on_off == 6)
+ {
+ printk("normal raw2diff\n");
+ icn85xx_log(2); //diff data
+ }
+
+ }
+ else if(icn85xx_ts->work_mode == 1)
+ {
+ printk("raw data\n");
+ icn85xx_log(0); //raw data
+ }
+ else if(icn85xx_ts->work_mode == 2)
+ {
+ printk("diff data\n");
+ icn85xx_log(1); //diff data
+ }
+ else if(icn85xx_ts->work_mode == 3)
+ {
+ printk("raw2diff data\n");
+ icn85xx_log(2); //diff data
+ }
+ else if(icn85xx_ts->work_mode == 4) //idle
+ {
+ ;
+ }
+ else if(icn85xx_ts->work_mode == 5)//write para, reinit
+ {
+ printk("reinit tp\n");
+ icn85xx_write_reg(0, 1);
+ mdelay(100);
+ icn85xx_write_reg(0, 0);
+ icn85xx_ts->work_mode = 0;
+ }
+
+#if SUPPORT_PROC_FS
+ up(&icn85xx_ts->sem);
+#endif
+
+
+}
+/***********************************************************************************************
+Name : chipone_timer_func
+Input : void
+Output :
+function : Timer interrupt service routine.
+***********************************************************************************************/
+static enum hrtimer_restart chipone_timer_func(struct hrtimer *timer)
+{
+ struct icn85xx_ts_data *icn85xx_ts = container_of(timer, struct icn85xx_ts_data, timer);
+ queue_work(icn85xx_ts->ts_workqueue, &icn85xx_ts->pen_event_work);
+ //icn85xx_info("chipone_timer_func\n");
+ if(icn85xx_ts->use_irq == 1)
+ {
+ if((icn85xx_ts->work_mode == 1) || (icn85xx_ts->work_mode == 2) || (icn85xx_ts->work_mode == 3))
+ {
+ hrtimer_start(&icn85xx_ts->timer, ktime_set(CTP_POLL_TIMER/1000, (CTP_POLL_TIMER%1000)*1000000), HRTIMER_MODE_REL);
+ }
+ }
+ else
+ {
+ hrtimer_start(&icn85xx_ts->timer, ktime_set(CTP_POLL_TIMER/1000, (CTP_POLL_TIMER%1000)*1000000), HRTIMER_MODE_REL);
+ }
+ return HRTIMER_NORESTART;
+}
+/***********************************************************************************************
+Name : icn85xx_ts_interrupt
+Input : void
+Output :
+function : interrupt service routine
+***********************************************************************************************/
+static irqreturn_t icn85xx_ts_interrupt(int irq, void *dev_id)
+{
+ struct icn85xx_ts_data *icn85xx_ts = dev_id;
+ int irqindex = g_param.irqgpio;
+
+ icn85xx_info("==========------icn85xx_ts TS Interrupt-----============\n");
+
+ if (gpio_irqstatus(irqindex)) {
+ wmt_gpio_ack_irq(irqindex);
+ if (is_gpio_irqenable(irqindex)) {
+ icn85xx_irq_disable();
+ if(icn85xx_ts->work_mode != 0) {
+ icn85xx_irq_enable();
+ return IRQ_HANDLED;
+ }
+ if (!work_pending(&icn85xx_ts->pen_event_work)) {
+ icn85xx_info("Enter work\n");
+ queue_work(icn85xx_ts->ts_workqueue, &icn85xx_ts->pen_event_work);
+ }
+ }
+ return IRQ_HANDLED;
+ }
+ return IRQ_NONE;
+
+ /*if(icn85xx_ts->use_irq)
+ icn85xx_irq_disable();
+ if (!work_pending(&icn85xx_ts->pen_event_work))
+ {
+ queue_work(icn85xx_ts->ts_workqueue, &icn85xx_ts->pen_event_work);
+
+ }
+
+ return IRQ_HANDLED;*/
+}
+
+/***********************************************************************************************
+Name : icn85xx_ts_suspend
+Input : void
+Output :
+function : tp enter sleep mode
+***********************************************************************************************/
+static int icn85xx_ts_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+ struct icn85xx_ts_data *icn85xx_ts = i2c_get_clientdata(client);
+ icn85xx_trace("icn85xx_ts_suspend\n");
+ if (icn85xx_ts->use_irq) {
+ icn85xx_irq_disable();
+ } else {
+ hrtimer_cancel(&icn85xx_ts->timer);
+ }
+ cancel_work_sync(&icn85xx_ts->pen_event_work);
+ flush_workqueue(icn85xx_ts->ts_workqueue);
+ //}
+
+ //reset flag if ic is flashless when power off
+ if(icn85xx_ts->ictype == ICN85XX_WITHOUT_FLASH)
+ {
+ //icn85xx_ts->code_loaded_flag = 0;
+ }
+#if SUSPEND_POWER_OFF
+
+#else
+ icn85xx_write_reg(ICN85xx_REG_PMODE, PMODE_HIBERNATE);
+#endif
+
+ return 0;
+
+}
+
+int resume_download_thread(void *arg)
+{
+ int retry = 1;
+ int need_update_fw = false;
+ int ret = -1;
+ unsigned char value;
+ struct icn85xx_ts_data *icn85xx_ts = (struct icn85xx_ts_data*)arg;
+ wake_lock(&downloadWakeLock);
+ while (retry-- && !need_update_fw) {
+ icn85xx_ts_reset();
+ icn85xx_bootfrom_sram();
+ msleep(50);
+ ret = icn85xx_read_reg(0xa, &value);
+ if (ret > 0) {
+ need_update_fw = false;
+ break;
+ }
+ }
+ if (retry < 0) need_update_fw = true;
+
+ if (need_update_fw) {
+ if(R_OK == icn85xx_fw_update(firmware)) {
+ icn85xx_ts->code_loaded_flag = 1;
+ icn85xx_trace("ICN85XX_WITHOUT_FLASH, reload code ok\n");
+ }
+ else {
+ icn85xx_ts->code_loaded_flag = 0;
+ icn85xx_trace("ICN85XX_WITHOUT_FLASH, reload code error\n");
+ }
+ }
+
+ if (icn85xx_ts->use_irq) {
+ icn85xx_irq_enable();
+ } else {
+ hrtimer_start(&icn85xx_ts->timer, ktime_set(CTP_START_TIMER/1000, \
+ (CTP_START_TIMER%1000)*1000000), HRTIMER_MODE_REL);
+ }
+ wake_unlock(&downloadWakeLock);
+ return 0;
+}
+
+/***********************************************************************************************
+Name : icn85xx_ts_resume
+Input : void
+Output :
+function : wakeup tp or reset tp
+***********************************************************************************************/
+static int icn85xx_ts_resume(struct i2c_client *client)
+{
+ struct icn85xx_ts_data *icn85xx_ts = i2c_get_clientdata(client);
+ int i;
+ icn85xx_trace("==icn85xx_ts_resume== \n");
+
+ //report touch release
+#if CTP_REPORT_PROTOCOL
+ for(i = 0; i < POINT_NUM; i++)
+ {
+ input_mt_slot(icn85xx_ts->input_dev, i);
+ input_mt_report_slot_state(icn85xx_ts->input_dev, MT_TOOL_FINGER, false);
+ }
+#else
+ icn85xx_ts_release();
+#endif
+
+
+ if(icn85xx_ts->ictype == ICN85XX_WITHOUT_FLASH) {
+ if (bl_is_delay) {
+ resume_download_task = kthread_create(resume_download_thread, icn85xx_ts, "resume_download");
+ if(IS_ERR(resume_download_task)) {
+ icn85xx_error("cread thread failed\n");
+ }
+ wake_up_process(resume_download_task);
+ } else
+ resume_download_thread(icn85xx_ts);
+ } else {
+ icn85xx_write_reg(ICN85xx_REG_PMODE, 0xff);
+ icn85xx_ts_reset();
+ if (icn85xx_ts->use_irq) {
+ icn85xx_irq_enable();
+ } else {
+ hrtimer_start(&icn85xx_ts->timer, ktime_set(CTP_START_TIMER/1000, \
+ (CTP_START_TIMER%1000)*1000000), HRTIMER_MODE_REL);
+ }
+ }
+
+ // icn85xx_write_reg(ICN85xx_REG_PMODE, 0x00);
+ return 0;
+}
+
+/***********************************************************************************************
+Name : icn85xx_request_io_port
+Input : void
+Output :
+function : 0 success,
+***********************************************************************************************/
+static int icn85xx_request_io_port(struct icn85xx_ts_data *icn85xx_ts)
+{
+
+#if SUPPORT_ROCKCHIP
+ icn85xx_ts->screen_max_x = SCREEN_MAX_X;
+ icn85xx_ts->screen_max_y = SCREEN_MAX_Y;
+ icn85xx_ts->irq = CTP_IRQ_PORT; //maybe need changed
+#endif
+ icn85xx_ts->irq = IRQ_GPIO;
+
+ if (gpio_request(g_param.rstgpio, "ts_rst") < 0) {
+ printk("gpio(%d) touchscreen reset request fail\n", g_param.rstgpio);
+ return -EIO;
+ }
+ gpio_direction_output(g_param.rstgpio, 1);
+
+ if (gpio_request(g_param.irqgpio, "ts_irq") < 0) {
+ printk("gpio(%d) touchscreen interrupt request fail\n", g_param.irqgpio);
+ gpio_free(g_param.rstgpio);
+ return -EIO;
+ }
+ wmt_gpio_setpull(g_param.irqgpio, WMT_GPIO_PULL_UP);
+ gpio_direction_input(g_param.irqgpio);
+
+
+ return 0;
+
+}
+
+/***********************************************************************************************
+Name : icn85xx_free_io_port
+Input : void
+Output :
+function : 0 success,
+***********************************************************************************************/
+static void icn85xx_free_io_port(void)
+{
+ gpio_free(g_param.rstgpio);
+ gpio_free(g_param.irqgpio);
+ return;
+}
+
+/***********************************************************************************************
+Name : icn85xx_request_irq
+Input : void
+Output :
+function : 0 success,
+***********************************************************************************************/
+static int icn85xx_request_irq(struct icn85xx_ts_data *icn85xx_ts)
+{
+ int err = -1;
+
+
+ wmt_gpio_set_irq_type(g_param.irqgpio, IRQ_TYPE_EDGE_FALLING);
+ err = request_irq(icn85xx_ts->irq, icn85xx_ts_interrupt, IRQF_SHARED, "icn85xx_ts", icn85xx_ts);
+ if (err < 0)
+ {
+ icn85xx_error("icn85xx_ts_probe: request irq failed\n");
+ return err;
+ }
+ else
+ {
+ icn85xx_irq_disable();
+ icn85xx_ts->use_irq = 1;
+ }
+
+#if SUPPORT_ROCKCHIP
+ err = gpio_request(icn85xx_ts->irq, "TS_INT"); //Request IO
+ if (err < 0)
+ {
+ icn85xx_error("Failed to request GPIO:%d, ERRNO:%d\n", (int)icn85xx_ts->irq, err);
+ return err;
+ }
+ gpio_direction_input(icn85xx_ts->irq);
+ err = request_irq(icn85xx_ts->irq, icn85xx_ts_interrupt, IRQ_TYPE_EDGE_FALLING, "icn85xx_ts", icn85xx_ts);
+ if (err < 0)
+ {
+ icn85xx_ts->use_irq = 0;
+ icn85xx_error("icn85xx_ts_probe: request irq failed\n");
+ return err;
+ }
+ else
+ {
+ icn85xx_irq_disable();
+ icn85xx_ts->use_irq = 1;
+ }
+#endif
+
+ return 0;
+}
+
+
+/***********************************************************************************************
+Name : icn85xx_free_irq
+Input : void
+Output :
+function : 0 success,
+***********************************************************************************************/
+static void icn85xx_free_irq(struct icn85xx_ts_data *icn85xx_ts)
+{
+ if (icn85xx_ts)
+ {
+ if (icn85xx_ts->use_irq)
+ {
+ free_irq(icn85xx_ts->irq, icn85xx_ts);
+ }
+ else
+ {
+ hrtimer_cancel(&icn85xx_ts->timer);
+ }
+ }
+
+}
+
+/***********************************************************************************************
+Name : icn85xx_request_input_dev
+Input : void
+Output :
+function : 0 success,
+***********************************************************************************************/
+static int icn85xx_request_input_dev(struct icn85xx_ts_data *icn85xx_ts)
+{
+ int ret = -1;
+ struct input_dev *input_dev;
+
+ input_dev = input_allocate_device();
+ if (!input_dev) {
+ icn85xx_error("failed to allocate input device\n");
+ return -ENOMEM;
+ }
+ icn85xx_ts->input_dev = input_dev;
+
+ icn85xx_ts->input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) ;
+#if CTP_REPORT_PROTOCOL
+ __set_bit(INPUT_PROP_DIRECT, icn85xx_ts->input_dev->propbit);
+ input_mt_init_slots(icn85xx_ts->input_dev, POINT_NUM*2);
+#else
+ set_bit(ABS_MT_TOUCH_MAJOR, icn85xx_ts->input_dev->absbit);
+ set_bit(ABS_MT_POSITION_X, icn85xx_ts->input_dev->absbit);
+ set_bit(ABS_MT_POSITION_Y, icn85xx_ts->input_dev->absbit);
+ set_bit(ABS_MT_WIDTH_MAJOR, icn85xx_ts->input_dev->absbit);
+#endif
+ if (g_param.lcd_exchg) {
+ input_set_abs_params(icn85xx_ts->input_dev, ABS_MT_POSITION_X, 0, g_param.panelres_y, 0, 0);
+ input_set_abs_params(icn85xx_ts->input_dev, ABS_MT_POSITION_Y, 0, g_param.panelres_x, 0, 0);
+ } else {
+ input_set_abs_params(icn85xx_ts->input_dev, ABS_MT_POSITION_X, 0, g_param.panelres_x, 0, 0);
+ input_set_abs_params(icn85xx_ts->input_dev, ABS_MT_POSITION_Y, 0, g_param.panelres_y, 0, 0);
+ }
+ input_set_abs_params(icn85xx_ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0);
+ input_set_abs_params(icn85xx_ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
+ input_set_abs_params(icn85xx_ts->input_dev, ABS_MT_TRACKING_ID, 0, POINT_NUM*2, 0, 0);
+
+ __set_bit(KEY_MENU, input_dev->keybit);
+ __set_bit(KEY_BACK, input_dev->keybit);
+ __set_bit(KEY_HOME, input_dev->keybit);
+ __set_bit(KEY_SEARCH, input_dev->keybit);
+
+ input_dev->name = CTP_NAME;
+ ret = input_register_device(input_dev);
+ if (ret) {
+ icn85xx_error("Register %s input device failed\n", input_dev->name);
+ input_free_device(input_dev);
+ return -ENODEV;
+ }
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ icn85xx_trace("==register_early_suspend =\n");
+ icn85xx_ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+ icn85xx_ts->early_suspend.suspend = icn85xx_ts_suspend;
+ icn85xx_ts->early_suspend.resume = icn85xx_ts_resume;
+ register_early_suspend(&icn85xx_ts->early_suspend);
+#endif
+
+ return 0;
+}
+#if SUPPORT_SENSOR_ID
+static void read_sensor_id(void)
+{
+ int i,ret;
+ //icn85xx_trace("scan sensor id value begin sensor_id_num = %d\n",(sizeof(sensor_id_table)/sizeof(sensor_id_table[0])));
+ ret = icn85xx_read_reg(0x10, &cursensor_id);
+ if(ret > 0)
+ {
+ icn85xx_trace("cursensor_id= 0x%x\n", cursensor_id);
+ }
+ else
+ {
+ icn85xx_error("icn85xx read cursensor_id failed.\n");
+ cursensor_id = -1;
+ }
+
+ ret = icn85xx_read_reg(0x1e, &tarsensor_id);
+ if(ret > 0)
+ {
+ icn85xx_trace("tarsensor_id= 0x%x\n", tarsensor_id);
+ tarsensor_id = -1;
+ }
+ else
+ {
+ icn85xx_error("icn85xx read tarsensor_id failed.\n");
+ }
+ ret = icn85xx_read_reg(0x1f, &id_match);
+ if(ret > 0)
+ {
+ icn85xx_trace("match_flag= 0x%x\n", id_match); // 1: match; 0:not match
+ }
+ else
+ {
+ icn85xx_error("icn85xx read id_match failed.\n");
+ id_match = -1;
+ }
+ // scan sensor id value
+ icn85xx_trace("begin to scan id table,find correct fw or bin. sensor_id_num = %d\n",(sizeof(sensor_id_table)/sizeof(sensor_id_table[0])));
+
+ for(i = 0;i < (sizeof(sensor_id_table)/sizeof(sensor_id_table[0])); i++) // not change tp
+ {
+ if (cursensor_id == sensor_id_table[i].value)
+ {
+ #if COMPILE_FW_WITH_DRIVER
+ icn85xx_set_fw(sensor_id_table[i].size, sensor_id_table[i].fw_name);
+ #else
+ strcpy(firmware,sensor_id_table[i].bin_name);
+ icn85xx_trace("icn85xx matched firmware = %s\n", firmware);
+ #endif
+ icn85xx_trace("icn85xx matched id = 0x%x\n", sensor_id_table[i].value);
+ invalid_id = 1;
+ break;
+ }
+ else
+ {
+ invalid_id = 0;
+ icn85xx_trace("icn85xx not matched id%d= 0x%x\n", i,sensor_id_table[i].value);
+ //icn85xx_trace("not match sensor_id_table[%d].value= 0x%x,bin_name = %s\n",i,sensor_id_table[i].value,sensor_id_table[i].bin_name);
+ }
+ }
+
+}
+static void compare_sensor_id(void)
+{
+ int retry = 5;
+
+ read_sensor_id(); // select sensor id
+
+ if(0 == invalid_id) //not compare sensor id,update default fw or bin
+ {
+ icn85xx_trace("not compare sensor id table,update default: invalid_id= %d, cursensor_id= %d\n", invalid_id,cursensor_id);
+ #if COMPILE_FW_WITH_DRIVER
+ icn85xx_set_fw(sensor_id_table[0].size, sensor_id_table[0].fw_name);
+ #else
+ strcpy(firmware,sensor_id_table[0].bin_name);
+ icn85xx_trace("match default firmware = %s\n", firmware);
+ #endif
+
+ while(retry > 0)
+ {
+ if(R_OK == icn85xx_fw_update(firmware))
+ {
+ icn85xx_trace("icn85xx upgrade default firmware ok\n");
+ break;
+ }
+ retry--;
+ icn85xx_error("icn85xx_fw_update default firmware failed.\n");
+ }
+ }
+
+ if ((1 == invalid_id)&&(0 == id_match)) // tp is changed,update current fw or bin
+ {
+ icn85xx_trace("icn85xx detect tp is changed!!! invalid_id= %d,id_match= %d,\n", invalid_id,id_match);
+ while(retry > 0)
+ {
+ if(R_OK == icn85xx_fw_update(firmware))
+ {
+ icn85xx_trace("icn85xx upgrade cursensor id firmware ok\n");
+ break;
+ }
+ retry--;
+ icn85xx_error("icn85xx_fw_update current id firmware failed.\n");
+ }
+ }
+}
+#endif
+
+static void icn85xx_update(struct icn85xx_ts_data *icn85xx_ts)
+{
+ short fwVersion = 0;
+ short curVersion = 0;
+ int retry = 0;
+
+ if(icn85xx_ts->ictype == ICN85XX_WITHOUT_FLASH)
+ {
+ #if (COMPILE_FW_WITH_DRIVER && !SUPPORT_SENSOR_ID)
+ icn85xx_set_fw(sizeof(icn85xx_fw), &icn85xx_fw[0]);
+ #endif
+
+ #if SUPPORT_SENSOR_ID
+ while(0 == invalid_id ) //reselect sensor id
+ {
+ compare_sensor_id(); // select sensor id
+ icn85xx_trace("invalid_id= %d\n", invalid_id);
+ }
+ #else
+ if(R_OK == icn85xx_fw_update(firmware))
+ {
+ icn85xx_ts->code_loaded_flag = 1;
+ icn85xx_trace("ICN85XX_WITHOUT_FLASH, update default fw ok\n");
+ }
+ else
+ {
+ icn85xx_ts->code_loaded_flag = 0;
+ icn85xx_trace("ICN85XX_WITHOUT_FLASH, update error\n");
+ }
+ #endif
+
+ }
+ else if(icn85xx_ts->ictype == ICN85XX_WITH_FLASH)
+ {
+ #if (COMPILE_FW_WITH_DRIVER && !SUPPORT_SENSOR_ID)
+ icn85xx_set_fw(sizeof(icn85xx_fw), &icn85xx_fw[0]);
+ #endif
+
+ #if SUPPORT_SENSOR_ID
+ while(0 == invalid_id ) //reselect sensor id
+ {
+ compare_sensor_id(); // select sensor id
+ if( 1 == invalid_id)
+ {
+ icn85xx_trace("select sensor id ok. begin compare fwVersion with curversion\n");
+ }
+ }
+ #endif
+
+ fwVersion = icn85xx_read_fw_Ver(firmware);
+ curVersion = icn85xx_readVersion();
+ icn85xx_trace("fwVersion : 0x%x\n", fwVersion);
+ icn85xx_trace("current version: 0x%x\n", curVersion);
+
+ #if FORCE_UPDATA_FW
+ retry = 5;
+ while(retry > 0)
+ {
+ if(icn85xx_goto_progmode() != 0)
+ {
+ printk("icn85xx_goto_progmode() != 0 error\n");
+ return -1;
+ }
+ icn85xx_read_flashid();
+ if(R_OK == icn85xx_fw_update(firmware))
+ {
+ break;
+ }
+ retry--;
+ icn85xx_error("icn85xx_fw_update failed.\n");
+ }
+
+ #else
+ if(fwVersion > curVersion)
+ {
+ retry = 5;
+ while(retry > 0)
+ {
+ if(R_OK == icn85xx_fw_update(firmware))
+ {
+ break;
+ }
+ retry--;
+ icn85xx_error("icn85xx_fw_update failed.\n");
+ }
+ }
+ #endif
+ }
+}
+static int icn85xx_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+ struct icn85xx_ts_data *icn85xx_ts;
+ int err = 0;
+
+ icn85xx_trace("====%s begin=====. \n", __func__);
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+ {
+ icn85xx_error("I2C check functionality failed.\n");
+ return -ENODEV;
+ }
+
+ icn85xx_ts = kzalloc(sizeof(*icn85xx_ts), GFP_KERNEL);
+ if (!icn85xx_ts)
+ {
+ icn85xx_error("Alloc icn85xx_ts memory failed.\n");
+ return -ENOMEM;
+ }
+ memset(icn85xx_ts, 0, sizeof(*icn85xx_ts));
+
+ this_client = client;
+ this_client->addr = client->addr;
+ i2c_set_clientdata(client, icn85xx_ts);
+
+ icn85xx_ts->work_mode = 0;
+ spin_lock_init(&icn85xx_ts->irq_lock);
+// icn85xx_ts->irq_lock = SPIN_LOCK_UNLOCKED;
+
+ icn85xx_request_io_port(icn85xx_ts);
+ if (err != 0) {
+ icn85xx_error("icn85xx_request_io_port failed.\n");
+ goto fail1;
+ }
+ memset(firmware, 0, 128);
+ sprintf(firmware,"%s.bin",g_param.fw_name);
+
+ icn85xx_ts_reset();
+
+ err = icn85xx_iic_test();
+ if (err <= 0)
+ {
+ icn85xx_error("icn85xx_iic_test failed.\n");
+ goto fail2;
+
+ }
+ else
+ {
+ icn85xx_trace("iic communication ok: 0x%x\n", icn85xx_ts->ictype);
+ }
+
+ icn85xx_update(icn85xx_ts);
+
+ err= icn85xx_request_input_dev(icn85xx_ts);
+ if (err < 0)
+ {
+ icn85xx_error("request input dev failed\n");
+ goto fail3;
+ }
+
+
+
+#if TOUCH_VIRTUAL_KEYS
+ icn85xx_ts_virtual_keys_init();
+#endif
+ err = icn85xx_request_irq(icn85xx_ts);
+ if (err != 0)
+ {
+ icn85xx_error("request irq error, use timer\n");
+ icn85xx_ts->use_irq = 0;
+ hrtimer_init(&icn85xx_ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ icn85xx_ts->timer.function = chipone_timer_func;
+ hrtimer_start(&icn85xx_ts->timer, ktime_set(CTP_START_TIMER/1000, (CTP_START_TIMER%1000)*1000000), HRTIMER_MODE_REL);
+ }
+#if SUPPORT_SYSFS
+ icn85xx_create_sysfs(client);
+#endif
+
+#if SUPPORT_PROC_FS
+ sema_init(&icn85xx_ts->sem, 1);
+ init_proc_node();
+#endif
+
+ INIT_WORK(&icn85xx_ts->pen_event_work, icn85xx_ts_pen_irq_work);
+ icn85xx_ts->ts_workqueue = create_singlethread_workqueue(dev_name(&client->dev));
+ if (!icn85xx_ts->ts_workqueue) {
+ icn85xx_error("create_singlethread_workqueue failed.\n");
+ err = -ESRCH;
+ goto fail4;
+ }
+
+ if(icn85xx_ts->use_irq)
+ icn85xx_irq_enable();
+ icn85xx_trace("==%s over =\n", __func__);
+ return 0;
+fail4:
+ cancel_work_sync(&icn85xx_ts->pen_event_work);
+fail3:
+ input_unregister_device(icn85xx_ts->input_dev);
+ input_free_device(icn85xx_ts->input_dev);
+fail2:
+ icn85xx_free_io_port();
+fail1:
+ kfree(icn85xx_ts);
+ icn85xx_free_fw();
+ return err;
+}
+
+static int __devexit icn85xx_ts_remove(struct i2c_client *client)
+{
+ struct icn85xx_ts_data *icn85xx_ts = i2c_get_clientdata(client);
+ icn85xx_trace("==icn85xx_ts_remove=\n");
+ if(icn85xx_ts->use_irq)
+ icn85xx_irq_disable();
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&icn85xx_ts->early_suspend);
+#endif
+
+#if SUPPORT_PROC_FS
+ uninit_proc_node();
+#endif
+
+#if SUPPORT_SYSFS
+ icn85xx_remove_sysfs(client);
+#endif
+ input_unregister_device(icn85xx_ts->input_dev);
+ input_free_device(icn85xx_ts->input_dev);
+ cancel_work_sync(&icn85xx_ts->pen_event_work);
+ destroy_workqueue(icn85xx_ts->ts_workqueue);
+ icn85xx_free_irq(icn85xx_ts);
+ icn85xx_free_io_port();
+ icn85xx_free_fw();
+ kfree(icn85xx_ts);
+ i2c_set_clientdata(client, NULL);
+ return 0;
+}
+
+static int wmt_check_touch_env(void)
+{
+ int ret = 0;
+ int len = 96;
+ char retval[200] = {0},*p=NULL,*s=NULL;
+ int Enable=0;
+
+ ret = wmt_getsyspara("wmt.io.touch", retval, &len);
+ if(ret){
+ printk("Read wmt.io.touch Failed.\n");
+ return -EIO;
+ }
+
+//paste:
+ p = retval;
+ Enable = (p[0] - '0' == 1) ? 1 : 0;
+ if(Enable == 0){
+ printk("Touch Screen Is Disabled.\n");
+ return -ENODEV;
+ }
+
+ p = strchr(p,':');p++;
+ s = strchr(p,':');
+ strncpy(g_param.fw_name,p, (s-p));
+ printk("ts_name=%s\n", g_param.fw_name);
+ if (strncmp(g_param.fw_name, "ICN85", 5)) {
+ printk("Wrong firmware name.\n");
+ return -ENODEV;
+ }
+
+ p = s+1;
+ ret = sscanf(p,"%d:%d:%d:%d:%d:%d:%d",
+ &(g_param.irqgpio),&(g_param.panelres_x),&(g_param.panelres_y),&(g_param.rstgpio),
+ &(g_param.xyswap),&(g_param.xdir),&(g_param.ydir));
+
+ if (ret < 7) {
+ printk("Wrong format ts u-boot param(%d)!\nwmt.io.touch=%s\n",ret,retval);
+ return -ENODEV;
+ }
+
+ printk("p.x = %d, p.y = %d, irqgpio=%d, rstgpio=%d,xyswap=%d,xdir=%d,ydir=%d\n",
+ g_param.panelres_x,g_param.panelres_y,g_param.irqgpio,g_param.rstgpio,
+ g_param.xyswap,g_param.xdir,g_param.ydir);
+
+ /*memset(retval,0,sizeof(retval));
+ ret = wmt_getsyspara("wmt.touch.earlysus", retval, &len);
+ if(!ret)
+ g_param.earlysus_en = (retval[0] - '0' == 1) ? 1 : 0;*/
+
+ memset(retval,0,sizeof(retval));
+ ret = wmt_getsyspara("wmt.display.fb0", retval, &len);
+ if (!ret) {
+ int tmp[6];
+ p = retval;
+ sscanf(p, "%d:[%d:%d:%d:%d:%d", &tmp[0], &tmp[1], &tmp[2], &tmp[3], &tmp[4], &tmp[5]);
+ if (tmp[4] > tmp[5])
+ g_param.lcd_exchg = 1;
+ }
+
+ ret = wmt_getsyspara("wmt.backlight.delay", retval, &len);
+ if(ret) {
+ bl_is_delay = 0;
+ } else
+ bl_is_delay = 1;
+
+ return 0;
+}
+
+static const struct i2c_device_id icn85xx_ts_id[] = {
+ { CTP_NAME, 0 },
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, icn85xx_ts_id);
+
+static struct i2c_driver icn85xx_ts_driver = {
+ .probe = icn85xx_ts_probe,
+ .remove = __devexit_p(icn85xx_ts_remove),
+#ifndef CONFIG_HAS_EARLYSUSPEND
+ .suspend = icn85xx_ts_suspend,
+ .resume = icn85xx_ts_resume,
+#endif
+ .id_table = icn85xx_ts_id,
+ .driver = {
+ .name = CTP_NAME,
+ .owner = THIS_MODULE,
+ },
+
+};
+
+
+static struct i2c_board_info i2c_board_info = {
+ I2C_BOARD_INFO(CTP_NAME, ICN85XX_IIC_ADDR),
+};
+
+
+static int __init icn85xx_ts_init(void)
+{
+ struct i2c_client *client;
+ struct i2c_adapter *adap;
+ icn85xx_trace("===========================%s=====================\n", __func__);
+
+ if(wmt_check_touch_env())
+ return -ENODEV;
+
+ {//register i2c device
+ adap = i2c_get_adapter(1); //i2c Bus 1
+ if (!adap)
+ return -ENODEV;
+ client = i2c_new_device(adap, &i2c_board_info);
+ i2c_put_adapter(adap);
+ if (!client) {
+ printk("i2c_new_device error\n");
+ return -ENODEV;
+ }
+ }
+
+ return i2c_add_driver(&icn85xx_ts_driver);
+}
+
+static void __exit icn85xx_ts_exit(void)
+{
+ icn85xx_trace("==icn85xx_ts_exit==\n");
+ i2c_unregister_device(this_client);
+ i2c_del_driver(&icn85xx_ts_driver);
+}
+late_initcall(icn85xx_ts_init);
+//module_init(icn85xx_ts_init);
+module_exit(icn85xx_ts_exit);
+
+MODULE_AUTHOR("<zmtian@chiponeic.com>");
+MODULE_DESCRIPTION("Chipone icn85xx TouchScreen driver");
+MODULE_LICENSE("GPL");
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/icn85xx_ts/icn85xx.h b/ANDROID_3.4.5/drivers/input/touchscreen/icn85xx_ts/icn85xx.h
new file mode 100755
index 00000000..262b76fb
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/icn85xx_ts/icn85xx.h
@@ -0,0 +1,500 @@
+/*++
+
+ Copyright (c) 2012-2022 ChipOne Technology (Beijing) Co., Ltd. All Rights Reserved.
+ This PROPRIETARY SOFTWARE is the property of ChipOne Technology (Beijing) Co., Ltd.
+ and may contains trade secrets and/or other confidential information of ChipOne
+ Technology (Beijing) Co., Ltd. This file shall not be disclosed to any third party,
+ in whole or in part, without prior written consent of ChipOne.
+ THIS PROPRIETARY SOFTWARE & ANY RELATED DOCUMENTATION ARE PROVIDED AS IS,
+ WITH ALL FAULTS, & WITHOUT WARRANTY OF ANY KIND. CHIPONE DISCLAIMS ALL EXPRESS OR
+ IMPLIED WARRANTIES.
+
+ File Name: icn85xx.h
+ Abstract:
+ input driver.
+Author: Zhimin Tian
+Date : 08,14,2013
+Version: 1.0
+History :
+ 2012,10,30, V0.1 first version
+
+ --*/
+
+#ifndef __LINUX_ICN85XX_H__
+#define __LINUX_ICN85XX_H__
+
+#include <linux/i2c.h>
+#include <linux/input.h>
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ #include <linux/pm.h>
+ #include <linux/earlysuspend.h>
+#endif
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/async.h>
+#include <linux/hrtimer.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <linux/input.h>
+#include <linux/input/mt.h>
+#include <linux/hrtimer.h>
+#include <linux/proc_fs.h>
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+ #include <linux/semaphore.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/ioctl.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/spinlock_types.h>
+#include <linux/workqueue.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <mach/wmt_iomux.h>
+#include <linux/kthread.h>
+#include <linux/wakelock.h>
+#include <linux/firmware.h>
+
+
+//-----------------------------------------------------------------------------
+// Pin Declarations
+//-----------------------------------------------------------------------------
+
+#define SUPPORT_ALLWINNER_A13 0
+#define SUPPORT_ROCKCHIP 0
+#define SUPPORT_SPREADTRUM 0
+
+
+
+
+#if SUPPORT_ROCKCHIP
+#include <linux/irq.h>
+#include <mach/irqs.h>
+#include <mach/system.h>
+#include <mach/hardware.h>
+#include <mach/board.h>
+#include <mach/gpio.h>
+
+
+#define CTP_IRQ_MODE 0
+
+
+ #define CTP_RST_PORT RK30_PIN2_PB1//RK30_PIN1_PB1
+ #define CTP_IRQ_PORT RK30_PIN1_PA1
+
+
+
+#define CTP_WAKEUP_PORT 0
+#define CTP_REPORT_PROTOCOL 1 //0: A protocol
+ //1: B protocol
+#define SCREEN_MAX_X (600)
+#define SCREEN_MAX_Y (1024)
+//#define SCREEN_MAX_X (480)
+//#define SCREEN_MAX_Y (800)
+#define ICN85XX_I2C_SCL 400*1000
+
+#endif
+
+
+#include <linux/irq.h>
+#include <mach/irqs.h>
+#include <mach/hardware.h>
+#include <mach/gpio.h>
+#define CTP_RST_PORT 4//RK30_PIN1_PB1
+#define CTP_IRQ_PORT 7
+#define CTP_REPORT_PROTOCOL 1 //0: A protocol
+#define SCREEN_MAX_X (1024)
+#define SCREEN_MAX_Y (600)
+#define ICN85XX_IIC_ADDR (0x90>>1)
+
+//-----------------------------------------------------------------------------
+// Global CONSTANTS
+//-----------------------------------------------------------------------------
+#define COL_NUM 24
+#define ROW_NUM 36
+
+#define MD25D40_ID1 0x514013
+#define MD25D40_ID2 0xC84013
+#define MD25D20_ID1 0x514012
+#define MD25D20_ID2 0xC84012
+#define GD25Q10_ID 0xC84011
+#define MX25L512E_ID 0xC22010
+
+#define ICN85XX_WITHOUT_FLASH 0x11
+#define ICN85XX_WITH_FLASH 0x22
+
+#define FLASH_TOTAL_SIZE 0x00010000
+#define FLASH_PAGE_SIZE 0x1000
+#define FLASH_AHB_BASE_ADDR 0x00100000
+#define FLASH_PATCH_PARA_BASE_ADDR (FLASH_TOTAL_SIZE - FLASH_PAGE_SIZE) // allocate 1 page for patch para, 0xff00
+#define FLASH_CODE_INFO_BASE_ADDR (FLASH_PATCH_PARA_BASE_ADDR - FLASH_PAGE_SIZE) // 0xfe00,allocate 1 page for system para
+#define FLASH_CRC_ADDR (FLASH_AHB_BASE_ADDR + FLASH_CODE_INFO_BASE_ADDR + 0x00) // 0xfe00
+#define FLASH_CODE_LENGTH_ADDR (FLASH_AHB_BASE_ADDR + FLASH_CODE_INFO_BASE_ADDR + 0x04) // 0xfe04
+
+
+//tp config
+#define TOUCH_VIRTUAL_KEYS 0
+#define SUPPORT_PROC_FS 1
+#define SUPPORT_SYSFS 1
+#define COMPILE_FW_WITH_DRIVER 0
+#define FORCE_UPDATA_FW 0
+#define SUSPEND_POWER_OFF 1
+#define SUPPORT_SENSOR_ID 0
+
+#define ICN85XX_NAME "icn85xx"
+#define ICN85XX_PROG_IIC_ADDR (0x30)
+#define CTP_NAME ICN85XX_NAME
+
+#define CTP_RESET_LOW_PERIOD (5)
+#define CTP_RESET_HIGH_PERIOD (100)
+#define CTP_WAKEUP_LOW_PERIOD (20)
+#define CTP_WAKEUP_HIGH_PERIOD (50)
+#define CTP_POLL_TIMER (16) /* ms delay between samples */
+#define CTP_START_TIMER (100) /* ms delay between samples */
+
+#define POINT_NUM 5
+#define POINT_SIZE 7
+
+#define TS_KEY_HOME 102
+#define TS_KEY_MENU 139
+#define TS_KEY_BACK 158
+#define TS_KEY_SEARCH 217
+
+#define ICN_VIRTUAL_BUTTON_HOME 0x02
+#define ICN_VIRTUAL_BUTTON_MENU 0x01
+#define ICN_VIRTUAL_BUTTON_BACK 0x04
+#define ICN_VIRTUAL_BUTTON_SEARCH 0x08
+
+#define IIC_RETRY_NUM 3
+
+//ICN85xx_REG_PMODE
+#define PMODE_ACTIVE 0x00
+#define PMODE_MONITOR 0x01
+#define PMODE_HIBERNATE 0x02
+
+#define B_SIZE 32
+//#define ENABLE_BYTE_CHECK
+
+//-----------------------------------------------------------------------------
+// Macro DEFINITIONS
+//-----------------------------------------------------------------------------
+#define DBG_ICN85xx_TRACE
+//#define DBG_ICN85xx_POINT
+//#define DBG_ICN85xx_INFO
+#define DBG_ICN85xx_ERROR
+//#define DBG_FLASH_INFO
+#define DBG_FLASH_ERROR
+#define DBG_OP_INFO
+#define DBG_OP_ERROR
+#define DBG_CALIB_INFO
+#define DBG_CALIB_ERROR
+//#define DBG_PROC_INFO
+#define DBG_PROC_ERROR
+
+
+#ifdef DBG_ICN85xx_TRACE
+#define icn85xx_trace(fmt, args...) \
+ do{ \
+ printk(fmt, ##args); \
+ }while(0)
+#else
+#define icn85xx_trace(fmt, args...) //
+#endif
+
+
+#ifdef DBG_ICN85xx_POINT
+#define icn85xx_point_info(fmt, args...) \
+ do{ \
+ printk(fmt, ##args); \
+ }while(0)
+#else
+#define icn85xx_point_info(fmt, args...) //
+#endif
+
+#ifdef DBG_ICN85xx_INFO
+#define icn85xx_info(fmt, args...) \
+ do{ \
+ printk(fmt, ##args); \
+ }while(0)
+#else
+#define icn85xx_info(fmt, args...) //
+#endif
+
+#ifdef DBG_ICN85xx_ERROR
+#define icn85xx_error(fmt, args...) \
+ do{ \
+ printk(fmt, ##args); \
+ }while(0)
+#else
+#define icn85xx_error(fmt, args...) //
+#endif
+
+#ifdef DBG_FLASH_INFO
+#define flash_info(fmt, args...) \
+ do{ \
+ printk(fmt, ##args); \
+ }while(0)
+#else
+#define flash_info(fmt, args...) //
+#endif
+
+#ifdef DBG_FLASH_ERROR
+#define flash_error(fmt, args...) \
+ do{ \
+ printk(fmt, ##args); \
+ }while(0)
+#else
+#define flash_error(fmt, args...) //
+#endif
+
+
+#ifdef DBG_OP_INFO
+#define op_info(fmt, args...) \
+ do{ \
+ printk(fmt, ##args); \
+ }while(0)
+#else
+#define op_info(fmt, args...) //
+#endif
+#ifdef DBG_OP_ERROR
+#define op_error(fmt, args...) \
+ do{ \
+ printk(fmt, ##args); \
+ }while(0)
+#else
+#define op_error(fmt, args...) //
+#endif
+
+
+#ifdef DBG_CALIB_INFO
+#define calib_info(fmt, args...) \
+ do{ \
+ printk(fmt, ##args); \
+ }while(0)
+#else
+#define calib_info(fmt, args...) //
+#endif
+
+#ifdef DBG_CALIB_ERROR
+#define calib_error(fmt, args...) \
+ do{ \
+ printk(fmt, ##args); \
+ }while(0)
+#else
+#define calib_error(fmt, args...) //
+#endif
+
+
+#ifdef DBG_PROC_INFO
+#define proc_info(fmt, args...) \
+ do{ \
+ printk(fmt, ##args); \
+ }while(0)
+#else
+#define proc_info(fmt, args...) //
+#endif
+
+#ifdef DBG_PROC_ERROR
+#define proc_error(fmt, args...) \
+ do{ \
+ printk(fmt, ##args); \
+ }while(0)
+#else
+#define proc_error(fmt, args...) //
+#endif
+
+#define swap_ab(a,b) {char temp;temp=a;a=b;b=temp;}
+#define U16LOBYTE(var) (*(unsigned char *) &var)
+#define U16HIBYTE(var) (*(unsigned char *)((unsigned char *) &var + 1))
+
+#define STRUCT_OFFSET(StructName,MemberName) ((int)(&(((StructName*)0)->MemberName)))
+
+
+//-----------------------------------------------------------------------------
+// Struct, Union and Enum DEFINITIONS
+//-----------------------------------------------------------------------------
+typedef struct _POINT_INFO
+{
+ unsigned char u8ID;
+ unsigned short u16PosX; // coordinate X, plus 4 LSBs for precision extension
+ unsigned short u16PosY; // coordinate Y, plus 4 LSBs for precision extension
+ unsigned char u8Pressure;
+ unsigned char u8EventId;
+}POINT_INFO;
+
+struct icn85xx_ts_data {
+ struct i2c_client *client;
+ struct input_dev *input_dev;
+ struct work_struct pen_event_work;
+ struct workqueue_struct *ts_workqueue;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend early_suspend;
+#endif
+ struct hrtimer timer;
+ spinlock_t irq_lock;
+ struct semaphore sem;
+ int ictype;
+ int code_loaded_flag;
+ POINT_INFO point_info[POINT_NUM+1];
+ int point_num;
+ int irq;
+ int irq_is_disable;
+ int use_irq;
+ int work_mode;
+ int screen_max_x;
+ int screen_max_y;
+ int revert_x_flag;
+ int revert_y_flag;
+ int exchange_x_y_flag;
+};
+
+struct touch_param {
+ char fw_name[32];
+ int irqgpio;
+ int rstgpio;
+ int panelres_x;
+ int panelres_y;
+ int xyswap;
+ int xdir;
+ int ydir;
+ int max_finger_num;
+ int force_download;
+ int earlysus_en;
+ int dbg;
+ int lcd_exchg;
+};
+
+#pragma pack(1)
+typedef struct{
+ unsigned char wr; //write read flag£¬0:R 1:W
+ unsigned char flag; //0:
+ unsigned char circle; //polling cycle
+ unsigned char times; //plling times
+ unsigned char retry; //I2C retry times
+ unsigned int data_len; //data length
+ unsigned char addr_len; //address length
+ unsigned char addr[2]; //address
+ unsigned char* data; //data pointer
+}pack_head;
+
+typedef struct _STRUCT_PANEL_PARA
+{
+ unsigned short u16ResX; // Row of resolution
+ unsigned short u16ResY; // Col of resolution
+
+ unsigned char u8RowNum; // Row total number (Tp + vk)
+ unsigned char u8ColNum; // Column total number (Tp + vk)
+ unsigned char u8TXOrder[36]; // TX Order, start from zero
+ unsigned char u8RXOrder[24]; // TX Order, start from zero
+
+ unsigned char u8NumVKey; // Virtual Key setting
+ unsigned char u8VKeyMode;
+ unsigned char u8TpVkOrder[4];
+ unsigned char u8VKDownThreshold;
+ unsigned char u8VKUpThreshold;
+
+ unsigned char u8MaxTouchNum; // max touch support
+
+ unsigned char u8ScanMode; // scan mode
+ unsigned short u16BitFreq;
+ unsigned short u16FreqCycleNum[2];
+ unsigned char u8MultiDrvNum;
+ unsigned char u8WindowType;
+
+ unsigned char u8FreHopMode; // freq hopping
+ unsigned short u16FreHopBitFreq[5]; // Bit Freq
+ unsigned short u16FreqHopCycleNum[5]; // Cycle Num
+ unsigned short u16FreHopThreshold; // Threshold of Freq Hop
+
+ unsigned char u8ShiftNum; // rawdata level
+ unsigned char u8DrvOutPutR;
+ unsigned char u8PgaC;
+ unsigned char u8RxVcmi;
+ unsigned char u8DacGain;
+ unsigned char u8PgaGain;
+ unsigned char u8PgaR;
+ unsigned char u8SpaceHolder[200];
+}STRUCT_PANEL_PARA_H;
+
+#pragma pack()
+
+#define DATA_LENGTH_UINT 512
+#define CMD_HEAD_LENGTH (sizeof(pack_head) - sizeof(unsigned char *))
+#define ICN85xx_ENTRY_NAME "icn85xx_tool"
+
+
+enum icn85xx_ts_regs {
+ ICN85xx_REG_PMODE = 0x04, /* Power Consume Mode */
+};
+
+typedef enum
+{
+ R_OK = 100,
+ R_FILE_ERR,
+ R_STATE_ERR,
+ R_ERASE_ERR,
+ R_PROGRAM_ERR,
+ R_VERIFY_ERR,
+}E_UPGRADE_ERR_TYPE;
+
+//-----------------------------------------------------------------------------
+// Global VARIABLES
+//-----------------------------------------------------------------------------
+
+
+//-----------------------------------------------------------------------------
+// Function PROTOTYPES
+//-----------------------------------------------------------------------------
+
+void icn85xx_ts_reset(void);
+int icn85xx_i2c_rxdata(unsigned short addr, char *rxdata, int length);
+int icn85xx_i2c_txdata(unsigned short addr, char *txdata, int length);
+int icn85xx_write_reg(unsigned short addr, char para);
+int icn85xx_read_reg(unsigned short addr, char *pdata);
+int icn85xx_prog_i2c_rxdata(unsigned int addr, char *rxdata, int length);
+int icn85xx_prog_i2c_txdata(unsigned int addr, char *txdata, int length);
+int icn85xx_prog_write_reg(unsigned int addr, char para);
+int icn85xx_prog_read_reg(unsigned int addr, char *pdata);
+
+int icn85xx_readVersion(void);
+void icn85xx_rawdatadump(short *mem, int size, char br);
+void icn85xx_set_fw(int size, unsigned char *buf);
+void icn85xx_memdump(char *mem, int size);
+int icn85xx_checksum(int sum, char *buf, unsigned int size);
+int icn85xx_update_status(int status);
+int icn85xx_get_status(void);
+int icn85xx_open_fw( char *fw);
+void icn85xx_free_fw(void);
+int icn85xx_read_fw(int offset, int length, char *buf);
+int icn85xx_close_fw(void);
+int icn85xx_goto_progmode(void);
+int icn85xx_check_progmod(void);
+int icn85xx_read_flashid(void);
+int icn85xx_erase_flash(void);
+int icn85xx_prog_buffer(unsigned int flash_addr,unsigned int sram_addr,unsigned int copy_length,unsigned char program_type);
+int icn85xx_prog_data(unsigned int flash_addr, unsigned int data);
+void icn85xx_read_flash(unsigned int sram_address,unsigned int flash_address,unsigned long copy_length,unsigned char i2c_wire_num);
+int icn85xx_fw_download(unsigned int offset, unsigned char * buffer, unsigned int size);
+int icn85xx_bootfrom_flash(void);
+int icn85xx_bootfrom_sram(void);
+int icn85xx_crc_enable(unsigned char enable);
+unsigned int icn85xx_crc_calc(unsigned crc_in, char *buf, int len);
+
+short icn85xx_read_fw_Ver(char *fw);
+//E_UPGRADE_ERR_TYPE icn85xx_fw_update(char *fw);
+int icn85xx_fw_update(void *arg);
+#endif
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/icn85xx_ts/icn85xx_flash.c b/ANDROID_3.4.5/drivers/input/touchscreen/icn85xx_ts/icn85xx_flash.c
new file mode 100755
index 00000000..a17cf176
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/icn85xx_ts/icn85xx_flash.c
@@ -0,0 +1,1050 @@
+/*++
+
+ Copyright (c) 2012-2022 ChipOne Technology (Beijing) Co., Ltd. All Rights Reserved.
+ This PROPRIETARY SOFTWARE is the property of ChipOne Technology (Beijing) Co., Ltd.
+ and may contains trade secrets and/or other confidential information of ChipOne
+ Technology (Beijing) Co., Ltd. This file shall not be disclosed to any third party,
+ in whole or in part, without prior written consent of ChipOne.
+ THIS PROPRIETARY SOFTWARE & ANY RELATED DOCUMENTATION ARE PROVIDED AS IS,
+ WITH ALL FAULTS, & WITHOUT WARRANTY OF ANY KIND. CHIPONE DISCLAIMS ALL EXPRESS OR
+ IMPLIED WARRANTIES.
+
+ File Name: icn85xx_flash.c
+ Abstract:
+ flash operation, read write etc.
+ Author: Zhimin Tian
+ Date : 08 14,2013
+ Version: 0.1[.revision]
+ History :
+ Change logs.
+ --*/
+#include "icn85xx.h"
+
+unsigned char* firmdata = NULL;
+int g_status = R_OK;
+static char fw_mode = 0;
+static int fw_size = 0;
+static unsigned char *fw_buf;
+static char boot_mode = ICN85XX_WITH_FLASH;
+void icn85xx_rawdatadump(short *mem, int size, char br)
+{
+ int i;
+ for(i=0;i<size; i++)
+ {
+ if((i!=0)&&(i%br == 0))
+ printk("\n");
+ printk(" %5d", mem[i]);
+ }
+ printk("\n");
+}
+
+void icn85xx_memdump(char *mem, int size)
+{
+ int i;
+ for(i=0;i<size; i++)
+ {
+ if(i%16 == 0)
+ printk("\n");
+ printk(" 0x%2x", mem[i]);
+ }
+ printk("\n");
+}
+
+int icn85xx_checksum(int sum, char *buf, unsigned int size)
+{
+ int i;
+ for(i=0; i<size; i++)
+ {
+ sum = sum + buf[i];
+ }
+ return sum;
+}
+
+
+int icn85xx_update_status(int status)
+{
+// flash_info("icn85xx_update_status: %d\n", status);
+ g_status = status;
+ return 0;
+}
+
+int icn85xx_get_status(void)
+{
+ return g_status;
+}
+
+void icn85xx_set_fw(int size, unsigned char *buf)
+{
+ fw_size = size;
+ fw_buf = buf;
+
+}
+
+/***********************************************************************************************
+Name : icn85xx_open_fw
+Input : *fw
+
+Output : file size
+function : open the fw file, and return total size
+***********************************************************************************************/
+extern struct i2c_client *this_client;
+int icn85xx_open_fw( char *fw)
+{
+ static int file_size = 0;
+ const struct firmware *fw_entry;
+
+ if (firmdata)
+ return file_size;
+
+ if(request_firmware(&fw_entry, fw, &(this_client->dev))!=0) {
+ flash_error(KERN_ERR "cat't request firmware\n");
+ return -1;
+ }
+ if (fw_entry->size <= 0) {
+ flash_error(KERN_ERR "load firmware error\n");
+ release_firmware(fw_entry);
+ return -1;
+ }
+
+ firmdata = kzalloc(fw_entry->size + 1, GFP_KERNEL);
+ memcpy(firmdata, fw_entry->data, fw_entry->size);
+ file_size = fw_entry->size;
+ release_firmware(fw_entry);
+ return file_size;
+}
+
+void icn85xx_free_fw(void)
+{
+ if (firmdata) {
+ kfree(firmdata);
+ firmdata = NULL;
+ }
+}
+
+/***********************************************************************************************
+Name : icn85xx_read_fw
+Input : offset
+ length, read length
+ buf, return buffer
+Output :
+function : read data to buffer
+***********************************************************************************************/
+int icn85xx_read_fw(int offset, int length, char *buf)
+{
+ if(fw_mode == 1)
+ {
+ memcpy(buf, fw_buf+offset, length);
+ }
+ else
+ {
+ memcpy(buf, firmdata + offset, length);
+ }
+// icn85xx_memdump(buf, length);
+ return 0;
+}
+
+
+/***********************************************************************************************
+Name : icn85xx_close_fw
+Input :
+Output :
+function : close file
+***********************************************************************************************/
+int icn85xx_close_fw(void)
+{
+ if(fw_mode == 0)
+ {
+ //filp_close(fp, NULL);
+ }
+
+ return 0;
+}
+/***********************************************************************************************
+Name : icn85xx_readVersion
+Input : void
+Output :
+function : return version
+***********************************************************************************************/
+int icn85xx_readVersion(void)
+{
+ int err = 0;
+ char tmp[2];
+ short CurVersion;
+ err = icn85xx_i2c_rxdata(0x000c, tmp, 2);
+ if (err < 0) {
+ flash_error("%s failed: %d\n", __func__, err);
+ return 0;
+ }
+ CurVersion = (tmp[0]<<8) | tmp[1];
+ return CurVersion;
+}
+
+
+/***********************************************************************************************
+Name : icn85xx_goto_progmode
+Input :
+Output :
+function : change MCU to progmod
+***********************************************************************************************/
+int icn85xx_goto_progmode(void)
+{
+ int ret = -1;
+ int retry = 3;
+ unsigned char ucTemp;
+
+// flash_info("icn85xx_goto_progmode\n");
+ while(retry > 0)
+ {
+ ucTemp = 0x5a;
+ ret = icn85xx_prog_i2c_txdata(0xcc3355, &ucTemp,1);
+ mdelay(2);
+ ucTemp = 01;
+ ret = icn85xx_prog_i2c_txdata(0x040400, &ucTemp,1);
+ mdelay(2);
+ ret = icn85xx_check_progmod();
+ if(ret == 0)
+ return ret;
+
+ retry--;
+ mdelay(2);
+ }
+ printk("icn85xx_goto_progmode over\n");
+ if(retry == 0)
+ return -1;
+
+ return 0;
+}
+
+/***********************************************************************************************
+Name : icn85xx_check_progmod
+Input :
+Output :
+function : check if MCU at progmode or not
+***********************************************************************************************/
+int icn85xx_check_progmod(void)
+{
+ int ret;
+ unsigned char ucTemp = 0x0;
+ ret = icn85xx_prog_i2c_rxdata(0x040002, &ucTemp, 1);
+// flash_info("icn85xx_check_progmod: 0x%x\n", ucTemp);
+ if(ret < 0)
+ {
+ flash_error("icn85xx_check_progmod error, ret: %d\n", ret);
+ return ret;
+ }
+ if(ucTemp == 0x85)
+ return 0;
+ else
+ return -1;
+
+}
+
+unsigned char FlashState(unsigned char State_Index)
+{
+ unsigned char ucTemp[4] = {0,0,0,0};
+
+ ucTemp[2]=0x08;
+ ucTemp[1]=0x10;
+ ucTemp[0]=0x00;
+ icn85xx_prog_i2c_txdata(0x4062c,ucTemp,3);
+
+ if(State_Index==0)
+ {
+ ucTemp[0]=0x05;
+ }
+ else if(State_Index==1)
+ {
+ ucTemp[0]=0x35;
+ }
+ icn85xx_prog_i2c_txdata(0x40630,ucTemp,1);
+
+ ucTemp[1]=0x00;
+ ucTemp[0]=0x01;
+ icn85xx_prog_i2c_txdata(0x40640,ucTemp,2);
+
+ ucTemp[0]=1;
+ icn85xx_prog_i2c_txdata(0x40644,ucTemp,1);
+ while(ucTemp[0])
+ {
+ icn85xx_prog_i2c_rxdata(0x40644,ucTemp,1);
+ }
+
+ icn85xx_prog_i2c_rxdata(0x40648,ucTemp,1);
+ return (unsigned char)(ucTemp[0]);
+}
+
+int icn85xx_read_flashid(void)
+{
+ unsigned char ucTemp[4] = {0,0,0,0};
+ int flashid=0;
+
+ ucTemp[2]=0x08;
+ ucTemp[1]=0x10;
+ ucTemp[0]=0x00;
+ icn85xx_prog_i2c_txdata(0x4062c,ucTemp,3);
+
+ ucTemp[0]=0x9f;
+
+ icn85xx_prog_i2c_txdata(0x40630,ucTemp,1);
+
+ ucTemp[1]=0x00;
+ ucTemp[0]=0x03;
+ icn85xx_prog_i2c_txdata(0x40640,ucTemp,2);
+
+ ucTemp[0]=1;
+ icn85xx_prog_i2c_txdata(0x40644,ucTemp,1);
+ while(ucTemp[0])
+ {
+ icn85xx_prog_i2c_rxdata(0x40644,ucTemp,1);
+ }
+
+ icn85xx_prog_i2c_rxdata(0x40648,(char *)&flashid,4);
+ flashid=flashid&0x00ffffff;
+
+ if((MD25D40_ID1 == flashid) || (MD25D40_ID2 == flashid)
+ ||(MD25D20_ID1 == flashid) || (MD25D20_ID1 == flashid)
+ ||(GD25Q10_ID == flashid) || (MX25L512E_ID == flashid))
+ {
+ boot_mode = ICN85XX_WITH_FLASH;
+ //printk("ICN85XX_WITH_FLASH\n");
+ }
+ else
+ {
+ boot_mode = ICN85XX_WITHOUT_FLASH;
+ //printk("ICN85XX_WITHOUT_FLASH\n");
+ }
+
+ printk("flashid: 0x%x\n", flashid);
+ return flashid;
+}
+
+
+void FlashWriteEnable(void)
+{
+ unsigned char ucTemp[4] = {0,0,0,0};
+
+ ucTemp[2]=0x00;
+ ucTemp[1]=0x10;
+ ucTemp[0]=0x00;
+ icn85xx_prog_i2c_txdata(0x4062c,ucTemp,3);
+
+ ucTemp[0]=0x06;
+ icn85xx_prog_i2c_txdata(0x40630,ucTemp,1);
+
+ ucTemp[0]=0x00;
+ ucTemp[1]=0x00;
+ icn85xx_prog_i2c_txdata(0x40640,ucTemp,2);
+
+ ucTemp[0]=1;
+ icn85xx_prog_i2c_txdata(0x40644,ucTemp,1);
+ while(ucTemp[0])
+ {
+ icn85xx_prog_i2c_rxdata(0x40644,ucTemp,1);
+ }
+
+ ucTemp[0]=FlashState(0);
+ while( (ucTemp[0]&0x02)!=0x02)
+ {
+ ucTemp[0]=FlashState(0);
+ }
+}
+
+#ifndef QUAD_OUTPUT_ENABLE
+void ClearFlashState(void)
+{
+ unsigned char ucTemp[4] = {0,0,0,0};
+ icn85xx_prog_i2c_rxdata(0x40603,ucTemp,1);
+ ucTemp[0]=(ucTemp[0]|0x20);
+ icn85xx_prog_i2c_txdata(0x40603, ucTemp, 1 );
+
+ FlashWriteEnable();
+ ////////////////////////////write comd to flash
+ ucTemp[2]=0x00;
+ ucTemp[1]=0x10;
+ ucTemp[0]=0x10;
+ icn85xx_prog_i2c_txdata(0x4062c,ucTemp,3);
+
+ ucTemp[0]=0x01;
+ icn85xx_prog_i2c_txdata(0x40630,ucTemp,1);
+
+ ucTemp[0]=0x00;
+ ucTemp[1]=0x00;
+ icn85xx_prog_i2c_txdata(0x40640,ucTemp,2);
+
+ ucTemp[0]=0x00;
+ icn85xx_prog_i2c_txdata(0x40638,ucTemp,1);
+
+ ucTemp[0]=1;
+ icn85xx_prog_i2c_txdata(0x40644,ucTemp,1);
+ while(ucTemp[0])
+ {
+ icn85xx_prog_i2c_rxdata(0x40644,ucTemp,1);
+ }
+ while(FlashState(0)&0x01);
+
+}
+#else
+void ClearFlashState(void)
+{
+}
+#endif
+
+
+void EarseFlash(unsigned char erase_index,ulong flash_addr)
+{
+ unsigned char ucTemp[4] = {0,0,0,0};
+ FlashWriteEnable();
+ if(erase_index==0) //erase the chip
+ {
+ ucTemp[0]=0xc7;
+ icn85xx_prog_i2c_txdata(0x40630, ucTemp, 1 );
+ ucTemp[2]=0x00;
+ ucTemp[1]=0x10;
+ ucTemp[0]=0x00;
+ icn85xx_prog_i2c_txdata(0x4062c, ucTemp, 3 );
+ }
+ else if(erase_index==1) //erase 32k space of the flash
+ {
+ ucTemp[0]=0x52;
+ icn85xx_prog_i2c_txdata(0x40630, ucTemp, 1);
+ ucTemp[2]=0x00;
+ ucTemp[1]=0x13;
+ ucTemp[0]=0x00;
+ icn85xx_prog_i2c_txdata(0x4062c, ucTemp, 3);
+ }
+ else if(erase_index==2) //erase 64k space of the flash
+ {
+ ucTemp[0]=0xd8;
+ icn85xx_prog_i2c_txdata(0x40630, ucTemp,1);
+ ucTemp[2]=0x00;
+ ucTemp[1]=0x13;
+ ucTemp[0]=0x00;
+ icn85xx_prog_i2c_txdata(0x4062c, ucTemp, 3);
+ }
+ else if(erase_index==3)
+ {
+ ucTemp[0]=0x20;
+ icn85xx_prog_i2c_txdata(0x40630, ucTemp, 1);
+ ucTemp[2]=0x00;
+ ucTemp[1]=0x13;
+ ucTemp[0]=0x00;
+ icn85xx_prog_i2c_txdata(0x4062c, ucTemp, 3);
+ }
+ ucTemp[2]=(unsigned char)(flash_addr>>16);
+ ucTemp[1]=(unsigned char)(flash_addr>>8);
+ ucTemp[0]=(unsigned char)(flash_addr);
+ icn85xx_prog_i2c_txdata(0x40634, ucTemp, 3);
+
+ ucTemp[1]=0x00;
+ ucTemp[0]=0x00;
+ icn85xx_prog_i2c_txdata(0x40640, ucTemp, 2 );
+
+ ucTemp[0]=1;
+ icn85xx_prog_i2c_txdata(0x40644, ucTemp, 1);
+ while(ucTemp[0])
+ {
+ icn85xx_prog_i2c_rxdata(0x40644,ucTemp,1);
+ }
+
+}
+
+/***********************************************************************************************
+Name : icn85xx_erase_flash
+Input :
+Output :
+function : erase flash
+***********************************************************************************************/
+int icn85xx_erase_flash(void)
+{
+ ClearFlashState();
+ while(FlashState(0)&0x01);
+ FlashWriteEnable();
+ EarseFlash(1,0);
+ while((FlashState(0)&0x01));
+ FlashWriteEnable();
+ EarseFlash(3,0x8000); //?which block
+ while((FlashState(0)&0x01));
+ FlashWriteEnable();
+ EarseFlash(3,0x9000);
+ while((FlashState(0)&0x01));
+ FlashWriteEnable();
+ EarseFlash(3,0xe000);
+ while((FlashState(0)&0x01));
+ return 0;
+}
+
+
+/***********************************************************************************************
+Name : icn85xx_prog_buffer
+Input :
+Output :
+function : progm flash
+***********************************************************************************************/
+int icn85xx_prog_buffer(unsigned int flash_addr,unsigned int sram_addr,unsigned int copy_length,unsigned char program_type)
+{
+ unsigned char ucTemp[4] = {0,0,0,0};
+ unsigned char prog_state=0;
+
+ unsigned int i=0;
+ unsigned char program_commond=0;
+ if(program_type == 0)
+ {
+ program_commond = 0x02;
+ }
+ else if(program_type == 1)
+ {
+ program_commond = 0xf2;
+ }
+ else
+ {
+ program_commond = 0x02;
+ }
+
+
+ for(i=0; i<copy_length; )
+ {
+ prog_state=(FlashState(0)&0x01);
+ while(prog_state)
+ {
+ prog_state=(FlashState(0)&0x01);
+ }
+ FlashWriteEnable();
+
+ ucTemp[2]=0;
+ ucTemp[1]=0x13;
+ ucTemp[0]=0;
+ icn85xx_prog_i2c_txdata(0x4062c, ucTemp, 3);
+
+ ucTemp[2]=(unsigned char)(flash_addr>>16);
+ ucTemp[1]=(unsigned char)(flash_addr>>8);
+ ucTemp[0]=(unsigned char)(flash_addr);
+ icn85xx_prog_i2c_txdata(0x40634, ucTemp, 3);
+
+ ucTemp[2]=(unsigned char)(sram_addr>>16);
+ ucTemp[1]=(unsigned char)(sram_addr>>8);
+ ucTemp[0]=(unsigned char)(sram_addr);
+ icn85xx_prog_i2c_txdata(0x4063c, ucTemp, 3);
+
+ if(i+256<=copy_length)
+ {
+ ucTemp[1]=0x01;
+ ucTemp[0]=0x00;
+ }
+ else
+ {
+ ucTemp[1]=(unsigned char)((copy_length-i)>>8);
+ ucTemp[0]=(unsigned char)(copy_length-i);
+ }
+ icn85xx_prog_i2c_txdata(0x40640, ucTemp,2);
+
+ ucTemp[0]=program_commond;
+ icn85xx_prog_i2c_txdata(0x40630, ucTemp,1);
+
+ ucTemp[0]=0x01;
+ icn85xx_prog_i2c_txdata(0x40644, ucTemp,1);
+
+ flash_addr+=256;
+ sram_addr+=256;
+ i+=256;
+ while(ucTemp[0])
+ {
+ icn85xx_prog_i2c_rxdata(0x40644,ucTemp,1);
+ }
+
+ }
+
+ prog_state=(FlashState(0)&0x01);
+ while(prog_state)
+ {
+ prog_state=(FlashState(0)&0x01);
+ }
+ return 0;
+}
+
+/***********************************************************************************************
+Name : icn85xx_prog_data
+Input :
+Output :
+function : write int data to flash
+***********************************************************************************************/
+int icn85xx_prog_data(unsigned int flash_addr, unsigned int data)
+{
+ unsigned char ucTemp[4] = {0,0,0,0};
+
+ ucTemp[3]=(unsigned char)(data>>24);
+ ucTemp[2]=(unsigned char)(data>>16);
+ ucTemp[1]=(unsigned char)(data>>8);
+ ucTemp[0]=(unsigned char)(data);
+
+ icn85xx_prog_i2c_txdata(0x7f00, ucTemp,4);
+ icn85xx_prog_buffer(flash_addr , 0x7f00, 0x04, 0);
+ return 0;
+}
+
+/***********************************************************************************************
+Name : icn85xx_read_flash
+Input :
+Output :
+function : read data from flash to sram
+***********************************************************************************************/
+void icn85xx_read_flash(unsigned int sram_address,unsigned int flash_address,unsigned long copy_length,unsigned char i2c_wire_num)
+{
+ unsigned char ucTemp[4] = {0,0,0,0};
+
+ if(i2c_wire_num==1)
+ {
+ ucTemp[2]=0x18;
+ ucTemp[1]=0x13;
+ ucTemp[0]=0x00;
+ }
+ else if(i2c_wire_num==2)
+ {
+ ucTemp[2]=0x1a;
+ ucTemp[1]=0x13;
+ ucTemp[0]=0x01;
+ }
+ else if(i2c_wire_num==4)
+ {
+ ucTemp[2]=0x19;
+ ucTemp[1]=0x13;
+ ucTemp[0]=0x01;
+ }
+ else
+ {
+ ucTemp[2]=0x18;
+ ucTemp[1]=0x13;
+ ucTemp[0]=0x01;
+ }
+ icn85xx_prog_i2c_txdata(0x4062c, ucTemp,3);
+
+ if(i2c_wire_num==1)
+ {
+ ucTemp[0]=0x03;
+ }
+ else if(i2c_wire_num==2)
+ {
+ ucTemp[0]=0x3b;
+ }
+ else if(i2c_wire_num==4)
+ {
+ ucTemp[0]=0x6b;
+ }
+ else
+ {
+ ucTemp[0]=0x0b;
+ }
+ icn85xx_prog_i2c_txdata(0x40630, ucTemp,1);
+
+ ucTemp[2]=(unsigned char)(flash_address>>16);
+ ucTemp[1]=(unsigned char)(flash_address>>8);
+ ucTemp[0]=(unsigned char)(flash_address);
+ icn85xx_prog_i2c_txdata(0x40634, ucTemp,3);
+
+ ucTemp[2]=(unsigned char)(sram_address>>16);
+ ucTemp[1]=(unsigned char)(sram_address>>8);
+ ucTemp[0]=(unsigned char)(sram_address);
+ icn85xx_prog_i2c_txdata(0x4063c, ucTemp,3);
+
+ ucTemp[1]=(unsigned char)(copy_length>>8);
+ ucTemp[0]=(unsigned char)(copy_length);
+ icn85xx_prog_i2c_txdata(0x40640, ucTemp,2);
+
+ ucTemp[0]=0x01;
+
+ icn85xx_prog_i2c_txdata(0x40644, ucTemp,1);
+ while(ucTemp[0])
+ {
+ icn85xx_prog_i2c_rxdata(0x40644,ucTemp,1);
+ }
+
+}
+
+/***********************************************************************************************
+Name : icn85xx_read_fw_Ver
+Input : fw
+Output :
+function : read fw version
+***********************************************************************************************/
+
+short icn85xx_read_fw_Ver(char *fw)
+{
+ short FWversion;
+ char tmp[2];
+ int file_size;
+ file_size = icn85xx_open_fw(fw);
+ if(file_size < 0)
+ {
+ return -1;
+ }
+ icn85xx_read_fw(0x100, 2, &tmp[0]);
+
+ icn85xx_close_fw();
+ FWversion = (tmp[1]<<8)|tmp[0];
+// flash_info("FWversion: 0x%x\n", FWversion);
+ return FWversion;
+
+
+}
+
+/***********************************************************************************************
+Name : icn85xx_fw_download
+Input :
+Output :
+function : download code to sram
+***********************************************************************************************/
+int icn85xx_fw_download(unsigned int offset, unsigned char * buffer, unsigned int size)
+{
+#ifdef ENABLE_BYTE_CHECK
+ int i;
+ char testb[B_SIZE];
+#endif
+
+ icn85xx_prog_i2c_txdata(offset,buffer,size);
+#ifdef ENABLE_BYTE_CHECK
+ icn85xx_prog_i2c_rxdata(offset,testb,size);
+ for(i = 0; i < size; i++)
+ {
+ if(buffer[i] != testb[i])
+ {
+ flash_error("buffer[%d]:%x testb[%d]:%x\n",i,buffer[i],i,testb[i]);
+ return -1;
+ }
+ }
+#endif
+ return 0;
+}
+
+/***********************************************************************************************
+Name : icn85xx_bootfrom_flash
+Input :
+Output :
+function :
+***********************************************************************************************/
+int icn85xx_bootfrom_flash(void)
+{
+ int ret = -1;
+ unsigned char ucTemp = 0x00;
+ flash_info("icn85xx_bootfrom_flash\n");
+
+ ucTemp=0x00;
+ ret = icn85xx_prog_i2c_txdata(0x40004, &ucTemp, 1 ); //nend flash sfcontrol clear
+ if (ret < 0) {
+ flash_error("%s failed: %d\n", __func__, ret);
+ return ret;
+ }
+
+ return ret;
+}
+
+/***********************************************************************************************
+Name : icn85xx_bootfrom_sram
+Input :
+Output :
+function :
+***********************************************************************************************/
+int icn85xx_bootfrom_sram(void)
+{
+ int ret = -1;
+ unsigned char ucTemp = 0x03;
+ unsigned long addr = 0x40400;
+ flash_info("icn85xx_bootfrom_sram\n");
+ ret = icn85xx_prog_i2c_txdata(addr, &ucTemp, 1 ); //change bootmode from sram
+ return ret;
+}
+/***********************************************************************************************
+Name : icn85xx_crc_calc
+Input :
+Output :
+function :
+***********************************************************************************************/
+/*
+unsigned int icn85xx_crc_calc(unsigned crc_in, char *buf, int len)
+{
+ int pos;
+ unsigned int crc_result;
+ unsigned char in_data_8b;
+ unsigned int crc_reg_32b;
+ unsigned char i;
+ unsigned char xor_flag;
+
+ crc_result = crc_in;
+ for(pos=0;pos<len;pos++)
+ {
+ in_data_8b = *(buf+pos);
+ crc_reg_32b = crc_result ;
+ for(i=0; i<32; i++)
+ {
+ if(crc_reg_32b & 0x00000001)
+ {
+ crc_reg_32b ^= 0x04C11DB7;
+ crc_reg_32b >>= 1;
+ crc_reg_32b |= 0x80000000;
+ }
+ else
+ {
+ crc_reg_32b >>= 1;
+ }
+ }
+
+ for(i=0; i<40; i++)
+ {
+ xor_flag = (crc_reg_32b>>31);
+ crc_reg_32b = (crc_reg_32b<<1) + (in_data_8b>>7);
+ in_data_8b = (in_data_8b<<1);
+ if(xor_flag)
+ {
+ crc_reg_32b = crc_reg_32b ^ 0x04C11DB7;
+ }
+ }
+ crc_result = crc_reg_32b;
+ }
+ return crc_result;
+}
+*/
+
+
+/*
+ This polynomial (0x04c11db7) is used at: AUTODIN II, Ethernet, & FDDI
+*/
+static unsigned int crc32table[256] = {
+ 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
+ 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
+ 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
+ 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
+ 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,
+ 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
+ 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,
+ 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
+ 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,
+ 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
+ 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
+ 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
+ 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4,
+ 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
+ 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,
+ 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
+ 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,
+ 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
+ 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,
+ 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
+ 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
+ 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
+ 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,
+ 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
+ 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,
+ 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
+ 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,
+ 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
+ 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,
+ 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
+ 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
+ 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
+ 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,
+ 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
+ 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,
+ 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
+ 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,
+ 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
+ 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,
+ 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
+ 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
+ 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
+ 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
+};
+
+unsigned int icn85xx_crc_calc(unsigned crc_in, char *buf, int len)
+{
+ int i;
+ unsigned int crc = crc_in;
+ for(i = 0; i < len; i++)
+ crc = (crc << 8) ^ crc32table[((crc >> 24) ^ *buf++) & 0xFF];
+ return crc;
+}
+
+
+/***********************************************************************************************
+Name : icn85xx_crc_enable
+Input :
+Output :
+function :control crc control
+***********************************************************************************************/
+int icn85xx_crc_enable(unsigned char enable)
+{
+ unsigned char ucTemp;
+ int ret = 0;
+ if(enable==1)
+ {
+ ucTemp = 1;
+ ret = icn85xx_prog_i2c_txdata(0x40028, &ucTemp, 1 );
+ }
+ else if(enable==0)
+ {
+ ucTemp = 0;
+ ret = icn85xx_prog_i2c_txdata(0x40028, &ucTemp, 1 );
+ }
+ return ret;
+}
+/***********************************************************************************************
+Name : icn85xx_crc_check
+Input :
+Output :
+function :chec crc right or not
+***********************************************************************************************/
+int icn85xx_crc_check(unsigned int crc, unsigned int len)
+{
+ int ret;
+ unsigned int crc_len;
+ unsigned int crc_result;
+ unsigned char ucTemp[4] = {0,0,0,0};
+
+ ret= icn85xx_prog_i2c_rxdata(0x4002c, ucTemp, 4 );
+ crc_result = ucTemp[3]<<24 | ucTemp[2]<<16 | ucTemp[1] << 8 | ucTemp[0];
+// flash_info("crc_result: 0x%x\n", crc_result);
+
+ ret = icn85xx_prog_i2c_rxdata(0x40034, ucTemp, 2);
+ crc_len = ucTemp[1] << 8 | ucTemp[0];
+// flash_info("crc_len: %d\n", crc_len);
+
+ if((crc_result == crc) && (crc_len == len))
+ return 0;
+ else
+ {
+ flash_info("crc_fw: 0x%x\n", crc);
+ flash_info("crc_result: 0x%x\n", crc_result);
+ flash_info("crc_len: %d\n", crc_len);
+ return -1;
+ }
+
+}
+
+
+/***********************************************************************************************
+Name : icn85xx_fw_update
+Input : fw
+Output :
+function : upgrade fw
+***********************************************************************************************/
+int icn85xx_fw_update(void *arg)
+{
+ int file_size, last_length;
+ int j, num;
+ char temp_buf[B_SIZE];
+ unsigned int crc_fw;
+ char *fw = (char *)arg;
+
+ file_size = icn85xx_open_fw(fw);
+ if(file_size < 0)
+ {
+ icn85xx_update_status(R_FILE_ERR);
+ return R_FILE_ERR;
+ }
+ if(icn85xx_goto_progmode() != 0)
+ {
+ flash_error("icn85xx_goto_progmode() != 0 error\n");
+ return R_STATE_ERR;
+ }
+ msleep(1);
+ icn85xx_crc_enable(1);
+
+ num = file_size/B_SIZE;
+ crc_fw = 0;
+ for(j=0; j < num; j++)
+ {
+ icn85xx_read_fw(j*B_SIZE, B_SIZE, temp_buf);
+ crc_fw = icn85xx_crc_calc(crc_fw, temp_buf, B_SIZE);
+ if(icn85xx_fw_download(j*B_SIZE, temp_buf, B_SIZE) != 0)
+ {
+ flash_error("error j:%d\n",j);
+ icn85xx_update_status(R_PROGRAM_ERR);
+ icn85xx_close_fw();
+ return R_PROGRAM_ERR;
+ }
+ icn85xx_update_status(5+(int)(60*j/num));
+ }
+ last_length = file_size - B_SIZE*j;
+ if(last_length > 0)
+ {
+ icn85xx_read_fw(j*B_SIZE, last_length, temp_buf);
+ crc_fw = icn85xx_crc_calc(crc_fw, temp_buf, last_length);
+ if(icn85xx_fw_download(j*B_SIZE, temp_buf, last_length) != 0)
+ {
+ flash_error("error last length\n");
+ icn85xx_update_status(R_PROGRAM_ERR);
+ icn85xx_close_fw();
+ return R_PROGRAM_ERR;
+ }
+ }
+ icn85xx_close_fw();
+ icn85xx_update_status(65);
+// flash_info("crc_fw: 0x%x\n", crc_fw);
+// msleep(1);
+ icn85xx_crc_enable(0);
+ if(icn85xx_crc_check(crc_fw, file_size) != 0)
+ {
+ flash_info("down fw error, crc error\n");
+ return R_PROGRAM_ERR;
+ }
+ else
+ {
+ //flash_info("downoad fw ok, crc ok\n");
+ }
+ icn85xx_update_status(70);
+
+ if(ICN85XX_WITH_FLASH == boot_mode)
+ {
+ icn85xx_erase_flash();
+ // return R_PROGRAM_ERR;
+ icn85xx_update_status(75);
+
+ FlashWriteEnable();
+
+ icn85xx_prog_buffer( 0, 0, file_size,0);
+
+ icn85xx_update_status(85);
+
+ while((FlashState(0)&0x01));
+ FlashWriteEnable();
+
+ icn85xx_prog_data(FLASH_CRC_ADDR, crc_fw);
+ icn85xx_prog_data(FLASH_CRC_ADDR+4, file_size);
+
+ icn85xx_update_status(90);
+
+
+ icn85xx_crc_enable(1);
+ icn85xx_read_flash( 0, 0, file_size, 2);
+ icn85xx_crc_enable(0);
+ if(icn85xx_crc_check(crc_fw, file_size) != 0)
+ {
+ flash_info("read flash data error, crc error\n");
+ return R_PROGRAM_ERR;
+ }
+ else
+ {
+ flash_info("read flash data ok, crc ok\n");
+ }
+ while((FlashState(0)&0x01));
+ icn85xx_update_status(95);
+
+ //if(icn85xx_bootfrom_flash() == 0)
+ if(icn85xx_bootfrom_sram() == 0) //code already in ram
+ {
+ flash_error("icn85xx_bootfrom_flash error\n");
+ icn85xx_update_status(R_STATE_ERR);
+ return R_STATE_ERR;
+ }
+ }
+ else if(ICN85XX_WITHOUT_FLASH == boot_mode)
+ {
+ if(icn85xx_bootfrom_sram() == 0)
+ {
+ flash_error("icn85xx_bootfrom_sram error\n");
+ icn85xx_update_status(R_STATE_ERR);
+ return R_STATE_ERR;
+ }
+ }
+ msleep(50);
+ icn85xx_update_status(R_OK);
+ flash_info("icn85xx upgrade ok\n");
+ return R_OK;
+}
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/icn85xx_ts/icn85xx_fw.h b/ANDROID_3.4.5/drivers/input/touchscreen/icn85xx_ts/icn85xx_fw.h
new file mode 100755
index 00000000..757408c2
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/icn85xx_ts/icn85xx_fw.h
@@ -0,0 +1,2517 @@
+const unsigned char icn85xx_fw[40235] = {
+ 0xb0,0x07,0x00,0x00,0xe4,0x07,0x00,0x00,0xe4,0x07,0x00,0x00,0xe4,0x07,0x00,0x00,
+ 0xe4,0x07,0x00,0x00,0xe4,0x07,0x00,0x00,0xe4,0x07,0x00,0x00,0xe4,0x07,0x00,0x00,
+ 0xe4,0x07,0x00,0x00,0xe4,0x07,0x00,0x00,0xe4,0x07,0x00,0x00,0xe4,0x07,0x00,0x00,
+ 0xe4,0x07,0x00,0x00,0xe4,0x07,0x00,0x00,0xe4,0x07,0x00,0x00,0xe4,0x07,0x00,0x00,
+ 0xe4,0x07,0x00,0x00,0xe4,0x07,0x00,0x00,0xe4,0x07,0x00,0x00,0xe4,0x07,0x00,0x00,
+ 0xe4,0x07,0x00,0x00,0xe4,0x07,0x00,0x00,0xe4,0x07,0x00,0x00,0xe4,0x07,0x00,0x00,
+ 0x36,0x16,0x00,0x00,0xe4,0x07,0x00,0x00,0xe4,0x07,0x00,0x00,0xe4,0x07,0x00,0x00,
+ 0xe4,0x07,0x00,0x00,0xe4,0x07,0x00,0x00,0xe4,0x07,0x00,0x00,0xe4,0x07,0x00,0x00,
+ 0xda,0x15,0x00,0x00,0xf0,0x13,0x00,0x00,0x6e,0x13,0x00,0x00,0xc4,0x14,0x00,0x00,
+ 0xfc,0x13,0x00,0x00,0xb8,0x12,0x00,0x00,0x98,0x11,0x00,0x00,0x96,0x10,0x00,0x00,
+ 0xfc,0x14,0x00,0x00,0xd0,0x14,0x00,0x00,0x82,0x15,0x00,0x00,0x28,0x15,0x00,0x00,
+ 0xe4,0x07,0x00,0x00,0xe4,0x07,0x00,0x00,0x38,0x16,0x00,0x00,0x3a,0x16,0x00,0x00,
+ 0x3e,0x16,0x00,0x00,0xe4,0x07,0x00,0x00,0xe4,0x07,0x00,0x00,0xe4,0x07,0x00,0x00,
+ 0xe4,0x07,0x00,0x00,0xe4,0x07,0x00,0x00,0xe4,0x07,0x00,0x00,0xe4,0x07,0x00,0x00,
+ 0x3c,0x16,0x00,0x00,0xe4,0x07,0x00,0x00,0xe4,0x07,0x00,0x00,0xe4,0x07,0x00,0x00,
+ 0xe4,0x07,0x00,0x00,0xe4,0x07,0x00,0x00,0x40,0x16,0x00,0x00,0x56,0x16,0x00,0x00,
+ 0x00,0x27,0x00,0x00,0x22,0x00,0x00,0x00,0x01,0x00,0x05,0x00,0x08,0x00,0x0c,0x00,
+ 0x0f,0x00,0x13,0x00,0x17,0x00,0x1a,0x00,0x1e,0x00,0x22,0x00,0x26,0x00,0x2a,0x00,
+ 0x2e,0x00,0x32,0x00,0x37,0x00,0x3c,0x00,0x40,0x00,0x46,0x00,0x4b,0x00,0x50,0x00,
+ 0x56,0x00,0x5d,0x00,0x63,0x00,0x6b,0x00,0x73,0x00,0x7b,0x00,0x84,0x00,0x8e,0x00,
+ 0x99,0x00,0xa6,0x00,0xb4,0x00,0xc4,0x00,0xd6,0x00,0xeb,0x00,0x04,0x01,0x22,0x01,
+ 0x47,0x01,0x75,0x01,0xb1,0x01,0x02,0x02,0x77,0x02,0x2e,0x03,0x77,0x04,0x74,0x07,
+ 0x60,0x16,0x00,0x00,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7e,0x7e,0x7e,0x7e,
+ 0x7e,0x7d,0x7d,0x7d,0x7d,0x7c,0x7c,0x7c,0x7b,0x7b,0x7a,0x7a,0x79,0x79,0x78,0x78,
+ 0x77,0x77,0x76,0x76,0x75,0x75,0x74,0x73,0x73,0x72,0x71,0x71,0x70,0x6f,0x6e,0x6d,
+ 0x6d,0x6c,0x6b,0x6a,0x69,0x68,0x67,0x67,0x66,0x65,0x64,0x63,0x62,0x61,0x60,0x5f,
+ 0x5e,0x5d,0x5b,0x5a,0x59,0x58,0x57,0x56,0x55,0x53,0x52,0x51,0x50,0x4f,0x4d,0x4c,
+ 0x4b,0x4a,0x48,0x47,0x46,0x44,0x43,0x42,0x40,0x3f,0x3e,0x3c,0x3b,0x3a,0x38,0x37,
+ 0x35,0x34,0x32,0x31,0x30,0x2e,0x2d,0x2b,0x2a,0x28,0x27,0x25,0x24,0x22,0x21,0x1f,
+ 0x1e,0x1c,0x1b,0x19,0x17,0x16,0x14,0x13,0x11,0x10,0x0e,0x0d,0x0b,0x09,0x08,0x06,
+ 0x05,0x03,0x02,0x00,0xaa,0xa5,0x55,0x5a,0x5a,0xa5,0x66,0x6a,0x58,0x02,0x00,0x04,
+ 0x10,0x0a,0x1f,0x1d,0x1b,0x19,0x17,0x15,0x13,0x12,0x0f,0x0d,0x0b,0x09,0x07,0x05,
+ 0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x16,0x14,0x0e,0x0c,0x0a,0x08,0x06,0x04,0x02,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,
+ 0x16,0x00,0x00,0x00,0x1e,0x14,0x05,0x01,0xa0,0x0f,0x28,0x00,0x96,0x00,0x09,0x01,
+ 0x00,0x34,0x21,0x40,0x1f,0x58,0x1b,0xa8,0x16,0x88,0x13,0x3a,0x00,0x32,0x00,0x2d,
+ 0x00,0x2a,0x00,0x14,0x00,0x58,0x02,0x03,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x14,
+ 0x28,0x3c,0x50,0xc8,0x00,0x03,0x01,0x00,0x01,0x01,0x10,0x01,0x14,0x00,0x28,0x00,
+ 0x58,0x02,0x00,0xea,0x00,0x01,0x06,0x1e,0x0a,0x00,0x10,0x27,0x00,0x00,0x00,0x80,
+ 0x01,0x50,0x50,0x50,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x02,
+ 0x00,0x02,0x01,0x00,0x02,0x80,0x01,0x06,0x00,0x02,0x00,0x01,0x01,0x0a,0x10,0x20,
+ 0x03,0xc4,0xff,0x3c,0x00,0x64,0x01,0x01,0x01,0x00,0x1e,0x00,0x64,0x01,0x00,0x01,
+ 0x00,0x00,0x64,0x0a,0x00,0x01,0x14,0x01,0x07,0x00,0xd0,0x07,0x14,0x14,0x14,0x14,
+ 0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,
+ 0x14,0x14,0x14,0x14,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x32,0x00,0x05,0x01,0x00,0x00,0x01,0x03,
+ 0x05,0x07,0x46,0x46,0x0f,0x01,0x00,0x00,0x01,0x32,0xe8,0x03,0x00,0x03,0x00,0x00,
+ 0x00,0x40,0x00,0x20,0x00,0x20,0x00,0xe0,0x00,0xe0,0x00,0x00,0x00,0xf0,0x00,0xf0,
+ 0x00,0xf0,0x00,0x10,0x00,0x00,0x00,0xe0,0x00,0x00,0x00,0x00,0x00,0xe0,0x00,0xe8,
+ 0x00,0xf8,0x00,0x08,0x00,0xf8,0x00,0x08,0x00,0xf8,0x00,0xf0,0x00,0xf0,0x00,0x00,
+ 0x00,0x00,0x00,0xf0,0x00,0x00,0x00,0xf0,0xab,0xfa,0x00,0xf0,0xab,0xfa,0x55,0x05,
+ 0x55,0x05,0x00,0xf0,0x55,0x05,0xab,0xfa,0xd8,0xf0,0x94,0xf7,0x36,0xf4,0xe5,0xf5,
+ 0x0d,0x05,0x79,0xed,0x43,0xf9,0x5e,0x03,0x51,0xfe,0x74,0xf9,0x2f,0xf2,0x46,0xff,
+ 0xe9,0xfa,0x5d,0xfc,0x8c,0x06,0xd1,0xed,0xba,0x00,0x17,0x05,0xa3,0x03,0xde,0xf4,
+ 0x37,0xfd,0x4d,0xef,0xd3,0xfb,0xf4,0x06,0xbd,0xe9,0x6f,0xfa,0x9b,0xfe,0xa6,0xf7,
+ 0xe9,0x0d,0x7a,0xf3,0x9a,0xf9,0x33,0xf7,0x66,0xfa,0xcd,0xf4,0x9a,0x05,0x33,0xf7,
+ 0x66,0x06,0xcd,0x00,0x9a,0xfd,0x33,0xfb,0x66,0x02,0xcd,0x00,0x55,0xf5,0x55,0xf5,
+ 0x55,0xf5,0x55,0xf5,0x00,0x00,0xff,0xff,0x55,0xf5,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x55,0xf5,0x00,0x00,0x00,0x00,0x2a,0x05,0x81,0xfa,0x9e,0xf8,0x66,0xf8,0x97,0xf8,
+ 0xb7,0x03,0xe6,0xf9,0x8f,0x02,0x27,0xf7,0x74,0xfd,0x30,0x03,0xe4,0x01,0x64,0xfd,
+ 0x7b,0xff,0x00,0xf8,0x00,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x00,0x00,
+ 0x00,0x00,0x00,0xf8,0x00,0xf8,0x00,0x00,0x00,0xf8,0x00,0x00,0x00,0xf8,0x00,0xf8,
+ 0x51,0x01,0xad,0xfc,0xaa,0xf9,0x2b,0xfb,0x6a,0xfa,0xcb,0xfa,0xf0,0xff,0xb3,0x02,
+ 0xa7,0xf6,0xad,0xfc,0x54,0x04,0x2b,0xfb,0x15,0x05,0xcb,0xfa,0xf0,0xff,0xb3,0x02,
+ 0x00,0x00,0x00,0xf8,0x00,0xf8,0x00,0x00,0x00,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xf8,0x00,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x00,0x00,0x00,0xf8,
+ 0x00,0xf8,0x5b,0xff,0xf2,0xfa,0xbb,0xfb,0x07,0xf8,0x31,0xf9,0xc4,0x01,0x90,0xfa,
+ 0x59,0xfa,0x20,0x00,0xd1,0x02,0xcf,0xfb,0xf3,0x03,0x15,0xfe,0xb5,0x02,0x25,0xfc,
+ 0x28,0xfd,0xff,0x02,0x4a,0x02,0x9a,0xf9,0x9a,0xf9,0x00,0x00,0x9a,0xf9,0x00,0x00,
+ 0x9a,0xf9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9a,0xf9,0x9a,0xf9,0x00,0x00,
+ 0x9a,0xf9,0x9a,0xf9,0x00,0x00,0x00,0x00,0x9a,0xf9,0x9a,0xf9,0x13,0xfe,0x0f,0xfc,
+ 0xd8,0xfa,0x7b,0xfb,0xb4,0xfc,0x50,0x02,0x2b,0xfb,0x14,0x02,0xc4,0xf9,0xf4,0x01,
+ 0x89,0x03,0x34,0x00,0xa9,0x00,0x41,0xfa,0x08,0xfd,0xe5,0x01,0xee,0xfc,0xb0,0xf9,
+ 0xf4,0x01,0x68,0x01,0x01,0x01,0x01,0xff,0xff,0x01,0xff,0xff,0xff,0x01,0xff,0xff,
+ 0x01,0x01,0xff,0xff,0xff,0x01,0xff,0x01,0xff,0xff,0xff,0x01,0x01,0xff,0x01,0xff,
+ 0xff,0xff,0xff,0x01,0x01,0xff,0x01,0xff,0xff,0xff,0xff,0xff,0x01,0xff,0x01,0x01,
+ 0x01,0xff,0xff,0xff,0xff,0xff,0x01,0xff,0x01,0x01,0x01,0x01,0xff,0xff,0xff,0x01,
+ 0xff,0xff,0x01,0x01,0x01,0xff,0xff,0xff,0xff,0xff,0x01,0xff,0x01,0x01,0xff,0xff,
+ 0x01,0x01,0xff,0xff,0xff,0xff,0x01,0x01,0xff,0x01,0xff,0x01,0xff,0x01,0x01,0x01,
+ 0xff,0xff,0xff,0xff,0x01,0xff,0x01,0xff,0xff,0x01,0x01,0xff,0x01,0xff,0xff,0x01,
+ 0x01,0x01,0xff,0x01,0x01,0xff,0xff,0x01,0xff,0x01,0xff,0xff,0x01,0xff,0xff,0xff,
+ 0xff,0xff,0x01,0x01,0xff,0xff,0x01,0xff,0x01,0xff,0x01,0x01,0xff,0xff,0xff,0x01,
+ 0xff,0x01,0x01,0x01,0xff,0xff,0x01,0x01,0x01,0xff,0x01,0xff,0xff,0x01,0xff,0xff,
+ 0xff,0xff,0x01,0xff,0xff,0x01,0x01,0xff,0x01,0xff,0x01,0xff,0xff,0x01,0x01,0xff,
+ 0xff,0x01,0xff,0x01,0xff,0x01,0x01,0x01,0x01,0xff,0xff,0x01,0xff,0xff,0x01,0x01,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0xff,0x01,0xff,0x01,0x01,0x01,0x01,0xff,
+ 0xff,0x01,0xff,0xff,0x01,0x01,0x00,0x00,0x01,0x02,0x04,0x08,0x00,0x01,0x02,0x02,
+ 0x03,0x03,0x03,0x03,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x05,0x05,0x05,0x05,
+ 0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x06,0x06,0x06,0x06,
+ 0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,
+ 0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x07,0x07,0x07,0x07,
+ 0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+ 0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+ 0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+ 0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x08,0x08,0x08,0x08,
+ 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+ 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+ 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+ 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+ 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+ 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+ 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+ 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x45,0x6e,0x74,0x65,
+ 0x72,0x20,0x44,0x75,0x6d,0x6d,0x79,0x20,0x45,0x78,0x63,0x65,0x70,0x74,0x69,0x6f,
+ 0x6e,0x20,0x48,0x61,0x6e,0x64,0x6c,0x65,0x72,0x21,0x20,0x00,0x6d,0x65,0x6d,0x6f,
+ 0x72,0x79,0x20,0x64,0x75,0x6d,0x70,0x3a,0x25,0x78,0x2c,0x25,0x64,0x0a,0x00,0x00,
+ 0x0a,0x00,0x00,0x00,0x25,0x78,0x20,0x00,0x25,0x32,0x64,0x3a,0x25,0x34,0x64,0x2c,
+ 0x25,0x34,0x64,0x2c,0x25,0x32,0x64,0x2c,0x25,0x32,0x64,0x7c,0x00,0x00,0x00,0x00,
+ 0x0a,0x00,0x00,0x00,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x41,0x42,
+ 0x43,0x44,0x45,0x46,0x00,0x00,0x00,0x00,0x41,0x64,0x64,0x72,0x3a,0x30,0x78,0x25,
+ 0x78,0x0a,0x00,0x00,0x25,0x35,0x64,0x2c,0x00,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,
+ 0x52,0x61,0x77,0x3a,0x54,0x78,0x3a,0x25,0x32,0x64,0x2c,0x52,0x78,0x3a,0x25,0x32,
+ 0x64,0x0a,0x00,0x00,0x42,0x61,0x73,0x65,0x3a,0x54,0x78,0x3a,0x25,0x32,0x64,0x2c,
+ 0x52,0x78,0x3a,0x25,0x32,0x64,0x0a,0x00,0x62,0x65,0x66,0x6f,0x72,0x65,0x20,0x64,
+ 0x63,0x0a,0x00,0x00,0x44,0x69,0x66,0x3a,0x54,0x78,0x3a,0x25,0x32,0x64,0x2c,0x52,
+ 0x78,0x3a,0x25,0x32,0x64,0x0a,0x00,0x00,0x61,0x66,0x74,0x65,0x72,0x20,0x64,0x63,
+ 0x66,0x69,0x6c,0x74,0x65,0x72,0x0a,0x00,0x54,0x6f,0x74,0x61,0x6c,0x20,0x4e,0x75,
+ 0x6d,0x3a,0x25,0x32,0x64,0x0a,0x00,0x00,0x30,0x78,0x25,0x34,0x78,0x2c,0x30,0x78,
+ 0x25,0x34,0x78,0x2c,0x25,0x64,0x2c,0x25,0x64,0x7c,0x00,0x00,0x75,0x38,0x50,0x6c,
+ 0x61,0x6d,0x53,0x75,0x6d,0x3a,0x25,0x64,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xb0,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x0a,0x71,0x10,0x12,0x02,0x60,0x03,0x60,0x01,0x60,0x04,0x60,0x05,0x60,0x06,0x60,
+ 0x07,0x60,0x08,0x60,0x09,0x60,0x0a,0x60,0x0b,0x60,0x0c,0x60,0x0d,0x60,0x0e,0x60,
+ 0x0f,0x60,0x02,0x7f,0x03,0x7f,0xff,0xf7,0xfc,0xaf,0x00,0x00,0xf2,0x07,0x00,0x00,
+ 0xec,0x88,0x00,0x00,0x70,0x24,0x00,0x9f,0x0d,0x72,0x0d,0x7f,0x00,0x8f,0x70,0x20,
+ 0xcf,0x00,0x70,0x24,0x00,0x9f,0x0b,0x77,0x0c,0x73,0x37,0x0f,0x04,0xe8,0x72,0x12,
+ 0x0b,0x74,0x74,0x05,0x0b,0x7f,0x0b,0x74,0x0c,0x77,0x74,0x0f,0x04,0xe8,0x72,0x12,
+ 0x03,0x60,0x74,0x05,0x0a,0x7f,0x00,0x8f,0x70,0x20,0xcf,0x00,0x8c,0x06,0x00,0x00,
+ 0x7a,0x25,0x00,0x00,0x00,0x9e,0x00,0x00,0x60,0x89,0x00,0x00,0x04,0x9e,0x00,0x00,
+ 0x8c,0x82,0x00,0x00,0x52,0xaa,0x00,0x00,0x10,0x9e,0x00,0x00,0x22,0x83,0x00,0x00,
+ 0x70,0x24,0x00,0x9f,0x12,0x60,0x69,0x7f,0x6a,0x77,0x07,0xa7,0x07,0x2a,0x29,0xe0,
+ 0x69,0x76,0x06,0x84,0x69,0x76,0x06,0x83,0x69,0x75,0x05,0x86,0xc6,0x30,0xd6,0x30,
+ 0x05,0x96,0x67,0x75,0x68,0x76,0x06,0x95,0x36,0x60,0x67,0x75,0x05,0xb6,0x67,0x75,
+ 0x05,0x97,0x67,0x75,0x05,0x97,0x35,0x12,0x65,0x01,0x66,0x77,0x07,0xd5,0x66,0x77,
+ 0x07,0xb6,0x66,0x77,0x07,0x94,0x16,0x60,0x66,0x77,0x07,0xb6,0x66,0x77,0x07,0xb6,
+ 0x76,0x12,0x06,0xa7,0x07,0x2a,0xfd,0xe7,0x62,0x76,0x06,0xb7,0x36,0x60,0x54,0x77,
+ 0x07,0xb6,0x00,0x8f,0x70,0x20,0xcf,0x00,0xcf,0x00,0x46,0x60,0x5f,0x77,0x07,0x96,
+ 0x26,0x60,0x5e,0x77,0x07,0xb6,0xcf,0x00,0x70,0x24,0x00,0x9f,0x23,0x12,0x43,0x01,
+ 0x5c,0x77,0x07,0xa7,0x07,0x2a,0x0e,0xe0,0x03,0x2a,0x5a,0x77,0x05,0xe8,0x07,0xa3,
+ 0x32,0x60,0x03,0x2a,0x05,0xe0,0x05,0xf0,0x07,0xa7,0x32,0x60,0x07,0x2a,0x01,0xe0,
+ 0x13,0x60,0x55,0x7f,0x00,0x8f,0x70,0x20,0xcf,0x00,0x54,0x76,0x06,0x87,0x07,0x34,
+ 0x17,0x34,0x06,0x97,0x53,0x76,0x06,0x87,0xe7,0x35,0x06,0x97,0xcf,0x00,0x4f,0x76,
+ 0x06,0x87,0x07,0x30,0x17,0x30,0x06,0x97,0x4e,0x76,0x06,0x87,0xe7,0x31,0x06,0x97,
+ 0xcf,0x00,0x70,0x24,0x00,0x9f,0x4b,0x77,0x07,0xa2,0x4b,0x77,0x72,0x03,0x4b,0x73,
+ 0x4c,0x7f,0x4c,0x77,0x07,0x92,0x00,0x8f,0x70,0x20,0xcf,0x00,0x70,0x24,0x00,0x9f,
+ 0x23,0x12,0x43,0x01,0x36,0x12,0x36,0x25,0x46,0x01,0x47,0x77,0x67,0x0c,0x01,0xe0,
+ 0x03,0x65,0x42,0x72,0x46,0x7f,0x40,0x77,0x72,0x03,0x40,0x73,0x41,0x7f,0x44,0x77,
+ 0x07,0x92,0x00,0x8f,0x70,0x20,0xcf,0x00,0x43,0x76,0x06,0x87,0x07,0x34,0x17,0x34,
+ 0x06,0x97,0x37,0x76,0x06,0x87,0x40,0x75,0x57,0x1e,0x06,0x97,0x16,0x60,0x3f,0x77,
+ 0x37,0xb6,0xcf,0x00,0x3c,0x76,0x06,0x87,0x07,0x30,0x17,0x30,0x06,0x97,0x30,0x76,
+ 0x06,0x87,0xf7,0x31,0x06,0x97,0xcf,0x00,0x70,0x24,0x00,0x9f,0x39,0x77,0x07,0xa2,
+ 0x39,0x7f,0x00,0x8f,0x70,0x20,0xcf,0x00,0x70,0x24,0x00,0x9f,0x02,0x60,0x36,0x7f,
+ 0x32,0x60,0x36,0x7f,0x32,0x60,0x13,0x60,0x36,0x7f,0x02,0x60,0x36,0x7f,0x36,0x7f,
+ 0x37,0x7f,0x37,0x7f,0x06,0x60,0x37,0x77,0x07,0xd6,0x37,0x7f,0x38,0x7f,0x00,0x8f,
+ 0x70,0x20,0xcf,0x00,0x03,0x01,0x07,0x60,0x02,0xf0,0x06,0xb1,0x07,0x20,0x26,0x12,
+ 0x76,0x1c,0x47,0x0f,0xfa,0xe7,0xcf,0x00,0x63,0x01,0x07,0x60,0x03,0xf0,0x02,0xd3,
+ 0x07,0x20,0x12,0x20,0x47,0x0f,0xfb,0xe7,0xcf,0x00,0x00,0x00,0xbc,0x1d,0x00,0x00,
+ 0x00,0x04,0x04,0x00,0x00,0xe0,0x10,0x00,0x04,0xe0,0x10,0x00,0x00,0x06,0x04,0x00,
+ 0x00,0x13,0x18,0x00,0x2c,0x06,0x04,0x00,0x30,0x06,0x04,0x00,0x34,0x06,0x04,0x00,
+ 0x3c,0x06,0x04,0x00,0x40,0x06,0x04,0x00,0x2a,0x00,0x04,0x00,0x30,0x00,0x04,0x00,
+ 0x28,0x00,0x04,0x00,0x44,0x06,0x04,0x00,0x0c,0x00,0x04,0x00,0x60,0x01,0x04,0x00,
+ 0x3b,0xaa,0x00,0x00,0xc2,0x9c,0x00,0x00,0x0c,0x21,0x00,0x00,0x00,0x02,0x04,0x00,
+ 0x10,0x00,0x00,0xe0,0xc3,0x9c,0x00,0x00,0x80,0xc3,0xc9,0x01,0xe8,0x03,0x00,0x00,
+ 0xd0,0x83,0x00,0x00,0x04,0x02,0x04,0x00,0xb4,0x00,0x00,0x00,0x3e,0x84,0x00,0x00,
+ 0x14,0x02,0x04,0x00,0x10,0x02,0x04,0x00,0x00,0x00,0x00,0x80,0xb0,0xa8,0x00,0x00,
+ 0xc6,0x9c,0x00,0x00,0x2c,0x09,0x00,0x00,0xa8,0x20,0x00,0x00,0xc2,0x20,0x00,0x00,
+ 0xec,0x20,0x00,0x00,0xb8,0x08,0x00,0x00,0x2c,0x10,0x00,0x00,0x12,0x09,0x00,0x00,
+ 0x88,0x09,0x00,0x00,0x10,0x9e,0x00,0x00,0x34,0x16,0x00,0x00,0x7e,0x23,0x00,0x00,
+ 0x70,0x25,0x7a,0x00,0x2c,0x12,0x3b,0x12,0x4a,0x12,0x4a,0x01,0x6e,0x72,0xc3,0x12,
+ 0xb4,0x12,0x6d,0x7f,0x0d,0x60,0x0b,0xf0,0xd2,0x12,0xa3,0x12,0x6c,0x7f,0x02,0x2a,
+ 0x02,0xe0,0x6b,0x72,0x69,0x7f,0x6b,0x72,0x0e,0xa3,0x67,0x7f,0x0d,0x20,0xce,0x12,
+ 0xde,0x1c,0xbd,0x0f,0xf1,0xe7,0x66,0x72,0x64,0x7f,0x6a,0x00,0x70,0x21,0xcf,0x00,
+ 0x07,0x60,0x02,0xf0,0x00,0x12,0x07,0x20,0x27,0x0f,0xfc,0xe7,0xcf,0x00,0xf0,0x25,
+ 0x78,0x00,0x70,0x24,0x61,0x77,0x07,0xa6,0x61,0x75,0x55,0xa7,0x06,0x2a,0x05,0xe0,
+ 0x07,0x2a,0x4a,0xe8,0x55,0xb6,0x55,0xa7,0x47,0xf0,0x07,0x2a,0x16,0xe0,0x5c,0x75,
+ 0x05,0xa7,0x07,0x2a,0x5c,0x77,0x0f,0xe0,0x25,0xa5,0x05,0x2a,0x0c,0xe0,0x07,0xc5,
+ 0x05,0x20,0x65,0x01,0x07,0xd5,0x35,0x3e,0x56,0x0c,0x36,0xe0,0x17,0x60,0x53,0x76,
+ 0x56,0xb7,0x56,0xa7,0x31,0xf0,0x06,0x60,0x2e,0xf0,0x50,0x75,0x55,0xa7,0x17,0x2a,
+ 0x0e,0xe0,0x4f,0x77,0x07,0xa6,0x06,0x2a,0x03,0xe0,0x27,0xa7,0x07,0x2a,0x24,0xe8,
+ 0x06,0x60,0x4c,0x77,0x07,0xd6,0x49,0x77,0x57,0xb6,0x57,0xa7,0x1d,0xf0,0x47,0x76,
+ 0x56,0xa7,0x27,0x2a,0x19,0xe0,0x48,0x7e,0x0e,0xca,0x48,0x7d,0x0d,0xc9,0x48,0x7c,
+ 0x0c,0xc8,0x48,0x7b,0x0b,0xc7,0x00,0x97,0x02,0x60,0x47,0x7f,0x42,0x66,0x47,0x7f,
+ 0x0e,0xda,0x0d,0xd9,0x0c,0xd8,0x00,0x85,0x0b,0xd5,0x45,0x7f,0x07,0x60,0x3b,0x76,
+ 0x56,0xb7,0x06,0x60,0x3c,0x77,0x07,0xd6,0x70,0x20,0x68,0x00,0xf0,0x21,0xcf,0x00,
+ 0xe2,0x01,0x95,0x2c,0x52,0x16,0x3f,0x77,0x27,0x0c,0x3f,0x77,0x07,0xe0,0x72,0x14,
+ 0x97,0x32,0x72,0x1c,0x02,0xa2,0xf5,0x67,0x52,0x1c,0x17,0xf0,0x86,0x2c,0x26,0x0c,
+ 0x07,0xe0,0x72,0x1c,0x3a,0x77,0x72,0x1c,0x02,0xa7,0xf2,0x67,0x72,0x05,0x0d,0xf0,
+ 0xf6,0x67,0x26,0x0c,0x06,0xe0,0x27,0x05,0x85,0x32,0x57,0x1c,0x07,0xa2,0x62,0x14,
+ 0x04,0xf0,0x72,0x1c,0x02,0xa2,0xf7,0x67,0x72,0x1c,0x42,0x01,0xcf,0x00,0xf0,0x24,
+ 0x7d,0x00,0x2d,0x12,0x6d,0x01,0x63,0x01,0x0d,0x2a,0x3e,0x12,0x7e,0x01,0x26,0xe8,
+ 0xe7,0x12,0xe7,0x1c,0xe7,0x1c,0x72,0x12,0x52,0x3c,0x72,0x1c,0x7d,0x01,0xe2,0x1c,
+ 0xd3,0x12,0x27,0x7f,0x25,0x12,0xe5,0x01,0x27,0x77,0x02,0x60,0xd6,0x62,0x07,0xc4,
+ 0x45,0x0d,0x05,0xe0,0x02,0x20,0x42,0x01,0x17,0x20,0x62,0x0f,0xf8,0xe7,0x0d,0x22,
+ 0x04,0xe0,0x0e,0x22,0x13,0xe8,0x20,0x77,0x03,0xf0,0xa7,0x65,0x0e,0x22,0x03,0xe0,
+ 0x27,0x05,0x72,0x12,0x01,0xf0,0x72,0x1c,0x42,0x01,0x08,0xf0,0xd2,0x62,0x0e,0x22,
+ 0x05,0xe8,0x03,0x2a,0x02,0xe8,0x19,0x72,0x01,0xf0,0x32,0x12,0x6d,0x00,0xf0,0x20,
+ 0xcf,0x00,0x00,0x00,0xac,0x06,0x00,0x00,0x7a,0x25,0x00,0x00,0x08,0x84,0x00,0x00,
+ 0xc0,0x06,0x00,0x00,0xc4,0x06,0x00,0x00,0xc7,0x9c,0x00,0x00,0x20,0xaa,0x00,0x00,
+ 0x70,0xa8,0x00,0x00,0x10,0x9e,0x00,0x00,0x1c,0x04,0x04,0x00,0x20,0x04,0x04,0x00,
+ 0x40,0x04,0x04,0x00,0x44,0x04,0x04,0x00,0x68,0x23,0x00,0x00,0xe0,0x0a,0x00,0x00,
+ 0x60,0x26,0x00,0x00,0x7f,0x01,0x00,0x00,0x64,0x01,0x00,0x00,0x00,0xff,0xff,0xff,
+ 0x3e,0x84,0x00,0x00,0x08,0x01,0x00,0x00,0xb4,0xff,0xff,0xff,0x87,0x00,0x00,0x00,
+ 0x72,0x01,0x22,0x03,0x73,0x01,0x33,0x03,0x23,0x1c,0xf5,0x32,0x02,0x60,0xf6,0x60,
+ 0x04,0x2d,0x17,0x60,0x37,0x0c,0x03,0xe8,0x32,0x12,0x62,0x01,0x0e,0xf0,0x27,0x12,
+ 0x27,0x1c,0x57,0x1c,0x67,0x1b,0x06,0x24,0x66,0x01,0x73,0x0c,0x03,0xe8,0x52,0x1c,
+ 0x62,0x01,0x73,0x05,0x15,0x3e,0x46,0x0f,0xf2,0xe7,0xcf,0x00,0x70,0x24,0x00,0x9f,
+ 0x28,0x77,0x07,0xa6,0x16,0x2e,0x06,0x2a,0x2f,0xe8,0x07,0xa6,0x26,0x75,0x56,0x16,
+ 0x07,0xb6,0x32,0x60,0x25,0x73,0x25,0x7f,0x32,0x60,0x25,0x73,0x24,0x7f,0x25,0x7f,
+ 0x87,0x2c,0x27,0x16,0x25,0x76,0x06,0xa5,0x06,0xb7,0x12,0x01,0x24,0x77,0x07,0xa5,
+ 0x07,0xb1,0x22,0x01,0x23,0x73,0x03,0xa5,0x03,0xb1,0x82,0x3f,0x22,0x74,0x04,0xa5,
+ 0x04,0xb2,0x06,0xa6,0x07,0xa5,0x85,0x3c,0x65,0x1e,0x03,0xa7,0x07,0x3d,0x57,0x1e,
+ 0x04,0xa3,0x83,0x3d,0x17,0x72,0x73,0x1e,0x1c,0x74,0x05,0x60,0x1c,0x7f,0x12,0x72,
+ 0x1c,0x73,0x44,0x60,0x05,0x60,0x19,0x7f,0x0e,0x77,0x07,0xa6,0x16,0x36,0x14,0xe8,
+ 0x07,0xa6,0x18,0x75,0x56,0x16,0x07,0xb6,0x32,0x60,0x17,0x73,0x0c,0x7f,0x32,0x60,
+ 0x17,0x73,0x0a,0x7f,0x16,0x72,0x16,0x73,0x17,0x74,0x05,0x60,0x10,0x7f,0x12,0x72,
+ 0x16,0x73,0x44,0x60,0x05,0x60,0x0d,0x7f,0x00,0x8f,0x70,0x20,0xcf,0x00,0x00,0x00,
+ 0x3c,0xaa,0x00,0x00,0xfe,0x00,0x00,0x00,0x00,0xb0,0x00,0x00,0x3c,0x1f,0x00,0x00,
+ 0x00,0xa0,0x00,0x00,0x96,0x3b,0x00,0x00,0x33,0xaa,0x00,0x00,0x34,0xaa,0x00,0x00,
+ 0x35,0xaa,0x00,0x00,0x36,0xaa,0x00,0x00,0xc0,0x06,0x00,0x00,0x20,0x20,0x00,0x00,
+ 0xe4,0x01,0x00,0x00,0xfd,0x00,0x00,0x00,0x00,0xd0,0x00,0x00,0x00,0xc0,0x00,0x00,
+ 0x00,0x9c,0x00,0x00,0x23,0x01,0x00,0x00,0xe8,0x01,0x00,0x00,0x70,0x24,0x7e,0x00,
+ 0x0b,0x7e,0xe2,0x12,0x03,0x60,0x64,0x60,0x0a,0x7f,0x16,0x60,0x0e,0xb6,0xa7,0x60,
+ 0x2e,0xb7,0x07,0x60,0x1e,0xb7,0x3e,0xb6,0x5e,0xb7,0x06,0x72,0x03,0x60,0x04,0x64,
+ 0x04,0x7f,0x05,0x7f,0x06,0x7f,0x6e,0x00,0x70,0x20,0xcf,0x00,0xb0,0xa8,0x00,0x00,
+ 0xc4,0x09,0x00,0x00,0x70,0xa8,0x00,0x00,0xf8,0x16,0x00,0x00,0xf8,0x1a,0x00,0x00,
+ 0xf0,0x25,0x78,0x00,0x6d,0x75,0x55,0xa7,0x27,0x2a,0xd2,0xe8,0x85,0xa7,0x07,0x2a,
+ 0x0c,0xe8,0x6a,0x77,0x16,0x60,0x17,0xb6,0x06,0x60,0x07,0xb6,0x67,0xb6,0x77,0xb6,
+ 0x47,0xb6,0x57,0xb6,0x44,0x60,0x97,0xb4,0x85,0xb6,0x64,0x77,0x07,0xa6,0x06,0x2a,
+ 0x13,0xe0,0x17,0xa6,0x06,0x2a,0x10,0xe0,0x27,0xa6,0x06,0x2a,0x0d,0xe0,0x37,0xa2,
+ 0x02,0x2a,0x0a,0xe0,0x5f,0x7e,0x1e,0xb2,0x5f,0x7f,0x3e,0xa7,0x07,0x2a,0xfd,0xef,
+ 0x06,0x60,0x5b,0x77,0x37,0xb6,0xac,0xf0,0x5a,0x77,0x27,0xa6,0x07,0xa7,0xa6,0x2a,
+ 0x06,0xe0,0x17,0x2a,0x02,0xe0,0x58,0x7f,0x07,0xf0,0x58,0x7f,0x05,0xf0,0x17,0x2a,
+ 0x02,0xe0,0x57,0x7f,0x01,0xf0,0x57,0x7f,0x2b,0x12,0x51,0x77,0x07,0xa6,0x16,0x2a,
+ 0x02,0xe8,0x16,0x60,0x07,0xb6,0x07,0xa7,0x0a,0x60,0x17,0x2a,0x51,0xe0,0x4b,0x78,
+ 0x28,0xa7,0x0b,0xb7,0xbd,0x12,0x1d,0x20,0x50,0x7c,0xae,0x12,0xa9,0x12,0x0e,0x01,
+ 0x0c,0xa7,0x07,0x2a,0x38,0xe8,0x09,0x20,0x49,0x01,0xe6,0x12,0xe6,0x1c,0xe6,0x1c,
+ 0x66,0x1c,0x86,0x1c,0x65,0x12,0x0d,0xb1,0x46,0xa6,0x1d,0xb6,0x55,0xa6,0x2d,0xb6,
+ 0x65,0xa6,0x3d,0xb6,0x75,0xa6,0x4d,0xb6,0xc6,0x12,0x06,0x24,0x06,0xa6,0x5d,0xb6,
+ 0x6d,0xb7,0x6d,0x20,0x17,0x2a,0x03,0xe8,0x47,0x2a,0x04,0xe0,0x02,0xf0,0x7a,0x12,
+ 0x01,0xf0,0x1a,0x60,0x3e,0x75,0x55,0xa6,0x05,0x64,0x56,0x16,0x06,0x2a,0x13,0xe8,
+ 0xe6,0x12,0xe6,0x1c,0xe6,0x1c,0x66,0x1c,0x86,0x1c,0x46,0xaf,0x56,0xa4,0x84,0x3c,
+ 0x66,0xa1,0x76,0xa5,0x85,0x3c,0xc6,0x12,0x06,0x24,0x35,0x72,0xe3,0x12,0xf4,0x1e,
+ 0x15,0x1e,0x06,0xa6,0x34,0x7f,0x0e,0x20,0x5c,0x20,0x5e,0x2a,0xc0,0xe7,0x2f,0x77,
+ 0x57,0xa7,0x06,0x64,0x67,0x16,0x07,0x2a,0x02,0xe8,0x2f,0x72,0x2e,0x7f,0x1b,0xb9,
+ 0x23,0x77,0x27,0xa6,0x37,0xb6,0x22,0x77,0x22,0x7d,0x37,0xa6,0x06,0x2a,0xfc,0xef,
+ 0x07,0x60,0x3d,0xb7,0x4e,0x66,0x29,0x72,0x2a,0x7f,0x5d,0xa7,0x07,0x2a,0x04,0xe8,
+ 0x0e,0x24,0x4e,0x01,0x0e,0x2a,0xf7,0xe7,0x1a,0x77,0x27,0xa6,0xa6,0x2a,0x02,0xe0,
+ 0xb6,0x60,0x01,0xf0,0xa6,0x60,0x27,0xb6,0x16,0x7d,0x17,0x60,0x1d,0xb7,0x1a,0x2a,
+ 0x1c,0xe0,0x0d,0xa7,0x3e,0x60,0x0c,0x60,0x4d,0xbc,0x12,0x60,0x12,0x7f,0x1d,0x7f,
+ 0x03,0xf0,0x1d,0xa7,0x07,0x2a,0x0b,0xe8,0x4d,0xa7,0x07,0x2a,0xfa,0xef,0x02,0x60,
+ 0x0d,0x7f,0x16,0x72,0x17,0x7f,0x0e,0x24,0x4e,0x01,0x0e,0x2a,0xed,0xe7,0x02,0x60,
+ 0x09,0x7f,0x06,0x60,0x15,0x77,0x07,0x96,0x03,0xf0,0x12,0x60,0x06,0x7f,0x11,0x7f,
+ 0x68,0x00,0xf0,0x21,0xcf,0x00,0x00,0x00,0x20,0xaa,0x00,0x00,0x70,0xa8,0x00,0x00,
+ 0xb0,0xa8,0x00,0x00,0xb8,0x08,0x00,0x00,0xc2,0x17,0x00,0x00,0x06,0x1b,0x00,0x00,
+ 0xbe,0x17,0x00,0x00,0xfa,0x1a,0x00,0x00,0x79,0xa8,0x00,0x00,0x44,0xaa,0x00,0x00,
+ 0xc8,0x06,0x00,0x00,0x7a,0x25,0x00,0x00,0xe0,0x06,0x00,0x00,0xc8,0x00,0x00,0x00,
+ 0xe0,0x0a,0x00,0x00,0xea,0x08,0x00,0x00,0x18,0x02,0x04,0x00,0x89,0x76,0x06,0x87,
+ 0x57,0x30,0x07,0x31,0x06,0x97,0x36,0x60,0x87,0x77,0x07,0xb6,0x87,0x76,0x87,0x77,
+ 0x07,0xd6,0x87,0x76,0x88,0x77,0x07,0xd6,0x17,0x60,0x87,0x76,0x06,0xb7,0x87,0x76,
+ 0x06,0xb7,0x87,0x77,0x07,0xa6,0x35,0x60,0x56,0x1e,0x07,0xb6,0x54,0x60,0x85,0x76,
+ 0x06,0xb4,0x85,0x76,0x06,0xb5,0x07,0xa6,0x85,0x75,0x56,0x16,0x07,0xb6,0x84,0x76,
+ 0x85,0x77,0x07,0xd6,0x85,0x76,0x06,0x87,0x07,0x34,0x06,0x97,0x84,0x77,0x05,0x60,
+ 0x07,0xb5,0x17,0xb5,0x24,0x60,0x37,0xb4,0x27,0xb5,0x47,0xb5,0x06,0x87,0x80,0x75,
+ 0x57,0x1e,0x06,0x97,0xcf,0x00,0xf0,0x24,0x7c,0x00,0x7e,0x77,0x13,0x60,0x57,0xb3,
+ 0x7e,0x75,0x05,0xa5,0x05,0x2a,0x64,0xe8,0x7d,0x74,0x04,0xa6,0x16,0x2e,0x06,0x2a,
+ 0x03,0xe8,0x07,0xb3,0x26,0x60,0x05,0xf0,0x04,0xa4,0x14,0x36,0x04,0xe8,0x26,0x60,
+ 0x07,0xb6,0x72,0x77,0x37,0xb6,0x71,0x76,0x07,0x60,0x26,0xb7,0x36,0xa7,0x57,0x0f,
+ 0x4f,0xe0,0x04,0x60,0x73,0x7d,0x0d,0xa2,0x26,0xa3,0x53,0x0c,0x0f,0xe0,0x03,0x2a,
+ 0x03,0xe0,0x06,0xb2,0x07,0x60,0x09,0xf0,0x06,0xae,0x16,0xa7,0x87,0x3c,0xe7,0x1e,
+ 0x87,0x3c,0x27,0x1c,0x67,0x01,0x06,0xb7,0x87,0x3e,0x16,0xb7,0x64,0x7e,0x37,0x12,
+ 0x07,0x20,0x26,0xb7,0x04,0x20,0x44,0x01,0x54,0x0f,0xe5,0xe7,0x07,0x60,0x4e,0xb7,
+ 0x16,0x60,0x56,0x77,0x07,0xb6,0x5f,0x77,0x07,0xa7,0x8d,0x60,0x62,0x7c,0x17,0x2a,
+ 0x14,0xe0,0x0e,0xa2,0x1e,0xa7,0x87,0x3c,0x72,0x1e,0x5f,0x7f,0x0c,0xb2,0x0e,0xa6,
+ 0x1e,0xa7,0x87,0x3c,0x67,0x1e,0x07,0x20,0x67,0x01,0x0e,0xb7,0x87,0x3e,0x1e,0xb7,
+ 0x0d,0x24,0x4d,0x01,0x0d,0x2a,0xed,0xe7,0x13,0xf0,0x0e,0xa2,0x1e,0xa7,0x87,0x3c,
+ 0x72,0x1e,0x56,0x7f,0x0c,0xb2,0x0e,0xa6,0x1e,0xa7,0x87,0x3c,0x67,0x1e,0x07,0x20,
+ 0x67,0x01,0x0e,0xb7,0x87,0x3e,0x1e,0xb7,0x0d,0x24,0x4d,0x01,0x0d,0x2a,0xed,0xe7,
+ 0x47,0x77,0x47,0xa6,0x06,0x2a,0x04,0xe8,0x06,0x60,0x3c,0x75,0x05,0xb6,0x47,0xb6,
+ 0x0e,0x60,0x27,0xbe,0x02,0x60,0x4a,0x7f,0x43,0x77,0x17,0xa6,0x06,0x2a,0x01,0xe8,
+ 0x17,0xbe,0x6c,0x00,0xf0,0x20,0xcf,0x00,0x70,0x25,0x7b,0x00,0x3e,0x76,0x07,0x60,
+ 0x56,0xb7,0x3a,0x7e,0x17,0x60,0x4e,0xb7,0x06,0xb7,0x26,0x60,0x3e,0xb6,0x3a,0x7c,
+ 0x0c,0xac,0x0c,0x2a,0x28,0xe8,0x0d,0x60,0x3a,0x7b,0x0b,0xa3,0x2e,0xa7,0x3e,0xa6,
+ 0x67,0x0c,0x0b,0xe0,0x07,0x2a,0x02,0xe0,0x0e,0xb3,0x14,0xf0,0x0e,0xa6,0x1e,0xa7,
+ 0x87,0x3c,0x67,0x1e,0x87,0x3c,0x37,0x1c,0x0a,0xf0,0x0e,0xa2,0x1e,0xa7,0x87,0x3c,
+ 0x72,0x1e,0x34,0x7f,0x0e,0xa6,0x1e,0xa7,0x87,0x3c,0x67,0x1e,0x07,0x20,0x67,0x01,
+ 0x0e,0xb7,0x87,0x3e,0x1e,0xb7,0x2e,0xa7,0x07,0x20,0x2e,0xb7,0x0d,0x20,0x4d,0x01,
+ 0xcd,0x0f,0xdb,0xe7,0x02,0xf0,0x19,0x76,0x06,0xb7,0x20,0x7e,0x2e,0xa6,0x3e,0xa7,
+ 0x76,0x0f,0x1a,0xe0,0x07,0x60,0x4e,0xb7,0x16,0x60,0x14,0x77,0x07,0xb6,0x8d,0x60,
+ 0x21,0x7c,0x0e,0xa2,0x1e,0xa7,0x87,0x3c,0x72,0x1e,0x1f,0x7f,0x0c,0xb2,0x0e,0xa6,
+ 0x1e,0xa7,0x87,0x3c,0x67,0x1e,0x07,0x20,0x67,0x01,0x0e,0xb7,0x87,0x3e,0x1e,0xb7,
+ 0x0d,0x24,0x4d,0x01,0x0d,0x2a,0xed,0xe7,0x6b,0x00,0x70,0x21,0xcf,0x00,0x00,0x00,
+ 0x08,0x00,0x04,0x00,0x14,0x00,0x04,0x00,0x78,0x01,0x00,0x00,0x20,0x0e,0x04,0x00,
+ 0x48,0x01,0x00,0x00,0x24,0x0e,0x04,0x00,0x19,0x0e,0x04,0x00,0x1d,0x0e,0x04,0x00,
+ 0x00,0x0e,0x04,0x00,0x2c,0x0e,0x04,0x00,0x30,0x0e,0x04,0x00,0xfb,0x00,0x00,0x00,
+ 0x88,0x03,0x00,0x00,0x34,0x0e,0x04,0x00,0x10,0x00,0x00,0xe0,0x12,0x9e,0x00,0x00,
+ 0xfe,0x00,0x00,0x00,0xb0,0xa8,0x00,0x00,0x18,0x0e,0x04,0x00,0x0c,0x0e,0x04,0x00,
+ 0x14,0x0e,0x04,0x00,0x10,0x0e,0x04,0x00,0xc6,0x17,0x00,0x00,0x12,0x1b,0x00,0x00,
+ 0xb8,0x08,0x00,0x00,0x9a,0x18,0x00,0x00,0x70,0x25,0x7b,0x00,0x75,0x75,0x07,0x60,
+ 0x55,0xb7,0x74,0x7e,0x17,0x60,0x4e,0xb7,0x26,0x60,0x05,0xb6,0x3e,0xb6,0x72,0x7c,
+ 0x0c,0xac,0x0c,0x2a,0x28,0xe8,0x0d,0x60,0x71,0x7b,0x0b,0xa3,0x2e,0xa7,0x3e,0xa6,
+ 0x67,0x0c,0x0b,0xe0,0x07,0x2a,0x02,0xe0,0x0e,0xb3,0x14,0xf0,0x0e,0xa6,0x1e,0xa7,
+ 0x87,0x3c,0x67,0x1e,0x87,0x3c,0x37,0x1c,0x0a,0xf0,0x0e,0xa2,0x1e,0xa7,0x87,0x3c,
+ 0x72,0x1e,0x67,0x7f,0x0e,0xa6,0x1e,0xa7,0x87,0x3c,0x67,0x1e,0x07,0x20,0x67,0x01,
+ 0x0e,0xb7,0x87,0x3e,0x1e,0xb7,0x2e,0xa7,0x07,0x20,0x2e,0xb7,0x0d,0x20,0x4d,0x01,
+ 0xcd,0x0f,0xdb,0xe7,0x02,0xf0,0x5f,0x76,0x06,0xb7,0x5a,0x7e,0x2e,0xa6,0x3e,0xa7,
+ 0x76,0x0f,0x1a,0xe0,0x07,0x60,0x4e,0xb7,0x16,0x60,0x5a,0x77,0x07,0xb6,0x8d,0x60,
+ 0x5a,0x7c,0x0e,0xa2,0x1e,0xa7,0x87,0x3c,0x72,0x1e,0x58,0x7f,0x0c,0xb2,0x0e,0xa6,
+ 0x1e,0xa7,0x87,0x3c,0x67,0x1e,0x07,0x20,0x67,0x01,0x0e,0xb7,0x87,0x3e,0x1e,0xb7,
+ 0x0d,0x24,0x4d,0x01,0x0d,0x2a,0xed,0xe7,0x6b,0x00,0x70,0x21,0xcf,0x00,0x70,0x25,
+ 0x7b,0x00,0x4f,0x77,0x07,0xac,0x8c,0x28,0x4c,0x01,0x45,0x77,0x07,0xa6,0x16,0x2a,
+ 0x19,0xe0,0x12,0xf0,0x0e,0xa2,0x1e,0xa7,0x87,0x3c,0x72,0x1e,0x4a,0x7f,0x0b,0xb2,
+ 0x0d,0x20,0x4d,0x01,0x0e,0xa6,0x1e,0xa7,0x87,0x3c,0x67,0x1e,0x07,0x20,0x67,0x01,
+ 0x0e,0xb7,0x87,0x3e,0x1e,0xb7,0x03,0xf0,0x0d,0x60,0x3a,0x7e,0x3f,0x7b,0xcd,0x0f,
+ 0xe9,0xe7,0x1b,0xf0,0x07,0xa7,0x27,0x2a,0x18,0xe0,0x12,0xf0,0x0e,0xa2,0x1e,0xa7,
+ 0x87,0x3c,0x72,0x1e,0x3a,0x7f,0x0b,0xb2,0x0d,0x20,0x4d,0x01,0x0e,0xa6,0x1e,0xa7,
+ 0x87,0x3c,0x67,0x1e,0x07,0x20,0x67,0x01,0x0e,0xb7,0x87,0x3e,0x1e,0xb7,0x03,0xf0,
+ 0x0d,0x60,0x2c,0x7e,0x31,0x7b,0xcd,0x0f,0xe9,0xe7,0x6b,0x00,0x70,0x21,0xcf,0x00,
+ 0x70,0x24,0x00,0x9f,0x31,0x7f,0x00,0x8f,0x70,0x20,0xcf,0x00,0x70,0x25,0x7a,0x00,
+ 0x2f,0x76,0x06,0xa7,0x17,0x2e,0x07,0x2a,0x07,0xe8,0x16,0x60,0x21,0x77,0x07,0xb6,
+ 0x26,0x60,0x20,0x77,0x37,0xb6,0x08,0xf0,0x06,0xa6,0x16,0x36,0x05,0xe8,0x27,0x60,
+ 0x1c,0x76,0x06,0xb7,0x1c,0x76,0x36,0xb7,0x1c,0x7c,0x0c,0xac,0x0d,0x60,0x1b,0x7b,
+ 0x19,0x7e,0x17,0x7a,0x28,0xf0,0x0b,0xa3,0x2e,0xa7,0x3e,0xa6,0x67,0x0c,0x0b,0xe0,
+ 0x07,0x2a,0x02,0xe0,0x0e,0xb3,0x19,0xf0,0x0e,0xa6,0x1e,0xa7,0x87,0x3c,0x67,0x1e,
+ 0x87,0x3c,0x37,0x1c,0x0f,0xf0,0x0a,0xa7,0x17,0x2a,0x0e,0xa2,0x1e,0xa7,0x87,0x3c,
+ 0x72,0x1e,0x02,0xe0,0x17,0x7f,0x01,0xf0,0x0e,0x7f,0x0e,0xa6,0x1e,0xa7,0x87,0x3c,
+ 0x67,0x1e,0x07,0x20,0x67,0x01,0x0e,0xb7,0x87,0x3e,0x1e,0xb7,0x2e,0xa7,0x07,0x20,
+ 0x2e,0xb7,0x0d,0x20,0x4d,0x01,0xcd,0x0f,0xd6,0xe7,0x6a,0x00,0x70,0x21,0xcf,0x00,
+ 0xb0,0xa8,0x00,0x00,0x12,0x9e,0x00,0x00,0x18,0x0e,0x04,0x00,0x14,0x0e,0x04,0x00,
+ 0x20,0x1b,0x00,0x00,0x1d,0x0e,0x04,0x00,0x10,0x0e,0x04,0x00,0x12,0x1b,0x00,0x00,
+ 0x1c,0x0e,0x04,0x00,0xc6,0x17,0x00,0x00,0x6e,0x13,0x00,0x00,0x0c,0x0e,0x04,0x00,
+ 0x9a,0x18,0x00,0x00,0x70,0x24,0x00,0x9f,0x4f,0x7f,0x00,0x8f,0x70,0x20,0xcf,0x00,
+ 0x70,0x24,0x7e,0x00,0x4d,0x7e,0x0e,0xa2,0x1e,0xa7,0x87,0x3c,0x72,0x1e,0x4b,0x7f,
+ 0x4c,0x77,0x07,0xb2,0x0e,0xa6,0x1e,0xa7,0x87,0x3c,0x67,0x1e,0x07,0x20,0x67,0x01,
+ 0x0e,0xb7,0x87,0x3e,0x1e,0xb7,0x6e,0x00,0x70,0x20,0xcf,0x00,0x70,0x24,0x7e,0x00,
+ 0x42,0x7e,0x0e,0xa2,0x1e,0xa7,0x87,0x3c,0x72,0x1e,0x42,0x7f,0x41,0x77,0x07,0xb2,
+ 0x0e,0xa6,0x1e,0xa7,0x87,0x3c,0x67,0x1e,0x07,0x20,0x67,0x01,0x0e,0xb7,0x87,0x3e,
+ 0x1e,0xb7,0x6e,0x00,0x70,0x20,0xcf,0x00,0x70,0x24,0x7e,0x00,0x16,0x60,0x3a,0x77,
+ 0x07,0xb6,0x35,0x7e,0x27,0x60,0x3e,0xb7,0x39,0x73,0x03,0xa3,0x2e,0xa5,0x16,0x60,
+ 0x56,0x0c,0x0e,0xe8,0x05,0x2a,0x04,0xe0,0x2e,0xb6,0x0e,0xb3,0x07,0x60,0x15,0xf0,
+ 0x2e,0xb7,0x0e,0xa6,0x1e,0xa7,0x87,0x3c,0x67,0x1e,0x87,0x3c,0x37,0x1c,0x0a,0xf0,
+ 0x0e,0xa2,0x1e,0xa7,0x87,0x3c,0x72,0x1e,0x2e,0x7f,0x0e,0xa6,0x1e,0xa7,0x87,0x3c,
+ 0x67,0x1e,0x07,0x20,0x67,0x01,0x0e,0xb7,0x87,0x3e,0x1e,0xb7,0x6e,0x00,0x70,0x20,
+ 0xcf,0x00,0x70,0x24,0x7e,0x00,0x27,0x60,0x24,0x76,0x06,0xb7,0x1f,0x7e,0x3e,0xb7,
+ 0x23,0x73,0x03,0xa3,0x2e,0xa5,0x16,0x60,0x56,0x0c,0x0e,0xe8,0x05,0x2a,0x04,0xe0,
+ 0x2e,0xb6,0x0e,0xb3,0x07,0x60,0x15,0xf0,0x2e,0xb7,0x0e,0xa6,0x1e,0xa7,0x87,0x3c,
+ 0x67,0x1e,0x87,0x3c,0x37,0x1c,0x0a,0xf0,0x0e,0xa2,0x1e,0xa7,0x87,0x3c,0x72,0x1e,
+ 0x19,0x7f,0x0e,0xa6,0x1e,0xa7,0x87,0x3c,0x67,0x1e,0x07,0x20,0x67,0x01,0x0e,0xb7,
+ 0x87,0x3e,0x1e,0xb7,0x6e,0x00,0x70,0x20,0xcf,0x00,0x70,0x24,0x00,0x9f,0x12,0x77,
+ 0x07,0xa6,0x12,0x75,0x56,0x16,0x07,0xb6,0x07,0xa6,0x16,0x34,0x07,0xb6,0x10,0x7f,
+ 0x00,0x8f,0x70,0x20,0xcf,0x00,0x62,0x01,0x04,0x77,0x07,0xb2,0x82,0x3e,0x17,0xb2,
+ 0xcf,0x00,0x00,0x00,0xfc,0x13,0x00,0x00,0x12,0x9e,0x00,0x00,0xc6,0x17,0x00,0x00,
+ 0x10,0x0e,0x04,0x00,0x12,0x1b,0x00,0x00,0xb0,0xa8,0x00,0x00,0x14,0x0e,0x04,0x00,
+ 0x9a,0x18,0x00,0x00,0x20,0x1b,0x00,0x00,0x04,0x00,0x04,0x00,0xfd,0x00,0x00,0x00,
+ 0x2c,0x10,0x00,0x00,0xcf,0x00,0xcf,0x00,0xcf,0x00,0xcf,0x00,0xcf,0x00,0xcf,0x00,
+ 0x70,0x24,0x00,0x9f,0x22,0x7f,0x02,0x60,0x22,0x7f,0x16,0x60,0x22,0x77,0x47,0xb6,
+ 0x00,0x8f,0x70,0x20,0xcf,0x00,0x16,0x60,0x1f,0x77,0x37,0xb6,0x1f,0x77,0x07,0xa6,
+ 0x06,0x20,0x46,0x01,0x07,0xb6,0x1d,0x75,0x05,0xa5,0x56,0x0c,0x1e,0xe8,0x06,0x60,
+ 0x07,0xb6,0x1b,0x72,0x02,0xa6,0x1b,0x74,0x04,0xa7,0x87,0x3c,0x67,0x1e,0x1a,0x75,
+ 0x05,0xa3,0x03,0x3d,0x73,0x1e,0x19,0x76,0x06,0xa7,0x87,0x3d,0x37,0x1e,0x07,0x20,
+ 0x83,0x2c,0x73,0x16,0x02,0xa1,0x02,0xb3,0x17,0x01,0x04,0xa3,0x04,0xb1,0x27,0x01,
+ 0x05,0xa4,0x05,0xb1,0x87,0x3f,0x06,0xa5,0x06,0xb7,0x11,0x75,0x05,0xa4,0x11,0x76,
+ 0x06,0xa7,0x87,0x3c,0x47,0x1e,0x07,0x20,0x67,0x01,0x84,0x2c,0x74,0x16,0x05,0xa3,
+ 0x05,0xb4,0x87,0x3e,0x06,0xa5,0x06,0xb7,0xcf,0x00,0x00,0x00,0xfe,0x08,0x00,0x00,
+ 0xb8,0x08,0x00,0x00,0xb0,0xa8,0x00,0x00,0x17,0x9e,0x00,0x00,0xc6,0x9c,0x00,0x00,
+ 0x37,0xaa,0x00,0x00,0x38,0xaa,0x00,0x00,0x39,0xaa,0x00,0x00,0x3a,0xaa,0x00,0x00,
+ 0x40,0xaa,0x00,0x00,0x41,0xaa,0x00,0x00,0xf0,0x24,0x7d,0x00,0x91,0x7e,0xe2,0x12,
+ 0x03,0x60,0x24,0x62,0x90,0x7f,0x90,0x72,0x03,0x60,0x90,0x74,0x8e,0x7f,0x90,0x72,
+ 0x03,0x60,0x64,0x60,0x8c,0x7f,0x76,0x62,0x9e,0xb6,0x8e,0x77,0xae,0xb7,0x47,0x60,
+ 0xbe,0xb7,0xce,0xb6,0xee,0xb7,0x02,0x60,0x8c,0x7f,0x2e,0x12,0x42,0x60,0x8a,0x7f,
+ 0x2d,0x12,0x27,0x12,0x47,0x3c,0xe7,0x1e,0x47,0x01,0x88,0x76,0x06,0xb7,0x02,0x2a,
+ 0x05,0xe0,0x42,0x60,0x87,0x7f,0x42,0x60,0xd3,0x12,0x86,0x7f,0x7d,0x77,0x0e,0x60,
+ 0x67,0xbe,0x77,0xbe,0x1d,0x60,0x87,0xbd,0x84,0x7f,0x86,0x2c,0x26,0x16,0x83,0x77,
+ 0x07,0xa5,0x07,0xb6,0x12,0x01,0x82,0x77,0x07,0xa6,0x07,0xb1,0x22,0x01,0x81,0x77,
+ 0x07,0xa6,0x07,0xb1,0x82,0x3f,0x80,0x77,0x07,0xa6,0x07,0xb2,0x80,0x77,0x07,0xa6,
+ 0x07,0xbe,0x7f,0x77,0x07,0xa6,0x07,0xbe,0x7f,0x77,0x07,0xa6,0x07,0xbe,0x7e,0x77,
+ 0x07,0xa6,0x07,0xbe,0x7e,0x77,0x07,0xbe,0x7e,0x77,0x07,0xbe,0x6d,0x77,0x57,0xbe,
+ 0x26,0x62,0x7c,0x77,0x07,0xb6,0x6d,0x76,0x06,0xa6,0x27,0x62,0x76,0x0f,0x7a,0x77,
+ 0x02,0xe0,0x07,0xbd,0x01,0xf0,0x07,0xbe,0x6d,0x00,0xf0,0x20,0xcf,0x00,0x62,0x72,
+ 0xcf,0x00,0x76,0x72,0xcf,0x00,0x27,0x12,0x67,0x01,0xc6,0x2c,0x76,0x0c,0x06,0xe8,
+ 0x82,0x2c,0x16,0x62,0x76,0x0c,0x60,0xe8,0x5a,0x76,0x0f,0xf0,0xd6,0x2c,0x76,0x0c,
+ 0x14,0xe8,0x6f,0x75,0x57,0x1c,0x67,0x01,0x82,0x2c,0x6e,0x76,0x76,0x0c,0x54,0xe8,
+ 0x6e,0x76,0x26,0xa5,0xa5,0x2a,0x04,0xe0,0x54,0x76,0x76,0x1c,0x06,0xa2,0x4c,0xf0,
+ 0x26,0xa6,0xb6,0x2a,0x49,0xe0,0x65,0x76,0xf8,0xf7,0x68,0x76,0x76,0x0c,0x12,0xe8,
+ 0x57,0x75,0x05,0xa5,0x57,0x76,0x06,0xa6,0x86,0x3c,0x56,0x1e,0x56,0x75,0x05,0xa5,
+ 0x05,0x3d,0x65,0x1e,0x55,0x76,0x06,0xa6,0x86,0x3d,0x56,0x1e,0x61,0x75,0x57,0x1c,
+ 0x67,0x01,0xe3,0xf7,0xe6,0x2c,0x76,0x0c,0x06,0xe8,0x5e,0x76,0x67,0x1c,0x67,0x01,
+ 0x5e,0x75,0x57,0x1c,0x28,0xf0,0x76,0x12,0x76,0x01,0x82,0x2c,0xf6,0x37,0x24,0xe8,
+ 0x5b,0x76,0x76,0x0c,0x05,0xe8,0x5a,0x76,0x67,0x1c,0x67,0x01,0x5a,0x76,0x1a,0xf0,
+ 0x5a,0x76,0x76,0x0c,0x19,0xe0,0xc5,0x32,0x57,0x1c,0x67,0x01,0x47,0x2a,0x38,0x76,
+ 0x11,0xe0,0x06,0xa5,0x16,0xa7,0x87,0x3c,0x57,0x1e,0x26,0xa5,0x05,0x3d,0x75,0x1e,
+ 0x36,0xa7,0x87,0x3d,0x57,0x1e,0x51,0x76,0x67,0x0f,0x05,0xe0,0x15,0x60,0x50,0x76,
+ 0x06,0xb5,0x01,0xf0,0x67,0x1c,0x07,0xa2,0xcf,0x00,0x70,0x24,0x7e,0x00,0x62,0x01,
+ 0x3e,0x12,0x4e,0x01,0xc7,0x2c,0x27,0x0c,0xda,0xe8,0x17,0x62,0x27,0x0c,0xff,0xe8,
+ 0x22,0x2a,0x0b,0xe8,0x42,0x2a,0x0c,0xe8,0x02,0x2a,0xf9,0xe0,0x21,0x77,0x07,0xa6,
+ 0xe6,0x0f,0xf5,0xe8,0x16,0x60,0x17,0xb6,0xee,0xf0,0x1d,0x77,0x27,0xbe,0xef,0xf0,
+ 0x1e,0x2a,0x02,0xe0,0x40,0x7f,0xc1,0xf0,0x2e,0x2a,0x03,0xe0,0x19,0x77,0x57,0xbe,
+ 0xbc,0xf0,0x4e,0x2a,0x08,0xe0,0x3c,0x77,0x07,0xa7,0x37,0x2a,0xb6,0xe0,0x28,0x76,
+ 0x06,0xa7,0x17,0x34,0x86,0xf0,0xe6,0x12,0xf6,0x24,0x46,0x01,0x67,0x60,0x67,0x0c,
+ 0x03,0xe8,0xe2,0x12,0x36,0x7f,0xa9,0xf0,0x07,0x62,0x7e,0x0f,0x07,0xe0,0x16,0x60,
+ 0x34,0x77,0x07,0xb6,0x06,0x60,0x0a,0x77,0x27,0xb6,0x9f,0xf0,0x07,0x63,0x7e,0x0f,
+ 0x03,0xe0,0x16,0x60,0x2b,0x77,0x98,0xf0,0x57,0x65,0x16,0x60,0x7e,0x0f,0x04,0xe8,
+ 0x67,0x66,0x7e,0x0f,0x57,0xe0,0x06,0x60,0x02,0x77,0x77,0xb6,0x8e,0xf0,0x00,0x00,
+ 0x20,0xaa,0x00,0x00,0x22,0x83,0x00,0x00,0xc0,0xa8,0x00,0x00,0x60,0x01,0x00,0x00,
+ 0x44,0xaa,0x00,0x00,0x85,0xff,0xff,0xff,0xa4,0x21,0x00,0x00,0x30,0xaa,0x00,0x00,
+ 0xc2,0x20,0x00,0x00,0xec,0x20,0x00,0x00,0x96,0x3b,0x00,0x00,0x33,0xaa,0x00,0x00,
+ 0x34,0xaa,0x00,0x00,0x35,0xaa,0x00,0x00,0x36,0xaa,0x00,0x00,0x37,0xaa,0x00,0x00,
+ 0x38,0xaa,0x00,0x00,0x39,0xaa,0x00,0x00,0x3a,0xaa,0x00,0x00,0x3b,0xaa,0x00,0x00,
+ 0x3c,0xaa,0x00,0x00,0x3e,0xaa,0x00,0x00,0x3f,0xaa,0x00,0x00,0x30,0xa9,0x00,0x00,
+ 0x00,0xf0,0xff,0xff,0xb0,0x00,0x00,0x00,0xb0,0xa8,0x00,0x00,0xff,0x2f,0x00,0x00,
+ 0x00,0xe0,0xff,0xff,0x00,0xd0,0xff,0xff,0x00,0xe0,0x02,0x00,0xff,0x8f,0x00,0x00,
+ 0x00,0x80,0xff,0xff,0x00,0x9c,0x00,0x00,0xff,0xef,0x00,0x00,0xff,0xff,0x04,0x00,
+ 0x31,0xaa,0x00,0x00,0x60,0x26,0x00,0x00,0x18,0x9e,0x00,0x00,0x72,0x2d,0x00,0x00,
+ 0x32,0xaa,0x00,0x00,0x17,0x62,0x7e,0x0f,0x06,0xe0,0x07,0x60,0x32,0x76,0x06,0xb7,
+ 0x32,0x76,0x26,0xb7,0x32,0xf0,0x07,0x67,0x7e,0x0f,0x05,0xe0,0x30,0x76,0x06,0xa7,
+ 0x07,0x34,0x06,0xb7,0x2a,0xf0,0x2e,0x77,0x26,0x60,0x7e,0x0f,0x04,0xe8,0x2d,0x77,
+ 0x7e,0x0f,0x03,0xe0,0x06,0x60,0x2c,0x77,0x1f,0xf0,0x2c,0x77,0x16,0x60,0x7e,0x0f,
+ 0x04,0xe8,0x2b,0x77,0x7e,0x0f,0x03,0xe0,0x06,0x60,0x2a,0x77,0x15,0xf0,0x5e,0x2a,
+ 0x06,0xe0,0x16,0x60,0x29,0x77,0x07,0xb6,0x32,0x60,0x13,0x60,0x07,0xf0,0x6e,0x2a,
+ 0x07,0xe0,0x16,0x60,0x25,0x77,0x07,0xb6,0x32,0x60,0x03,0x60,0x24,0x7f,0x05,0xf0,
+ 0x7e,0x2a,0x03,0xe0,0x06,0x60,0x20,0x77,0x07,0xb6,0x21,0x77,0x24,0xf0,0xd7,0x2c,
+ 0x27,0x0c,0x25,0xe0,0xe7,0x2c,0x27,0x0c,0x22,0xe0,0x27,0x12,0xf7,0x36,0x1f,0xe8,
+ 0x1d,0x77,0x27,0x0c,0x05,0xe8,0x1c,0x77,0x72,0x1c,0x62,0x01,0x1c,0x77,0x15,0xf0,
+ 0x1c,0x77,0x27,0x0c,0x14,0xe0,0xc7,0x32,0x72,0x1c,0x62,0x01,0x42,0x2a,0x19,0x77,
+ 0x0c,0xe0,0x07,0xa6,0x17,0xa5,0x85,0x3c,0x65,0x1e,0x27,0xa6,0x06,0x3d,0x56,0x1e,
+ 0x37,0xa7,0x87,0x3d,0x67,0x1e,0x07,0xbe,0x02,0xf0,0x72,0x1c,0x02,0xbe,0x6e,0x00,
+ 0x70,0x20,0xcf,0x00,0x32,0xaa,0x00,0x00,0x20,0xaa,0x00,0x00,0x3c,0xaa,0x00,0x00,
+ 0x90,0x00,0x00,0x00,0x91,0x00,0x00,0x00,0x72,0x9c,0x00,0x00,0xa0,0x00,0x00,0x00,
+ 0xa1,0x00,0x00,0x00,0x11,0x9d,0x00,0x00,0x3b,0xaa,0x00,0x00,0x0c,0x21,0x00,0x00,
+ 0x18,0x9e,0x00,0x00,0xff,0x8f,0x00,0x00,0x00,0x80,0xff,0xff,0x00,0x9c,0x00,0x00,
+ 0xff,0xef,0x00,0x00,0x44,0xaa,0x00,0x00,0xcf,0x00,0x70,0x24,0x00,0x9f,0x0c,0x7f,
+ 0x00,0x8f,0x70,0x20,0xcf,0x00,0x70,0x24,0x00,0x9f,0x0a,0x7f,0x00,0x8f,0x70,0x20,
+ 0xcf,0x00,0x70,0x24,0x00,0x9f,0x62,0x01,0x08,0x7f,0x00,0x8f,0x70,0x20,0xcf,0x00,
+ 0x70,0x24,0x00,0x9f,0x62,0x01,0x43,0x01,0x05,0x7f,0x00,0x8f,0x70,0x20,0xcf,0x00,
+ 0xbe,0x17,0x00,0x00,0xc2,0x17,0x00,0x00,0xc6,0x17,0x00,0x00,0x9a,0x18,0x00,0x00,
+ 0x70,0x24,0x00,0x9f,0x09,0x77,0x07,0x86,0x09,0x77,0x09,0x72,0x76,0x0f,0x05,0xe0,
+ 0x09,0x73,0x09,0x74,0x15,0x60,0x09,0x7f,0x03,0xf0,0x09,0x73,0x07,0x74,0x09,0x7f,
+ 0x00,0x8f,0x70,0x20,0xcf,0x00,0x00,0x00,0x00,0xd0,0x10,0x00,0x5a,0xa5,0x66,0x6a,
+ 0x00,0x9c,0x00,0x00,0x00,0xc0,0x00,0x00,0x23,0x01,0x00,0x00,0xf6,0x1e,0x00,0x00,
+ 0xec,0x01,0x00,0x00,0x8c,0x82,0x00,0x00,0xf0,0x25,0x79,0x00,0x24,0x76,0x07,0x60,
+ 0x16,0xb7,0x56,0xb7,0x23,0x75,0x05,0xb7,0x26,0xb7,0x22,0x7f,0x23,0x72,0x23,0x7f,
+ 0x24,0x7f,0x24,0x7f,0x25,0x7f,0x25,0x7f,0x02,0x2a,0xfb,0xe7,0x25,0x7f,0x1b,0x7e,
+ 0x1c,0x79,0x24,0x7d,0x25,0x7c,0x25,0x7b,0x26,0x7a,0x26,0xf0,0x26,0x7f,0x26,0x7f,
+ 0x1d,0x7f,0x1d,0x7f,0x1e,0x7f,0x02,0x2a,0xfb,0xe7,0x24,0x7f,0x25,0x7f,0x09,0xa7,
+ 0x07,0x2a,0x13,0xe8,0x24,0x7f,0x87,0x2c,0x27,0x16,0x0d,0xa6,0x0d,0xb7,0x12,0x01,
+ 0x0c,0xa7,0x0c,0xb1,0x22,0x01,0x0b,0xa7,0x0b,0xb1,0x82,0x3f,0x0a,0xa7,0x0a,0xb2,
+ 0x17,0x60,0x2e,0xb7,0x2e,0xa7,0x07,0x2a,0xfd,0xe7,0x1b,0x7f,0x1c,0x7f,0x1c,0x7f,
+ 0x1d,0x72,0x1d,0x7f,0x1e,0x7f,0x1e,0x7f,0x0e,0xa7,0x07,0x2a,0xd7,0xef,0x1d,0x7f,
+ 0x16,0x60,0x02,0x77,0x17,0xb6,0x69,0x00,0xf0,0x21,0xcf,0x00,0x20,0xaa,0x00,0x00,
+ 0x32,0xaa,0x00,0x00,0x58,0x09,0x00,0x00,0x00,0x9c,0x00,0x00,0x8e,0x31,0x00,0x00,
+ 0x94,0x3b,0x00,0x00,0xd0,0x3c,0x00,0x00,0xea,0x3c,0x00,0x00,0x16,0x3c,0x00,0x00,
+ 0x7c,0x3c,0x00,0x00,0x33,0xaa,0x00,0x00,0x34,0xaa,0x00,0x00,0x35,0xaa,0x00,0x00,
+ 0x36,0xaa,0x00,0x00,0x8e,0x23,0x00,0x00,0x5e,0x31,0x00,0x00,0x70,0x3b,0x00,0x00,
+ 0xfc,0x0c,0x00,0x00,0x96,0x3b,0x00,0x00,0xf4,0x3c,0x00,0x00,0x5c,0x4f,0x00,0x00,
+ 0xf6,0x63,0x00,0x00,0x70,0xa8,0x00,0x00,0x3a,0x48,0x00,0x00,0x30,0x0e,0x00,0x00,
+ 0xee,0x0a,0x00,0x00,0x74,0x09,0x00,0x00,0xf0,0x25,0x79,0x00,0x02,0x60,0x34,0x7f,
+ 0x35,0x7e,0x0d,0x60,0x2e,0xbd,0x5e,0xbd,0x34,0x72,0x34,0x7f,0x1e,0xbd,0x34,0x7d,
+ 0x35,0x7c,0x35,0x7b,0x36,0x7a,0x19,0x60,0x20,0xf0,0x35,0x7f,0x36,0x7f,0x36,0x7f,
+ 0x37,0x7f,0x37,0x7f,0x02,0x2a,0xfb,0xe7,0x37,0x7f,0x37,0x7f,0x38,0x7f,0x87,0x2c,
+ 0x27,0x16,0x0d,0xa6,0x0d,0xb7,0x12,0x01,0x0c,0xa7,0x0c,0xb1,0x22,0x01,0x0b,0xa7,
+ 0x0b,0xb1,0x82,0x3f,0x0a,0xa7,0x0a,0xb2,0x2e,0xb9,0x04,0xf0,0x29,0x7f,0x0e,0xa7,
+ 0x17,0x2a,0x03,0xe0,0x2e,0xa7,0x07,0x2a,0xf9,0xe7,0x0e,0xa7,0x17,0x2a,0xdd,0xef,
+ 0x06,0x60,0x1c,0x77,0x27,0xb6,0x69,0x00,0xf0,0x21,0xcf,0x00,0xf0,0x25,0x78,0x00,
+ 0x02,0x60,0x17,0x7f,0x18,0x7e,0x0d,0x60,0x2e,0xbd,0x5e,0xbd,0x17,0x72,0x17,0x7f,
+ 0x1e,0xbd,0xed,0x12,0x23,0x7c,0x23,0x7b,0x24,0x7a,0x24,0x79,0x25,0x78,0x17,0xf0,
+ 0x18,0x7f,0x0c,0xbe,0x0b,0xa7,0x17,0x3e,0x47,0x34,0x0a,0xb7,0x09,0xbe,0x07,0x60,
+ 0x08,0xd7,0x20,0x76,0x21,0x77,0x07,0xd6,0x17,0x60,0x2d,0xb7,0x04,0xf0,0x10,0x7f,
+ 0x0d,0xa7,0x27,0x2a,0x03,0xe0,0x2d,0xa7,0x07,0x2a,0xf9,0xe7,0x13,0x7f,0x0d,0xae,
+ 0x2e,0x2a,0xe6,0xef,0x06,0x60,0x03,0x77,0x27,0xb6,0x68,0x00,0xf0,0x21,0xcf,0x00,
+ 0xa8,0x08,0x00,0x00,0x20,0xaa,0x00,0x00,0x00,0x9c,0x00,0x00,0x8e,0x31,0x00,0x00,
+ 0x33,0xaa,0x00,0x00,0x34,0xaa,0x00,0x00,0x35,0xaa,0x00,0x00,0x36,0xaa,0x00,0x00,
+ 0x8e,0x23,0x00,0x00,0x5e,0x31,0x00,0x00,0xd0,0x3c,0x00,0x00,0xea,0x3c,0x00,0x00,
+ 0x16,0x3c,0x00,0x00,0x70,0x3b,0x00,0x00,0xfc,0x0c,0x00,0x00,0x96,0x3b,0x00,0x00,
+ 0x5c,0x08,0x04,0x00,0x2a,0x9c,0x00,0x00,0x5d,0x08,0x04,0x00,0x74,0x08,0x04,0x00,
+ 0xa8,0x08,0x04,0x00,0xfc,0x7f,0x00,0x00,0xaa,0x08,0x04,0x00,0x02,0x01,0x78,0x76,
+ 0x06,0x87,0x78,0x74,0x47,0x1e,0x06,0x97,0x11,0x2a,0x77,0x77,0x07,0xa6,0x1a,0xe0,
+ 0x77,0x75,0x56,0x16,0x07,0xb6,0x76,0x76,0x06,0xa7,0x57,0x16,0x06,0xb7,0x75,0x76,
+ 0x06,0xa7,0x57,0x16,0x06,0xb7,0x74,0x77,0x07,0xb1,0x36,0x60,0x74,0x77,0x07,0xb6,
+ 0x74,0x75,0x05,0xa7,0x6e,0x74,0x47,0x16,0x05,0xb7,0x72,0x75,0x05,0xa7,0x47,0x16,
+ 0x05,0xb7,0x32,0xf0,0x21,0x2a,0x1a,0xe0,0x69,0x75,0x56,0x16,0x07,0xb6,0x68,0x76,
+ 0x06,0xa7,0x07,0x34,0x06,0xb7,0x67,0x76,0x06,0xa7,0x57,0x16,0x06,0xb7,0x16,0x60,
+ 0x66,0x77,0x07,0xb6,0x35,0x60,0x65,0x77,0x07,0xb5,0x65,0x75,0x05,0xa7,0x5f,0x74,
+ 0x47,0x16,0x05,0xb7,0x64,0x77,0x07,0xb6,0xb6,0x63,0x16,0xf0,0x41,0x2a,0x0d,0xe0,
+ 0x5b,0x75,0x56,0x16,0x07,0xb6,0x5a,0x77,0x07,0xa7,0x07,0x34,0x5a,0x76,0x06,0xb7,
+ 0x16,0x60,0x5c,0x77,0x07,0xb6,0xb6,0x66,0x07,0xf0,0x54,0x74,0x46,0x16,0x07,0xb6,
+ 0x16,0x60,0x58,0x77,0x07,0xb6,0xb6,0x60,0x58,0x77,0x07,0xb6,0x16,0x60,0x57,0x77,
+ 0x07,0x96,0xcf,0x00,0xc6,0x32,0x56,0x77,0x07,0x96,0x66,0x60,0x56,0x77,0x07,0xb6,
+ 0x06,0x60,0x55,0x77,0x07,0x96,0x55,0x77,0x16,0x60,0x07,0xb6,0x07,0xa6,0x06,0x2a,
+ 0xfd,0xe7,0xcf,0x00,0x02,0x01,0x52,0x76,0x4e,0x77,0x07,0x96,0x57,0x63,0x01,0x2a,
+ 0x01,0xe0,0x57,0x60,0x4c,0x76,0x06,0xb7,0x16,0x60,0x4b,0x77,0x07,0x96,0x4b,0x77,
+ 0x07,0xb6,0x07,0xa6,0x06,0x2a,0xfd,0xe7,0x4b,0x72,0x02,0xa2,0xcf,0x00,0x70,0x24,
+ 0x00,0x9f,0x49,0x7f,0x4a,0x76,0x42,0x77,0x07,0x96,0x16,0x60,0x42,0x77,0x07,0xb6,
+ 0x05,0x60,0x41,0x77,0x07,0x95,0x46,0x75,0x47,0x77,0x07,0xd5,0x40,0x77,0x07,0xb6,
+ 0x07,0xa6,0x06,0x2a,0xfd,0xe7,0x02,0x60,0x44,0x7f,0x12,0x2e,0x02,0x2a,0xfb,0xe7,
+ 0x00,0x8f,0x70,0x20,0xcf,0x00,0x05,0x01,0x11,0x2a,0x07,0xe8,0x21,0x2a,0x08,0xe8,
+ 0x41,0x2a,0x09,0xe0,0x3e,0x76,0xb7,0x66,0x08,0xf0,0x3d,0x76,0x37,0x60,0x05,0xf0,
+ 0x3d,0x76,0xb7,0x63,0x02,0xf0,0x3c,0x76,0xb7,0x60,0x2d,0x75,0x05,0x96,0x2d,0x76,
+ 0x06,0xb7,0x3a,0x77,0x07,0x93,0x3a,0x77,0x07,0x92,0x2b,0x77,0x07,0x94,0x2b,0x77,
+ 0x16,0x60,0x07,0xb6,0x07,0xa6,0x06,0x2a,0xfd,0xe7,0xcf,0x00,0xf0,0x24,0x7d,0x00,
+ 0x3d,0x12,0x2e,0x12,0x4e,0x01,0x28,0x7f,0x0e,0x2a,0x22,0x77,0x06,0xe0,0x31,0x76,
+ 0x07,0xb6,0xc6,0x32,0x1f,0x77,0x07,0x96,0x12,0xf0,0x1e,0x2a,0x06,0xe0,0x26,0x65,
+ 0x07,0xb6,0x2d,0x76,0x1b,0x77,0x07,0x96,0x08,0xf0,0x04,0x62,0x2e,0x2a,0x18,0x76,
+ 0x2a,0x75,0x01,0xe0,0x2a,0x74,0x07,0xb4,0x06,0x95,0x24,0x77,0x07,0x9d,0x06,0x60,
+ 0x16,0x77,0x07,0x96,0x16,0x77,0x16,0x60,0x07,0xb6,0x07,0xa6,0x06,0x2a,0xfd,0xe7,
+ 0x02,0x60,0x19,0x7f,0x12,0x2e,0x02,0x2a,0xfb,0xe7,0x6d,0x00,0xf0,0x20,0xcf,0x00,
+ 0x00,0x06,0x04,0x00,0x00,0x00,0x00,0x15,0x04,0x06,0x04,0x00,0xfe,0x00,0x00,0x00,
+ 0x08,0x06,0x04,0x00,0x0c,0x06,0x04,0x00,0x10,0x06,0x04,0x00,0x14,0x06,0x04,0x00,
+ 0x18,0x06,0x04,0x00,0x1c,0x06,0x04,0x00,0x20,0x06,0x04,0x00,0x28,0x06,0x04,0x00,
+ 0x2c,0x06,0x04,0x00,0x30,0x06,0x04,0x00,0x40,0x06,0x04,0x00,0x44,0x06,0x04,0x00,
+ 0x00,0x10,0x08,0x00,0x48,0x06,0x04,0x00,0x74,0x1e,0x00,0x00,0x20,0x10,0x00,0x00,
+ 0x02,0x02,0x00,0x00,0x38,0x06,0x04,0x00,0x94,0x1e,0x00,0x00,0x01,0x1d,0x18,0x00,
+ 0x00,0x13,0x18,0x00,0x01,0x1d,0x1a,0x00,0x01,0x13,0x18,0x00,0x34,0x06,0x04,0x00,
+ 0x3c,0x06,0x04,0x00,0xc7,0xff,0xff,0xff,0x00,0x13,0x00,0x00,0xd8,0xff,0xff,0xff,
+ 0xf0,0x25,0x78,0x00,0x70,0x24,0x38,0x12,0x4c,0x12,0x05,0x01,0x2a,0x60,0x01,0x2a,
+ 0x03,0xe8,0x11,0x2a,0x01,0xe0,0x74,0x7a,0x2b,0x12,0x0e,0x60,0x74,0x79,0x24,0xf0,
+ 0x02,0x60,0x73,0x7f,0x12,0x2e,0x02,0x2a,0xfb,0xe7,0x72,0x7f,0x73,0x77,0x73,0x76,
+ 0x06,0x97,0x73,0x76,0x06,0x9b,0x00,0x86,0x73,0x77,0x07,0x96,0x87,0x32,0xd7,0x1c,
+ 0x7c,0x0c,0x03,0xe8,0x87,0x32,0x09,0xd7,0x03,0xf0,0xcd,0x14,0x6d,0x01,0x09,0xdd,
+ 0x6e,0x77,0x07,0xba,0x6e,0x77,0x16,0x60,0x07,0xb6,0x86,0x32,0x6b,0x1c,0x07,0xa6,
+ 0x06,0x2a,0xfd,0xe7,0x87,0x32,0x7e,0x1c,0xe6,0x12,0x86,0x1c,0x00,0x96,0xed,0x12,
+ 0x6d,0x01,0xcd,0x0c,0xd5,0xef,0x02,0x60,0x5e,0x7f,0x12,0x2e,0x02,0x2a,0xfb,0xe7,
+ 0x70,0x20,0x68,0x00,0xf0,0x21,0xcf,0x00,0x02,0x01,0x01,0x2a,0x61,0x76,0x06,0xa7,
+ 0x04,0xe0,0x07,0x30,0x17,0x30,0x07,0x34,0x02,0xf0,0x5e,0x75,0x57,0x16,0x06,0xb7,
+ 0xcf,0x00,0x02,0x01,0x87,0x60,0x17,0x0c,0x06,0xe8,0x5b,0x77,0x07,0xc6,0x11,0x13,
+ 0x61,0x1e,0x61,0x01,0x07,0xd1,0xcf,0x00,0x02,0x01,0x87,0x60,0x17,0x0c,0x05,0xe8,
+ 0x56,0x76,0x06,0xc7,0x11,0x13,0x17,0x1f,0x06,0xd7,0xcf,0x00,0x02,0x01,0x43,0x01,
+ 0x87,0x60,0x17,0x0c,0x0a,0xe8,0x03,0x2a,0x51,0x77,0x11,0x13,0x07,0xc6,0x03,0xe8,
+ 0x16,0x1e,0x66,0x01,0x01,0xf0,0x16,0x1f,0x07,0xd6,0xcf,0x00,0x02,0x01,0x43,0x01,
+ 0x87,0x60,0x17,0x0c,0x0a,0xe8,0x03,0x2a,0x4a,0x77,0x11,0x13,0x07,0xc6,0x03,0xe8,
+ 0x16,0x1e,0x66,0x01,0x01,0xf0,0x16,0x1f,0x07,0xd6,0xcf,0x00,0x02,0x01,0x43,0x01,
+ 0x87,0x60,0x17,0x0c,0x0a,0xe8,0x03,0x2a,0x43,0x77,0x11,0x13,0x07,0xc6,0x03,0xe8,
+ 0x16,0x1e,0x66,0x01,0x01,0xf0,0x16,0x1f,0x07,0xd6,0xcf,0x00,0x02,0x01,0x82,0x2c,
+ 0x87,0x60,0x17,0x0c,0x08,0xe8,0x3c,0x76,0x06,0xc6,0x17,0x13,0x67,0x16,0x47,0x01,
+ 0x17,0x1a,0x72,0x12,0x42,0x01,0xcf,0x00,0x02,0x01,0x77,0x60,0x17,0x0c,0x0a,0xe8,
+ 0x37,0x76,0x06,0xc7,0x11,0x13,0x17,0x1f,0x06,0xd7,0x35,0x76,0x06,0xc7,0x17,0x1e,
+ 0x67,0x01,0x06,0xd7,0xcf,0x00,0x02,0x01,0x77,0x60,0x17,0x0c,0x0a,0xe8,0x30,0x76,
+ 0x06,0xc7,0x11,0x13,0x17,0x1f,0x06,0xd7,0x2d,0x76,0x06,0xc7,0x17,0x1e,0x67,0x01,
+ 0x06,0xd7,0xcf,0x00,0x70,0x25,0x7a,0x00,0x2e,0x12,0x4e,0x01,0x82,0x2c,0x77,0x60,
+ 0xe7,0x0c,0x26,0xe8,0x21,0x7d,0x0d,0xcd,0x21,0x7c,0x0c,0xcc,0x24,0x7b,0x0b,0xcb,
+ 0x24,0x7a,0x0a,0xca,0xe2,0x12,0x23,0x7f,0xe2,0x12,0x03,0x60,0x23,0x7f,0xe2,0x12,
+ 0x23,0x7f,0x42,0x66,0x23,0x7f,0xe2,0x12,0x23,0x7f,0x02,0x2a,0x09,0xe8,0xe2,0x12,
+ 0x22,0x7f,0x42,0x66,0x1f,0x7f,0xe2,0x12,0x1f,0x7f,0x02,0x2a,0x32,0x00,0x02,0x20,
+ 0x12,0x77,0x07,0xdd,0x12,0x77,0x07,0xdc,0x15,0x77,0x07,0xdb,0x15,0x77,0x07,0xda,
+ 0x6a,0x00,0x70,0x21,0xcf,0x00,0x00,0x00,0xf2,0x00,0x00,0x00,0x40,0x06,0x04,0x00,
+ 0x94,0x1e,0x00,0x00,0x74,0x1e,0x00,0x00,0x00,0x13,0x00,0x00,0x2c,0x06,0x04,0x00,
+ 0x34,0x06,0x04,0x00,0x3c,0x06,0x04,0x00,0x30,0x06,0x04,0x00,0x44,0x06,0x04,0x00,
+ 0x58,0x01,0x04,0x00,0xfc,0x00,0x00,0x00,0x1c,0x04,0x04,0x00,0x20,0x04,0x04,0x00,
+ 0x24,0x04,0x04,0x00,0x08,0x04,0x04,0x00,0x28,0x04,0x04,0x00,0x38,0x04,0x04,0x00,
+ 0x3c,0x04,0x04,0x00,0xc2,0x20,0x00,0x00,0xec,0x20,0x00,0x00,0x68,0x21,0x00,0x00,
+ 0xe0,0x0a,0x00,0x00,0x4c,0x21,0x00,0x00,0x86,0x21,0x00,0x00,0xf0,0x24,0x7d,0x00,
+ 0x2e,0x12,0x4e,0x01,0x3d,0x12,0x4d,0x01,0x87,0x60,0xe7,0x0c,0x12,0xe8,0xe2,0x12,
+ 0x03,0x60,0x5f,0x7f,0x60,0x76,0x06,0xc7,0xee,0x13,0xe5,0x12,0x65,0x01,0x57,0x1e,
+ 0x06,0xd7,0x0d,0x2a,0x5d,0x77,0x07,0xc6,0x02,0xe8,0x56,0x1e,0x01,0xf0,0xe6,0x1f,
+ 0x07,0xd6,0x6d,0x00,0xf0,0x20,0xcf,0x00,0x02,0x01,0x21,0x2a,0x08,0xe0,0x57,0x76,
+ 0x06,0xa7,0x17,0x34,0x06,0xb7,0x56,0x76,0x06,0xa7,0x17,0x34,0x06,0xb7,0x55,0x76,
+ 0x06,0xa7,0x55,0x75,0x57,0x1e,0x06,0xb7,0x55,0x76,0x06,0xa7,0x57,0x1e,0x06,0xb7,
+ 0x54,0x76,0x06,0xa7,0x57,0x1e,0x06,0xb7,0x66,0x60,0x52,0x77,0x07,0xb6,0x52,0x76,
+ 0x06,0x87,0xa7,0x34,0x06,0x97,0x16,0x60,0x51,0x77,0x07,0xb6,0x51,0x76,0x06,0xa7,
+ 0x07,0x34,0x06,0xb7,0x50,0x76,0x06,0x87,0x50,0x75,0x57,0x1e,0x06,0x97,0x4f,0x76,
+ 0x06,0x87,0x4f,0x75,0x57,0x1e,0x06,0x97,0x4f,0x77,0x07,0xa6,0x16,0x34,0x07,0xb6,
+ 0x07,0xa6,0x06,0x34,0x07,0xb6,0xcf,0x00,0x02,0x01,0x4a,0x77,0x07,0xa6,0x4a,0x75,
+ 0x56,0x16,0x07,0xb6,0x07,0xa6,0x49,0x75,0x56,0x16,0x07,0xb6,0x06,0x60,0x3f,0x77,
+ 0x07,0xb6,0x40,0x76,0x06,0x87,0x46,0x75,0x57,0x16,0x06,0x97,0x40,0x76,0x06,0x87,
+ 0x45,0x75,0x57,0x16,0x06,0x97,0x3a,0x76,0x06,0xa7,0x3f,0x75,0x57,0x16,0x06,0xb7,
+ 0x21,0x2a,0x09,0xe0,0x2e,0x76,0x06,0xa7,0x3d,0x75,0x57,0x16,0x06,0xb7,0x2c,0x76,
+ 0x06,0xa7,0x57,0x16,0x06,0xb7,0xcf,0x00,0x70,0x24,0x7e,0x00,0x2e,0x12,0x4e,0x01,
+ 0xe2,0x12,0x39,0x7f,0xe2,0x12,0x39,0x7f,0x6e,0x00,0x70,0x20,0xcf,0x00,0x38,0x76,
+ 0x39,0x77,0x07,0xd6,0xcf,0x00,0x06,0x60,0x37,0x77,0x07,0xd6,0xcf,0x00,0x36,0x77,
+ 0x16,0x60,0x07,0xb6,0x36,0x76,0x07,0xb6,0xcf,0x00,0xf0,0x24,0x7d,0x00,0x2d,0x12,
+ 0x3e,0x12,0x4e,0x01,0x32,0x60,0x0e,0x2a,0x0b,0xe8,0x52,0x60,0x4e,0x2a,0x08,0xe8,
+ 0x5e,0x2a,0x03,0xe0,0x12,0x60,0x23,0x12,0x04,0xf0,0x7e,0x2a,0x14,0xe0,0x22,0x60,
+ 0x13,0x60,0x2b,0x7f,0xe2,0x12,0x2b,0x7f,0xd2,0x12,0x2b,0x73,0x2c,0x7f,0x62,0x01,
+ 0x2c,0x77,0x07,0xd2,0x2c,0x77,0x07,0xd2,0x16,0x61,0x2b,0x77,0x07,0xb6,0x2b,0x76,
+ 0x06,0xa7,0x07,0x34,0x06,0xb7,0x6d,0x00,0xf0,0x20,0xcf,0x00,0x02,0x01,0x28,0x77,
+ 0x07,0xb1,0x28,0x76,0x06,0xa7,0x17,0x2e,0x07,0x2a,0xfc,0xe7,0xcf,0x00,0x00,0x00,
+ 0xec,0x20,0x00,0x00,0x40,0x04,0x04,0x00,0x44,0x04,0x04,0x00,0x21,0x0e,0x04,0x00,
+ 0x25,0x0e,0x04,0x00,0x1c,0x04,0x04,0x00,0xa7,0x00,0x00,0x00,0x20,0x04,0x04,0x00,
+ 0x38,0x04,0x04,0x00,0x61,0x01,0x04,0x00,0x04,0x00,0x04,0x00,0x40,0x01,0x04,0x00,
+ 0x0b,0x00,0x04,0x00,0x0c,0x01,0x04,0x00,0x00,0x00,0x0f,0x00,0x04,0x01,0x04,0x00,
+ 0x03,0x20,0x00,0x00,0x44,0x01,0x04,0x00,0xfe,0x00,0x00,0x00,0xfd,0x00,0x00,0x00,
+ 0xff,0xff,0xf0,0xff,0xfc,0xdf,0xff,0xff,0xa8,0x22,0x00,0x00,0x18,0x23,0x00,0x00,
+ 0x10,0x02,0x00,0x00,0x24,0x00,0x04,0x00,0x26,0x00,0x04,0x00,0xfe,0xff,0xff,0xff,
+ 0x2c,0x21,0x00,0x00,0xd8,0x20,0x00,0x00,0x00,0xc2,0x01,0x00,0xd0,0x83,0x00,0x00,
+ 0x22,0x02,0x04,0x00,0x32,0x02,0x04,0x00,0x30,0x02,0x04,0x00,0x20,0x02,0x04,0x00,
+ 0x24,0x02,0x04,0x00,0x28,0x02,0x04,0x00,0xf0,0x25,0x78,0x00,0x01,0x63,0x10,0x05,
+ 0x3c,0x12,0x4a,0x12,0x4a,0x01,0x59,0x12,0x49,0x01,0x09,0x2a,0x27,0x00,0xa0,0x97,
+ 0xa6,0x12,0x06,0x24,0x46,0x01,0xf7,0x60,0x67,0x0c,0x07,0xe0,0xa7,0x62,0x03,0xb7,
+ 0x07,0x60,0x13,0xb7,0x32,0x12,0x12,0x20,0x4d,0xf0,0x0b,0x60,0xf2,0x37,0x03,0xe8,
+ 0xaa,0x2a,0x4d,0xe8,0x2b,0x60,0x2d,0x12,0x2b,0x2a,0x4c,0xe0,0x5a,0x77,0x26,0x12,
+ 0xf6,0x2e,0x67,0x1c,0x07,0xa7,0x00,0xb7,0x4d,0x3e,0x1e,0x60,0x08,0x12,0xe8,0x1c,
+ 0x13,0xf0,0xd2,0x12,0xa3,0x12,0x54,0x7f,0x53,0x77,0x72,0x1c,0x02,0xa7,0x08,0xb7,
+ 0x08,0x20,0x0e,0x20,0x4e,0x01,0xd2,0x12,0xa3,0x12,0x50,0x7f,0x2d,0x12,0xa0,0x87,
+ 0x07,0x2a,0x02,0xe8,0x9e,0x0c,0x04,0xe0,0x0d,0x2a,0xeb,0xe7,0x08,0x0f,0xe9,0xef,
+ 0x1b,0x2a,0x05,0xe0,0xd7,0x62,0x08,0xb7,0x08,0x20,0x0e,0x20,0x4e,0x01,0xa0,0x87,
+ 0x07,0x2a,0x06,0xe8,0x08,0xf0,0x08,0xb7,0x08,0x20,0x0e,0x20,0x4e,0x01,0x04,0xf0,
+ 0x86,0x12,0xc7,0x12,0x08,0xf0,0x07,0x62,0x9e,0x0c,0xf5,0xef,0xf9,0xf7,0x06,0x24,
+ 0x06,0xa5,0x07,0xb5,0x07,0x20,0x06,0x0f,0xfa,0xe7,0x82,0x12,0x02,0x05,0xc2,0x1c,
+ 0x07,0x60,0x02,0xb7,0x01,0x63,0x10,0x1c,0x68,0x00,0xf0,0x21,0xcf,0x00,0x2d,0x12,
+ 0x0d,0x28,0x1b,0x60,0x0e,0x60,0x08,0x12,0xcf,0xf7,0x81,0x63,0x10,0x05,0xd0,0x97,
+ 0xc0,0x96,0xb0,0x95,0xa0,0x94,0x90,0x93,0x80,0x92,0x78,0x00,0xf0,0x25,0x07,0x64,
+ 0x07,0x1c,0x07,0x8e,0x4d,0x64,0x0d,0x1c,0x0c,0x60,0x59,0x62,0x4a,0x64,0x4a,0xf0,
+ 0x97,0x0f,0x0a,0xe8,0x0c,0x2a,0x08,0xe0,0xa7,0x2a,0x02,0xe0,0xd2,0x60,0x28,0x7f,
+ 0x0e,0xa2,0x0e,0x20,0x27,0x7f,0x3e,0xf0,0x1e,0xa2,0xa2,0x0f,0x18,0xe8,0x2a,0x0c,
+ 0x06,0xe8,0x24,0x76,0x26,0x1c,0x87,0x60,0x67,0x0c,0x2f,0xe8,0x0a,0xf0,0x47,0x66,
+ 0x72,0x0f,0x0d,0xe8,0x87,0x67,0x72,0x0f,0x19,0xe8,0x87,0x65,0x72,0x0f,0x25,0xe0,
+ 0x15,0xf0,0x0e,0x20,0x1d,0x77,0x72,0x1c,0x2c,0x12,0x4c,0x01,0x23,0xf0,0xdb,0x12,
+ 0x3b,0x20,0x0d,0x82,0x03,0x12,0xa4,0x60,0xc5,0x12,0x18,0x7f,0x08,0x12,0x02,0xf0,
+ 0x14,0x7f,0x08,0x20,0x08,0xa2,0x02,0x2a,0xfb,0xe7,0x11,0xf0,0xdb,0x12,0x3b,0x20,
+ 0x0d,0x82,0x03,0x12,0x04,0x61,0xc5,0x12,0x11,0x7f,0x08,0x12,0x02,0xf0,0x0c,0x7f,
+ 0x08,0x20,0x08,0xa2,0x02,0x2a,0xfb,0xe7,0x02,0xf0,0x09,0x7f,0xdb,0x12,0x1e,0x20,
+ 0xbd,0x12,0x0c,0x60,0x0e,0xa7,0x07,0x2a,0xb3,0xe7,0xf0,0x21,0x68,0x00,0x81,0x63,
+ 0x10,0x1c,0xcf,0x00,0xe4,0x06,0x00,0x00,0x08,0x84,0x00,0x00,0xd0,0x83,0x00,0x00,
+ 0xec,0x23,0x00,0x00,0xcf,0xff,0xff,0xff,0xd0,0xff,0xff,0xff,0x98,0x24,0x00,0x00,
+ 0x10,0x76,0x06,0xa7,0x10,0x75,0x57,0x16,0x06,0xb7,0xcf,0x00,0x0f,0x75,0x05,0xc5,
+ 0x45,0x01,0xf7,0x61,0x57,0x0c,0x12,0xe8,0x0d,0x77,0x07,0xc7,0xf7,0x01,0x47,0x01,
+ 0x75,0x0f,0x0c,0xe0,0x07,0xf0,0x07,0x84,0x47,0xa3,0x04,0xb3,0x06,0x20,0x46,0x01,
+ 0x77,0x20,0x02,0xf0,0x07,0x77,0x06,0x60,0x56,0x0c,0xf5,0xef,0xcf,0x00,0x00,0x00,
+ 0x04,0x00,0x04,0x00,0xfe,0x00,0x00,0x00,0x00,0xf0,0x10,0x00,0x02,0xf0,0x10,0x00,
+ 0x04,0xf0,0x10,0x00,0x70,0x24,0x7e,0x00,0xb2,0x71,0x01,0x8f,0xff,0x34,0x01,0x9f,
+ 0xb1,0x71,0x01,0x8f,0x1f,0x34,0x01,0x9f,0xb0,0x7e,0x0e,0xb2,0xb0,0x72,0x02,0xb3,
+ 0xb0,0x73,0x03,0x95,0xb0,0x75,0x05,0x96,0xb0,0x76,0x06,0x97,0xb0,0x77,0x20,0x86,
+ 0x07,0x96,0xaf,0x77,0x07,0xb4,0x01,0x87,0x07,0x34,0x01,0x97,0xae,0x76,0x06,0x87,
+ 0x17,0x2e,0x07,0x2a,0xfc,0xe7,0xa2,0x76,0x06,0x87,0xf7,0x34,0x06,0x97,0xa1,0x76,
+ 0x06,0x87,0x17,0x30,0x06,0x97,0x6e,0x00,0x70,0x20,0xcf,0x00,0x70,0x24,0x7e,0x00,
+ 0x2e,0x12,0x32,0x12,0xf2,0x3c,0x03,0x60,0x35,0x12,0xa3,0x7f,0xa4,0x74,0x05,0x60,
+ 0xa4,0x7f,0x62,0x01,0x0e,0x2a,0x02,0xe0,0xa3,0x77,0x13,0xf0,0x1e,0x2a,0x04,0xe8,
+ 0x2e,0x2a,0x04,0xe0,0xa0,0x77,0x07,0xd2,0xa0,0x77,0x0b,0xf0,0x3e,0x2a,0x02,0xe0,
+ 0x9f,0x77,0x07,0xf0,0x4e,0x2a,0x04,0xe8,0x5e,0x2a,0x04,0xe0,0x9c,0x77,0x07,0xd2,
+ 0x9c,0x77,0x07,0xd2,0x6e,0x00,0x70,0x20,0xcf,0x00,0x70,0x24,0x7e,0x00,0x2e,0x12,
+ 0x99,0x72,0x99,0x7f,0x0e,0x2a,0x03,0xe0,0x62,0x01,0x98,0x77,0x09,0xf0,0x1e,0x2a,
+ 0x03,0xe0,0x62,0x01,0x97,0x77,0x04,0xf0,0x2e,0x2a,0x03,0xe0,0x62,0x01,0x95,0x77,
+ 0x07,0xd2,0x6e,0x00,0x70,0x20,0xcf,0x00,0x94,0x75,0x95,0xa6,0x06,0x2a,0x93,0x77,
+ 0x01,0xe8,0x16,0x60,0x07,0xb6,0x05,0xa6,0x15,0xa7,0x87,0x3c,0x67,0x1e,0x25,0xa6,
+ 0x06,0x3d,0x76,0x1e,0x35,0xa7,0x87,0x3d,0x67,0x1e,0x8d,0x76,0x67,0x0f,0x02,0xe0,
+ 0x8d,0x76,0x04,0xf0,0x8d,0x76,0x67,0x0f,0x03,0xe0,0x8c,0x76,0x8d,0x77,0x07,0xd6,
+ 0x86,0x77,0xa7,0xa6,0xb7,0xa7,0x87,0x3c,0x67,0x1e,0x8a,0x76,0x06,0xd7,0x6c,0x76,
+ 0x06,0x87,0xf7,0x34,0x06,0x97,0x88,0x77,0x07,0x86,0x16,0x34,0x07,0x96,0x07,0x86,
+ 0x06,0x34,0x07,0x96,0x70,0x76,0x06,0x87,0x87,0x2e,0x07,0x2a,0xfc,0xe7,0x64,0x76,
+ 0x06,0x87,0xf7,0x34,0x06,0x97,0x80,0x76,0x06,0x87,0x17,0x30,0x06,0x97,0xcf,0x00,
+ 0x70,0x25,0x7a,0x00,0x75,0x77,0x0d,0x60,0x97,0xbd,0x7c,0x7e,0x07,0xbe,0x1e,0x01,
+ 0x17,0xb1,0x2e,0x01,0x27,0xb1,0xe6,0x12,0x86,0x3f,0x37,0xb6,0x79,0x76,0x26,0xac,
+ 0x8b,0x2c,0xcb,0x16,0xa7,0xbb,0x06,0x60,0xb7,0xb6,0x76,0x7f,0x77,0x74,0x04,0xa6,
+ 0x14,0xa7,0x87,0x3c,0x67,0x1e,0x75,0x76,0x06,0xb7,0x87,0x3e,0x16,0xb7,0x74,0x77,
+ 0x07,0xbd,0x74,0x77,0x07,0xbd,0x74,0x77,0x07,0xad,0x74,0x77,0x07,0xa3,0x02,0x60,
+ 0x25,0x12,0x6f,0x12,0xa1,0x61,0x19,0xf0,0x57,0x12,0x57,0x1c,0x46,0x12,0x76,0x1c,
+ 0x26,0xaa,0xf7,0x1c,0x27,0xba,0x36,0xaa,0x37,0xba,0x26,0xa7,0x36,0xaa,0xf1,0x11,
+ 0x17,0x03,0xf9,0x11,0xa7,0x1c,0x77,0x1c,0xe7,0x1c,0x07,0xc7,0x72,0x0c,0x03,0xe0,
+ 0x26,0xad,0x36,0xa3,0x72,0x12,0x05,0x20,0x65,0x01,0x04,0xa6,0x14,0xa7,0x87,0x3c,
+ 0x67,0x1e,0x75,0x0c,0xe1,0xef,0x87,0x2c,0x27,0x16,0x5d,0x76,0x06,0xb7,0x82,0x3e,
+ 0x5d,0x76,0x06,0xb2,0x5d,0x76,0x06,0xbd,0x5d,0x76,0x06,0xb3,0x42,0x01,0x82,0x3c,
+ 0x72,0x1e,0x5b,0x77,0x07,0x8e,0x5b,0x77,0xe7,0x1c,0x07,0xa7,0xf1,0x11,0x72,0x03,
+ 0xf9,0x11,0x43,0x66,0x41,0x7f,0x2c,0x0c,0x58,0x77,0x06,0xe0,0x62,0x01,0x07,0xb2,
+ 0x82,0x3e,0x56,0x77,0x07,0xb2,0x04,0xf0,0x07,0xbb,0x54,0x77,0x06,0x60,0x07,0xb6,
+ 0x3e,0x76,0x17,0x60,0x96,0xb7,0x52,0x77,0xe7,0x1c,0x07,0xa5,0x52,0x77,0x7e,0x1c,
+ 0x0e,0xa7,0x87,0x3c,0x57,0x1e,0x07,0x3d,0x07,0x3b,0xe7,0x01,0x67,0x01,0x0e,0x60,
+ 0xa6,0xb7,0x87,0x3e,0xb6,0xb7,0x3f,0x7f,0x40,0x74,0x04,0xa6,0x14,0xa7,0x87,0x3c,
+ 0x67,0x1e,0x49,0x76,0x06,0xb7,0x87,0x3e,0x49,0x76,0x06,0xb7,0x49,0x77,0x07,0xbe,
+ 0x49,0x77,0x07,0xbe,0xe6,0x12,0x39,0x7d,0x35,0x72,0xa3,0x61,0x1b,0xf0,0x65,0x12,
+ 0x65,0x1c,0x45,0x1c,0x25,0xaf,0x07,0x67,0x67,0x1c,0x77,0x1c,0xd7,0x1c,0x27,0xbf,
+ 0x35,0xaf,0x37,0xbf,0x25,0xa7,0x35,0xa5,0xf1,0x11,0x37,0x03,0xf9,0x11,0x57,0x1c,
+ 0x77,0x1c,0x27,0x1c,0x07,0xc7,0x77,0x01,0xe7,0x01,0x67,0x01,0x7e,0x0c,0x7e,0x0a,
+ 0x06,0x20,0x66,0x01,0x04,0xa5,0x14,0xa7,0x87,0x3c,0x57,0x1e,0x76,0x0c,0xdf,0xef,
+ 0x34,0x77,0x07,0xbe,0x8e,0x3e,0x33,0x77,0x07,0xbe,0x6a,0x00,0x70,0x21,0xcf,0x00,
+ 0x08,0x00,0x04,0x00,0x30,0x0a,0x04,0x00,0x00,0x0a,0x04,0x00,0x01,0x0a,0x04,0x00,
+ 0x24,0x0a,0x04,0x00,0x28,0x0a,0x04,0x00,0x20,0x0a,0x04,0x00,0x2c,0x0a,0x04,0x00,
+ 0x02,0x0a,0x04,0x00,0x3c,0x0a,0x04,0x00,0xd2,0x84,0x00,0x00,0x80,0xc3,0xc9,0x01,
+ 0x34,0x85,0x00,0x00,0x50,0x08,0x04,0x00,0x52,0x08,0x04,0x00,0x6c,0x08,0x04,0x00,
+ 0x6e,0x08,0x04,0x00,0xa0,0x25,0x26,0x00,0xd0,0x83,0x00,0x00,0x9a,0x08,0x04,0x00,
+ 0x9e,0x08,0x04,0x00,0x96,0x08,0x04,0x00,0x7a,0x9e,0x00,0x00,0x47,0x0a,0x04,0x00,
+ 0x00,0xe0,0x02,0x00,0x36,0x50,0x00,0x00,0x00,0x00,0x03,0x00,0x36,0x60,0x00,0x00,
+ 0x40,0x0a,0x04,0x00,0x48,0x0a,0x04,0x00,0x50,0x0a,0x04,0x00,0x00,0xe0,0x02,0x00,
+ 0x86,0x9e,0x00,0x00,0x88,0x27,0x00,0x00,0x00,0x08,0x03,0x00,0x8a,0x9e,0x00,0x00,
+ 0x3e,0xa4,0x00,0x00,0x3f,0xa4,0x00,0x00,0x40,0xa4,0x00,0x00,0x41,0xa4,0x00,0x00,
+ 0x1c,0x9e,0x00,0x00,0xc0,0x00,0x00,0x00,0x44,0xa4,0x00,0x00,0x45,0xa4,0x00,0x00,
+ 0xb5,0x00,0x00,0x00,0xb6,0x00,0x00,0x00,0x6a,0x9f,0x00,0x00,0x6b,0x9f,0x00,0x00,
+ 0x42,0xa4,0x00,0x00,0x43,0xa4,0x00,0x00,0xf0,0x25,0x78,0x00,0x81,0x62,0x10,0x05,
+ 0x29,0x12,0x3c,0x12,0x58,0x12,0x58,0x1c,0x4d,0x12,0x0b,0x60,0xa0,0xf0,0x02,0x12,
+ 0x03,0x60,0x04,0x61,0x52,0x7f,0x06,0x12,0xf6,0x20,0x07,0x60,0x73,0x12,0x04,0x61,
+ 0x1e,0xf0,0x75,0x12,0x75,0x1c,0xd5,0x1c,0x05,0xc5,0x75,0x01,0x4d,0x72,0x52,0x0d,
+ 0x02,0xe8,0x06,0xb4,0x0c,0xf0,0x4b,0x72,0x25,0x0d,0x02,0xe8,0x06,0xb3,0x07,0xf0,
+ 0xf5,0x37,0x02,0xe8,0xf2,0x63,0x25,0x1c,0x65,0x3a,0x75,0x20,0x06,0xb5,0x06,0xa5,
+ 0x55,0x01,0x05,0x1c,0x05,0xa2,0x02,0x20,0x05,0xb2,0x07,0x20,0x06,0x20,0x07,0x01,
+ 0xc1,0x0c,0xdf,0xef,0x07,0x60,0x76,0x12,0x75,0x12,0x07,0x01,0x04,0x12,0x74,0x1c,
+ 0x04,0xa4,0x45,0x0c,0x16,0x0a,0x45,0x0a,0x07,0x20,0x07,0x2b,0xf6,0xe7,0x07,0x60,
+ 0x7a,0x12,0x75,0x12,0x07,0x01,0x04,0x12,0x74,0x1c,0x04,0xa4,0x45,0x0c,0x03,0xe0,
+ 0x61,0x0f,0x1a,0x02,0x45,0x02,0x07,0x20,0x07,0x2b,0xf4,0xe7,0x07,0x60,0x72,0x12,
+ 0x73,0x12,0x10,0xf0,0x05,0x61,0x05,0x1c,0x75,0x1c,0x05,0xa5,0x55,0x01,0x65,0x0f,
+ 0x08,0xe0,0x75,0x12,0x75,0x1c,0xd5,0x1c,0x05,0xc5,0x75,0x01,0x52,0x1c,0x03,0x20,
+ 0x43,0x01,0x07,0x20,0x07,0x01,0xc1,0x0c,0xed,0xef,0x03,0x2a,0x03,0xe8,0x26,0x7f,
+ 0x2e,0x12,0x01,0xf0,0x3e,0x12,0x25,0x76,0x06,0x87,0x62,0x67,0x27,0x1c,0x07,0xa6,
+ 0x07,0x60,0x72,0x12,0x73,0x12,0xe6,0x0d,0x11,0xe0,0x18,0xf0,0x06,0x61,0x06,0x1c,
+ 0x76,0x1c,0x06,0xa6,0x56,0x01,0xa6,0x0f,0x08,0xe0,0x76,0x12,0x76,0x1c,0xd6,0x1c,
+ 0x06,0xc6,0x76,0x01,0x62,0x1c,0x03,0x20,0x43,0x01,0x07,0x20,0x07,0x01,0xc1,0x0c,
+ 0xed,0xef,0x03,0x2a,0x03,0xe8,0x14,0x7f,0x2e,0x0d,0x2e,0x0a,0xd7,0x12,0x06,0x60,
+ 0x63,0x12,0x10,0xf0,0x07,0xc5,0x54,0x12,0x74,0x01,0xf4,0x37,0x02,0xe0,0x4e,0x0d,
+ 0x01,0xf0,0xe4,0x0d,0x03,0xe8,0xe5,0x05,0x07,0xd5,0x01,0xf0,0x07,0xd3,0x06,0x20,
+ 0x46,0x01,0x17,0x20,0xc6,0x0f,0xee,0xe7,0x0b,0x20,0x4b,0x01,0x8d,0x1c,0x9b,0x0f,
+ 0x5e,0xe7,0x81,0x62,0x10,0x1c,0x68,0x00,0xf0,0x21,0xcf,0x00,0x22,0x83,0x00,0x00,
+ 0xc0,0x01,0x00,0x00,0x40,0xfe,0xff,0xff,0x3e,0x84,0x00,0x00,0x1c,0x9e,0x00,0x00,
+ 0xf0,0x25,0x79,0x00,0x2a,0x12,0x39,0x12,0x83,0x7f,0x83,0x72,0xa3,0x12,0x83,0x7f,
+ 0x0d,0x60,0x83,0x7c,0x17,0xf0,0x9e,0x12,0xf1,0x11,0xde,0x03,0xf9,0x11,0xee,0x1c,
+ 0xae,0x1c,0x0b,0x60,0x07,0xf0,0x0e,0xc3,0x1e,0x20,0x7e,0x72,0x73,0x01,0x7b,0x7f,
+ 0x0b,0x20,0x6b,0x01,0x0c,0x87,0x57,0xa7,0x7b,0x0c,0xf5,0xef,0x7b,0x72,0x77,0x7f,
+ 0x0d,0x20,0x6d,0x01,0x0c,0x87,0x47,0xa7,0x7d,0x0c,0xe5,0xef,0x69,0x00,0xf0,0x21,
+ 0xcf,0x00,0xf0,0x25,0x79,0x00,0x70,0x24,0xc6,0x60,0x74,0x77,0x07,0xb6,0x0e,0x60,
+ 0xed,0x12,0x73,0x7b,0x74,0x7a,0x74,0x79,0x6e,0x7c,0x19,0xf0,0xe6,0x12,0xe6,0x1c,
+ 0xe6,0x1c,0x46,0x3c,0x09,0xa2,0x0c,0x87,0x57,0xa3,0x70,0x77,0x67,0x1e,0x00,0x97,
+ 0xf4,0x60,0x6f,0x75,0x70,0x77,0x76,0x1e,0x07,0x60,0x6f,0x7f,0xb7,0x12,0xd7,0x1c,
+ 0x26,0x62,0x67,0x1c,0x07,0xa7,0x7e,0x1c,0x4e,0x01,0x0d,0x20,0x4d,0x01,0x0a,0xa7,
+ 0x7d,0x0c,0xe4,0xef,0x5f,0x7e,0x0e,0x87,0x47,0xa2,0x57,0xa3,0x64,0x7c,0x65,0x7d,
+ 0x00,0x9d,0x24,0x60,0xc5,0x12,0x06,0x60,0x67,0x12,0x63,0x7f,0xc6,0x60,0x63,0x77,
+ 0x07,0xb6,0x0e,0x8e,0x4e,0xa2,0x5e,0xa3,0x00,0x9c,0xe4,0x60,0xd5,0x12,0x60,0x76,
+ 0x07,0x60,0x5d,0x7f,0x4e,0xa2,0x5e,0xa3,0x00,0x9d,0x24,0x60,0xc5,0x12,0x06,0x60,
+ 0x67,0x12,0x59,0x7f,0x70,0x20,0x69,0x00,0xf0,0x21,0xcf,0x00,0xf0,0x24,0x20,0x9f,
+ 0x30,0x9e,0x4b,0x77,0x07,0x8e,0x4e,0xa2,0x5e,0xa3,0x56,0x77,0x00,0x97,0x24,0x60,
+ 0x51,0x75,0x06,0x60,0x67,0x12,0x50,0x7f,0x54,0x77,0x7e,0x1c,0x0e,0xa7,0x07,0x2a,
+ 0x13,0xe8,0x47,0x77,0x17,0xa6,0x07,0xa7,0x76,0x1c,0x07,0x60,0x50,0x73,0x50,0x74,
+ 0x09,0xf0,0x75,0x12,0x75,0x1c,0x32,0x12,0x52,0x1c,0x45,0x1c,0x05,0xc5,0x02,0xd5,
+ 0x07,0x20,0x47,0x01,0x67,0x0d,0xf5,0xe7,0x20,0x8f,0x30,0x8e,0xf0,0x20,0xcf,0x00,
+ 0x70,0x25,0x7a,0x00,0x2a,0x12,0x3c,0x12,0x0d,0x60,0xde,0x12,0x46,0x7b,0x23,0xf0,
+ 0xa7,0x12,0xe7,0x1c,0x07,0xa7,0x07,0x2a,0x1c,0xe0,0xe6,0x12,0xe6,0x1c,0xc6,0x1c,
+ 0x26,0xa5,0x87,0x65,0xd7,0x1c,0x77,0x1c,0xb7,0x1c,0x87,0xb5,0x36,0xa6,0x97,0xb6,
+ 0xed,0x0f,0x0d,0xe8,0xd2,0x12,0x32,0x3c,0xd2,0x05,0xb2,0x1c,0xe3,0x12,0x33,0x3c,
+ 0xe3,0x05,0xb3,0x1c,0xa7,0x62,0x72,0x1c,0x73,0x1c,0x74,0x60,0x37,0x7f,0x0d,0x20,
+ 0x4d,0x01,0x0e,0x20,0x4e,0x01,0x0c,0xa6,0x1c,0xa7,0x87,0x3c,0x67,0x1e,0x7e,0x0c,
+ 0xd7,0xef,0x32,0x77,0x07,0xbd,0x32,0x77,0x06,0x60,0x07,0xb6,0x6a,0x00,0x70,0x21,
+ 0xcf,0x00,0x02,0x01,0x01,0x2b,0x0e,0xe0,0x1a,0x77,0x07,0x84,0x2e,0x77,0x2e,0x75,
+ 0x46,0x12,0x76,0x1c,0x2e,0x73,0x36,0x1c,0x06,0xa6,0x07,0xb6,0x07,0x20,0x57,0x0f,
+ 0xf7,0xe7,0x13,0xf0,0xf1,0x2e,0x27,0x77,0x14,0x60,0x27,0x75,0x07,0xa6,0x06,0x2a,
+ 0x03,0xe8,0x61,0x0c,0x06,0xe0,0x01,0xf0,0x06,0x62,0x16,0x05,0x46,0x01,0x07,0xb6,
+ 0x01,0xf0,0x07,0xb4,0x07,0x20,0x57,0x0f,0xf1,0xe7,0x07,0x60,0x1f,0x76,0x06,0xb7,
+ 0x20,0x76,0x06,0xb7,0x07,0x77,0x07,0x87,0x1f,0x76,0x67,0x1c,0x07,0xa6,0x1e,0x77,
+ 0x07,0xb6,0xcf,0x00,0x8e,0x23,0x00,0x00,0xf8,0x06,0x00,0x00,0x7a,0x25,0x00,0x00,
+ 0x1c,0x9e,0x00,0x00,0x04,0x07,0x00,0x00,0x0c,0x07,0x00,0x00,0x07,0x0a,0x04,0x00,
+ 0x20,0x9e,0x00,0x00,0x41,0x9e,0x00,0x00,0x42,0x9e,0x00,0x00,0x00,0x00,0x03,0x18,
+ 0x00,0x00,0x01,0x24,0x00,0x00,0x02,0x18,0xb4,0x26,0x00,0x00,0x06,0x0a,0x04,0x00,
+ 0x00,0x00,0x07,0x18,0x36,0x00,0x04,0x1a,0xc8,0x00,0x00,0x00,0x5e,0xa5,0x00,0x00,
+ 0xec,0xa4,0x00,0x00,0x8a,0x9e,0x00,0x00,0x8c,0x82,0x00,0x00,0x40,0x9f,0x00,0x00,
+ 0x41,0x9f,0x00,0x00,0x40,0x09,0x04,0x00,0x64,0x09,0x04,0x00,0xa8,0xf7,0xfb,0xff,
+ 0x65,0x09,0x04,0x00,0xcc,0x00,0x00,0x00,0x66,0x09,0x04,0x00,0x42,0x01,0x03,0x01,
+ 0x44,0x01,0x15,0x12,0x35,0x2e,0x55,0x1c,0x27,0x12,0x37,0x3c,0x27,0x1c,0x16,0x33,
+ 0x67,0x1c,0x21,0x3e,0x17,0x1c,0x07,0xa6,0x33,0x60,0x53,0x1b,0x36,0x1f,0x54,0x1b,
+ 0x46,0x1e,0x46,0x01,0x07,0xb6,0xcf,0x00,0xf0,0x25,0x78,0x00,0xf0,0x24,0x2d,0x12,
+ 0x4d,0x01,0x12,0x33,0x83,0x2c,0x80,0x74,0x81,0x7f,0x81,0x76,0x06,0x8e,0x4e,0xa1,
+ 0x00,0x91,0x0d,0x2a,0x14,0xe0,0x7f,0x75,0x05,0xa7,0x7f,0x74,0x47,0x16,0x05,0xb7,
+ 0xde,0x12,0x6d,0x12,0x07,0xf0,0xe7,0x1c,0xe2,0x12,0x67,0xa3,0x14,0x60,0x7b,0x7f,
+ 0x0e,0x20,0x4e,0x01,0x0d,0x87,0x47,0xa6,0x6e,0x0c,0xf5,0xef,0xc8,0xf0,0x2d,0x2a,
+ 0x3f,0xe0,0x74,0x76,0x06,0xa7,0x07,0x30,0x17,0x30,0x17,0x34,0x06,0xb7,0x6e,0xa5,
+ 0x16,0x61,0x07,0x60,0x56,0x0c,0x4e,0xa5,0x07,0xe8,0x11,0xf0,0x07,0x20,0xe4,0x12,
+ 0x74,0x1c,0x54,0xa4,0x46,0x0c,0x10,0xe0,0x7c,0x12,0x4c,0x01,0x5c,0x0c,0xf6,0xef,
+ 0x0a,0xf0,0x07,0x20,0xe4,0x12,0x74,0x1c,0x54,0xa4,0x46,0x0c,0x05,0xe8,0x7c,0x12,
+ 0x4c,0x01,0x5c,0x0c,0xf6,0xef,0x0c,0x60,0x0d,0x60,0x07,0xf0,0xe7,0x12,0xd7,0x1c,
+ 0xd2,0x12,0x67,0xa3,0x14,0x60,0x61,0x7f,0x0d,0x20,0x0d,0x01,0xc1,0x0c,0xf6,0xef,
+ 0x0d,0x60,0x07,0xf0,0xe7,0x1c,0xd2,0x12,0x67,0xa3,0x14,0x60,0x5c,0x7f,0x0d,0x20,
+ 0x4d,0x01,0xd7,0x12,0xc7,0x1c,0x47,0x01,0x4e,0xa6,0x67,0x0c,0xf3,0xef,0x87,0xf0,
+ 0x1d,0x2a,0x85,0xe0,0x54,0x76,0x06,0xa7,0x07,0x30,0x17,0x30,0x07,0x34,0x06,0xb7,
+ 0x4e,0xad,0x53,0x7b,0x07,0x60,0x0b,0xb7,0x05,0x60,0x00,0x95,0x26,0x65,0xe6,0x1c,
+ 0x10,0x96,0xe9,0x12,0x44,0xf0,0x78,0x1c,0x07,0x20,0x07,0x01,0x61,0x0c,0xfb,0xef,
+ 0x6d,0x0c,0xd6,0x0a,0x30,0x96,0x00,0x8c,0x0a,0x60,0xc7,0x12,0x97,0x1c,0x20,0x97,
+ 0x1a,0xf0,0xe2,0x12,0xa2,0x1c,0x10,0x81,0x01,0xa3,0x46,0x7f,0x82,0x1c,0x02,0xa4,
+ 0x20,0x87,0xe7,0x1c,0xc2,0x12,0x67,0xa3,0x14,0x2a,0x01,0xe8,0x24,0x60,0x3f,0x7f,
+ 0x0e,0x20,0x01,0xf0,0x0e,0x60,0x0e,0x01,0x30,0x84,0x41,0x0c,0xea,0xef,0x0a,0x20,
+ 0x4a,0x01,0x0c,0x20,0x4c,0x01,0x10,0x85,0x05,0xa7,0x7a,0x0c,0xf3,0xef,0x0b,0xa6,
+ 0xd7,0x0c,0x08,0xe0,0x39,0x71,0x16,0x1c,0x24,0x62,0x46,0x1c,0x06,0xb7,0x7d,0x05,
+ 0x4d,0x01,0x06,0xf0,0x35,0x75,0x56,0x1c,0x21,0x62,0x16,0x1c,0x06,0xbd,0x0d,0x60,
+ 0x00,0x84,0x47,0x1c,0x07,0x01,0x00,0x91,0x0b,0xa7,0x07,0x20,0x0b,0xb7,0x0d,0x2a,
+ 0x04,0xe0,0x2e,0x77,0x07,0xab,0x2e,0x79,0x09,0xf0,0x10,0x84,0x04,0xa6,0x07,0x60,
+ 0x2d,0x78,0xb3,0xf7,0xd7,0x12,0xd7,0x1c,0x79,0x1c,0x0d,0x20,0x0d,0x01,0xb1,0x0c,
+ 0xf9,0xef,0x0d,0x60,0x29,0x78,0x19,0xf0,0xea,0x12,0xea,0x1c,0xca,0x1c,0xe2,0x12,
+ 0xd2,0x1c,0xb3,0x12,0x20,0x7f,0x22,0x1c,0x92,0x1c,0x02,0xc7,0x0a,0xd7,0x0e,0x20,
+ 0x07,0xf0,0x0e,0x60,0xdc,0x12,0x3c,0x3c,0xd7,0x12,0x67,0x3c,0x7c,0x1c,0x8c,0x1c,
+ 0x0e,0x01,0xb1,0x0c,0xe9,0xef,0x0d,0x20,0x4d,0x01,0xbd,0x0f,0xf2,0xe7,0x10,0x77,
+ 0x07,0x85,0x45,0xa3,0x07,0x60,0x76,0x12,0x14,0x61,0x08,0xf0,0x52,0x12,0x72,0x1c,
+ 0x62,0xa2,0x24,0x0c,0x02,0xe8,0x06,0x20,0x46,0x01,0x07,0x20,0x07,0x01,0x31,0x0c,
+ 0xf5,0xef,0x12,0x77,0x07,0xb6,0x00,0x85,0x56,0x14,0x46,0x01,0x11,0x77,0x07,0xb6,
+ 0xf0,0x20,0x68,0x00,0xf0,0x21,0xcf,0x00,0x44,0x01,0x00,0x00,0xc4,0x09,0x00,0x00,
+ 0x1c,0x9e,0x00,0x00,0x54,0x08,0x04,0x00,0xfc,0x00,0x00,0x00,0x4c,0x2e,0x00,0x00,
+ 0x41,0x9e,0x00,0x00,0x74,0x84,0x00,0x00,0x20,0x9e,0x00,0x00,0x42,0x9e,0x00,0x00,
+ 0x10,0x03,0x00,0x00,0xb4,0x04,0x00,0x00,0x00,0x60,0x02,0x00,0x5a,0x08,0x04,0x00,
+ 0x5b,0x08,0x04,0x00,0x70,0x25,0x7b,0x00,0x23,0x12,0x63,0x01,0xb7,0x72,0xb7,0x7f,
+ 0x2d,0x12,0x6d,0x01,0xdc,0x12,0x0c,0x20,0x1c,0x3e,0x0e,0x60,0xb5,0x7b,0x0b,0xf0,
+ 0xe2,0x12,0x92,0x3c,0xd3,0x12,0xb1,0x7f,0xb3,0x7f,0xb2,0x14,0x42,0x01,0xb2,0x77,
+ 0xe7,0x1c,0x07,0xb2,0x0e,0x20,0xe7,0x12,0x67,0x01,0xc7,0x0c,0xf1,0xef,0x6b,0x00,
+ 0x70,0x21,0xcf,0x00,0x70,0x24,0x7e,0x00,0xad,0x7e,0xe2,0x12,0x03,0x60,0x44,0x61,
+ 0xac,0x7f,0x07,0x60,0x0e,0xb7,0x2e,0xb7,0x3e,0xb7,0xfe,0xb7,0xae,0xb7,0x07,0x2c,
+ 0xbe,0xb7,0xf7,0x67,0xce,0xb7,0x6e,0x00,0x70,0x20,0xcf,0x00,0x70,0x24,0x00,0x9f,
+ 0xa5,0x77,0x07,0xa7,0xa5,0x76,0x06,0x85,0xa5,0x76,0x65,0x0f,0x0a,0xe0,0x74,0x12,
+ 0x74,0x1c,0x74,0x1c,0xa3,0x72,0xa3,0x73,0x44,0x3c,0x15,0x60,0xa3,0x7f,0x16,0x60,
+ 0x01,0xf0,0x06,0x60,0x9a,0x77,0x27,0xb6,0x00,0x8f,0x70,0x20,0xcf,0x00,0x70,0x24,
+ 0x00,0x9f,0x06,0x60,0x9e,0x77,0x07,0xb6,0x9e,0x76,0x06,0x87,0x9e,0x75,0x57,0x16,
+ 0x06,0x97,0x9d,0x76,0x06,0x87,0xd7,0x30,0x06,0x97,0x9c,0x76,0x06,0x87,0xe7,0x31,
+ 0xf7,0x31,0x06,0x97,0xa2,0x60,0x9a,0x7f,0x00,0x8f,0x70,0x20,0xcf,0x00,0xf0,0x25,
+ 0x78,0x00,0xf0,0x24,0x98,0x7e,0x0e,0x92,0x98,0x77,0x00,0x97,0x42,0x62,0x83,0x61,
+ 0x94,0x60,0x05,0x60,0x56,0x12,0x57,0x12,0x95,0x7f,0x95,0x77,0x00,0x97,0x42,0x62,
+ 0x83,0x61,0x94,0x60,0x05,0x60,0x56,0x12,0x57,0x12,0x90,0x7f,0x92,0x77,0x00,0x97,
+ 0x42,0x62,0xa3,0x61,0x94,0x60,0x05,0x60,0x56,0x12,0x57,0x12,0x8c,0x7f,0x8e,0x77,
+ 0x00,0x97,0x42,0x62,0xa3,0x61,0x94,0x60,0x05,0x60,0x56,0x12,0x57,0x12,0x87,0x7f,
+ 0x8b,0x77,0x00,0x97,0x42,0x62,0xa3,0x61,0x94,0x60,0x05,0x60,0x56,0x12,0x57,0x12,
+ 0x83,0x7f,0x87,0x77,0x00,0x97,0x42,0x62,0x23,0x12,0x94,0x60,0x05,0x60,0x56,0x12,
+ 0x57,0x12,0x7e,0x7f,0x70,0x7d,0xd2,0x12,0x03,0x60,0x64,0x64,0x6d,0x7f,0x0e,0x8e,
+ 0x27,0x64,0xe7,0x1c,0x07,0xa7,0x07,0x2a,0x05,0xe0,0x4e,0xa7,0x0d,0xb7,0x5e,0xa7,
+ 0x1d,0xb7,0x99,0xf0,0x36,0x64,0xe6,0x1c,0x06,0xa4,0x14,0x2a,0x4e,0xa5,0x5e,0xa6,
+ 0x19,0xe0,0x54,0x12,0x04,0x24,0x0d,0xb4,0x64,0x12,0x74,0x05,0x1d,0xb4,0x03,0x60,
+ 0x34,0x12,0x72,0x12,0xd2,0x1c,0x09,0xf0,0x4c,0x12,0xdc,0x1c,0x2c,0xb5,0x2c,0x12,
+ 0x3c,0x1c,0x6c,0xb6,0x04,0x20,0x06,0x24,0x46,0x01,0x03,0x24,0x04,0x01,0x71,0x0c,
+ 0xf3,0xef,0x79,0xf0,0x24,0x2a,0x19,0xe0,0x54,0x12,0x74,0x05,0x0d,0xb4,0x64,0x12,
+ 0x04,0x24,0x1d,0xb4,0x03,0x60,0x34,0x12,0x72,0x12,0xd2,0x1c,0x09,0xf0,0x4c,0x12,
+ 0xdc,0x1c,0x6c,0xb6,0x2c,0x12,0x3c,0x1c,0x2c,0xb5,0x04,0x20,0x05,0x24,0x45,0x01,
+ 0x03,0x24,0x04,0x01,0x71,0x0c,0xf3,0xef,0x5e,0xf0,0x34,0x2a,0x25,0xe0,0x54,0x12,
+ 0x04,0x24,0x0d,0xb4,0x1d,0xb6,0x5b,0x73,0x04,0x60,0x1a,0xf0,0x32,0x12,0x32,0x24,
+ 0x02,0xb5,0x02,0x60,0xed,0x12,0x4d,0x1c,0x48,0x64,0x8d,0x1c,0x0c,0xf0,0x02,0x20,
+ 0xec,0x12,0x2c,0x1c,0x9b,0x62,0xbc,0x1c,0x0d,0xab,0x0c,0xac,0xcb,0x0f,0x03,0xe0,
+ 0x01,0x20,0x03,0xb1,0x03,0xf0,0x02,0x01,0x61,0x0c,0xf1,0xef,0x04,0x20,0x03,0x20,
+ 0x04,0x01,0x71,0x0c,0xe3,0xef,0x37,0xf0,0x44,0x2a,0x21,0xe0,0x0d,0xb5,0x64,0x12,
+ 0x04,0x24,0x1d,0xb4,0x49,0x73,0x04,0x60,0x16,0xf0,0x43,0xb6,0x02,0x60,0xed,0x12,
+ 0x4d,0x1c,0x4f,0x64,0xfd,0x1c,0x0a,0xf0,0x02,0x20,0xec,0x12,0x2c,0x1c,0x0d,0xab,
+ 0x5c,0xac,0xcb,0x0f,0x03,0xe0,0x01,0x20,0x03,0xb1,0x03,0xf0,0x02,0x01,0x51,0x0c,
+ 0xf3,0xef,0x04,0x20,0x03,0x20,0x04,0x01,0x71,0x0c,0xe7,0xef,0x14,0xf0,0x54,0x12,
+ 0x74,0x05,0x0d,0xb4,0x64,0x12,0x74,0x05,0x1d,0xb4,0x7d,0x1c,0x0d,0x20,0x04,0x60,
+ 0x53,0x12,0x43,0x05,0x0d,0xb3,0x63,0x12,0x43,0x05,0x4d,0xb3,0x04,0x20,0x44,0x01,
+ 0x0d,0x24,0x74,0x0f,0xf5,0xe7,0x1b,0x77,0x17,0xad,0x8d,0x3c,0x86,0x2c,0xd6,0x16,
+ 0xa7,0xb6,0xd6,0x12,0x86,0x3e,0xb7,0xb6,0x2d,0x76,0xe6,0x1c,0x06,0xa6,0x26,0x2a,
+ 0x07,0xa6,0x96,0x00,0x86,0x3c,0x66,0x01,0x85,0x2c,0x65,0x16,0xc7,0xb5,0x86,0x3e,
+ 0xd7,0xb6,0x27,0x77,0xe7,0x1c,0x07,0xa9,0x27,0x77,0xe7,0x1c,0x07,0xa8,0x98,0x1c,
+ 0x26,0x72,0x28,0x1c,0x26,0x77,0xe7,0x1c,0x07,0xa7,0x20,0x97,0x0a,0x7a,0xca,0xa7,
+ 0xda,0xac,0x8c,0x3c,0x7c,0x1e,0x44,0xf0,0xa0,0x25,0x26,0x00,0xd0,0x83,0x00,0x00,
+ 0xfe,0xff,0xff,0xff,0xa0,0x0b,0x00,0x00,0x00,0x80,0x01,0x00,0x66,0x9e,0x00,0x00,
+ 0xc4,0x09,0x00,0x00,0x20,0x9e,0x00,0x00,0x00,0xb0,0x10,0x00,0xaa,0xa5,0x55,0x5a,
+ 0x00,0x00,0x03,0x00,0x00,0xa0,0x00,0x00,0xf6,0x1e,0x00,0x00,0x40,0x01,0x04,0x00,
+ 0x0c,0x01,0x04,0x00,0xff,0xff,0xf0,0xff,0x04,0x01,0x04,0x00,0x08,0x01,0x04,0x00,
+ 0xe0,0x0a,0x00,0x00,0x1c,0x9e,0x00,0x00,0x00,0x00,0x02,0x18,0xb4,0x26,0x00,0x00,
+ 0x00,0x00,0x03,0x18,0x00,0x00,0x04,0x1a,0x00,0x00,0x05,0x1a,0x00,0x00,0x06,0x1a,
+ 0x00,0x00,0x01,0x24,0x26,0x9e,0x00,0x00,0x22,0x9e,0x00,0x00,0x20,0x01,0x00,0x00,
+ 0x95,0x00,0x00,0x00,0x96,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0x97,0x00,0x00,0x00,
+ 0x27,0x12,0xc7,0x1c,0x20,0x8b,0xb7,0x1c,0xca,0x76,0xe6,0x1c,0x06,0xa6,0x67,0x1c,
+ 0x67,0x01,0x30,0x97,0x7f,0x32,0xf9,0x1c,0x0e,0xa7,0x1e,0xab,0x8b,0x3c,0x7b,0x1e,
+ 0xd8,0x1c,0x68,0x01,0x92,0x12,0xf1,0x11,0xb2,0x03,0xf9,0x11,0x83,0x12,0xc1,0x7f,
+ 0x62,0x01,0xea,0xb2,0x82,0x3e,0xfa,0xb2,0x92,0x12,0xd2,0x1c,0xbf,0x73,0x32,0x1c,
+ 0xf1,0x11,0xb2,0x03,0xf9,0x11,0x83,0x12,0xbb,0x7f,0x62,0x01,0xbc,0x77,0x07,0xb2,
+ 0x82,0x3e,0xbb,0x77,0x07,0xb2,0x20,0x8a,0x74,0x32,0x4a,0x1c,0x2e,0xa7,0x3e,0xab,
+ 0x8b,0x3c,0x7b,0x1e,0xa2,0x12,0xf1,0x11,0xb2,0x03,0xf9,0x11,0x30,0x83,0xb1,0x7f,
+ 0x62,0x01,0xb4,0x77,0x07,0xb2,0x82,0x3e,0xb4,0x77,0x07,0xb2,0xa2,0x12,0xc2,0x1c,
+ 0xae,0x75,0x52,0x1c,0xf1,0x11,0xb2,0x03,0xf9,0x11,0x30,0x83,0xaa,0x7f,0x62,0x01,
+ 0xaf,0x77,0x07,0xb2,0x82,0x3e,0xae,0x77,0x07,0xb2,0xae,0x77,0xe7,0x1c,0x07,0xa6,
+ 0xae,0x77,0xe7,0x1c,0x07,0xa7,0x87,0x3c,0x67,0x1e,0x85,0x2c,0x75,0x16,0xab,0x76,
+ 0x06,0xb5,0x76,0x12,0x86,0x3e,0xaa,0x74,0x04,0xb6,0xaa,0x74,0x04,0xb5,0xaa,0x75,
+ 0x05,0xb6,0x7d,0x05,0x6d,0x01,0xa9,0x76,0x06,0xbd,0x8d,0x3e,0xa9,0x76,0x06,0xbd,
+ 0xc7,0x14,0x67,0x01,0xa8,0x76,0x06,0xb7,0x87,0x3e,0xa7,0x76,0x06,0xb7,0xa7,0x77,
+ 0x66,0x67,0xe6,0x1c,0x06,0xa6,0x07,0xb6,0x56,0x67,0xe6,0x1c,0x06,0xa6,0x17,0xb6,
+ 0x46,0x67,0xe6,0x1c,0x06,0xa6,0x27,0xb6,0x06,0x60,0x37,0xb6,0xb7,0x64,0xe7,0x1c,
+ 0x07,0xa7,0x27,0x2a,0xcd,0x64,0xed,0x1c,0xdc,0x64,0xec,0x1c,0x0d,0xa3,0x0c,0xa6,
+ 0x86,0x3c,0xe7,0x64,0xe7,0x1c,0x07,0xa4,0xf7,0x64,0xe7,0x1c,0x07,0xa7,0x87,0x3c,
+ 0x10,0xe0,0x02,0x60,0x63,0x1e,0x74,0x1e,0x96,0x7f,0x0d,0xa3,0x0c,0xa6,0x86,0x3c,
+ 0x07,0x65,0xe7,0x1c,0x07,0xa4,0x17,0x65,0xe7,0x1c,0x07,0xa7,0x87,0x3c,0x12,0x60,
+ 0x01,0xf0,0x22,0x60,0x63,0x1e,0x74,0x1e,0x8e,0x7f,0xc7,0x64,0xe7,0x1c,0x07,0xa3,
+ 0xd7,0x64,0xe7,0x1c,0x07,0xa7,0x87,0x3c,0x02,0x60,0x73,0x1e,0x8a,0x7f,0xb7,0x64,
+ 0x7e,0x1c,0x0e,0xa2,0x89,0x7f,0x89,0x77,0xc6,0x60,0x07,0xb6,0x07,0xb6,0x88,0x72,
+ 0xf3,0x63,0x84,0x61,0x88,0x7f,0x88,0x77,0x07,0x83,0x07,0x60,0x75,0x12,0x76,0x12,
+ 0x18,0xf0,0x34,0x12,0x64,0x1c,0xa8,0x62,0x84,0x1c,0x04,0xa2,0x14,0x60,0x42,0x0e,
+ 0x12,0x3e,0x64,0x12,0x54,0x34,0x05,0xe8,0x05,0x20,0x45,0x01,0x80,0x7b,0xb2,0x1c,
+ 0x04,0xf0,0x07,0x20,0x47,0x01,0x7a,0x7d,0xd2,0x1c,0x44,0x01,0x02,0xb4,0x06,0x20,
+ 0x66,0x01,0x53,0xa4,0x46,0x0c,0xe5,0xef,0x7a,0x76,0x06,0xb7,0x7a,0x77,0x07,0xb5,
+ 0x86,0x60,0x79,0x77,0x07,0x96,0x74,0x77,0x07,0x87,0x36,0x65,0x76,0x1c,0x06,0xa6,
+ 0x06,0x2a,0x09,0xe0,0x76,0x77,0x07,0xa6,0x76,0x7e,0xe6,0x16,0x07,0xb6,0x07,0xa6,
+ 0x75,0x72,0x26,0x16,0x0f,0xf0,0xc6,0x64,0x76,0x1c,0x06,0xa2,0xd3,0x64,0x37,0x1c,
+ 0x07,0xa7,0x87,0x3c,0x72,0x1e,0x70,0x7f,0x6d,0x77,0x07,0xa6,0x06,0x34,0x07,0xb6,
+ 0x07,0xa6,0x46,0x34,0x07,0xb6,0x69,0x76,0x06,0xa7,0x17,0x34,0x06,0xb7,0x6b,0x75,
+ 0x05,0xa7,0x6b,0x74,0x47,0x16,0x60,0x76,0x06,0x86,0xb4,0x66,0x64,0x1c,0x04,0xa4,
+ 0x47,0x1e,0x05,0xb7,0x68,0x75,0x05,0xa7,0x07,0x34,0x05,0xb7,0x15,0x60,0x66,0x77,
+ 0x07,0xb5,0x05,0x60,0x66,0x77,0x07,0xb5,0x05,0x60,0x65,0x77,0x07,0xd5,0x85,0x32,
+ 0x65,0x77,0x07,0xd5,0x65,0x75,0x65,0x77,0x07,0xd5,0x05,0x62,0x65,0x77,0x07,0xb5,
+ 0x07,0x60,0x12,0xf0,0x64,0x12,0x74,0x1c,0xa3,0x62,0x43,0x1c,0x03,0xa5,0x61,0x78,
+ 0x85,0x1c,0x61,0x7b,0xb4,0x1c,0x04,0xa2,0x05,0xb2,0x03,0xa5,0x60,0x7d,0xd5,0x1c,
+ 0x04,0xa4,0x05,0xb4,0x07,0x20,0x67,0x01,0x56,0xa5,0x57,0x0c,0xeb,0xef,0x5c,0x72,
+ 0x03,0x60,0x44,0x62,0x44,0x7f,0x44,0x77,0x07,0x87,0xbe,0x64,0xe7,0x1c,0x07,0xa7,
+ 0x17,0x2a,0x46,0x77,0x07,0xa6,0x02,0xe8,0x26,0x34,0x02,0xf0,0x56,0x72,0x26,0x16,
+ 0x07,0xb6,0x3d,0x7e,0x0e,0x87,0xf3,0x66,0x37,0x1c,0x07,0xa3,0x53,0x72,0x83,0x3c,
+ 0x53,0x74,0x53,0x7f,0x0e,0x87,0x04,0x67,0x47,0x1c,0x07,0xa7,0x73,0x12,0x43,0x3c,
+ 0x73,0x1e,0x50,0x72,0x43,0x01,0x50,0x74,0x33,0x7f,0x0e,0x87,0x50,0x75,0x57,0x1c,
+ 0x07,0xa7,0x73,0x12,0x43,0x3c,0x73,0x1e,0x4e,0x72,0x43,0x01,0x54,0x62,0x2d,0x7f,
+ 0x0e,0x87,0x4c,0x76,0x76,0x1c,0x06,0xa6,0x06,0x2a,0xd2,0xe8,0xe6,0x64,0x76,0x1c,
+ 0x06,0xa6,0xf5,0x64,0x75,0x1c,0x05,0xa2,0x82,0x3c,0x62,0x1e,0xc6,0x64,0x76,0x1c,
+ 0x06,0xa5,0xd6,0x64,0x76,0x1c,0x06,0xa6,0x86,0x3c,0x56,0x1e,0x43,0x78,0x87,0x1c,
+ 0xf1,0x11,0x62,0x03,0xf9,0x11,0x07,0xa3,0x07,0x7f,0x23,0x12,0x63,0x01,0x12,0x60,
+ 0x19,0x7f,0x15,0x60,0x3e,0x77,0x07,0xb5,0x0e,0x87,0x3d,0x7b,0x7b,0xf0,0x00,0x00,
+ 0x98,0x00,0x00,0x00,0xd0,0x83,0x00,0x00,0x00,0xfe,0xff,0xff,0x30,0x9e,0x00,0x00,
+ 0x31,0x9e,0x00,0x00,0x32,0x9e,0x00,0x00,0x33,0x9e,0x00,0x00,0x34,0x9e,0x00,0x00,
+ 0x35,0x9e,0x00,0x00,0xa7,0x00,0x00,0x00,0xa8,0x00,0x00,0x00,0x36,0x9e,0x00,0x00,
+ 0x37,0x9e,0x00,0x00,0x38,0x9e,0x00,0x00,0x39,0x9e,0x00,0x00,0x3a,0x9e,0x00,0x00,
+ 0x3b,0x9e,0x00,0x00,0x3c,0x9e,0x00,0x00,0x3d,0x9e,0x00,0x00,0x86,0x9e,0x00,0x00,
+ 0x0c,0x27,0x00,0x00,0x5a,0x27,0x00,0x00,0x78,0x2e,0x00,0x00,0x62,0x08,0x04,0x00,
+ 0x00,0x08,0x04,0x00,0xc4,0x09,0x00,0x00,0x1c,0x9e,0x00,0x00,0x0c,0x08,0x04,0x00,
+ 0x58,0x08,0x04,0x00,0x59,0x08,0x04,0x00,0x2c,0x08,0x04,0x00,0x40,0x08,0x04,0x00,
+ 0xfe,0x00,0x00,0x00,0xef,0x00,0x00,0x00,0xc4,0x30,0x00,0x00,0x41,0x08,0x04,0x00,
+ 0xf8,0xff,0xff,0xff,0x68,0x08,0x04,0x00,0x69,0x08,0x04,0x00,0x84,0x08,0x04,0x00,
+ 0x8c,0x08,0x04,0x00,0x8e,0x08,0x04,0x00,0x96,0x00,0x00,0x00,0x90,0x08,0x04,0x00,
+ 0x98,0x08,0x04,0x00,0xd0,0x08,0x04,0x00,0xd0,0x00,0x00,0x00,0xe8,0x08,0x04,0x00,
+ 0x14,0x09,0x04,0x00,0xfb,0x00,0x00,0x00,0x00,0x40,0x02,0x00,0x60,0x03,0x00,0x00,
+ 0xd8,0x09,0x00,0x00,0x00,0x20,0x02,0x00,0xbc,0x01,0x00,0x00,0xcb,0x00,0x00,0x00,
+ 0xbc,0x21,0x02,0x00,0xc8,0x00,0x00,0x00,0xca,0x00,0x00,0x00,0x9c,0x08,0x04,0x00,
+ 0xc9,0x00,0x00,0x00,0xb7,0x1c,0x07,0xa6,0x06,0x2a,0x96,0x77,0x06,0xe0,0x07,0x85,
+ 0x35,0x31,0x07,0x95,0x95,0x77,0x07,0xb6,0x0a,0xf0,0x16,0x2a,0x07,0x86,0x03,0xe0,
+ 0x36,0x35,0x07,0x96,0x04,0xf0,0x36,0x31,0x07,0x96,0x8f,0x77,0x07,0xb5,0x8f,0x76,
+ 0x06,0xa7,0x57,0x34,0x06,0xb7,0x8e,0x75,0x05,0xa6,0x8e,0x77,0x07,0x87,0xbd,0x66,
+ 0xd7,0x1c,0x07,0xa7,0x47,0x3c,0x8c,0x7e,0xe6,0x16,0x67,0x1e,0x47,0x01,0x05,0xb7,
+ 0x86,0x2d,0x8a,0x77,0x07,0x96,0x06,0x2c,0x8a,0x77,0x07,0x96,0x06,0x60,0x89,0x77,
+ 0x07,0xb6,0xf6,0x61,0x89,0x77,0x07,0xb6,0x89,0x76,0x06,0xa7,0x17,0x34,0x04,0xf0,
+ 0x87,0x76,0x06,0xa7,0x87,0x72,0x27,0x16,0x06,0xb7,0x86,0x7f,0x02,0x61,0x86,0x7f,
+ 0x02,0x60,0x86,0x77,0x07,0xb2,0x86,0x77,0x07,0x84,0x7a,0x73,0x03,0x85,0x16,0x67,
+ 0x56,0x1c,0x06,0xa6,0x66,0x3d,0x64,0x31,0x74,0x31,0x46,0x1e,0x07,0x96,0x07,0x84,
+ 0xe6,0x66,0x56,0x1c,0x06,0xa6,0x16,0x3d,0x14,0x31,0x24,0x31,0x46,0x1e,0x07,0x96,
+ 0x07,0x84,0xd6,0x66,0x56,0x1c,0x06,0xa6,0x06,0x3d,0x04,0x31,0x46,0x1e,0x07,0x96,
+ 0x79,0x74,0x04,0x86,0xc7,0x66,0x75,0x1c,0x05,0xa7,0xd7,0x3c,0xd6,0x30,0xe6,0x30,
+ 0x67,0x1e,0x04,0x97,0x75,0x75,0x05,0xb2,0x07,0x60,0xf2,0x61,0x34,0x60,0x0f,0xf0,
+ 0x76,0x1c,0x66,0xa6,0x62,0x0c,0x09,0xe0,0x05,0xae,0xf6,0x25,0x06,0x30,0x48,0x12,
+ 0x68,0x1b,0x86,0x12,0xe6,0x1e,0x46,0x01,0x05,0xb6,0x07,0x20,0x47,0x01,0x03,0x86,
+ 0x46,0xae,0xe7,0x0c,0xed,0xef,0x69,0x72,0x03,0x60,0x69,0x74,0x6a,0x7f,0x07,0x60,
+ 0x6a,0x76,0x06,0xb7,0x15,0x60,0x69,0x76,0x06,0xb5,0x69,0x76,0x06,0xb7,0x63,0x73,
+ 0x3e,0x12,0x06,0x60,0x62,0x12,0x3a,0x12,0x6b,0x64,0x0c,0x2c,0xfd,0x67,0x1b,0xf0,
+ 0xe7,0x12,0x47,0x1c,0x64,0x78,0x87,0x1c,0x07,0xb2,0x57,0x12,0x37,0x3c,0x57,0x05,
+ 0x97,0x1c,0xa7,0x1c,0x61,0x78,0x87,0x1c,0x37,0xbc,0x47,0xbd,0x57,0xbc,0x67,0xbd,
+ 0x77,0xb2,0x87,0xb2,0x05,0x20,0x64,0x20,0xa5,0x2a,0xea,0xe7,0x06,0x20,0x6f,0x64,
+ 0xfe,0x1c,0x46,0x2a,0x24,0xe8,0x04,0x60,0x45,0x12,0x69,0x12,0xf1,0x11,0xb9,0x03,
+ 0xf9,0x11,0xde,0xf7,0x47,0x12,0x37,0x3c,0x37,0x1c,0x54,0x78,0x87,0x1c,0x0d,0x60,
+ 0x07,0xb5,0x27,0x12,0x47,0x1c,0x52,0x7b,0xb7,0x1c,0x37,0x3c,0xe7,0x1c,0x0b,0x60,
+ 0x37,0xbc,0x47,0xb5,0x57,0xb5,0x67,0xb5,0x77,0xb5,0x87,0xb5,0x04,0x20,0xa4,0x2a,
+ 0xe9,0xe7,0x06,0x20,0x0f,0x65,0xf3,0x1c,0x46,0x2a,0x05,0xe0,0x0b,0xf0,0x06,0x60,
+ 0x6c,0x12,0x65,0x12,0x3e,0x7e,0x04,0x60,0x62,0x12,0x62,0x1c,0x67,0x12,0x37,0x3c,
+ 0x72,0x1c,0xd8,0xf7,0x44,0x72,0xb3,0x12,0x3b,0x7f,0x43,0x7e,0x44,0x77,0x0e,0xb7,
+ 0x17,0x01,0x1e,0xb1,0x27,0x01,0x2e,0xb1,0x87,0x3f,0x3e,0xb7,0x47,0x61,0x4e,0xb7,
+ 0x40,0x7c,0x0c,0xa7,0x5e,0xb7,0x1c,0xa7,0x6e,0xb7,0x9e,0xbb,0x22,0x7a,0x0a,0x87,
+ 0x42,0x67,0x27,0x1c,0x07,0xa7,0xae,0xb7,0x07,0x60,0xbe,0xb7,0x3a,0x77,0x07,0xa6,
+ 0x07,0xbd,0x17,0xa6,0x17,0xbd,0x38,0x77,0x27,0xbd,0x37,0xbd,0x07,0xbd,0x17,0xbd,
+ 0x47,0xbd,0x57,0xbd,0x36,0x7f,0x36,0x76,0x06,0x87,0x47,0x30,0x57,0x30,0x06,0x97,
+ 0x35,0x76,0x35,0x77,0x07,0xd6,0x35,0x76,0x36,0x77,0x07,0xd6,0x1c,0xa7,0x87,0x3c,
+ 0x0c,0xa6,0x67,0x1e,0x34,0x76,0x06,0xd7,0xa6,0x61,0x33,0x77,0x07,0xb6,0x33,0x77,
+ 0x07,0xbd,0x0a,0x87,0x43,0x67,0x37,0x1c,0x07,0xa6,0x31,0x77,0x07,0xd6,0x4e,0xa6,
+ 0x31,0x77,0x07,0xb6,0x31,0x7f,0x31,0x77,0x07,0x9b,0xf0,0x20,0x68,0x00,0xf0,0x21,
+ 0xcf,0x00,0x00,0x00,0x08,0x01,0x04,0x00,0x9d,0x08,0x04,0x00,0x40,0x08,0x04,0x00,
+ 0x41,0x08,0x04,0x00,0x1c,0x9e,0x00,0x00,0x8f,0xff,0xff,0xff,0xa0,0x08,0x04,0x00,
+ 0xa4,0x08,0x04,0x00,0xcc,0x08,0x04,0x00,0x66,0x09,0x04,0x00,0x68,0x08,0x04,0x00,
+ 0xfd,0x00,0x00,0x00,0x5e,0x31,0x00,0x00,0x72,0x2d,0x00,0x00,0x3c,0x01,0x04,0x00,
+ 0x04,0x01,0x04,0x00,0x0c,0x01,0x04,0x00,0x48,0x01,0x04,0x00,0x8a,0x9e,0x00,0x00,
+ 0xe9,0x05,0x00,0x00,0xc4,0x09,0x00,0x00,0x63,0xa4,0x00,0x00,0x64,0xa4,0x00,0x00,
+ 0xe5,0xa3,0x00,0x00,0x02,0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x1a,0x04,0x00,0x00,
+ 0x83,0x00,0x00,0x00,0xfa,0xa3,0x00,0x00,0x7a,0x9e,0x00,0x00,0x00,0xe0,0x02,0x00,
+ 0x20,0x9e,0x00,0x00,0x00,0x08,0x03,0x00,0x73,0xa4,0x00,0x00,0x04,0x31,0x00,0x00,
+ 0x04,0x0a,0x04,0x00,0x36,0x50,0x00,0x00,0x40,0x0a,0x04,0x00,0x00,0x68,0x00,0x00,
+ 0x42,0x0a,0x04,0x00,0x44,0x0a,0x04,0x00,0x46,0x0a,0x04,0x00,0x47,0x0a,0x04,0x00,
+ 0x48,0x0a,0x04,0x00,0x4a,0x0a,0x04,0x00,0x2c,0x31,0x00,0x00,0x4c,0x06,0x04,0x00,
+ 0x16,0x60,0x82,0x77,0x07,0xb6,0x82,0x76,0x06,0x87,0x82,0x75,0x57,0x1e,0x06,0x97,
+ 0x82,0x76,0x06,0x87,0xd7,0x34,0x06,0x97,0x81,0x76,0x06,0x87,0xe7,0x35,0xf7,0x35,
+ 0x06,0x97,0xcf,0x00,0xcf,0x00,0x7e,0x72,0xcf,0x00,0xf0,0x24,0x7d,0x00,0x7d,0x77,
+ 0x07,0x83,0x7d,0x77,0x37,0x1c,0x07,0xa7,0x07,0x2a,0x32,0xe8,0x7c,0x77,0x17,0xa6,
+ 0x7c,0x74,0x05,0x60,0x7c,0x72,0x0b,0xf0,0x37,0x12,0x57,0x1c,0xaf,0x62,0xf7,0x1c,
+ 0x07,0xa7,0x77,0x1c,0x27,0x1c,0x07,0xc7,0x04,0xd7,0x05,0x20,0x14,0x20,0x05,0x01,
+ 0x61,0x0c,0xf2,0xef,0x72,0x77,0x07,0xad,0x05,0x60,0x54,0x12,0xff,0x61,0x70,0x7e,
+ 0x71,0x71,0x66,0x1c,0x11,0xf0,0x37,0x12,0x47,0x1c,0x67,0xa7,0x52,0x12,0x62,0x1c,
+ 0xe2,0x1c,0x7f,0x0c,0x02,0xe8,0x77,0x21,0x01,0xf0,0xb7,0x24,0x77,0x1c,0x17,0x1c,
+ 0x07,0xc7,0x02,0xd7,0x04,0x20,0x15,0x20,0x47,0x12,0x47,0x01,0xd7,0x0c,0xeb,0xef,
+ 0x6d,0x00,0xf0,0x20,0xcf,0x00,0x70,0x24,0x7e,0x00,0x63,0x77,0x07,0xa6,0x06,0x20,
+ 0x46,0x01,0x07,0xb6,0x62,0x77,0x07,0xa7,0x07,0x2a,0x07,0xe0,0x5a,0x77,0x07,0x87,
+ 0x85,0x67,0x75,0x1c,0x05,0xa5,0x05,0x2a,0x0d,0xe0,0x06,0x60,0x5b,0x77,0x07,0xb6,
+ 0x55,0x77,0x07,0x87,0xb6,0x64,0x67,0x1c,0x07,0xa7,0x0e,0x60,0x17,0x2a,0x12,0xe0,
+ 0x58,0x7f,0x10,0xf0,0x95,0x67,0x75,0x1c,0x05,0xa5,0x1e,0x60,0x56,0x0c,0x0a,0xe8,
+ 0xb6,0x64,0x67,0x1c,0x07,0xa7,0x17,0x2a,0x01,0xe0,0x51,0x7f,0x06,0x60,0x4e,0x77,
+ 0x07,0xb6,0x0e,0x60,0xe2,0x12,0x6e,0x00,0x70,0x20,0xcf,0x00,0xf0,0x24,0x20,0x9f,
+ 0x30,0x9e,0x44,0x77,0x07,0x8e,0x4e,0xa2,0x5e,0xa3,0x4a,0x77,0x00,0x97,0x24,0x60,
+ 0x4a,0x75,0x06,0x60,0x67,0x12,0x49,0x7f,0x40,0x77,0x7e,0x1c,0x0e,0xa7,0x07,0x2a,
+ 0x13,0xe8,0x3e,0x77,0x17,0xa6,0x07,0xa7,0x76,0x1c,0x07,0x60,0x45,0x73,0x3c,0x74,
+ 0x09,0xf0,0x75,0x12,0x75,0x1c,0x32,0x12,0x52,0x1c,0x45,0x1c,0x05,0xc5,0x02,0xd5,
+ 0x07,0x20,0x47,0x01,0x67,0x0d,0xf5,0xe7,0x20,0x8f,0x30,0x8e,0xf0,0x20,0xcf,0x00,
+ 0x70,0x24,0x00,0x9f,0x06,0x60,0x3b,0x77,0x07,0xb6,0x16,0x60,0x3b,0x77,0x07,0xb6,
+ 0xa2,0x60,0x3a,0x7f,0x00,0x8f,0x70,0x20,0xcf,0x00,0x37,0x77,0x07,0xa6,0x16,0x36,
+ 0xfd,0xef,0xcf,0x00,0xcf,0x00,0xcf,0x00,0x42,0x01,0x03,0x01,0x35,0x76,0xa7,0x61,
+ 0xf1,0x11,0x27,0x03,0xf9,0x11,0x17,0x1c,0x77,0x1c,0x76,0x1c,0x06,0xc5,0x54,0x12,
+ 0x74,0x01,0x30,0x77,0x07,0xa6,0x30,0x77,0x07,0xa7,0x87,0x3c,0x67,0x1e,0x74,0x0d,
+ 0x17,0xe0,0x2e,0x77,0x27,0xa3,0x37,0xa6,0x86,0x3c,0x36,0x1e,0x06,0x20,0x66,0x01,
+ 0x27,0xb6,0x86,0x3e,0x37,0xb6,0x47,0xa3,0x57,0xa6,0x86,0x3c,0x36,0x1e,0x46,0x0d,
+ 0x07,0xe8,0x56,0x12,0x66,0x01,0x47,0xb6,0x86,0x3e,0x57,0xb6,0x67,0xb2,0x77,0xb1,
+ 0x23,0x77,0x87,0xa6,0x62,0x0c,0x01,0xe0,0x87,0xb2,0x97,0xa7,0x71,0x0c,0x02,0xe0,
+ 0x1f,0x77,0x97,0xb1,0x1e,0x77,0xa7,0xa6,0x26,0x0c,0x01,0xe0,0xa7,0xb2,0xb7,0xa7,
+ 0x17,0x0c,0x02,0xe0,0x1a,0x77,0xb7,0xb1,0xcf,0x00,0x00,0x00,0x40,0x01,0x04,0x00,
+ 0x0c,0x01,0x04,0x00,0x00,0x00,0x0f,0x00,0x04,0x01,0x04,0x00,0x08,0x01,0x04,0x00,
+ 0x00,0x80,0x02,0x00,0x1c,0x9e,0x00,0x00,0xc8,0x00,0x00,0x00,0x20,0x9e,0x00,0x00,
+ 0xec,0xa4,0x00,0x00,0xc0,0x86,0x02,0x00,0x5c,0xa5,0x00,0x00,0x20,0xaa,0x00,0x00,
+ 0x12,0x2c,0x00,0x00,0x36,0x00,0x04,0x1a,0x00,0x00,0x02,0x18,0xb4,0x26,0x00,0x00,
+ 0x5e,0xa5,0x00,0x00,0x74,0x08,0x04,0x00,0x70,0x08,0x04,0x00,0xe0,0x0a,0x00,0x00,
+ 0x00,0xe0,0x02,0x00,0x44,0xa4,0x00,0x00,0x45,0xa4,0x00,0x00,0x73,0xa4,0x00,0x00,
+ 0x70,0x25,0x7a,0x00,0x42,0x01,0x43,0x01,0x04,0x01,0xad,0x77,0x07,0xa7,0xad,0x76,
+ 0x06,0xaf,0x8f,0x3c,0x7f,0x1e,0x86,0x2c,0x5e,0x60,0xec,0x12,0x05,0x60,0xaa,0x7a,
+ 0x1a,0xf0,0x52,0x0f,0x16,0xe8,0x87,0x65,0x57,0x1c,0x77,0x1c,0xa7,0x1c,0x87,0xad,
+ 0x3d,0x14,0x5d,0x01,0xed,0x01,0x4d,0x01,0x97,0xa7,0x17,0x14,0x57,0x01,0xe7,0x01,
+ 0x47,0x01,0x7b,0x12,0xdb,0x1c,0x4b,0x01,0x6b,0x0c,0x03,0xe0,0xb6,0x12,0x7e,0x12,
+ 0xdc,0x12,0x05,0x20,0x45,0x01,0xf5,0x0c,0xe4,0xef,0x22,0x60,0x62,0x0c,0x09,0xe8,
+ 0x02,0x60,0x26,0x2a,0x06,0xe0,0x62,0x12,0x0c,0x2a,0x03,0xe8,0x0e,0x2a,0x22,0x00,
+ 0x22,0x28,0x6a,0x00,0x70,0x21,0xcf,0x00,0xf0,0x25,0x79,0x00,0x27,0x12,0x47,0x01,
+ 0x03,0x01,0x45,0x01,0x5b,0x12,0x5b,0x1c,0x02,0x60,0x2f,0x12,0x07,0x24,0x01,0x24,
+ 0x4c,0x61,0x1b,0xf0,0xe3,0x12,0xa3,0x1c,0x33,0x1c,0x43,0x1c,0x3d,0x12,0xbd,0x1c,
+ 0x03,0xc6,0x76,0x01,0x1d,0xc9,0x79,0x01,0x96,0x1c,0x13,0xc3,0x73,0x01,0x36,0x05,
+ 0x0d,0xc3,0x73,0x01,0x36,0x05,0xe6,0x01,0x6c,0x0c,0x01,0xe0,0x62,0x1c,0x0e,0x20,
+ 0x4e,0x01,0x1e,0x0d,0xe7,0xe7,0x0f,0x20,0x4f,0x01,0x7f,0x0d,0x06,0xe8,0xfa,0x12,
+ 0xf1,0x11,0x5a,0x03,0xf9,0x11,0x0e,0x60,0xf4,0xf7,0x69,0x00,0xf0,0x21,0xcf,0x00,
+ 0xf0,0x24,0x7d,0x00,0x7a,0x77,0x07,0xa2,0x17,0xa3,0x79,0x74,0x85,0x61,0x79,0x7f,
+ 0x7a,0x7d,0x0d,0xa5,0x05,0x2a,0x79,0x77,0x7a,0x7e,0x03,0xe0,0x07,0x92,0x0e,0x92,
+ 0x2d,0xf0,0x0e,0x86,0x26,0x1c,0x0e,0x96,0x07,0x87,0x72,0x05,0xe2,0x01,0x75,0x77,
+ 0x07,0x87,0x75,0x74,0x74,0x1c,0x04,0xa4,0x75,0x73,0x37,0x1c,0x07,0xa7,0x87,0x3c,
+ 0x47,0x1e,0x27,0x0d,0x04,0xe8,0x06,0x60,0x72,0x77,0x07,0xb6,0x15,0xf0,0x87,0x60,
+ 0x57,0x0c,0x14,0xe0,0x15,0x60,0x6e,0x77,0x07,0xb5,0x62,0x12,0xa3,0x60,0x6d,0x7f,
+ 0x0e,0x92,0x6d,0x77,0x07,0xb2,0x12,0x01,0x6d,0x77,0x07,0xb1,0x22,0x01,0x6c,0x77,
+ 0x07,0xb1,0x82,0x3f,0x6c,0x77,0x07,0xb2,0x07,0x2c,0x0d,0xb7,0x5f,0x77,0x07,0xa6,
+ 0x06,0x20,0x07,0xb6,0x65,0x77,0x07,0xa6,0x65,0x77,0x07,0xa7,0x87,0x3c,0x67,0x1e,
+ 0x64,0x76,0x06,0xa6,0x06,0x3d,0x76,0x1e,0x63,0x77,0x07,0xa7,0x87,0x3d,0x67,0x1e,
+ 0x62,0x7e,0x0e,0xa5,0x62,0x74,0x04,0xa6,0x86,0x3c,0x56,0x1e,0x61,0x75,0x05,0xa2,
+ 0x02,0x3d,0x62,0x1e,0x60,0x76,0x06,0xa3,0x83,0x3d,0x23,0x1e,0x37,0x0c,0x07,0xe0,
+ 0x0e,0xb7,0x17,0x01,0x04,0xb1,0x27,0x01,0x05,0xb1,0x87,0x3f,0x06,0xb7,0x6d,0x00,
+ 0xf0,0x20,0xcf,0x00,0x70,0x24,0x7e,0x00,0x58,0x7e,0x0e,0xa7,0x17,0x2a,0x03,0xe0,
+ 0x27,0x60,0x0e,0xb7,0xff,0xf0,0x27,0x2a,0xfd,0xe0,0x54,0x7f,0x55,0x77,0x07,0xa7,
+ 0x07,0x2a,0xd0,0xe8,0xfe,0xa7,0x07,0x2a,0x20,0xe8,0x52,0x77,0x07,0xa7,0x52,0x76,
+ 0x06,0xa6,0x86,0x3c,0x76,0x1e,0x51,0x77,0x07,0xa7,0x07,0x3d,0x67,0x1e,0x50,0x76,
+ 0x06,0xa6,0x86,0x3d,0x76,0x1e,0x4f,0x77,0x07,0xa5,0x4f,0x77,0x07,0xa7,0x87,0x3c,
+ 0x57,0x1e,0x4e,0x75,0x05,0xa5,0x05,0x3d,0x75,0x1e,0x4d,0x77,0x07,0xa7,0x87,0x3d,
+ 0x57,0x1e,0x67,0x0c,0x02,0xe0,0x07,0x60,0xfe,0xb7,0x4a,0x77,0x07,0xa7,0x07,0x2a,
+ 0x3e,0x77,0x26,0xe8,0x06,0x60,0xa7,0xb6,0x34,0x76,0x06,0xa6,0x34,0x75,0x05,0xa5,
+ 0x85,0x3c,0x65,0x1e,0x33,0x76,0x06,0xa6,0x06,0x3d,0x56,0x1e,0x32,0x75,0x05,0xa5,
+ 0x85,0x3d,0x65,0x1e,0x41,0x76,0x06,0xa4,0x41,0x76,0x06,0xa6,0x86,0x3c,0x46,0x1e,
+ 0x40,0x74,0x04,0xa4,0x04,0x3d,0x64,0x1e,0x3f,0x76,0x06,0xa6,0x86,0x3d,0x46,0x1e,
+ 0x16,0x3e,0x65,0x0c,0xaf,0xe0,0x16,0x60,0x3c,0x75,0x05,0xb6,0xf7,0xb6,0xaa,0xf0,
+ 0x16,0x60,0xa7,0xb6,0xf7,0xa6,0x06,0x2a,0x1b,0x76,0x06,0x85,0x0e,0xe8,0x37,0x76,
+ 0x56,0x1c,0x06,0xa4,0x37,0x76,0x56,0x1c,0x06,0xa6,0x86,0x3c,0x46,0x1e,0xb7,0xb6,
+ 0x86,0x3e,0xc7,0xb6,0x34,0x74,0x45,0x1c,0x0d,0xf0,0x33,0x76,0x56,0x1c,0x06,0xa4,
+ 0x33,0x76,0x56,0x1c,0x06,0xa6,0x86,0x3c,0x46,0x1e,0xb7,0xb6,0x86,0x3e,0xc7,0xb6,
+ 0x30,0x76,0x65,0x1c,0x05,0xa6,0xd7,0xb6,0x06,0x60,0xe7,0xb6,0x83,0xf0,0x00,0x00,
+ 0x40,0x9f,0x00,0x00,0x41,0x9f,0x00,0x00,0x8a,0x9e,0x00,0x00,0x20,0x9e,0x00,0x00,
+ 0x00,0x80,0x02,0x00,0x58,0x3e,0x00,0x00,0xce,0xa5,0x00,0x00,0xd0,0xa5,0x00,0x00,
+ 0xd4,0xa5,0x00,0x00,0x1c,0x9e,0x00,0x00,0x1e,0x01,0x00,0x00,0x1f,0x01,0x00,0x00,
+ 0x71,0xa4,0x00,0x00,0xd0,0x83,0x00,0x00,0x6d,0xa4,0x00,0x00,0x6e,0xa4,0x00,0x00,
+ 0x6f,0xa4,0x00,0x00,0x70,0xa4,0x00,0x00,0x69,0xa4,0x00,0x00,0x6a,0xa4,0x00,0x00,
+ 0x6b,0xa4,0x00,0x00,0x6c,0xa4,0x00,0x00,0x66,0x9e,0x00,0x00,0xc0,0x3e,0x00,0x00,
+ 0x64,0xa4,0x00,0x00,0x37,0xaa,0x00,0x00,0x38,0xaa,0x00,0x00,0x39,0xaa,0x00,0x00,
+ 0x3a,0xaa,0x00,0x00,0x76,0x9e,0x00,0x00,0x77,0x9e,0x00,0x00,0x78,0x9e,0x00,0x00,
+ 0x79,0x9e,0x00,0x00,0xa5,0xa0,0x00,0x00,0x65,0xa4,0x00,0x00,0x66,0xa4,0x00,0x00,
+ 0x67,0xa4,0x00,0x00,0x68,0xa4,0x00,0x00,0x31,0xaa,0x00,0x00,0x0f,0x01,0x00,0x00,
+ 0x10,0x01,0x00,0x00,0x0e,0x01,0x00,0x00,0x0c,0x01,0x00,0x00,0x0d,0x01,0x00,0x00,
+ 0xba,0x00,0x00,0x00,0x17,0x60,0xad,0x76,0x06,0xb7,0xfe,0xb7,0xad,0x77,0x07,0xa7,
+ 0xad,0x76,0x06,0xa6,0x86,0x3c,0x76,0x1e,0xac,0x77,0x07,0xa7,0x07,0x3d,0x67,0x1e,
+ 0xab,0x76,0x06,0xa6,0x86,0x3d,0x76,0x1e,0xaa,0x77,0x07,0x87,0xaa,0x75,0x75,0x1c,
+ 0x05,0xa5,0xa9,0x74,0x47,0x1c,0x07,0xa7,0x87,0x3c,0x57,0x1e,0x67,0x1c,0xa7,0x76,
+ 0x06,0xb7,0x17,0x01,0xa7,0x76,0x06,0xb1,0x27,0x01,0xa6,0x76,0x06,0xb1,0x87,0x3f,
+ 0xa6,0x76,0x06,0xb7,0x6e,0x00,0x70,0x20,0xcf,0x00,0xa4,0x77,0x37,0xa6,0x06,0x2a,
+ 0xa4,0xe0,0xa3,0x75,0x05,0xa6,0x06,0x2a,0x40,0xe0,0xa2,0x76,0x06,0xa4,0xa2,0x76,
+ 0x06,0xa6,0x86,0x3c,0x46,0x1e,0xa1,0x74,0x04,0xa4,0x04,0x3d,0x64,0x1e,0xa0,0x76,
+ 0x06,0xa6,0x86,0x3d,0x46,0x1e,0x06,0x2a,0xbd,0xe1,0x9e,0x76,0x06,0xa4,0x9e,0x76,
+ 0x06,0xa6,0x86,0x3c,0x46,0x1e,0x9d,0x74,0x04,0xa4,0x04,0x3d,0x64,0x1e,0x9c,0x76,
+ 0x06,0xa6,0x86,0x3d,0x46,0x1e,0x06,0x2a,0x02,0xe8,0x16,0x60,0xa6,0xf0,0x17,0xa6,
+ 0x06,0x20,0x46,0x01,0x17,0xb6,0x55,0x60,0x65,0x0c,0xba,0xe1,0x16,0x60,0x17,0xb6,
+ 0xa7,0xb6,0x83,0x76,0x06,0x85,0x93,0x76,0x56,0x1c,0x06,0xa4,0x93,0x76,0x56,0x1c,
+ 0x06,0xa6,0x86,0x3c,0x46,0x1e,0xb7,0xb6,0x86,0x3e,0xc7,0xb6,0x90,0x72,0x25,0x1c,
+ 0x05,0xa6,0xd7,0xb6,0x06,0x60,0xe7,0xb6,0xa3,0xf1,0x16,0x2a,0x2b,0xe0,0x81,0x74,
+ 0x04,0xa3,0x81,0x74,0x04,0xa4,0x84,0x3c,0x34,0x1e,0x80,0x73,0x03,0xa3,0x03,0x3d,
+ 0x43,0x1e,0x7f,0x74,0x04,0xa4,0x84,0x3d,0x34,0x1e,0x04,0x2a,0x09,0xe8,0x17,0xa5,
+ 0x05,0x20,0x45,0x01,0x17,0xb5,0x34,0x60,0x54,0x0c,0x8a,0xe1,0x17,0xb6,0x41,0xf0,
+ 0x79,0x74,0x04,0xa3,0x79,0x74,0x04,0xa4,0x84,0x3c,0x34,0x1e,0x78,0x73,0x03,0xa3,
+ 0x03,0x3d,0x43,0x1e,0x77,0x74,0x04,0xa4,0x84,0x3d,0x34,0x1e,0x17,0xb6,0x04,0x2a,
+ 0x4d,0xe9,0x5c,0xf0,0x26,0x2a,0x74,0xe1,0x6b,0x74,0x04,0xa3,0x6b,0x74,0x04,0xa4,
+ 0x84,0x3c,0x34,0x1e,0x6a,0x73,0x03,0xa3,0x03,0x3d,0x43,0x1e,0x69,0x74,0x04,0xa4,
+ 0x84,0x3d,0x34,0x1e,0x04,0x2a,0x4e,0xe1,0x67,0x74,0x04,0xa3,0x67,0x74,0x04,0xa4,
+ 0x84,0x3c,0x34,0x1e,0x66,0x73,0x03,0xa3,0x03,0x3d,0x43,0x1e,0x65,0x74,0x04,0xa4,
+ 0x84,0x3d,0x34,0x1e,0x04,0x2a,0x0f,0xe8,0x17,0xa4,0x04,0x20,0x44,0x01,0x17,0xb4,
+ 0x50,0x75,0x05,0x85,0x63,0x73,0x35,0x1c,0x05,0xa5,0x45,0x0c,0x49,0xe1,0x15,0x60,
+ 0x17,0xb5,0x37,0xb6,0x45,0xf1,0x16,0x60,0xbd,0xf0,0x16,0x2a,0xbd,0xe0,0x05,0x60,
+ 0xa7,0xb5,0x4f,0x75,0x05,0xa3,0x03,0x2a,0x30,0xe0,0x4e,0x74,0x04,0xa3,0x4e,0x74,
+ 0x04,0xa4,0x84,0x3c,0x34,0x1e,0x4d,0x73,0x03,0xa3,0x03,0x3d,0x43,0x1e,0x4c,0x74,
+ 0x04,0xa4,0x84,0x3d,0x34,0x1e,0x04,0x2a,0x16,0xe1,0x4a,0x74,0x04,0xa3,0x4a,0x74,
+ 0x04,0xa4,0x84,0x3c,0x34,0x1e,0x49,0x73,0x03,0xa3,0x03,0x3d,0x43,0x1e,0x48,0x74,
+ 0x04,0xa4,0x84,0x3d,0x34,0x1e,0x04,0x2a,0x04,0xe8,0x17,0xb6,0x27,0x60,0x05,0xb7,
+ 0x17,0xf1,0x17,0xa3,0x03,0x20,0x43,0x01,0x17,0xb3,0x31,0x75,0x05,0x85,0x44,0x72,
+ 0x25,0x1c,0x05,0xa5,0x35,0x0c,0x0c,0xe1,0xbb,0xf0,0x13,0x2a,0x22,0xe0,0x35,0x76,
+ 0x06,0xa4,0x35,0x76,0x06,0xa6,0x86,0x3c,0x46,0x1e,0x34,0x74,0x04,0xa4,0x04,0x3d,
+ 0x64,0x1e,0x33,0x76,0x06,0xa6,0x86,0x3d,0x46,0x1e,0x06,0x2a,0xf9,0xe0,0x31,0x76,
+ 0x06,0xa4,0x31,0x76,0x06,0xa6,0x86,0x3c,0x46,0x1e,0x30,0x74,0x04,0xa4,0x04,0x3d,
+ 0x64,0x1e,0x2f,0x76,0x06,0xa6,0x86,0x3d,0x46,0x1e,0x17,0xb3,0x06,0x2a,0xe7,0xe8,
+ 0xcd,0xf7,0x23,0x2a,0xe5,0xe0,0x23,0x74,0x04,0xa2,0x23,0x74,0x04,0xa4,0x84,0x3c,
+ 0x24,0x1e,0x22,0x72,0x02,0xa2,0x02,0x3d,0x42,0x1e,0x21,0x74,0x04,0xa4,0x84,0x3d,
+ 0x24,0x1e,0x04,0x2a,0xc0,0xe0,0x1f,0x74,0x04,0xa2,0x1f,0x74,0x04,0xa4,0x84,0x3c,
+ 0x24,0x1e,0x1e,0x72,0x02,0xa2,0x02,0x3d,0x42,0x1e,0x1d,0x74,0x04,0xa4,0x84,0x3d,
+ 0x24,0x1e,0x04,0x2a,0x3f,0xe8,0x0a,0x75,0x05,0x85,0x1d,0x74,0x45,0x1c,0x17,0xa4,
+ 0x05,0xa5,0x45,0x0c,0xbd,0xe0,0x17,0xb6,0x37,0xb3,0xba,0xf0,0x31,0xaa,0x00,0x00,
+ 0x37,0xaa,0x00,0x00,0x38,0xaa,0x00,0x00,0x39,0xaa,0x00,0x00,0x3a,0xaa,0x00,0x00,
+ 0x1c,0x9e,0x00,0x00,0xb7,0x00,0x00,0x00,0xb8,0x00,0x00,0x00,0x76,0x9e,0x00,0x00,
+ 0x77,0x9e,0x00,0x00,0x78,0x9e,0x00,0x00,0x79,0x9e,0x00,0x00,0x66,0x9e,0x00,0x00,
+ 0xd8,0xa5,0x00,0x00,0x46,0xa4,0x00,0x00,0x47,0xa4,0x00,0x00,0x48,0xa4,0x00,0x00,
+ 0x49,0xa4,0x00,0x00,0x4a,0xa4,0x00,0x00,0x4b,0xa4,0x00,0x00,0x4c,0xa4,0x00,0x00,
+ 0x4d,0xa4,0x00,0x00,0x0c,0x01,0x00,0x00,0x0d,0x01,0x00,0x00,0xba,0x00,0x00,0x00,
+ 0xb9,0x00,0x00,0x00,0x17,0xb6,0x5a,0xf0,0x26,0x2a,0x82,0xe0,0x05,0x60,0xa7,0xb5,
+ 0x92,0x75,0x05,0xa3,0x03,0x2a,0x2f,0xe0,0x91,0x74,0x04,0xa3,0x91,0x74,0x04,0xa4,
+ 0x84,0x3c,0x34,0x1e,0x90,0x73,0x03,0xa3,0x03,0x3d,0x43,0x1e,0x8f,0x74,0x04,0xa4,
+ 0x84,0x3d,0x34,0x1e,0x04,0x2a,0x56,0xe0,0x8d,0x74,0x04,0xa3,0x8d,0x74,0x04,0xa4,
+ 0x84,0x3c,0x34,0x1e,0x8c,0x73,0x03,0xa3,0x03,0x3d,0x43,0x1e,0x8b,0x74,0x04,0xa4,
+ 0x84,0x3d,0x34,0x1e,0x04,0x2a,0x59,0xe0,0x17,0xa5,0x05,0x20,0x45,0x01,0x17,0xb5,
+ 0x87,0x76,0x06,0x86,0x87,0x72,0x26,0x1c,0x06,0xa6,0x56,0x0c,0x51,0xe0,0x16,0x60,
+ 0x17,0xb6,0x37,0xb4,0x4d,0xf0,0x13,0x2a,0x23,0xe0,0x78,0x74,0x04,0xa2,0x78,0x74,
+ 0x04,0xa4,0x84,0x3c,0x24,0x1e,0x77,0x72,0x02,0xa2,0x02,0x3d,0x42,0x1e,0x76,0x74,
+ 0x04,0xa4,0x84,0x3d,0x24,0x1e,0x04,0x2a,0x3b,0xe0,0x74,0x74,0x04,0xa2,0x74,0x74,
+ 0x04,0xa4,0x84,0x3c,0x24,0x1e,0x73,0x72,0x02,0xa2,0x02,0x3d,0x42,0x1e,0x72,0x74,
+ 0x04,0xa4,0x84,0x3d,0x24,0x1e,0x17,0xb3,0x04,0x2a,0x29,0xe0,0x05,0xb4,0x28,0xf0,
+ 0x23,0x2a,0x26,0xe0,0x66,0x76,0x06,0xa4,0x66,0x76,0x06,0xa6,0x86,0x3c,0x46,0x1e,
+ 0x65,0x74,0x04,0xa4,0x04,0x3d,0x64,0x1e,0x64,0x76,0x06,0xa6,0x86,0x3d,0x46,0x1e,
+ 0x06,0x2a,0x03,0xe8,0x16,0x60,0x17,0xb6,0x12,0xf0,0x60,0x76,0x06,0xa4,0x60,0x76,
+ 0x06,0xa6,0x86,0x3c,0x46,0x1e,0x5f,0x74,0x04,0xa4,0x04,0x3d,0x64,0x1e,0x5e,0x76,
+ 0x06,0xa6,0x86,0x3d,0x46,0x1e,0x06,0x2a,0x03,0xe0,0x14,0x60,0x17,0xb4,0x05,0xb6,
+ 0xcf,0x00,0xf0,0x24,0x7c,0x00,0x5b,0x77,0x77,0xa7,0x07,0x2a,0x05,0xe8,0x57,0x77,
+ 0x07,0x87,0x76,0x67,0x67,0x1c,0x07,0xf0,0x58,0x77,0x07,0xa7,0x07,0x2a,0x57,0x77,
+ 0x02,0xe8,0x17,0xa7,0x01,0xf0,0x07,0xa7,0x56,0x73,0x03,0xa6,0x13,0xa4,0x84,0x3c,
+ 0x64,0x1e,0x06,0x60,0x65,0x12,0x53,0x7d,0xae,0x61,0x7f,0x12,0x7f,0x01,0x1d,0xf0,
+ 0x57,0x12,0x57,0x1c,0x37,0x1c,0x27,0xa1,0x37,0xa2,0x2c,0x12,0x5c,0x01,0x17,0x12,
+ 0x57,0x01,0xf1,0x11,0xe7,0x03,0xf9,0x11,0xc7,0x1c,0x77,0x1c,0xd7,0x1c,0x07,0xc7,
+ 0x77,0x01,0x7f,0x0d,0x08,0xe8,0x87,0x65,0x67,0x1c,0x77,0x1c,0x37,0x1c,0x87,0xb1,
+ 0x97,0xb2,0x06,0x20,0x46,0x01,0x05,0x20,0x45,0x01,0x45,0x0c,0xe1,0xef,0x42,0x77,
+ 0x07,0xb6,0x42,0x77,0x06,0x60,0x07,0xb6,0x6c,0x00,0xf0,0x20,0xcf,0x00,0xf0,0x25,
+ 0x60,0x9f,0x70,0x9e,0x36,0x77,0x07,0x87,0x3e,0x76,0x76,0x1c,0x06,0xa6,0x06,0x2a,
+ 0x4f,0xe8,0x3c,0x76,0x06,0xa4,0x3c,0x76,0x06,0xa6,0x86,0x3c,0x3c,0x75,0x75,0x1c,
+ 0x05,0xa5,0x3b,0x72,0x27,0x1c,0x07,0xa7,0x87,0x3c,0x46,0x1e,0x57,0x1e,0x67,0x0c,
+ 0x39,0x75,0x39,0x77,0x04,0xe0,0x16,0x60,0x05,0xb6,0x56,0x60,0x05,0xf0,0x07,0xa6,
+ 0x06,0x2a,0x86,0x00,0x01,0xe0,0x05,0xb6,0x07,0xb6,0x32,0x77,0x07,0xa7,0x07,0x2a,
+ 0x2f,0xe8,0x2c,0x77,0x07,0xa6,0x2c,0x77,0x07,0xa7,0x87,0x3c,0x67,0x1e,0x7e,0x12,
+ 0x7e,0x1c,0x7e,0x1c,0x2e,0x3e,0x02,0x12,0x03,0x60,0x44,0x61,0x2c,0x7f,0x22,0x77,
+ 0x07,0xa7,0x22,0x76,0x06,0xa5,0x85,0x3c,0x75,0x1e,0x06,0x60,0x1d,0x73,0x7e,0x01,
+ 0x14,0x60,0x11,0xf0,0x67,0x12,0x37,0x3c,0x67,0x05,0x37,0x1c,0x82,0x62,0x27,0x1c,
+ 0x77,0xa2,0x87,0xa7,0x87,0x3c,0x27,0x1e,0xe7,0x0d,0x03,0xe8,0x07,0x12,0x67,0x1c,
+ 0x07,0xb4,0x06,0x20,0x46,0x01,0x56,0x0c,0xed,0xef,0x02,0x12,0x13,0x73,0x1c,0x7f,
+ 0x60,0x8f,0x70,0x8e,0xf0,0x21,0xcf,0x00,0xd8,0xa5,0x00,0x00,0x46,0xa4,0x00,0x00,
+ 0x47,0xa4,0x00,0x00,0x48,0xa4,0x00,0x00,0x49,0xa4,0x00,0x00,0x4a,0xa4,0x00,0x00,
+ 0x4b,0xa4,0x00,0x00,0x4c,0xa4,0x00,0x00,0x4d,0xa4,0x00,0x00,0x1c,0x9e,0x00,0x00,
+ 0xb9,0x00,0x00,0x00,0x20,0xaa,0x00,0x00,0x4a,0xa0,0x00,0x00,0x86,0x9e,0x00,0x00,
+ 0x8a,0x9e,0x00,0x00,0x00,0xe0,0x02,0x00,0x40,0x9f,0x00,0x00,0x41,0x9f,0x00,0x00,
+ 0x83,0x00,0x00,0x00,0x3e,0xa4,0x00,0x00,0x3f,0xa4,0x00,0x00,0x84,0x00,0x00,0x00,
+ 0x85,0x00,0x00,0x00,0xd9,0xa5,0x00,0x00,0x00,0x9e,0x00,0x00,0x22,0x83,0x00,0x00,
+ 0x00,0x2d,0x00,0x00,0x70,0x25,0x7a,0x00,0xbd,0x77,0x07,0x8f,0xbd,0x77,0xf7,0x1c,
+ 0x07,0xa7,0x07,0x2a,0x77,0xe8,0xbb,0x77,0x07,0xa6,0xbb,0x77,0x07,0xa7,0xbb,0x71,
+ 0x7c,0x12,0x4c,0x3c,0x75,0x12,0x65,0x3c,0x5c,0x1c,0xb9,0x74,0xc4,0x1c,0x03,0x60,
+ 0x7d,0x12,0x7d,0x1c,0x37,0x3c,0x7d,0x1c,0x0c,0x28,0x6e,0x12,0x4e,0x3c,0x67,0x12,
+ 0x67,0x3c,0x7e,0x1c,0x01,0xa7,0x27,0x2a,0x58,0xe0,0x04,0xa7,0x07,0x2a,0x55,0xe8,
+ 0xb1,0x7b,0xd7,0x12,0x37,0x1c,0xb0,0x75,0x57,0x1c,0x37,0x3c,0xb7,0x1c,0x77,0xa5,
+ 0x87,0xa2,0x82,0x3c,0x52,0x1e,0xad,0x77,0xf7,0x1c,0x07,0xa7,0xad,0x75,0xf5,0x1c,
+ 0x05,0xa5,0x85,0x3c,0x75,0x1e,0x25,0x0c,0x12,0xe0,0x67,0x12,0x67,0x1c,0x6a,0x12,
+ 0x3a,0x3c,0xa7,0x1c,0x37,0x1c,0xa4,0x7a,0xa7,0x1c,0x37,0x3c,0xb7,0x1c,0x77,0xab,
+ 0x87,0xa7,0x87,0x3c,0xb7,0x1e,0x5b,0x12,0x2b,0x3e,0x7b,0x0c,0x14,0xe8,0x9d,0x7b,
+ 0x67,0x12,0x67,0x1c,0x6a,0x12,0x3a,0x3c,0xa7,0x1c,0x37,0x1c,0x9b,0x7a,0xa7,0x1c,
+ 0x37,0x3c,0x7b,0x1c,0x7b,0xaa,0x8b,0xa7,0x87,0x3c,0xa7,0x1e,0x75,0x0c,0x1d,0xe0,
+ 0x25,0x3e,0x25,0x0c,0x1a,0xe0,0x74,0xa7,0xc5,0x12,0x45,0x1c,0xe5,0x1c,0x75,0xa5,
+ 0x57,0x05,0xe7,0x01,0x67,0x01,0x72,0x12,0x72,0x01,0xa5,0x65,0x25,0x0d,0x04,0xe8,
+ 0x91,0x75,0x75,0x05,0x57,0x12,0x67,0x01,0x77,0x01,0x8f,0x75,0xf5,0x1c,0x05,0xa5,
+ 0x15,0x3e,0x75,0x0d,0x02,0xe8,0x47,0x60,0x01,0xb7,0x03,0x20,0x01,0x20,0x74,0x20,
+ 0xa3,0x2a,0xa0,0xe7,0x6a,0x00,0x70,0x21,0xcf,0x00,0xf0,0x25,0x78,0x00,0x01,0x65,
+ 0x10,0x05,0x2a,0x12,0x86,0x77,0x07,0xa7,0x07,0x2a,0x17,0xe8,0x06,0x60,0x84,0x77,
+ 0x07,0xb6,0x7a,0x77,0x84,0x72,0x13,0x60,0x44,0x60,0x07,0xa5,0x15,0x2a,0x02,0xe0,
+ 0x07,0xb6,0x05,0xf0,0x15,0x24,0x45,0x01,0x53,0x0c,0x01,0xe8,0x07,0xb4,0x07,0x20,
+ 0x27,0x0f,0xf3,0xe7,0x06,0x60,0x79,0x77,0x07,0xb6,0x79,0x77,0x07,0xa7,0x0a,0xb7,
+ 0x7a,0x77,0x07,0xa7,0x1a,0xb7,0x79,0x77,0x07,0xa7,0x2a,0xb7,0xa6,0x12,0x07,0x60,
+ 0x6d,0x74,0x75,0x12,0x45,0x1c,0x76,0x73,0x35,0x1c,0x05,0xa5,0x96,0xb5,0x07,0x20,
+ 0x56,0x20,0xa7,0x2a,0xf6,0xe7,0x61,0x77,0x07,0x8e,0x72,0x77,0xe7,0x1c,0x07,0xa7,
+ 0x74,0x32,0x47,0x1c,0x00,0x97,0x70,0x77,0xe7,0x1c,0x07,0xa7,0x47,0x1c,0x10,0x97,
+ 0x6f,0x77,0xa7,0xa6,0xb7,0xa5,0x85,0x3c,0x65,0x1e,0x40,0x95,0x56,0x12,0x6c,0x73,
+ 0x36,0x1c,0x66,0x01,0x60,0x96,0xc7,0xa6,0xd7,0xa4,0x84,0x3c,0x64,0x1e,0x50,0x94,
+ 0x46,0x12,0x36,0x1c,0x66,0x01,0x70,0x96,0xe7,0xa6,0xf7,0xa8,0x88,0x3c,0x68,0x1e,
+ 0x65,0x77,0x07,0xa7,0x65,0x76,0x06,0xa9,0x89,0x3c,0x79,0x1e,0x95,0x12,0x85,0x05,
+ 0xc0,0x95,0x62,0x77,0x07,0xa7,0x62,0x76,0x06,0xa6,0x86,0x3c,0x76,0x1e,0x20,0x96,
+ 0x61,0x77,0x07,0xa7,0x61,0x76,0x06,0xa6,0x86,0x3c,0x76,0x1e,0x30,0x96,0x20,0x87,
+ 0x76,0x05,0xd0,0x96,0x0d,0x60,0x5d,0x73,0xe3,0x1c,0x90,0x93,0x5d,0x74,0xe4,0x1c,
+ 0xa0,0x94,0x5c,0x75,0xe5,0x1c,0xe0,0x95,0x5c,0x76,0xe6,0x1c,0xb0,0x96,0x10,0x87,
+ 0x83,0x2c,0x37,0x16,0xf0,0x97,0x10,0x85,0x85,0x3e,0x04,0x64,0x04,0x1c,0x04,0x95,
+ 0x00,0x87,0x37,0x16,0x46,0x64,0x06,0x1c,0x06,0x97,0x00,0x84,0x84,0x3e,0x83,0x64,
+ 0x03,0x1c,0x03,0x94,0x87,0xf1,0xd6,0x12,0x36,0x3c,0xd6,0x1c,0x76,0x1c,0x4f,0x75,
+ 0x65,0x1c,0x05,0xab,0xb7,0x1c,0x3e,0x75,0x57,0x1c,0x07,0xa7,0x47,0x2a,0x78,0xe9,
+ 0x07,0x2a,0x76,0xe9,0x4b,0x77,0x76,0x1c,0x56,0xa7,0x66,0xa2,0x82,0x3c,0x72,0x1e,
+ 0x87,0x32,0x27,0x0c,0x22,0xe8,0x00,0x83,0x32,0x0c,0x08,0xe0,0x44,0x64,0x04,0x1c,
+ 0x04,0xa4,0x56,0xb4,0x85,0x64,0x05,0x1c,0x05,0xa5,0x66,0xb5,0xd7,0x12,0x37,0x3c,
+ 0xd7,0x1c,0x40,0x76,0x67,0x1c,0x57,0xa6,0x67,0xa7,0x87,0x3c,0x67,0x1e,0x00,0x86,
+ 0x67,0x05,0x90,0x83,0x03,0xac,0x82,0x12,0xc2,0x05,0xf1,0x11,0x72,0x03,0xf9,0x11,
+ 0x83,0x32,0x63,0x05,0x39,0x7f,0x2c,0x1c,0x8b,0xf0,0x60,0x84,0x24,0x0c,0x7d,0xe0,
+ 0x37,0x77,0xe7,0x1c,0x07,0xa7,0x45,0x12,0x73,0x32,0x35,0x1c,0x75,0x05,0x25,0x0d,
+ 0x08,0xe8,0x40,0x85,0x33,0x74,0x45,0x1c,0x75,0x05,0x65,0x01,0x56,0xb5,0x85,0x3e,
+ 0x66,0xb5,0xd5,0x12,0x35,0x3c,0xd5,0x1c,0x2b,0x76,0x65,0x1c,0x55,0xa6,0x65,0xa2,
+ 0x82,0x3c,0x62,0x1e,0x60,0x85,0x52,0x05,0x0e,0xa5,0x1e,0xa6,0x86,0x3c,0x56,0x1e,
+ 0x29,0x75,0xe5,0x1c,0x05,0xa5,0x56,0x05,0x4f,0xf0,0x00,0x00,0x1c,0x9e,0x00,0x00,
+ 0x1a,0x01,0x00,0x00,0xe4,0xa3,0x00,0x00,0xe5,0xa3,0x00,0x00,0xfa,0xa3,0x00,0x00,
+ 0xa4,0xa2,0x00,0x00,0x8a,0x9e,0x00,0x00,0x83,0x00,0x00,0x00,0x1b,0x01,0x00,0x00,
+ 0x1c,0x01,0x00,0x00,0xb4,0x00,0x00,0x00,0x1d,0x01,0x00,0x00,0x62,0xa4,0x00,0x00,
+ 0xa5,0xa0,0x00,0x00,0x04,0xa4,0x00,0x00,0x4a,0xa0,0x00,0x00,0x2c,0xa4,0x00,0x00,
+ 0x70,0x05,0x00,0x00,0x9d,0x00,0x00,0x00,0x9f,0x00,0x00,0x00,0x20,0x9e,0x00,0x00,
+ 0x00,0xff,0xff,0xff,0x30,0x9e,0x00,0x00,0x31,0x9e,0x00,0x00,0x32,0x9e,0x00,0x00,
+ 0x33,0x9e,0x00,0x00,0x34,0x9e,0x00,0x00,0x35,0x9e,0x00,0x00,0x99,0x00,0x00,0x00,
+ 0x9b,0x00,0x00,0x00,0xc1,0x00,0x00,0x00,0x9c,0x00,0x00,0x00,0x1c,0x02,0x00,0x00,
+ 0x18,0x02,0x00,0x00,0xa2,0xa0,0x00,0x00,0xd0,0x83,0x00,0x00,0x9e,0x00,0x00,0x00,
+ 0x80,0xff,0xff,0xff,0x9a,0x00,0x00,0x00,0x96,0x05,0xf1,0x11,0x62,0x03,0xf9,0x11,
+ 0x73,0x32,0x73,0x05,0x7e,0x7f,0x92,0x1c,0x0a,0xf0,0x7d,0x76,0x62,0x1c,0xc0,0x87,
+ 0xf1,0x11,0x72,0x03,0xf9,0x11,0x60,0x83,0x63,0x1c,0x78,0x7f,0x82,0x1c,0x2c,0x12,
+ 0x6c,0x01,0xd6,0x12,0x36,0x3c,0xd6,0x1c,0x77,0x77,0x76,0x1c,0x76,0xa7,0x86,0xa2,
+ 0x82,0x3c,0x72,0x1e,0x87,0x2c,0x27,0x0c,0x24,0xe8,0x10,0x83,0x32,0x0c,0x08,0xe0,
+ 0xc4,0x63,0x04,0x1c,0x04,0xa4,0x76,0xb4,0x05,0x64,0x05,0x1c,0x05,0xa5,0x86,0xb5,
+ 0xd7,0x12,0x37,0x3c,0xd7,0x1c,0x6b,0x76,0x67,0x1c,0x77,0xa6,0x87,0xa7,0x87,0x3c,
+ 0x67,0x1e,0x10,0x86,0x67,0x05,0xa0,0x83,0x03,0xa3,0x80,0x93,0x20,0x82,0x32,0x05,
+ 0xf1,0x11,0x72,0x03,0xf9,0x11,0x83,0x32,0x63,0x05,0x60,0x7f,0x80,0x84,0x42,0x1c,
+ 0x3b,0xf0,0x70,0x85,0x25,0x0c,0x2d,0xe0,0x60,0x77,0xe7,0x1c,0x07,0xa7,0x73,0x32,
+ 0x35,0x1c,0x75,0x05,0x25,0x0d,0x08,0xe8,0x50,0x85,0x5c,0x74,0x45,0x1c,0x75,0x05,
+ 0x65,0x01,0x76,0xb5,0x85,0x3e,0x86,0xb5,0xd5,0x12,0x35,0x3c,0xd5,0x1c,0x55,0x76,
+ 0x65,0x1c,0x75,0xa6,0x85,0xa2,0x82,0x3c,0x62,0x1e,0x70,0x85,0x52,0x05,0x2e,0xa5,
+ 0x3e,0xa6,0x86,0x3c,0x56,0x1e,0xb0,0x83,0x03,0xa5,0x56,0x05,0x30,0x84,0x46,0x05,
+ 0xf1,0x11,0x62,0x03,0xf9,0x11,0x73,0x32,0x73,0x05,0x48,0x7f,0x30,0x85,0x52,0x1c,
+ 0x0b,0xf0,0x47,0x76,0x62,0x1c,0xd0,0x87,0xf1,0x11,0x72,0x03,0xf9,0x11,0x70,0x83,
+ 0x63,0x1c,0x42,0x7f,0x20,0x83,0x32,0x1c,0x62,0x01,0x90,0x84,0x04,0xa7,0x7c,0x0c,
+ 0x10,0xe8,0x0e,0xa6,0x1e,0xa7,0x87,0x3c,0x67,0x1e,0x41,0x76,0xe6,0x1c,0x06,0xa6,
+ 0x75,0x12,0x65,0x05,0x5c,0x0d,0x06,0xe0,0x07,0x24,0x67,0x05,0x7c,0x12,0x6c,0x01,
+ 0x01,0xf0,0x7c,0x12,0xa0,0x85,0x05,0xa7,0x72,0x0c,0x0f,0xe8,0x2e,0xa6,0x3e,0xa7,
+ 0x87,0x3c,0x67,0x1e,0xb0,0x83,0x03,0xa6,0x75,0x12,0x65,0x05,0x52,0x0d,0x06,0xe0,
+ 0x07,0x24,0x67,0x05,0x72,0x12,0x62,0x01,0x01,0xf0,0x72,0x12,0xe0,0x84,0x04,0xa7,
+ 0x07,0x2a,0xb7,0x12,0xb7,0x1c,0x86,0x2c,0x26,0x16,0x85,0x2c,0xc5,0x16,0xb7,0x1c,
+ 0x77,0x1c,0xa7,0x1c,0x07,0xe8,0x47,0xb6,0x82,0x3e,0x57,0xb2,0x67,0xb5,0x8c,0x3e,
+ 0x77,0xbc,0x06,0xf0,0x47,0xb5,0x8c,0x3e,0x57,0xbc,0x67,0xb6,0x82,0x3e,0x77,0xb2,
+ 0xb7,0x12,0xb7,0x1c,0xb7,0x1c,0x77,0x1c,0xa7,0x1c,0xd6,0x12,0x36,0x3c,0xd6,0x1c,
+ 0x1d,0x75,0x56,0x1c,0x96,0xa5,0xa6,0xa6,0x86,0x3c,0x56,0x1e,0x46,0x3e,0x87,0xb6,
+ 0x0d,0x20,0x4d,0x01,0x1c,0x77,0x1c,0x76,0x06,0xa6,0x6d,0x0c,0x74,0xee,0x05,0x60,
+ 0x1b,0x72,0x53,0x12,0x12,0xf0,0x56,0x12,0x36,0x3c,0x56,0x1c,0x76,0x1c,0x18,0x74,
+ 0x46,0x1c,0x06,0xa4,0x46,0x12,0x46,0x1c,0x46,0x1c,0x66,0x1c,0xa6,0x1c,0x96,0xa4,
+ 0x44,0x2a,0x01,0xe0,0x86,0xb3,0x05,0x20,0x45,0x01,0x02,0xa6,0x65,0x0c,0xeb,0xef,
+ 0x0e,0x73,0x03,0xa7,0x74,0x12,0x34,0x3c,0x74,0x1c,0x0c,0x72,0x04,0x20,0x0d,0x7f,
+ 0x01,0x65,0x10,0x1c,0x68,0x00,0xf0,0x21,0xcf,0x00,0x00,0x00,0xd0,0x83,0x00,0x00,
+ 0x00,0xff,0xff,0xff,0xa2,0xa0,0x00,0x00,0xa0,0x00,0x00,0x00,0x80,0xff,0xff,0xff,
+ 0x9a,0x00,0x00,0x00,0x8a,0x9e,0x00,0x00,0xa5,0xa0,0x00,0x00,0x4a,0xa0,0x00,0x00,
+ 0xc1,0x01,0x00,0x00,0x8c,0x82,0x00,0x00,0x70,0x25,0x7a,0x00,0x86,0x7e,0x86,0x77,
+ 0x07,0xa7,0x07,0x2a,0x56,0xe8,0x0e,0xa7,0x1e,0xa5,0x85,0x3c,0x75,0x1e,0x1b,0x60,
+ 0x5b,0x0c,0x4f,0xe0,0x82,0x77,0x07,0xa7,0x82,0x76,0x06,0xaa,0x8a,0x3c,0x7a,0x1e,
+ 0x81,0x77,0x07,0x8d,0x67,0x67,0xd7,0x1c,0x07,0xa7,0x77,0x1c,0x7a,0x0d,0x48,0xe8,
+ 0x57,0x67,0xd7,0x1c,0x07,0xa7,0x7a,0x0c,0x0e,0xe8,0xba,0x0b,0x7b,0x7c,0x2c,0xba,
+ 0x7b,0x7f,0x0e,0xa6,0x1e,0xa7,0x87,0x3c,0x67,0x1e,0x7b,0x0c,0x39,0xe8,0x3c,0xbb,
+ 0x0c,0xba,0x1c,0xba,0x2e,0xf0,0x76,0x77,0x07,0xac,0x76,0x77,0x07,0xad,0x03,0x60,
+ 0xf2,0x67,0x36,0x12,0x5c,0x01,0x5d,0x01,0x16,0xf0,0x67,0x12,0x67,0x1c,0xe7,0x1c,
+ 0x27,0xa4,0x54,0x01,0xc4,0x05,0xe4,0x01,0x37,0xa7,0x57,0x01,0xd7,0x05,0xe7,0x01,
+ 0x47,0x1c,0x47,0x01,0x74,0x12,0x54,0x01,0x24,0x0d,0x27,0x0a,0x01,0xe8,0x63,0x12,
+ 0x06,0x20,0x46,0x01,0x72,0x12,0x56,0x0c,0x5f,0x77,0xe7,0xef,0x16,0x60,0x07,0xb6,
+ 0x06,0x60,0x17,0xb6,0x36,0x12,0x36,0x1c,0x76,0x1c,0x26,0xa5,0x27,0xb5,0x36,0xa6,
+ 0x37,0xb6,0x59,0x77,0x07,0xa6,0x60,0x77,0x07,0xb6,0x6a,0x00,0x70,0x21,0xcf,0x00,
+ 0x5a,0x77,0x66,0x67,0xd6,0x1c,0x06,0xa6,0x07,0xb6,0x56,0x67,0xd6,0x1c,0x06,0xa6,
+ 0x17,0xb6,0x46,0x67,0x6d,0x1c,0x0d,0xa6,0x27,0xb6,0x06,0x60,0x4f,0x77,0x07,0xb6,
+ 0xe8,0xf7,0xf0,0x25,0x78,0x00,0xf0,0x24,0x42,0x01,0x03,0x01,0x26,0x12,0x06,0x24,
+ 0x46,0x01,0x4c,0x77,0x07,0x87,0x0f,0x60,0x1a,0x12,0x0a,0x24,0x4a,0x01,0x4f,0x7b,
+ 0xac,0x61,0x6d,0x67,0x7d,0x1c,0x5e,0x67,0x7e,0x1c,0x43,0x67,0x73,0x1c,0x4c,0x75,
+ 0x75,0x1c,0x00,0x95,0x4c,0x75,0x75,0x1c,0x10,0x95,0x29,0xf0,0xa5,0x12,0x69,0x12,
+ 0xf1,0x11,0xc9,0x03,0xf9,0x11,0x20,0x96,0x1d,0xf0,0x97,0x12,0x57,0x1c,0x77,0x1c,
+ 0xb7,0x1c,0x07,0xc4,0x74,0x01,0x0d,0xa7,0x47,0x0d,0x12,0xe0,0x0e,0xa7,0x47,0x0d,
+ 0x0f,0xe0,0x03,0xa7,0x47,0x0d,0x0c,0xe0,0x00,0x86,0x06,0xa8,0x10,0x86,0x06,0xa7,
+ 0x87,0x3c,0x87,0x1e,0x07,0x3d,0x07,0x3b,0x74,0x0d,0x02,0xe8,0x0f,0x20,0x4f,0x01,
+ 0x05,0x20,0x45,0x01,0x51,0x0d,0xe1,0xef,0x20,0x86,0x06,0x20,0x46,0x01,0x62,0x0d,
+ 0xd5,0xef,0x27,0x60,0xf7,0x0c,0x22,0x00,0xf0,0x20,0x68,0x00,0xf0,0x21,0xcf,0x00,
+ 0xf0,0x24,0x7c,0x00,0x24,0x7c,0x30,0x77,0x07,0xa6,0x30,0x77,0x07,0xa7,0x87,0x3c,
+ 0x67,0x1e,0x1e,0x60,0x07,0x2a,0x16,0xe8,0x0c,0xa7,0x1c,0xae,0x8e,0x3c,0x7e,0x1e,
+ 0x0d,0x60,0x0e,0x2a,0x0b,0xe0,0x0e,0xf0,0xd7,0x12,0xd7,0x1c,0xc7,0x1c,0x27,0xa2,
+ 0x37,0xa3,0x27,0x7f,0x02,0x2a,0x04,0xe0,0x0d,0x20,0x4d,0x01,0xed,0x0c,0xf4,0xef,
+ 0xed,0x0c,0x3e,0x00,0x24,0x77,0x07,0xa7,0x07,0x2a,0x23,0x77,0x0f,0xe8,0x06,0x60,
+ 0x0e,0x2a,0x02,0xe0,0x07,0xa6,0x06,0x20,0x07,0xb6,0x1f,0x77,0x07,0xa5,0xa6,0x60,
+ 0x56,0x0c,0x15,0xe0,0x06,0x60,0x1b,0x75,0x05,0xb6,0x10,0xf0,0x0e,0x2a,0x04,0xe8,
+ 0x07,0xa6,0x06,0x20,0x07,0xb6,0x01,0xf0,0x07,0xbe,0x17,0x77,0x07,0xa5,0xa6,0x60,
+ 0x56,0x0c,0x05,0xe0,0x15,0x60,0x13,0x76,0x06,0xb5,0x06,0x60,0x07,0xb6,0x6c,0x00,
+ 0xf0,0x20,0xcf,0x00,0x8a,0x9e,0x00,0x00,0x63,0xa4,0x00,0x00,0x3e,0xa4,0x00,0x00,
+ 0x3f,0xa4,0x00,0x00,0x1c,0x9e,0x00,0x00,0x86,0x9e,0x00,0x00,0x00,0x28,0x00,0x00,
+ 0x4f,0xa0,0x00,0x00,0x4d,0xa0,0x00,0x00,0x3d,0xaa,0x00,0x00,0x00,0xe0,0x02,0x00,
+ 0xb5,0x00,0x00,0x00,0xb6,0x00,0x00,0x00,0x6a,0x9f,0x00,0x00,0x6b,0x9f,0x00,0x00,
+ 0xe2,0x4d,0x00,0x00,0x64,0xa4,0x00,0x00,0xda,0xa5,0x00,0x00,0xf0,0x25,0x78,0x00,
+ 0xa4,0x71,0x10,0x05,0xa4,0x77,0x07,0x8e,0x4e,0xa2,0x5e,0xa3,0xa3,0x77,0x00,0x97,
+ 0x34,0x60,0xa2,0x75,0xa3,0x76,0x07,0x60,0xa3,0x7f,0xa3,0x77,0xe7,0x1c,0x07,0xa7,
+ 0x07,0x2a,0x18,0xe8,0xa2,0x77,0x17,0xa6,0x07,0xa7,0x76,0x1c,0x07,0x60,0xa0,0x72,
+ 0xa1,0x73,0xa1,0x74,0x0d,0xf0,0x75,0x12,0x75,0x1c,0x2f,0x12,0x5f,0x1c,0x3d,0x12,
+ 0x5d,0x1c,0x45,0x1c,0x0d,0xcd,0x05,0xc5,0xd5,0x14,0x0f,0xd5,0x07,0x20,0x47,0x01,
+ 0x67,0x0d,0xf1,0xe7,0x9a,0x77,0x57,0xa7,0x17,0x2e,0x07,0x2a,0x07,0xe8,0x98,0x72,
+ 0x4e,0xa3,0x5e,0xa4,0x98,0x7f,0x98,0x72,0x83,0x61,0x98,0x7f,0x94,0x77,0x57,0xa7,
+ 0x47,0x2e,0x07,0x2a,0x09,0xe8,0x87,0x77,0x07,0x87,0x95,0x72,0x47,0xa3,0x57,0xa4,
+ 0x91,0x7f,0x94,0x72,0xa3,0x61,0x91,0x7f,0x8d,0x77,0x57,0xa7,0x27,0x2e,0x07,0x2a,
+ 0x0b,0xe8,0x91,0x72,0x8c,0x7f,0x7f,0x77,0x07,0x87,0x90,0x72,0x47,0xa3,0x57,0xa4,
+ 0x89,0x7f,0x8f,0x72,0xa3,0x61,0x89,0x7f,0x7b,0x77,0x07,0x8e,0xa7,0x67,0xe7,0x1c,
+ 0x07,0xa7,0x07,0x2a,0x06,0xe8,0x7d,0x77,0x07,0xa2,0x17,0xa3,0x89,0x74,0xa5,0x61,
+ 0x89,0x7f,0xd1,0x67,0x1e,0x1c,0x0e,0xa7,0x07,0x2a,0x49,0xe9,0x78,0x77,0x07,0xa3,
+ 0x86,0x72,0x02,0x1c,0x02,0x93,0x17,0xa5,0x85,0x74,0x04,0x1c,0x04,0x95,0x0e,0x60,
+ 0xed,0x12,0x6c,0x78,0x37,0xf1,0x08,0x87,0x26,0x65,0x67,0x1c,0x07,0xae,0xde,0x1c,
+ 0x4e,0x01,0x7d,0x77,0x07,0x1c,0x07,0x87,0x7e,0x0c,0x7e,0x02,0xd2,0x12,0x12,0x28,
+ 0xe2,0x1c,0x42,0x01,0x22,0x1c,0x33,0x60,0x7a,0x7f,0x7a,0x73,0x03,0x1c,0x03,0x92,
+ 0x0c,0x60,0xa9,0x61,0x14,0xf1,0x02,0x12,0x72,0x20,0x03,0x60,0x04,0x61,0x76,0x7f,
+ 0xd7,0x12,0x04,0x60,0x05,0x61,0x31,0xf0,0x76,0x12,0xf1,0x11,0x96,0x03,0xf9,0x11,
+ 0xc6,0x1c,0x66,0x1c,0x6b,0x71,0x16,0x1c,0x06,0xc6,0x76,0x01,0x70,0x72,0x62,0x0d,
+ 0x05,0xe8,0xc6,0x61,0x06,0x1c,0x76,0x1c,0x06,0xb5,0x12,0xf0,0x6d,0x73,0x36,0x0d,
+ 0x05,0xe8,0xc6,0x61,0x06,0x1c,0x76,0x1c,0x06,0xb4,0x0a,0xf0,0xc3,0x61,0x03,0x1c,
+ 0x73,0x1c,0xf6,0x37,0x02,0xe8,0xff,0x63,0xf6,0x1c,0x66,0x3a,0x76,0x20,0x03,0xb6,
+ 0xc6,0x61,0x06,0x1c,0x76,0x1c,0x06,0xa6,0x56,0x01,0x81,0x60,0x01,0x1c,0x16,0x1c,
+ 0x06,0xa3,0x03,0x20,0x06,0xb3,0x07,0x20,0x47,0x01,0xe7,0x0c,0xcd,0xef,0x07,0x60,
+ 0x75,0x12,0x76,0x12,0x07,0x01,0x84,0x60,0x04,0x1c,0x74,0x1c,0x04,0xa4,0x46,0x0c,
+ 0x15,0x0a,0x46,0x0a,0x07,0x20,0x07,0x2b,0xf5,0xe7,0x07,0x60,0x56,0x72,0x02,0x1c,
+ 0x02,0x97,0x76,0x12,0x07,0x01,0x84,0x60,0x04,0x1c,0x74,0x1c,0x04,0xa4,0x46,0x0c,
+ 0x06,0xe0,0x51,0x0f,0x04,0xe8,0x4f,0x73,0x03,0x1c,0x03,0x91,0x46,0x12,0x07,0x20,
+ 0x07,0x2b,0xf0,0xe7,0xd6,0x12,0x02,0x60,0x2b,0x12,0x16,0xf0,0xc7,0x61,0x07,0x1c,
+ 0x67,0x1c,0x07,0xa7,0x57,0x01,0x57,0x0f,0x0d,0xe0,0x67,0x12,0xf1,0x11,0x97,0x03,
+ 0xf9,0x11,0xc7,0x1c,0x77,0x1c,0x3a,0x74,0x47,0x1c,0x07,0xc7,0x77,0x01,0x72,0x1c,
+ 0x0b,0x20,0x4b,0x01,0x06,0x20,0x46,0x01,0xe6,0x0c,0xe8,0xef,0x0b,0x2a,0x04,0xe8,
+ 0xb3,0x12,0x37,0x7f,0x2a,0x12,0x01,0xf0,0xba,0x12,0x36,0x75,0x05,0x1c,0x05,0x85,
+ 0x5b,0x0d,0x2b,0xe8,0x08,0x87,0x66,0x67,0x67,0x1c,0x07,0xa7,0xa7,0x0d,0x1b,0xe0,
+ 0x24,0xf0,0xc7,0x61,0x07,0x1c,0x67,0x1c,0x07,0xa7,0x57,0x01,0x32,0x71,0x01,0x1c,
+ 0x01,0x81,0x17,0x0f,0x0d,0xe0,0x67,0x12,0xf1,0x11,0x97,0x03,0xf9,0x11,0xc7,0x1c,
+ 0x77,0x1c,0x23,0x74,0x47,0x1c,0x07,0xc7,0x77,0x01,0x72,0x1c,0x03,0x20,0x43,0x01,
+ 0x06,0x20,0x46,0x01,0x03,0xf0,0xd6,0x12,0x02,0x60,0x23,0x12,0xe6,0x0c,0xe1,0xef,
+ 0x03,0x2a,0x03,0xe8,0x1f,0x7f,0x2a,0x0d,0x2a,0x0a,0x08,0x87,0xe5,0x67,0x57,0x1c,
+ 0x07,0xa6,0xf1,0x11,0xa6,0x03,0xf9,0x11,0x46,0x3a,0xd5,0x12,0x02,0x60,0x53,0xf0,
+ 0xd0,0x00,0x00,0x00,0x1c,0x9e,0x00,0x00,0x36,0x00,0x05,0x1a,0x36,0x00,0x04,0x1a,
+ 0x00,0x00,0x02,0x18,0xb4,0x26,0x00,0x00,0xc8,0x00,0x00,0x00,0x20,0x9e,0x00,0x00,
+ 0xdc,0xa5,0x00,0x00,0x5e,0xa5,0x00,0x00,0xec,0xa4,0x00,0x00,0x44,0xaa,0x00,0x00,
+ 0x10,0x07,0x00,0x00,0x7a,0x25,0x00,0x00,0x00,0x80,0x02,0x00,0xc0,0x2b,0x00,0x00,
+ 0x24,0x07,0x00,0x00,0x36,0xc0,0x02,0x00,0x38,0x07,0x00,0x00,0x44,0x07,0x00,0x00,
+ 0x36,0xe0,0x02,0x00,0x48,0x2a,0x00,0x00,0xb0,0x00,0x00,0x00,0xb4,0x00,0x00,0x00,
+ 0x3e,0x84,0x00,0x00,0xbc,0x00,0x00,0x00,0x22,0x83,0x00,0x00,0xc0,0x01,0x00,0x00,
+ 0x40,0xfe,0xff,0xff,0xb8,0x00,0x00,0x00,0x57,0x12,0xf1,0x11,0x97,0x03,0xf9,0x11,
+ 0xc7,0x1c,0x77,0x1c,0xad,0x71,0x17,0x1c,0x07,0xc4,0x43,0x12,0x73,0x01,0xf3,0x37,
+ 0x02,0xe0,0x36,0x0d,0x01,0xf0,0x63,0x0d,0x03,0xe8,0x64,0x05,0x07,0xd4,0x01,0xf0,
+ 0x07,0xd2,0x05,0x20,0x45,0x01,0xe5,0x0c,0xe7,0xef,0x0c,0x20,0x4c,0x01,0xa3,0x72,
+ 0x02,0x1c,0x02,0x82,0x2c,0x0f,0xe7,0xe6,0x08,0x87,0x23,0x65,0x37,0x1c,0x07,0xa7,
+ 0x7d,0x1c,0x4d,0x01,0x9f,0x74,0x04,0x1c,0x04,0x84,0x4e,0x0c,0xc4,0xee,0x9d,0x77,
+ 0x57,0xa7,0x27,0x2e,0x07,0x2a,0x05,0xe8,0x9c,0x72,0x9c,0x7f,0x97,0x72,0xa3,0x61,
+ 0x9c,0x7f,0x9c,0x77,0x07,0x8e,0x4e,0xa2,0x5e,0xa3,0x57,0x67,0xe7,0x1c,0x07,0xa7,
+ 0x0d,0x60,0x00,0x9d,0xc4,0x60,0x98,0x75,0xd6,0x12,0x98,0x7f,0x99,0x7c,0x0c,0x87,
+ 0x99,0x76,0x06,0xb7,0x17,0x01,0x98,0x76,0x06,0xb1,0x27,0x01,0x98,0x76,0x06,0xb1,
+ 0x87,0x3f,0x97,0x76,0x06,0xb7,0x4e,0xa2,0x5e,0xa3,0x96,0x7b,0xeb,0x1c,0x0b,0xa6,
+ 0x96,0x7a,0xea,0x1c,0x0a,0xa7,0x87,0x3c,0x67,0x1e,0x07,0x3d,0x00,0x9d,0xd4,0x60,
+ 0x8a,0x75,0xd6,0x12,0x07,0x3b,0x89,0x7f,0x0c,0x87,0x90,0x76,0x06,0xb7,0x17,0x01,
+ 0x90,0x76,0x06,0xb1,0x27,0x01,0x8f,0x76,0x06,0xb1,0x87,0x3f,0x8f,0x76,0x06,0xb7,
+ 0x4e,0xa2,0x5e,0xa3,0x47,0x67,0xe7,0x1c,0x07,0xa7,0x00,0x9d,0xa4,0x60,0x7e,0x75,
+ 0xd6,0x12,0x7e,0x7f,0x0c,0x87,0x89,0x75,0x05,0xb7,0x17,0x01,0x89,0x76,0x06,0xb1,
+ 0x27,0x01,0x88,0x78,0x08,0xb1,0x87,0x3f,0x88,0x71,0x01,0xb7,0x4e,0xa2,0x5e,0xa3,
+ 0x0b,0xa6,0x0a,0xa7,0x87,0x3c,0x67,0x1e,0x07,0x3d,0x00,0x9d,0xb4,0x60,0x72,0x75,
+ 0xd6,0x12,0x07,0x3b,0x72,0x7f,0x0c,0x87,0xe7,0x01,0x80,0x7b,0x0b,0xb7,0x17,0x01,
+ 0x80,0x7a,0x0a,0xb1,0x27,0x01,0x7f,0x79,0x09,0xb1,0x87,0x3f,0x7f,0x78,0x08,0xb7,
+ 0x4e,0xa2,0x5e,0xa3,0x37,0x67,0xe7,0x1c,0x07,0xa7,0x00,0x9d,0xc4,0x60,0x66,0x75,
+ 0xd6,0x12,0x66,0x7f,0x0c,0x87,0x79,0x76,0x06,0xb7,0x17,0x01,0x79,0x76,0x06,0xb1,
+ 0x27,0x01,0x78,0x76,0x06,0xb1,0x87,0x3f,0x78,0x76,0x06,0xb7,0x6c,0x72,0x02,0xa6,
+ 0x6c,0x73,0x03,0xa7,0x87,0x3c,0x67,0x1e,0x6b,0x74,0x04,0xa6,0x06,0x3d,0x76,0x1e,
+ 0x6a,0x75,0x05,0xa7,0x87,0x3d,0x67,0x1e,0x71,0x76,0x06,0x86,0x76,0x05,0x70,0x73,
+ 0x36,0x0d,0x20,0xe0,0x70,0x74,0x64,0x0d,0x1d,0xe0,0x0b,0xa5,0x0a,0xa6,0x86,0x3c,
+ 0x56,0x1e,0x09,0xa5,0x05,0x3d,0x65,0x1e,0x08,0xa6,0x86,0x3d,0x56,0x1e,0x6a,0x75,
+ 0x05,0x85,0x65,0x05,0x35,0x0d,0x0e,0xe0,0x54,0x0d,0x0c,0xe0,0x68,0x76,0x06,0xa7,
+ 0x45,0x61,0x75,0x0c,0x04,0xe0,0x16,0x60,0x66,0x77,0x07,0xb6,0x1a,0xf0,0x07,0x20,
+ 0x06,0xb7,0x17,0xf0,0x06,0x60,0x61,0x75,0x05,0xb6,0x61,0x75,0x05,0xb6,0x5b,0x76,
+ 0x06,0x97,0x52,0x77,0x07,0xa6,0x52,0x77,0x07,0xa7,0x87,0x3c,0x67,0x1e,0x51,0x76,
+ 0x06,0xa6,0x06,0x3d,0x76,0x1e,0x50,0x77,0x07,0xa7,0x87,0x3d,0x67,0x1e,0x56,0x76,
+ 0x06,0x97,0x27,0x67,0xe7,0x1c,0x07,0xac,0x0c,0x2a,0x09,0xe0,0x56,0x77,0x07,0xa6,
+ 0x06,0x2a,0xd2,0xe8,0x15,0x60,0x54,0x76,0x36,0xb5,0x07,0xbc,0xcd,0xf0,0x1c,0x2a,
+ 0x09,0xe0,0x50,0x77,0x07,0xa6,0x26,0x2a,0xc7,0xe8,0x4f,0x76,0x36,0xbc,0x26,0x60,
+ 0x07,0xb6,0xc2,0xf0,0x2c,0x2a,0xc0,0xe0,0x4b,0x7b,0x0b,0xad,0x0d,0x2a,0x15,0xe0,
+ 0x4b,0x76,0x06,0xa7,0x27,0x2a,0x4a,0x77,0x0e,0xe0,0x36,0xa6,0x26,0x2a,0x0b,0xe8,
+ 0x07,0xc6,0x06,0x20,0x66,0x01,0x07,0xd6,0x55,0x60,0x65,0x0c,0xad,0xe0,0x07,0xdd,
+ 0x17,0x60,0x0b,0xb7,0xa9,0xf0,0x07,0xdd,0xa7,0xf0,0x1d,0x2a,0x94,0xe0,0x40,0x76,
+ 0x06,0xc7,0x07,0x20,0x67,0x01,0x06,0xd7,0x46,0x66,0x76,0x0c,0x85,0xe8,0x3d,0x77,
+ 0x06,0x60,0x97,0xb6,0x3d,0x76,0x07,0xb6,0x16,0x01,0x17,0xb1,0x26,0x01,0x27,0xb1,
+ 0x86,0x3f,0x37,0xb6,0x36,0x67,0x6e,0x1c,0x0e,0xa6,0x06,0x24,0x66,0x01,0xa7,0xb6,
+ 0x86,0x3e,0xb7,0xb6,0x36,0x7f,0x36,0x77,0x07,0xa6,0x17,0xa7,0x87,0x3c,0x67,0x1e,
+ 0x07,0x2a,0x34,0x77,0x6d,0xe0,0x07,0xc6,0x06,0x20,0x66,0x01,0x07,0xd6,0x57,0x60,
+ 0x67,0x0c,0x7a,0xe0,0x61,0xf0,0x00,0x00,0x36,0xe0,0x02,0x00,0xb4,0x00,0x00,0x00,
+ 0xb0,0x00,0x00,0x00,0x44,0xaa,0x00,0x00,0x58,0x07,0x00,0x00,0x7a,0x25,0x00,0x00,
+ 0xc0,0x2b,0x00,0x00,0x1c,0x9e,0x00,0x00,0x36,0x00,0x05,0x1a,0xb4,0x26,0x00,0x00,
+ 0x34,0x0a,0x04,0x00,0x46,0xa4,0x00,0x00,0x47,0xa4,0x00,0x00,0x48,0xa4,0x00,0x00,
+ 0x49,0xa4,0x00,0x00,0xb5,0x00,0x00,0x00,0xb6,0x00,0x00,0x00,0x4a,0xa4,0x00,0x00,
+ 0x4b,0xa4,0x00,0x00,0x4c,0xa4,0x00,0x00,0x4d,0xa4,0x00,0x00,0x52,0xa4,0x00,0x00,
+ 0x53,0xa4,0x00,0x00,0x54,0xa4,0x00,0x00,0x55,0xa4,0x00,0x00,0x56,0xa4,0x00,0x00,
+ 0x57,0xa4,0x00,0x00,0x58,0xa4,0x00,0x00,0x59,0xa4,0x00,0x00,0x4e,0xa4,0x00,0x00,
+ 0x4f,0xa4,0x00,0x00,0x50,0xa4,0x00,0x00,0x51,0xa4,0x00,0x00,0x4c,0xa6,0x00,0x00,
+ 0x39,0xff,0xff,0xff,0xc7,0x00,0x00,0x00,0x50,0xa6,0x00,0x00,0x54,0xa6,0x00,0x00,
+ 0x72,0xa4,0x00,0x00,0x63,0xa4,0x00,0x00,0x86,0x9e,0x00,0x00,0x66,0x9e,0x00,0x00,
+ 0x56,0xa6,0x00,0x00,0x7a,0x9e,0x00,0x00,0x00,0xe0,0x02,0x00,0x88,0x27,0x00,0x00,
+ 0x00,0x08,0x03,0x00,0x58,0xa6,0x00,0x00,0xad,0x77,0x37,0xbd,0x0b,0xbc,0x14,0xf0,
+ 0x06,0x60,0x07,0xd6,0x11,0xf0,0x2d,0x2a,0x0f,0xe0,0xa9,0x77,0x07,0xa6,0x37,0xa7,
+ 0x27,0x2a,0x02,0xe8,0x26,0x2a,0x08,0xe8,0x07,0x60,0xa6,0x76,0x06,0xd7,0x15,0x60,
+ 0xa3,0x76,0x36,0xb5,0xa5,0x76,0x06,0xb7,0xa1,0x77,0x37,0xa6,0x06,0x2a,0x1a,0xe8,
+ 0x06,0x60,0x37,0xb6,0xa1,0x76,0x06,0xa6,0x26,0x2a,0xa0,0x76,0x06,0x86,0x06,0xe0,
+ 0x38,0x67,0x86,0x1c,0x06,0xa6,0x07,0xb6,0x17,0xb6,0x0b,0xf0,0x65,0x67,0x65,0x1c,
+ 0x05,0xa5,0x07,0xb5,0x55,0x67,0x65,0x1c,0x05,0xa5,0x17,0xb5,0x4d,0x67,0xd6,0x1c,
+ 0x06,0xa6,0x27,0xb6,0x97,0x77,0x07,0xa5,0x97,0x76,0x06,0xb5,0x97,0x71,0x15,0x16,
+ 0x07,0xb5,0x92,0x75,0x05,0x85,0x29,0x64,0x59,0x1c,0x09,0xa4,0x04,0x2a,0x8e,0xe8,
+ 0x06,0xa8,0x06,0x60,0x92,0x7a,0x8b,0x64,0x5b,0x1c,0x9c,0x64,0x5c,0x1c,0x90,0x73,
+ 0x53,0x1c,0x90,0x72,0x02,0x1c,0x02,0x93,0x90,0x74,0x7f,0x12,0x41,0xf0,0xa7,0x12,
+ 0x67,0x1c,0x07,0xa2,0x27,0x12,0x87,0x16,0x07,0x2a,0x02,0xe8,0x0c,0xad,0x01,0xf0,
+ 0x0b,0xad,0x8a,0x73,0x63,0x1c,0x23,0xa7,0x63,0xa3,0xae,0x61,0xf1,0x11,0xe7,0x03,
+ 0xf9,0x11,0x37,0x1c,0x77,0x1c,0x86,0x73,0x73,0x1c,0x03,0xce,0xe3,0x12,0x73,0x01,
+ 0x3d,0x0d,0x04,0xe8,0x0f,0xa7,0x72,0x1e,0x0f,0xb2,0x20,0xf0,0x82,0x72,0x62,0x1c,
+ 0x02,0xad,0x0d,0x20,0x4d,0x01,0x02,0xbd,0x51,0x60,0xd1,0x0c,0x17,0xe0,0x0d,0x60,
+ 0x02,0xbd,0x78,0x7d,0x0d,0x1c,0x0d,0x8d,0x0d,0xa2,0x32,0x0d,0x04,0xe8,0x47,0x1c,
+ 0x07,0xc3,0x32,0x14,0x07,0xf0,0x2d,0x12,0x0d,0x28,0x47,0x1c,0xd3,0x0d,0x07,0xc3,
+ 0x03,0xe8,0x32,0x1c,0x07,0xd2,0x02,0xf0,0x3e,0x14,0x07,0xde,0x06,0x20,0x46,0x01,
+ 0x09,0xa7,0x76,0x0c,0xbc,0xef,0x3f,0x64,0xf5,0x1c,0x05,0xa7,0x37,0x2a,0x6b,0x7e,
+ 0x0e,0xe0,0x2e,0xa6,0x65,0x12,0x65,0x1c,0x65,0x1c,0x57,0x12,0x47,0x3c,0x57,0x1c,
+ 0x67,0x1c,0x69,0x71,0x17,0x1e,0x00,0x97,0x12,0x60,0x83,0x61,0x22,0xf0,0x47,0x2a,
+ 0x06,0xe0,0x6e,0xa7,0x97,0x21,0x77,0x1c,0x64,0x72,0x27,0x1e,0x17,0xf0,0x2e,0xa6,
+ 0x65,0x12,0x65,0x1c,0x65,0x1c,0x57,0x12,0x47,0x3c,0x57,0x1c,0x67,0x1c,0x5e,0x73,
+ 0x37,0x1e,0x00,0x97,0x12,0x60,0x83,0x61,0x84,0x60,0x05,0x60,0x56,0x12,0x57,0x12,
+ 0x5b,0x7f,0x6e,0xa7,0x97,0x21,0x77,0x1c,0x58,0x74,0x47,0x1e,0x00,0x97,0x42,0x62,
+ 0x13,0x60,0x84,0x60,0x05,0x60,0x56,0x12,0x57,0x12,0x54,0x7f,0x55,0x7f,0x55,0x7f,
+ 0x56,0x7f,0x09,0x60,0x56,0x7d,0x4e,0x7b,0x10,0xf2,0x97,0x12,0x97,0x1c,0x54,0x75,
+ 0x57,0x1c,0x27,0xae,0x54,0x76,0x76,0xbe,0x37,0xac,0x86,0xbc,0x56,0xa8,0x52,0x77,
+ 0x07,0x1c,0x07,0x98,0x8d,0xb8,0x66,0xa2,0x43,0x71,0x01,0x1c,0x01,0x92,0x9d,0xb2,
+ 0x17,0x60,0xad,0xb7,0xbd,0xb7,0x07,0x60,0x0d,0xb7,0x1d,0xb7,0x2d,0xb7,0x3d,0xb7,
+ 0xa8,0x61,0xf1,0x11,0xe8,0x03,0xf9,0x11,0x87,0x12,0xc7,0x1c,0x77,0x1c,0xb7,0x1c,
+ 0x07,0xa6,0x4d,0xb6,0x17,0xa7,0x5d,0xb7,0x6d,0xbe,0x7d,0xbc,0xe2,0x12,0xc3,0x12,
+ 0x43,0x7f,0xca,0x12,0x05,0xf0,0x0a,0x20,0x4a,0x01,0xe2,0x12,0xa3,0x12,0x3f,0x7f,
+ 0x87,0x12,0xa7,0x1c,0x07,0x20,0x77,0x1c,0xb7,0x1c,0x07,0xc6,0x76,0x01,0x3c,0x73,
+ 0x03,0xa5,0x3c,0x74,0x04,0xa7,0x87,0x3c,0x57,0x1e,0x76,0x0d,0x05,0xe0,0x29,0x75,
+ 0x05,0x1c,0x05,0x85,0xa5,0x0c,0xe7,0xe7,0x0d,0xa6,0x1d,0xa7,0x87,0x3c,0x67,0x1e,
+ 0xd7,0x1c,0x46,0x65,0x67,0x1c,0x07,0xba,0xca,0x12,0xa8,0x61,0xf1,0x11,0xe8,0x03,
+ 0xf9,0x11,0x05,0xf0,0x0a,0x24,0x4a,0x01,0xe2,0x12,0xa3,0x12,0x2c,0x7f,0x87,0x12,
+ 0xa7,0x1c,0x07,0x24,0x77,0x1c,0xb7,0x1c,0x07,0xc6,0x76,0x01,0x29,0x77,0x07,0xa5,
+ 0x29,0x71,0x01,0xa7,0x87,0x3c,0x57,0x1e,0x76,0x0d,0x02,0xe0,0x0a,0x2a,0xea,0xe7,
+ 0x0d,0xa6,0x1d,0xa7,0x87,0x3c,0x67,0x1e,0xd6,0x12,0x76,0x1c,0x05,0x63,0x65,0x1c,
+ 0x05,0xba,0xc6,0xbe,0x07,0x20,0x67,0x01,0x0d,0xb7,0x87,0x3e,0x1d,0xb7,0xc8,0x12,
+ 0xea,0x12,0x1d,0x72,0x02,0x1c,0x02,0x99,0xe9,0x12,0xbf,0xf0,0x86,0x9e,0x00,0x00,
+ 0x66,0x9e,0x00,0x00,0x56,0xa6,0x00,0x00,0x63,0xa4,0x00,0x00,0x1c,0x9e,0x00,0x00,
+ 0x2c,0xa4,0x00,0x00,0x2d,0xa4,0x00,0x00,0xf0,0xff,0xff,0xff,0x88,0x05,0x00,0x00,
+ 0xbb,0x00,0x00,0x00,0xb0,0x00,0x00,0x00,0x00,0xc0,0x02,0x00,0x20,0x9e,0x00,0x00,
+ 0x00,0xe0,0x02,0x00,0x5c,0xa6,0x00,0x00,0x00,0x00,0x05,0x1a,0xb4,0x26,0x00,0x00,
+ 0x00,0x28,0x00,0x00,0xf8,0x4c,0x00,0x00,0x80,0x4e,0x00,0x00,0x73,0xa4,0x00,0x00,
+ 0x8a,0x9e,0x00,0x00,0x7a,0x9e,0x00,0x00,0xb8,0x00,0x00,0x00,0xf8,0x3c,0x00,0x00,
+ 0x44,0xa4,0x00,0x00,0x45,0xa4,0x00,0x00,0xb4,0x00,0x00,0x00,0xa7,0x12,0x07,0x24,
+ 0xb7,0x73,0x03,0xa5,0xb7,0x74,0x04,0xa6,0x86,0x3c,0x56,0x1e,0xa5,0x61,0xf1,0x11,
+ 0x57,0x03,0xf9,0x11,0x87,0x1c,0x75,0x12,0x75,0x1c,0xb5,0x1c,0x05,0xc5,0x75,0x01,
+ 0x65,0x0d,0x12,0xe8,0x75,0x12,0x05,0x24,0x55,0x1c,0xb5,0x1c,0x05,0xc5,0x75,0x01,
+ 0x65,0x0d,0x98,0x00,0x08,0xe8,0x07,0x20,0x77,0x1c,0xb7,0x1c,0x07,0xc7,0x77,0x01,
+ 0x67,0x0d,0xef,0xe0,0x08,0x20,0x48,0x01,0x0a,0x24,0x4a,0x01,0xa2,0x12,0x83,0x12,
+ 0xa5,0x7f,0x8e,0x12,0xa7,0x61,0xf1,0x11,0xa7,0x03,0xf9,0x11,0xa3,0x76,0x06,0x1c,
+ 0x06,0x97,0x05,0xf0,0x0e,0x20,0x4e,0x01,0xa2,0x12,0xe3,0x12,0x9e,0x7f,0x9e,0x71,
+ 0x01,0x1c,0x01,0x87,0xe7,0x1c,0x07,0x20,0x77,0x1c,0xb7,0x1c,0x07,0xc6,0x76,0x01,
+ 0x97,0x72,0x02,0xa5,0x97,0x73,0x03,0xa7,0x87,0x3c,0x57,0x1e,0x76,0x0d,0x05,0xe0,
+ 0x97,0x74,0x04,0x1c,0x04,0x84,0xe4,0x0c,0xe5,0xe7,0x0d,0xa6,0x1d,0xa7,0x87,0x3c,
+ 0x67,0x1e,0xd7,0x1c,0x45,0x65,0x57,0x1c,0x07,0xbe,0x8e,0x12,0xa7,0x61,0xf1,0x11,
+ 0xa7,0x03,0xf9,0x11,0x8d,0x76,0x06,0x1c,0x06,0x97,0x05,0xf0,0x0e,0x24,0x4e,0x01,
+ 0xa2,0x12,0xe3,0x12,0x88,0x7f,0x88,0x71,0x01,0x1c,0x01,0x87,0xe7,0x1c,0x07,0x24,
+ 0x77,0x1c,0xb7,0x1c,0x07,0xc6,0x76,0x01,0x81,0x72,0x02,0xa5,0x81,0x73,0x03,0xa7,
+ 0x87,0x3c,0x57,0x1e,0x76,0x0d,0x02,0xe0,0x0e,0x2a,0xe8,0xe7,0x0d,0xa6,0x1d,0xa7,
+ 0x87,0x3c,0x67,0x1e,0xd6,0x12,0x76,0x1c,0x05,0x63,0x65,0x1c,0x05,0xbe,0xc6,0xba,
+ 0x07,0x20,0x67,0x01,0x0d,0xb7,0x87,0x3e,0x1d,0xb7,0x0a,0x2a,0x77,0xe7,0x9e,0x12,
+ 0x78,0x74,0x04,0x1c,0x04,0x89,0x89,0xf0,0xe7,0x12,0x07,0x20,0x70,0x76,0x06,0xa5,
+ 0x08,0xa6,0x86,0x3c,0x56,0x1e,0xaf,0x61,0xf1,0x11,0xf7,0x03,0xf9,0x11,0xc7,0x1c,
+ 0x75,0x12,0x75,0x1c,0xb5,0x1c,0x05,0xc5,0x75,0x01,0x65,0x0d,0x12,0xe8,0x75,0x12,
+ 0x05,0x24,0x55,0x1c,0xb5,0x1c,0x05,0xc5,0x75,0x01,0x65,0x0d,0x9c,0x00,0x08,0xe8,
+ 0x07,0x20,0x77,0x1c,0xb7,0x1c,0x07,0xc7,0x77,0x01,0x67,0x0d,0x6c,0xe0,0x0c,0x20,
+ 0x4c,0x01,0x0e,0x20,0x4e,0x01,0xe2,0x12,0xc3,0x12,0x5e,0x7f,0xca,0x12,0xa2,0x61,
+ 0xf1,0x11,0xe2,0x03,0xf9,0x11,0x5e,0x71,0x01,0x1c,0x01,0x92,0x05,0xf0,0x0a,0x20,
+ 0x4a,0x01,0xe2,0x12,0xa3,0x12,0x57,0x7f,0x5a,0x73,0x03,0x1c,0x03,0x87,0xa7,0x1c,
+ 0x07,0x20,0x77,0x1c,0xb7,0x1c,0x07,0xc6,0x76,0x01,0x50,0x74,0x04,0xa5,0x08,0xa7,
+ 0x87,0x3c,0x57,0x1e,0x76,0x0d,0x05,0xe0,0x51,0x75,0x05,0x1c,0x05,0x85,0xa5,0x0c,
+ 0xe6,0xe7,0x0d,0xa6,0x1d,0xa7,0x87,0x3c,0x67,0x1e,0xd7,0x1c,0x46,0x65,0x67,0x1c,
+ 0x07,0xba,0xca,0x12,0xaf,0x61,0xf1,0x11,0xef,0x03,0xf9,0x11,0x49,0x77,0x07,0x1c,
+ 0x07,0x9f,0x05,0xf0,0x0a,0x24,0x4a,0x01,0xe2,0x12,0xa3,0x12,0x42,0x7f,0x44,0x71,
+ 0x01,0x1c,0x01,0x87,0xa7,0x1c,0x07,0x24,0x77,0x1c,0xb7,0x1c,0x07,0xc6,0x76,0x01,
+ 0x3b,0x72,0x02,0xa5,0x08,0xa7,0x87,0x3c,0x57,0x1e,0x76,0x0d,0x02,0xe0,0x0a,0x2a,
+ 0xe9,0xe7,0x0d,0xa6,0x1d,0xa7,0x87,0x3c,0x67,0x1e,0xd6,0x12,0x76,0x1c,0x05,0x63,
+ 0x65,0x1c,0x05,0xba,0xc6,0xbe,0x07,0x20,0x67,0x01,0x0d,0xb7,0x87,0x3e,0x1d,0xb7,
+ 0x05,0xf0,0x9e,0x12,0x33,0x73,0x03,0x1c,0x03,0x89,0x2d,0x78,0x32,0x74,0x04,0x1c,
+ 0x04,0x84,0xe4,0x0c,0x71,0xe7,0x8d,0xa2,0x97,0x12,0x37,0x3c,0x97,0x05,0x2e,0x75,
+ 0x57,0x1c,0xa6,0x62,0x76,0x1c,0x06,0xb2,0x9d,0xa4,0xb6,0x62,0x76,0x1c,0x06,0xb4,
+ 0xad,0xaf,0xc6,0x62,0x76,0x1c,0x06,0xbf,0xbd,0xa3,0xd6,0x62,0x76,0x1c,0x06,0xb3,
+ 0xe6,0x62,0x76,0x1c,0x2d,0xa5,0x06,0xb5,0x86,0x62,0x67,0x1c,0x4d,0xa5,0x5d,0xa6,
+ 0x86,0x3c,0x56,0x1e,0x77,0xb6,0x86,0x3e,0x87,0xb6,0xf7,0x12,0x27,0x05,0x57,0x01,
+ 0x17,0x22,0x05,0xe8,0x37,0x12,0x47,0x05,0x57,0x01,0x17,0x22,0x0c,0xe0,0x95,0x12,
+ 0x95,0x1c,0x19,0x77,0x75,0x1c,0xf6,0x12,0x26,0x1c,0x16,0x3a,0x25,0xb6,0x37,0x12,
+ 0x47,0x1c,0x17,0x3a,0x35,0xb7,0x09,0x20,0x49,0x01,0x13,0x7c,0x0c,0xa7,0x1c,0xae,
+ 0x8e,0x3c,0x7e,0x1e,0xe9,0x0c,0xe9,0xed,0x02,0x12,0x72,0x20,0x03,0x60,0x44,0x61,
+ 0x0f,0x7f,0x1f,0x60,0xef,0x0c,0x68,0xe0,0x0c,0xa7,0x1c,0xa4,0x84,0x3c,0x74,0x1e,
+ 0x05,0x60,0x0b,0x7b,0xad,0x61,0x2e,0x60,0x5d,0xf0,0x00,0x00,0x44,0xa4,0x00,0x00,
+ 0x45,0xa4,0x00,0x00,0xf8,0x3c,0x00,0x00,0xbc,0x00,0x00,0x00,0xb0,0x00,0x00,0x00,
+ 0xb4,0x00,0x00,0x00,0xb8,0x00,0x00,0x00,0x8a,0x9e,0x00,0x00,0x22,0x83,0x00,0x00,
+ 0x00,0xe0,0x02,0x00,0x87,0x60,0x07,0x1c,0x57,0x1c,0x07,0xa7,0x07,0x2a,0x40,0xe0,
+ 0x56,0x12,0x56,0x1c,0xc6,0x1c,0x26,0xa7,0x36,0xaa,0x53,0x12,0x03,0x20,0x43,0x01,
+ 0x79,0x12,0x09,0x20,0xa6,0x12,0x56,0x01,0x57,0x01,0xf1,0x11,0xd7,0x03,0xf9,0x11,
+ 0x67,0x1c,0x77,0x1c,0xb7,0x1c,0x2a,0xf0,0x32,0x12,0x32,0x1c,0xc2,0x1c,0x22,0xa6,
+ 0x32,0xa8,0x92,0x12,0x62,0x05,0x42,0x01,0x2e,0x0c,0x1e,0xe8,0xa2,0x12,0x02,0x20,
+ 0x82,0x05,0x42,0x01,0x2e,0x0c,0x18,0xe8,0x58,0x01,0x56,0x01,0xf1,0x11,0xd6,0x03,
+ 0xf9,0x11,0x86,0x1c,0x66,0x1c,0xb6,0x1c,0x07,0xc2,0x72,0x01,0x06,0xc6,0x76,0x01,
+ 0x26,0x0d,0x05,0xe8,0x86,0x60,0x06,0x1c,0x36,0x1c,0x06,0xbf,0x05,0xf0,0x87,0x60,
+ 0x07,0x1c,0x57,0x1c,0x07,0xbf,0x04,0xf0,0x03,0x20,0x43,0x01,0x43,0x0c,0xd4,0xef,
+ 0x05,0x20,0x45,0x01,0x45,0x0c,0xb6,0xef,0x02,0x12,0x72,0x20,0xb0,0x73,0xb0,0x7f,
+ 0xb1,0x77,0x77,0xa7,0x07,0x2a,0x05,0xe8,0xb0,0x77,0x07,0x87,0x78,0x67,0x87,0x1c,
+ 0x11,0xf0,0xae,0x77,0x07,0xa7,0x07,0x2a,0x0c,0xe8,0xad,0x77,0x07,0xa7,0xad,0x76,
+ 0x06,0xae,0x8e,0x3c,0x7e,0x1e,0x2e,0x3e,0xac,0x77,0x17,0xa7,0x7e,0x0d,0x7e,0x02,
+ 0x02,0xf0,0xa9,0x77,0x07,0xae,0x02,0x12,0x72,0x20,0x03,0x60,0x44,0x61,0xa7,0x7f,
+ 0xa8,0x77,0x07,0xa7,0xa8,0x76,0x06,0xa5,0x85,0x3c,0x75,0x1e,0x06,0x60,0x9b,0x73,
+ 0x7e,0x01,0x14,0x60,0x12,0xf0,0x67,0x12,0x37,0x3c,0x67,0x05,0x37,0x1c,0x8d,0x62,
+ 0xd7,0x1c,0x77,0xa2,0x87,0xa7,0x87,0x3c,0x27,0x1e,0xe7,0x0d,0x04,0xe8,0x87,0x60,
+ 0x07,0x1c,0x67,0x1c,0x07,0xb4,0x06,0x20,0x46,0x01,0x56,0x0c,0xec,0xef,0x98,0x7c,
+ 0x02,0x12,0x72,0x20,0xc3,0x12,0x8e,0x7f,0x90,0x77,0x07,0x87,0x97,0x71,0x01,0x1c,
+ 0x01,0x97,0xf2,0x67,0x27,0x1c,0x07,0xa7,0x07,0x2a,0xf1,0xe8,0x02,0x12,0x72,0x20,
+ 0x03,0x60,0x44,0x61,0x8e,0x7f,0x8e,0x67,0x0e,0x1c,0xe2,0x12,0x03,0x60,0x44,0x63,
+ 0x8b,0x7f,0x4d,0x64,0x0d,0x1c,0xd2,0x12,0x03,0x60,0x44,0x63,0x88,0x7f,0x0c,0xa7,
+ 0x89,0x76,0x06,0xa4,0x84,0x3c,0x74,0x1e,0x07,0x60,0x7c,0x7a,0xeb,0x12,0xdc,0x12,
+ 0x7c,0xf0,0x86,0x65,0x76,0x1c,0x66,0x1c,0xa6,0x1c,0x86,0xa9,0x96,0xa6,0x93,0x12,
+ 0x03,0x24,0x43,0x01,0x05,0x60,0x09,0x20,0x62,0x12,0x02,0x24,0x02,0x01,0x7f,0x78,
+ 0x08,0x1c,0x08,0x91,0x12,0x20,0x7e,0x71,0x01,0x1c,0x01,0x92,0x1d,0xf0,0x7b,0x78,
+ 0x08,0x1c,0x08,0x82,0xa8,0x61,0xf1,0x11,0x38,0x03,0xf9,0x11,0x0e,0xf0,0x8f,0x12,
+ 0x2f,0x1c,0xff,0x1c,0x78,0x71,0x1f,0x1c,0x0f,0xcf,0xf1,0x12,0x71,0x01,0x01,0x22,
+ 0x02,0xe0,0xf5,0x1c,0x65,0x01,0x02,0x20,0x42,0x01,0x71,0x71,0x01,0x1c,0x01,0x81,
+ 0x21,0x0d,0xed,0xef,0x03,0x20,0x43,0x01,0x39,0x0d,0xe1,0xef,0x73,0x12,0x73,0x1c,
+ 0xc2,0x61,0x02,0x1c,0x23,0x1c,0x03,0xd5,0x63,0x12,0x63,0x1c,0xb3,0x1c,0x03,0xc2,
+ 0x72,0x01,0x59,0x12,0x79,0x01,0x92,0x0d,0x01,0xe8,0x03,0xd5,0x62,0x12,0x02,0x24,
+ 0x23,0x12,0x23,0x1c,0xe3,0x1c,0x03,0xcf,0x7f,0x01,0x9f,0x0d,0x01,0xe8,0x03,0xd5,
+ 0x63,0x12,0x03,0x20,0x3f,0x12,0x3f,0x1c,0xbf,0x1c,0x0f,0xc8,0x78,0x01,0x98,0x0d,
+ 0x01,0xe8,0x0f,0xd5,0x75,0x12,0x35,0x3c,0x75,0x05,0xa5,0x1c,0x88,0x62,0x85,0x1c,
+ 0x75,0xaf,0x85,0xa5,0x85,0x3c,0xf5,0x1e,0x66,0x1c,0xc6,0x1c,0x06,0xcf,0x7f,0x01,
+ 0x5f,0x0d,0x01,0xe8,0x06,0xd5,0x26,0x12,0x26,0x1c,0xd6,0x1c,0x06,0xc2,0x72,0x01,
+ 0x52,0x0d,0x01,0xe8,0x06,0xd5,0x36,0x12,0x36,0x1c,0xc6,0x1c,0x06,0xc3,0x73,0x01,
+ 0x53,0x0d,0x01,0xe8,0x06,0xd5,0x07,0x20,0x47,0x01,0x47,0x0c,0x82,0xef,0x4a,0x77,
+ 0x17,0xac,0x0c,0x20,0x0d,0x60,0x44,0x71,0x01,0x1c,0x01,0x8b,0x72,0x32,0x2b,0x1c,
+ 0x10,0xf0,0xde,0x12,0xde,0x1c,0x83,0x67,0x03,0x1c,0x3e,0x1c,0x0e,0xc2,0x72,0x01,
+ 0x0b,0xa7,0xf1,0x11,0x72,0x03,0xf9,0x11,0x43,0x66,0x40,0x7f,0x0e,0xd2,0x0d,0x20,
+ 0x4d,0x01,0xdc,0x0d,0xee,0xef,0x36,0x77,0x07,0xa7,0x36,0x76,0x06,0xa5,0x85,0x3c,
+ 0x75,0x1e,0x07,0x60,0x2a,0x72,0x1f,0x60,0x2c,0xf0,0x86,0x65,0x76,0x1c,0x66,0x1c,
+ 0x26,0x1c,0x96,0xa4,0x76,0x12,0x36,0x3c,0x76,0x05,0x26,0x1c,0x88,0x62,0x86,0x1c,
+ 0x76,0xa3,0x86,0xa6,0x86,0x3c,0x36,0x1e,0x44,0x1c,0x43,0x64,0x03,0x1c,0x43,0x1c,
+ 0x03,0xc3,0x73,0x01,0x13,0x3a,0x63,0x0d,0x12,0xe0,0x76,0x12,0x76,0x1c,0xcd,0x61,
+ 0x0d,0x1c,0xd6,0x1c,0x81,0x67,0x01,0x1c,0x14,0x1c,0x06,0xc3,0x73,0x01,0x04,0xc6,
+ 0x76,0x01,0x63,0x0d,0x04,0xe8,0x86,0x60,0x06,0x1c,0x76,0x1c,0x06,0xbf,0x07,0x20,
+ 0x47,0x01,0x57,0x0c,0xd2,0xef,0x02,0x12,0x72,0x20,0x19,0x73,0x11,0x7f,0x20,0x7f,
+ 0x12,0x77,0x07,0x87,0x20,0x72,0x27,0x1c,0x07,0xa7,0x07,0x2a,0x57,0xe8,0x1e,0x77,
+ 0x37,0xa7,0x27,0x2a,0x53,0xe0,0x10,0x77,0x07,0xae,0xee,0x1c,0x02,0x12,0x72,0x20,
+ 0x03,0x60,0x44,0x61,0x0e,0x7f,0x0e,0x77,0x07,0xa7,0x0e,0x76,0x06,0xa5,0x85,0x3c,
+ 0x75,0x1e,0x06,0x60,0x02,0x73,0x7e,0x01,0x14,0x60,0x3a,0xf0,0x8a,0x9e,0x00,0x00,
+ 0x00,0x2d,0x00,0x00,0x20,0xaa,0x00,0x00,0x1c,0x9e,0x00,0x00,0x4a,0xa0,0x00,0x00,
+ 0x3e,0xa4,0x00,0x00,0x3f,0xa4,0x00,0x00,0x86,0x9e,0x00,0x00,0x22,0x83,0x00,0x00,
+ 0x40,0x9f,0x00,0x00,0x41,0x9f,0x00,0x00,0xb0,0x00,0x00,0x00,0xb8,0x00,0x00,0x00,
+ 0xb4,0x00,0x00,0x00,0x00,0xe0,0x02,0x00,0x20,0x9e,0x00,0x00,0x3e,0x84,0x00,0x00,
+ 0x0e,0x46,0x00,0x00,0x86,0x00,0x00,0x00,0x66,0x9e,0x00,0x00,0x67,0x12,0x37,0x3c,
+ 0x67,0x05,0x37,0x1c,0x88,0x62,0x87,0x1c,0x77,0xa2,0x87,0xa7,0x87,0x3c,0x27,0x1e,
+ 0xe7,0x0d,0x04,0xe8,0x87,0x60,0x07,0x1c,0x67,0x1c,0x07,0xb4,0x06,0x20,0x46,0x01,
+ 0x56,0x0c,0xec,0xef,0x02,0x12,0x72,0x20,0xbd,0x73,0xbd,0x7f,0xbc,0x77,0x07,0xa7,
+ 0xbd,0x76,0x06,0xaf,0xbd,0x7d,0x0d,0x1c,0x8f,0x3c,0x7f,0x1e,0x0d,0x9f,0x0d,0xa2,
+ 0xbb,0x71,0x01,0x1c,0x01,0x92,0xba,0x77,0x07,0xb2,0x0d,0x60,0x0b,0xf1,0xd7,0x12,
+ 0x37,0x3c,0xd7,0x05,0xb8,0x73,0x37,0x1c,0xc6,0x62,0x76,0x1c,0x06,0xa5,0xa6,0x62,
+ 0x76,0x1c,0x06,0xa4,0xd6,0x62,0x76,0x1c,0x06,0xa6,0xb8,0x62,0x87,0x1c,0x07,0xa7,
+ 0x53,0x12,0x43,0x05,0x43,0x01,0x1f,0x60,0x3f,0x0c,0x35,0xe8,0x63,0x12,0x73,0x05,
+ 0x43,0x01,0x3f,0x0c,0x30,0xe8,0x87,0x65,0xd7,0x1c,0x77,0x1c,0xaa,0x71,0x17,0x1c,
+ 0x87,0xa7,0xfc,0x12,0x22,0x60,0x72,0x0c,0x03,0xe0,0x7c,0x12,0x0c,0x24,0x4c,0x01,
+ 0xa6,0x73,0x03,0xaa,0xa6,0x12,0x06,0x24,0x67,0x0d,0x03,0xe8,0x07,0x20,0x7a,0x12,
+ 0x4a,0x01,0x87,0x65,0xd7,0x1c,0x77,0x1c,0x9f,0x74,0x47,0x1c,0x97,0xa7,0x16,0x60,
+ 0x9f,0x75,0x05,0x1c,0x05,0x96,0x28,0x60,0x78,0x0c,0x04,0xe0,0x76,0x12,0x06,0x24,
+ 0x06,0x01,0x05,0x91,0x99,0x72,0x12,0xa9,0x96,0x12,0x06,0x24,0x67,0x0d,0x26,0xe8,
+ 0x07,0x20,0x79,0x12,0x22,0xf0,0x1c,0x60,0x23,0x60,0x43,0x0c,0x03,0xe0,0x04,0x24,
+ 0x4c,0x12,0x4c,0x01,0x91,0x74,0x04,0xaa,0xa4,0x12,0x04,0x24,0x45,0x0d,0x03,0xe8,
+ 0x05,0x20,0x5a,0x12,0x4a,0x01,0x18,0x60,0x8d,0x75,0x05,0x1c,0x05,0x98,0x2f,0x60,
+ 0x7f,0x0c,0x03,0xe0,0x07,0x24,0x07,0x01,0x05,0x91,0x87,0x72,0x12,0xa9,0x97,0x12,
+ 0x07,0x24,0x76,0x0d,0x03,0xe8,0x06,0x20,0x69,0x12,0x49,0x01,0x08,0x60,0x84,0x73,
+ 0x03,0x1c,0x03,0x98,0x84,0x74,0x04,0x1c,0x04,0x98,0xdb,0x12,0x35,0xf0,0x82,0x75,
+ 0x05,0x1c,0x05,0x87,0xd7,0x1c,0x77,0x1c,0x81,0x76,0x67,0x1c,0x07,0xce,0x7e,0x01,
+ 0x0e,0x22,0x24,0xe0,0xb2,0x12,0xc3,0x12,0xd4,0x12,0x7d,0x7f,0x72,0x01,0x2e,0x1b,
+ 0x7e,0x01,0x2e,0x3a,0x7c,0x71,0x01,0x1c,0x01,0x87,0xf1,0x11,0xe7,0x03,0xf9,0x11,
+ 0x74,0x72,0x02,0x1c,0x02,0x83,0x73,0x1c,0x72,0x72,0x02,0x1c,0x02,0x93,0xd7,0x12,
+ 0x17,0x3c,0x07,0x24,0x67,0x01,0xf1,0x11,0xe7,0x03,0xf9,0x11,0x6e,0x74,0x04,0x1c,
+ 0x04,0x85,0x75,0x1c,0x6c,0x74,0x04,0x1c,0x04,0x95,0xe8,0x1c,0x0d,0x20,0x4d,0x01,
+ 0xd9,0x0c,0xcd,0xe7,0x0c,0x20,0x4c,0x01,0xca,0x0c,0x12,0xe8,0xc7,0x12,0x17,0x3c,
+ 0x07,0x24,0x67,0x01,0x68,0x76,0x06,0x1c,0x06,0x97,0x60,0x77,0x07,0x1c,0x07,0x8d,
+ 0xa2,0x61,0xf1,0x11,0xc2,0x03,0xf9,0x11,0x60,0x71,0x01,0x1c,0x01,0x92,0xe8,0xf7,
+ 0xbd,0x12,0xbe,0x12,0x3e,0x3c,0xbe,0x1c,0x57,0x73,0x3e,0x1c,0x5f,0x74,0x4e,0x1c,
+ 0x59,0x75,0x05,0x1c,0x05,0x82,0x72,0x3c,0x83,0x12,0x5c,0x7f,0x62,0x01,0x4e,0xb2,
+ 0x82,0x3e,0x5e,0xb2,0x53,0x76,0x06,0x1c,0x06,0x82,0x72,0x3c,0x83,0x12,0x57,0x7f,
+ 0x62,0x01,0x6e,0xb2,0x27,0x12,0x87,0x3e,0x7e,0xb7,0x55,0x78,0x08,0x87,0x55,0x71,
+ 0x17,0x1c,0x07,0xa7,0x27,0x2a,0x06,0xe0,0x54,0x73,0x32,0x1c,0x62,0x01,0x6e,0xb2,
+ 0x82,0x3e,0x7e,0xb2,0xd5,0x12,0x35,0x3c,0x56,0x12,0xd6,0x1c,0x42,0x74,0x46,0x1c,
+ 0x4f,0x77,0x67,0x1c,0x04,0x2c,0x07,0xb4,0x48,0x77,0x76,0x1c,0xd5,0x05,0x3d,0x78,
+ 0x85,0x1c,0x87,0x62,0x57,0x1c,0x77,0xa4,0x87,0xa7,0x87,0x3c,0x47,0x1e,0x86,0xb7,
+ 0x87,0x3e,0x96,0xb7,0xef,0x62,0xf5,0x1c,0x05,0xa7,0xa6,0xb7,0x07,0x60,0xb6,0xb7,
+ 0x0d,0x20,0x4d,0x01,0x31,0x71,0x01,0x1c,0x01,0x81,0x1d,0x0c,0xf0,0xee,0x40,0x77,
+ 0x57,0xa7,0x07,0x2f,0x07,0x2a,0x31,0xe8,0x2d,0x72,0x02,0x1c,0x02,0x82,0x02,0x2a,
+ 0x05,0xe8,0x3c,0x72,0x2a,0x74,0x04,0x1c,0x04,0x83,0x3b,0x7f,0x0e,0x60,0x29,0x7d,
+ 0x28,0x7c,0x1c,0xf0,0xe7,0x12,0x37,0x3c,0xe7,0x1c,0xd7,0x1c,0x2f,0x75,0x57,0x1c,
+ 0x47,0xab,0x57,0xa3,0x83,0x3c,0x67,0xaf,0x77,0xa4,0x84,0x3c,0x87,0xa6,0x97,0xa5,
+ 0x85,0x3c,0x65,0x1e,0x05,0x3d,0xa7,0xa6,0xb7,0xa7,0x87,0x3c,0x30,0x72,0xb3,0x1e,
+ 0xf4,0x1e,0x05,0x3b,0x76,0x1e,0x2c,0x7f,0x0e,0x20,0x4e,0x01,0x0c,0xa7,0x7e,0x0c,
+ 0xe1,0xef,0x07,0x2a,0x02,0xe8,0x2a,0x72,0x28,0x7f,0x21,0x77,0x07,0x87,0x29,0x76,
+ 0x67,0x1c,0x07,0xa7,0x07,0x2a,0xa2,0xe8,0x22,0x77,0x57,0xa7,0x77,0x36,0x10,0xe8,
+ 0x26,0x77,0x07,0xa7,0x26,0x76,0x06,0xa6,0x86,0x3c,0x76,0x1e,0x25,0x77,0x07,0xa7,
+ 0x07,0x3d,0x67,0x1e,0x24,0x76,0x06,0xa3,0x83,0x3d,0x23,0x72,0x73,0x1e,0x1a,0x7f,
+ 0x14,0x77,0x07,0x87,0x1d,0x76,0x06,0xa6,0x1d,0x75,0x40,0xf0,0x40,0x9f,0x00,0x00,
+ 0x00,0x2d,0x00,0x00,0x41,0x9f,0x00,0x00,0xb0,0x00,0x00,0x00,0xb4,0x00,0x00,0x00,
+ 0x94,0x9f,0x00,0x00,0x8a,0x9e,0x00,0x00,0x20,0x9e,0x00,0x00,0xb8,0x00,0x00,0x00,
+ 0xbc,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0xc8,0x00,0x00,0x00,0x00,0xe0,0x02,0x00,
+ 0xe0,0x3d,0x00,0x00,0xc4,0x00,0x00,0x00,0x08,0x01,0x00,0x00,0xd0,0x83,0x00,0x00,
+ 0x1c,0x9e,0x00,0x00,0x20,0x01,0x00,0x00,0x80,0xff,0xff,0xff,0x0b,0x01,0x00,0x00,
+ 0x44,0xaa,0x00,0x00,0x68,0x07,0x00,0x00,0x7a,0x25,0x00,0x00,0x78,0x07,0x00,0x00,
+ 0x0c,0x07,0x00,0x00,0x8d,0x00,0x00,0x00,0x52,0xa4,0x00,0x00,0x53,0xa4,0x00,0x00,
+ 0x54,0xa4,0x00,0x00,0x55,0xa4,0x00,0x00,0x8c,0x07,0x00,0x00,0x05,0xa5,0x85,0x3c,
+ 0x65,0x1e,0xa6,0x76,0x06,0xa6,0x06,0x3d,0x56,0x1e,0xa5,0x75,0x05,0xa5,0x85,0x3d,
+ 0x65,0x1e,0xa4,0x76,0x76,0x1c,0x06,0xa4,0xa4,0x76,0x76,0x1c,0x06,0xa6,0x86,0x3c,
+ 0x46,0x1e,0xa2,0x74,0x74,0x1c,0x04,0xa4,0x04,0x3d,0x64,0x1e,0xa1,0x76,0x76,0x1c,
+ 0x06,0xa6,0x86,0x3d,0x46,0x1e,0x56,0x0c,0x9f,0x76,0x24,0xe8,0x07,0x60,0x06,0xb7,
+ 0x9e,0x76,0x0c,0xf0,0x9d,0x74,0x04,0xa5,0x05,0x20,0x45,0x01,0x04,0xb5,0x9b,0x78,
+ 0x87,0x1c,0x07,0xa7,0x27,0x3e,0x57,0x0c,0x02,0xe0,0x17,0x60,0x06,0xb7,0x95,0x77,
+ 0x07,0xa7,0x07,0x2a,0x97,0x77,0x02,0xe8,0xa6,0x60,0x04,0xf0,0x07,0xa6,0x06,0x2a,
+ 0x02,0xe8,0x06,0x24,0x07,0xb6,0x07,0xa7,0x07,0x2a,0x08,0xe8,0x16,0x60,0x91,0x77,
+ 0x07,0xb6,0x04,0xf0,0x06,0xa5,0x05,0x2a,0xdd,0xef,0xe9,0xf7,0x8f,0x71,0x10,0x1c,
+ 0x68,0x00,0xf0,0x21,0xcf,0x00,0xf0,0x25,0x78,0x00,0x01,0x64,0x10,0x05,0x8b,0x77,
+ 0x07,0xae,0x3c,0x60,0x0e,0x2a,0x03,0xe8,0xec,0x12,0x0c,0x24,0x4c,0x01,0x88,0x77,
+ 0x07,0xa5,0xa6,0x60,0x56,0x0c,0x01,0xe0,0x07,0xb6,0x0a,0x12,0x1a,0x21,0xa6,0x12,
+ 0x07,0x60,0x04,0x2c,0x75,0x12,0x06,0xd4,0x83,0x60,0x03,0x1c,0x73,0x1c,0x03,0xb5,
+ 0x07,0x20,0x16,0x20,0xa7,0x2a,0xf7,0xe7,0x6d,0x64,0xf1,0x11,0xde,0x03,0xf9,0x11,
+ 0x7d,0x72,0x7d,0x73,0xe3,0x1c,0xd4,0x12,0x7d,0x7f,0x7d,0x76,0xa6,0xa5,0xb6,0xa7,
+ 0x87,0x3c,0x57,0x1e,0x7c,0x71,0x71,0x1c,0x1f,0x12,0x7b,0x72,0x27,0x1c,0x7b,0x12,
+ 0x6b,0x01,0xc6,0xa5,0xd6,0xa7,0x87,0x3c,0x57,0x1e,0x76,0x72,0x72,0x1c,0x76,0x73,
+ 0x37,0x1c,0x79,0x12,0x69,0x01,0x05,0x60,0x75,0x73,0xf1,0x11,0xcd,0x03,0xf9,0x11,
+ 0xf8,0x67,0x57,0x12,0x37,0x1c,0x72,0x74,0x47,0x1c,0x07,0xa7,0x27,0x2a,0x45,0xe0,
+ 0x54,0x12,0x34,0x3c,0x54,0x05,0x47,0x12,0xe7,0x1c,0x37,0x1c,0x6e,0x76,0x67,0x1c,
+ 0x37,0xac,0x47,0xa6,0x86,0x3c,0xc6,0x1e,0x57,0xac,0x67,0xa7,0x87,0x3c,0xc7,0x1e,
+ 0x66,0x1c,0xd4,0x1c,0x34,0x1c,0x67,0x7c,0xc4,0x1c,0x34,0xa1,0x44,0xac,0x8c,0x3c,
+ 0x1c,0x1e,0xc6,0x05,0x66,0x01,0x77,0x1c,0x54,0xac,0x64,0xa4,0x84,0x3c,0xc4,0x1e,
+ 0x47,0x05,0x74,0x12,0x64,0x01,0x67,0x12,0x77,0x01,0x78,0x0d,0x03,0xe8,0xf7,0x0d,
+ 0x03,0xe8,0x03,0xf0,0x76,0x32,0x01,0xf0,0xb6,0x12,0x47,0x12,0x77,0x01,0x78,0x0d,
+ 0x03,0xe8,0x27,0x0d,0x03,0xe8,0x03,0xf0,0x74,0x32,0x01,0xf0,0x94,0x12,0x57,0x12,
+ 0x37,0x3c,0x57,0x05,0x37,0x1c,0x54,0x71,0x17,0x1c,0x66,0x01,0x57,0xb6,0x86,0x3e,
+ 0x67,0xb6,0x64,0x01,0x77,0xb4,0x84,0x3e,0x87,0xb4,0x05,0x20,0xa5,0x2a,0xb1,0xe7,
+ 0x0e,0x60,0x4a,0x78,0xa9,0x12,0x3f,0xf0,0xe7,0x12,0x37,0x3c,0xe7,0x1c,0x87,0x1c,
+ 0x4b,0x76,0x76,0x1c,0x46,0xa5,0x56,0xac,0x8c,0x3c,0x5c,0x1e,0x66,0xa5,0x76,0xab,
+ 0x8b,0x3c,0x5b,0x1e,0x3c,0x7a,0x0d,0x60,0x46,0x72,0x72,0x1c,0xb0,0x92,0x0d,0x01,
+ 0xa0,0x91,0x0a,0xa7,0x07,0x2a,0x21,0xe8,0xd7,0x12,0x37,0x3c,0xd7,0x05,0x87,0x1c,
+ 0x3e,0x72,0x27,0x1c,0x57,0xa6,0x67,0xa2,0x82,0x3c,0x62,0x1e,0xc2,0x14,0x77,0xa6,
+ 0x87,0xa3,0x83,0x3c,0x63,0x1e,0xb3,0x14,0x72,0x01,0x73,0x01,0x3a,0x7f,0xe7,0x12,
+ 0xe7,0x1c,0x23,0x61,0x03,0x1c,0x37,0x1c,0x07,0xc6,0x62,0x0c,0x06,0xe0,0x07,0xd2,
+ 0x84,0x62,0x04,0x1c,0x04,0xa5,0xb0,0x84,0x04,0xb5,0x0d,0x20,0x6a,0x20,0xad,0x2a,
+ 0xd6,0xe7,0x0e,0x20,0x4e,0x01,0x22,0x76,0x06,0xa2,0x2e,0x0c,0xbd,0xef,0x9a,0x12,
+ 0x2e,0x7d,0xd3,0x12,0x05,0x60,0x54,0x12,0x8b,0x2c,0x24,0x7e,0x0c,0x2c,0xe8,0x12,
+ 0x19,0x60,0x6a,0xf0,0x04,0x20,0x44,0x01,0x46,0x12,0x5a,0xf0,0x03,0xaf,0xbf,0x0f,
+ 0x59,0xe8,0x67,0x12,0x37,0x3c,0x67,0x1c,0xe7,0x1c,0x21,0x71,0x17,0x1c,0x07,0xa1,
+ 0xf1,0x0f,0x4c,0xe0,0x6f,0x12,0x6f,0x1c,0x21,0x61,0x01,0x1c,0x1f,0x1c,0x0a,0xc1,
+ 0x0f,0xcf,0x1f,0x0c,0x3b,0xe8,0x07,0xbc,0x41,0xf0,0x00,0x00,0x54,0xa4,0x00,0x00,
+ 0x55,0xa4,0x00,0x00,0x8e,0x00,0x00,0x00,0x8f,0x00,0x00,0x00,0x90,0x00,0x00,0x00,
+ 0x91,0x00,0x00,0x00,0x3c,0xa4,0x00,0x00,0x3d,0xa4,0x00,0x00,0xc6,0x00,0x00,0x00,
+ 0x60,0xa6,0x00,0x00,0x62,0xa4,0x00,0x00,0xd0,0x00,0x00,0x00,0xe5,0xa3,0x00,0x00,
+ 0x94,0x9f,0x00,0x00,0x46,0xa1,0x00,0x00,0x8c,0xa1,0x00,0x00,0x8c,0x82,0x00,0x00,
+ 0x20,0x9e,0x00,0x00,0x81,0xff,0xff,0xff,0x80,0xff,0xff,0xff,0x8a,0x9e,0x00,0x00,
+ 0x8e,0x05,0x00,0x00,0x00,0x03,0x00,0x00,0xb8,0x02,0x00,0x00,0x08,0x01,0x00,0x00,
+ 0x0b,0x01,0x00,0x00,0xc0,0x0c,0x00,0x00,0x95,0x9f,0x00,0x00,0x57,0x12,0x37,0x3c,
+ 0x57,0x1c,0x87,0x1c,0xbe,0x76,0x67,0x1c,0x07,0xbc,0x04,0xf0,0x06,0x20,0x46,0x01,
+ 0x26,0x0f,0xa4,0xe7,0x03,0xa7,0xb7,0x0f,0x04,0xe8,0x81,0x60,0x01,0x1c,0x17,0x1c,
+ 0x07,0xb9,0x05,0x20,0x83,0x20,0x1a,0x20,0x24,0x0f,0x94,0xe7,0xb5,0x77,0x07,0xac,
+ 0xb5,0x77,0x07,0xab,0xb5,0x74,0x05,0x60,0x56,0x12,0x8f,0x2c,0xb4,0x7e,0x12,0x60,
+ 0x24,0xf0,0x04,0xa7,0xf7,0x0f,0x1f,0xe0,0x57,0x12,0x37,0x3c,0x57,0x1c,0xe7,0x1c,
+ 0xb0,0x73,0x37,0x1c,0x87,0xa3,0x97,0xa7,0x87,0x3c,0x37,0x1e,0x07,0x3d,0x07,0x3b,
+ 0xb7,0x0d,0x11,0xe0,0x0e,0xf0,0x67,0x12,0x07,0x20,0x47,0x01,0x83,0x60,0x03,0x1c,
+ 0x63,0x1c,0x03,0xaa,0x0a,0x2a,0x04,0xe0,0x04,0xb6,0x03,0xb2,0x76,0x12,0x03,0xf0,
+ 0x76,0x12,0xc6,0x0c,0xf0,0xef,0x05,0x20,0x84,0x20,0x05,0x01,0xc1,0x0c,0xd9,0xef,
+ 0x0e,0x60,0xeb,0x12,0x8a,0x2c,0x9d,0x79,0x11,0xf0,0x0d,0xa7,0xa7,0x0f,0x0b,0xe8,
+ 0xe2,0x12,0x32,0x3c,0xe2,0x1c,0x92,0x1c,0x9b,0x74,0x42,0x1c,0xd3,0x12,0x94,0x60,
+ 0x9a,0x7f,0x0e,0x20,0x4e,0x01,0x0b,0x20,0x4b,0x01,0x8d,0x20,0xcb,0x0f,0xed,0xe7,
+ 0x97,0x77,0x07,0xbe,0x97,0x77,0x07,0xa8,0x97,0x76,0x06,0xb8,0x86,0x12,0x06,0x20,
+ 0x46,0x01,0x07,0xb6,0x35,0x60,0x65,0x0c,0x02,0xe0,0x06,0x60,0x07,0xb6,0x07,0xac,
+ 0x02,0x12,0x72,0x20,0x03,0x60,0xa4,0x60,0x90,0x7f,0x8c,0x77,0x07,0xab,0x8f,0x72,
+ 0x04,0x60,0x86,0x7d,0x63,0x64,0xf1,0x11,0xc3,0x03,0xf9,0x11,0x1e,0x60,0x2c,0xf0,
+ 0x02,0xaf,0xf7,0x12,0x37,0x3c,0xf7,0x05,0x37,0x1c,0xd7,0x1c,0x89,0x76,0x76,0x1c,
+ 0x06,0xbe,0x88,0x76,0x76,0x1c,0x47,0x12,0x37,0x3c,0x47,0x1c,0xd7,0x1c,0x86,0x79,
+ 0x97,0x1c,0x77,0xaa,0x87,0xa5,0x85,0x3c,0xa5,0x1e,0x36,0xb5,0x85,0x3e,0x46,0xb5,
+ 0x97,0xaa,0xa7,0xa5,0x85,0x3c,0xa5,0x1e,0x56,0xb5,0x85,0x3e,0x66,0xb5,0xb7,0xa5,
+ 0xc7,0xa7,0x87,0x3c,0x57,0x1e,0x76,0xb7,0x87,0x3e,0x86,0xb7,0x81,0x60,0x01,0x1c,
+ 0x1f,0x1c,0x0f,0xbe,0x04,0x20,0x82,0x20,0x04,0x01,0xb1,0x0c,0xd1,0xef,0x04,0x60,
+ 0x46,0x12,0x65,0x64,0xf1,0x11,0xc5,0x03,0xf9,0x11,0x68,0x7d,0x5f,0x12,0xdf,0x1c,
+ 0x0e,0x2c,0xf2,0x67,0x87,0x60,0x07,0x1c,0x67,0x1c,0x07,0xa3,0x03,0x2a,0x12,0xe0,
+ 0xf7,0x12,0x47,0x1c,0x6b,0x79,0x97,0x1c,0x07,0xb3,0x67,0x12,0x37,0x3c,0x67,0x05,
+ 0x57,0x1c,0xd7,0x1c,0x68,0x7b,0xb7,0x1c,0x37,0xbe,0x47,0xb2,0x57,0xbe,0x67,0xb2,
+ 0x77,0xb3,0x87,0xb3,0x06,0x20,0x64,0x20,0xa6,0x2a,0xe4,0xe7,0xcd,0x12,0x4d,0x3c,
+ 0xc7,0x12,0x67,0x3c,0x7d,0x1c,0x55,0x79,0x9d,0x1c,0x60,0x71,0x1d,0x1c,0x0b,0x60,
+ 0xba,0x12,0x62,0x64,0xf1,0x11,0xc2,0x03,0xf9,0x11,0xa0,0x92,0x92,0x1c,0xb0,0x92,
+ 0x63,0x64,0xf1,0x11,0x38,0x03,0xf9,0x11,0x94,0x12,0x84,0x1c,0xc0,0x94,0xb0,0x87,
+ 0xb7,0x1c,0x53,0x75,0x57,0x1c,0x07,0xa7,0x07,0x2a,0x52,0xe8,0xc0,0x87,0xb7,0x1c,
+ 0x57,0x1c,0x07,0xa7,0x07,0x2a,0x4c,0xe8,0x17,0x60,0x0d,0xb7,0xce,0x12,0xce,0x1c,
+ 0xc7,0x12,0x37,0x3c,0x7e,0x1c,0xae,0x1c,0x4e,0x76,0x6e,0x1c,0x3e,0x3c,0x9e,0x1c,
+ 0xa7,0x12,0x37,0x3c,0xa7,0x05,0xa0,0x86,0x76,0x1c,0x96,0x1c,0x46,0x71,0x16,0x1c,
+ 0x36,0xa4,0x46,0xa5,0x85,0x3c,0x45,0x1e,0x87,0x1c,0x97,0x1c,0x17,0x1c,0x37,0xa3,
+ 0x47,0xa4,0x84,0x3c,0x34,0x1e,0x45,0x05,0x65,0x01,0x3e,0xb5,0x85,0x3e,0x4e,0xb5,
+ 0x56,0xa5,0x66,0xa3,0x83,0x3c,0x53,0x1e,0x57,0xa6,0x67,0xa7,0x87,0x3c,0x67,0x1e,
+ 0x73,0x05,0x63,0x01,0x5e,0xb3,0x37,0x12,0x87,0x3e,0x6e,0xb7,0x3e,0xa7,0x4e,0xa2,
+ 0x82,0x3c,0x72,0x1e,0x02,0x3d,0x02,0x3b,0x73,0x01,0x36,0x7f,0x7e,0xb2,0x82,0x3e,
+ 0x8e,0xb2,0x3e,0xa7,0x4e,0xa2,0x82,0x3c,0x72,0x1e,0x02,0x3d,0x5e,0xa7,0x6e,0xa3,
+ 0x83,0x3c,0x73,0x1e,0x03,0x3d,0x02,0x3b,0x03,0x3b,0x2f,0x7f,0x7d,0xb2,0x12,0xf0,
+ 0x06,0x60,0x0d,0xb6,0xc7,0x12,0xc7,0x1c,0xc5,0x12,0x35,0x3c,0x57,0x1c,0xa7,0x1c,
+ 0x28,0x72,0x27,0x1c,0x37,0x3c,0x97,0x1c,0x37,0xb6,0x47,0xb6,0x57,0xb6,0x67,0xb6,
+ 0x77,0xb6,0x87,0xb6,0x0a,0x20,0x6b,0x20,0x7d,0x20,0x63,0x64,0x3b,0x0f,0x8f,0xe7,
+ 0x18,0x77,0x07,0xae,0x22,0x77,0x07,0x8c,0x22,0x78,0xa0,0x98,0x22,0x76,0x87,0x12,
+ 0x05,0x60,0x0e,0x73,0x29,0x60,0x6f,0x64,0xe4,0x12,0xf1,0x11,0xf4,0x03,0xf9,0x11,
+ 0x43,0x1c,0x1d,0x7a,0xca,0x1c,0x4b,0x60,0x54,0x12,0x1c,0x71,0x1c,0x1c,0x1d,0x60,
+ 0x07,0xa2,0x42,0x2a,0x35,0xe0,0x07,0xb4,0x56,0xf0,0x00,0x00,0x0b,0x01,0x00,0x00,
+ 0x94,0x9f,0x00,0x00,0x86,0x9e,0x00,0x00,0x95,0x9f,0x00,0x00,0x8a,0x9e,0x00,0x00,
+ 0x08,0x01,0x00,0x00,0x66,0x01,0x00,0x00,0x8c,0x82,0x00,0x00,0xef,0x9f,0x00,0x00,
+ 0xe5,0xa3,0x00,0x00,0xe4,0xa3,0x00,0x00,0xc4,0x09,0x00,0x00,0xf0,0x9f,0x00,0x00,
+ 0x02,0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x60,0x01,0x00,0x00,0x1a,0x04,0x00,0x00,
+ 0x83,0x00,0x00,0x00,0xc0,0x0c,0x00,0x00,0xee,0x0b,0x00,0x00,0x1c,0x9e,0x00,0x00,
+ 0xfa,0xa3,0x00,0x00,0x0e,0xa4,0x00,0x00,0xa1,0x00,0x00,0x00,0xa2,0x00,0x00,0x00,
+ 0x02,0x2a,0x19,0xe0,0x32,0x12,0x52,0x1c,0xb8,0x78,0x82,0x1c,0x02,0xa2,0x02,0x2a,
+ 0x0e,0xe8,0x06,0xa2,0x02,0x2a,0x03,0xe0,0x78,0x12,0x98,0x24,0x08,0xbe,0x02,0x20,
+ 0x42,0x01,0x06,0xb2,0x0c,0xa8,0x28,0x0c,0x19,0xe0,0x07,0xbd,0x17,0xf0,0x07,0xb2,
+ 0x06,0xb2,0xa7,0xb2,0x13,0xf0,0x07,0xb9,0x32,0x12,0x52,0x1c,0xab,0x71,0x12,0x1c,
+ 0x02,0xa2,0x02,0x2a,0x03,0xe8,0x06,0xb4,0xa7,0xb4,0x08,0xf0,0xa7,0xa2,0x02,0x20,
+ 0x42,0x01,0xa7,0xb2,0x0a,0xa8,0x28,0x0c,0x01,0xe0,0x07,0xbb,0x07,0x20,0x06,0x20,
+ 0x65,0x20,0xf5,0x0f,0x95,0xe7,0xa1,0x76,0x06,0x87,0xa2,0x64,0x27,0x1c,0x07,0xac,
+ 0x0e,0x60,0x9f,0x7b,0x87,0xf0,0xb7,0x12,0xe7,0x1c,0x9e,0x73,0x37,0x1c,0x07,0xa7,
+ 0x07,0x2a,0x05,0xe8,0x0e,0x20,0x4e,0x01,0x6e,0x0c,0xf5,0xef,0x7b,0xf0,0x26,0x60,
+ 0x98,0x7d,0xb7,0x12,0xc7,0x1c,0x97,0x74,0x47,0x1c,0x07,0xa5,0x05,0x24,0x45,0x01,
+ 0x56,0x0c,0x6c,0xe8,0xd6,0x12,0xe6,0x1c,0x46,0x1c,0x15,0x60,0x06,0xb5,0x46,0x60,
+ 0x07,0xb6,0xe8,0x12,0x38,0x3c,0xb0,0x98,0x82,0x12,0xe2,0x05,0xd2,0x1c,0xc8,0x12,
+ 0x38,0x3c,0x89,0x12,0xc9,0x05,0xd3,0x12,0x93,0x1c,0x8b,0x71,0x12,0x1c,0x13,0x1c,
+ 0x74,0x60,0x8a,0x7f,0x9d,0x1c,0x84,0x72,0x2d,0x1c,0x0a,0x60,0xc0,0x98,0x09,0x28,
+ 0xd0,0x99,0xb0,0x89,0xb8,0x12,0x98,0x1c,0xb0,0x98,0xd0,0x82,0xd2,0x1c,0x97,0x12,
+ 0xe7,0x05,0x72,0x1c,0xd3,0x12,0x74,0x60,0x81,0x7f,0x7d,0x78,0xb0,0x82,0xa2,0x1c,
+ 0xc0,0x83,0xb3,0x1c,0xa3,0x1c,0x7e,0x71,0x12,0x1c,0x13,0x1c,0x84,0x60,0x7b,0x7f,
+ 0x07,0x60,0x0d,0xb7,0x62,0x64,0x2d,0x1c,0x03,0x65,0x3a,0x1c,0x7a,0x74,0x4a,0x0f,
+ 0xe4,0xe7,0x87,0x12,0xc7,0x1c,0x78,0x76,0x76,0x1c,0x06,0xa5,0xe8,0x1c,0x76,0x76,
+ 0x86,0x1c,0x06,0xb5,0x76,0x76,0x76,0x1c,0x06,0xa5,0x74,0x76,0x86,0x1c,0x06,0xb5,
+ 0x74,0x76,0x76,0x1c,0x06,0xa5,0x72,0x76,0x86,0x1c,0x06,0xb5,0x72,0x76,0x76,0x1c,
+ 0x06,0xa5,0x70,0x76,0x86,0x1c,0x06,0xb5,0x70,0x76,0x76,0x1c,0x06,0xa5,0x6e,0x76,
+ 0x86,0x1c,0x06,0xb5,0x6e,0x76,0x76,0x1c,0x06,0xa5,0x6c,0x76,0x86,0x1c,0x06,0xb5,
+ 0x6c,0x75,0x57,0x1c,0x07,0xa7,0x58,0x1c,0x08,0xb7,0x04,0xf0,0x0c,0x20,0x4c,0x01,
+ 0xac,0x2a,0x86,0xe7,0x5a,0x76,0x06,0x87,0xa8,0x64,0x87,0x1c,0x07,0xa6,0x6e,0x0c,
+ 0x03,0xe0,0x97,0x60,0xc7,0x0c,0x6f,0xe7,0x56,0x76,0x62,0x77,0x07,0xa3,0x62,0x77,
+ 0x07,0xa7,0x69,0x64,0x71,0x12,0xf1,0x11,0x91,0x03,0xf9,0x11,0x62,0x12,0x12,0x1c,
+ 0x4e,0x7b,0xb2,0x1c,0x7a,0x12,0x4a,0x3c,0x75,0x12,0x65,0x3c,0x5a,0x1c,0xa6,0x1c,
+ 0x50,0x7c,0xc6,0x1c,0x05,0x60,0xf1,0x11,0x39,0x03,0xf9,0x11,0x0a,0x28,0x3d,0x12,
+ 0x4d,0x3c,0x34,0x12,0x64,0x3c,0x4d,0x1c,0x46,0x7e,0x54,0x12,0xe4,0x1c,0x45,0x78,
+ 0x84,0x1c,0x04,0xa4,0x14,0x24,0x44,0x01,0x1b,0x60,0x4b,0x0c,0x5c,0xe8,0x02,0xa4,
+ 0x04,0x2a,0x59,0xe0,0x24,0x60,0x02,0xb4,0x5c,0x12,0x3c,0x3c,0x5c,0x05,0xc4,0x12,
+ 0x94,0x1c,0xe4,0x1c,0x4a,0x78,0x84,0x1c,0x34,0xa8,0x44,0xaf,0x8f,0x3c,0x8f,0x1e,
+ 0x1c,0x1c,0xec,0x1c,0x46,0x78,0x8c,0x1c,0x3c,0xbf,0x8f,0x3e,0x4c,0xbf,0x54,0xaf,
+ 0x64,0xa4,0x84,0x3c,0xf4,0x1e,0x5c,0xb4,0x84,0x3e,0x6c,0xb4,0x04,0x67,0x7c,0xb4,
+ 0x34,0x60,0x8c,0xb4,0x34,0x12,0x34,0x1c,0x3f,0x12,0x3f,0x3c,0xf4,0x1c,0x54,0x1c,
+ 0x3c,0x7c,0xc4,0x1c,0x34,0x3c,0xe4,0x1c,0x74,0xac,0x84,0xaf,0x8f,0x3c,0xcf,0x1e,
+ 0xfc,0x63,0x06,0xbb,0xfc,0x0c,0x34,0xaf,0x44,0xac,0x8c,0x3c,0xfc,0x1e,0x7f,0x12,
+ 0x7f,0x1c,0x7b,0x12,0x3b,0x3c,0xbf,0x1c,0x5f,0x1c,0x03,0xe8,0x31,0x78,0x8f,0x1c,
+ 0x02,0xf0,0x2f,0x7b,0xbf,0x1c,0x3f,0x3c,0xef,0x1c,0x3f,0xbc,0x8c,0x3e,0x4f,0xbc,
+ 0x54,0xac,0x64,0xae,0x8e,0x3c,0xce,0x1e,0x5f,0xbe,0x8e,0x3e,0x6f,0xbe,0x74,0xae,
+ 0x84,0xa4,0x84,0x3c,0xe4,0x1e,0x7f,0xb4,0x84,0x3e,0x8f,0xb4,0xa4,0x12,0x64,0x1c,
+ 0xd4,0x1c,0x74,0xa4,0x76,0xb4,0x05,0x20,0x62,0x20,0x76,0x20,0xa5,0x2a,0x94,0xe7,
+ 0x04,0x60,0x0f,0x7e,0x6c,0x64,0x7a,0x12,0xf1,0x11,0xca,0x03,0xf9,0x11,0x42,0x12,
+ 0x3b,0x60,0x46,0x12,0xe6,0x1c,0x0b,0x75,0x65,0x1c,0x05,0xa5,0x15,0x2a,0x5f,0xe0,
+ 0x0f,0x71,0x16,0x1c,0x06,0xa5,0x4d,0x12,0x3d,0x3c,0x4d,0x05,0xd3,0x12,0xa3,0x1c,
+ 0xe3,0x1c,0x12,0x76,0x63,0x1c,0x51,0xf0,0x02,0x03,0x00,0x00,0x1c,0x9e,0x00,0x00,
+ 0x8a,0x9e,0x00,0x00,0x70,0x05,0x00,0x00,0x76,0x02,0x00,0x00,0x8c,0x82,0x00,0x00,
+ 0x1a,0x04,0x00,0x00,0x40,0x01,0x00,0x00,0x5c,0x05,0x00,0x00,0x66,0x05,0x00,0x00,
+ 0x7a,0x05,0x00,0x00,0x84,0x05,0x00,0x00,0x8e,0x05,0x00,0x00,0x98,0x05,0x00,0x00,
+ 0xa7,0x05,0x00,0x00,0xe4,0xa3,0x00,0x00,0xe5,0xa3,0x00,0x00,0x00,0x03,0x00,0x00,
+ 0x83,0x00,0x00,0x00,0x33,0xa6,0x43,0xaf,0x8f,0x3c,0x6f,0x1e,0x56,0x12,0xf1,0x11,
+ 0xc6,0x03,0xf9,0x11,0xd6,0x1c,0xe6,0x1c,0xc0,0x78,0x86,0x1c,0x36,0xbf,0x8f,0x3e,
+ 0x46,0xbf,0x53,0xa9,0x63,0xaf,0x8f,0x3c,0x9f,0x1e,0x56,0xbf,0x8f,0x3e,0x66,0xbf,
+ 0x56,0x12,0x56,0x1c,0x5f,0x12,0x3f,0x3c,0xf6,0x1c,0x46,0x1c,0xb8,0x79,0x96,0x1c,
+ 0x36,0x3c,0xe6,0x1c,0x36,0xb2,0x46,0xb2,0x56,0xb2,0x66,0xb2,0x76,0xb2,0x86,0xb2,
+ 0x96,0xb2,0x05,0x20,0x45,0x01,0x5b,0x0c,0xd5,0x01,0x75,0x0f,0xd3,0xe7,0x04,0x20,
+ 0xa4,0x2a,0x97,0xe7,0xaf,0x75,0x06,0x60,0x64,0x12,0x2b,0x60,0xae,0x7e,0x3c,0x60,
+ 0x6d,0x12,0x6f,0x64,0xf1,0x11,0x7f,0x03,0xf9,0x11,0x06,0x01,0x57,0x12,0x37,0x21,
+ 0x07,0xa7,0x73,0x12,0x03,0x24,0x43,0x01,0x3b,0x0c,0x3b,0xe8,0x17,0x2a,0x43,0x12,
+ 0x33,0x3c,0x43,0x1c,0xe3,0x1c,0xa4,0x77,0x37,0x1c,0x07,0xb1,0x0a,0xe0,0xa3,0x71,
+ 0x13,0x1c,0x67,0x12,0x37,0x3c,0x67,0x05,0xf7,0x1c,0xe7,0x1c,0x9b,0x72,0x27,0x1c,
+ 0x09,0xf0,0x9e,0x77,0x73,0x1c,0x67,0x12,0x37,0x3c,0x67,0x05,0xf7,0x1c,0xe7,0x1c,
+ 0x96,0x78,0x87,0x1c,0x37,0xaa,0x47,0xa2,0x82,0x3c,0xa2,0x1e,0x53,0xb2,0x82,0x3e,
+ 0x63,0xb2,0x57,0xaa,0x67,0xa2,0x82,0x3c,0xa2,0x1e,0x73,0xb2,0x82,0x3e,0x83,0xb2,
+ 0x77,0xa2,0x87,0xa7,0x87,0x3c,0x27,0x1e,0x93,0xb7,0x87,0x3e,0xa3,0xb7,0xa5,0xa7,
+ 0x05,0xb7,0x07,0x20,0x47,0x01,0xa5,0xb7,0x7c,0x0c,0x01,0xe0,0xa5,0xbd,0x04,0x20,
+ 0x44,0x01,0x06,0x20,0x05,0x20,0xa6,0x2a,0xb8,0xe7,0x89,0x77,0x07,0xb4,0x89,0x7d,
+ 0x0e,0x60,0x84,0x7c,0x6b,0x64,0xe7,0x12,0xc7,0x1c,0x87,0x76,0x76,0x1c,0x06,0xa6,
+ 0x16,0x2a,0x10,0xe0,0x86,0x79,0x97,0x1c,0x07,0xa7,0xe3,0x12,0x33,0x3c,0xe3,0x05,
+ 0xf1,0x11,0xb7,0x03,0xf9,0x11,0x73,0x1c,0xc3,0x1c,0xd2,0x12,0x81,0x71,0x13,0x1c,
+ 0x74,0x60,0x80,0x7f,0x0e,0x20,0x6d,0x20,0xae,0x2a,0xe5,0xe7,0x7f,0x7e,0x0d,0x60,
+ 0x19,0x60,0xd8,0x12,0x74,0x7c,0x7d,0x7b,0xe7,0x12,0xd7,0x25,0x07,0xa7,0x76,0x12,
+ 0x16,0x24,0x46,0x01,0x69,0x0c,0x73,0xe8,0x7a,0x72,0x02,0xaa,0x7a,0x73,0x03,0xa7,
+ 0xd5,0x12,0x35,0x3c,0xd5,0x05,0x64,0x64,0xa6,0x12,0xf1,0x11,0x46,0x03,0xf9,0x11,
+ 0x56,0x1c,0xc6,0x1c,0x65,0x71,0x16,0x1c,0x36,0xa3,0x46,0xa2,0x82,0x3c,0x32,0x1e,
+ 0xf1,0x11,0x47,0x03,0xf9,0x11,0x57,0x1c,0xc7,0x1c,0x17,0x1c,0x37,0xa4,0x47,0xa5,
+ 0x85,0x3c,0x45,0x1e,0x52,0x05,0x56,0xa5,0x66,0xa3,0x83,0x3c,0x53,0x1e,0x57,0xa6,
+ 0x67,0xa7,0x87,0x3c,0x67,0x1e,0x73,0x05,0x72,0x01,0x73,0x01,0x67,0x7f,0x72,0x01,
+ 0x0b,0x87,0x66,0x76,0x76,0x1c,0x06,0xa6,0x66,0x73,0x37,0x1c,0x07,0xa7,0x87,0x3c,
+ 0x67,0x1e,0x27,0x0d,0x03,0xe8,0x27,0x60,0x0e,0xb7,0x04,0xf0,0x0e,0xa7,0x27,0x2a,
+ 0x01,0xe0,0x0e,0xb9,0x0e,0xa7,0x07,0x2a,0x37,0xe0,0xd6,0x12,0x36,0x3c,0xd6,0x05,
+ 0x67,0x64,0xf1,0x11,0xa7,0x03,0xf9,0x11,0x67,0x1c,0xc7,0x1c,0x47,0x74,0x47,0x1c,
+ 0x37,0xa5,0x47,0xa2,0x82,0x3c,0x52,0x1e,0xc6,0x1c,0x56,0x75,0x56,0x1c,0x76,0xa4,
+ 0x86,0xa5,0x85,0x3c,0x45,0x1e,0x52,0x05,0x57,0xa5,0x67,0xa3,0x83,0x3c,0x53,0x1e,
+ 0x96,0xa5,0xa6,0xa7,0x87,0x3c,0x57,0x1e,0x73,0x05,0x72,0x01,0x73,0x01,0x4a,0x7f,
+ 0x72,0x01,0x0b,0x87,0x4a,0x76,0x76,0x1c,0x06,0xa6,0x49,0x71,0x17,0x1c,0x07,0xa7,
+ 0x87,0x3c,0x67,0x1e,0x27,0x0d,0x08,0xe8,0x17,0x60,0x0e,0xb7,0x05,0xf0,0x17,0x2a,
+ 0x02,0xe8,0x47,0x2a,0x01,0xe0,0x0e,0xb8,0x0d,0x20,0x0e,0x20,0xad,0x2a,0x7c,0xe7,
+ 0x42,0x7f,0x3a,0x77,0x07,0x87,0xb0,0x97,0x41,0x72,0x27,0x1c,0x07,0xa7,0x07,0x2a,
+ 0x06,0xe9,0x38,0x77,0x07,0xac,0x36,0x77,0x07,0xa7,0x76,0x12,0x46,0x3c,0x75,0x12,
+ 0x65,0x3c,0x56,0x1c,0x3b,0x7b,0x6b,0x1c,0x3b,0x7a,0x09,0x60,0x78,0x12,0x78,0x1c,
+ 0x37,0x3c,0x78,0x1c,0xc0,0x98,0x06,0x28,0xe0,0x96,0xc8,0x12,0x48,0x3c,0xc7,0x12,
+ 0x67,0x3c,0x78,0x1c,0xd0,0x98,0xa0,0x88,0x08,0xa7,0x17,0x24,0x47,0x01,0x1d,0x60,
+ 0x7d,0x0c,0xcb,0xe8,0x0a,0xa7,0x07,0x2a,0x76,0xe0,0x0b,0xa7,0x07,0x2a,0xc5,0xe8,
+ 0x19,0x7e,0xc0,0x87,0x97,0x1c,0x15,0x71,0x17,0x1c,0x37,0x3c,0xe7,0x1c,0x77,0xa6,
+ 0x87,0xa2,0x82,0x3c,0x62,0x1e,0xb0,0x87,0x28,0x73,0x37,0x1c,0x07,0xa6,0xb0,0x87,
+ 0x27,0x74,0x47,0x1c,0x07,0xa7,0x87,0x3c,0x67,0x1e,0x27,0x0c,0xae,0xe0,0xe0,0x87,
+ 0xb7,0x1c,0xd0,0x88,0x87,0x1c,0x07,0xa7,0x07,0x2a,0xa7,0xe8,0xb0,0x87,0x20,0x71,
+ 0x17,0x1c,0x07,0xa3,0x20,0x7f,0x62,0x01,0xc7,0x12,0xc7,0x1c,0xc6,0x12,0x36,0x3c,
+ 0x67,0x1c,0x97,0x1c,0x02,0x73,0x38,0xf0,0x00,0x03,0x00,0x00,0x83,0x00,0x00,0x00,
+ 0xe6,0xa3,0x00,0x00,0x8a,0x9e,0x00,0x00,0x1c,0x02,0x00,0x00,0x18,0x02,0x00,0x00,
+ 0xa5,0xa0,0x00,0x00,0x00,0xa1,0x00,0x00,0x70,0x05,0x00,0x00,0x5c,0x05,0x00,0x00,
+ 0x02,0x03,0x00,0x00,0x8c,0x82,0x00,0x00,0x18,0xa4,0x00,0x00,0x1c,0x9e,0x00,0x00,
+ 0xe5,0xa3,0x00,0x00,0xe4,0xa3,0x00,0x00,0xc0,0x0c,0x00,0x00,0xae,0x00,0x00,0x00,
+ 0xaf,0x00,0x00,0x00,0x70,0x02,0x00,0x00,0x34,0x47,0x00,0x00,0xaa,0x00,0x00,0x00,
+ 0xa4,0xa2,0x00,0x00,0x22,0xa4,0x00,0x00,0xac,0x00,0x00,0x00,0xad,0x00,0x00,0x00,
+ 0xab,0x00,0x00,0x00,0x3e,0x84,0x00,0x00,0x37,0x1c,0x37,0x3c,0xe7,0x1c,0x77,0xa6,
+ 0x87,0xa7,0x87,0x3c,0x67,0x1e,0x26,0x12,0xd6,0x0b,0x67,0x0c,0x53,0xe8,0x27,0x0c,
+ 0x4e,0xe0,0x0a,0xbd,0x52,0xf0,0x17,0x2a,0x50,0xe0,0x0b,0xa7,0x07,0x2a,0x4d,0xe8,
+ 0xae,0x77,0xc0,0x8d,0x9d,0x1c,0xad,0x71,0x1d,0x1c,0x3d,0x3c,0x7d,0x1c,0x7d,0xa6,
+ 0x8d,0xa8,0x88,0x3c,0x68,0x1e,0xce,0x12,0xce,0x1c,0xc6,0x12,0x36,0x3c,0x6e,0x1c,
+ 0x9e,0x1c,0x1e,0x1c,0x3e,0x3c,0x7e,0x1c,0x7e,0xa2,0x8e,0xa6,0x86,0x3c,0xb0,0x87,
+ 0xa4,0x73,0x37,0x1c,0x62,0x1e,0x07,0xa3,0xa3,0x7f,0x62,0x01,0x28,0x0c,0x2a,0xe8,
+ 0x3e,0xa7,0x4e,0xa5,0x85,0x3c,0x75,0x1e,0x05,0x3d,0x05,0x3b,0x5e,0xa7,0x6e,0xa6,
+ 0x86,0x3c,0x76,0x1e,0x06,0x3d,0x06,0x3b,0x54,0x12,0xe4,0x01,0x67,0x12,0xe7,0x01,
+ 0x47,0x0d,0x0a,0xe8,0x3d,0xa6,0x4d,0xa7,0x87,0x3c,0x67,0x1e,0x07,0x3d,0x07,0x3b,
+ 0xf1,0x11,0x57,0x03,0xf9,0x11,0x09,0xf0,0x5d,0xa5,0x6d,0xa7,0x87,0x3c,0x57,0x1e,
+ 0x07,0x3d,0x07,0x3b,0xf1,0x11,0x67,0x03,0xf9,0x11,0x07,0x22,0x03,0xe0,0x27,0x60,
+ 0x0a,0xb7,0x03,0xf0,0x47,0x60,0xa0,0x88,0x08,0xb7,0x09,0x20,0xa0,0x88,0x08,0x20,
+ 0xa0,0x98,0x7b,0x20,0x0a,0x20,0xa9,0x2a,0x26,0xe7,0x07,0x60,0x83,0x73,0x74,0x12,
+ 0x76,0x12,0x36,0x1c,0x85,0x75,0x65,0x1c,0x05,0xa5,0x15,0x2a,0x02,0xe8,0x45,0x2a,
+ 0x03,0xe0,0x82,0x79,0x96,0x1c,0x06,0xb4,0x07,0x20,0xa7,0x2a,0xf1,0xe7,0x80,0x77,
+ 0x07,0x87,0x80,0x7b,0xb7,0x1c,0x07,0xa7,0x0d,0x60,0x07,0x2a,0x18,0xe1,0x1b,0xf1,
+ 0xd7,0x12,0x37,0x3c,0xd7,0x1c,0x74,0x7c,0xc7,0x1c,0x7b,0x71,0x17,0x1c,0x07,0xae,
+ 0xc7,0x12,0xe7,0x1c,0x75,0x72,0x27,0x1c,0x07,0xa7,0x17,0x2a,0x07,0xe8,0x47,0x2a,
+ 0x05,0xe8,0x76,0x73,0x03,0xa5,0x76,0x76,0x07,0x60,0xfc,0xf0,0xee,0x1c,0x75,0x76,
+ 0xe6,0x1c,0x07,0x60,0x06,0xd7,0x74,0x74,0x4e,0x1c,0x0e,0xd7,0xf6,0xf0,0x74,0x12,
+ 0x06,0xa3,0x07,0x20,0x86,0x20,0x3e,0x0f,0xed,0xe0,0xd7,0x12,0x37,0x3c,0xd7,0x1c,
+ 0x62,0x75,0x57,0x1c,0x6e,0x76,0x67,0x1c,0x57,0xa6,0x67,0xa5,0x85,0x3c,0x65,0x1e,
+ 0x77,0xa3,0x87,0xa6,0x86,0x3c,0x36,0x1e,0x47,0x12,0x37,0x3c,0x47,0x1c,0x5a,0x78,
+ 0x87,0x1c,0x67,0x79,0x97,0x1c,0x27,0xa4,0x37,0xab,0x8b,0x3c,0x4b,0x1e,0xbc,0x12,
+ 0x6c,0x01,0xa0,0x9c,0x47,0xa4,0x57,0xa9,0x89,0x3c,0x49,0x1e,0x98,0x12,0x68,0x01,
+ 0xb0,0x98,0x75,0x01,0xc0,0x95,0x8c,0x62,0x0c,0x1c,0x0c,0xc8,0x78,0x01,0xd0,0x98,
+ 0x5a,0x12,0x8a,0x05,0xea,0x01,0x6a,0x01,0x76,0x01,0xe0,0x96,0xcc,0x62,0x0c,0x1c,
+ 0x0c,0xc8,0x78,0x01,0xf0,0x98,0x86,0x05,0x68,0x12,0xe8,0x01,0x68,0x01,0xa2,0x12,
+ 0x72,0x01,0x83,0x12,0x73,0x01,0x53,0x7f,0x2c,0x12,0x49,0x77,0x07,0x87,0x49,0x76,
+ 0x76,0x1c,0x06,0xa6,0x26,0x2a,0x33,0xe0,0x50,0x76,0x76,0x1c,0x06,0xa6,0x4f,0x71,
+ 0x17,0x1c,0x07,0xa3,0x83,0x3c,0x63,0x1e,0x82,0x32,0x3c,0x0c,0x08,0xe0,0xc2,0x12,
+ 0x82,0x3c,0x4b,0x7f,0x62,0x01,0xf7,0x60,0x27,0x0c,0x01,0xe8,0x02,0x61,0xe7,0x12,
+ 0xe7,0x1c,0x41,0x76,0x76,0x1c,0x06,0xc6,0x6c,0x0c,0x04,0xe0,0x3e,0x72,0x27,0x1c,
+ 0x07,0xc2,0x03,0xf0,0x3c,0x73,0x37,0x1c,0x07,0xd2,0xe7,0x12,0xe7,0x1c,0x3a,0x74,
+ 0x47,0x1c,0x07,0xdc,0x87,0x32,0x72,0x0c,0x72,0x02,0xf1,0x11,0x2a,0x03,0xf9,0x11,
+ 0x8a,0x3e,0x6a,0x01,0xf1,0x11,0x28,0x03,0xf9,0x11,0x88,0x3e,0x1e,0xf0,0x16,0x2a,
+ 0x1d,0xe0,0x35,0x76,0x76,0x1c,0x06,0xa6,0x35,0x75,0x57,0x1c,0x07,0xa7,0x87,0x3c,
+ 0x67,0x1e,0x75,0x12,0x35,0x3e,0x46,0x60,0x52,0x0c,0x0c,0xe8,0x75,0x12,0x25,0x3e,
+ 0x36,0x60,0x52,0x0c,0x07,0xe8,0x75,0x12,0x15,0x3e,0x26,0x60,0x52,0x0c,0x02,0xe8,
+ 0x72,0x0c,0x36,0x00,0x6a,0x1a,0x6a,0x01,0x68,0x1a,0x68,0x01,0x17,0x76,0x6e,0x1c,
+ 0x1b,0x77,0x7e,0x1c,0x0e,0xa7,0x17,0x2a,0x12,0xe8,0xc0,0x8c,0xd0,0x81,0xc1,0x0d,
+ 0x02,0xe8,0xab,0x1c,0x01,0xf0,0xab,0x05,0x6b,0x01,0xa0,0x9b,0xe0,0x8b,0xf0,0x8c,
+ 0xbc,0x0d,0x02,0xe8,0x89,0x1c,0x01,0xf0,0x89,0x05,0x69,0x01,0xb0,0x99,0xd7,0x12,
+ 0x37,0x3c,0xd7,0x1c,0x09,0x71,0x17,0x1c,0x15,0x72,0x27,0x1c,0x83,0x62,0x03,0x1c,
+ 0x03,0xcb,0x57,0xbb,0x8b,0x3e,0x67,0xbb,0xc4,0x62,0x04,0x1c,0x04,0xc9,0x77,0xb9,
+ 0x89,0x3e,0x87,0xb9,0x2a,0xf0,0x00,0x00,0x8a,0x9e,0x00,0x00,0x83,0x00,0x00,0x00,
+ 0xab,0x00,0x00,0x00,0x3e,0x84,0x00,0x00,0x70,0x05,0x00,0x00,0x98,0x05,0x00,0x00,
+ 0x1c,0x9e,0x00,0x00,0xa3,0x00,0x00,0x00,0x1c,0x02,0x00,0x00,0x4a,0xa0,0x00,0x00,
+ 0x4b,0xa0,0x00,0x00,0x62,0xa6,0x00,0x00,0x76,0xa6,0x00,0x00,0x18,0x02,0x00,0x00,
+ 0xc0,0x01,0x00,0x00,0xc0,0x0c,0x00,0x00,0xa4,0x00,0x00,0x00,0xa5,0x00,0x00,0x00,
+ 0xd0,0x83,0x00,0x00,0x07,0x01,0x51,0x0c,0x0a,0xef,0x0d,0x20,0x4d,0x01,0xa9,0x75,
+ 0x05,0xa7,0x7d,0x0c,0xe5,0xee,0xa8,0x77,0x07,0x87,0xa8,0x76,0x67,0x1c,0x07,0xa5,
+ 0x16,0x60,0x56,0x0c,0x92,0xe0,0x56,0x60,0x56,0x0c,0x01,0xe0,0x07,0xb6,0x0c,0x60,
+ 0xa4,0x78,0xa4,0x7a,0xa5,0x79,0x85,0xf0,0xc3,0x12,0x33,0x3c,0xc3,0x1c,0x83,0x1c,
+ 0xa3,0x77,0x37,0x1c,0x07,0xad,0x87,0x12,0xd7,0x1c,0xa1,0x76,0x76,0x1c,0x06,0xa6,
+ 0x16,0x2a,0x21,0xe0,0xa7,0x12,0xd7,0x1c,0x06,0x60,0x07,0xb6,0x0e,0x60,0x3b,0x12,
+ 0x9b,0x77,0x7b,0x1c,0x10,0xf0,0xe2,0x12,0x32,0x3c,0xe2,0x1c,0xd7,0x12,0xd7,0x1c,
+ 0xd7,0x1c,0x76,0x12,0x46,0x3c,0x76,0x05,0x62,0x1c,0x92,0x1c,0xb3,0x12,0x94,0x60,
+ 0x95,0x7f,0x0e,0x20,0x4e,0x01,0x8c,0x71,0x01,0x87,0x8c,0x72,0x27,0x1c,0x07,0xa7,
+ 0x7e,0x0c,0xe9,0xef,0x54,0xf0,0x46,0x2a,0x52,0xe8,0x8f,0x74,0x47,0x1c,0x07,0xa7,
+ 0x17,0x2a,0x4d,0xe8,0xa7,0x12,0xd7,0x1c,0x07,0xa7,0xa0,0x97,0x72,0x12,0x32,0x3c,
+ 0x72,0x1c,0xd7,0x12,0xd7,0x1c,0xd7,0x1c,0x7e,0x12,0x4e,0x3c,0x7e,0x05,0xe2,0x1c,
+ 0x92,0x1c,0x82,0x75,0x53,0x1c,0x94,0x60,0x83,0x7f,0x7b,0x76,0x06,0x87,0x7b,0x7b,
+ 0xb7,0x1c,0x07,0xab,0x06,0x60,0xb0,0x96,0x62,0x12,0x64,0x12,0x10,0xf0,0x67,0x12,
+ 0x37,0x3c,0x67,0x1c,0xe7,0x1c,0x97,0x1c,0x17,0xa3,0x27,0xa5,0x85,0x3c,0x35,0x1e,
+ 0x52,0x1c,0x37,0xa5,0x47,0xa7,0x87,0x3c,0x57,0x1e,0x74,0x1c,0x06,0x20,0x06,0x01,
+ 0xb1,0x0c,0xed,0xef,0xb0,0x94,0xce,0x12,0x3e,0x3c,0xce,0x1c,0x8e,0x1c,0x73,0x71,
+ 0x1e,0x1c,0xb3,0x12,0x73,0x7f,0x62,0x01,0x5e,0xb2,0x82,0x3e,0x6e,0xb2,0xb0,0x82,
+ 0xb3,0x12,0x6f,0x7f,0x62,0x01,0x7e,0xb2,0x82,0x3e,0x8e,0xb2,0xa0,0x87,0x07,0x20,
+ 0x47,0x01,0xad,0x1c,0x0d,0xb7,0xb7,0x0c,0x02,0xe8,0x02,0x60,0x0d,0xb2,0x0c,0x20,
+ 0x4c,0x01,0x5c,0x73,0x03,0xa7,0x7c,0x0c,0x77,0xef,0x5b,0x77,0x07,0x87,0x65,0x74,
+ 0x47,0x1c,0x07,0xa7,0x07,0x2a,0x02,0xe9,0x5a,0x7a,0x56,0x77,0x07,0xa1,0x11,0x2a,
+ 0xfd,0xe0,0x61,0x77,0x07,0xa9,0x61,0x76,0x62,0x77,0x07,0xa7,0x62,0x75,0x05,0xab,
+ 0x8b,0x3c,0x7b,0x1e,0x61,0x77,0x07,0xa7,0x61,0x75,0x05,0xac,0x8c,0x3c,0x7c,0x1e,
+ 0x60,0x77,0x07,0xa7,0x60,0x75,0x05,0xad,0x8d,0x3c,0x7d,0x1e,0x5f,0x77,0x07,0xa7,
+ 0x5f,0x75,0x05,0xae,0x8e,0x3c,0x7e,0x1e,0xa6,0xa5,0xb6,0xa7,0x87,0x3c,0x57,0x1e,
+ 0x5c,0x75,0x75,0x1c,0xa0,0x95,0x5b,0x78,0x87,0x1c,0x67,0x01,0xb0,0x97,0xc6,0xa5,
+ 0xd6,0xa7,0x87,0x3c,0x57,0x1e,0x56,0x72,0x72,0x1c,0xc0,0x92,0x87,0x1c,0x67,0x01,
+ 0xd0,0x97,0x55,0x77,0x07,0xa7,0x55,0x76,0x06,0xa3,0x83,0x3c,0x73,0x1e,0x54,0x77,
+ 0x07,0xa7,0x54,0x76,0x06,0xa4,0x84,0x3c,0x74,0x1e,0x53,0x77,0x07,0xa8,0x67,0x64,
+ 0xf1,0x11,0x78,0x03,0xf9,0x11,0xa2,0x12,0x82,0x1c,0x50,0x75,0x52,0x1c,0x06,0x60,
+ 0xf1,0x11,0x79,0x03,0xf9,0x11,0x02,0xa7,0x27,0x2a,0xa2,0xe0,0x67,0x12,0xa7,0x1c,
+ 0x34,0x75,0x75,0x1c,0x05,0xa5,0x15,0x24,0x45,0x01,0x51,0x0c,0x99,0xe8,0x48,0x75,
+ 0x57,0x1c,0x07,0xa7,0x07,0x24,0x47,0x01,0x71,0x0c,0x92,0xe8,0x67,0x12,0x37,0x3c,
+ 0x67,0x05,0x87,0x1c,0xa7,0x1c,0x43,0x75,0x57,0x1c,0x37,0xaf,0x47,0xa5,0x85,0x3c,
+ 0xf5,0x1e,0xb5,0x0c,0x0a,0xe8,0x5c,0x0c,0x08,0xe8,0x57,0xaf,0x67,0xa7,0x87,0x3c,
+ 0xf7,0x1e,0xd7,0x0c,0x02,0xe8,0x7e,0x0c,0x7b,0xe0,0x55,0x1c,0x6f,0x12,0x3f,0x3c,
+ 0x6f,0x05,0xf7,0x12,0x97,0x1c,0xa7,0x1c,0x37,0x73,0x37,0x1c,0x37,0xa3,0x47,0xa4,
+ 0x84,0x3c,0x34,0x1e,0x45,0x05,0x65,0x01,0x8f,0x1c,0xaf,0x1c,0x32,0x74,0x4f,0x1c,
+ 0x5f,0xa3,0x6f,0xa4,0x84,0x3c,0x34,0x1e,0x44,0x1c,0x57,0xa3,0x67,0xa7,0x87,0x3c,
+ 0x37,0x1e,0x74,0x05,0x64,0x01,0x57,0x12,0x77,0x01,0xf3,0x67,0x73,0x0d,0x04,0xe8,
+ 0xa0,0x83,0x37,0x0d,0x03,0xe8,0x03,0xf0,0x75,0x32,0x01,0xf0,0xb0,0x85,0x47,0x12,
+ 0x77,0x01,0xf3,0x67,0x73,0x0d,0x04,0xe8,0xc0,0x83,0x37,0x0d,0x45,0xe8,0x45,0xf0,
+ 0x74,0x32,0x43,0xf0,0xa5,0xa0,0x00,0x00,0x1c,0x9e,0x00,0x00,0x21,0x01,0x00,0x00,
+ 0x8a,0x9e,0x00,0x00,0x8c,0xa6,0x00,0x00,0x96,0xa6,0x00,0x00,0x1c,0x02,0x00,0x00,
+ 0x70,0x05,0x00,0x00,0x8c,0x82,0x00,0x00,0x98,0x05,0x00,0x00,0x18,0x02,0x00,0x00,
+ 0x3e,0x84,0x00,0x00,0xa6,0x00,0x00,0x00,0xe4,0xa3,0x00,0x00,0x20,0x9e,0x00,0x00,
+ 0x36,0x9e,0x00,0x00,0x37,0x9e,0x00,0x00,0x3a,0x9e,0x00,0x00,0x3b,0x9e,0x00,0x00,
+ 0x38,0x9e,0x00,0x00,0x39,0x9e,0x00,0x00,0x3c,0x9e,0x00,0x00,0x3d,0x9e,0x00,0x00,
+ 0x81,0xff,0xff,0xff,0x80,0xff,0xff,0xff,0xa7,0xa0,0x00,0x00,0xa8,0xa0,0x00,0x00,
+ 0xa9,0xa0,0x00,0x00,0xaa,0xa0,0x00,0x00,0xe5,0xa3,0x00,0x00,0x02,0x03,0x00,0x00,
+ 0x8e,0x05,0x00,0x00,0x00,0x03,0x00,0x00,0xd0,0x84,0x53,0x12,0x63,0x01,0x64,0x01,
+ 0x06,0x20,0x62,0x20,0xa6,0x2a,0x57,0xe7,0x9f,0x77,0x07,0xb3,0x83,0x3e,0x9e,0x77,
+ 0x07,0xb3,0x9e,0x77,0x07,0xb4,0x84,0x3e,0x9e,0x77,0x07,0xb4,0x9e,0x77,0x07,0xa6,
+ 0x9e,0x77,0x07,0xa5,0x17,0x60,0x57,0x0c,0x9d,0x77,0x07,0x87,0x03,0xe0,0x9c,0x74,
+ 0x47,0x1c,0x02,0xf0,0x9c,0x75,0x57,0x1c,0x07,0xab,0x1b,0x3c,0x0a,0x60,0xac,0x12,
+ 0x9a,0x7d,0x68,0x64,0xf1,0x11,0x68,0x03,0xf9,0x11,0xb9,0x12,0x8a,0xf0,0xc7,0x12,
+ 0x37,0x3c,0xc7,0x1c,0xd7,0x1c,0x95,0x76,0x67,0x1c,0x07,0xab,0xd7,0x12,0xb7,0x1c,
+ 0x94,0x76,0x76,0x1c,0x06,0xa6,0x26,0x2a,0x74,0xe0,0x92,0x77,0x07,0xa5,0x92,0x77,
+ 0x06,0x60,0x2e,0xf0,0x74,0x12,0x87,0x20,0x04,0xa4,0xb4,0x0f,0x27,0xe0,0xb7,0x12,
+ 0x37,0x3c,0xb7,0x05,0x87,0x1c,0xd7,0x1c,0x8d,0x71,0x17,0x1c,0x37,0xa5,0x47,0xa2,
+ 0x82,0x3c,0x52,0x1e,0x6e,0x12,0x3e,0x3c,0x6e,0x1c,0xde,0x1c,0x89,0x73,0x3e,0x1c,
+ 0x2e,0xa5,0x3e,0xa6,0x86,0x3c,0x56,0x1e,0x62,0x05,0x57,0xa6,0x67,0xa3,0x83,0x3c,
+ 0x63,0x1e,0x4e,0xa6,0x5e,0xa7,0x87,0x3c,0x67,0x1e,0x73,0x05,0x72,0x01,0x73,0x01,
+ 0x81,0x7f,0x92,0x0c,0xc7,0x12,0x37,0x3c,0x06,0xe8,0x3a,0xf0,0x06,0x20,0x46,0x01,
+ 0x56,0x0f,0xd0,0xe7,0x44,0xf0,0xc7,0x1c,0xd7,0x1c,0x74,0x76,0x76,0x1c,0x06,0xa6,
+ 0xd6,0x1c,0x79,0x74,0x46,0x1c,0x06,0xa4,0x6d,0x75,0x05,0x85,0x78,0x73,0x53,0x1c,
+ 0x03,0xa3,0x34,0x0c,0x77,0x71,0x15,0x1c,0x08,0xe0,0x04,0x20,0x06,0xb4,0x05,0xa6,
+ 0x26,0x2a,0x2d,0xe0,0x74,0x72,0x27,0x1c,0x0c,0xf0,0x0a,0x20,0x4a,0x01,0xdb,0x1c,
+ 0x68,0x73,0x3b,0x1c,0x36,0x60,0x0b,0xb6,0x05,0xa6,0x06,0x2a,0x20,0xe8,0x6d,0x74,
+ 0x47,0x1c,0x2e,0xa5,0x3e,0xa6,0x86,0x3c,0x56,0x1e,0x57,0xb6,0x86,0x3e,0x67,0xb6,
+ 0x4e,0xa5,0x5e,0xa6,0x86,0x3c,0x56,0x1e,0x77,0xb6,0x86,0x3e,0x87,0xb6,0x0f,0xf0,
+ 0xc7,0x1c,0xd7,0x1c,0x5a,0x75,0x57,0x1c,0x07,0xa7,0xd7,0x1c,0x5f,0x76,0x67,0x1c,
+ 0x04,0xf0,0x16,0x2a,0x04,0xe0,0x5c,0x7b,0xb7,0x1c,0x06,0x60,0x07,0xb6,0x0c,0x20,
+ 0x4c,0x01,0x4d,0x71,0x01,0xa7,0x7c,0x0c,0x72,0xef,0x0a,0x2a,0x08,0xe8,0x5a,0x77,
+ 0x07,0xa6,0x5a,0x77,0x07,0xa7,0x87,0x3c,0x67,0x1e,0x7a,0x0c,0x2a,0x00,0x58,0x77,
+ 0x07,0xba,0x46,0x77,0x07,0x87,0x57,0x76,0x76,0x1c,0x06,0xa6,0x06,0x2a,0x05,0xe0,
+ 0x56,0x77,0x07,0xa6,0xf2,0x67,0x26,0x16,0xd4,0xf0,0x4f,0x76,0x06,0xa6,0x4f,0x75,
+ 0x05,0xa5,0x85,0x3c,0x65,0x1e,0x05,0x01,0x04,0x60,0x3f,0x7c,0x50,0x7d,0x7d,0x1c,
+ 0x50,0x7e,0x7e,0x1c,0x50,0x73,0x73,0x1c,0x3f,0x12,0x4f,0x72,0x72,0x1c,0x16,0xf0,
+ 0x86,0x65,0x46,0x1c,0x66,0x1c,0xc6,0x1c,0x86,0xa3,0x96,0xa6,0x0d,0xab,0xb3,0x0c,
+ 0x0b,0xe8,0x0e,0xab,0x3b,0x0c,0x08,0xe8,0x0f,0xa3,0x36,0x0c,0x05,0xe8,0x02,0xa3,
+ 0x63,0x0c,0x02,0xe8,0x01,0x24,0x41,0x01,0x04,0x20,0x44,0x01,0x54,0x0c,0xe8,0xef,
+ 0x15,0x60,0x15,0x0c,0x33,0xe8,0x3d,0x76,0x76,0x1c,0x06,0xa4,0x3d,0x76,0x76,0x1c,
+ 0x06,0xac,0x05,0x60,0x3c,0x7d,0x7d,0x1c,0x3c,0x76,0x76,0x1c,0x6f,0x12,0x3b,0x7e,
+ 0xa2,0x61,0x16,0xf0,0x0d,0xa3,0x0f,0xaa,0x4b,0x12,0xf1,0x11,0x2b,0x03,0xf9,0x11,
+ 0x0b,0xf0,0xb6,0x12,0x36,0x1c,0x66,0x1c,0xe6,0x1c,0x06,0xc6,0x76,0x01,0x06,0x22,
+ 0x01,0xe0,0x65,0x1c,0x03,0x20,0x43,0x01,0x3a,0x0c,0xf3,0xe7,0x04,0x20,0x44,0x01,
+ 0x4c,0x0c,0xe8,0xe7,0x11,0x2a,0x05,0xe0,0x66,0x67,0x76,0x1c,0x06,0xa6,0x66,0x1c,
+ 0x03,0xf0,0x2b,0x76,0x76,0x1c,0x06,0xa6,0x56,0x0c,0x35,0x00,0x2a,0x76,0x06,0xa6,
+ 0x76,0x36,0x29,0x76,0x59,0xe8,0x05,0x2a,0x02,0xe8,0x07,0x60,0x53,0xf0,0x06,0xa5,
+ 0x27,0x78,0x87,0x1c,0x07,0xa7,0x57,0x0c,0x4b,0xe0,0x1b,0x77,0x07,0xa6,0xf9,0x67,
+ 0x96,0x16,0x56,0xf0,0xa7,0xa0,0x00,0x00,0xa8,0xa0,0x00,0x00,0xa9,0xa0,0x00,0x00,
+ 0xaa,0xa0,0x00,0x00,0xe5,0xa3,0x00,0x00,0xa5,0xa0,0x00,0x00,0x1c,0x9e,0x00,0x00,
+ 0xb3,0x00,0x00,0x00,0xb2,0x00,0x00,0x00,0x8a,0x9e,0x00,0x00,0x1c,0x02,0x00,0x00,
+ 0x70,0x05,0x00,0x00,0x4a,0xa0,0x00,0x00,0x4b,0xa0,0x00,0x00,0x00,0x03,0x00,0x00,
+ 0xc0,0x01,0x00,0x00,0xc0,0x0c,0x00,0x00,0xa7,0x05,0x00,0x00,0xb1,0x00,0x00,0x00,
+ 0xb0,0x00,0x00,0x00,0x18,0x02,0x00,0x00,0x40,0x9f,0x00,0x00,0x41,0x9f,0x00,0x00,
+ 0x3b,0xa4,0x00,0x00,0x11,0x01,0x00,0x00,0x2c,0xa4,0x00,0x00,0x12,0x01,0x00,0x00,
+ 0x13,0x01,0x00,0x00,0x14,0x01,0x00,0x00,0x15,0x01,0x00,0x00,0x00,0xe0,0x02,0x00,
+ 0x17,0x01,0x00,0x00,0x2d,0xa4,0x00,0x00,0x58,0xa8,0x00,0x00,0x18,0x01,0x00,0x00,
+ 0x57,0x12,0x07,0x20,0x06,0xb7,0x0f,0xf0,0x05,0x2a,0x0c,0xe8,0x06,0xa5,0xa4,0x7b,
+ 0xb7,0x1c,0x07,0xa7,0x57,0x0c,0xf4,0xe7,0xa3,0x77,0x07,0xa6,0xa3,0x7c,0xc6,0x1e,
+ 0x07,0xb6,0x01,0xf0,0x06,0xb5,0x9f,0x77,0x07,0xa7,0x77,0x36,0x03,0xe8,0x16,0x60,
+ 0x9f,0x77,0x07,0xb6,0x9f,0x7e,0x0e,0xa7,0x07,0x2a,0x42,0xe8,0x9e,0x7f,0x9e,0x77,
+ 0x07,0xa2,0x17,0xa3,0x9e,0x74,0x85,0x61,0x9e,0x7f,0x9e,0x77,0x07,0xb2,0x12,0x01,
+ 0x9e,0x77,0x07,0xb1,0x22,0x01,0x9d,0x77,0x07,0xb1,0x82,0x3f,0x9d,0x77,0x07,0xb2,
+ 0x9d,0x77,0x07,0xa6,0x9d,0x77,0x07,0xa7,0x87,0x3c,0x67,0x1e,0x9c,0x76,0x06,0xa6,
+ 0x06,0x3d,0x76,0x1e,0x9b,0x77,0x07,0xa7,0x87,0x3d,0x67,0x1e,0x07,0x2a,0x1a,0xe0,
+ 0x99,0x77,0x07,0xa6,0x99,0x77,0x07,0xa7,0x87,0x3c,0x67,0x1e,0x98,0x76,0x06,0xa6,
+ 0x06,0x3d,0x76,0x1e,0x97,0x77,0x07,0xa7,0x87,0x3d,0x67,0x1e,0x07,0x2a,0x0a,0xe0,
+ 0x95,0x75,0x05,0xa6,0x06,0x20,0x46,0x01,0x05,0xb6,0x25,0x60,0x65,0x0c,0x05,0xe0,
+ 0x0e,0xb7,0x03,0xf0,0x06,0x60,0x8f,0x77,0x07,0xb6,0x16,0x60,0x7c,0x77,0x07,0xb6,
+ 0x8e,0x76,0x06,0x87,0x07,0x20,0x06,0x97,0x8d,0x7e,0x0e,0xa7,0x07,0x2a,0x7f,0xe0,
+ 0x81,0x77,0x07,0xa6,0x81,0x77,0x07,0xa7,0x87,0x3c,0x67,0x1e,0x80,0x76,0x06,0xa6,
+ 0x06,0x3d,0x76,0x1e,0x7f,0x77,0x07,0xa7,0x87,0x3d,0x67,0x1e,0x07,0x2a,0x10,0xe0,
+ 0x7d,0x77,0x07,0xa7,0x7d,0x76,0x06,0xa6,0x86,0x3c,0x76,0x1e,0x7c,0x77,0x07,0xa7,
+ 0x07,0x3d,0x67,0x1e,0x7b,0x76,0x06,0xad,0x8d,0x3d,0x7d,0x1e,0x0d,0x2a,0x05,0xe8,
+ 0x69,0x7f,0x06,0x60,0x7a,0x77,0x17,0xb6,0x23,0xf3,0x1e,0xa7,0x26,0x60,0x76,0x0c,
+ 0x04,0xe8,0x07,0x20,0x1e,0xb7,0x63,0x7f,0x1b,0xf3,0x56,0x60,0x76,0x0c,0x0f,0xe8,
+ 0x07,0x20,0x1e,0xb7,0x17,0x60,0xae,0xb7,0xbe,0xbd,0xce,0xbd,0x71,0x77,0x07,0x87,
+ 0x71,0x71,0x17,0x1c,0x07,0xa7,0xde,0xb7,0x07,0x60,0xee,0xb7,0x09,0xf3,0x5a,0x77,
+ 0x07,0xa2,0x17,0xa3,0x5a,0x74,0x85,0x61,0x5a,0x7f,0x86,0x2c,0x26,0x16,0x59,0x77,
+ 0x07,0xb6,0x12,0x01,0x17,0x12,0x58,0x75,0x05,0xb1,0x22,0x01,0x58,0x75,0x05,0xb1,
+ 0x82,0x3f,0x57,0x75,0x05,0xb2,0x64,0x75,0x05,0xb6,0x64,0x75,0x05,0xb7,0x64,0x75,
+ 0x05,0xb1,0x64,0x75,0x05,0xb2,0x64,0x75,0x05,0xb6,0x64,0x76,0x06,0xb7,0x64,0x77,
+ 0x07,0xb1,0x64,0x77,0x07,0xb2,0xae,0xbd,0x64,0x76,0x06,0xa6,0x64,0x77,0x07,0xa7,
+ 0x87,0x3c,0x67,0x1e,0x63,0x76,0x06,0xa6,0x06,0x3d,0x76,0x1e,0x62,0x77,0x07,0xa7,
+ 0x87,0x3d,0x67,0x1e,0x4e,0xb7,0x17,0x01,0x5e,0xb1,0x27,0x01,0x6e,0xb1,0x87,0x3f,
+ 0x7e,0xb7,0x1e,0xbd,0x17,0x60,0x0e,0xb7,0x5c,0x77,0x67,0xbd,0xc9,0xf2,0x4c,0x76,
+ 0x06,0x8d,0x5a,0x76,0xd6,0x1c,0x06,0xa6,0x06,0x2a,0x03,0xe0,0x27,0x60,0x0e,0xb7,
+ 0x31,0xf3,0x16,0x2a,0xdd,0xe1,0x17,0x2a,0xb4,0xe2,0x07,0x60,0xae,0xb7,0x54,0x77,
+ 0xd7,0x1c,0x07,0xa6,0x06,0x2a,0x50,0x77,0x03,0xe0,0x26,0x60,0x67,0xb6,0xb1,0xf1,
+ 0x16,0x2a,0x0a,0xe1,0x67,0xa6,0x06,0x2a,0xec,0xe0,0x4e,0x77,0x07,0xa7,0x07,0x2a,
+ 0x07,0xe0,0x4d,0x77,0x07,0xa7,0x17,0x2a,0x3c,0xe0,0x4c,0x76,0x06,0xb7,0x3c,0xf0,
+ 0x17,0x2a,0x37,0xe0,0x49,0x77,0x07,0xa7,0x17,0x2a,0x36,0xe8,0x49,0x77,0x07,0xa6,
+ 0x06,0x2a,0x2f,0xe0,0x46,0x77,0x07,0xa5,0x15,0x2a,0x2d,0xe0,0x46,0x77,0x07,0xa7,
+ 0x66,0x64,0xf1,0x11,0x67,0x03,0xf9,0x11,0x44,0x76,0x67,0x1c,0x44,0x72,0x27,0x1c,
+ 0x37,0xa6,0x47,0xa2,0x82,0x3c,0x62,0x1e,0x42,0x76,0x06,0xa5,0x42,0x76,0x06,0xa6,
+ 0x86,0x3c,0x56,0x1e,0x62,0x05,0x57,0xa6,0x67,0xa3,0x83,0x3c,0x63,0x1e,0x3e,0x77,
+ 0x07,0xa6,0x3e,0x77,0x07,0xa7,0x87,0x3c,0x67,0x1e,0x73,0x05,0x72,0x01,0x73,0x01,
+ 0x3c,0x7f,0x72,0x01,0x97,0x32,0x27,0x0d,0x07,0xe8,0x26,0x60,0x2b,0x77,0x67,0xb6,
+ 0x03,0xf0,0x06,0x60,0x2e,0x77,0x07,0xb6,0x1a,0x77,0x07,0x85,0x36,0x77,0x6c,0xf0,
+ 0x18,0x01,0x00,0x00,0x2c,0xa4,0x00,0x00,0x80,0xff,0xff,0xff,0x62,0xa4,0x00,0x00,
+ 0x31,0xaa,0x00,0x00,0xac,0x2c,0x00,0x00,0x20,0x9e,0x00,0x00,0x00,0x80,0x02,0x00,
+ 0x58,0x3e,0x00,0x00,0x65,0xa4,0x00,0x00,0x66,0xa4,0x00,0x00,0x67,0xa4,0x00,0x00,
+ 0x68,0xa4,0x00,0x00,0x46,0xa4,0x00,0x00,0x47,0xa4,0x00,0x00,0x48,0xa4,0x00,0x00,
+ 0x49,0xa4,0x00,0x00,0x4a,0xa4,0x00,0x00,0x4b,0xa4,0x00,0x00,0x4c,0xa4,0x00,0x00,
+ 0x4d,0xa4,0x00,0x00,0x59,0xa8,0x00,0x00,0x5c,0xa8,0x00,0x00,0x66,0x9e,0x00,0x00,
+ 0x1c,0x9e,0x00,0x00,0xba,0x00,0x00,0x00,0x69,0xa4,0x00,0x00,0x6a,0xa4,0x00,0x00,
+ 0x6b,0xa4,0x00,0x00,0x6c,0xa4,0x00,0x00,0x6d,0xa4,0x00,0x00,0x6e,0xa4,0x00,0x00,
+ 0x6f,0xa4,0x00,0x00,0x70,0xa4,0x00,0x00,0x37,0xaa,0x00,0x00,0x38,0xaa,0x00,0x00,
+ 0x39,0xaa,0x00,0x00,0x3a,0xaa,0x00,0x00,0x20,0xaa,0x00,0x00,0xb4,0x00,0x00,0x00,
+ 0xbc,0x00,0x00,0x00,0x4a,0xa0,0x00,0x00,0xa5,0xa0,0x00,0x00,0x60,0xa8,0x00,0x00,
+ 0xef,0x9f,0x00,0x00,0xe4,0xa3,0x00,0x00,0x8a,0x9e,0x00,0x00,0x00,0x03,0x00,0x00,
+ 0x01,0xa1,0x00,0x00,0x02,0xa1,0x00,0x00,0x03,0xa1,0x00,0x00,0x04,0xa1,0x00,0x00,
+ 0xc0,0x0c,0x00,0x00,0x42,0xa4,0x00,0x00,0x07,0xa6,0xb7,0x77,0x07,0xa7,0x87,0x3c,
+ 0x67,0x1e,0x56,0x67,0x56,0x1c,0x06,0xa6,0xb5,0x73,0x35,0x1c,0x05,0xa5,0x56,0x1b,
+ 0x76,0x0d,0xe7,0xe8,0xb3,0x77,0x07,0xa7,0xb3,0x76,0x06,0xa6,0x86,0x3c,0x76,0x1e,
+ 0xb2,0x77,0x07,0xa7,0x07,0x3d,0x67,0x1e,0xb1,0x76,0x06,0xa6,0x86,0x3d,0x76,0x1e,
+ 0xb0,0x77,0x07,0xa5,0xb0,0x77,0x07,0xa7,0x87,0x3c,0x57,0x1e,0xaf,0x75,0x05,0xa5,
+ 0x05,0x3d,0x75,0x1e,0xae,0x77,0x07,0xa7,0x87,0x3d,0x57,0x1e,0x67,0x0c,0x06,0xe0,
+ 0x06,0x60,0xab,0x77,0x17,0xb6,0x16,0x60,0xab,0x77,0x67,0xb6,0x06,0x60,0xaa,0x77,
+ 0x19,0xf0,0x67,0xa7,0x17,0x2a,0xbd,0xe0,0x1e,0xa6,0x06,0x20,0x46,0x01,0x1e,0xb6,
+ 0xa7,0x74,0x4d,0x1c,0x0d,0xa7,0x17,0x3e,0x67,0x0c,0x04,0xe8,0xa5,0x77,0x07,0xa7,
+ 0x07,0x2a,0x06,0xe8,0x16,0x60,0xa3,0x77,0x07,0xb6,0x06,0x60,0x9e,0x77,0x67,0xb6,
+ 0x16,0x60,0xa1,0x77,0x07,0xb6,0xa5,0xf0,0x26,0x2a,0xa3,0xe0,0x67,0xa6,0x06,0x2a,
+ 0x34,0xe0,0x9e,0x77,0x07,0xa6,0x8c,0x77,0x07,0xa7,0x87,0x3c,0x67,0x1e,0x56,0x67,
+ 0xd6,0x1c,0x06,0xa6,0x8a,0x75,0x5d,0x1c,0x0d,0xa5,0x56,0x1b,0x76,0x0d,0x65,0xe8,
+ 0x88,0x77,0x07,0xa7,0x88,0x76,0x06,0xa6,0x86,0x3c,0x76,0x1e,0x87,0x77,0x07,0xa7,
+ 0x07,0x3d,0x67,0x1e,0x86,0x76,0x06,0xa6,0x86,0x3d,0x76,0x1e,0x85,0x77,0x07,0xa5,
+ 0x85,0x77,0x07,0xa7,0x87,0x3c,0x57,0x1e,0x84,0x75,0x05,0xa5,0x05,0x3d,0x75,0x1e,
+ 0x83,0x77,0x07,0xa7,0x87,0x3d,0x57,0x1e,0x67,0x0c,0x47,0xe0,0x06,0x60,0x80,0x77,
+ 0x17,0xb6,0x16,0x60,0x80,0x77,0x67,0xb6,0x40,0xf0,0x67,0xa7,0x17,0x2a,0x3d,0xe0,
+ 0x1e,0xa6,0x06,0x20,0x46,0x01,0x1e,0xb6,0x7d,0x77,0xd7,0x1c,0x07,0xa7,0x17,0x3e,
+ 0x67,0x0c,0x04,0xe8,0x7b,0x77,0x07,0xa7,0x07,0x2a,0x2c,0xe8,0x76,0x73,0x16,0x60,
+ 0x79,0x77,0x07,0xb6,0x7b,0x76,0x06,0xa6,0x7b,0x77,0x07,0xa7,0x87,0x3c,0x67,0x1e,
+ 0x7a,0x76,0x06,0xa6,0x06,0x3d,0x76,0x1e,0x79,0x77,0x07,0xa7,0x87,0x3d,0x67,0x1e,
+ 0x6c,0x74,0x44,0xa5,0x54,0xa6,0x86,0x3c,0x56,0x1e,0x64,0xa5,0x05,0x3d,0x65,0x1e,
+ 0x74,0xa6,0x86,0x3d,0x56,0x1e,0x67,0x05,0x72,0x76,0xd6,0x1c,0x06,0xa5,0x71,0x76,
+ 0x6d,0x1c,0x0d,0xa6,0x86,0x3c,0x56,0x1e,0x76,0x0c,0x02,0xe0,0x27,0x60,0x01,0xf0,
+ 0x07,0x60,0x63,0xb7,0x06,0x60,0x60,0x77,0x07,0xb6,0x5e,0x73,0x63,0xa7,0x07,0x2a,
+ 0x28,0xe0,0x63,0x76,0x06,0xa6,0x63,0x77,0x07,0xa7,0x87,0x3c,0x67,0x1e,0x62,0x76,
+ 0x06,0xa6,0x06,0x3d,0x76,0x1e,0x61,0x77,0x07,0xa7,0x87,0x3d,0x67,0x1e,0x54,0x74,
+ 0x44,0xa5,0x54,0xa6,0x86,0x3c,0x56,0x1e,0x64,0xa5,0x05,0x3d,0x65,0x1e,0x74,0xa6,
+ 0x86,0x3d,0x56,0x1e,0x67,0x05,0x5c,0x76,0x06,0x86,0x59,0x75,0x65,0x1c,0x05,0xa5,
+ 0x59,0x78,0x86,0x1c,0x06,0xa6,0x86,0x3c,0x56,0x1e,0x76,0x0c,0x02,0xe0,0x27,0x60,
+ 0x63,0xb7,0x48,0x75,0x65,0xa5,0x25,0x2a,0xfb,0xe0,0x45,0x76,0x07,0x60,0x16,0xb7,
+ 0x36,0xb7,0x4b,0x74,0x04,0xa4,0x4b,0x77,0x07,0xa7,0x87,0x3c,0x47,0x1e,0x4a,0x74,
+ 0x04,0xa4,0x04,0x3d,0x74,0x1e,0x49,0x77,0x07,0xa7,0x87,0x3d,0x47,0x1e,0x46,0xb7,
+ 0x17,0x01,0x56,0xb1,0x27,0x01,0x66,0xb1,0x87,0x3f,0x76,0xb7,0x06,0xb5,0xe0,0xf0,
+ 0x26,0x2a,0xdb,0xe0,0x2e,0xa6,0x06,0x2a,0xda,0xe8,0x17,0x2a,0xd2,0xe0,0x43,0x7c,
+ 0x0c,0xa2,0x5d,0xa3,0x43,0x7b,0x00,0x9b,0x34,0x60,0x42,0x75,0x43,0x76,0x07,0x60,
+ 0x43,0x7f,0x0c,0xa2,0x5d,0xa3,0x49,0x67,0xd9,0x1c,0x09,0xa7,0x0e,0x60,0x00,0x9e,
+ 0xc4,0x60,0xb5,0x12,0xe6,0x12,0x3d,0x7f,0x3e,0x7a,0x0a,0x88,0xb0,0x98,0x0c,0xa2,
+ 0x5d,0xa3,0x3c,0x78,0xd8,0x1c,0x08,0xa6,0x3c,0x71,0xd1,0x1c,0xa0,0x91,0x01,0xa7,
+ 0x87,0x3c,0x67,0x1e,0x07,0x3d,0x00,0x9e,0xd4,0x60,0xb5,0x12,0xe6,0x12,0x07,0x3b,
+ 0x33,0x7f,0x0a,0x82,0xc0,0x92,0x0c,0xa2,0x1c,0xa3,0x34,0x74,0x85,0x61,0x34,0x7f,
+ 0x0c,0xa2,0x5d,0xa3,0x09,0xa7,0x00,0x9e,0xc4,0x60,0xb5,0x12,0xe6,0x12,0x2b,0x7f,
+ 0x0a,0x89,0x0c,0xa2,0x5d,0xa3,0x08,0xa6,0xa0,0x88,0x08,0xa7,0x87,0x3c,0x67,0x1e,
+ 0x07,0x3d,0x00,0x9e,0xd4,0x60,0xb5,0x12,0xe6,0x12,0x07,0x3b,0x24,0x7f,0x0a,0x87,
+ 0xb0,0x8b,0x0b,0x2a,0x03,0xe0,0xc0,0x8c,0x0c,0x2a,0x04,0xe8,0x09,0x2a,0xd3,0xe0,
+ 0x07,0x2a,0xd1,0xe0,0x0b,0x7e,0x46,0xf0,0x43,0xa4,0x00,0x00,0xbd,0x00,0x00,0x00,
+ 0x56,0xa4,0x00,0x00,0x57,0xa4,0x00,0x00,0x58,0xa4,0x00,0x00,0x59,0xa4,0x00,0x00,
+ 0x52,0xa4,0x00,0x00,0x53,0xa4,0x00,0x00,0x54,0xa4,0x00,0x00,0x55,0xa4,0x00,0x00,
+ 0x66,0x9e,0x00,0x00,0x20,0xaa,0x00,0x00,0xa5,0xa0,0x00,0x00,0xb9,0x00,0x00,0x00,
+ 0x72,0xa4,0x00,0x00,0x31,0xaa,0x00,0x00,0x62,0xa4,0x00,0x00,0x42,0xa4,0x00,0x00,
+ 0x37,0xaa,0x00,0x00,0x38,0xaa,0x00,0x00,0x39,0xaa,0x00,0x00,0x3a,0xaa,0x00,0x00,
+ 0xbe,0x00,0x00,0x00,0xbf,0x00,0x00,0x00,0x1c,0x9e,0x00,0x00,0x20,0x9e,0x00,0x00,
+ 0x00,0x00,0x03,0x18,0x00,0x00,0x06,0x18,0x00,0x00,0x02,0x18,0xb4,0x26,0x00,0x00,
+ 0x34,0x0a,0x04,0x00,0xb5,0x00,0x00,0x00,0xb6,0x00,0x00,0x00,0x00,0xa0,0x02,0x00,
+ 0x48,0x2a,0x00,0x00,0x1e,0xa7,0x07,0x20,0x47,0x01,0x1e,0xb7,0x2d,0x60,0x7d,0x0c,
+ 0x37,0xe0,0x07,0x60,0x3e,0xb7,0x1e,0xb7,0x56,0x7f,0x56,0x76,0x06,0xa6,0x56,0x77,
+ 0x07,0xa7,0x87,0x3c,0x67,0x1e,0x55,0x76,0x06,0xa6,0x06,0x3d,0x76,0x1e,0x54,0x77,
+ 0x07,0xa7,0x87,0x3d,0x67,0x1e,0x4e,0xb7,0x17,0x01,0x5e,0xb1,0x27,0x01,0x6e,0xb1,
+ 0x87,0x3f,0x7e,0xb7,0x0e,0xbd,0x1c,0xf0,0x37,0xbf,0x0c,0xac,0x0e,0xa6,0x86,0x3c,
+ 0xc6,0x1e,0x02,0xa5,0x05,0x3d,0x65,0x1e,0x03,0xa6,0x86,0x3d,0x56,0x1e,0x47,0xb6,
+ 0x16,0x01,0x57,0xb1,0x26,0x01,0x67,0xb1,0x86,0x3f,0x77,0xb6,0x26,0x60,0x07,0xb6,
+ 0x07,0xf0,0x27,0x2a,0x05,0xe0,0x43,0x7f,0x03,0xf0,0x36,0x2a,0x01,0xe0,0x42,0x7f,
+ 0x43,0x76,0xd6,0xa5,0xe6,0xa7,0x87,0x3c,0x57,0x1e,0x7f,0x12,0x6f,0x01,0xa6,0xa5,
+ 0x05,0x2a,0x68,0xe8,0x3f,0x75,0x05,0x82,0x3f,0x75,0x25,0x1c,0x05,0xa4,0x04,0x2a,
+ 0x61,0xe0,0x3d,0x75,0x05,0xc3,0x03,0x20,0x63,0x01,0x05,0xd3,0xb6,0xae,0xc6,0xa6,
+ 0x86,0x3c,0xe6,0x1e,0x63,0x0c,0x56,0xe8,0x05,0xd4,0x42,0xaa,0x15,0x60,0x37,0x7b,
+ 0xac,0x61,0x7f,0x01,0x37,0x73,0xfd,0x12,0x0d,0x28,0x1c,0xf0,0x96,0x12,0x46,0x1c,
+ 0x66,0x1c,0xbe,0x12,0x6e,0x1c,0x0e,0xce,0xe1,0x12,0x71,0x01,0x36,0x1c,0x1f,0x0d,
+ 0x03,0xe8,0x06,0xce,0x7e,0x05,0x07,0xf0,0xd1,0x0d,0x03,0xe8,0x06,0xce,0x7e,0x1c,
+ 0x02,0xf0,0x06,0xc1,0x1e,0x14,0x06,0xde,0x04,0x20,0x44,0x01,0x48,0x0c,0xe6,0xe7,
+ 0x05,0x20,0x45,0x01,0x5a,0x0c,0x2e,0xe8,0x52,0xa8,0x14,0x60,0x59,0x12,0xf1,0x11,
+ 0xc9,0x03,0xf9,0x11,0xf3,0xf7,0x1d,0x77,0x0f,0x60,0x17,0xbf,0x16,0x7c,0x0c,0xa5,
+ 0x16,0x7e,0x0e,0xa6,0x86,0x3c,0x56,0x1e,0x15,0x72,0x02,0xa5,0x05,0x3d,0x65,0x1e,
+ 0x14,0x73,0x03,0xa6,0x86,0x3d,0x56,0x1e,0x47,0xa4,0x57,0xa5,0x85,0x3c,0x45,0x1e,
+ 0x67,0xa4,0x04,0x3d,0x54,0x1e,0x77,0xa5,0x85,0x3d,0x45,0x1e,0x56,0x05,0x15,0x75,
+ 0xd5,0x1c,0x05,0xa4,0x15,0x71,0x1d,0x1c,0x0d,0xa5,0x85,0x3c,0x45,0x1e,0x65,0x0c,
+ 0x73,0xef,0x8e,0xf7,0x01,0x64,0x10,0x1c,0x68,0x00,0xf0,0x21,0xcf,0x00,0x00,0x00,
+ 0xac,0x2c,0x00,0x00,0x37,0xaa,0x00,0x00,0x38,0xaa,0x00,0x00,0x39,0xaa,0x00,0x00,
+ 0x3a,0xaa,0x00,0x00,0xaa,0x41,0x00,0x00,0x94,0x3f,0x00,0x00,0x66,0x9e,0x00,0x00,
+ 0x1c,0x9e,0x00,0x00,0x11,0x01,0x00,0x00,0x62,0xa8,0x00,0x00,0x00,0xe0,0x02,0x00,
+ 0x00,0xc0,0x02,0x00,0xb7,0x00,0x00,0x00,0xb8,0x00,0x00,0x00,0x70,0x24,0x7e,0x00,
+ 0xf1,0x60,0x41,0x0c,0x38,0xe0,0x37,0x12,0x27,0x1e,0x37,0x2e,0x07,0x2a,0x3f,0xe0,
+ 0x36,0x12,0x27,0x12,0x45,0x12,0x06,0x8f,0x07,0x9f,0x16,0x8f,0x17,0x9f,0x26,0x8f,
+ 0x27,0x9f,0x36,0x8f,0x37,0x9f,0xf7,0x20,0xf6,0x20,0xf5,0x24,0x51,0x0c,0xf3,0xef,
+ 0x46,0x12,0xf6,0x24,0x46,0x3e,0x06,0x20,0x46,0x3c,0x27,0x12,0x67,0x1c,0x63,0x1c,
+ 0xf4,0x2e,0x3e,0x60,0x4e,0x0c,0x1e,0xe0,0x31,0x12,0x75,0x12,0x46,0x12,0x01,0x8f,
+ 0x05,0x9f,0x35,0x20,0x31,0x20,0x36,0x24,0x6e,0x0c,0xf9,0xef,0x45,0x12,0x35,0x24,
+ 0x25,0x3e,0x05,0x20,0x25,0x3c,0x34,0x2e,0x53,0x1c,0x57,0x1c,0x04,0x2a,0x05,0xe0,
+ 0x6e,0x00,0x70,0x20,0xcf,0x00,0x27,0x12,0x05,0xf0,0x03,0xa6,0x07,0xb6,0x07,0x20,
+ 0x03,0x20,0x04,0x24,0x04,0x2a,0xf9,0xe7,0x6e,0x00,0x70,0x20,0xcf,0x00,0x27,0x12,
+ 0xf4,0xf7,0x70,0x24,0x00,0x9f,0x37,0x60,0x72,0x0e,0x4c,0xe8,0x04,0x2a,0x47,0xe8,
+ 0x04,0x24,0x03,0x01,0x27,0x12,0x05,0xf0,0x46,0x12,0x06,0x24,0x04,0x2a,0x3f,0xe8,
+ 0x64,0x12,0x07,0xb1,0x07,0x20,0x36,0x60,0x67,0x0e,0xf6,0xe7,0x36,0x60,0x46,0x0c,
+ 0x2e,0xe0,0x85,0x2c,0x35,0x16,0x56,0x12,0x86,0x3c,0x56,0x1e,0x65,0x12,0x05,0x3d,
+ 0x65,0x1e,0xff,0x60,0x4f,0x0c,0x30,0xe0,0x76,0x12,0x41,0x12,0x06,0x95,0x16,0x95,
+ 0x26,0x95,0x36,0x95,0xf6,0x20,0xf1,0x24,0x1f,0x0c,0xf8,0xef,0x41,0x12,0xf1,0x24,
+ 0x41,0x3e,0x01,0x20,0x41,0x3c,0x71,0x1c,0xf4,0x2e,0x37,0x60,0x47,0x0c,0x1e,0xe0,
+ 0x16,0x12,0x47,0x12,0x3f,0x60,0x06,0x95,0x36,0x20,0x37,0x24,0x7f,0x0c,0xfb,0xef,
+ 0x47,0x12,0x37,0x24,0x27,0x3e,0x07,0x20,0x27,0x3c,0x34,0x2e,0x17,0x1c,0x04,0x2a,
+ 0x06,0xe8,0x43,0x01,0x07,0xb3,0x07,0x20,0x04,0x24,0x04,0x2a,0xfb,0xe7,0x00,0x8f,
+ 0x70,0x20,0xcf,0x00,0x27,0x12,0xc2,0xf7,0x71,0x12,0xe2,0xf7,0x17,0x12,0xef,0xf7,
+ 0x02,0x2a,0x19,0xe8,0x03,0x2a,0x02,0xe0,0x0b,0x00,0x15,0xf0,0x07,0x60,0x21,0x12,
+ 0x34,0x12,0xf1,0x37,0x03,0xe8,0xf1,0x33,0x01,0xf0,0x14,0x3c,0x41,0x0f,0x02,0xe8,
+ 0x41,0x0c,0xfb,0xe7,0x01,0xf0,0x14,0x3e,0x42,0x0c,0x01,0xe8,0x42,0x05,0x77,0x06,
+ 0x43,0x0c,0xf9,0xef,0x72,0x12,0xcf,0x00,0x02,0x2a,0x18,0xe8,0x03,0x2a,0x02,0xe0,
+ 0x0b,0x00,0x14,0xf0,0x07,0x60,0x21,0x12,0x34,0x12,0xf1,0x37,0x03,0xe8,0xf1,0x33,
+ 0x01,0xf0,0x14,0x3c,0x41,0x0f,0x02,0xe8,0x41,0x0c,0xfb,0xe7,0x01,0xf0,0x14,0x3e,
+ 0x42,0x0c,0x01,0xe8,0x42,0x05,0x77,0x06,0x43,0x0c,0xf9,0xef,0xcf,0x00,0x03,0x2a,
+ 0x02,0xe0,0x0b,0x00,0x16,0xf0,0x07,0x60,0x31,0x12,0x21,0x17,0xe2,0x01,0xe3,0x01,
+ 0x34,0x12,0x01,0xf0,0x14,0x3c,0x42,0x0c,0xfd,0xe7,0x01,0xf0,0x14,0x3e,0x42,0x0c,
+ 0x01,0xe8,0x42,0x05,0x77,0x06,0x43,0x0c,0xf9,0xef,0xf1,0x37,0x01,0xe8,0x07,0x28,
+ 0x72,0x12,0xcf,0x00,0x25,0x12,0xe2,0x01,0xe3,0x01,0x01,0x60,0x14,0x60,0x03,0x2a,
+ 0x01,0xe0,0x0b,0x00,0x27,0x12,0x07,0x2a,0x02,0xe0,0x02,0x60,0xcf,0x00,0x30,0x24,
+ 0x00,0x91,0xf6,0x61,0x71,0x12,0x61,0x0b,0x01,0x2a,0x03,0xe8,0xf6,0x29,0x67,0x12,
+ 0x08,0xf0,0x06,0x24,0x71,0x12,0x61,0x0b,0x01,0x2a,0xf8,0xe7,0x06,0x2a,0xf2,0xe7,
+ 0x07,0x62,0x00,0x81,0x30,0x20,0x74,0x1b,0x72,0x1b,0x02,0x3c,0x11,0x06,0x31,0x0c,
+ 0x01,0xe8,0x31,0x05,0x44,0x06,0xf9,0xef,0x12,0x12,0xf5,0x37,0x01,0xe8,0x02,0x28,
+ 0xcf,0x00,0xf0,0x25,0x60,0x92,0x70,0x93,0x40,0x94,0x50,0x95,0x07,0x2d,0x27,0x16,
+ 0x25,0x12,0x05,0x3f,0x06,0x2d,0x46,0x16,0x41,0x12,0x01,0x3f,0x63,0x12,0x73,0x03,
+ 0x17,0x03,0x56,0x03,0x15,0x03,0x67,0x1c,0x31,0x12,0x01,0x3f,0x17,0x1c,0x67,0x0c,
+ 0x02,0xe0,0x06,0x33,0x65,0x1c,0x76,0x12,0x06,0x3f,0x56,0x1c,0x10,0x96,0x07,0x3d,
+ 0x06,0x2d,0x63,0x16,0x37,0x1c,0x00,0x97,0x00,0x86,0x10,0x87,0x20,0x96,0x30,0x97,
+ 0x50,0x87,0x27,0x03,0x70,0x86,0x46,0x03,0x67,0x1c,0x20,0x82,0x30,0x83,0x73,0x1c,
+ 0xf0,0x21,0xcf,0x00,0xf0,0x25,0x78,0x00,0x81,0x62,0x10,0x05,0x40,0x92,0x50,0x93,
+ 0x20,0x94,0x30,0x95,0x4d,0x12,0x57,0x12,0x2b,0x12,0x3e,0x12,0x05,0x2a,0x58,0xe0,
+ 0x43,0x0c,0x76,0xe0,0x06,0x2d,0x46,0x0c,0xd4,0xe0,0x87,0x2d,0x47,0x0c,0x8b,0xe9,
+ 0x07,0x61,0x75,0x12,0x9f,0x76,0xd3,0x12,0x73,0x0b,0x36,0x1c,0x06,0xa6,0x56,0x1c,
+ 0x07,0x62,0x67,0x05,0x07,0x2a,0x06,0xe8,0x7d,0x1b,0x7e,0x1b,0xb4,0x12,0x64,0x0b,
+ 0x4e,0x1e,0x7b,0x1b,0xdc,0x12,0x0c,0x3f,0x09,0x2d,0xd9,0x16,0xe2,0x12,0xc3,0x12,
+ 0x95,0x7f,0x28,0x12,0xe2,0x12,0xc3,0x12,0x94,0x7f,0x2a,0x12,0x2e,0x12,0x9e,0x03,
+ 0x08,0x3d,0xb7,0x12,0x07,0x3f,0x78,0x1e,0xe8,0x0c,0x08,0xe0,0x27,0x12,0x07,0x24,
+ 0xd8,0x1c,0xd8,0x0c,0x02,0xe8,0xe8,0x0c,0x8d,0xe9,0x7a,0x12,0x8e,0x14,0xe2,0x12,
+ 0xc3,0x12,0x88,0x7f,0x28,0x12,0xe2,0x12,0xc3,0x12,0x87,0x7f,0x27,0x12,0x29,0x03,
+ 0x08,0x3d,0x05,0x2d,0x5b,0x16,0xb8,0x1e,0x98,0x0c,0x08,0xe0,0x26,0x12,0x06,0x24,
+ 0xd8,0x1c,0xd8,0x0c,0x4b,0xe9,0x98,0x0c,0x49,0xe1,0x17,0x24,0xa2,0x12,0x02,0x3d,
+ 0x72,0x1e,0x0c,0x60,0xc3,0x12,0x81,0x62,0x10,0x1c,0x68,0x00,0xf0,0x21,0xcf,0x00,
+ 0x53,0x0c,0x77,0xe8,0x06,0x2d,0x56,0x0c,0x76,0xe0,0x86,0x2d,0x56,0x0c,0x45,0xe9,
+ 0x05,0x61,0x54,0x12,0x73,0x76,0x73,0x12,0x53,0x0b,0x36,0x1c,0x06,0xa6,0x46,0x1c,
+ 0x0c,0x62,0x6c,0x05,0x0c,0x2a,0x79,0xe0,0x12,0x60,0xe7,0x0c,0x03,0xe8,0xdb,0x0c,
+ 0x01,0xe0,0xc2,0x12,0xc3,0x12,0x81,0x62,0x10,0x1c,0x68,0x00,0xf0,0x21,0xcf,0x00,
+ 0x04,0x2a,0x04,0xe0,0x12,0x60,0x43,0x12,0x68,0x7f,0x2d,0x12,0x07,0x2d,0xd7,0x0c,
+ 0x5e,0xe0,0x87,0x2d,0xd7,0x0c,0x27,0xe9,0x06,0x61,0x65,0x12,0x61,0x77,0xd3,0x12,
+ 0x63,0x0b,0x37,0x1c,0x07,0xa6,0x56,0x1c,0x07,0x62,0x67,0x05,0x07,0x2a,0xbe,0xe0,
+ 0xde,0x05,0xda,0x12,0x0a,0x3f,0x08,0x2d,0xd8,0x16,0x1c,0x60,0xe2,0x12,0xa3,0x12,
+ 0x59,0x7f,0x60,0x92,0xe2,0x12,0xa3,0x12,0x58,0x7f,0x29,0x12,0x27,0x12,0x87,0x03,
+ 0x60,0x8e,0x0e,0x3d,0xb6,0x12,0x06,0x3f,0x6e,0x1e,0x7e,0x0c,0x08,0xe0,0x26,0x12,
+ 0x06,0x24,0xde,0x1c,0xde,0x0c,0x02,0xe8,0x7e,0x0c,0x11,0xe9,0x69,0x12,0x7e,0x05,
+ 0xe2,0x12,0xa3,0x12,0x4c,0x7f,0x60,0x92,0xe2,0x12,0xa3,0x12,0x4b,0x7f,0x26,0x12,
+ 0x28,0x03,0x60,0x87,0x07,0x3d,0x03,0x2d,0x3b,0x16,0xb7,0x1e,0x87,0x0c,0x08,0xe0,
+ 0x25,0x12,0x05,0x24,0xd7,0x1c,0xd7,0x0c,0xd3,0xe8,0x87,0x0c,0xd1,0xe0,0x16,0x24,
+ 0x92,0x12,0x02,0x3d,0x62,0x1e,0xc3,0x12,0x81,0x62,0x10,0x1c,0x68,0x00,0xf0,0x21,
+ 0xcf,0x00,0x0c,0x60,0x9e,0xf7,0x86,0x2c,0x56,0x0c,0xd2,0xe8,0x05,0x60,0x54,0x12,
+ 0x89,0xf7,0x86,0x2c,0x46,0x0c,0xb8,0xe0,0x87,0x60,0x75,0x12,0x2b,0xf7,0x87,0x2c,
+ 0xd7,0x0c,0xcc,0xe8,0x06,0x60,0x65,0x12,0xa1,0xf7,0x7a,0x12,0xca,0x1b,0xd7,0x12,
+ 0x67,0x0b,0x7a,0x1e,0xcd,0x1b,0x60,0x9d,0xe8,0x12,0x68,0x0b,0xe9,0x12,0xc9,0x1b,
+ 0xb7,0x12,0x67,0x0b,0x79,0x1e,0xad,0x12,0x0d,0x3f,0x04,0x2d,0xa4,0x16,0x70,0x94,
+ 0x82,0x12,0xd3,0x12,0x28,0x7f,0x2e,0x12,0x82,0x12,0xd3,0x12,0x27,0x7f,0x28,0x12,
+ 0x70,0x87,0x27,0x03,0x0e,0x3d,0x96,0x12,0x06,0x3f,0x6e,0x1e,0x7e,0x0c,0x06,0xe0,
+ 0x26,0x12,0x06,0x24,0xae,0x1c,0xae,0x0c,0xa9,0xe0,0x68,0x12,0x7e,0x05,0xe2,0x12,
+ 0xd3,0x12,0x1c,0x7f,0x80,0x92,0xe2,0x12,0xd3,0x12,0x1b,0x7f,0x70,0x86,0x26,0x03,
+ 0x80,0x87,0x07,0x3d,0x05,0x2d,0x59,0x16,0x97,0x1e,0x67,0x0c,0x06,0xe0,0x25,0x12,
+ 0x05,0x24,0xa7,0x1c,0xa7,0x0c,0x8d,0xe0,0x52,0x12,0x76,0x14,0x08,0x3d,0x28,0x1e,
+ 0x07,0x2d,0x87,0x16,0x84,0x12,0x04,0x3f,0x60,0x85,0x03,0x2d,0x35,0x16,0x60,0x8d,
+ 0x0d,0x3f,0x73,0x12,0x53,0x03,0xd7,0x03,0x45,0x03,0x4d,0x03,0x57,0x1c,0x34,0x12,
+ 0x04,0x3f,0x47,0x1c,0x57,0x0c,0x02,0xe0,0x04,0x33,0x4d,0x1c,0x75,0x12,0x05,0x3f,
+ 0xd5,0x1c,0x56,0x0c,0x5e,0xe8,0x56,0x0f,0x55,0xe8,0x82,0x12,0x0c,0x60,0x2a,0xf7,
+ 0x8c,0x05,0x00,0x00,0x08,0x84,0x00,0x00,0xd0,0x83,0x00,0x00,0x7d,0x1b,0xe9,0x12,
+ 0x69,0x0b,0xec,0x12,0x7c,0x1b,0xb4,0x12,0x64,0x0b,0x4c,0x1e,0x7b,0x1b,0xda,0x12,
+ 0x0a,0x3f,0x08,0x2d,0xd8,0x16,0x92,0x12,0xa3,0x12,0x34,0x7f,0x2e,0x12,0x92,0x12,
+ 0xa3,0x12,0x33,0x7f,0x29,0x12,0x27,0x12,0x87,0x03,0x0e,0x3d,0xc6,0x12,0x06,0x3f,
+ 0x6e,0x1e,0x7e,0x0c,0x09,0xe0,0x26,0x12,0x06,0x24,0xde,0x1c,0xde,0x0c,0x4d,0xe8,
+ 0x7e,0x0c,0x4b,0xe0,0x19,0x24,0xde,0x1c,0x7e,0x05,0xe2,0x12,0xa3,0x12,0x27,0x7f,
+ 0x60,0x92,0xe2,0x12,0xa3,0x12,0x26,0x7f,0x27,0x12,0x87,0x03,0x60,0x8e,0x0e,0x3d,
+ 0x05,0x2d,0x5c,0x16,0xce,0x1e,0x7e,0x0c,0x09,0xe0,0x26,0x12,0x06,0x24,0xde,0x1c,
+ 0xde,0x0c,0x31,0xe8,0x7e,0x0c,0x2f,0xe0,0x12,0x24,0xde,0x1c,0x7e,0x05,0x9c,0x12,
+ 0x0c,0x3d,0x2c,0x1e,0x03,0xf7,0x87,0x61,0x75,0x12,0x74,0xf6,0x67,0x12,0xb6,0xf6,
+ 0x56,0x12,0x2e,0xf7,0xcb,0x1b,0x07,0x3d,0x05,0x2d,0x53,0x16,0x37,0x1c,0x7b,0x0c,
+ 0xa4,0xe7,0x82,0x12,0x02,0x24,0x0c,0x60,0xcd,0xf6,0x85,0x61,0x54,0x12,0xba,0xf6,
+ 0x85,0x60,0x54,0x12,0xb7,0xf6,0x86,0x61,0x65,0x12,0xd8,0xf6,0x86,0x60,0x65,0x12,
+ 0xd5,0xf6,0x67,0x0c,0x71,0xe7,0x12,0x24,0xa7,0x1c,0x6f,0xf7,0x7e,0x0c,0x55,0xe7,
+ 0x18,0x24,0xae,0x1c,0x53,0xf7,0x62,0x12,0xd1,0xf7,0x69,0x12,0xb5,0xf7,0x19,0x24,
+ 0xde,0x1c,0xed,0xf6,0x1a,0x24,0xd8,0x1c,0x71,0xf6,0x00,0x00,0x08,0x84,0x00,0x00,
+ 0xd0,0x83,0x00,0x00,0xbe,0xbe,0xbe,0xbe,0xbe,0xbe,0xbe,0xbe,0x70,0x24,0x7e,0x00,
+ 0x0e,0x7f,0x06,0x66,0x0e,0x77,0x07,0xb6,0x0e,0x7f,0x0e,0x7f,0x0f,0x72,0x43,0x60,
+ 0x0f,0x7f,0x0f,0x7f,0x10,0x7f,0x10,0x7f,0x11,0x7e,0x0e,0xa7,0x17,0x2a,0x07,0xe8,
+ 0x07,0x2a,0x03,0xe8,0x27,0x2a,0xf9,0xe7,0x04,0xf0,0x0d,0x7f,0xf6,0xf7,0x0d,0x7f,
+ 0xf4,0xf7,0x0d,0x7f,0xf2,0xf7,0x00,0x00,0x40,0x08,0x00,0x00,0x20,0x01,0x04,0x00,
+ 0xaa,0x08,0x00,0x00,0x6c,0x26,0x00,0x00,0x80,0xc3,0xc9,0x01,0x9a,0x23,0x00,0x00,
+ 0x40,0x1b,0x00,0x00,0xec,0x0d,0x00,0x00,0x98,0x09,0x00,0x00,0x20,0xaa,0x00,0x00,
+ 0x88,0x1b,0x00,0x00,0x88,0x1c,0x00,0x00,0xfc,0x1c,0x00,0x00,0xbe,0xbe,0xbe,0xbe,
+ 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+}; \ No newline at end of file
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/lw86x0_ts/Kconfig b/ANDROID_3.4.5/drivers/input/touchscreen/lw86x0_ts/Kconfig
new file mode 100755
index 00000000..34cf42cb
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/lw86x0_ts/Kconfig
@@ -0,0 +1,11 @@
+config TOUCHSCREEN_LW86X0
+ tristate "LW86X0 Touchscreen Driver"
+ default y
+ depends on ARCH_WMT
+ ---help---
+ Say Y here if you have an WMT based board with touchscreen
+ attached to it.
+ If unsure, say N.
+ To compile this driver as a module, choose M here: the
+ module will be called lw86x0_ts.
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/lw86x0_ts/Makefile b/ANDROID_3.4.5/drivers/input/touchscreen/lw86x0_ts/Makefile
new file mode 100755
index 00000000..a7cbba75
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/lw86x0_ts/Makefile
@@ -0,0 +1,34 @@
+#KERNELDIR=/home/hangyan/android8850/kernel/ANDROID_3.0.8
+KERNELDIR=../../../../
+CROSS = arm_1103_le-
+CC= $(CROSS)gcc
+LD= $(CROSS)ld
+STRIP = $(CROSS)strip
+
+DEBUG = n
+
+# Add your debugging flag (or not) to EXTRA_CFLAGS
+ifeq ($(DEBUG),y)
+# DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+DEBFLAGS = -O0 -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+
+else
+ DEBFLAGS = -O2 -Wall
+endif
+
+EXTRA_CFLAGS += $(DEBFLAGS)
+
+
+MY_MODULE_NAME=s_wmt_ts_lw86x0
+
+obj-m := $(MY_MODULE_NAME).o
+$(MY_MODULE_NAME)-objs := lw86x0_ts.o wmt_ts.o
+
+default:
+ $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules
+ $(STRIP) --strip-debug $(MY_MODULE_NAME).ko
+ rm -rf *.o *~ core .depend .*.cmd *.mod.c .tmp_versions *.order *.symvers
+
+clean:
+ rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.order *.symvers
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/lw86x0_ts/lw86x0_ts.c b/ANDROID_3.4.5/drivers/input/touchscreen/lw86x0_ts/lw86x0_ts.c
new file mode 100755
index 00000000..ce741c9c
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/lw86x0_ts/lw86x0_ts.c
@@ -0,0 +1,1321 @@
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+//#include <linux/earlysuspend.h>
+#include <linux/delay.h>
+#include <linux/jiffies.h>
+#include <linux/cdev.h>
+#include <asm/uaccess.h>
+#include <linux/pm_runtime.h>
+
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+#include <linux/earlysuspend.h>
+#endif
+#include <linux/input/mt.h>
+
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <mach/hardware.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/suspend.h>
+#include <linux/async.h>
+#include <linux/wait.h>
+#include <linux/hrtimer.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/irq.h>
+#include <linux/kthread.h>
+#include <linux/firmware.h>
+#include <linux/power/wmt_battery.h>
+#include "../../../video/backlight/wmt_bl.h"
+#include "lw86x0_ts.h"
+#include "wmt_ts.h"
+//#include "wmt_custom_lw86x0.h"
+
+#define TIME_CHECK_CHARGE 3000
+
+#define MAX_MULTI_DATA_SIZE 256
+
+#define HDMI_BASE_ADDR (HDMI_TRANSMITTE_BASE_ADDR + 0xC000)
+#define REG_HDMI_HOTPLUG_DETECT (HDMI_BASE_ADDR + 0x3ec)
+
+struct i2c_client *lw_i2c_client = NULL;
+struct i2c_client *client;//add by jackie
+extern char g_dbgmode;
+extern int COL_NUM;
+extern int ROW_NUM;
+extern int SKIP_ZERO_POINT;
+
+struct wmtts_device lw86x0_tsdev;
+static int tsirq_gpio;
+
+static int skip_zero_num = 0;
+
+u16 mcu_status_old = 0xffff;
+u16 mcu_status = 0xffff;
+
+typedef struct Fw_Version{ //add by jackie
+ u8 magic_num1;
+ u8 magic_num2;
+ u8 mj_ver;
+ u8 mn_ver;
+}Fw_Ver;//add by jackie
+
+//struct for report touch info
+struct ts_event {
+ u16 x[SUPPORT_POINT_NUM_MAX];//point x
+ u16 y[SUPPORT_POINT_NUM_MAX];//point y
+ u16 pressure[SUPPORT_POINT_NUM_MAX];//point pressure
+ u8 touch_point;//touch point number
+};
+
+struct lw86x0_ts_data {
+ struct input_dev *input_dev;
+ struct ts_event event;
+ struct work_struct touch_event_work;
+ struct workqueue_struct *ts_workqueue;
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+ struct early_suspend early_suspend;
+#endif
+}l_tsdata;
+
+static struct mutex ts_data_mutex;
+static int l_powermode = -1;
+static int l_hdmimode = -1;
+
+static int l_keylen = 4;
+static int l_baseaxis = 1; //0:x-axis,1:y-axis
+int l_keypos[TS_KEY_NUM+1][2];
+
+unsigned int l_tskey[TS_KEY_NUM][2] = {
+ {0,KEY_MENU},
+ {0,KEY_HOME},
+ {0,KEY_BACK},
+ {0,KEY_SEARCH},
+};
+static int l_early_suspend = 0; // 1:the early suspend function has been excuted
+
+static int stop_timer = 0;
+struct work_struct phone_status_work;
+struct timer_list polling_phone_status_timer;
+static int check_chip_status(void);
+static int first_init_reg = 1;
+static u16 auto_coff_value[20] = {0};
+//static finger_up_status = 1;
+
+u8 get_fw_file_check_sum(void);
+u16 get_fw_check_sum(void);
+
+extern int register_bl_notifier(struct notifier_block *nb);
+
+extern int unregister_bl_notifier(struct notifier_block *nb);
+//static struct ts_event old_event;
+
+void swap_byte_in_buffer(u16* buf, int count )
+{
+ int i;
+ for(i = 0; i < count; i++ )
+ {
+ buf[i] = swap16(buf[i]);
+ }
+}
+
+/**
+** for read register
+** rxbuf:read value
+** txdata:read register address
+** rxlength:read value length
+**/
+
+static int lw86x0_i2c_rxdata(char *rxbuf, char*txdata, int rxlength)
+{
+ int ret;
+ //int reg;//add jackie
+
+ struct i2c_msg msgs[] = {
+ {
+ .addr = lw_i2c_client->addr,
+ .flags = 0,
+ .len = 2,
+ .buf = txdata,
+ },
+ {
+ .addr = lw_i2c_client->addr,
+ .flags = I2C_M_RD,
+ .len = rxlength,
+ .buf = rxbuf,
+ },
+ };
+
+ //ret = wmt_i2c_xfer_continue_if_4(msgs, 2, 1);
+
+ ret = i2c_transfer(lw_i2c_client->adapter, &msgs[0], 2);//add by jackie
+ if (ret != 2)
+ {
+ dbg("msg i2c rxdata error: %d\n", ret);
+ return -1;
+ }
+ else
+ {
+ return 0;
+ }
+
+#if 0
+ struct i2c_msg xfer_msg[2];
+ if (reg < 0x80) {
+ i2c_transfer(client->adapter, xfer_msg, ARRAY_SIZE(xfer_msg));
+ msleep(5);
+ }
+ return i2c_transfer(client->adapter, xfer_msg, ARRAY_SIZE(xfer_msg)) == ARRAY_SIZE(xfer_msg) ? 0 : -EFAULT;
+#endif
+
+}
+
+/**
+** for write register
+** txdata:register address and value u8
+** length:txdata length
+**/
+
+static int lw86x0_i2c_txdata(char *txdata, int length)
+{
+ int ret;
+
+ struct i2c_msg msg[] = {
+ {
+ .addr = lw_i2c_client->addr,
+ .flags = 0,
+ .len = length,
+ .buf = txdata,
+ },
+ };
+
+
+ ret = i2c_transfer(lw_i2c_client->adapter, &msg[0], 1);//1
+
+ //ret = wmt_i2c_xfer_continue_if_4(msg, 1, 1);
+ if (ret != 1)
+ {
+ dbg("i2c txdata error: %d\n", ret);
+ return -1;
+ }
+ else
+ {
+ return 0;
+ }
+
+}
+
+/**
+** Interface write register for other functions
+** addr:write register address
+** value:write register value
+**/
+
+int lw86x0_write_reg(u16 addr, u16 value)
+{
+ u8 buf[4];
+ int ret = -1;
+ unsigned char * pVal = (unsigned char *) &value;
+ unsigned char * pOffset = (unsigned char *) &addr;
+ buf[0] = pOffset[1];
+ buf[1] = pOffset[0];
+ buf[2] = pVal[1];
+ buf[3] = pVal[0];
+ ret = lw86x0_i2c_txdata(buf, 4);
+ if (ret < 0)
+ {
+ dbg("lw86x0_write_reg error: %d\n", ret);
+ return -1;
+ }
+ return 0;
+}
+
+/*int lw86x0_write_reg_multi(u16 start_addr, u16 value[], u16 num)
+{
+ u8 buf[MAX_MULTI_DATA_SIZE];
+ int ret = -1;
+ int i = 0;
+ unsigned char * pVal = (unsigned char *) &value[0];
+ unsigned char * pOffset = (unsigned char *) &addr;
+ buf[0] = pOffset[1];
+ buf[1] = pOffset[0];
+ //buf[2] = pVal[1];
+ //buf[3] = pVal[0];
+ for(i = 0; i < num; i++)
+ {
+ pVal = (unsigned char *) &value[i];
+ buf[2*i + 2] = pVal[1];
+ buf[2*i + 3] = pVal[0];
+ }
+
+ ret = lw86x0_i2c_txdata(buf, num*2+2);
+
+ if (ret < 0)
+ {
+ dbg("lw86x0_write_reg error: %d\n", ret);
+ return -1;
+ }
+ return 0;
+}*/
+/**
+** Interface read register for other functions
+** addr:read register address
+** pdata:read register value
+** regcnt:read register count
+**/
+
+int lw86x0_read_reg(u16 addr, u16 *pdata, int regcnt)
+{
+ int ret;
+
+ u16 offset_reverse = swap16(addr);
+ ret = lw86x0_i2c_rxdata((char*)pdata, (char*)&offset_reverse, 2*regcnt);
+
+ if (ret < 0)
+ {
+ dbg("lw86x0_read_reg error: %d\n", ret);
+ return -1;
+ }
+ else
+ {
+ swap_byte_in_buffer(pdata, regcnt);
+ return 0;
+ }
+}
+
+int wmt_ts_load_firmware(char* firmwarename, unsigned char** firmdata, int* fwlen)
+{
+ int i;
+ const struct firmware *fw_entry;
+ for (i = 0; i < 3; i++) {
+ if(request_firmware(&fw_entry, firmwarename, &lw_i2c_client->dev)!=0)
+ printk(KERN_ERR "cat't request firmware #%d\n", i);
+ else
+ break;
+ }
+ if (i == 3)
+ return -EINVAL;
+
+ if (fw_entry->size <= 0) {
+ printk(KERN_ERR "load firmware error\n");
+ release_firmware(fw_entry);
+ return -1;
+ }
+
+ *firmdata = kzalloc(fw_entry->size + 1, GFP_KERNEL);
+ memcpy(*firmdata, fw_entry->data, fw_entry->size);
+ *fwlen = fw_entry->size;
+ release_firmware(fw_entry);
+
+ return 0;
+}
+
+static u16 *default_setting_table;
+static int cfg_len;
+
+static int load_cfgfile(void)
+{
+ u32 val[2];
+ u16 temp[200];
+ int i = 0;
+ char cfgname[32] = {0};
+ u8 *pData;
+ int fileLen;
+ char *p;
+ char *s;
+
+ wmt_ts_get_configfilename(cfgname);
+ if (wmt_ts_load_firmware(cfgname, &pData, &fileLen)) {
+ errlog("Load config file failed~ \n");
+ return -1;
+ }
+ s = pData;
+ p = strstr(s, "COL_NUM");
+ sscanf(p, "COL_NUM=%d;", &COL_NUM);
+ p = strstr(s, "ROW_NUM");
+ sscanf(p, "ROW_NUM=%d;", &ROW_NUM);
+ p = strstr(s, "SKIP_ZERO_POINT");
+ sscanf(p, "SKIP_ZERO_POINT=%d;", &SKIP_ZERO_POINT);
+ dbg("COL_NUM=%d;ROW_NUM=%d;SKIP_ZERO_POINT=%d;",COL_NUM,ROW_NUM,SKIP_ZERO_POINT);
+
+ p = pData;
+ while (*p != '{') {
+ p++;
+ if(*p == '\0') {
+ errlog("Bad config file\n");
+ i = -1;
+ goto end;
+ }
+ }
+ while (*p != '}') {
+ if (!strncmp(p, "0x", 2)) {
+ i++;
+ if ((i & 0x0001) != 0) {
+ sscanf(p, "0x%x,0x%x,", val, val+1);
+ temp[i-1] = val[0] & 0x0000FFFF;
+ temp[i] = val[1] & 0x0000FFFF;
+ }
+ }
+ p++;
+ if(*p == '\0') {
+ i = -1;
+ errlog("Bad config file\n");
+ goto end;
+ }
+ };
+
+ dbg("the number of data:0x%x\n", i);
+ default_setting_table = kzalloc(i*2, GFP_KERNEL);
+ memcpy(default_setting_table, temp, i*2);
+ cfg_len = i;
+
+ dbg("paring config file end.\n");
+end:
+ kfree(pData);
+ return i;
+}
+
+void lw86x0_stop_timer(int flags)
+{
+ stop_timer = flags;
+}
+
+
+static u16 get_trim_info(void)
+{
+ u16 trim_info = 0;
+ u8 buf[2] = {0};
+ lw86x0_write_reg(0x00e4, 0x0000);
+ lw86x0_write_reg(0x00e2, 0x0302);
+ lw86x0_write_reg(0x00e3, 0x0000);
+ lw86x0_write_reg(0x00e2, 0x034e);
+ lw86x0_write_reg(0x00e2, 0x0302);
+ lw86x0_read_reg(0x00e4, buf, 1);
+ lw86x0_write_reg(0x00e2, 0x0000);
+ trim_info = buf[1];
+ dbg("trim info is %04x",trim_info);
+ return trim_info;
+}
+
+/**
+** load default register setting
+**/
+
+void lw86x0_load_def_setting(void)
+{
+ int i = 0;
+ u16 trim_value = 0;
+ u16 trim_info = 0;
+
+ lw86x0_write_reg(0x00e6, 0x3311);
+ trim_info = get_trim_info();
+ for(i = 0; i < cfg_len / 2; i++)
+ {
+ if(default_setting_table[2*i] == 0xffff)
+ {
+ msleep(default_setting_table[2*i+1]);
+ }
+ else
+ {
+ if(default_setting_table[2*i] == 0x00ee)
+ {
+ lw86x0_read_reg(0x00ee, &trim_value, 1);
+ if(trim_value == 0x00a0)
+ {
+ trim_value = 0x00c0 + trim_info;
+ }
+ else
+ {
+ trim_value = 0x100 + trim_value;
+ }
+ lw86x0_write_reg(0x00ee, trim_value);
+ }
+ else
+ {
+ lw86x0_write_reg(default_setting_table[2*i], default_setting_table[2*i+1]);
+ }
+ //lw86x0_write_reg(default_setting_table[2*i], default_setting_table[2*i+1]);
+ }
+ /*if(i == 0)
+ {
+ msleep(100);
+ }*/
+ }
+ if(first_init_reg == 1)
+ {
+ for(i = 0; i < 19; i++)
+ {
+ lw86x0_read_reg(0x0092+i, &auto_coff_value[i], 1);
+ }
+ first_init_reg = 0;
+ }
+ else
+ {
+ lw86x0_write_reg(0x0035, 0x0070);
+ lw86x0_write_reg(0x0060, 0x0307);
+ lw86x0_write_reg(0x0091, 0x0200);
+ for(i = 0; i < 19; i++)
+ {
+ lw86x0_write_reg(0x0092+i, auto_coff_value[i]);
+ }
+ lw86x0_write_reg(0x0035, 0x2070);
+ msleep(100);
+ lw86x0_write_reg(0x0060, 0x0306);
+ }
+}
+
+/**
+** set reset pin for lw86x0
+**/
+
+static void lw86x0_hw_reset(void)
+{
+ wmt_rst_output(0);
+ //msleep(500);
+ msleep(30);
+ wmt_rst_output(1);
+}
+
+static void lw86x0_ts_release(void)
+{
+ int i = 0;
+ struct lw86x0_ts_data *data = &l_tsdata;
+ int down = 0;
+
+ // dbg("lw86x0_ts_release");
+
+ for (i = 0; i < l_keylen; i++)
+ {
+ down |= l_tskey[i][0];
+ }
+ if (down != 0)
+ {
+ // if down clear the flag
+ for ( i = 0; i < l_keylen; i++)
+ {
+ l_tskey[i][0] = 0;
+ };
+ //dbg("key up!\n");
+ if (wmt_ts_enable_keyled())
+ wmt_ts_turnoff_light();
+ }
+ else
+ {
+ if (!lw86x0_tsdev.penup)
+ {
+ input_mt_sync(data->input_dev);
+ input_sync(data->input_dev);
+ //dbg("rpt pen\n");
+ }
+ lw86x0_tsdev.penup = 1;
+ //dbg("pen up\n");
+ //wake_up(&ts_penup_wait_queue);
+ }
+}
+
+/**
+**set wmt touch key count
+**/
+
+void wmt_ts_set_keylen(int keylen)
+{
+ l_keylen = keylen;
+}
+
+/**
+**set wmt touch baseaxis
+**axis:0--x axis,1--y axis.
+**/
+
+void wmt_ts_set_baseaxis(int axis)
+{
+ l_baseaxis = axis;
+}
+
+/**
+** set wmt touch key info struct keypos
+** index:set key number
+** min:key min point value
+** max:key max point value
+**/
+
+void wmt_ts_set_keypos(int index, int min,int max)
+{
+ l_keypos[index][0] = min;
+ l_keypos[index][1] = max;
+}
+
+/**
+** report key info to wmt android
+**/
+#if 0
+
+static int lw86x0_report_key_info(void)
+{
+ struct lw86x0_ts_data *data = &l_tsdata;
+ u16 x, y;
+ u16 key_stpos,key_vrpos; // the stable and variable position for touch key
+ int i =0;
+ lw86x0_read_reg(0x0161, &x, 1);
+ lw86x0_read_reg(0x016B, &y, 1);
+ if (wmt_ts_enable_tskey() != 0)
+ {
+ switch (l_baseaxis)
+ {
+ case 0:
+ key_stpos = y;
+ key_vrpos = x;
+ break;
+ case 1:
+ default:
+ key_stpos = x;
+ key_vrpos = y;
+ break;
+ }
+ }
+ for (i=0;i < l_keylen;i++)
+ {
+ if ((key_vrpos>=l_keypos[i][0]) && (key_vrpos<=l_keypos[i][1]))
+ {
+ // report the key
+ if (0 == l_tskey[i][0])
+ {
+ input_report_key(data->input_dev, l_tskey[i][1], 1);
+ input_report_key(data->input_dev, l_tskey[i][1], 0);
+ input_sync(data->input_dev);
+ l_tskey[i][0] = 1;
+ dbg("report tskey:%d\n",i);
+ if (wmt_ts_enable_keyled())
+ wmt_ts_turnon_light();
+ }
+ return 1;//key
+ }
+ }
+ return 0;//no key
+
+}
+#endif
+
+static void check_mode(void)
+{
+ int dcin = wmt_charger_is_dc_plugin();
+ int hdmiin = (REG32_VAL(REG_HDMI_HOTPLUG_DETECT) & BIT31) >> 31;
+
+ if (dcin == l_powermode && hdmiin == l_hdmimode)
+ return;
+ if (!dcin && !hdmiin) {
+ klog("DC and HDMI removed\n");
+ lw86x0_write_reg(0x01e9, 0x0000);
+ } else {
+ klog("DC or HDMI in\n");
+ lw86x0_write_reg(0x01e9, 0x0001);
+ }
+ l_powermode = dcin;
+ l_hdmimode = hdmiin;
+}
+
+/**
+** report touch info to wmt android
+** touch_number: touch count
+**/
+
+static void lw86x0_report_touch_info(u16 touch_number)
+{
+ struct lw86x0_ts_data *data = &l_tsdata;
+ struct ts_event *event = &data->event;
+ u16 i;
+
+ //old_event = *event;
+ //dbg("Enter into lw86x0_report_touch_info");
+ check_mode();
+ if(touch_number == 0)
+ {
+ input_mt_sync(data->input_dev);
+ input_sync(data->input_dev);
+ return;
+ }
+ if(touch_number> wmt_ts_get_fingernum()){
+ //dbg("Invalid Touch point count is found %d",touch_number);
+ return;
+ }
+ event->touch_point = touch_number;
+
+ //memset(event->x, 0, SUPPORT_POINT_NUM*sizeof(u16) );
+ //memset(event->y, 0, SUPPORT_POINT_NUM*sizeof(u16) );
+ //memset(event->pressure, 0, SUPPORT_POINT_NUM*sizeof(u16) );
+ for( i = 0; i <touch_number; i++ )
+ {
+ lw86x0_read_reg(0x0161+i, &event->x[i], 1);
+ lw86x0_read_reg(0x016B+i, &event->y[i], 1);
+ lw86x0_read_reg(0x0175+i, &event->pressure[i], 1);
+ }
+
+ for (i = 0; i < touch_number; i++)
+ {
+ int x = (event->x[i]) & 0x03ff;
+ int y = (event->y[i]) & 0x03ff;
+ int id = ((event->x[i])>>12)&0x000f;
+ int tmp;
+
+ if(x>wmt_ts_get_resolvX())
+ {
+ x = wmt_ts_get_resolvX();
+ }
+
+ if(y>wmt_ts_get_resolvY())
+ {
+ y= wmt_ts_get_resolvY();
+ }
+
+ if (wmt_ts_get_xaxis()) {
+ tmp = x;
+ x = y;
+ y = tmp;
+ }
+ if (wmt_ts_get_xdir())
+ x = wmt_ts_get_resolvX() - x;
+ if (wmt_ts_get_ydir())
+ y = wmt_ts_get_resolvY() - y;
+
+ if (wmt_ts_get_lcdexchg()) {
+ int tmp;
+ tmp = x;
+ x = y;
+ y = wmt_ts_get_resolvX() - tmp;
+ }
+
+ dbg("id %d [%d, %d] p %d",id, x, y, event->pressure[i]);
+ //input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR,event->pressure[i]);
+ input_report_abs(data->input_dev, ABS_MT_POSITION_X, x);
+ input_report_abs(data->input_dev, ABS_MT_POSITION_Y, y);
+ input_report_abs(data->input_dev, ABS_MT_TRACKING_ID, id);
+ input_mt_sync(data->input_dev);
+ }
+ /* SYN_REPORT */
+ input_sync(data->input_dev);
+}
+
+/**
+**lw86x0 touch irq work function
+**/
+
+static void lw86x0_ts_touch_irq_work(struct work_struct *work)
+{
+
+ u16 int_touch_status=0;
+ mutex_lock(&ts_data_mutex);
+
+ //dbg("Enter into lw86x0_ts_touch_irq_work");
+
+ //finger_up_status = 0;
+ lw86x0_read_reg(0x01f5, &int_touch_status, 1);
+
+ //dbg("Read 0x1f5 = %d",int_touch_status);
+ if( int_touch_status & 0x0001)
+ {
+ u16 touch_number=0;
+ lw86x0_read_reg(0x0160, &touch_number, 1);
+ //dbg("tn=%d\n",touch_number);
+ if(touch_number==0)
+ {
+ skip_zero_num++;
+ if(SKIP_ZERO_POINT==skip_zero_num)
+ {
+ dbg("tn=%d\n",touch_number);
+ lw86x0_write_reg(0x01f2, 0x0010);
+ lw86x0_report_touch_info(touch_number);
+ lw86x0_ts_release();
+ //finger_up_status = 1;
+ }
+ else if(SKIP_ZERO_POINT<skip_zero_num)
+ {
+ skip_zero_num = SKIP_ZERO_POINT+1;
+ }
+ }
+ else if(touch_number==15)
+ {
+ //dbg("touch_number=%d\n",touch_number);
+ }
+ else
+ {
+ dbg("tn=%d\n",touch_number);
+ lw86x0_write_reg(0x01f2, 0x0011);
+ skip_zero_num = 0;
+ lw86x0_report_touch_info(touch_number);
+ }
+ }
+ else
+ {
+ //finger_up_status = 1;
+ }
+ lw86x0_write_reg(0x01f5, 0xffff);//clear interrupt
+ //mdelay(500);
+ //dbg("clear interrupt 1");
+ lw86x0_write_reg(0x01f5, 0xffff);//clear interrupt
+ //mdelay(500);
+ //dbg("clear interrupt 2");
+ //lw86x0_write_reg(0x01f5, 0xffff);//clear interrupt
+ //mdelay(500);
+ //dbg("clear interrupt 3");
+ //lw86x0_write_reg(0x01f5, 0xffff);//clear interrupt
+ //mdelay(500);
+ //dbg("clear interrupt 4");
+ //dbg("Write 0x1f5 = 0xffff");
+ //lw86x0_read_reg(0x01f5, &int_touch_status, 1);
+ //dbg("Re-Read 0x1f5 = %d",int_touch_status);
+
+ if(g_dbgmode==0)
+ {
+ //dbg("Enable Irq");
+ wmt_enable_gpirq(tsirq_gpio);
+ }
+ mutex_unlock(&ts_data_mutex);
+}
+
+static irqreturn_t lw86x0_ts_interrupt(int irq, void *dev_id)
+{
+ //dbg("enter lw86x0_ts_interrupt");
+ //if (!wmt_is_tsirq_enable(tsirq_gpio))
+ //{
+ // dbg("tsirq not enabled");
+ // return IRQ_NONE;
+ //}
+ if (wmt_is_tsint(tsirq_gpio))
+ {
+ wmt_clr_int(tsirq_gpio);
+ wmt_disable_gpirq(tsirq_gpio);
+ if(!l_early_suspend)
+ {
+ //dbg("tsirq enabled");
+ queue_work(l_tsdata.ts_workqueue, &l_tsdata.touch_event_work);
+ }
+ return IRQ_HANDLED;
+ }
+ return IRQ_NONE;
+}
+
+static void reset_chip(void)
+{
+ printk("\nReset LW IC\n\n");
+ lw86x0_write_reg(0x00e6, 0x3311);
+ lw86x0_write_reg(0x00e0, 0x0005);
+ lw86x0_write_reg(0x0214, 0x0020);
+ lw86x0_write_reg(0x033d, 0x8100);
+ mdelay(500);
+ wmt_rst_output(0);
+ wmt_set_irq_mode(tsirq_gpio, 0);
+ mdelay(100);
+ wmt_rst_output(1);
+ wmt_set_gpirq(tsirq_gpio, GIRQ_FALLING);
+ lw86x0_load_def_setting();
+ if(g_dbgmode==0)
+ {
+ wmt_enable_gpirq(tsirq_gpio);
+ }
+}
+
+
+static int check_chip_status(void)
+{
+ u16 read_value = 0;
+ u16 read_sram = 0;
+ int ret = lw86x0_read_reg(0x00e6, &read_value, 1);
+ if(ret != 0)
+ {
+ reset_chip();
+ return 0;
+ }
+ if(read_value != 0x3311)
+ {
+ reset_chip();
+ return 0;
+ }
+ else
+ {
+ lw86x0_read_reg(0x00e0, &read_value, 1);
+ if(read_value != 0x0005 && read_value != 0x000d)
+ {
+ dbg("0x00e0!=0x0005,0x000d\n");
+ reset_chip();
+ return 0;
+ }
+ lw86x0_read_reg(0x0180, &read_sram, 1);
+ if(read_sram != 0)
+ {
+ dbg("0x0180!=0\n");
+ reset_chip();
+ return 0;
+ }
+ lw86x0_read_reg(0x0181, &mcu_status, 1);
+ if(mcu_status_old == mcu_status)
+ {
+ dbg("0x0180 old!=new\n");
+ reset_chip();
+ mcu_status_old = mcu_status;
+ return 0;
+ }
+ else
+ {
+ mcu_status_old = mcu_status;
+ return 1;
+ }
+ }
+ return 1;
+}
+
+static void phone_status_listener(struct work_struct *work)
+{
+ if(stop_timer == 0)
+ {
+ check_chip_status();
+ }
+}
+
+static void lw86x0_ts_polling_phone_status(long unsigned int dev_addr)
+{
+ schedule_work(&phone_status_work);
+ mod_timer(&polling_phone_status_timer, jiffies + msecs_to_jiffies(2000));
+}
+
+/**
+** lw86x0 ts early suspend function
+**/
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void ts_early_suspend(void)
+{
+ wmt_disable_gpirq(tsirq_gpio);
+}
+
+//#ifdef CONFIG_HAS_EARLYSUSPEND
+
+static void lw86x0_ts_early_suspend(struct early_suspend *handler)
+{
+ printk("lw86x0_ts_early_suspend\n");
+ ts_early_suspend();
+ l_early_suspend = 1;
+ lw86x0_write_reg(0x000c, 0xffff);
+ lw86x0_write_reg(0x033d, 0x0d60);
+ lw86x0_write_reg(0x00e2, 0x0300);
+ lw86x0_write_reg(0x000d, 0x4000);
+ lw86x0_write_reg(0x00e5, 0x4c01);
+ stop_timer = 1;
+}
+
+/**
+** lw86x0 late resume function
+**/
+static void ts_late_resume(void)
+{
+ printk("ts_late_resume\n");
+ //wmt_disable_gpirq(tsirq_gpio);
+ //lw86x0_hw_reset();
+ l_early_suspend = 0;
+
+ wmt_set_gpirq(tsirq_gpio, GIRQ_FALLING);
+ if(g_dbgmode==0)
+ {
+ printk("g_dbgmode==0\n");
+ wmt_enable_gpirq(tsirq_gpio);
+ }
+}
+
+
+static void lw86x0_ts_late_resume(struct early_suspend *handler)
+{
+ printk("==lw86x0_ts_resume=\n");
+ int ret = check_chip_status();
+ if(ret == 1)
+ {
+ lw86x0_write_reg(0x000d, 0xc000);
+ lw86x0_write_reg(0x00e2, 0x0100);
+ lw86x0_write_reg(0x00e5, 0x4c00);
+ lw86x0_write_reg(0x000c, 0xffff);
+ }
+ ts_late_resume();
+ l_early_suspend = 0;
+ stop_timer = 0;
+}
+#endif
+
+/**
+** lw86x0 ts suspend function
+**/
+
+static int lw86x0_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ return 0;
+}
+
+/**
+** lw86x0 resume function
+**/
+
+static int lw86x0_resume(struct platform_device *pdev)
+{
+ lw86x0_hw_reset();
+ first_init_reg = 1;
+ lw86x0_load_def_setting();
+ return 0;
+}
+
+#ifdef SUPPORT_FW_UPGRADE
+//add by jackie
+#define BYTES_PER_PACKET 64
+//#define FILEPATH "/etc/firmware/TOUCH.BIN"
+int fileLen;
+u8 *pData;
+
+void read_data_from_fw_file(void)
+{
+ char fwname[32] = {0};
+ wmt_ts_get_firmwfilename(fwname);
+ if (wmt_ts_load_firmware(fwname, &pData, &fileLen)) {
+ dbg("Load firmware file failed~ \n");
+ return;
+ }
+}
+
+u8 check_fw_version(void)
+{
+ //Fw_Ver* pfwVerInFile = NULL;
+ //Fw_Ver fwVer;
+
+ u16 fw_check_sum;
+ u16 fw_file_check_sum = 0;
+
+ read_data_from_fw_file();
+ /*pfwVerInFile = (Fw_Ver* )&(pData[0x2000]);
+
+ printk("struct data:%c%c%d%d\n",pfwVerInFile->magic_num1,pfwVerInFile->magic_num2,pfwVerInFile->mj_ver,pfwVerInFile->mn_ver);//add by jackie
+ lw86x0_write_reg(0x00e6,0x3311);
+ lw86x0_flash_read((u8*)&fwVer,0x2000,4);
+ printk("lw86x0_flash:%c%c%d%d\n",fwVer.magic_num1,fwVer.magic_num2,fwVer.mj_ver,fwVer.mn_ver);//add by jackie
+ //printk("lw86x0_flash:%d%d\n",fwVer.magic_num1,fwVer.magic_num2);//add by jackie
+ if((fwVer.magic_num1!='L'||fwVer.magic_num2!='W')
+ ||((fwVer.magic_num1=='L'&&fwVer.magic_num2=='W')
+ &&(pfwVerInFile->magic_num1=='L'&&pfwVerInFile->magic_num2=='W')
+ &&(fwVer.mj_ver!=pfwVerInFile->mj_ver || fwVer.mn_ver!=pfwVerInFile->mn_ver))
+ )*/
+ lw86x0_write_reg(0x00e6, 0x3311);
+ lw86x0_write_reg(0x0020, 0x9000);
+ lw86x0_write_reg(0x0002, 0x8900);
+ lw86x0_write_reg(0x0115, 0x0100);
+ lw86x0_write_reg(0x0020, 0x1000);
+ msleep(200);
+ fw_check_sum = get_fw_check_sum();
+ fw_file_check_sum = get_fw_file_check_sum();
+ printk("**********fw_check_sum = %04x, fw_file_check_sum = %04x\n",fw_check_sum,fw_file_check_sum);
+ if(((fw_check_sum&0xff00)!=0x8000)||((fw_check_sum&0x00ff)!=fw_file_check_sum))
+ {
+ lw86x0_write_reg(0x0002, 0x8800);
+ printk("firmware crc check is not equal, update firmware......\n");
+ return 1;//return 1 means needing upgrade
+ }
+ else
+ {
+ printk("firmware is not updated......\n");
+ lw86x0_write_reg(0x0002, 0x8800);
+ return 0;
+ }
+}
+
+void fw_download(void)
+{
+ int pkt_num = (fileLen+BYTES_PER_PACKET-1)/BYTES_PER_PACKET;
+ int i;
+ int last_pkt_size = ((int)fileLen) % BYTES_PER_PACKET;
+ printk("pkt_num is:%d\n",pkt_num);//add
+ if(last_pkt_size==0)
+ {
+ last_pkt_size = BYTES_PER_PACKET;
+ }
+ lw86x0_flash_write_prepare();
+ for(i=0;i<pkt_num;i++)
+ {
+ lw86x0_flash_write(&pData[i*BYTES_PER_PACKET],i*BYTES_PER_PACKET,(i==pkt_num-1)?last_pkt_size:BYTES_PER_PACKET);
+ }
+ lw86x0_flash_write_finish(fileLen);
+ printk("firmware is updated......\n");//add
+}
+
+
+u8 get_fw_file_check_sum(void)
+{
+ //u16 dataLen;
+ //u8* pData = NULL;
+ u16 i;
+ u8 checksum = 0;
+ printk("**********dataLen = %04x\n",fileLen);
+ for(i=0;i<fileLen;i++)
+ {
+ checksum+=pData[i];
+ }
+ return checksum;
+}
+
+u16 get_fw_check_sum(void)
+{
+ u8 cnt = 10;
+ u16 check_sum = 0;
+ //u16 fw_length = 0;
+ while(cnt>0)
+ {
+ lw86x0_read_reg(0x0182, &check_sum, 1);
+ printk("**********check_sum = %04x\n",check_sum);
+ if((check_sum&0xff00)==0x8000)
+ {
+ break;
+ }
+ cnt--;
+ msleep(100);
+ }
+ return check_sum;
+}
+
+static void fw_upgrader(void)
+{
+ u16 fw_check_sum;
+ u16 fw_file_check_sum = 0;
+
+ if(check_fw_version()==0)
+ {
+ return;
+ }
+
+ lw86x0_write_reg(0x00e6, 0x3311);
+ fw_download();
+ lw86x0_write_reg(0x0020, 0x9000);
+ lw86x0_write_reg(0x0002, 0x8900);
+ lw86x0_write_reg(0x0115, 0x0100);
+ lw86x0_write_reg(0x0020, 0x1000);
+ msleep(200);
+ fw_check_sum = get_fw_check_sum();
+ fw_file_check_sum = get_fw_file_check_sum();
+ printk("**********fw_check_sum = %04x, fw_file_check_sum = %04x\n",fw_check_sum,fw_file_check_sum);
+ if(((fw_check_sum&0xff00)!=0x8000)||((fw_check_sum&0x00ff)!=fw_file_check_sum))
+ {
+ printk("*********redownload fw\n");
+ fw_download();
+ lw86x0_write_reg(0x00e6, 0x3311);
+ lw86x0_write_reg(0x0020, 0x9000);
+ lw86x0_write_reg(0x0002, 0x8900);
+ lw86x0_write_reg(0x0115, 0x0100);
+ lw86x0_write_reg(0x0020, 0x1000);
+ msleep(200);
+ fw_check_sum = get_fw_check_sum();
+ fw_file_check_sum = get_fw_file_check_sum();
+ printk("**********re-check fw_check_sum = %04x, fw_file_check_sum = %04x\n",fw_check_sum,fw_file_check_sum);
+ if(((fw_check_sum&0xff00)!=0x8000)||((fw_check_sum&0x00ff)!=fw_file_check_sum))
+ {
+ lw86x0_flash_write_prepare();
+ }
+ }
+ else
+ {
+ }
+ lw86x0_write_reg(0x0002, 0x8800);
+ kfree(pData);
+ lw86x0_hw_reset();
+
+}
+
+#endif
+
+
+static int wmt_wakeup_bl_notify(struct notifier_block *nb, unsigned long event,
+ void *dummy)
+{
+ //printk("get notify\n");
+ switch (event) {
+ case BL_CLOSE:
+ l_early_suspend = 1;
+ wmt_disable_gpirq(tsirq_gpio);
+ stop_timer = 1;
+ cancel_work_sync(&l_tsdata.touch_event_work);
+ cancel_work_sync(&phone_status_work);
+ printk("\nclose backlight\n\n");
+ break;
+ case BL_OPEN:
+ l_early_suspend = 0;
+ wmt_enable_gpirq(tsirq_gpio);
+ lw86x0_write_reg(0x01f5,0xffff);//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ stop_timer = 0;
+ printk("\nopen backlight\n\n");
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block wmt_bl_notify = {
+ .notifier_call = wmt_wakeup_bl_notify,
+};
+
+static int lw86x0_ts_probe(struct platform_device *pdev)
+{
+ int err = 0;
+ int i = 0;
+ u16 read_from_e6 = 0;
+ lw_i2c_client = ts_get_i2c_client();//get i2c_client
+
+ memset(&l_tsdata, 0 ,sizeof(l_tsdata));
+ INIT_WORK(&l_tsdata.touch_event_work, lw86x0_ts_touch_irq_work);
+ mutex_init(&ts_data_mutex);
+
+ l_tsdata.ts_workqueue = create_singlethread_workqueue("lw86x0-ts-queue");
+ if (!l_tsdata.ts_workqueue) {
+ err = -ESRCH;
+ goto exit_create_singlethread;
+ }
+
+ l_tsdata.input_dev = input_allocate_device();
+ if (!l_tsdata.input_dev) {
+ err = -ENOMEM;
+ dbg("failed to allocate input device\n");
+ goto exit_input_dev_alloc_failed;
+ }
+
+ l_tsdata.input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ l_tsdata.input_dev->propbit[0] = BIT_MASK(INPUT_PROP_DIRECT);
+
+ if (wmt_ts_get_lcdexchg()) {
+ input_set_abs_params(l_tsdata.input_dev,
+ ABS_MT_POSITION_X, 0, wmt_ts_get_resolvY(), 0, 0);
+ input_set_abs_params(l_tsdata.input_dev,
+ ABS_MT_POSITION_Y, 0, wmt_ts_get_resolvX(), 0, 0);
+ } else {
+ input_set_abs_params(l_tsdata.input_dev,
+ ABS_MT_POSITION_X, 0, wmt_ts_get_resolvX(), 0, 0);
+ input_set_abs_params(l_tsdata.input_dev,
+ ABS_MT_POSITION_Y, 0, wmt_ts_get_resolvY(), 0, 0);
+ }
+ input_set_abs_params(l_tsdata.input_dev,
+ ABS_MT_TRACKING_ID, 0, 15, 0, 0);
+
+ l_tsdata.input_dev->name = LW86X0_NAME;
+ for (i = 0; i < TS_KEY_NUM; i++)
+ {
+ set_bit(l_tskey[i][1], l_tsdata.input_dev->keybit);
+ };
+ err = input_register_device(l_tsdata.input_dev);
+ if (err) {
+ errlog("lw86x0_ts_probe: failed to register input device.");
+ goto exit_input_register_device_failed;
+ }
+
+#ifdef SUPPORT_FW_UPGRADE
+ fw_upgrader();
+ mdelay(500);
+#endif
+
+ err = load_cfgfile();
+ if (err < 0)
+ goto exit_load_cfgfile_failed;
+ lw86x0_load_def_setting();
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ l_tsdata.early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB+ 1;
+ l_tsdata.early_suspend.suspend = lw86x0_ts_early_suspend;
+ l_tsdata.early_suspend.resume = lw86x0_ts_late_resume;
+ register_early_suspend(&l_tsdata.early_suspend);
+#endif
+
+ // init interrupt gpio
+ tsirq_gpio = wmt_ts_get_gpionum();
+ wmt_set_gpirq(tsirq_gpio, GIRQ_FALLING);//GIRQ_FALLING);
+ wmt_disable_gpirq(tsirq_gpio);
+
+ if(request_irq(wmt_get_tsirqnum(), lw86x0_ts_interrupt, IRQF_SHARED, "ts_lw86x0", l_tsdata.input_dev) < 0){
+ errlog("Could not allocate intrrupt for ts_lw86x0 !\n");
+ err = -1;
+ goto exit_register_irq;
+ }
+ lw86x0_ts_touch_irq_work(&l_tsdata.touch_event_work);
+ if(g_dbgmode==0)
+ {
+ wmt_enable_gpirq(tsirq_gpio);
+ }
+ msleep(5);
+ dbg("irqgpio=%d,irq=%d,resetgpio=%d\n", tsirq_gpio, wmt_get_tsirqnum(),wmt_ts_get_resetgpnum());
+
+ lw86x0_read_reg(0x00e6, &read_from_e6, 1);
+ if(read_from_e6 == 0x3311 || read_from_e6 == 0xa311)
+ {
+ INIT_WORK(&phone_status_work, phone_status_listener);
+ init_timer(&polling_phone_status_timer);
+ setup_timer(&polling_phone_status_timer, lw86x0_ts_polling_phone_status, (long unsigned int) pdev);
+ lw86x0_ts_polling_phone_status((long unsigned int) pdev);
+ }
+
+ register_bl_notifier(&wmt_bl_notify);
+
+ return 0;
+exit_register_irq:
+#ifdef CONFIG_HAS_EARLYSUSPEND//add by jackie
+ unregister_early_suspend(&l_tsdata.early_suspend);
+#endif
+ kfree(default_setting_table);
+exit_load_cfgfile_failed:
+
+exit_input_register_device_failed:
+ input_free_device(l_tsdata.input_dev);
+exit_input_dev_alloc_failed:
+ cancel_work_sync(&l_tsdata.touch_event_work);
+ destroy_workqueue(l_tsdata.ts_workqueue);
+exit_create_singlethread:
+ return err;
+}
+
+static int lw86x0_ts_remove(struct platform_device *pdev)
+{
+ kfree(default_setting_table);
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&l_tsdata.early_suspend);
+#endif
+ free_irq(wmt_get_tsirqnum(), l_tsdata.input_dev);
+ input_unregister_device(l_tsdata.input_dev);
+ flush_workqueue(l_tsdata.ts_workqueue);
+ cancel_work_sync(&l_tsdata.touch_event_work);
+ destroy_workqueue(l_tsdata.ts_workqueue);
+ mutex_destroy(&ts_data_mutex);
+ del_timer(&polling_phone_status_timer);
+ unregister_bl_notifier(&wmt_bl_notify);
+ dbg("remove...\n");
+ return 0;
+}
+
+
+static int lw86x0_ts_init(void)
+{
+ dbg("lw86x0_ts_init\n");
+ lw86x0_hw_reset();
+ return 0;
+}
+
+static void lw86x0_ts_exit(void)
+{
+ dbg("lw86x0_ts_exit\n");
+}
+
+struct wmtts_device lw86x0_tsdev = {
+ .driver_name = "s_lw86x0_ts",
+ .ts_id = "lw86x0",
+ .init = lw86x0_ts_init,
+ .exit = lw86x0_ts_exit,
+ .probe = lw86x0_ts_probe,
+ .remove = lw86x0_ts_remove,
+ .suspend = lw86x0_suspend,
+ .resume = lw86x0_resume,
+ .penup = 1,
+};
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/lw86x0_ts/lw86x0_ts.h b/ANDROID_3.4.5/drivers/input/touchscreen/lw86x0_ts/lw86x0_ts.h
new file mode 100755
index 00000000..cc2d9e26
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/lw86x0_ts/lw86x0_ts.h
@@ -0,0 +1,53 @@
+#ifndef _LW86X0_TS_H_
+#define _LW86X0_TS_H_
+
+//#include "wmt_custom_lw86x0.h"
+
+// define byte swap of a WORD
+#define swap16(a) ((((a)&0xff)<<8)|(((a)>>8)&0xff))
+
+//struct _reg_word for ioctl read or write register
+#define LW86X0_NAME "touch_lw86x0"
+
+#define SUPPORT_FW_UPGRADE
+#define TS_KEY_NUM 4
+#define COL_NUM_MAX 28
+#define ROW_NUM_MAX 16
+#define SUPPORT_POINT_NUM_MAX 10
+#define MULTI_DATA_MAX_SIZE 49
+
+typedef struct _reg_word
+{
+ u16 uOffset;
+ u16 uValue;
+ u16 multi_data[MULTI_DATA_MAX_SIZE];
+ int data_size;
+}reg_word;
+
+//struct _flash_op for ioctl write or read frimware
+#define FLASH_XFER_PKT_SIZE 256
+typedef struct _flash_op
+{
+ u16 startaddr; //=0 if the first pkt
+ u16 lastpkt; // =1 if last pkt; =0, otherwise
+ u16 pktlen; //data length in this pkt
+ char data[FLASH_XFER_PKT_SIZE];
+}flash_op;
+
+//struct _raw_data for ioctl read cdc/amb/diff data
+typedef struct _raw_data
+{
+ u8 row;
+ u8 col;
+ u16 data[COL_NUM_MAX*ROW_NUM_MAX];
+}rawdata;
+
+extern void wmt_ts_set_keylen(int keylen);
+extern void wmt_ts_set_baseaxis(int axis);
+extern void wmt_ts_set_keypos(int index, int min,int max);
+extern int lw86x0_write_reg(u16 addr, u16 value);
+extern int lw86x0_read_reg(u16 addr, u16 *pdata, int regcnt);
+extern void getversion(void);
+extern void lw86x0_stop_timer(int flags);
+
+#endif
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/lw86x0_ts/wmt_ts.c b/ANDROID_3.4.5/drivers/input/touchscreen/lw86x0_ts/wmt_ts.c
new file mode 100755
index 00000000..505dedfd
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/lw86x0_ts/wmt_ts.c
@@ -0,0 +1,1165 @@
+#include <linux/unistd.h>
+#include <linux/time.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/suspend.h>
+#include <linux/proc_fs.h>
+#include <linux/input.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <mach/hardware.h>
+#include <asm/uaccess.h>
+#include <linux/i2c.h>//add
+#include "wmt_ts.h"
+#include "lw86x0_ts.h"
+//#include "wmt_custom_lw86x0.h"
+
+
+struct i2c_client *l_client = NULL;
+
+
+
+/////////////////////////////////////////////////////////////////
+
+// commands for ui
+#define TS_IOC_MAGIC 't'
+#define LW86X0_READ_REG _IOWR(TS_IOC_MAGIC, 1, int*)
+#define LW86X0_WRITE_REG _IOW(TS_IOC_MAGIC, 2, int*)
+#define LW86X0_FLASH_DOWNLOAD _IOW(TS_IOC_MAGIC, 3, int *)
+#define LW86X0_FLASH_UPLOAD _IOWR(TS_IOC_MAGIC, 4, int *)
+#define LW86X0_CTRL_DEBUG_MODE _IOW(TS_IOC_MAGIC, 5, int *)
+#define LW86X0_CTRL_RD_DIFF _IOR(TS_IOC_MAGIC, 6, int *)
+#define LW86X0_CTRL_RD_CDC _IOR(TS_IOC_MAGIC, 7, int *)
+#define LW86X0_CTRL_RD_AMB _IOR(TS_IOC_MAGIC, 8, int *)
+#define LW86X0_CTRL_STOP_TIMER _IOR(TS_IOC_MAGIC, 15, int *)
+#define TS_IOC_MAXNR 15
+
+//
+#define TS_MAJOR 11
+#define TS_DRIVER_NAME "wmtts_touch"
+#define TS_NAME "wmtts"
+#define WMTTS_PROC_NAME "wmtts_config"
+
+#define LIGHT_ON_WAIT_TIME 5000 // 5s
+
+#define EXT_GPIO0 0
+#define EXT_GPIO1 1
+#define EXT_GPIO2 2
+#define EXT_GPIO3 3
+#define EXT_GPIO4 4
+#define EXT_GPIO5 5
+#define EXT_GPIO6 6
+#define EXT_GPIO7 7
+
+struct touch_tp_info {
+ char name[64];
+ unsigned int i2caddr;
+ int xaxis; // 0:x,1:x swap with y
+ int xdir; // 1:positive,-1:revert
+ int ydir; // 1:positive,-1:revert
+ int finger_num;
+};
+
+
+static struct touch_tp_info l_tp[] = {
+ {"LW86X0",(0x30>>1), 0, 1, 1},
+};
+
+static int irq_gpio;
+static int rst_gpio;
+static int keyled_gpio = -1;
+static int light_level;
+static int light_time = 5000; // unit: ms
+static int panelres_x;
+static int panelres_y;
+static int lcd_exchg = 0;
+static DECLARE_WAIT_QUEUE_HEAD(queue);
+static TS_EVENT g_evLast;
+static struct mutex cal_mutex;
+
+static struct class* l_dev_class = NULL;
+static struct device *l_clsdevice = NULL;
+extern struct wmtts_device lw86x0_tsdev;
+static struct wmtts_device* l_tsdev = &lw86x0_tsdev;
+static unsigned char ts_i2c_addr = 0;
+
+static struct proc_dir_entry* l_tsproc = NULL;
+static struct timer_list l_lighttimer; // for shaking
+static int l_tskey_btn = 0; // zero to disable touch key, positive to support touch key
+
+#if 0
+//add
+struct tp_infor{
+
+char name[64];
+int i2caddr;
+int xaxis;
+int xdir;
+int ydir;
+int finger_num;
+};
+
+//add by jackie
+//static int l_tpindex = -1;
+static struct tp_infor l_tpinfor[1];
+#endif
+/////////////////////////////////////////////////////
+// extrenal function
+/////////////////////////////////////////////////////
+extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
+extern int wmt_setsyspara(char *varname, unsigned char *varval);
+/////////////////////////////////////////////////////
+static int ts_writeproc( struct file *file,
+ const char *buffer,
+ unsigned long count,
+ void *data );
+static int ts_readproc(char *page, char **start, off_t off,
+ int count, int *eof, void *data);
+
+
+char g_dbgmode = 0;
+int COL_NUM;
+int ROW_NUM;
+int SKIP_ZERO_POINT;
+
+int wmt_ts_get_configfilename(char* fname)
+{
+ sprintf(fname,"%s.cfg",l_tp[0].name);
+ return 0;
+}
+
+int wmt_ts_get_firmwfilename(char* fname)
+{
+ sprintf(fname,"%s_fw.bin",l_tp[0].name);
+ return 0;
+}
+
+int wmt_ts_get_xaxis(void)
+{
+ return l_tp[0].xaxis;
+}
+
+int wmt_ts_get_xdir(void)
+{
+ return l_tp[0].xdir;
+}
+
+int wmt_ts_get_ydir(void)
+{
+ return l_tp[0].ydir;
+}
+
+int wmt_ts_get_fingernum(void)
+{
+ return l_tp[0].finger_num;
+}
+
+ int wmt_ts_get_gpionum(void)
+{
+ return irq_gpio;
+}
+
+int wmt_ts_get_resetgpnum(void)
+{
+ return rst_gpio;
+}
+
+int wmt_ts_get_lcdexchg(void)
+{
+ return lcd_exchg;
+}
+
+int wmt_ts_get_resolvX(void)
+{
+ return panelres_x;
+}
+
+int wmt_ts_get_resolvY(void)
+{
+ return panelres_y;
+}
+
+int wmt_ts_enable_tskey(void)
+{
+ return l_tskey_btn;
+}
+
+int wmt_ts_enable_keyled(void)
+{
+ return (keyled_gpio>=0 ? 1:0);
+}
+
+
+static void ts_lighttimer_timeout(unsigned long timeout)
+{
+ // turn off the light
+ if (20 == keyled_gpio)
+ {
+ if (light_level>=0)
+ {
+ REG32_VAL(__GPIO_BASE+0x00F0) &= ~BIT4; // output low
+ dbg("turn off the light!\n");
+ } else {
+ REG32_VAL(__GPIO_BASE+0x00F0) |= BIT4; // output high
+ dbg("turn off the light!\n");
+ }
+ }
+}
+
+
+static void wmt_ts_init_light(void)
+{
+ if (20 == keyled_gpio)
+ {
+ setup_timer(&l_lighttimer, ts_lighttimer_timeout, 0);
+ // init gpio20 and turn off light
+ REG32_VAL(__GPIO_BASE+0x00F0) &= ~BIT4; // output low
+ REG32_VAL(__GPIO_BASE+0x00B0) |= BIT4; // output enable
+ REG32_VAL(__GPIO_BASE+0x0070) |= BIT4; // enable gpio
+ REG32_VAL(__GPIO_BASE+0x04F0) |= BIT4; // pull up
+ REG32_VAL(__GPIO_BASE+0x04B0) |= BIT4; // enable pull up/down
+ }
+}
+
+void wmt_ts_turnoff_light(void)
+{
+ if (20 == keyled_gpio)
+ {
+ mod_timer(&l_lighttimer, jiffies + msecs_to_jiffies(light_time));
+ }
+}
+
+void wmt_ts_turnon_light(void)
+{
+ if (20 == keyled_gpio)
+ {
+ del_timer(&l_lighttimer);
+ if (light_level >= 0)
+ {
+ REG32_VAL(__GPIO_BASE+0x00F0) |= BIT4; // output high
+ dbg("turn on the light!\n");
+ } else {
+ REG32_VAL(__GPIO_BASE+0x00F0) &= ~BIT4; // output low
+ dbg("turn on the light!\n");
+ }
+ }
+}
+
+static void wmt_ts_remove_light(void)
+{
+ if (20 == keyled_gpio)
+ {
+ if (light_level >= 0)
+ {
+ REG32_VAL(__GPIO_BASE+0x00F0) &= ~BIT4; // output low
+ } else {
+ REG32_VAL(__GPIO_BASE+0x00F0) |= BIT4; // output high
+ }
+ del_timer(&l_lighttimer);
+ }
+}
+
+int wmt_is_tsirq_enable(int num)
+{
+ int val = 0;
+
+ if(num > 11)
+ return 0;
+
+ if(num<4)
+ val = REG32_VAL(__GPIO_BASE+0x0300) & (1<<(num*8+7));
+ else if(num >= 4 && num < 8)
+ val = REG32_VAL(__GPIO_BASE+0x0304) & (1<<((num-4)*8+7));
+ else
+ val = REG32_VAL(__GPIO_BASE+0x0308) & (1<<((num-8)*8+7));
+
+ return val?1:0;
+}
+
+int wmt_is_tsint(int num)
+{
+ if (num > 11)
+ {
+ return 0;
+ }
+ return (REG32_VAL(__GPIO_BASE+0x0360) & (1<<num)) ? 1: 0;
+}
+
+void wmt_clr_int(int num)
+{
+ if (num > 11)
+ {
+ return;
+ }
+ REG32_VAL(__GPIO_BASE+0x0360) = 1<<num;
+}
+
+void wmt_tsreset_init(int num)
+{
+ REG32_VAL(__GPIO_BASE+0x0040) |= (1<<num);//&= ~(1<<num); //enable gpio
+ REG32_VAL(__GPIO_BASE+0x00C0) |= (1<<num); // out high
+ REG32_VAL(__GPIO_BASE+0x0080) |= (1<<num); //output enable
+ msleep(5);
+ //REG32_VAL(__GPIO_BASE+0x00C0) |= (1<<num);
+}
+
+// enable:0-disable,1-enable
+void wmt_enable_rst_pull(int enable)
+{
+ if (enable)
+ {
+ REG32_VAL(__GPIO_BASE+0x0480) |= (1<<rst_gpio); //enable pull up/down
+ } else {
+ REG32_VAL(__GPIO_BASE+0x0480) &= ~(1<<rst_gpio); //disable pull up/down
+ }
+}
+
+// up:0-pull down,1-pull up
+void wmt_set_rst_pull(int up)
+{
+ if (up)
+ {
+ REG32_VAL(__GPIO_BASE+0x04c0) |= (1<<rst_gpio); //pull up
+ } else {
+ REG32_VAL(__GPIO_BASE+0x04c0) &= ~(1<<rst_gpio); //pull down
+ }
+}
+
+// high:0-low level,1-high level
+void wmt_rst_output(int high)
+{
+ REG32_VAL(__GPIO_BASE+0x0040) |= (1<<rst_gpio); //enable gpio
+ if (high)
+ {
+ REG32_VAL(__GPIO_BASE+0x00C0) |= (1<<rst_gpio); // high
+ } else {
+ REG32_VAL(__GPIO_BASE+0x00C0) &= ~(1<<rst_gpio); // low
+ }
+ REG32_VAL(__GPIO_BASE+0x0080) |= (1<<rst_gpio); //set output
+}
+
+void wmt_rst_input(void)
+{
+ REG32_VAL(__GPIO_BASE+0x0040) |= (1<<rst_gpio); //enable gpio
+ REG32_VAL(__GPIO_BASE+0x0080) &= ~(1<<rst_gpio); //set input
+}
+
+int wmt_set_irq_mode(unsigned int num, int mode)
+{
+ if(num >11)
+ return -1;
+ REG32_VAL(__GPIO_BASE+0x0040) &= ~(1<<num); //enable gpio
+ if(mode == 0)
+ {
+ REG32_VAL(__GPIO_BASE+0x0080) |= (1<<num); //set output
+ REG32_VAL(__GPIO_BASE+0x04c0) |= (1<<num); //pull down
+ REG32_VAL(__GPIO_BASE+0x0480) &= ~(1<<num); //enable pull up/down
+ }
+ else if(mode == 1)
+ REG32_VAL(__GPIO_BASE+0x0080) &= ~(1<<num); //set input
+ //msleep(5);
+ return 0;
+}
+
+
+int wmt_set_gpirq(unsigned int num, int type)
+{
+ int shift;
+ int offset;
+ unsigned long reg;
+
+ if(num >11)
+ return -1;
+ //if (num > 9)
+ //GPIO_PIN_SHARING_SEL_4BYTE_VAL &= ~BIT4; // gpio10,11 as gpio
+ REG32_VAL(__GPIO_BASE+0x0040) &= ~(1<<num); //enable gpio
+ REG32_VAL(__GPIO_BASE+0x0080) &= ~(1<<num); //set input
+ REG32_VAL(__GPIO_BASE+0x04c0) |= (1<<num); //pull down
+ REG32_VAL(__GPIO_BASE+0x0480) &= ~(1<<num); //enable pull up/down
+
+ //set gpio irq triger type
+ if(num < 4){//[0,3]
+ shift = num;
+ offset = 0x0300;
+ }else if(num >= 4 && num < 8){//[4,7]
+ shift = num-4;
+ offset = 0x0304;
+ }else{// [8,11]
+ shift = num-8;
+ offset = 0x0308;
+ }
+
+ reg = REG32_VAL(__GPIO_BASE + offset);
+
+ switch(type){
+ case GIRQ_LOW:
+ reg &= ~(1<<(shift*8+2));
+ reg &= ~(1<<(shift*8+1));
+ reg &= ~(1<<(shift*8));
+ break;
+ case GIRQ_HIGH:
+ reg &= ~(1<<(shift*8+2));
+ reg &= ~(1<<(shift*8+1));
+ reg |= (1<<(shift*8));
+ break;
+ case GIRQ_FALLING:
+ reg &= ~(1<<(shift*8+2));
+ reg |= (1<<(shift*8+1));
+ reg &= ~(1<<(shift*8));
+ break;
+ case GIRQ_RISING:
+ reg &= ~(1<<(shift*8+2));
+ reg |= (1<<(shift*8+1));
+ reg |= (1<<(shift*8));
+ break;
+ default://both edge
+ reg |= (1<<(shift*8+2));
+ reg &= ~(1<<(shift*8+1));
+ reg &= ~(1<<(shift*8));
+ break;
+
+ }
+ //reg |= 1<<(shift*8+7);//enable interrupt
+ reg &= ~(1<<(shift*8+7)); //disable int
+ REG32_VAL(__GPIO_BASE + offset) = reg;
+ REG32_VAL(__GPIO_BASE+0x0360) = 1<<num; //clear interrupt status
+ msleep(5);
+ return 0;
+}
+
+int wmt_enable_gpirq(unsigned int num)
+{
+ if(num > 11)
+ return -1;
+ if(num<4)
+ REG32_VAL(__GPIO_BASE+0x0300) |= 1<<(num*8+7); //enable interrupt
+ else if(num >= 4 && num < 8)
+ REG32_VAL(__GPIO_BASE+0x0304) |= 1<<((num-4)*8+7); //enable interrupt
+ else
+ REG32_VAL(__GPIO_BASE+0x0308) |= 1<<((num-8)*8+7); //enable interrupt
+
+ return 0;
+}
+
+int wmt_disable_gpirq(unsigned int num)
+{
+ if(num > 11)
+ return -1;
+
+ if(num<4)
+ REG32_VAL(__GPIO_BASE+0x0300) &= ~(1<<(num*8+7)); //enable interrupt
+ else if(num >= 4 && num < 8)
+ REG32_VAL(__GPIO_BASE+0x0304) &= ~(1<<((num-4)*8+7)); //enable interrupt
+ else
+ REG32_VAL(__GPIO_BASE+0x0308) &= ~(1<<((num-8)*8+7)); //enable interrupt
+
+ return 0;
+}
+
+
+int wmt_get_tsirqnum(void)
+{
+ return IRQ_GPIO;
+}
+
+int wmt_ts_set_rawcoord(unsigned short x, unsigned short y)
+{
+ g_evLast.x = x;
+ g_evLast.y = y;
+ //dbg("raw(%d,%d)*\n", x, y);
+ return 0;
+}
+
+static void wmt_ts_platform_release(struct device *device)
+{
+ return;
+}
+
+static struct platform_device wmt_ts_plt_device = {
+ .name = TS_DRIVER_NAME,
+ .id = 0,
+ .dev = {
+ .release = wmt_ts_platform_release,
+ },
+// .num_resources = ARRAY_SIZE(wm9715_ts_resources),
+// .resource = wm9715_ts_resources,
+};
+
+static int wmt_ts_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ dbg("ts suspend....\n");
+ if (wmt_ts_enable_keyled())
+ wmt_ts_remove_light();
+ if (l_tsdev->suspend !=NULL)
+ {
+ return l_tsdev->suspend(pdev, state);
+ }
+ return 0;
+}
+static int wmt_ts_resume(struct platform_device *pdev)
+{
+ klog("ts resume....\n");
+ if (wmt_ts_enable_keyled())
+ wmt_ts_init_light();
+ if (l_tsdev->resume != NULL)
+ {
+ return l_tsdev->resume(pdev);
+ }
+ return 0;
+}
+
+static int wmt_ts_probe(struct platform_device *pdev)
+{
+ l_tsproc= create_proc_entry(WMTTS_PROC_NAME, 0666, NULL/*&proc_root*/);
+ if (l_tsproc != NULL)
+ {
+ l_tsproc->read_proc = ts_readproc;
+ l_tsproc->write_proc = ts_writeproc;
+ }
+ if (l_tsdev->probe != NULL)
+ {
+ return l_tsdev->probe(pdev);
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+static int wmt_ts_remove(struct platform_device *pdev)
+{
+ if (l_tsproc != NULL)
+ {
+ remove_proc_entry(WMTTS_PROC_NAME, NULL);
+ l_tsproc = NULL;
+ }
+
+ if (l_tsdev->remove != NULL)
+ return l_tsdev->remove(pdev);
+ else
+ return 0;
+}
+
+static struct platform_driver wmt_ts_plt_driver = {
+ .driver = {
+ .name = TS_DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = wmt_ts_probe,
+ .remove = wmt_ts_remove,
+ .suspend = wmt_ts_suspend,
+ .resume = wmt_ts_resume,
+};
+
+static int wmt_ts_open(struct inode *inode, struct file *filp)
+{
+ int ret = 0;
+ return ret;
+}
+
+static int wmt_ts_close(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+static unsigned int wmt_ts_poll(struct file *filp, struct poll_table_struct *wait)
+{
+ return 0;
+}
+
+
+void read_diff(rawdata* pdata)
+{
+ //u16 Buffer[COL_NUM_MAX*ROW_NUM_MAX*2];
+ u16 *Buffer;
+ u16 idx = 0;
+ int i,j;
+ u16 addr =0;
+ pdata->col = COL_NUM;
+ pdata->row = ROW_NUM;
+ Buffer = kzalloc(COL_NUM_MAX*ROW_NUM_MAX*2*2, GFP_KERNEL);
+ if (!Buffer) {
+ errlog("mem alloc fail.\n");
+ return;
+ }
+ for(i=0;i<pdata->row;i++)
+ {
+ addr = 0x42f2+i*60;
+ printk("read_diff: addr=0x%04x\n",addr);
+ for(j=0;j<pdata->col*2;j++)
+ {
+ if(lw86x0_read_reg(addr+j, &Buffer[idx],1)!=0)
+ {
+ lw86x0_read_reg(addr+j, &Buffer[idx],1);
+ }
+ printk("read_diff: Buffer[%d]=0x%04x\n",idx,Buffer[idx]);
+ idx++;
+ }
+ }
+ for(i=0; i<pdata->col * pdata->row; i++)
+ {
+ pdata->data[i] = ((Buffer[i*2]<<8)&0xff00)|(Buffer[i*2+1]&0x00ff);
+ printk("read_diff: pdata->data[%d]=0x%04x\n",i,pdata->data[i]);
+ }
+ kfree(Buffer);
+}
+
+void read_cdc(rawdata* pdata)
+{
+ int i,j;
+ u16 addr = 0x2fc8;
+ u16 idx = 0;
+
+ pdata->col = COL_NUM;
+ pdata->row = ROW_NUM;
+
+ for(i=0;i<pdata->col;i++)
+ {
+ for(j=0;j<pdata->row;j++)
+ {
+ printk("read_cdc: addr=0x%04x\n",addr+idx);
+ if(lw86x0_read_reg(addr+idx, &pdata->data[j*pdata->col+i],1)!=0)
+ {
+ lw86x0_read_reg(addr+idx, &pdata->data[j*pdata->col+i],1);
+ }
+ printk("read_cdc: pdata->data[%d]=0x%04x\n",j*pdata->col+i,pdata->data[j*pdata->col+i]);
+ idx++;
+ }
+ }
+}
+
+void read_amb(rawdata* pdata)
+{
+ int i,j;
+ u16 addr = 0x2E04;
+ u16 idx = 0;
+
+ pdata->col = COL_NUM;
+ pdata->row = ROW_NUM;
+
+ for(i=0;i<pdata->col;i++)
+ {
+ for(j=0;j<pdata->row;j++)
+ {
+ printk("read_amb: addr=0x%04x\n",addr+idx);
+ if(lw86x0_read_reg(addr+idx, &pdata->data[j*pdata->col+i],1)!=0)
+ {
+ lw86x0_read_reg(addr+idx, &pdata->data[j*pdata->col+i],1);
+ }
+ printk("read_amb: pdata->data[%d]=0x%04x\n",j*pdata->col+i,pdata->data[j*pdata->col+i]);
+ idx++;
+ }
+ }
+
+
+}
+
+void lw86x0_flash_write_prepare(void)
+{
+ lw86x0_stop_timer(1);
+ lw86x0_write_reg(0x00e2, 0x0300);//#write_en=1 tmr=1
+ udelay(1);
+ //mass erase
+ lw86x0_write_reg(0x00e2, 0x0305);//#xe=1 mas1=1
+ lw86x0_write_reg(0x00e2, 0x0315);//#erase=1
+ udelay(5);
+ lw86x0_write_reg(0x00e2, 0x0395);//#nvstr=1
+ mdelay(20);
+ lw86x0_write_reg(0x00e2, 0x0385);//#erase=0
+ udelay(100);
+ lw86x0_write_reg(0x00e2, 0x0305);//#nvstr=0
+ lw86x0_write_reg(0x00e2, 0x0300);//#xe=0 mas1=0
+}
+
+void lw86x0_flash_write(u8* pbData,u16 start_addr, u16 num)
+{
+ u16 yaddr = start_addr;
+ u16 xaddr = (start_addr)&0xFF80;//x addr is a 8bit address
+ u16 cnt = 0;
+ while(cnt<num)
+ {
+ while(1)
+ {
+ lw86x0_write_reg(0x00e3, xaddr);//#xaddr
+ lw86x0_write_reg(0x00e2, 0x0304);//#xe=1
+ lw86x0_write_reg(0x00e2, 0x0324);//#prog=1
+ udelay(5);
+ lw86x0_write_reg(0x00e2, 0x03a4);//#nvstr=1
+ udelay(10);
+ do
+ {
+ u16 data = pbData[cnt];
+ lw86x0_write_reg(0x00e3, yaddr);//#yaddr
+ lw86x0_write_reg(0x00e4, data);//#din
+ lw86x0_write_reg(0x00e2, 0xfbac);//#ye=0
+ lw86x0_write_reg(0x00e2, 0x03a4);//#ye=0
+ yaddr++;
+ cnt++;
+ if(cnt==num)
+ {
+ break;
+ }
+ }while(yaddr&0x007F);
+ xaddr+=0x0080;
+ udelay(20);
+ lw86x0_write_reg(0x00e2, 0x0384);//#prog=0
+ udelay(100);
+ lw86x0_write_reg(0x00e2, 0x0304);//#nvstr=0
+ lw86x0_write_reg(0x00e2, 0x0300);//#xe=0
+ if(cnt==num)
+ {
+ break;
+ }
+ }
+ }
+
+}
+
+void lw86x0_flash_write_finish(u16 total_len)
+{
+ //write length of FW to last 2 byte of flash
+ u8 *pLen = (u8 *)&total_len;
+ lw86x0_flash_write(&(pLen[1]),0x7FFE, 1);
+ lw86x0_flash_write(&(pLen[0]),0x7FFF, 1);
+
+ lw86x0_write_reg(0x00e2, 0x0300);//#tmr=1
+ lw86x0_write_reg(0x00e2, 0x0200);//#tmr=0
+ lw86x0_write_reg(0x00e2, 0x02c0);//#nvstr=1 se=1
+ lw86x0_write_reg(0x00e2, 0x02eb);//#prog=1 ifren=1 ye=1 mas=1
+ lw86x0_write_reg(0x00e2, 0x03eb);//#tmr=1
+ lw86x0_write_reg(0x00e2, 0x02eb);//#tmr=0
+ lw86x0_write_reg(0x00e2, 0x02c0);//#prog=0 ifren=0 ye=0 mas=0
+ lw86x0_write_reg(0x00e2, 0x0200);//#nvstr=0 se=0
+ lw86x0_write_reg(0x00e2, 0x0204);//#xe=1
+ lw86x0_write_reg(0x00e2, 0x0214);//#erase=1
+ udelay(5);
+ lw86x0_write_reg(0x00e2, 0x0294);//#nvstr=1
+ mdelay(20);
+ lw86x0_write_reg(0x00e2, 0x0284);//#erase=0
+ udelay(5);
+ lw86x0_write_reg(0x00e2, 0x0204);//#nvstr=0
+ lw86x0_write_reg(0x00e2, 0x0200);//#xe=0
+ lw86x0_write_reg(0x00e2, 0x0000);
+ lw86x0_write_reg(0x000c, 0xffff);
+ lw86x0_stop_timer(0);
+}
+
+void lw86x0_flash_read(u8* pbData, u16 start_addr, u16 num)
+{
+ lw86x0_stop_timer(1);
+ u16 cnt;
+ u16 rd_data = 0;
+ u8 *buf;
+ for(cnt=0; cnt<num;cnt++)
+ {
+ lw86x0_write_reg(0x00e4, 0x0000);//#read data
+ lw86x0_write_reg(0x00e2, 0x0300);//#tmr=1
+ lw86x0_write_reg(0x00e3, start_addr+cnt);
+ lw86x0_write_reg(0x00e2, 0x034c);//#se=1 ye=1 xe=1
+ lw86x0_write_reg(0x00e2, 0x0300);//#se=1 ye=1 xe=1
+ lw86x0_read_reg(0x00e4, &rd_data,1);
+ buf = (u8 *)&rd_data;
+ pbData[cnt] = buf[1];
+ }
+ lw86x0_stop_timer(0);
+}
+
+
+static long wmt_ts_ioctl(/*struct inode * node,*/ struct file *dev, unsigned int cmd, unsigned long arg)
+{
+ reg_word regword;
+ //rawdata rdata;
+ rawdata *rdata;
+ flash_op f_pkt;//flash packet
+
+ int ret = 0;
+ char ch;
+ rdata = kzalloc(sizeof(rawdata), GFP_KERNEL);
+ if (!rdata) {
+ errlog("mem alloc fail.\n");
+ return -ENOMEM;
+ }
+
+ if (_IOC_TYPE(cmd) != TS_IOC_MAGIC){
+ dbg("CMD ERROR!");
+ return -ENOTTY;
+ }
+
+ if (_IOC_NR(cmd) > TS_IOC_MAXNR){
+ dbg("NO SUCH IO CMD!\n");
+ return -ENOTTY;
+ }
+
+ switch (cmd) {
+ case LW86X0_WRITE_REG:
+ copy_from_user(&regword, (reg_word*)arg, sizeof(regword));
+ dbg("write reg[%d] word value 0x%x", regword.uOffset, regword.uValue );
+ ret = lw86x0_write_reg(regword.uOffset, regword.uValue);
+ if (ret != 0)
+ {
+ dbg("Faied to write reg. ret 0x%x\n",ret);
+ }
+ return 0;
+ case LW86X0_READ_REG:
+ copy_from_user(&regword, (reg_word*)arg, sizeof(regword));
+ ret = lw86x0_read_reg(regword.uOffset, &regword.uValue, 1);
+ if (ret != 0)
+ {
+ dbg("Faied to read reg. ret 0x%x\n",ret);
+ }
+ else
+ {
+
+ dbg("read reg[%d]=0x%04x",regword.uOffset, regword.uValue);
+ }
+ copy_to_user((unsigned int*)arg, &regword, sizeof(regword));
+ return 0;
+ case LW86X0_CTRL_DEBUG_MODE:
+ copy_from_user(&ch, (char*)arg, sizeof(char));
+ printk("LW86X0_CTRL_DEBUG_MODE,%c", ch);
+ if(ch=='1')
+ {
+ g_dbgmode = 1;
+ wmt_disable_gpirq(irq_gpio);
+ }
+ else
+ {
+ g_dbgmode = 0;
+ wmt_enable_gpirq(irq_gpio);
+ }
+ return 0;
+ /*
+ case LW86X0_CTRL_RD_DIFF:
+ copy_from_user(&rdata, (rawdata*)arg, sizeof(rdata));
+ printk("tpd-ioctrl: LW86X0_CTRL_RD_DIFF\n");
+ read_diff(&rdata);
+ copy_to_user((unsigned int*)arg, &rdata, sizeof(rdata));
+ return 0;
+ case LW86X0_CTRL_RD_CDC:
+ copy_from_user(&rdata, (rawdata*)arg, sizeof(rdata));
+ printk("tpd-ioctrl: LW86X0_CTRL_RD_CDC\n");
+ read_cdc(&rdata);
+ copy_to_user((unsigned int*)arg, &rdata, sizeof(rdata));
+ return 0;
+ case LW86X0_CTRL_RD_AMB:
+ copy_from_user(&rdata, (rawdata*)arg, sizeof(rdata));
+ printk("tpd-ioctrl: LW86X0_CTRL_RD_AMB\n");
+ read_amb(&rdata);
+ copy_to_user((unsigned int*)arg, &rdata, sizeof(rdata));
+ return 0;
+ */
+ case LW86X0_CTRL_RD_DIFF:
+ copy_from_user(rdata, (rawdata*)arg, sizeof(*rdata));
+ printk("tpd-ioctrl: LW86X0_CTRL_RD_DIFF\n");
+ read_diff(rdata);
+ copy_to_user((unsigned int*)arg, rdata, sizeof(*rdata));
+ return 0;
+ case LW86X0_CTRL_RD_CDC:
+ copy_from_user(rdata, (rawdata*)arg, sizeof(*rdata));
+ printk("tpd-ioctrl: LW86X0_CTRL_RD_CDC\n");
+ read_cdc(rdata);
+ copy_to_user((unsigned int*)arg, rdata, sizeof(*rdata));
+ return 0;
+ case LW86X0_CTRL_RD_AMB:
+ copy_from_user(rdata, (rawdata*)arg, sizeof(*rdata));
+ printk("tpd-ioctrl: LW86X0_CTRL_RD_AMB\n");
+ read_amb(rdata);
+ copy_to_user((unsigned int*)arg, rdata, sizeof(*rdata));
+ return 0;
+ case LW86X0_FLASH_DOWNLOAD:
+ copy_from_user(&f_pkt, (flash_op*)arg, sizeof(f_pkt));
+ if(f_pkt.startaddr==0)
+ {
+ lw86x0_flash_write_prepare();
+ }
+ lw86x0_flash_write(f_pkt.data,
+ f_pkt.startaddr,
+ f_pkt.pktlen);
+ printk("dnload: start addr = %04x\n",f_pkt.startaddr);
+ if(f_pkt.lastpkt==1)
+ {
+ u16 write_len = f_pkt.startaddr + f_pkt.pktlen;
+ lw86x0_flash_write_finish(write_len);
+ }
+ return 0;
+ case LW86X0_FLASH_UPLOAD:
+ copy_from_user(&f_pkt, (flash_op*)arg, sizeof(f_pkt));
+ lw86x0_flash_read(f_pkt.data, f_pkt.startaddr, f_pkt.pktlen);
+ printk("upload: start addr = %04x\n",f_pkt.startaddr);
+ printk("\n");
+ copy_to_user((int*)arg, &f_pkt, sizeof(f_pkt));
+ return 0;
+ case LW86X0_CTRL_STOP_TIMER:
+ copy_from_user(&ch, (char*)arg, sizeof(char));
+ if(ch == '1')
+ lw86x0_stop_timer(1);
+ else
+ lw86x0_stop_timer(0);
+ return 0;
+ }
+ kfree(rdata);
+ return -EINVAL;
+}
+
+static ssize_t wmt_ts_read(struct file *filp, char *buf, size_t count, loff_t *l)
+{
+ return 0;
+}
+
+
+static struct file_operations wmt_ts_fops = {
+ .read = wmt_ts_read,
+ .poll = wmt_ts_poll,
+ .unlocked_ioctl = wmt_ts_ioctl,
+ .open = wmt_ts_open,
+ .release = wmt_ts_close,
+};
+
+static int ts_writeproc( struct file *file,
+ const char *buffer,
+ unsigned long count,
+ void *data )
+{
+ int calibrate = 0;
+ int val = 0;
+
+ if (sscanf(buffer, "calibrate=%d\n", &calibrate))
+ {
+ if (1 == calibrate)
+ {
+ if((l_tsdev->capacitance_calibrate != NULL) &&
+ (0 == l_tsdev->capacitance_calibrate()))
+ {
+ printk(KERN_ALERT "%s calibration successfully!\n", l_tsdev->ts_id);
+ } else {
+ printk(KERN_ALERT "%s calibration failed!\n", l_tsdev->ts_id);
+ }
+ }
+ } else if (sscanf(buffer, "out=%d\n", &val))
+ {
+ switch(val)
+ {
+ case 1: // reset1
+ REG32_VAL(__GPIO_BASE+0x0040) |= (1<<irq_gpio); //enable gpio
+ REG32_VAL(__GPIO_BASE+0x00C0) |= (1<<irq_gpio); //out high
+ REG32_VAL(__GPIO_BASE+0x0080) |= (1<<irq_gpio); //set input
+ break;
+ case 0: // reset2
+ REG32_VAL(__GPIO_BASE+0x0040) |= (1<<irq_gpio); //enable gpio
+ REG32_VAL(__GPIO_BASE+0x00C0) &= ~(1<<irq_gpio); //out high
+ REG32_VAL(__GPIO_BASE+0x0080) |= (1<<irq_gpio); //set input
+ break;
+ default:
+ break;
+ };
+ }
+ return count;
+}
+
+static int ts_readproc(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int len = 0;
+
+ len = sprintf(page,
+ "echo calibrate=1 > /proc/wmtts_config to calibrate ts.\n");
+ return len;
+}
+
+unsigned char wmt_ts_get_i2caddr(void)
+{
+ return ts_i2c_addr;
+}
+
+static int wmt_check_touch_env(void)
+{
+ int ret = 0;
+ int len = 127;
+ char retval[128] = {0},*p=NULL,*s=NULL;
+ int Enable=0;
+
+ // Get u-boot parameter
+ ret = wmt_getsyspara("wmt.io.touch", retval, &len);
+ if(ret){
+ errlog("Read wmt.io.touch Failed.\n");
+ return -EIO;
+ }
+
+ //check touch enable
+ p = retval;
+ sscanf(p,"%d:", &Enable);
+ if(Enable == 0){
+ errlog("Touch Screen Is Disabled.\n");
+ return -ENODEV;
+ }
+
+ //check touch IC name
+ p = strchr(p,':');p++;
+ if (strncmp(p, l_tp[0].name, strlen(l_tp[0].name))) {
+ errlog("Can't find %s!\n", l_tp[0].name);
+ return -ENODEV;
+ }
+
+ //get firmware file name
+ s = strchr(p,':');
+ memset(l_tp[0].name,0x00,sizeof(l_tp[0].name));
+ strncpy(l_tp[0].name, p, (s-p));
+ dbg("ts_fwname=%s\n", l_tp[0].name);
+
+ p = s + 1;
+ ret = sscanf(p,"%d:%d:%d:%d:%d:%d:%d:%d:%x",
+ &irq_gpio,&panelres_x,&panelres_y,&rst_gpio,
+ &(l_tp[0].xaxis),&(l_tp[0].xdir),&(l_tp[0].ydir),
+ &(l_tp[0].finger_num),&(l_tp[0].i2caddr));
+
+ dbg("%d;%d;%d;%d;%d;%d;%d;%d;%x;",irq_gpio,panelres_x,panelres_y,rst_gpio,
+ (l_tp[0].xaxis),(l_tp[0].xdir),(l_tp[0].ydir),
+ (l_tp[0].finger_num),(l_tp[0].i2caddr));
+
+ ret = wmt_getsyspara("wmt.display.fb0", retval, &len);
+ if (!ret) {
+ int tmp[6];
+ p = retval;
+ sscanf(p, "%d:[%d:%d:%d:%d:%d", &tmp[0], &tmp[1], &tmp[2], &tmp[3], &tmp[4], &tmp[5]);
+ if (tmp[4] > tmp[5])
+ lcd_exchg = 1;
+ }
+
+ return 0;
+}
+//#if 0
+//add by jackie i2c_board_info
+struct i2c_board_info ts_i2c_board_info = {
+ .type = WMT_TS_I2C_NAME,
+ .flags = 0x00,
+ //.addr = 0x18, //WMT_TS_I2C_ADDR,//why error?
+ .platform_data = NULL,
+ .archdata = NULL,
+ .irq = -1,
+};
+//add jackie static
+ int ts_i2c_register_device (void)
+{
+ struct i2c_board_info *ts_i2c_bi;
+ struct i2c_adapter *adapter = NULL;
+ //struct i2c_client *client = NULL;
+
+ ts_i2c_board_info.addr = l_tp[0].i2caddr;
+ ts_i2c_bi = &ts_i2c_board_info;
+ adapter = i2c_get_adapter(1);/*in bus 1*/
+
+ if (NULL == adapter) {
+ printk("can not get i2c adapter, client address error\n");
+ return -1;
+ }
+ l_client = i2c_new_device(adapter, ts_i2c_bi);
+ if (l_client == NULL) {
+ printk("allocate i2c client failed\n");
+ return -1;
+ }
+ i2c_put_adapter(adapter);
+ return 0;
+}
+//add by jackie
+struct i2c_client* ts_get_i2c_client(void)
+{
+ return l_client;
+}
+//add
+static int __init wmt_ts_init(void)
+{
+ int ret = 0;
+
+ if(wmt_check_touch_env())
+ return -ENODEV;
+
+//add by jackie
+ if (ts_i2c_register_device()<0)
+ {
+ dbg("Error to run ts_i2c_register_device()!\n");
+ return -1;
+ }
+
+ mutex_init(&cal_mutex);
+
+ if (l_tsdev->init() < 0){
+ printk(KERN_ERR "Errors to init %s ts IC!!!\n", l_tsdev->ts_id);
+ return -1;
+ }
+ if (wmt_ts_enable_keyled())
+ wmt_ts_init_light();
+ // Create device node
+ if (register_chrdev (TS_MAJOR, TS_NAME, &wmt_ts_fops)) {
+ printk (KERN_ERR "wmt touch: unable to get major %d\n", TS_MAJOR);
+ return -EIO;
+ }
+
+ l_dev_class = class_create(THIS_MODULE, TS_NAME);
+ if (IS_ERR(l_dev_class)){
+ ret = PTR_ERR(l_dev_class);
+ printk(KERN_ERR "Can't class_create touch device !!\n");
+ return ret;
+ }
+ l_clsdevice = device_create(l_dev_class, NULL, MKDEV(TS_MAJOR, 0), NULL, TS_NAME);
+ if (IS_ERR(l_clsdevice)){
+ ret = PTR_ERR(l_clsdevice);
+ printk(KERN_ERR "Failed to create device %s !!!",TS_NAME);
+ return ret;
+ }
+
+ // register device and driver of platform
+ ret = platform_device_register(&wmt_ts_plt_device);
+ if(ret){
+ errlog("wmt ts plat device register failed!\n");
+ return ret;
+ }
+ ret = platform_driver_register(&wmt_ts_plt_driver);
+ if(ret){
+ errlog("can not register platform_driver_register\n");
+ platform_device_unregister(&wmt_ts_plt_device);
+ return ret;
+ }
+
+ klog("wmt ts driver init ok!\n");
+ return ret;
+}
+
+//add by jackie
+static void ts_i2c_unregister_device(void)
+{
+ if (l_client != NULL)
+ {
+ i2c_unregister_device(l_client);
+ l_client = NULL;
+ }
+}
+//add end
+
+static void __exit wmt_ts_exit(void)
+{
+ dbg("%s\n",__FUNCTION__);
+
+ if (wmt_ts_enable_keyled())
+ wmt_ts_remove_light();
+ l_tsdev->exit();
+ mutex_destroy(&cal_mutex);
+ platform_driver_unregister(&wmt_ts_plt_driver);
+ platform_device_unregister(&wmt_ts_plt_device);
+ device_destroy(l_dev_class, MKDEV(TS_MAJOR, 0));
+ unregister_chrdev(TS_MAJOR, TS_NAME);
+ class_destroy(l_dev_class);
+ ts_i2c_unregister_device();
+}
+
+
+module_init(wmt_ts_init);
+module_exit(wmt_ts_exit);
+
+MODULE_LICENSE("GPL");
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/lw86x0_ts/wmt_ts.h b/ANDROID_3.4.5/drivers/input/touchscreen/lw86x0_ts/wmt_ts.h
new file mode 100755
index 00000000..ff1218ac
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/lw86x0_ts/wmt_ts.h
@@ -0,0 +1,98 @@
+
+#ifndef WMT_TSH_201010191758
+#define WMT_TSH_201010191758
+
+#include <linux/platform_device.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/suspend.h>
+
+//#define DEBUG_WMT_TS
+#ifdef DEBUG_WMT_TS
+#undef dbg
+#define dbg(fmt, args...) printk(KERN_ALERT "[%s]: " fmt, __FUNCTION__ , ## args)
+
+//#define dbg(fmt, args...) if (wmt_ts_isrundbg()) printk(KERN_ALERT "[%s]: " fmt, __FUNCTION__, ## args)
+
+#else
+#define dbg(fmt, args...)
+#endif
+
+#undef errlog
+#undef klog
+#define errlog(fmt, args...) printk("[%s]: " fmt, __FUNCTION__, ## args)
+#define klog(fmt, args...) printk("[%s]: " fmt, __FUNCTION__, ## args)
+
+#define DONOTHING 0xff
+
+#define WMT_TS_I2C_NAME "lw86x0-ts"
+//////////////////////////////data type///////////////////////////
+typedef struct {
+ short pressure;
+ short x;
+ short y;
+ //short millisecs;
+} TS_EVENT;
+
+struct wmtts_device
+{
+ //data
+ char* driver_name;
+ char* ts_id;
+ //function
+ int (*init)(void);
+ int (*probe)(struct platform_device *platdev);
+ int (*remove)(struct platform_device *pdev);
+ void (*exit)(void);
+ int (*suspend)(struct platform_device *pdev, pm_message_t state);
+ int (*resume)(struct platform_device *pdev);
+ int (*capacitance_calibrate)(void);
+ int (*wait_penup)(struct wmtts_device*tsdev); // waiting untill penup
+ int penup; // 0--pendown;1--penup
+
+};
+
+//////////////////////////function interface/////////////////////////
+extern int wmt_ts_get_gpionum(void);
+extern int wmt_ts_get_resolvX(void);
+extern int wmt_ts_get_resolvY(void);
+extern int wmt_ts_set_rawcoord(unsigned short x, unsigned short y);
+extern int wmt_set_gpirq(unsigned int num, int type);
+extern int wmt_get_tsirqnum(void);
+extern int wmt_disable_gpirq(unsigned int num);
+extern int wmt_enable_gpirq(unsigned int num);
+extern int wmt_is_tsirq_enable(int num);
+extern void wmt_enable_rst_pull(int enable);
+extern void wmt_set_rst_pull(int up);
+extern void wmt_rst_output(int high);
+void wmt_rst_input(void);
+extern int wmt_is_tsint(int num);
+extern void wmt_clr_int(int num);
+extern void wmt_tsreset_init(int num);
+extern int wmt_ts_get_resetgpnum(void);
+extern int wmt_ts_get_lcdexchg(void);
+extern unsigned char wmt_ts_get_i2caddr(void);
+extern void wmt_ts_turnoff_light(void);
+extern void wmt_ts_turnon_light(void);
+extern int wmt_ts_enable_tskey(void);
+extern int wmt_ts_get_configfilename(char* fname);
+extern int wmt_ts_get_firmwfilename(char* fname);
+extern int wmt_ts_get_xaxis(void);
+extern int wmt_ts_get_xdir(void);
+extern int wmt_ts_get_ydir(void);
+extern int wmt_ts_get_fingernum(void);
+extern int wmt_ts_enable_keyled(void);
+extern int wmt_set_irq_mode(unsigned int num, int mode);
+extern int wmt_disable_gpirq(unsigned int num);
+extern int wmt_enable_gpirq(unsigned int num);
+extern int ts_i2c_register_device (void);
+extern struct i2c_client* ts_get_i2c_client(void);
+
+extern void lw86x0_flash_write_prepare(void);
+extern void lw86x0_flash_read(u8* pbData, u16 start_addr, u16 num);
+extern void lw86x0_flash_write(u8* pbData,u16 start_addr, u16 num);
+extern void lw86x0_flash_write_finish(u16 total_len);
+#endif
+
+
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/metusb/Makefile b/ANDROID_3.4.5/drivers/input/touchscreen/metusb/Makefile
new file mode 100755
index 00000000..f806933e
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/metusb/Makefile
@@ -0,0 +1,33 @@
+KERNELDIR=../../../../
+CROSS = arm_1103_le-
+CC= $(CROSS)gcc
+LD= $(CROSS)ld
+STRIP = $(CROSS)strip
+
+DEBUG = n
+
+# Add your debugging flag (or not) to EXTRA_CFLAGS
+ifeq ($(DEBUG),y)
+# DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+DEBFLAGS = -O0 -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+
+else
+ DEBFLAGS = -O2 -Wall
+endif
+
+EXTRA_CFLAGS += $(DEBFLAGS)
+
+
+MY_MODULE_NAME=metusb
+
+obj-m := $(MY_MODULE_NAME).o
+
+default:
+ $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules
+ $(STRIP) --strip-debug $(MY_MODULE_NAME).ko
+ rm -rf *.o *~ core .depend .*.cmd *.mod.c .tmp_versions *.order *.symvers modules.builtin
+clean:
+ rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.order *.symvers modules.builtin
+
+
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/metusb/metusb.c b/ANDROID_3.4.5/drivers/input/touchscreen/metusb/metusb.c
new file mode 100755
index 00000000..e86bf03c
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/metusb/metusb.c
@@ -0,0 +1,856 @@
+
+//#define DEBUG
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/init.h>
+#include <linux/usb.h>
+#include <linux/usb/input.h>
+#include <linux/hid.h>
+#include <asm/uaccess.h>
+#include <linux/fs.h>
+#include <linux/syscalls.h>
+
+
+#define DRIVER_VERSION "v1.0"
+#define DRIVER_AUTHOR "Xiaoyijian"
+#define DRIVER_DESC "Metouch USB Touchscreen Driver"
+
+static int swap_xy = 0;
+static int swapx=0;
+static int swapy=0;
+
+static int v_shift=0;
+static int v_flag=0;
+
+static int h_shift=0;
+static int h_flag=0;
+
+
+#define TP_TIMEOUT 30
+#define TP_TIMEROUT_MAX 3
+
+/* device specifc data/functions */
+struct usbtouch_usb;
+struct usbtouch_device_info {
+ int min_xc, max_xc;
+ int min_yc, max_yc;
+ int min_press, max_press;
+ int rept_size;
+
+ /*
+ * Always service the USB devices irq not just when the input device is
+ * open. This is useful when devices have a watchdog which prevents us
+ * from periodically polling the device. Leave this unset unless your
+ * touchscreen device requires it, as it does consume more of the USB
+ * bandwidth.
+ */
+ bool irq_always;
+
+ void (*process_pkt) (struct usbtouch_usb *usbtouch, unsigned char *pkt, int len);
+
+ /*
+ * used to get the packet len. possible return values:
+ * > 0: packet len
+ * = 0: skip one byte
+ * < 0: -return value more bytes needed
+ */
+ int (*get_pkt_len) (unsigned char *pkt, int len);
+
+ int (*read_data) (struct usbtouch_usb *usbtouch, unsigned char *pkt);
+ int (*alloc) (struct usbtouch_usb *usbtouch);
+ int (*init) (struct usbtouch_usb *usbtouch);
+ void (*exit) (struct usbtouch_usb *usbtouch);
+};
+
+/* a usbtouch device */
+struct usbtouch_usb {
+ unsigned char *data;
+ dma_addr_t data_dma;
+ unsigned char *buffer;
+ int buf_len;
+ struct urb *irq;
+ struct usb_interface *interface;
+ struct input_dev *input;
+
+ struct workqueue_struct *tp_queue;
+ struct delayed_work tp_work;
+ struct mutex tp_timeout_mutex;
+ int tp_timer_count;
+
+ struct usbtouch_device_info *type;
+ char name[128];
+ char phys[64];
+ void *priv;
+ int x, y;
+ int touch, press;
+};
+
+#define DEVTYPE_METOUCH 0
+
+#define USB_DEVICE_HID_CLASS(vend, prod) \
+ .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS \
+ | USB_DEVICE_ID_MATCH_DEVICE, \
+ .idVendor = (vend), \
+ .idProduct = (prod), \
+ .bInterfaceClass = USB_INTERFACE_CLASS_HID, \
+ .bInterfaceProtocol = USB_INTERFACE_PROTOCOL_MOUSE
+
+/* Define these values to match your devices */
+#define METOUCH_VENDOR_ID 0x5A53
+#define METOUCH_PRODUCT_ID 0x0001
+#define METUSB_MINOR_BASE 0x0
+
+static int metouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt);
+static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch,unsigned char *pkt, int len);
+static void usbtouch_irq(struct urb *urb);
+static int usbtouch_open(struct input_dev *input);
+static void usbtouch_close(struct input_dev *input);
+static int usbtouch_suspend(struct usb_interface *intf, pm_message_t message);
+static int usbtouch_resume(struct usb_interface *intf);
+static int usbtouch_reset_resume(struct usb_interface *intf);
+static void usbtouch_free_buffers(struct usb_device *udev,struct usbtouch_usb *usbtouch);
+static struct usb_endpoint_descriptor *usbtouch_get_input_endpoint(struct usb_host_interface *interface);
+static int usbtouch_probe(struct usb_interface *intf,const struct usb_device_id *id);
+static void usbtouch_disconnect(struct usb_interface *intf);
+static int __init usbtouch_init(void);
+static void __exit usbtouch_cleanup(void);
+static void GetUserCfg(void);
+static void AnlysCmd(char *cmd);
+static int myatoi(char *str);
+static void DeleteAllSpace(char *cmd);
+int mypow(int t);
+
+
+static struct usbtouch_device_info usbtouch_dev_info[] = {
+ [DEVTYPE_METOUCH] = {
+ .min_xc = 0x0,
+ .max_xc = 0x0fff,
+ .min_yc = 0x0,
+ .max_yc = 0x0fff,
+ .rept_size = 8,
+ .read_data = metouch_read_data,
+ },
+};
+
+static struct usb_device_id metusb_table [] = {
+ { USB_DEVICE(METOUCH_VENDOR_ID, METOUCH_PRODUCT_ID) },
+ { } /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, metusb_table);
+
+/*****************************************************************************
+ * METOUCH Part
+ */
+/*
+AA 55 XL XH YL YH BTN CRC
+****************************************************************************/
+static int metouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
+{
+ dev->x = (pkt[3] << 8) | pkt[2];
+ dev->y = (pkt[5] << 8) | pkt[4];
+ dev->touch = (pkt[6] & 0x03) ? 1 : 0;
+
+ if (h_flag == 0) dev->x = dev->x + h_shift;
+ if (v_flag == 0) dev->y = dev->y + v_shift;
+
+ if (h_flag>0)
+ {
+ if (dev->x > h_shift) dev->x = dev->x - h_shift;
+ else dev->x=0;
+ }
+
+ if (v_flag>0)
+ {
+ if (dev->y > v_shift) dev->y = dev->y - v_shift;
+ else dev->y=0;
+ }
+
+ if (dev->x > 4095) dev->x=4095;
+ if (dev->y > 4095) dev->y=4095;
+
+ if (dev->x <0) dev->x=0;
+ if (dev->y <0) dev->y=0;
+
+ if (swapx>0) dev->x = 4095 - dev->x;
+ if (swapy>0) dev->y = 4095 - dev->y;
+
+ return 1;
+}
+
+
+/*****************************************************************************
+ * Generic Part
+ */
+static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch,
+ unsigned char *pkt, int len)
+{
+ struct usbtouch_device_info *type = usbtouch->type;
+
+ if (!type->read_data(usbtouch, pkt))
+ return;
+
+ mutex_lock(&usbtouch->tp_timeout_mutex);
+ if( usbtouch->tp_timer_count < 0 ){
+ queue_delayed_work(usbtouch->tp_queue, &usbtouch->tp_work, msecs_to_jiffies(TP_TIMEOUT));
+ }
+ usbtouch->tp_timer_count = TP_TIMEROUT_MAX;
+ mutex_unlock(&usbtouch->tp_timeout_mutex);
+
+ //input_report_key(usbtouch->input, BTN_TOUCH, usbtouch->touch);
+ input_report_abs(usbtouch->input, ABS_MT_TRACKING_ID, 0);
+ if (swap_xy) {
+ //input_report_abs(usbtouch->input, ABS_X, usbtouch->y);
+ //input_report_abs(usbtouch->input, ABS_Y, usbtouch->x);
+ input_report_abs(usbtouch->input, ABS_MT_POSITION_X, usbtouch->y );
+ input_report_abs(usbtouch->input, ABS_MT_POSITION_Y, usbtouch->x );
+ } else {
+ //input_report_abs(usbtouch->input, ABS_X, usbtouch->x);
+ //input_report_abs(usbtouch->input, ABS_Y, usbtouch->y);
+ input_report_abs(usbtouch->input, ABS_MT_POSITION_X, usbtouch->x );
+ input_report_abs(usbtouch->input, ABS_MT_POSITION_Y, usbtouch->y );
+ }
+ //if (type->max_press)
+ // input_report_abs(usbtouch->input, ABS_PRESSURE, usbtouch->press);
+ //input_sync(usbtouch->input);
+ input_mt_sync(usbtouch->input);
+ input_sync(usbtouch->input);
+
+
+
+}
+
+
+static void usbtouch_irq(struct urb *urb)
+{
+ struct usbtouch_usb *usbtouch = urb->context;
+ int retval;
+
+ switch (urb->status) {
+ case 0:
+ /* success */
+ break;
+ case -ETIME:
+ /* this urb is timing out */
+ dbg("%s - urb timed out - was the device unplugged?",
+ __func__);
+ return;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ case -EPIPE:
+ /* this urb is terminated, clean up */
+ dbg("%s - urb shutting down with status: %d",
+ __func__, urb->status);
+ return;
+ default:
+ dbg("%s - nonzero urb status received: %d",
+ __func__, urb->status);
+ goto exit;
+ }
+
+ usbtouch->type->process_pkt(usbtouch, usbtouch->data, urb->actual_length);
+
+exit:
+ usb_mark_last_busy(interface_to_usbdev(usbtouch->interface));
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
+ if (retval)
+ err("%s - usb_submit_urb failed with result: %d",
+ __func__, retval);
+}
+
+static int usbtouch_open(struct input_dev *input)
+{
+ struct usbtouch_usb *usbtouch = input_get_drvdata(input);
+ int r;
+
+ usbtouch->irq->dev = interface_to_usbdev(usbtouch->interface);
+
+ r = usb_autopm_get_interface(usbtouch->interface) ? -EIO : 0;
+ if (r < 0)
+ goto out;
+
+ if (!usbtouch->type->irq_always) {
+ if (usb_submit_urb(usbtouch->irq, GFP_KERNEL)) {
+ r = -EIO;
+ goto out_put;
+ }
+ }
+
+ usbtouch->interface->needs_remote_wakeup = 1;
+out_put:
+ usb_autopm_put_interface(usbtouch->interface);
+out:
+ return r;
+}
+
+static void usbtouch_close(struct input_dev *input)
+{
+ struct usbtouch_usb *usbtouch = input_get_drvdata(input);
+ int r;
+
+ if (!usbtouch->type->irq_always)
+ usb_kill_urb(usbtouch->irq);
+ r = usb_autopm_get_interface(usbtouch->interface);
+ usbtouch->interface->needs_remote_wakeup = 0;
+ if (!r)
+ usb_autopm_put_interface(usbtouch->interface);
+}
+
+static int usbtouch_suspend(struct usb_interface *intf, pm_message_t message)
+{
+ struct usbtouch_usb *usbtouch = usb_get_intfdata(intf);
+
+ usb_kill_urb(usbtouch->irq);
+
+ return 0;
+}
+
+static int usbtouch_resume(struct usb_interface *intf)
+{
+ struct usbtouch_usb *usbtouch = usb_get_intfdata(intf);
+ struct input_dev *input = usbtouch->input;
+ int result = 0;
+
+ mutex_lock(&input->mutex);
+ if (input->users || usbtouch->type->irq_always)
+ result = usb_submit_urb(usbtouch->irq, GFP_NOIO);
+ mutex_unlock(&input->mutex);
+
+ return result;
+}
+
+static int usbtouch_reset_resume(struct usb_interface *intf)
+{
+ struct usbtouch_usb *usbtouch = usb_get_intfdata(intf);
+ struct input_dev *input = usbtouch->input;
+ int err = 0;
+
+ /* reinit the device */
+ if (usbtouch->type->init) {
+ err = usbtouch->type->init(usbtouch);
+ if (err) {
+ dbg("%s - type->init() failed, err: %d",
+ __func__, err);
+ return err;
+ }
+ }
+
+ /* restart IO if needed */
+ mutex_lock(&input->mutex);
+ if (input->users)
+ err = usb_submit_urb(usbtouch->irq, GFP_NOIO);
+ mutex_unlock(&input->mutex);
+
+ return err;
+}
+
+static void usbtouch_free_buffers(struct usb_device *udev,
+ struct usbtouch_usb *usbtouch)
+{
+ usb_free_coherent(udev, usbtouch->type->rept_size,
+ usbtouch->data, usbtouch->data_dma);
+ kfree(usbtouch->buffer);
+}
+
+static struct usb_endpoint_descriptor *usbtouch_get_input_endpoint(struct usb_host_interface *interface)
+{
+ int i;
+
+ for (i = 0; i < interface->desc.bNumEndpoints; i++)
+ if (usb_endpoint_dir_in(&interface->endpoint[i].desc))
+ return &interface->endpoint[i].desc;
+
+ return NULL;
+}
+
+
+static void tp_timeout_func(struct work_struct *work){
+ struct usbtouch_usb *usbtouch =
+ container_of(work, struct usbtouch_usb, tp_work.work);
+ int button_up = -1;
+
+ mutex_lock(&usbtouch->tp_timeout_mutex);
+ button_up = --usbtouch->tp_timer_count;
+ mutex_unlock(&usbtouch->tp_timeout_mutex);
+
+ if( button_up < 0){
+ input_mt_sync(usbtouch->input);
+ input_sync(usbtouch->input);
+ }else{
+ queue_delayed_work(usbtouch->tp_queue, &usbtouch->tp_work, msecs_to_jiffies(TP_TIMEOUT));
+ }
+
+}
+
+static int usbtouch_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct usbtouch_usb *usbtouch;
+ struct input_dev *input_dev;
+ struct usb_endpoint_descriptor *endpoint;
+ struct usb_device *udev = interface_to_usbdev(intf);
+ struct usbtouch_device_info *type;
+ int err = -ENOMEM;
+
+ GetUserCfg();
+
+ /* some devices are ignored */
+ if (id->driver_info == -1)
+ return -ENODEV;
+
+ endpoint = usbtouch_get_input_endpoint(intf->cur_altsetting);
+ if (!endpoint)
+ return -ENXIO;
+
+ usbtouch = kzalloc(sizeof(struct usbtouch_usb), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!usbtouch || !input_dev)
+ goto out_free;
+
+ type = &usbtouch_dev_info[id->driver_info];
+ usbtouch->type = type;
+ if (!type->process_pkt)
+ type->process_pkt = usbtouch_process_pkt;
+
+ usbtouch->data = usb_alloc_coherent(udev, type->rept_size,
+ GFP_KERNEL, &usbtouch->data_dma);
+ if (!usbtouch->data)
+ goto out_free;
+
+ if (type->get_pkt_len) {
+ usbtouch->buffer = kmalloc(type->rept_size, GFP_KERNEL);
+ if (!usbtouch->buffer)
+ goto out_free_buffers;
+ }
+
+ usbtouch->irq = usb_alloc_urb(0, GFP_KERNEL);
+ if (!usbtouch->irq) {
+ dbg("%s - usb_alloc_urb failed: usbtouch->irq", __func__);
+ goto out_free_buffers;
+ }
+
+ usbtouch->interface = intf;
+ usbtouch->input = input_dev;
+
+ if (udev->manufacturer)
+ strlcpy(usbtouch->name, udev->manufacturer, sizeof(usbtouch->name));
+
+ if (udev->product) {
+ if (udev->manufacturer)
+ strlcat(usbtouch->name, " ", sizeof(usbtouch->name));
+ strlcat(usbtouch->name, udev->product, sizeof(usbtouch->name));
+ }
+
+ if (!strlen(usbtouch->name))
+ snprintf(usbtouch->name, sizeof(usbtouch->name),
+ "USB Touchscreen %04x:%04x",
+ le16_to_cpu(udev->descriptor.idVendor),
+ le16_to_cpu(udev->descriptor.idProduct));
+
+ usb_make_path(udev, usbtouch->phys, sizeof(usbtouch->phys));
+ strlcat(usbtouch->phys, "/input0", sizeof(usbtouch->phys));
+
+ input_dev->name = usbtouch->name;
+ input_dev->phys = usbtouch->phys;
+ usb_to_input_id(udev, &input_dev->id);
+ input_dev->dev.parent = &intf->dev;
+
+
+ input_set_drvdata(input_dev, usbtouch);
+
+ input_dev->open = usbtouch_open;
+ input_dev->close = usbtouch_close;
+
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+
+
+ set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+
+ set_bit(ABS_MT_POSITION_X, input_dev->absbit);
+ set_bit(ABS_MT_POSITION_Y, input_dev->absbit);
+ input_set_abs_params(input_dev, ABS_MT_POSITION_X, type->min_xc, type->max_xc, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_POSITION_Y, type->min_yc, type->max_yc, 0, 0);
+
+ mutex_init(&usbtouch->tp_timeout_mutex);
+ usbtouch->tp_timer_count = -1;
+ usbtouch->tp_queue= create_singlethread_workqueue("tp_queue");
+ INIT_DELAYED_WORK(&usbtouch->tp_work, tp_timeout_func);
+ //queue_delayed_work(tp_queue, &tp_work, msecs_to_jiffies(TP_TIMEOUT));
+
+ //input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+ //input_set_abs_params(input_dev, ABS_X, type->min_xc, type->max_xc, 0, 0);
+ //input_set_abs_params(input_dev, ABS_Y, type->min_yc, type->max_yc, 0, 0);
+
+ //if (type->max_press)
+ // input_set_abs_params(input_dev, ABS_PRESSURE, type->min_press,
+ // type->max_press, 0, 0);
+
+
+ if (usb_endpoint_type(endpoint) == USB_ENDPOINT_XFER_INT)
+ usb_fill_int_urb(usbtouch->irq, udev,
+ usb_rcvintpipe(udev, endpoint->bEndpointAddress),
+ usbtouch->data, type->rept_size,
+ usbtouch_irq, usbtouch, endpoint->bInterval);
+ else
+ usb_fill_bulk_urb(usbtouch->irq, udev,
+ usb_rcvbulkpipe(udev, endpoint->bEndpointAddress),
+ usbtouch->data, type->rept_size,
+ usbtouch_irq, usbtouch);
+
+ usbtouch->irq->dev = udev;
+ usbtouch->irq->transfer_dma = usbtouch->data_dma;
+ usbtouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+ /* device specific allocations */
+ if (type->alloc) {
+ err = type->alloc(usbtouch);
+ if (err) {
+ dbg("%s - type->alloc() failed, err: %d", __func__, err);
+ goto out_free_urb;
+ }
+ }
+
+ /* device specific initialisation*/
+ if (type->init) {
+ err = type->init(usbtouch);
+ if (err) {
+ dbg("%s - type->init() failed, err: %d", __func__, err);
+ goto out_do_exit;
+ }
+ }
+
+ err = input_register_device(usbtouch->input);
+ if (err) {
+ dbg("%s - input_register_device failed, err: %d", __func__, err);
+ goto out_do_exit;
+ }
+
+ usb_set_intfdata(intf, usbtouch);
+
+ if (usbtouch->type->irq_always) {
+ /* this can't fail */
+ usb_autopm_get_interface(intf);
+ err = usb_submit_urb(usbtouch->irq, GFP_KERNEL);
+ if (err) {
+ usb_autopm_put_interface(intf);
+ err("%s - usb_submit_urb failed with result: %d",
+ __func__, err);
+ goto out_unregister_input;
+ }
+ }
+
+ return 0;
+
+out_unregister_input:
+ input_unregister_device(input_dev);
+ input_dev = NULL;
+out_do_exit:
+ if (type->exit)
+ type->exit(usbtouch);
+out_free_urb:
+ usb_free_urb(usbtouch->irq);
+out_free_buffers:
+ usbtouch_free_buffers(udev, usbtouch);
+out_free:
+ input_free_device(input_dev);
+ kfree(usbtouch);
+ return err;
+}
+
+static void usbtouch_disconnect(struct usb_interface *intf)
+{
+ struct usbtouch_usb *usbtouch = usb_get_intfdata(intf);
+
+ dbg("%s - called", __func__);
+
+ if (!usbtouch)
+ return;
+
+ dbg("%s - usbtouch is initialized, cleaning up", __func__);
+ mutex_destroy(&usbtouch->tp_timeout_mutex);
+ usb_set_intfdata(intf, NULL);
+ /* this will stop IO via close */
+ input_unregister_device(usbtouch->input);
+ usb_free_urb(usbtouch->irq);
+ if (usbtouch->type->exit)
+ usbtouch->type->exit(usbtouch);
+ usbtouch_free_buffers(interface_to_usbdev(intf), usbtouch);
+ kfree(usbtouch);
+}
+
+
+static void GetUserCfg(void)
+{
+struct file *fd;
+char buffer[256];
+loff_t pos;
+
+mm_segment_t old_fs = get_fs();
+set_fs(KERNEL_DS);
+
+memset((char *)&buffer[0],0,256);
+
+fd= filp_open("/etc/metouch.cfg",O_RDONLY,0);
+
+if (IS_ERR(fd))
+ {
+ printk("Unable to open metouch config information.\n");
+ goto exithere;
+ }
+else
+ {
+ printk("open metouch config file ok.\n");
+
+ pos=0;
+ vfs_read(fd,buffer,256,&pos);
+
+ if (pos < 0)
+ {
+ printk("reach the end of file\n");
+ }
+ else
+ {
+ AnlysCmd(buffer);
+ }
+ filp_close(fd,NULL);
+ }
+exithere:;
+set_fs(old_fs);
+}
+
+static void AnlysCmd(char *cmd)
+{
+//static int swapx=0;
+//static int swapy=0;
+//static int v_shift=0;
+//static int h_shift=0;
+char *pstr=NULL;
+char upx[10];
+char upy[10];
+char vsh[10];
+char hsh[10];
+int i=0;
+
+//clear all invisible char
+DeleteAllSpace(cmd);
+
+//find UPSIDEX
+pstr=NULL;
+pstr=strstr((const char*)cmd,(const char*)"UPSIDEX=");
+if (pstr!=NULL)
+{
+strncpy(upx,(char *)(pstr+strlen("UPSIDEX=")),4);
+
+i=0;
+while (i<4)
+ {
+ if (upx[i]<0x20)
+ {
+ upx[i]=0;
+ swapx = myatoi(upx);
+ break;
+ }
+ i++;
+ }
+}
+
+//find UPSIDEY
+pstr=NULL;
+pstr=strstr((const char*)cmd,(const char*)"UPSIDEY=");
+if (pstr!=NULL)
+{
+strncpy(upy,(char *)(pstr+strlen("UPSIDEY=")),4);
+
+i=0;
+while (i<4)
+ {
+ if (upy[i]<0x20)
+ {
+ upy[i]=0;
+ swapy = myatoi(upy);
+ break;
+ }
+ i++;
+ }
+}
+
+//find V_SHIFT
+pstr=NULL;
+pstr=strstr((const char*)cmd,(const char*)"V_SHIFT=");
+if (pstr!=NULL)
+{
+strncpy(vsh,(char *)(pstr+strlen("V_SHIFT=")),4);
+i=0;
+while (i<4)
+ {
+ if (vsh[i]<0x20)
+ {
+ vsh[i]=0;
+ v_shift = myatoi(vsh);
+ break;
+ }
+ i++;
+ }
+}
+
+//find H_SHIFT
+pstr=NULL;
+pstr=strstr((const char*)cmd,(const char*)"H_SHIFT=");
+if (pstr!=NULL)
+{
+strncpy(hsh,(char *)(pstr+strlen("H_SHIFT=")),4);
+i=0;
+while (i<4)
+ {
+ if (hsh[i]<0x20)
+ {
+ hsh[i]=0;
+ h_shift = myatoi(hsh);
+ break;
+ }
+ i++;
+ }
+}
+//v_flag
+pstr=NULL;
+pstr=strstr((const char*)cmd,(const char*)"V_FLAG=");
+if (pstr!=NULL)
+{
+strncpy(hsh,(char *)(pstr+strlen("V_FLAG=")),4);
+
+i=0;
+while (i<4)
+ {
+ if (hsh[i]<0x20)
+ {
+ hsh[i]=0;
+ v_flag = myatoi(hsh);
+ break;
+ }
+ i++;
+ }
+}
+
+//H_flag
+pstr=NULL;
+pstr=strstr((const char*)cmd,(const char*)"H_FLAG=");
+if (pstr!=NULL)
+{
+strncpy(hsh,(char *)(pstr+strlen("H_FLAG=")),4);
+i=0;
+while (i<4)
+ {
+ if (hsh[i]<0x20)
+ {
+ hsh[i]=0;
+ h_flag = myatoi(hsh);
+ break;
+ }
+ i++;
+ }
+}
+
+printk("%d\n",v_flag);
+printk("%d\n",h_flag);
+printk("%d\n",swapx);
+printk("%d\n",swapy);
+printk("%d\n",v_shift);
+printk("%d\n",h_shift);
+}
+
+static void DeleteAllSpace(char *cmd)
+{
+char tmp[256];
+int i=0;
+int j=0;
+memset((char *)&tmp,0,256);
+for (i=0;i<250;i++)
+ {
+ //printk("%02x ",cmd[i]&0xff);
+
+ if ((cmd[i]!=0x09) && (cmd[i]!=0x20))
+ {
+ tmp[j]=cmd[i];
+ j++;
+ }
+ }
+//printk("%s\n",cmd);
+
+//printk("\n");
+tmp[j]=0;
+//for (i=0;i<250;i++)
+// {
+ //printk("%02x ",tmp[i]&0xff);
+// }
+//printk("%s\n",tmp);
+
+strncpy(cmd,tmp,250);
+}
+
+static int myatoi(char *str)
+{
+int i;
+int num=0;
+int len = strlen(str);
+
+
+for (i=0;i<len;i++)
+ {
+ // printk("%02x ",str[i]);
+ if (str[i]<0x30)
+ break;
+ else
+ {
+ // printk("s=%x d=%x s=%x ",str[i],str[i]-0x30,mypow(len-i-1));
+ num = num + mypow(i)*(str[len-i-1]-0x30);
+ // printk("num = %d\n",num);
+ }
+ }
+//printk("\n");
+return num;
+}
+
+int mypow(int t)
+{
+if (t==0) return 1;
+if (t==1) return 10;
+if (t==2) return 100;
+if (t==3) return 1000;
+if (t==4) return 10000;
+else
+return 0;
+}
+
+static struct usb_driver usbtouch_driver = {
+ .name = "metusb",
+ .probe = usbtouch_probe,
+ .disconnect = usbtouch_disconnect,
+ .suspend = usbtouch_suspend,
+ .resume = usbtouch_resume,
+ .reset_resume = usbtouch_reset_resume,
+ .id_table = metusb_table,
+ .supports_autosuspend = 1,
+};
+
+
+static int __init usbtouch_init(void)
+{
+ return usb_register(&usbtouch_driver);
+}
+
+static void __exit usbtouch_cleanup(void)
+{
+ usb_deregister(&usbtouch_driver);
+}
+
+module_init(usbtouch_init);
+module_exit(usbtouch_cleanup);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+MODULE_ALIAS("metusb");
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/semisens/Makefile b/ANDROID_3.4.5/drivers/input/touchscreen/semisens/Makefile
new file mode 100755
index 00000000..4539aa8d
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/semisens/Makefile
@@ -0,0 +1,33 @@
+KERNELDIR=../../../../
+CROSS = arm_1103_le-
+CC= $(CROSS)gcc
+LD= $(CROSS)ld
+STRIP = $(CROSS)strip
+
+DEBUG = n
+
+# Add your debugging flag (or not) to EXTRA_CFLAGS
+ifeq ($(DEBUG),y)
+# DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+DEBFLAGS = -O0 -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+
+else
+ DEBFLAGS = -O2 -Wall
+endif
+
+EXTRA_CFLAGS += $(DEBFLAGS)
+
+
+MY_MODULE_NAME=s_wmt_ts_semisens
+
+obj-m := $(MY_MODULE_NAME).o
+$(MY_MODULE_NAME)-objs := sn310m-touch.o touch.o
+#mach-sn310m-sample.o
+
+default:
+ $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules
+ $(STRIP) --strip-debug $(MY_MODULE_NAME).ko
+ rm -rf *.o *~ core .depend .*.cmd *.mod.c .tmp_versions *.order *.symvers modules.builtin
+
+clean:
+ rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.order *.symvers modules.builtin
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/semisens/sn310m-touch-pdata.h b/ANDROID_3.4.5/drivers/input/touchscreen/semisens/sn310m-touch-pdata.h
new file mode 100755
index 00000000..fcf1e3c6
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/semisens/sn310m-touch-pdata.h
@@ -0,0 +1,201 @@
+/****************************************************************
+ *
+ * sn310m-touch-pdata.c
+ *
+ * Copyright (c) 2013 SEMISENS Co.,Ltd
+ * http://www.semisens.com
+ *
+ ****************************************************************/
+
+#ifndef __TOUCH_PDATA_H
+#define __TOUCH_PDATA_H
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ #include <linux/earlysuspend.h>
+#endif
+
+#include <linux/interrupt.h>
+
+#ifndef errlog
+#define errlog(fmt, args...) printk(KERN_ERR "[%s:%d]: " fmt, __FUNCTION__, __LINE__ ,## args)
+#endif
+
+
+//#define DEBUG_TOUCH
+
+#undef dbg
+#ifdef DEBUG_TOUCH
+#define dbg(fmt, args...) printk(KERN_ERR "[%s:%d]: " fmt, __FUNCTION__, __LINE__ ,## args)
+#else
+#define dbg(fmt, args...)
+#endif
+
+#undef MSM_GPIO_TO_INT
+#define MSM_GPIO_TO_INT(a) (a)
+
+
+
+
+#define I2C_TOUCH_NAME "SN310M"
+#define I2C_SEND_MAX_SIZE 512 // I2C Send/Receive data max size
+
+//--------------------------------------------
+// Button struct (1 = press, 0 = release)
+//--------------------------------------------
+typedef struct button__t {
+ unsigned char bt0_press :1; // lsb
+ unsigned char bt1_press :1;
+ unsigned char bt2_press :1;
+ unsigned char bt3_press :1;
+ unsigned char bt4_press :1;
+ unsigned char bt5_press :1;
+ unsigned char bt6_press :1;
+ unsigned char bt7_press :1; // msb
+} __attribute__ ((packed)) button_t;
+
+typedef union button__u {
+ unsigned char ubyte;
+ button_t bits;
+} __attribute__ ((packed)) button_u;
+
+//--------------------------------------------
+// Touch Event type define
+//--------------------------------------------
+#define TS_EVENT_UNKNOWN 0x00
+#define TS_EVENT_PRESS 0x01
+#define TS_EVENT_MOVE 0x02
+#define TS_EVENT_RELEASE 0x03
+
+typedef struct finger__t {
+ unsigned int status; // true : ts data updated, false : no update data
+ unsigned int event; // ts event type
+ unsigned int id; // ts received id
+ unsigned int x; // ts data x
+ unsigned int y; // ts data y
+ unsigned int area; // ts finger area
+ unsigned int pressure; // ts finger pressure
+} __attribute__ ((packed)) finger_t;
+
+struct touch {
+ int irq;
+ struct i2c_client *client;
+ struct touch_pdata *pdata;
+ struct input_dev *input;
+ char phys[32];
+
+ finger_t *finger; // finger data
+ struct mutex mutex;
+
+ // sysfs control flags
+ unsigned char disabled; // interrupt status
+ unsigned char fw_version;
+
+ unsigned char *fw_buf;
+ unsigned int fw_size;
+ int fw_status;
+
+ // irq func used
+ struct workqueue_struct *work_queue;
+ struct work_struct work;
+
+ // noise filter work
+ struct delayed_work filter_dwork;
+
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+ struct early_suspend power;
+#endif
+};
+
+struct i2c_client;
+struct input_dev;
+struct device;
+
+#define IRQ_MODE_THREAD 0
+#define IRQ_MODE_NORMAL 1
+#define IRQ_MODE_POLLING 2
+
+//--------------------------------------------
+// IRQ type & trigger action
+//--------------------------------------------
+//
+// IRQF_TRIGGER_RISING, IRQF_TRIGGER_FALLING, IRQF_TRIGGER_HIGH, IRQF_TRIGGER_LOW
+// IRQF_DISABLED, IRQF_SHARED, IRQF_IRQPOLL, IRQF_ONESHOT, IRQF_NO_THREAD
+//
+//--------------------------------------------
+struct touch_pdata {
+ char *name; // input drv name
+
+ int irq_gpio; // irq gpio define
+ int reset_gpio; // reset gpio define
+ int reset_level; // reset level setting (1 = High reset, 0 = Low reset)
+
+ int irq_mode; // IRQ_MODE_THREAD, IRQ_MODE_NORMAL, IRQ_MODE_POLLING
+ int irq_flags; // irq flags setup : Therad irq mode(IRQF_TRIGGER_HIGH | IRQF_ONESHOT)
+
+ int abs_max_x, abs_max_y;
+ int abs_min_x, abs_min_y;
+
+ int area_max, area_min;
+ int press_max, press_min;
+ int id_max, id_min;
+
+ int vendor, product, version;
+
+ int max_fingers;
+
+ int *keycode, keycnt;
+ int lcd_exchg;
+
+ //--------------------------------------------
+ // Control function
+ //--------------------------------------------
+ void (*gpio_init) (void); // gpio early-init function
+
+ irqreturn_t (*irq_func) (int irq, void *handle);
+ void (*touch_work) (struct touch *ts);
+
+ void (*report) (struct touch *ts);
+ void (*key_report) (struct touch *ts, unsigned char button_data);
+
+ int (*early_probe) (struct touch *ts);
+ int (*probe) (struct touch *ts);
+ void (*enable) (struct touch *ts);
+ void (*disable) (struct touch *ts);
+ int (*input_open) (struct input_dev *input);
+ void (*input_close) (struct input_dev *input);
+
+ void (*event_clear) (struct touch *ts);
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ void (*resume) (struct early_suspend *h);
+ void (*suspend) (struct early_suspend *h);
+#endif
+
+ /* by limst, added to control power for touch IC */
+ int (*power) (int on);
+
+ //--------------------------------------------
+ // I2C control function
+ //--------------------------------------------
+ int (*i2c_write) (struct i2c_client *client, unsigned char *cmd, unsigned int cmd_len, unsigned char *data, unsigned int len);
+ int (*i2c_read) (struct i2c_client *client, unsigned char *cmd, unsigned int cmd_len, unsigned char *data, unsigned int len);
+
+ //--------------------------------------------
+ // Firmware update control function
+ //--------------------------------------------
+ char *fw_filename;
+ int fw_filesize;
+
+ int (*i2c_boot_write) (struct i2c_client *client, unsigned char *cmd, unsigned int cmd_len, unsigned char *data, unsigned int len);
+ int (*i2c_boot_read) (struct i2c_client *client, unsigned char *cmd, unsigned int cmd_len, unsigned char *data, unsigned int len);
+ int (*fw_control) (struct touch *ts, unsigned int fw_status);
+ int (*flash_firmware) (struct device *dev, const char *fw_name);
+
+ //--------------------------------------------
+ // Calibration control function
+ //--------------------------------------------
+ int (*calibration) (struct touch *ts);
+};
+
+#endif // __TOUCH_PDATA_H
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/semisens/sn310m-touch.c b/ANDROID_3.4.5/drivers/input/touchscreen/semisens/sn310m-touch.c
new file mode 100755
index 00000000..81275baf
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/semisens/sn310m-touch.c
@@ -0,0 +1,332 @@
+/****************************************************************
+ *
+ * sn310m-touch.c : I2C Touchscreen driver (platform data struct)
+ *
+ * Copyright (c) 2013 SEMISENS Co.,Ltd
+ * http://www.semisens.com
+ *
+ ****************************************************************/
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/slab.h>
+#include <linux/hrtimer.h>
+#include <asm/unaligned.h>
+#include <linux/firmware.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+
+#include <linux/gpio.h>
+#include <mach/wmt_iomux.h>
+
+//----------------------------------------------
+#include "sn310m-touch-pdata.h"
+#include "sn310m-touch.h"
+#include "touch.h"
+
+
+//----------------------------------------------
+unsigned char sn310m_id_tracking(struct touch *ts, unsigned char find_id);
+
+//----------------------------------------------
+// Touch i2c control function
+//----------------------------------------------
+int sn310m_i2c_read(struct i2c_client *client, unsigned char *cmd, unsigned int cmd_len, unsigned char *data, unsigned int len)
+{
+ struct i2c_msg msg[2];
+ int ret = 0;
+ unsigned char i = 0;
+ unsigned char cmd_tmp[10] = {0, };
+
+ if((len == 0) || (data == NULL)) {
+ dev_err(&client->dev, "I2C read error: Null pointer or length == 0\n");
+ return -1;
+ }
+
+ memset(cmd_tmp, 0x00, sizeof(cmd_tmp));
+
+ if(cmd_len) {
+ for(i = 0; i < cmd_len; i++) {
+ cmd_tmp[i] = cmd[cmd_len -1 -i];
+ }
+ }
+
+ memset(msg, 0x00, sizeof(msg));
+ msg[0].addr = client->addr;
+ msg[0].flags = client->flags & I2C_M_TEN;
+ msg[0].len = cmd_len;
+ msg[0].buf = cmd_tmp;
+
+ msg[1].addr = client->addr;
+ msg[1].flags = client->flags & I2C_M_TEN;
+ msg[1].flags |= I2C_M_RD;
+ msg[1].len = len;
+ msg[1].buf = data;
+
+ if((ret = i2c_transfer(client->adapter, msg, 2)) != 2) {
+ dev_err(&client->dev, "I2C read error: (%d) reg: 0x%X len: %d\n", ret, cmd_tmp[0], len);
+ return -EIO;
+ }
+
+ return len;
+}
+
+int sn310m_i2c_write(struct i2c_client *client, unsigned char *cmd, unsigned int cmd_len, unsigned char *data, unsigned int len)
+{
+ int ret = 0;
+ unsigned char block_data[10] = {0, };
+ unsigned char i = 0;
+ unsigned char cmd_tmp[10] = {0, };
+
+ if((cmd_len + len) >= sizeof(block_data)) {
+ dev_err(&client->dev, "I2C write error: wdata overflow reg: 0x%X len: %d\n", cmd[0], cmd_len + len);
+ return -1;
+ }
+
+ memset(block_data, 0x00, sizeof(block_data));
+ memset(cmd_tmp, 0x00, sizeof(cmd_tmp));
+
+ if(cmd_len) {
+ for(i = 0; i < cmd_len; i++) {
+ cmd_tmp[i] = cmd[cmd_len -1 -i];
+ }
+ }
+
+ if(cmd_len)
+ memcpy(&block_data[0], &cmd_tmp[0], cmd_len);
+
+ if(len)
+ memcpy(&block_data[cmd_len], &data[0], len);
+
+ if((ret = i2c_master_send(client, block_data, (cmd_len + len))) < 0) {
+ dev_err(&client->dev, "I2C write error: (%d) reg: 0x%X len: %d\n", ret, cmd[0], len);
+ return ret;
+ }
+
+ return len;
+}
+
+//----------------------------------------------
+// Touch initialize & finalize function
+//----------------------------------------------
+int sn310m_input_open(struct input_dev *input)
+{
+ struct touch *ts = input_get_drvdata(input);
+
+ dbg("%s\n", __func__);
+
+ ts->pdata->enable(ts);
+
+ return 0;
+}
+
+void sn310m_enable(struct touch *ts)
+{
+ unsigned short cmd = REG_TS_STATUS;
+ unsigned int rdata = 0;
+ dbg("sn310m_enable++\n");
+ if(ts->disabled) {
+ while(!gpio_get_value(ts->pdata->irq_gpio))
+ ts->pdata->i2c_read(ts->client, (unsigned char *)&cmd, sizeof(cmd), (unsigned char *)&rdata, sizeof(rdata));
+ wmt_gpio_set_irq_type(ts->pdata->irq_gpio, IRQ_TYPE_EDGE_FALLING);
+ wmt_gpio_unmask_irq(ts->pdata->irq_gpio);
+ dbg("enable_irq (%d)\n",ts->irq);
+ ts->disabled = false;
+ }
+ dbg("sn310m_enable--\n");
+}
+
+void sn310m_disable(struct touch *ts)
+{
+ dbg("sn310m_disable++\n");
+ if(!ts->disabled) {
+ //disable_irq(ts->irq);//wmt_gpio_mask_irq(ts->pdata->irq_gpio);//
+ wmt_gpio_mask_irq(ts->pdata->irq_gpio);
+ dbg("disable_irq(ts->irq);\n");
+ ts->disabled = true;
+ if(ts->pdata->event_clear){
+ ts->pdata->event_clear(ts);
+ }
+ }
+ dbg("sn310m_disable--");
+}
+
+int sn310m_early_probe(struct touch *ts)
+{
+ // nothing to do...
+
+ return 0;
+}
+
+int sn310m_probe(struct touch *ts)
+{
+ unsigned short cmd = REG_FIRMWARE_VERSION;
+ unsigned short rdata = 0;
+
+ if(ts->pdata->i2c_read(ts->client, (unsigned char *)&cmd, sizeof(cmd), (unsigned char *)&rdata, sizeof(rdata)) < 0) {
+ errlog("fail to get touch ic firmware version.\n");
+ return -1;
+ }
+
+ ts->fw_version = rdata;
+
+ dbg("touch ic firmware version : %d \n", rdata);
+
+ return 0;
+}
+
+//----------------------------------------------
+// calibration function
+//----------------------------------------------
+int sn310m_calibration(struct touch *ts)
+{
+ // nothing to do...
+
+ return 0;
+}
+
+#define SN310M_NATIVE_INTERFACE
+#if defined(SN310M_NATIVE_INTERFACE)
+#include <linux/syscalls.h>
+extern int g_MiscInitialize;
+#endif
+
+//----------------------------------------------
+// Touch data processing function
+//----------------------------------------------
+void sn310m_work(struct touch *ts)
+{
+ unsigned char find_slot = 0;
+ unsigned short cmd = 0;
+ status_reg_u status;
+ data_reg_t data;
+ button_u button;
+ unsigned int ids = 0;
+ int i = 0;
+
+ mutex_lock(&ts->mutex);
+
+ cmd = REG_TS_STATUS;
+ ts->pdata->i2c_read(ts->client, (unsigned char *)&cmd, sizeof(cmd), (unsigned char *)&status.uint, sizeof(status_reg_u));
+
+ if(status.bits.ts_cnt <= ts->pdata->max_fingers) {
+ unsigned char cnt = 0;
+
+ if(ts->pdata->keycode && (status.bits.ts_cnt == 0)) {
+ button.bits.bt0_press = (status.bits.button & 0x01) ? 1 : 0;
+ button.bits.bt1_press = (status.bits.button & 0x02) ? 1 : 0;
+ button.bits.bt2_press = (status.bits.button & 0x04) ? 1 : 0;
+ button.bits.bt3_press = (status.bits.button & 0x08) ? 1 : 0;
+
+ ts->pdata->key_report(ts, button.ubyte);
+ }
+
+ for(cnt = 0; cnt < status.bits.ts_cnt; cnt++) {
+ unsigned int id;
+ unsigned int x;
+ unsigned int y;
+ unsigned int area;
+ unsigned int pressure;
+
+ cmd = REG_TS_DATA(cnt);
+ ts->pdata->i2c_read(ts->client, (unsigned char *)&cmd, sizeof(cmd), (unsigned char *)&data.packet0, sizeof(data_reg_t));
+
+ id = data.packet0 >> 12;
+ x = data.packet0 & 0xfff;
+ y = data.packet1 & 0xfff;
+ area = data.packet2 & 0xfff;
+ pressure = ((data.packet1 >> 8) & 0x00f0) + (data.packet2 >> 12);
+
+ dbg("DEBUG(%s) : cmd=%d, id=%d, x=%d, y=%d, area=%d, pressure=%d \n", __func__, cmd, id, x, y, area, pressure);
+ dbg("DEBUG(%s) : pkt0=%x pkt1=%x pkt2=%x \n", __func__, data.packet0, data.packet1, data.packet2);
+
+ if((x >= ts->pdata->abs_max_x) || (y >= ts->pdata->abs_max_y)) {
+ if(ts->pdata->event_clear)
+ ts->pdata->event_clear(ts);
+
+ dbg("ERROR(%s) : x(%d) or y(%d) value overflow!\n", __func__, x, y);
+ continue;
+ }
+
+ if(ts->pdata->id_max) {
+ if((id >= ts->pdata->id_max) || (id < ts->pdata->id_min)) {
+ if(ts->pdata->event_clear)
+ ts->pdata->event_clear(ts);
+
+ dbg("ERROR(%s) : id(%d) value overflow!\n", __func__, id);
+ continue;
+ }
+ if((find_slot = sn310m_id_tracking(ts, id)) == 0xFF) {
+ dbg("ERROR(%s) : Empty slot not found\n", __func__);
+ continue;
+ }
+ }
+ else {
+ if(id == 0)
+ continue;
+
+ find_slot = cnt;
+ }
+
+ if(ts->finger[find_slot].event == TS_EVENT_UNKNOWN)
+ ts->finger[find_slot].event = TS_EVENT_PRESS;
+ else if((ts->finger[find_slot].event == TS_EVENT_PRESS) || (ts->finger[find_slot].event == TS_EVENT_MOVE))
+ ts->finger[find_slot].event = TS_EVENT_MOVE;
+
+ if (ts->pdata->lcd_exchg) {
+ int tmp;
+ tmp = x;
+ x = y;
+ y = ts->pdata->abs_max_x - tmp;
+ }
+
+ ts->finger[find_slot].status = true;
+ ts->finger[find_slot].id = id;
+ ts->finger[find_slot].x = x;
+ ts->finger[find_slot].y = y;
+ ts->finger[find_slot].area = (ts->pdata->area_max < area) ? ts->pdata->area_max : area;
+ ts->finger[find_slot].pressure = (ts->pdata->press_max < pressure) ? ts->pdata->press_max : pressure;
+ ids |= 1 << find_slot;
+ }
+ }
+
+ for(i = 0; i < ts->pdata->max_fingers; i++) {
+ if(!(ids & (1 << i))) {
+ if(ts->finger[i].event != TS_EVENT_UNKNOWN) {
+ ts->finger[i].status = true;
+ ts->finger[i].event = TS_EVENT_RELEASE;
+ }
+ }
+ }
+
+ ts->pdata->report(ts);
+ mutex_unlock(&ts->mutex);
+ wmt_gpio_unmask_irq(ts->pdata->irq_gpio);
+}
+
+unsigned char sn310m_id_tracking(struct touch *ts, unsigned char find_id)
+{
+ unsigned char find_slot = 0xFF;
+ int i = 0;
+
+ for(i = 0; i < ts->pdata->max_fingers; i++) {
+ if(ts->finger[i].id == find_id)
+ find_slot = i;
+
+ if((ts->finger[i].event == TS_EVENT_UNKNOWN) && (find_slot == 0xFF))
+ find_slot = i;
+ }
+ return find_slot;
+}
+
+//----------------------------------------------
+// Firmware update Control function
+//----------------------------------------------
+int sn310m_flash_firmware(struct device *dev, const char *fw_name)
+{
+ // nothing to do...
+ return 0;
+}
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/semisens/sn310m-touch.h b/ANDROID_3.4.5/drivers/input/touchscreen/semisens/sn310m-touch.h
new file mode 100755
index 00000000..0469bf19
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/semisens/sn310m-touch.h
@@ -0,0 +1,97 @@
+/****************************************************************
+ *
+ * sn310m-touch.c : i2c Touchscreen driver (platform data struct)
+ *
+ * Copyright (c) 2013 SEMISENS Co.,Ltd
+ * http://www.semisens.com
+ *
+ ****************************************************************/
+#ifndef __SN310M_TOUCH_H
+#define __SN310M_TOUCH_H
+
+//----------------------------------------------
+// register address for firmware update
+//----------------------------------------------
+#define REG_CMD_ISP_MODE 0x02F1 // 0x0200 : prepare eFlash, 0x0100 : finish eFalsh
+#define REG_CMD_FLASH_BUS 0x04F1 // 0x0000 : set eFlash bus functions
+#define REG_CMD_FLASH_ENABLE 0x08F1 // 0xFFFF : enable eFlash functions
+#define REG_CMD_FLASH_AUTH 0x00F4 // 0x0100 : get eFlash approach authority
+#define REG_CMD_FLASH_CON_EN 0x02F4 // 0x0000 : enable eFlash controller
+#define REG_CMD_FLASH_COMMAND 0x04F4 // 0x0200 : erase eFlash, 0x0000 : write eFlash
+#define REG_CMD_FLASH_BUSY 0x08F4 // [15] bit is busy flag for eflash eperating.
+
+//----------------------------------------------
+// register setting value for firmware update
+//----------------------------------------------
+#define REG_SET_PREPARE_FLASH_ACCESS 0x0200
+#define REG_SET_FINISH_FLASH_ACCESS 0x0100
+#define REG_SET_ENABLE_FLASH_ERASE 0x0200
+#define REG_SET_ENABLE_FLASH_WRITE 0x0000
+
+#define SN310M_MAX_FW_SIZE (10*1024) // 10 Kbytes
+#define REG_FIRMWARE_VERSION (0x3EE0)
+
+//----------------------------------------------
+// Touch status & data register address
+//----------------------------------------------
+#define REG_TS_STATUS 0x00E0
+
+typedef struct status_reg__t {
+ unsigned int ts_cnt :4; // lsb
+ unsigned int reserved1 :4;
+ unsigned int button :5;
+ unsigned int reserved2 :3; // msb
+} __attribute__ ((packed)) status_reg_t;
+
+typedef union status_reg__u {
+ unsigned short uint;
+ status_reg_t bits;
+} __attribute__ ((packed)) status_reg_u;
+
+#define REG_TS_DATA_BASE 0x02E0
+#define REG_TS_DATA(x) (((x * 6) << 8) + REG_TS_DATA_BASE)
+
+typedef struct data_reg__t {
+ unsigned short packet0;
+ unsigned short packet1;
+ unsigned short packet2;
+} __attribute__ ((packed)) data_reg_t;
+
+typedef union data_reg__u {
+ unsigned int uint;
+ data_reg_t bits;
+} __attribute__ ((packed)) data_reg_u;
+
+
+//----------------------------------------------
+// i2c Control function
+//----------------------------------------------
+extern int sn310m_i2c_read(struct i2c_client *client, unsigned char *cmd, unsigned int cmd_len, unsigned char *data, unsigned int len);
+extern int sn310m_i2c_write(struct i2c_client *client, unsigned char *cmd, unsigned int cmd_len, unsigned char *data, unsigned int len);
+
+//----------------------------------------------
+// Touch initialize & finalize function
+//----------------------------------------------
+extern int sn310m_input_open(struct input_dev *input);
+extern void sn310m_enable(struct touch *ts);
+extern void sn310m_disable(struct touch *ts);
+extern int sn310m_early_probe(struct touch *ts);
+extern int sn310m_probe(struct touch *ts);
+
+//----------------------------------------------
+// Calibration function
+//----------------------------------------------
+extern int sn310m_calibration(struct touch *ts);
+
+//----------------------------------------------
+// Touch data processing function
+//----------------------------------------------
+extern void sn310m_work(struct touch *ts);
+
+//----------------------------------------------
+// Firmware update Control function
+//----------------------------------------------
+extern int sn310m_flash_firmware(struct device *dev, const char *fw_name);
+
+#endif // __SN310M_TOUCH_H
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/semisens/touch.c b/ANDROID_3.4.5/drivers/input/touchscreen/semisens/touch.c
new file mode 100755
index 00000000..39d6ce15
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/semisens/touch.c
@@ -0,0 +1,1121 @@
+/****************************************************************
+ *
+ * touch.c : I2C Touchscreen driver
+ *
+ * Copyright (c) 2013 SEMISENS Co.,Ltd
+ * http://www.semisens.com
+ *
+ ****************************************************************/
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/slab.h>
+#include <linux/hrtimer.h>
+#include <asm/unaligned.h>
+#include <linux/firmware.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+
+//----------------------------------------------
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+ #include <linux/wakelock.h>
+ #include <linux/earlysuspend.h>
+ #include <linux/suspend.h>
+#endif
+
+//----------------------------------------------
+#include <linux/input/mt.h>
+#include "sn310m-touch-pdata.h"
+#include "sn310m-touch.h"
+
+//----------------------------------------------
+#include "touch.h"
+#include <linux/gpio.h>
+#include <mach/wmt_iomux.h>
+
+
+extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
+extern int wmt_setsyspara(char *varname, unsigned char *varval);
+
+#define SN310M_NATIVE_INTERFACE /* This is to debug semisens TSC */
+
+#if defined(SN310M_NATIVE_INTERFACE)
+#include <linux/miscdevice.h>
+#include <linux/syscalls.h>
+struct touch* g_ts;
+int g_MiscInitialize = 0;
+static int P_SN310M_Dist_Probe(struct touch* ts);
+static int P_SN310M_Dist_Open(struct inode *inode, struct file *file);
+static long P_SN310M_Dist_Ioctl(struct file *file, unsigned int cmd, unsigned long arg);
+static void P_SN310M_Dist_Remove(void);
+#endif
+
+// function prototype define
+//----------------------------------------------
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ static void touch_suspend(struct early_suspend *h);
+ static void touch_resume(struct early_suspend *h);
+#endif
+
+irqreturn_t touch_irq(int irq, void *handle);
+#if 0 /* unused */
+ static void touch_work(struct touch *ts);
+#endif
+static void touch_work_q(struct work_struct *work);
+static void touch_key_report(struct touch *ts, unsigned char button_data);
+static void touch_report_protocol_a(struct touch *ts);
+static void touch_report_protocol_b(struct touch *ts);
+static void touch_event_clear(struct touch *ts);
+#if 0 /* unused */
+ static void touch_enable(struct touch *ts);
+ static void touch_disable(struct touch *ts);
+#endif
+static void touch_input_close(struct input_dev *input);
+static int touch_input_open(struct input_dev *input);
+static int touch_check_functionality (struct touch_pdata *pdata);
+void touch_hw_reset(struct touch *ts);
+int touch_info_display(struct touch *ts);
+int touch_probe(struct i2c_client *client, const struct i2c_device_id *client_id);
+int touch_remove(struct i2c_client *client);
+
+
+// Kinsey:
+#define WMT_TS_I2C_NAME "wmt-ts"
+static struct i2c_client *l_client;
+
+
+
+
+//----------------------------------------------
+irqreturn_t touch_irq(int irq, void *handle)
+{
+ struct touch *ts = handle;
+ if (gpio_irqstatus(ts->pdata->irq_gpio)){
+ wmt_gpio_ack_irq(ts->pdata->irq_gpio);
+ if (is_gpio_irqenable(ts->pdata->irq_gpio)){
+ wmt_gpio_mask_irq(ts->pdata->irq_gpio);
+ #ifdef CONFIG_HAS_EARLYSUSPEND
+ if(!ts->earlysus)
+ queue_work(ts->work_queue, &ts->work);
+ #else
+ queue_work(ts->work_queue, &ts->work);
+ #endif
+ }
+ return IRQ_HANDLED;
+ }
+ return IRQ_NONE;
+
+}
+
+//----------------------------------------------
+static void touch_work_q(struct work_struct *work)
+{
+ struct touch *ts = container_of(work, struct touch, work);
+ ts->pdata->touch_work(ts);
+}
+
+//----------------------------------------------
+static void touch_key_report(struct touch *ts, unsigned char button_data)
+{
+ static button_u button_old;
+ button_u button_new;
+
+ button_new.ubyte = button_data;
+ if(button_old.ubyte != button_new.ubyte) {
+ if((button_old.bits.bt0_press != button_new.bits.bt0_press) && (ts->pdata->keycnt > 0)) {
+ if(button_new.bits.bt0_press) input_report_key(ts->input, ts->pdata->keycode[0], true);
+ else input_report_key(ts->input, ts->pdata->keycode[0], false);
+ #if defined(DEBUG_TOUCH_KEY)
+ dbg("keycode[0](0x%04X) %s\n", ts->pdata->keycode[0], button_new.bits.bt0_press ? "press":"release");
+ #endif
+ }
+ if((button_old.bits.bt1_press != button_new.bits.bt1_press) && (ts->pdata->keycnt > 1)) {
+ if(button_new.bits.bt1_press) input_report_key(ts->input, ts->pdata->keycode[1], true);
+ else input_report_key(ts->input, ts->pdata->keycode[1], false);
+ #if defined(DEBUG_TOUCH_KEY)
+ dbg("keycode[1](0x%04X) %s\n", ts->pdata->keycode[1], button_new.bits.bt1_press ? "press":"release");
+ #endif
+ }
+ if((button_old.bits.bt2_press != button_new.bits.bt2_press) && (ts->pdata->keycnt > 2)) {
+ if(button_new.bits.bt2_press) input_report_key(ts->input, ts->pdata->keycode[2], true);
+ else input_report_key(ts->input, ts->pdata->keycode[2], false);
+ #if defined(DEBUG_TOUCH_KEY)
+ dbg("keycode[2](0x%04X) %s\n", ts->pdata->keycode[2], button_new.bits.bt2_press ? "press":"release");
+ #endif
+ }
+ if((button_old.bits.bt3_press != button_new.bits.bt3_press) && (ts->pdata->keycnt > 3)) {
+ if(button_new.bits.bt3_press) input_report_key(ts->input, ts->pdata->keycode[3], true);
+ else input_report_key(ts->input, ts->pdata->keycode[3], false);
+ #if defined(DEBUG_TOUCH_KEY)
+ dbg("keycode[3](0x%04X) %s\n", ts->pdata->keycode[3], button_new.bits.bt3_press ? "press":"release");
+ #endif
+ }
+ if((button_old.bits.bt4_press != button_new.bits.bt4_press) && (ts->pdata->keycnt > 4)) {
+ if(button_new.bits.bt4_press) input_report_key(ts->input, ts->pdata->keycode[4], true);
+ else input_report_key(ts->input, ts->pdata->keycode[4], false);
+ #if defined(DEBUG_TOUCH_KEY)
+ dbg("keycode[4](0x%04X) %s\n", ts->pdata->keycode[4], button_new.bits.bt4_press ? "press":"release");
+ #endif
+ }
+ if((button_old.bits.bt5_press != button_new.bits.bt5_press) && (ts->pdata->keycnt > 5)) {
+ if(button_new.bits.bt5_press) input_report_key(ts->input, ts->pdata->keycode[5], true);
+ else input_report_key(ts->input, ts->pdata->keycode[5], false);
+ #if defined(DEBUG_TOUCH_KEY)
+ dbg("keycode[5](0x%04X) %s\n", ts->pdata->keycode[5], button_new.bits.bt5_press ? "press":"release");
+ #endif
+ }
+ if((button_old.bits.bt6_press != button_new.bits.bt6_press) && (ts->pdata->keycnt > 6)) {
+ if(button_new.bits.bt6_press) input_report_key(ts->input, ts->pdata->keycode[6], true);
+ else input_report_key(ts->input, ts->pdata->keycode[6], false);
+ #if defined(DEBUG_TOUCH_KEY)
+ dbg("keycode[6](0x%04X) %s\n", ts->pdata->keycode[6], button_new.bits.bt6_press ? "press":"release");
+ #endif
+ }
+ if((button_old.bits.bt7_press != button_new.bits.bt7_press) && (ts->pdata->keycnt > 7)) {
+ if(button_new.bits.bt7_press) input_report_key(ts->input, ts->pdata->keycode[7], true);
+ else input_report_key(ts->input, ts->pdata->keycode[7], false);
+ #if defined(DEBUG_TOUCH_KEY)
+ dbg("keycode[7](0x%04X) %s\n", ts->pdata->keycode[7], button_new.bits.bt7_press ? "press":"release");
+ #endif
+ }
+ button_old.ubyte = button_new.ubyte;
+ }
+}
+
+//----------------------------------------------
+static void touch_report_protocol_a(struct touch *ts)
+{
+ int id;
+
+ for(id = 0; id < ts->pdata->max_fingers; id++) {
+
+ if(ts->finger[id].event == TS_EVENT_UNKNOWN) continue;
+
+ if(ts->finger[id].event != TS_EVENT_RELEASE) {
+ if(ts->pdata->id_max) input_report_abs(ts->input, ABS_MT_TRACKING_ID, ts->finger[id].id);
+ if(ts->pdata->area_max) input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR, ts->finger[id].area ? ts->finger[id].area : 10);
+ if(ts->pdata->press_max) input_report_abs(ts->input, ABS_MT_PRESSURE, ts->finger[id].pressure);
+
+ input_report_abs(ts->input, ABS_MT_POSITION_X, ts->finger[id].x);
+ input_report_abs(ts->input, ABS_MT_POSITION_Y, ts->finger[id].y);
+ dbg("%s : id = %d, x = %d, y = %d\n", __func__, ts->finger[id].id, ts->finger[id].x, ts->finger[id].y);
+ }
+ else {
+ ts->finger[id].event = TS_EVENT_UNKNOWN;
+ dbg("%s : release id = %d\n", __func__, ts->finger[id].id);
+ }
+
+ input_mt_sync(ts->input);
+ }
+
+ input_sync(ts->input);
+}
+
+//----------------------------------------------
+static void touch_report_protocol_b(struct touch *ts)
+{
+ int id;
+#if defined(DEBUG_TOUCH)
+ char *event_str[] = {"unknown", "press", "move", "release"};
+#endif
+
+ for(id = 0; id < ts->pdata->max_fingers; id++) {
+ if((ts->finger[id].event == TS_EVENT_UNKNOWN) || (ts->finger[id].status == false))
+ continue;
+
+ input_mt_slot(ts->input, id);
+ ts->finger[id].status = false;
+
+ if(ts->finger[id].event != TS_EVENT_RELEASE) {
+ input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, true);
+
+ input_report_abs(ts->input, ABS_MT_TRACKING_ID, ts->finger[id].id);
+ input_report_abs(ts->input, ABS_MT_POSITION_X, ts->finger[id].x);
+ input_report_abs(ts->input, ABS_MT_POSITION_Y, ts->finger[id].y);
+
+ if(ts->pdata->area_max) input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR, ts->finger[id].area ? ts->finger[id].area : 10);
+ if(ts->pdata->press_max) input_report_abs(ts->input, ABS_MT_PRESSURE, ts->finger[id].pressure);
+
+#if defined(DEBUG_TOUCH)
+ dbg("%s : event = %s, slot = %d, id = %d, x = %d, y = %d\n", __func__, event_str[ts->finger[id].event], id, ts->finger[id].id, ts->finger[id].x, ts->finger[id].y);
+#endif
+ }
+ else {
+#if defined(DEBUG_TOUCH)
+ dbg("%s : event = %s, slot = %d, id = %d\n", __func__, event_str[ts->finger[id].event], id, ts->finger[id].id);
+#endif
+ ts->finger[id].event = TS_EVENT_UNKNOWN;
+ input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, false);
+ }
+ }
+ input_sync(ts->input);
+}
+
+//----------------------------------------------
+static void touch_event_clear(struct touch *ts)
+{
+ unsigned char id;
+
+ for(id = 0; id < ts->pdata->max_fingers; id++) {
+ if(ts->finger[id].event == TS_EVENT_MOVE) {
+ ts->finger[id].status = true;
+ ts->finger[id].event = TS_EVENT_RELEASE;
+ }
+ }
+ ts->pdata->report(ts);
+ if(ts->pdata->keycode)
+ ts->pdata->key_report(ts, 0x00);
+}
+
+//----------------------------------------------
+static int touch_input_open(struct input_dev *input)
+{
+ struct touch *ts = input_get_drvdata(input);
+
+ ts->pdata->enable(ts);
+
+ dbg("%s\n", __func__);
+
+ return 0;
+}
+
+//----------------------------------------------
+static void touch_input_close(struct input_dev *input)
+{
+ struct touch *ts = input_get_drvdata(input);
+
+ ts->pdata->disable(ts);
+
+ dbg("%s\n", __func__);
+}
+
+//----------------------------------------------
+static int touch_check_functionality(struct touch_pdata *pdata)
+{
+ if(!pdata) {
+ errlog("Error : Platform data is NULL pointer!\n"); return -1;
+ }
+
+ pdata->i2c_read = sn310m_i2c_read;
+ pdata->i2c_write = sn310m_i2c_write;
+
+ pdata->i2c_boot_read = sn310m_i2c_read;
+ pdata->i2c_boot_write = sn310m_i2c_write;
+
+ pdata->enable = sn310m_enable;
+ pdata->disable = sn310m_disable;
+ pdata->probe = sn310m_probe;
+
+ if(!pdata->report) {
+ if(pdata->id_max) pdata->report = touch_report_protocol_b;
+ else pdata->report = touch_report_protocol_a;
+ }
+ if(!pdata->key_report) pdata->key_report = touch_key_report;
+
+ pdata->touch_work = sn310m_work;
+
+ if(!pdata->irq_func) pdata->irq_func = touch_irq;
+
+ if(!pdata->event_clear) pdata->event_clear = touch_event_clear;
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ if(!pdata->resume) pdata->resume = touch_resume;
+ if(!pdata->suspend) pdata->suspend = touch_suspend;
+#endif
+
+ //pdata->irq_gpio = 7;
+
+ return 0;
+}
+
+//----------------------------------------------
+void touch_hw_reset(struct touch *ts)
+{
+ if(ts->pdata->reset_gpio) {
+ if(gpio_request(ts->pdata->reset_gpio, "touch reset")) {
+ errlog("--------------------------------------------------------\n");
+ errlog("%s : request port error!\n", "touch reset");
+ errlog("--------------------------------------------------------\n");
+ }
+ else {
+ if(ts->pdata->power) {
+ /* power sequence: reset low -> power on -> reset high */
+ gpio_direction_output(ts->pdata->reset_gpio, 0);
+ gpio_set_value(ts->pdata->reset_gpio, 0);
+ mdelay(15);
+ ts->pdata->power(1);
+ mdelay(50);
+ gpio_set_value(ts->pdata->reset_gpio, 1);
+ mdelay(15);
+ }
+ else {
+ /* if there is no power control for touch, then just do reset (high -> low -> high) */
+ gpio_direction_output(ts->pdata->reset_gpio, 1);
+ gpio_set_value(ts->pdata->reset_gpio, 1);
+ mdelay(15);
+ gpio_set_value(ts->pdata->reset_gpio, 0);
+ mdelay(20);
+ gpio_set_value(ts->pdata->reset_gpio, 1);
+ mdelay(15);
+ }
+ }
+ }
+}
+
+//----------------------------------------------
+int touch_info_display(struct touch *ts)
+{
+ errlog("--------------------------------------------------------\n");
+ errlog(" TOUCH SCREEN INFORMATION\n");
+ errlog("--------------------------------------------------------\n");
+ if(ts->pdata->irq_gpio) {
+ errlog("TOUCH INPUT Name = %s\n", ts->pdata->name);
+
+ switch(ts->pdata->irq_mode) {
+ default :
+ case IRQ_MODE_THREAD: errlog("TOUCH IRQ Mode = %s\n", "IRQ_MODE_THREAD"); break;
+ case IRQ_MODE_NORMAL: errlog("TOUCH IRQ Mode = %s\n", "IRQ_MODE_NORMAL"); break;
+ case IRQ_MODE_POLLING: errlog("TOUCH IRQ Mode = %s\n", "IRQ_MODE_POLLING"); break;
+ }
+ errlog("TOUCH F/W Version = %d.%02d\n", ts->fw_version / 100, ts->fw_version % 100);
+ errlog("TOUCH FINGRES MAX = %d\n", ts->pdata->max_fingers);
+ errlog("TOUCH ABS X MAX = %d, TOUCH ABS X MIN = %d\n", ts->pdata->abs_max_x, ts->pdata->abs_min_x);
+ errlog("TOUCH ABS Y MAX = %d, TOUCH ABS Y MIN = %d\n", ts->pdata->abs_max_y, ts->pdata->abs_min_y);
+
+ if(ts->pdata->area_max)
+ errlog("TOUCH MAJOR MAX = %d, TOUCH MAJOR MIN = %d\n", ts->pdata->area_max, ts->pdata->area_min);
+
+ if(ts->pdata->press_max)
+ errlog("TOUCH PRESS MAX = %d, TOUCH PRESS MIN = %d\n", ts->pdata->press_max, ts->pdata->press_min);
+
+ if(ts->pdata->id_max) {
+ errlog("TOUCH ID MAX = %d, TOUCH ID MIN = %d\n", ts->pdata->id_max, ts->pdata->id_min);
+ errlog("Mulit-Touch Protocol-B Used.\n");
+ }
+ else
+ errlog("Mulit-Touch Protocol-A Used.\n");
+
+ if(ts->pdata->gpio_init)
+ errlog("GPIO early-init function implemented\n");
+
+ if(ts->pdata->reset_gpio)
+ errlog("H/W Reset function implemented\n");
+
+ #ifdef CONFIG_HAS_EARLYSUSPEND
+ errlog("Early-suspend function implemented\n");
+ #endif
+ if(ts->pdata->fw_control)
+ errlog("Firmware update function(sysfs control) implemented\n");
+
+ /* flashing sample is not implemented yet */
+ if(ts->pdata->flash_firmware)
+ errlog("Firmware update function(udev control) implemented\n");
+
+ if(ts->pdata->calibration)
+ errlog("Calibration function implemented\n");
+ }
+ else {
+ errlog("TOUCH INPUT Name = %s\n", ts->pdata->name);
+ errlog("Dummy Touchscreen driver!\n");
+ }
+ errlog("--------------------------------------------------------\n");
+ return 0;
+}
+
+//----------------------------------------------
+int touch_probe(struct i2c_client *client, const struct i2c_device_id *client_id)
+{
+ return -1;
+}
+
+//----------------------------------------------
+//
+// Power Management function
+//
+//----------------------------------------------
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void touch_suspend(struct early_suspend *h)
+{
+ struct touch *ts = container_of(h, struct touch, power);
+
+ dbg("%s++\n", __func__);
+
+ /* TSC enters deep sleep mode */
+ dbg("[%s] touch reset goes low!\n", __func__);
+ gpio_direction_output(ts->pdata->reset_gpio, 0);
+ gpio_set_value(ts->pdata->reset_gpio, 0);
+
+ ts->pdata->disable(ts);
+}
+
+//----------------------------------------------
+static void touch_resume(struct early_suspend *h)
+{
+ struct touch *ts = container_of(h, struct touch, power);
+
+ dbg("%s++\n", __func__);
+
+ /* TSC enters active mode */
+ dbg("[%s] touch reset goes high!\n", __func__);
+ gpio_direction_output(ts->pdata->reset_gpio, 1);
+ gpio_set_value(ts->pdata->reset_gpio, 1);
+
+ ts->pdata->enable(ts);
+}
+#endif
+
+//----------------------------------------------
+int touch_remove(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct touch *ts = dev_get_drvdata(dev);
+
+ dbg("touch_remove++");
+
+ if(ts->irq) free_irq(ts->irq, ts);
+
+ if(ts->pdata->reset_gpio) gpio_free(ts->pdata->reset_gpio);
+
+ if(ts->pdata->irq_gpio) gpio_free(ts->pdata->irq_gpio);
+
+ input_unregister_device(ts->input);
+
+ dev_set_drvdata(dev, NULL);
+
+#if defined(SN310M_NATIVE_INTERFACE)
+ P_SN310M_Dist_Remove();
+#endif
+
+ kfree(ts->finger); ts->finger = NULL;
+ kfree(ts); ts = NULL;
+
+ return 0;
+}
+
+#if defined(SN310M_NATIVE_INTERFACE)
+#define SN310M_DIST_MINOR 250
+
+typedef struct {
+ unsigned int addr;
+ short *buf;
+ unsigned int size;
+} packet_t;
+
+static const struct file_operations SN310M_Dist_Fops =
+{
+ .owner = THIS_MODULE,
+ .open = P_SN310M_Dist_Open,
+ .unlocked_ioctl = P_SN310M_Dist_Ioctl,
+};
+
+
+static struct miscdevice SN310M_Dist_MiscDev =
+{
+ .minor = SN310M_DIST_MINOR,
+ .name = "sn310m_dist",
+ .fops = &SN310M_Dist_Fops,
+ .mode = 0x666,
+};
+
+
+static long P_SN310M_Dist_Ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ packet_t* packet = (packet_t*)arg;
+ int i;
+
+ mutex_lock(&g_ts->mutex);
+ switch(cmd) {
+ case 0: // write data
+ if(packet->size) {
+ unsigned short addr = (packet->addr >> 8) | (packet->addr & 0x00ff) << 8;
+ g_ts->pdata->i2c_write(g_ts->client, (unsigned char *)&addr, sizeof(addr), (unsigned char *)packet->buf, packet->size*2);
+ dbg("Request I2C Write\n");
+ }
+ break;
+
+ case 1: // read data
+ if(packet->size) {
+ unsigned short addr = (packet->addr >> 8) | (packet->addr & 0x00ff) << 8;
+ short buffer[500] = {0, };
+
+ g_ts->pdata->i2c_read(g_ts->client, (unsigned char *)&addr, sizeof(addr), (unsigned char *)buffer, packet->size*2);
+ for(i = 0; (i < packet->size) && (i < 500); i++) {
+ packet->buf[i] = buffer[i];
+ }
+ dbg("Request I2C Read\n");
+ }
+ break;
+
+ default:
+ mutex_unlock(&g_ts->mutex);
+ return -ENOIOCTLCMD;
+ }
+
+ mutex_unlock(&g_ts->mutex);
+ return 0;
+}
+
+static int P_SN310M_Dist_Open(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static int P_SN310M_Dist_Probe(struct touch* ts)
+{
+ int result = 0;
+
+ g_ts = ts;
+ result = misc_register(&SN310M_Dist_MiscDev);
+ if(result == 0) {
+ dbg("succeeded to register sn310m_misc_device \n");
+ }
+ else {
+ errlog("failed to register sn310m_misc_device \n");
+ }
+
+ return result;
+}
+
+static void P_SN310M_Dist_Remove(void)
+{
+ misc_deregister(&SN310M_Dist_MiscDev);
+ g_ts = NULL;
+}
+#endif
+static const struct i2c_device_id sample_ts_id[] = {
+ { I2C_TOUCH_NAME, 0 },
+ {},
+};
+
+
+
+#define TS_DRIVER_NAME "wmt-touch"
+
+static void wmt_ts_platform_release(struct device *device)
+{
+ dbg("wmt_ts_platform_release\n");
+ return;
+}
+
+static struct platform_device wmt_ts_plt_device = {
+ .name = TS_DRIVER_NAME,
+ .id = 0,
+ .dev = {
+ .release = wmt_ts_platform_release,
+ },
+};
+
+static int sn310m_keycode[] = {
+ KEY_HOME, KEY_MENU, KEY_BACK, KEY_SEARCH
+};
+
+struct touch_pdata sn310m_touch_pdata = {
+
+ .name = "sn310m", // input drv name
+ .irq_gpio = 7,//SAMPLE_GPIO_0, // irq gpio define
+ .reset_gpio = 4,//SAMPLE_GPIO_1, // reset gpio define
+ .reset_level = 0, // reset level setting (1 = High reset, 0 = Low reset)
+
+ .irq_mode = IRQ_MODE_NORMAL, // IRQ_MODE_THREAD, IRQ_MODE_NORMAL, IRQ_MODE_POLLING
+ .irq_flags = IRQF_SHARED ,//IRQF_TRIGGER_FALLING | IRQF_DISABLED,
+
+ .abs_max_x = 600,
+ .abs_max_y = 1024,
+
+ .area_max = 10,
+ .press_max = 255,
+
+ .id_max = 10 + 1,
+ .id_min = 0,
+
+ .vendor = 0x16B4,
+ .product = 0x0310,
+ .version = 0x0001,
+
+ .max_fingers = 5,
+
+ .keycnt = 4,
+ .keycode = sn310m_keycode,
+ .lcd_exchg = 0,
+
+ //--------------------------------------------
+ // Control function
+ //--------------------------------------------
+ .touch_work = sn310m_work,
+ .enable = sn310m_enable,
+ .disable = sn310m_disable,
+ .early_probe = sn310m_early_probe,
+ .probe = sn310m_probe,
+
+ //--------------------------------------------
+ // I2C control function
+ //--------------------------------------------
+ .i2c_write = sn310m_i2c_write,
+ .i2c_read = sn310m_i2c_read,
+
+ //--------------------------------------------
+ // Calibration function
+ //--------------------------------------------
+ .calibration = sn310m_calibration,
+
+ //--------------------------------------------
+ // Firmware update control function
+ //--------------------------------------------
+ .fw_filename = "sn310m_fw.bin",
+ .fw_filesize = (10 * 1024), // 10K bytes
+ .input_open = sn310m_input_open,
+ .flash_firmware = sn310m_flash_firmware,
+};
+
+
+int temp;
+static int wmt_ts_probe(struct platform_device *pdev)
+{
+ int rc = -1;
+ struct i2c_client *client = l_client;
+ struct device *dev = &client->dev;
+ struct touch *ts;
+
+
+ dbg("wmt_ts_probe\n");
+
+ if(!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+ dev_err(&client->dev, "i2c byte data not supported\n");
+ return -EIO;
+ }
+
+
+ client->dev.platform_data = &sn310m_touch_pdata;
+
+ if(touch_check_functionality(client->dev.platform_data) < 0) {
+ dev_err(&client->dev, "Platform data is not available!\n");
+ return -EINVAL;
+ }
+
+ if(!(ts = kzalloc(sizeof(struct touch), GFP_KERNEL))) {
+ errlog("touch struct malloc error!\n");
+ return -ENOMEM;
+ }
+ ts->client = client;
+ ts->pdata = client->dev.platform_data;
+
+
+ /* by limst, setting gpio for IRQ */
+ if(ts->pdata->irq_gpio) {
+ int ret;
+
+ ts->irq = IRQ_GPIO;//MSM_GPIO_TO_INT(ts->pdata->irq_gpio);
+ dbg("IRQ_GPIO(%d) IRQ(%d) REG\n", ts->pdata->irq_gpio, ts->irq);
+
+ ret = gpio_request(ts->pdata->irq_gpio, "touch_int");
+ if(ret < 0)
+ errlog("FAIL: touch_int gpio_request\n");
+ else
+ dbg("OK: touch_int gpio_request value(%d)\n", gpio_get_value(ts->pdata->irq_gpio));
+
+ wmt_gpio_setpull(ts->pdata->irq_gpio,WMT_GPIO_PULL_UP);
+ gpio_direction_input(ts->pdata->irq_gpio);
+ wmt_gpio_set_irq_type(ts->pdata->irq_gpio, IRQ_TYPE_EDGE_FALLING);
+ }
+
+ i2c_set_clientdata(client, ts);
+
+ if(ts->pdata->max_fingers) {
+ if(!(ts->finger = kzalloc(sizeof(finger_t) * ts->pdata->max_fingers, GFP_KERNEL))) {
+ kfree(ts);
+ errlog("touch data struct malloc error!\n");
+ return -ENOMEM;
+ }
+ }
+
+ if(ts->pdata->gpio_init) ts->pdata->gpio_init();
+
+ if(ts->pdata->early_probe) {
+ if((rc = ts->pdata->early_probe(ts)) < 0)
+ goto err_free_mem;
+ }
+
+
+ dev_set_drvdata(dev, ts);
+
+ if(!(ts->input = input_allocate_device()))
+ goto err_free_mem;
+
+ snprintf(ts->phys, sizeof(ts->phys), "%s/input0", ts->pdata->name);
+
+ if(!ts->pdata->input_open) ts->input->open = touch_input_open;
+ else ts->input->open = ts->pdata->input_open;
+ if(!ts->pdata->input_close) ts->input->close = touch_input_close;
+ else ts->input->close = ts->pdata->input_close;
+
+ /*
+ * by limst, for the test purpose,
+ * input device's name is forcedly set to the name of android idc file
+ */
+ ts->input->name = "qwerty";//idc's filename //"touch_dev";
+ //ts->input->name = ts->pdata->name;
+ ts->input->phys = ts->phys;
+ ts->input->dev.parent = dev;
+ ts->input->id.bustype = BUS_I2C;
+
+ ts->input->id.vendor = ts->pdata->vendor;
+ ts->input->id.product = ts->pdata->product;
+ ts->input->id.version = ts->pdata->version;
+
+ set_bit(EV_SYN, ts->input->evbit);
+ set_bit(EV_ABS, ts->input->evbit);
+
+ /* Register Touch Key Event */
+ if(ts->pdata->keycode) {
+ int key;
+
+ set_bit(EV_KEY, ts->input->evbit);
+
+ for(key = 0; key < ts->pdata->keycnt; key++) {
+ if(ts->pdata->keycode[key] <= 0) continue;
+ set_bit(ts->pdata->keycode[key] & KEY_MAX, ts->input->keybit);
+ }
+ }
+
+ input_set_drvdata(ts->input, ts);
+
+ if (sn310m_touch_pdata.lcd_exchg) {
+ input_set_abs_params(ts->input, ABS_MT_POSITION_X, ts->pdata->abs_min_y, ts->pdata->abs_max_y, 0, 0);
+ input_set_abs_params(ts->input, ABS_MT_POSITION_Y, ts->pdata->abs_min_x, ts->pdata->abs_max_x, 0, 0);
+ } else {
+ input_set_abs_params(ts->input, ABS_MT_POSITION_X, ts->pdata->abs_min_x, ts->pdata->abs_max_x, 0, 0);
+ input_set_abs_params(ts->input, ABS_MT_POSITION_Y, ts->pdata->abs_min_y, ts->pdata->abs_max_y, 0, 0);
+ }
+
+ if(ts->pdata->area_max)
+ input_set_abs_params(ts->input, ABS_MT_TOUCH_MAJOR, ts->pdata->area_min, ts->pdata->area_max, 0, 0);
+
+ if(ts->pdata->press_max)
+ input_set_abs_params(ts->input, ABS_MT_PRESSURE, ts->pdata->press_min, ts->pdata->press_max, 0, 0);
+
+ if(ts->pdata->id_max) {
+ input_set_abs_params(ts->input, ABS_MT_TRACKING_ID, ts->pdata->id_min, ts->pdata->id_max, 0, 0);
+ input_mt_init_slots(ts->input, ts->pdata->max_fingers);
+ }
+
+
+ mutex_init(&ts->mutex);
+ if(ts->irq) {
+ switch(ts->pdata->irq_mode) {
+ default :
+ case IRQ_MODE_THREAD:
+ INIT_WORK(&ts->work, touch_work_q);
+ if((ts->work_queue = create_singlethread_workqueue("work_queue")) == NULL)
+ goto err_free_input_mem;
+
+ if((rc = request_threaded_irq(ts->irq, NULL, ts->pdata->irq_func,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT, ts->pdata->name, ts))) {
+ dev_err(dev, "threaded irq %d request fail!\n", ts->irq);
+ goto err_free_input_mem;
+ }
+ break;
+ case IRQ_MODE_NORMAL:
+ INIT_WORK(&ts->work, touch_work_q);
+ if((ts->work_queue = create_singlethread_workqueue("work_queue")) == NULL)
+ goto err_free_input_mem;
+
+ if((rc = request_irq(ts->irq, ts->pdata->irq_func, ts->pdata->irq_flags, ts->pdata->name, ts))) {
+ errlog("irq %d request fail!\n", ts->irq);
+ goto err_free_input_mem;
+ }
+ dbg("irq %d request ok!\n", ts->irq);
+ break;
+ case IRQ_MODE_POLLING:
+ errlog("Error IRQ_MODE POLLING!! but defined irq_gpio\n");
+ break;
+ } /* end of switch */
+ }
+ ts->disabled = true;
+
+ if((rc = input_register_device(ts->input))) {
+ dev_err(dev, "(%s) input register fail!\n", ts->input->name);
+ goto err_free_input_mem;
+ }
+
+ /* by limst, added to turn on the power and reset of Touch IC */
+ touch_hw_reset(ts);
+
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+ if(ts->pdata->suspend) ts->power.suspend = ts->pdata->suspend;
+ if(ts->pdata->resume) ts->power.resume = ts->pdata->resume;
+
+ ts->power.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 1;
+
+ register_early_suspend(&ts->power);
+#endif
+
+ if(ts->pdata->probe) {
+ ts->pdata->probe(ts);
+ }
+
+ touch_info_display(ts);
+
+#if defined(SN310M_NATIVE_INTERFACE)
+ if(P_SN310M_Dist_Probe(ts) < 0) {
+ errlog("P_SN310M_Dist_Probe(), fail\n");
+ }
+#endif
+
+ return 0;
+
+ free_irq(ts->irq, ts);
+ input_unregister_device(ts->input);
+ err_free_input_mem:
+ input_free_device(ts->input);
+ ts->input = NULL;
+ err_free_mem:
+ kfree(ts->finger);
+ ts->finger = NULL;
+ kfree(ts);
+ ts = NULL;
+ return rc;
+}
+
+static int wmt_ts_remove(struct platform_device *pdev)
+{
+ struct i2c_client *client = l_client;
+ struct device *dev = &client->dev;
+ struct touch *ts = dev_get_drvdata(dev);
+
+ dbg("wmt_ts_remove\n");
+
+ if(ts->irq) free_irq(ts->irq, ts);
+
+ if(ts->pdata->reset_gpio) gpio_free(ts->pdata->reset_gpio);
+
+ if(ts->pdata->irq_gpio) gpio_free(ts->pdata->irq_gpio);
+
+ input_unregister_device(ts->input);
+
+ dev_set_drvdata(dev, NULL);
+
+ #if defined(SN310M_NATIVE_INTERFACE)
+ P_SN310M_Dist_Remove();
+ #endif
+
+ kfree(ts->finger); ts->finger = NULL;
+ kfree(ts); ts = NULL;
+
+ return 0;
+}
+
+static int wmt_ts_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct i2c_client *client = l_client;
+ struct device *dev = &client->dev;
+ struct touch *ts = dev_get_drvdata(dev);
+
+ dbg("%s++\n", __func__);
+
+ /* TSC enters deep sleep mode */
+ dbg("[%s] touch reset goes low!\n", __func__);
+ gpio_direction_output(ts->pdata->reset_gpio, 0);
+ gpio_set_value(ts->pdata->reset_gpio, 0);
+
+
+ ts->pdata->disable(ts);
+
+ return 0;
+}
+static int wmt_ts_resume(struct platform_device *pdev)
+{
+ struct i2c_client *client = l_client;
+ struct device *dev = &client->dev;
+ struct touch *ts = dev_get_drvdata(dev);
+
+ dbg("%s++\n", __func__);
+
+ /* TSC enters active mode */
+ dbg("[%s] touch reset goes high!\n", __func__);
+ gpio_direction_output(ts->pdata->reset_gpio, 1);
+ gpio_set_value(ts->pdata->reset_gpio, 1);
+
+ ts->pdata->enable(ts);
+ //touch_hw_reset(ts);
+
+ return 0;
+}
+
+
+static struct platform_driver wmt_ts_plt_driver = {
+ .driver = {
+ .name = TS_DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = wmt_ts_probe,
+ .remove = wmt_ts_remove,
+ .suspend = wmt_ts_suspend,
+ .resume = wmt_ts_resume,
+};
+
+
+
+struct i2c_board_info ts_i2c_board_info = {
+ .type = WMT_TS_I2C_NAME,
+ .flags = 0x00,
+ .platform_data = NULL,
+ .archdata = NULL,
+ .irq = -1,
+};
+
+static int ts_i2c_register_device (void)
+{
+ struct i2c_board_info *ts_i2c_bi;
+ struct i2c_adapter *adapter = NULL;
+
+ ts_i2c_board_info.addr =(unsigned short) 0x3c;
+ ts_i2c_bi = &ts_i2c_board_info;
+ adapter = i2c_get_adapter(1);/*in bus 1*/
+
+ if (NULL == adapter) {
+ errlog("can not get i2c adapter, client address error\n");
+ return -1;
+ }
+ l_client = i2c_new_device(adapter, ts_i2c_bi);
+ if (l_client == NULL) {
+ errlog("allocate i2c client failed\n");
+ return -1;
+ }
+ i2c_put_adapter(adapter);
+ return 0;
+}
+
+static void ts_i2c_unregister_device(void)
+{
+ if (l_client != NULL)
+ {
+ i2c_unregister_device(l_client);
+ l_client = NULL;
+ }
+}
+
+static struct tp_info l_tpinfo;
+static int wmt_check_touch_env(void)
+{
+ int ret = 0;
+ int len = 127;
+ char retval[200] = {0};
+ char *p=NULL;
+ char *s=NULL;
+ int Enable=0;
+
+ // Get u-boot parameter
+ ret = wmt_getsyspara("wmt.io.touch", retval, &len);
+ if(ret){
+ errlog("Read wmt.io.touch Failed.\n");
+ return -EIO;
+ }
+ memset(&l_tpinfo,0,sizeof(l_tpinfo));
+
+ p = retval;
+ sscanf(p,"%d:", &Enable);
+ p = strchr(p,':');
+ p++;
+ s = strchr(p,':');
+ strncpy(l_tpinfo.name,p, (s-p));
+ p = s+1;
+ //dbg("ts_name=%s\n", l_tpinfo.name);
+
+ ret = sscanf(p,"%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
+ &l_tpinfo.irq_gpio,&l_tpinfo.panelres_x,&l_tpinfo.panelres_y,&l_tpinfo.rst_gpio,
+ &(l_tpinfo.xaxis),&(l_tpinfo.xdir),&(l_tpinfo.ydir),
+ &(l_tpinfo.max_finger_num),&l_tpinfo.i2caddr,&l_tpinfo.low_Impendence_mode,&l_tpinfo.download_option);
+
+ if (ret < 8){
+ errlog("Wrong format ts u-boot param(%d)!\nwmt.io.touch=%s\n",ret,retval);
+ return -ENODEV;
+ }
+
+ //check touch enable
+ if(Enable == 0){
+ errlog("Touch Screen Is Disabled.\n");
+ return -ENODEV;
+ }
+ if (strstr(l_tpinfo.name, sn310m_touch_pdata.name) == NULL){
+ errlog("Can't find %s in the wmt.io.touch\n", sn310m_touch_pdata.name);
+ return -ENODEV;
+ }
+
+ errlog("p.x = %d, p.y = %d, gpio=%d, resetgpio=%d,xaxis=%d,xdir=%d,ydri=%d,maxfingernum=%d,,i2c_addr=0x%X,low_Impendence_mode=%d,s_download_option=%d\n",
+ l_tpinfo.panelres_x, l_tpinfo.panelres_y, l_tpinfo.irq_gpio, l_tpinfo.rst_gpio,
+ l_tpinfo.xaxis,l_tpinfo.xdir,l_tpinfo.ydir,
+ l_tpinfo.max_finger_num,l_tpinfo.i2caddr,l_tpinfo.low_Impendence_mode,l_tpinfo.download_option);
+
+ sn310m_touch_pdata.irq_gpio = l_tpinfo.irq_gpio;
+ sn310m_touch_pdata.reset_gpio = l_tpinfo.rst_gpio;
+ sn310m_touch_pdata.abs_max_x = l_tpinfo.panelres_x;
+ sn310m_touch_pdata.abs_max_y = l_tpinfo.panelres_y;
+
+ memset(retval,0,sizeof(retval));
+ ret = wmt_getsyspara("wmt.display.fb0", retval, &len);
+ if (!ret) {
+ int tmp[6];
+ p = retval;
+ sscanf(p, "%d:[%d:%d:%d:%d:%d", &tmp[0], &tmp[1], &tmp[2], &tmp[3], &tmp[4], &tmp[5]);
+ if (tmp[4] > tmp[5])
+ sn310m_touch_pdata.lcd_exchg = 1;
+ }
+
+ return 0;
+}
+
+
+static int __init sample_touch_init(void)
+{
+ int ret = 0;
+
+ if(wmt_check_touch_env())
+ return -ENODEV;
+
+
+ if (ts_i2c_register_device()<0){
+ errlog("Error to run ts_i2c_register_device()!\n");
+ return -1;
+ }
+
+ ret = platform_device_register(&wmt_ts_plt_device);
+ if(ret){
+ errlog("wmt ts plat device register failed!\n");
+ return ret;
+ }
+ ret = platform_driver_register(&wmt_ts_plt_driver);
+ if(ret){
+ errlog("can not register platform_driver_register\n");
+ platform_device_unregister(&wmt_ts_plt_device);
+ return ret;
+ }
+ return 0;
+}
+
+static void sample_touch_exit(void)
+{
+ platform_driver_unregister(&wmt_ts_plt_driver);
+ platform_device_unregister(&wmt_ts_plt_device);
+ ts_i2c_unregister_device();
+
+ return;
+}
+
+
+module_init(sample_touch_init);
+module_exit(sample_touch_exit);
+
+#ifndef MODULE
+__initcall(sample_touch_init);
+#endif
+
+
+
+MODULE_AUTHOR("SEMISENS Co., Ltd.");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Touchscreen Driver for SN310M");
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/semisens/touch.h b/ANDROID_3.4.5/drivers/input/touchscreen/semisens/touch.h
new file mode 100755
index 00000000..750112ea
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/semisens/touch.h
@@ -0,0 +1,54 @@
+/****************************************************************
+ *
+ * touch.c : I2C Touchscreen driver
+ *
+ * Copyright (c) 2013 SEMISENS Co.,Ltd
+ * http://www.semisens.com
+ *
+ ****************************************************************/
+#ifndef _TOUCH_H_
+#define _TOUCH_H_
+
+//----------------------------------------------
+// extern function define
+//----------------------------------------------
+extern void touch_hw_reset(struct touch *ts);
+extern int touch_info_display(struct touch *ts);
+#if 0 /* depends on kernel version */
+extern int touch_probe(struct i2c_client *client);
+extern int touch_remove(struct device *dev);
+#else
+extern int touch_probe(struct i2c_client *client, const struct i2c_device_id *client_id);
+extern int touch_remove(struct i2c_client *client);
+#endif
+
+struct tp_info
+{
+ char name[64];
+ unsigned int xaxis; //0: x, 1: x swap with y
+ unsigned int xdir; // 1: positive,-1: revert
+ unsigned int ydir; // 1: positive,-1: revert
+ unsigned int max_finger_num;
+ unsigned int download_option; // 0: disable 1:force download 2:force cancel download
+ unsigned int low_Impendence_mode; // 0: High Impendence Mode 1: Low Impendence Mode
+ unsigned int irq_gpio;
+ unsigned int rst_gpio;
+ unsigned int panelres_x;
+ unsigned int panelres_y;
+ unsigned int i2caddr;
+ unsigned int lcd_exchg;
+#if 0
+ struct input_dev *inputdev;
+ struct work_struct int_work;
+ struct i2c_client *i2cclient;
+ struct workqueue_struct *wq;
+#if SUPPORT_TS_KEY
+ int key_num;
+#endif
+#endif
+
+};
+
+
+
+#endif /* _TOUCH_H_ */
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/sis_usbhid_ts/Kconfig b/ANDROID_3.4.5/drivers/input/touchscreen/sis_usbhid_ts/Kconfig
new file mode 100755
index 00000000..21574ec3
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/sis_usbhid_ts/Kconfig
@@ -0,0 +1,16 @@
+#
+# SIS USB capacity touch screen driver configuration
+#
+config TOUCHSCREEN_SIS
+ tristate "SIS USB Capacitive Touchscreen Input Driver Support"
+ depends on ARCH_WMT
+ default y
+ help
+ Say Y here if you have an WMT based board with touchscreen
+ attached to it.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called s_wmt_ts_sis
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/sis_usbhid_ts/Makefile b/ANDROID_3.4.5/drivers/input/touchscreen/sis_usbhid_ts/Makefile
new file mode 100755
index 00000000..045ea698
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/sis_usbhid_ts/Makefile
@@ -0,0 +1,32 @@
+KERNELDIR=../../../../
+CROSS = arm_1103_le-
+CC= $(CROSS)gcc
+LD= $(CROSS)ld
+STRIP = $(CROSS)strip
+
+DEBUG = n
+
+# Add your debugging flag (or not) to EXTRA_CFLAGS
+ifeq ($(DEBUG),y)
+# DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+DEBFLAGS = -O0 -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+
+else
+ DEBFLAGS = -O2 -Wall
+endif
+
+EXTRA_CFLAGS += $(DEBFLAGS)
+
+
+MY_MODULE_NAME=s_wmt_ts_sis
+
+obj-m := $(MY_MODULE_NAME).o
+$(MY_MODULE_NAME)-objs := hid-sis.o
+
+default:
+ $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules
+ $(STRIP) --strip-debug $(MY_MODULE_NAME).ko
+ rm -rf *.o *~ core .depend .*.cmd *.mod.c .tmp_versions *.order *.symvers modules.builtin
+
+clean:
+ rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.order *.symvers modules.builtin
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/sis_usbhid_ts/hid-sis.c b/ANDROID_3.4.5/drivers/input/touchscreen/sis_usbhid_ts/hid-sis.c
new file mode 100755
index 00000000..0b9cee3d
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/sis_usbhid_ts/hid-sis.c
@@ -0,0 +1,1104 @@
+/*
+ * HID driver for sis 9237/9257 test touchscreens
+ *
+ * Copyright (c) 2008 Rafi Rubin
+ * Copyright (c) 2009 Stephane Chatty
+ *
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+#include <linux/hid-debug.h>
+//for i2c-bridge
+#include <linux/usb.h>
+#include "../../../hid/usbhid/usbhid.h"
+#include <asm/uaccess.h>
+#include <linux/types.h>
+
+#ifdef CONFIG_HID_SIS_UPDATE_FW
+//for ioctl
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+
+#define INTERNAL_DEVICE_NAME "sis_zeus_hid_touch_device"
+#define BRIDGE_DEVICE_NAME "sis_zeus_hid_bridge_touch_device"
+#define SIS817_DEVICE_NAME "sis_aegis_hid_touch_device"
+#define SISF817_DEVICE_NAME "sis_aegis_hid_bridge_touch_device"
+
+static int sis_char_devs_count = 1; /* device count */
+static int sis_char_major = 0;
+static struct cdev sis_char_cdev;
+static struct class *sis_char_class = NULL;
+//20110111 Tammy system call for tool
+static struct hid_device *hid_dev_backup = NULL; //backup address
+static struct urb *backup_urb = NULL;
+#endif //CONFIG_HID_SIS_UPDATE_FW
+
+///////////////// SIS START /////////////////
+#define USB_VENDOR_ID_SIS_TOUCH 0x1039
+#define USB_VENDOR_ID_SIS2_TOUCH 0x0457
+#define USB_PRODUCT_ID_SIS_TOUCH 0x0810
+#define USB_PRODUCT_ID_SIS2_TOUCH 0x0151
+#define USB_PRODUCT_ID_NEW_SIS2_TOUCH 0x0816
+#define USB_PRODUCT_ID_SIS9200_TOUCH 0x9200
+#define USB_PRODUCT_ID_SIS817_TOUCH 0x0817
+#define USB_PRODUCT_ID_SISF817_TOUCH 0xF817
+
+//waltop id-table
+#define USB_VENUS_ID_WALTOP 0x0503
+#define USB_VENUS_ID_WALTOP2 0x1040
+///////////////// SIS END /////////////////
+//#define CONFIG_HID_SIS_UPDATE_FW
+//#define CONFIG_DEBUG_HID_SIS_INIT
+//#define CONFIG_DEBUG_HID_SIS_SENDPOINT
+
+#define MAX_X 4095
+#define MAX_Y 4095
+//#define MAX_PRESSURE 2047
+#define MAX_SCANTIME 65535
+#define MAX_CONTACTID 31
+
+#define MAX_POINT 10
+#define HID_DG_SCANTIME 0x000d0056 //new usage not defined in hid.h
+#define REPORTID_10 0x10
+#define REPORTID_TYPE1 0x30
+
+#define CTRL 0
+#define DIR_IN 0x1
+
+struct Point {
+ u16 x, y, id, pressure, width, height;
+};
+
+struct sis_data {
+ int id, total, ReportID, scantime;
+ struct Point pt[MAX_POINT];
+};
+
+
+static int pkg_num=0;
+static int idx=-1;
+
+/*
+ * this driver is aimed at two firmware versions in circulation:
+ * - dual pen/fingedrivers/hid/hid-sis.c:83:r single touch
+ * - finger multitouch, pen not working
+ */
+
+static int sis_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ // No special mappings needed for the pen and single touch
+ if (field->physical == HID_GD_POINTER)
+ return -1;
+
+ else if (field->physical && (field->physical != HID_GD_POINTER))
+ return 0;
+
+#ifdef CONFIG_DEBUG_HID_SIS_INIT
+ printk (KERN_INFO "sis_input_mapping : usage->hid = %x\n", usage->hid);
+#endif //CONFIG_DEBUG_HID_SIS_INIT
+
+ switch (usage->hid & HID_USAGE_PAGE) {
+ case HID_UP_GENDESK:
+ switch (usage->hid) {
+ case HID_GD_X:
+ hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_POSITION_X);
+ input_set_abs_params(hi->input, ABS_X,
+ field->logical_minimum, field->logical_maximum, 0, 0);
+ return 1;
+
+ case HID_GD_Y:
+ hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_POSITION_Y);
+ input_set_abs_params(hi->input, ABS_Y,
+ field->logical_minimum, field->logical_maximum, 0, 0);
+ return 1;
+ }
+ return 0;
+
+ case HID_UP_DIGITIZER:
+ switch (usage->hid) {
+ /* we do not want to map these for now */
+ case HID_DG_CONFIDENCE:
+ case HID_DG_INPUTMODE:
+ case HID_DG_DEVICEINDEX:
+ case HID_DG_CONTACTCOUNT:
+ case HID_DG_CONTACTMAX:
+ case HID_DG_INRANGE:
+
+ //new usage for SiS817 Device(for later use)
+ case HID_DG_WIDTH:
+ //hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_TOUCH_MINOR);
+ //input_set_abs_params(hi->input, ABS_MT_TOUCH_MINOR, 0, 255, 0, 0);
+ //return 1;
+ case HID_DG_HEIGHT:
+ //hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_TOUCH_MAJOR);
+ //input_set_abs_params(hi->input, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
+ //return 1;
+ case HID_DG_TIPPRESSURE:
+ //hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_PRESSURE);
+ //input_set_abs_params(hi->input, ABS_MT_PRESSURE, 0, 2047, 0, 0);
+ //return 1;
+ case HID_DG_SCANTIME:
+ return -1;
+
+ case HID_DG_TIPSWITCH:
+ hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_PRESSURE);
+ input_set_abs_params(hi->input, ABS_MT_PRESSURE, 0, 1, 0, 0);
+ return 1;
+
+ case HID_DG_CONTACTID:
+ hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_TRACKING_ID);
+ input_set_abs_params(hi->input, ABS_MT_TRACKING_ID, 0, 127, 0, 0);
+ return 1;
+ }
+ return 0;
+
+ /*case HID_UP_BUTTON:
+ return 0;*/
+
+ case 0xff000000:
+ /* ignore HID features */
+ return -1;
+
+ }
+ /* ignore buttons */
+ return 0;
+}
+
+//sis_input_mapped : unmapped usage that no use in sis_event
+static int sis_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+#ifdef CONFIG_DEBUG_HID_SIS_INIT
+ printk (KERN_INFO "sis_input_mapping : usage->hid = %x\n", usage->hid);
+#endif //CONFIG_DEBUG_HID_SIS_INIT
+
+ if (usage->type == EV_KEY || usage->type == EV_ABS)
+ clear_bit(usage->code, *bit);
+
+ return 0;
+}
+
+static void sis_event_emission(struct sis_data *nd, struct input_dev *input)
+{
+ int i;
+ bool all_touch_up = true;
+ for(i=0; i< nd->total; i++)
+ {
+
+#ifdef CONFIG_DEBUG_HID_SIS_SENDPOINT
+ printk(KERN_INFO "MT_event: finger(s)=%d, id=%d, x=%d, y=%d\n", nd->total, nd->pt[i].id, nd->pt[i].x, nd->pt[i].y);
+ printk(KERN_INFO "MT_event: pressure=%d, width=%d, height=%d, scantime=%d\n", nd->pt[i].pressure, nd->pt[i].width, nd->pt[i].height, nd->scantime);
+#endif //CONFIG_DEBUG_HID_SIS_SENDPOINT
+
+ //checking correction of data
+ if(nd->pt[i].x > MAX_X || nd->pt[i].y > MAX_Y || nd->pt[i].id > MAX_CONTACTID /*|| nd->scantime > MAX_SCANTIME*/)
+ {
+ printk(KERN_INFO "point data error : abort sending point this time");
+ break;
+ }
+
+ if(nd->pt[i].pressure)
+ {
+ //input_report_abs(input, ABS_MT_TOUCH_MAJOR, max(nd->pt[i].height,nd->pt[i].width));
+ //input_report_abs(input, ABS_MT_TOUCH_MINOR, min(nd->pt[i].height,nd->pt[i].width));
+
+ input_report_abs(input, ABS_MT_PRESSURE, nd->pt[i].pressure);
+ input_report_abs(input, ABS_MT_POSITION_X, MAX_Y - nd->pt[i].y);
+ input_report_abs(input, ABS_MT_POSITION_Y, nd->pt[i].x);
+ input_report_abs(input, ABS_MT_TRACKING_ID, nd->pt[i].id);
+ input_mt_sync(input);
+ all_touch_up = false;
+ }
+
+ if(i == (nd->total - 1) && all_touch_up == true)
+ input_mt_sync(input);
+ }
+ //input_sync(input);
+ //input_sync will be send by hid default flow
+}
+
+static void sis_event_clear(struct sis_data *nd, int max)
+{
+ int i;
+ for(i=0; i<max; i++)
+ {
+ nd->pt[i].id = 0;
+ nd->pt[i].x = 0;
+ nd->pt[i].y = 0;
+ nd->pt[i].pressure = 0;
+ nd->pt[i].width = 0;
+ nd->pt[i].height = 0;
+ }
+ nd->scantime = 0;
+ idx = -1;
+ pkg_num = 0;
+}
+
+static int sis_raw_event (struct hid_device *hid, struct hid_report *report,
+ u8 *raw_data, int size)
+{
+ struct sis_data *nd = hid_get_drvdata(hid);
+ nd->ReportID = raw_data[0];
+
+#ifdef CONFIG_DEBUG_HID_SIS_SENDPOINT
+ printk(KERN_INFO "raw_event : ReportID = %d\n", nd->ReportID);
+#endif //CONFIG_DEBUG_HID_SIS_SENDPOINT
+
+ hid_set_drvdata(hid, nd);
+ return 0;
+}
+
+static void sis_event_lastdata(struct hid_device *hid, struct sis_data *nd, struct input_dev *input)
+{
+ int pkg_n=0;
+
+//817 method : original format
+ if ( (hid->product == USB_PRODUCT_ID_SIS817_TOUCH || hid->product == USB_PRODUCT_ID_SISF817_TOUCH) && nd->ReportID == REPORTID_10)
+ {
+#ifdef CONFIG_DEBUG_HID_SIS_SENDPOINT
+ printk (KERN_INFO "sis_event_lastdata : 817 original format\n");
+#endif //CONFIG_DEBUG_HID_SIS_SENDPOINT
+
+ sis_event_emission(nd, input);
+ sis_event_clear(nd, MAX_POINT);
+ }
+ //817 method : Extend Class Format
+ else if ( (hid->product == USB_PRODUCT_ID_SIS817_TOUCH || hid->product == USB_PRODUCT_ID_SISF817_TOUCH) && nd->ReportID != REPORTID_10)
+ {
+#ifdef CONFIG_DEBUG_HID_SIS_SENDPOINT
+ printk (KERN_INFO "sis_event_lastdata : 817 extend format\n");
+#endif //CONFIG_DEBUG_HID_SIS_SENDPOINT
+
+ if(nd->total >= 6)
+ {
+ idx = 4;
+ pkg_num = nd->total;
+ }
+ else if(nd->total >= 1)
+ {
+ sis_event_emission(nd, input);
+ sis_event_clear(nd, MAX_POINT);
+ }
+ else
+ {
+ if(pkg_num >0)
+ {
+ nd->total = pkg_num;
+ sis_event_emission(nd, input);
+ pkg_n = 0;
+ sis_event_clear(nd, MAX_POINT);
+ }
+ else
+ {
+ sis_event_clear(nd, MAX_POINT);
+ }
+ }
+ }
+ else //816 method
+ {
+#ifdef CONFIG_DEBUG_HID_SIS_SENDPOINT
+ printk (KERN_INFO "sis_event_lastdata : 816 format\n");
+#endif //CONFIG_DEBUG_HID_SIS_SENDPOINT
+
+ if(nd->total >= 3)
+ {
+ idx = 1;
+ pkg_num = nd->total;
+ }
+ else if(nd->total >= 1)
+ {
+ sis_event_emission(nd, input);
+ sis_event_clear(nd, MAX_POINT);
+ }
+ else
+ {
+ if(pkg_num >0)
+ {
+ if((pkg_num%2)>0)
+ pkg_n = pkg_num+1;
+ else
+ pkg_n = pkg_num;
+
+ if(pkg_n == (idx + 1) )
+ {
+ nd->total = pkg_num;
+ sis_event_emission(nd, input);
+ pkg_n = 0;
+ sis_event_clear(nd, MAX_POINT);
+ }
+ }
+ else
+ {
+ sis_event_clear(nd, MAX_POINT);
+ }
+ }
+ }
+}
+/*
+ * this function is called upon all reports
+ * so that we can filter contact point information,
+ * decide whether we are in multi or single touch mode
+ * and call input_mt_sync after each point if necessary
+ */
+static int sis_event (struct hid_device *hid, struct hid_field *field,
+ struct hid_usage *usage, __s32 value)
+{
+ struct sis_data *nd = hid_get_drvdata(hid);
+ //printk (KERN_INFO "sis_event");
+
+ if (hid->claimed & HID_CLAIMED_INPUT) {
+ struct input_dev *input = field->hidinput->input;
+#ifdef CONFIG_DEBUG_HID_SIS_SENDPOINT
+ printk (KERN_INFO "sis_event : usage->hid = %x, value = %d\n", usage->hid, value);
+#endif //CONFIG_DEBUG_HID_SIS_SENDPOINT
+ switch (usage->hid) {
+ case HID_DG_INRANGE:
+ break;
+
+ case HID_DG_TIPSWITCH:
+ idx++;
+ nd->pt[idx].pressure = !!value;
+ break;
+
+ case HID_DG_CONTACTID:
+ nd->pt[idx].id = value;
+ break;
+
+ case HID_GD_X:
+ nd->pt[idx].x = value;
+ break;
+
+ case HID_GD_Y:
+ nd->pt[idx].y = value;
+ break;
+
+ //new usage for SiS817 Extend Class Device
+ case HID_DG_SCANTIME:
+ nd->scantime = value;
+ if ( (nd->ReportID & 0xf0) > REPORTID_TYPE1 )
+ sis_event_lastdata(hid, nd, input);
+ break;
+
+ case HID_DG_WIDTH:
+ nd->pt[idx].width = value;
+ break;
+
+ case HID_DG_HEIGHT:
+ nd->pt[idx].height = value;
+ break;
+
+ case HID_DG_TIPPRESSURE:
+ nd->pt[idx].pressure = value;
+ break;
+ //end of new usage for SiS817 Extend Class Device
+
+ case HID_DG_CONTACTCOUNT:
+ nd->total = value;
+ if ( (nd->ReportID & 0xf0) <= REPORTID_TYPE1 )
+ sis_event_lastdata(hid, nd, input);
+ break;
+ default:
+ //fallback to the generic hidinput handling
+ return 0;
+ }
+ }
+
+ /* we have handled the hidinput part, now remains hiddev */
+ if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
+ hid->hiddev_hid_event(hid, field, usage, value);
+
+ return 1;
+}
+
+#ifdef CONFIG_HID_SIS_UPDATE_FW
+int sis_cdev_open(struct inode *inode, struct file *filp) //20120306 Yuger ioctl for tool
+{
+ //20110511, Yuger, kill current urb by method of usbhid_stop
+ struct usbhid_device *usbhid;
+
+#ifdef CONFIG_DEBUG_HID_SIS_UPDATE_FW
+ printk( KERN_INFO "sis_cdev_open\n" );
+#endif //CONFIG_DEBUG_HID_SIS_UPDATE_FW
+
+ if ( !hid_dev_backup )
+ {
+ printk( KERN_INFO "sis_cdev_open : hid_dev_backup is not initialized yet" );
+ return -1;
+ }
+
+ usbhid = hid_dev_backup->driver_data;
+
+ //20110602, Yuger, fix bug: not contact usb cause kernel panic
+ if( !usbhid )
+ {
+ printk( KERN_INFO "sis_cdev_open : usbhid is not initialized yet" );
+ return -1;
+ }
+ else if ( !usbhid->urbin )
+ {
+ printk( KERN_INFO "sis_cdev_open : usbhid->urbin is not initialized yet" );
+ return -1;
+ }
+ else if (hid_dev_backup->vendor == USB_VENDOR_ID_SIS2_TOUCH)
+ {
+ usb_fill_int_urb(backup_urb, usbhid->urbin->dev, usbhid->urbin->pipe,
+ usbhid->urbin->transfer_buffer, usbhid->urbin->transfer_buffer_length,
+ usbhid->urbin->complete, usbhid->urbin->context, usbhid->urbin->interval);
+
+ clear_bit( HID_STARTED, &usbhid->iofl );
+ set_bit( HID_DISCONNECTED, &usbhid->iofl );
+
+ usb_kill_urb( usbhid->urbin );
+ usb_free_urb( usbhid->urbin );
+ usbhid->urbin = NULL;
+ return 0;
+ }
+ else
+ {
+ printk (KERN_INFO "This is not a SiS device");
+ return -801;
+ }
+}
+
+int sis_cdev_release(struct inode *inode, struct file *filp)
+{
+ //20110505, Yuger, rebuild the urb which is at the same urb address, then re-submit it
+ int ret;
+ struct usbhid_device *usbhid;
+ unsigned long flags;
+
+#ifdef CONFIG_DEBUG_HID_SIS_UPDATE_FW
+ printk( KERN_INFO "sis_cdev_release" );
+#endif //CONFIG_DEBUG_HID_SIS_UPDATE_FW
+
+ if ( !hid_dev_backup )
+ {
+ printk( KERN_INFO "sis_cdev_release : hid_dev_backup is not initialized yet" );
+ return -1;
+ }
+
+ usbhid = hid_dev_backup->driver_data;
+
+ printk( KERN_INFO "sys_sis_HID_start" );
+
+ if( !usbhid )
+ {
+ printk( KERN_INFO "sis_cdev_release : usbhid is not initialized yet" );
+ return -1;
+ }
+
+ if( !backup_urb )
+ {
+ printk( KERN_INFO "sis_cdev_release : urb_backup is not initialized yet" );
+ return -1;
+ }
+
+ clear_bit( HID_DISCONNECTED, &usbhid->iofl );
+ usbhid->urbin = usb_alloc_urb( 0, GFP_KERNEL );
+
+ if( !backup_urb->interval )
+ {
+ printk( KERN_INFO "sis_cdev_release : urb_backup->interval does not exist" );
+ return -1;
+ }
+
+ usb_fill_int_urb(usbhid->urbin, backup_urb->dev, backup_urb->pipe,
+ backup_urb->transfer_buffer, backup_urb->transfer_buffer_length,
+ backup_urb->complete, backup_urb->context, backup_urb->interval);
+ usbhid->urbin->transfer_dma = usbhid->inbuf_dma;
+ usbhid->urbin->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+ set_bit( HID_STARTED, &usbhid->iofl );
+
+ //method at hid_start_in
+ spin_lock_irqsave( &usbhid->lock, flags );
+ ret = usb_submit_urb( usbhid->urbin, GFP_ATOMIC );
+ spin_unlock_irqrestore( &usbhid->lock, flags );
+ //yy
+
+#ifdef CONFIG_DEBUG_HID_SIS_UPDATE_FW
+ printk( KERN_INFO "sis_cdev_release : ret = %d", ret );
+#endif //CONFIG_DEBUG_HID_SIS_UPDATE_FW
+
+ return ret;
+}
+
+//SiS 817 only
+ssize_t sis_cdev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+{
+ int actual_length = 0, timeout = 0;
+ u8 *rep_data = NULL;
+ u16 size = 0;
+ long rep_ret;
+ struct usb_interface *intf = to_usb_interface(hid_dev_backup->dev.parent);
+ struct usb_device *dev = interface_to_usbdev(intf);
+
+#ifdef CONFIG_DEBUG_HID_SIS_UPDATE_FW
+ printk( KERN_INFO "sis_cdev_read\n");
+#endif //CONFIG_DEBUG_HID_SIS_UPDATE_FW
+
+ size = (((u16)(buf[64] & 0xff)) << 24) + (((u16)(buf[65] & 0xff)) << 16) +
+ (((u16)(buf[66] & 0xff)) << 8) + (u16)(buf[67] & 0xff);
+ timeout = (((int)(buf[68] & 0xff)) << 24) + (((int)(buf[69] & 0xff)) << 16) +
+ (((int)(buf[70] & 0xff)) << 8) + (int)(buf[71] & 0xff);
+
+ rep_data = kzalloc(size, GFP_KERNEL);
+ if (!rep_data)
+ return -12;
+
+ if ( copy_from_user( rep_data, (void*)buf, size) )
+ {
+ printk( KERN_INFO "copy_to_user fail\n" );
+ //free allocated data
+ kfree( rep_data );
+ rep_data = NULL;
+ return -19;
+ }
+
+ rep_ret = usb_interrupt_msg(dev, backup_urb->pipe,
+ rep_data, size, &actual_length, timeout);
+
+#ifdef CONFIG_DEBUG_HID_SIS_UPDATE_FW
+ printk(KERN_INFO "sis_cdev_read : rep_data = ");
+ for (i=0; i<8; i++)
+ {
+ printk ("%02X ", rep_data[i]);
+ }
+ printk ("\n");
+#endif //CONFIG_DEBUG_HID_SIS_UPDATE_FW
+
+ if( rep_ret == 0 )
+ {
+ rep_ret = actual_length;
+ if ( copy_to_user( (void*)buf, rep_data, rep_ret ) )
+ {
+ printk( KERN_INFO "copy_to_user fail\n" );
+ //free allocated data
+ kfree( rep_data );
+ rep_data = NULL;
+ return -19;
+ }
+ }
+
+ //free allocated data
+ kfree( rep_data );
+ rep_data = NULL;
+
+#ifdef CONFIG_DEBUG_HID_SIS_UPDATE_FW
+ printk( KERN_INFO "sis_cdev_read : rep_ret = %ld\n", rep_ret );
+#endif //CONFIG_DEBUG_HID_SIS_UPDATE_FW
+
+ return rep_ret;
+}
+
+ssize_t sis_cdev_write( struct file *file, const char __user *buf, size_t count, loff_t *f_pos )
+{
+ int i, actual_length = 0;
+ u8 *tmp_data = NULL; //include report id
+ u8 *rep_data = NULL;
+ long rep_ret;
+ struct usb_interface *intf = to_usb_interface( hid_dev_backup->dev.parent );
+ struct usb_device *dev = interface_to_usbdev( intf );
+ struct usbhid_device *usbhid = hid_dev_backup->driver_data;
+
+ if ( hid_dev_backup->product == USB_PRODUCT_ID_SIS817_TOUCH || hid_dev_backup->product == USB_PRODUCT_ID_SISF817_TOUCH ) //817 method
+ {
+ u16 size = (((u16)(buf[64] & 0xff)) << 24) + (((u16)(buf[65] & 0xff)) << 16) +
+ (((u16)(buf[66] & 0xff)) << 8) + (u16)(buf[67] & 0xff);
+ int timeout = (((int)(buf[68] & 0xff)) << 24) + (((int)(buf[69] & 0xff)) << 16) +
+ (((int)(buf[70] & 0xff)) << 8) + (int)(buf[71] & 0xff);
+
+#ifdef CONFIG_DEBUG_HID_SIS_UPDATE_FW
+ printk( KERN_INFO "sis_cdev_write : 817 method\n");
+#endif //CONFIG_DEBUG_HID_SIS_UPDATE_FW
+
+ rep_data = kzalloc(size, GFP_KERNEL);
+ if (!rep_data)
+ return -12;
+
+ if ( copy_from_user( rep_data, (void*)buf, size) )
+ {
+ printk( KERN_INFO "copy_to_user fail\n" );
+ //free allocated data
+ kfree( rep_data );
+ rep_data = NULL;
+ return -19;
+ }
+
+ rep_ret = usb_interrupt_msg( dev, usbhid->urbout->pipe,
+ rep_data, size, &actual_length, timeout );
+
+#ifdef CONFIG_DEBUG_HID_SIS_UPDATE_FW
+ printk(KERN_INFO "sis_cdev_write : rep_data = ");
+ for (i=0; i<size-1; i++)
+ {
+ printk ("%02X ", rep_data[i]);
+ }
+ if (i == size-1)
+ printk ("%02X\n", rep_data[i]);
+#endif //CONFIG_DEBUG_HID_SIS_UPDATE_FW
+
+ if( rep_ret == 0 )
+ {
+ rep_ret = actual_length;
+ if ( copy_to_user( (void*)buf, rep_data, rep_ret ) )
+ {
+ printk( KERN_INFO "copy_to_user fail\n" );
+ //free allocated data
+ kfree( rep_data );
+ rep_data = NULL;
+ return -19;
+ }
+ }
+
+#ifdef CONFIG_DEBUG_HID_SIS_UPDATE_FW
+ printk( KERN_INFO "sis_cdev_write : rep_ret = %ld\n", rep_ret );
+#endif //CONFIG_DEBUG_HID_SIS_UPDATE_FW
+
+ }
+ else //816 method
+ {
+
+ u8 request = buf[0];
+ u8 dir = buf[1];
+ u16 value = (((u16)(buf[2] & 0xff)) << 24) + (((u16)(buf[3] & 0xff)) << 16) + (((u16)(buf[4] & 0xff)) << 8) + (u16)(buf[5] & 0xff);
+ u16 index = (((u16)(buf[6] & 0xff)) << 24) + (((u16)(buf[7] & 0xff)) << 16) + (((u16)(buf[8] & 0xff)) << 8) + (u16)(buf[9] & 0xff);
+
+
+ u16 size = (((u16)(buf[29] & 0xff)) << 24) + (((u16)(buf[30] & 0xff)) << 16) + (((u16)(buf[31] & 0xff)) << 8) + (u16)(buf[32] & 0xff);
+ int timeout = (((int)(buf[33] & 0xff)) << 24) + (((int)(buf[34] & 0xff)) << 16) + (((int)(buf[35] & 0xff)) << 8) + (int)(buf[36] & 0xff);
+
+#ifdef CONFIG_DEBUG_HID_SIS_UPDATE_FW
+ printk( KERN_INFO "sis_cdev_write : 816 method\n");
+ printk (KERN_INFO "dir = %d, value = %d, index = %d, timeout = %d\n", dir, value, index, timeout);
+#endif //CONFIG_DEBUG_HID_SIS_UPDATE_FW
+
+ rep_data = kzalloc( size , GFP_KERNEL );
+ if ( rep_data == 0 )
+ {
+ return -12;
+ }
+
+ for( i = 0; i < size; i++)
+ {
+ rep_data[i] = buf[10+i];
+ }
+
+ tmp_data = kzalloc( size + 1, GFP_KERNEL ); //include report id, so size +1
+
+ for( i = 0; i < size; i++ )
+ {
+ tmp_data[i+1] = rep_data[i];
+ }
+
+ buf += 10;
+
+ if( dir & DIR_IN )
+ {
+ if ( hid_dev_backup->product == USB_PRODUCT_ID_SIS2_TOUCH || hid_dev_backup->product == USB_PRODUCT_ID_NEW_SIS2_TOUCH )
+ {
+ //20110510, Yuger, for correcting intr data send into interrupt msg(receive, in, endp=2)
+ tmp_data[0] = 0x0A;//in
+
+ rep_ret = usb_interrupt_msg( dev, backup_urb->pipe, tmp_data, size+1, &actual_length, timeout );
+ //yy
+
+#ifdef CONFIG_DEBUG_HID_SIS_UPDATE_FW
+ printk(KERN_INFO "(INT_IN)rep_ret = %ld, actual_length = %d", rep_ret, actual_length);
+#endif //CONFIG_DEBUG_HID_SIS_UPDATE_FW
+
+ if( rep_ret == 0 )
+ {
+ rep_ret = actual_length;
+ }
+
+ //20110510, Yuger, for recovering rep_data
+ for( i = 0; i < size; i++ )
+ {
+ rep_data[i] = tmp_data[i+1];
+ }
+ //yy
+
+#ifdef CONFIG_DEBUG_HID_SIS_UPDATE_FW
+ printk(KERN_INFO "(INT_IN)size = %u, dir = %u, rep_ret = %ld, rep_data = %X %X %X", size, dir, rep_ret, rep_data[0], rep_data[1], rep_data[2]);
+#endif //CONFIG_DEBUG_HID_SIS_UPDATE_FW
+
+ if ( copy_to_user( (void*)buf, rep_data, rep_ret ) )
+ {
+ printk( KERN_INFO "copy_to_user fail\n" );
+ //free allocated data
+ kfree( rep_data );
+ kfree( tmp_data );
+ rep_data = NULL;
+ tmp_data = NULL;
+ return -19;
+ }
+ }
+ else
+ {
+ //control message
+ rep_ret = usb_control_msg( dev, usb_rcvctrlpipe( dev, CTRL ),
+ request, (USB_DIR_IN|USB_TYPE_VENDOR|USB_RECIP_DEVICE),
+ value, index, rep_data, size, timeout );
+
+#ifdef CONFIG_DEBUG_HID_SIS_UPDATE_FW
+ printk ("(CTRL) size = %d, dir = %d, rep_ret = %ld, rep_data = ", size, dir, rep_ret);
+ for (i=0; i<size-1; i++)
+ {
+ printk ("%02X ", rep_data[i]);
+ }
+ if (i == size-1)
+ printk ("%02X\n", rep_data[i]);
+#endif //CONFIG_DEBUG_HID_SIS_UPDATE_FW
+
+ if ( copy_to_user( (void*)buf, rep_data, rep_ret ) )
+ {
+ printk( KERN_INFO "copy_to_user fail\n" );
+ //free allocated data
+ kfree( rep_data );
+ rep_data = NULL;
+ return -19;
+ }
+ }
+ }
+ else
+ {
+ if ( hid_dev_backup->product == USB_PRODUCT_ID_SIS2_TOUCH || hid_dev_backup->product == USB_PRODUCT_ID_NEW_SIS2_TOUCH )
+ {
+ //20110510, Yuger, for correcting intr data send into interrupt msg(send, out, endp=1)
+ tmp_data[0] = 0x09;//out
+
+ rep_ret = usb_interrupt_msg( dev, usbhid->urbout->pipe, tmp_data, size + 1, &actual_length, timeout );
+
+ //just return success or not(no need to return actual_length if succeed)
+
+ //20110510, Yuger, for recovering rep_data
+ for( i = 0; i < size; i++ )
+ {
+ rep_data[i] = tmp_data[i+1];
+ }
+ //yy
+
+#ifdef CONFIG_DEBUG_HID_SIS_UPDATE_FW
+ printk(KERN_INFO "(INT_OUT)size = %u, actual_length = %d, rep_ret = %ld, rep_data = %x %x %x", size, actual_length, rep_ret, rep_data[0], rep_data[1], rep_data[2]);
+#endif //CONFIG_DEBUG_HID_SIS_UPDATE_FW
+
+ if ( copy_to_user( (void*)buf, rep_data, actual_length-1 ) )
+ {
+ printk( KERN_INFO "copy_to_user fail\n" );
+ //free allocated data
+ kfree( rep_data );
+ kfree( tmp_data );
+ rep_data = NULL;
+ tmp_data = NULL;
+ return -19;
+ }
+ }
+ else
+ {
+ //control message
+ rep_ret = usb_control_msg( dev, usb_sndctrlpipe( dev, CTRL ),
+ request, (USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_DEVICE),
+ value, index, rep_data, 16, timeout );
+
+#ifdef CONFIG_DEBUG_HID_SIS_UPDATE_FW
+ printk ("(CTRL) size = %d, dir = %d, rep_ret = %ld, rep_data = ", size, dir, rep_ret);
+ for (i=0; i<size-1; i++)
+ {
+ printk ("%02X ", rep_data[i]);
+ }
+ if (i == size-1)
+ printk ("%02X\n", rep_data[i]);
+#endif //CONFIG_DEBUG_HID_SIS_UPDATE_FW
+
+ if ( copy_to_user( (void*)buf, rep_data, rep_ret ) )
+ {
+ printk( KERN_INFO "copy_to_user fail\n" );
+ //free allocated data
+ kfree( rep_data );
+ rep_data = NULL;
+ return -19;
+ }
+ }
+ }
+ //free allocated data
+ kfree( tmp_data );
+ tmp_data = NULL;
+ }
+ //free allocated data
+ kfree( rep_data );
+ rep_data = NULL;
+
+#ifdef CONFIG_DEBUG_HID_SIS_UPDATE_FW
+ printk( KERN_INFO "End of sis_cdev_write\n" );
+#endif //CONFIG_DEBUG_HID_SIS_UPDATE_FW
+
+ return rep_ret;
+}
+
+//~TT
+
+//for ioctl
+static const struct file_operations sis_cdev_fops = {
+ .owner = THIS_MODULE,
+ .read = sis_cdev_read,
+ .write = sis_cdev_write,
+ .open = sis_cdev_open,
+ .release= sis_cdev_release,
+};
+
+//for ioctl
+static int sis_setup_chardev(struct hid_device *hdev, struct sis_data *nd)
+{
+
+ dev_t dev = MKDEV(sis_char_major, 0);
+ int alloc_ret = 0;
+ int cdev_err = 0;
+ int input_err = 0;
+ struct device *class_dev = NULL;
+ void *ptr_err;
+
+ printk("sis_setup_chardev.\n");
+
+ if (nd == NULL)
+ {
+ input_err = -ENOMEM;
+ goto error;
+ }
+
+ // dynamic allocate driver handle
+ if (hdev->product == USB_PRODUCT_ID_SIS9200_TOUCH)
+ alloc_ret = alloc_chrdev_region(&dev, 0, sis_char_devs_count, BRIDGE_DEVICE_NAME);
+ else if (hdev->product == USB_PRODUCT_ID_SIS817_TOUCH)
+ alloc_ret = alloc_chrdev_region(&dev, 0, sis_char_devs_count, SIS817_DEVICE_NAME);
+ else if (hdev->product == USB_PRODUCT_ID_SISF817_TOUCH)
+ alloc_ret = alloc_chrdev_region(&dev, 0, sis_char_devs_count, SISF817_DEVICE_NAME);
+ else
+ alloc_ret = alloc_chrdev_region(&dev, 0, sis_char_devs_count, INTERNAL_DEVICE_NAME);
+
+ if (alloc_ret)
+ goto error;
+
+ sis_char_major = MAJOR(dev);
+ cdev_init(&sis_char_cdev, &sis_cdev_fops);
+ sis_char_cdev.owner = THIS_MODULE;
+ cdev_err = cdev_add(&sis_char_cdev, MKDEV(sis_char_major, 0), sis_char_devs_count);
+ if (cdev_err)
+ goto error;
+
+ if (hdev->product == USB_PRODUCT_ID_SIS9200_TOUCH)
+ printk(KERN_INFO "%s driver(major %d) installed.\n", BRIDGE_DEVICE_NAME, sis_char_major);
+ else if (hdev->product == USB_PRODUCT_ID_SIS817_TOUCH)
+ printk(KERN_INFO "%s driver(major %d) installed.\n", SIS817_DEVICE_NAME, sis_char_major);
+ else if (hdev->product == USB_PRODUCT_ID_SISF817_TOUCH)
+ printk(KERN_INFO "%s driver(major %d) installed.\n", SISF817_DEVICE_NAME, sis_char_major);
+ else
+ printk(KERN_INFO "%s driver(major %d) installed.\n", INTERNAL_DEVICE_NAME, sis_char_major);
+
+ // register class
+ if (hdev->product == USB_PRODUCT_ID_SIS9200_TOUCH)
+ sis_char_class = class_create(THIS_MODULE, BRIDGE_DEVICE_NAME);
+ else if (hdev->product == USB_PRODUCT_ID_SIS817_TOUCH)
+ sis_char_class = class_create(THIS_MODULE, SIS817_DEVICE_NAME);
+ else if (hdev->product == USB_PRODUCT_ID_SISF817_TOUCH)
+ sis_char_class = class_create(THIS_MODULE, SISF817_DEVICE_NAME);
+ else
+ sis_char_class = class_create(THIS_MODULE, INTERNAL_DEVICE_NAME);
+
+ if(IS_ERR(ptr_err = sis_char_class))
+ {
+ goto err2;
+ }
+
+ if (hdev->product == USB_PRODUCT_ID_SIS9200_TOUCH)
+ class_dev = device_create(sis_char_class, NULL, MKDEV(sis_char_major, 0), NULL, BRIDGE_DEVICE_NAME);
+ else if (hdev->product == USB_PRODUCT_ID_SIS817_TOUCH)
+ class_dev = device_create(sis_char_class, NULL, MKDEV(sis_char_major, 0), NULL, SIS817_DEVICE_NAME);
+ else if (hdev->product == USB_PRODUCT_ID_SISF817_TOUCH)
+ class_dev = device_create(sis_char_class, NULL, MKDEV(sis_char_major, 0), NULL, SISF817_DEVICE_NAME);
+ else
+ class_dev = device_create(sis_char_class, NULL, MKDEV(sis_char_major, 0), NULL, INTERNAL_DEVICE_NAME);
+
+ if(IS_ERR(ptr_err = class_dev))
+ {
+ goto err;
+ }
+
+ return 0;
+error:
+ if (cdev_err == 0)
+ cdev_del(&sis_char_cdev);
+ if (alloc_ret == 0)
+ unregister_chrdev_region(MKDEV(sis_char_major, 0), sis_char_devs_count);
+ if(input_err != 0)
+ {
+ printk("sis_ts_bak error!\n");
+ }
+err:
+ device_destroy(sis_char_class, MKDEV(sis_char_major, 0));
+err2:
+ class_destroy(sis_char_class);
+ return -1;
+}
+#endif //CONFIG_HID_SIS_UPDATE_FW
+
+static int sis_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+ int ret;
+ struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+ struct usb_device *dev = interface_to_usbdev(intf);
+ struct sis_data *nd;
+ u8 *rep_data = NULL;
+
+#ifdef CONFIG_HID_SIS_UPDATE_FW
+ hid_dev_backup = hdev;
+#endif //CONFIG_HID_SIS_UPDATE_FW
+
+ printk(KERN_INFO "sis_probe\n");
+
+#ifdef CONFIG_HID_SIS_UPDATE_FW
+ backup_urb = usb_alloc_urb(0, GFP_KERNEL); //0721test
+ if (!backup_urb) {
+ dev_err(&hdev->dev, "cannot allocate backup_urb\n");
+ return -ENOMEM;
+ }
+#endif //CONFIG_HID_SIS_UPDATE_FW
+
+// command Set_Feature for changing device from mouse to touch device
+ rep_data = kmalloc(3,GFP_KERNEL); //return value will be 0xabcd
+ if (hdev->product == USB_PRODUCT_ID_SIS9200_TOUCH)
+ {
+ if(!rep_data)
+ return -ENOMEM;
+ rep_data[0] = 0x07;
+ rep_data[1] = 0x02;
+ rep_data[2] = 0xA9;
+
+ ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ USB_REQ_SET_CONFIGURATION, (USB_DIR_OUT | USB_TYPE_CLASS |
+ USB_RECIP_INTERFACE), 0x0307, 0, rep_data, 3, 1000);
+ }
+
+// allocate memory for sis_data struct
+ nd = kzalloc(sizeof(struct sis_data), GFP_KERNEL);
+ if (!nd) {
+ dev_err(&hdev->dev, "cannot allocate SiS 9200 data\n");
+ kfree(rep_data);
+ rep_data = NULL;
+ return -ENOMEM;
+ }
+
+ hid_set_drvdata(hdev, nd);
+
+#ifdef CONFIG_HID_SIS_UPDATE_FW
+ //for ioctl
+ ret = sis_setup_chardev(hdev, nd);
+ if(ret)
+ {
+ printk( KERN_INFO "sis_setup_chardev fail\n");
+ }
+#endif //CONFIG_HID_SIS_UPDATE_FW
+
+ //set noget for not init reports (speed improvement)
+ hdev->quirks |= HID_QUIRK_NOGET;
+ hdev->quirks &= ~HID_QUIRK_MULTITOUCH; //only hid-multitouch cat use this flag!
+
+ ret = hid_parse(hdev);
+ if (ret) {
+ dev_err(&hdev->dev, "parse failed\n");
+ goto err_free;
+ }
+
+ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+ if (ret) {
+ dev_err(&hdev->dev, "hw start failed\n");
+ goto err_free;
+ }
+
+err_free:
+ kfree(rep_data);
+ rep_data = NULL;
+ return ret;
+}
+
+static void sis_remove(struct hid_device *hdev)
+{
+#ifdef CONFIG_HID_SIS_UPDATE_FW
+ //for ioctl
+ dev_t dev = MKDEV(sis_char_major, 0);
+
+ printk(KERN_INFO "sis_remove\n");
+
+ cdev_del(&sis_char_cdev);
+ unregister_chrdev_region(dev, sis_char_devs_count);
+ device_destroy(sis_char_class, MKDEV(sis_char_major, 0));
+ class_destroy(sis_char_class);
+#else //CONFIG_HID_SIS_UPDATE_FW
+
+ printk(KERN_INFO "sis_remove\n");
+
+#endif //CONFIG_HID_SIS_UPDATE_FW
+
+#ifdef CONFIG_HID_SIS_UPDATE_FW
+ usb_kill_urb( backup_urb );
+ usb_free_urb( backup_urb );
+ backup_urb = NULL;
+#endif
+ hid_hw_stop(hdev);
+ kfree(hid_get_drvdata(hdev));
+ hid_set_drvdata(hdev, NULL);
+}
+
+static const struct hid_device_id sis_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_SIS2_TOUCH, USB_PRODUCT_ID_SIS2_TOUCH) }, //0x0457, 0x0151
+ { HID_USB_DEVICE(USB_VENDOR_ID_SIS2_TOUCH, USB_PRODUCT_ID_SIS_TOUCH) }, //0x0457, 0x0810
+ { HID_USB_DEVICE(USB_VENDOR_ID_SIS2_TOUCH, USB_PRODUCT_ID_NEW_SIS2_TOUCH) }, //0x0457, 0x0816
+ { HID_USB_DEVICE(USB_VENDOR_ID_SIS2_TOUCH, USB_PRODUCT_ID_SIS9200_TOUCH) }, //0x0457, 0x9200
+ { HID_USB_DEVICE(USB_VENDOR_ID_SIS2_TOUCH, USB_PRODUCT_ID_SIS817_TOUCH) }, //0x0457, 0x0817
+ { HID_USB_DEVICE(USB_VENDOR_ID_SIS2_TOUCH, USB_PRODUCT_ID_SISF817_TOUCH) }, //0x0457, 0xF817
+ { }
+};
+MODULE_DEVICE_TABLE(hid, sis_devices);
+
+
+
+static struct hid_driver sis_driver = {
+ .name = "sis",
+ .id_table = sis_devices,
+ .probe = sis_probe,
+ .remove = sis_remove,
+ .raw_event = sis_raw_event,
+ .input_mapped = sis_input_mapped,
+ .input_mapping = sis_input_mapping,
+ .event = sis_event,
+};
+
+static int __init sis_init(void)
+{
+ printk(KERN_INFO "sis_init\n");
+ return hid_register_driver(&sis_driver);
+}
+
+static void __exit sis_exit(void)
+{
+ printk(KERN_INFO "sis_exit\n");
+ hid_unregister_driver(&sis_driver);
+}
+
+module_init(sis_init);
+module_exit(sis_exit);
+MODULE_DESCRIPTION("SiS 817 Touchscreen Driver");
+MODULE_LICENSE("GPL");
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/sitronix/Kconfig b/ANDROID_3.4.5/drivers/input/touchscreen/sitronix/Kconfig
new file mode 100755
index 00000000..eb37231f
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/sitronix/Kconfig
@@ -0,0 +1,11 @@
+config TOUCHSCREEN_SITRONIX
+ tristate "Sitronix ST1xx series Capacity Touchscreen Device Support"
+ default m
+ depends on ARCH_WMT
+ ---help---
+ Say Y here if you have an WMT based board with touchscreen
+ attached to it.
+ If unsure, say N.
+ To compile this driver as a module, choose M here: the
+ module will be called s_wmt_ts_sitronix.ko.
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/sitronix/Makefile b/ANDROID_3.4.5/drivers/input/touchscreen/sitronix/Makefile
new file mode 100755
index 00000000..b38deb74
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/sitronix/Makefile
@@ -0,0 +1,34 @@
+KERNELDIR=../../../../
+CROSS = arm_1103_le-
+CC= $(CROSS)gcc
+LD= $(CROSS)ld
+STRIP = $(CROSS)strip
+
+DEBUG = n
+
+# Add your debugging flag (or not) to EXTRA_CFLAGS
+ifeq ($(DEBUG),y)
+# DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+DEBFLAGS = -O0 -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+
+else
+ DEBFLAGS = -O2 -Wall
+endif
+
+EXTRA_CFLAGS += $(DEBFLAGS)
+
+
+MY_MODULE_NAME=s_wmt_ts_sitronix
+
+#obj-$(CONFIG_TOUCHSCREEN_SITRONIX) := $(MY_MODULE_NAME).o
+obj-m := $(MY_MODULE_NAME).o
+$(MY_MODULE_NAME)-objs := sitronix_i2c.o irq_gpio.o
+
+default:
+ $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules
+ $(STRIP) --strip-debug $(MY_MODULE_NAME).ko
+ @rm -rf *.o *~ core .depend .*.cmd *.mod.c .tmp_versions *.order *.symvers
+
+clean:
+ @rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.order *.symvers
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/sitronix/irq_gpio.c b/ANDROID_3.4.5/drivers/input/touchscreen/sitronix/irq_gpio.c
new file mode 100755
index 00000000..bf57ff92
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/sitronix/irq_gpio.c
@@ -0,0 +1,148 @@
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+#include <mach/hardware.h>
+#include "irq_gpio.h"
+
+int wmt_enable_gpirq(int num)
+{
+ if(num > 15)
+ return -1;
+
+ if(num < 4)
+ REG32_VAL(__GPIO_BASE+0x0300) |= 1<<(num*8+7); //enable interrupt
+ else if(num >= 4 && num < 8)
+ REG32_VAL(__GPIO_BASE+0x0304) |= 1<<((num-4)*8+7); //enable interrupt
+ else if(num >= 8 && num < 12)
+ REG32_VAL(__GPIO_BASE+0x0308) |= 1<<((num-8)*8+7); //enable interrupt
+ else
+ REG32_VAL(__GPIO_BASE+0x030C) |= 1<<((num-12)*8+7); //enable interrupt
+
+ return 0;
+}
+
+int wmt_disable_gpirq(int num)
+{
+ if(num > 15)
+ return -1;
+
+ if(num<4)
+ REG32_VAL(__GPIO_BASE+0x0300) &= ~(1<<(num*8+7)); //enable interrupt
+ else if(num >= 4 && num < 8)
+ REG32_VAL(__GPIO_BASE+0x0304) &= ~(1<<((num-4)*8+7)); //enable interrupt
+ else if(num >= 8 && num < 12)
+ REG32_VAL(__GPIO_BASE+0x0308) &= ~(1<<((num-8)*8+7)); //enable interrupt
+ else
+ REG32_VAL(__GPIO_BASE+0x030C) &= ~(1<<((num-12)*8+7)); //enable interrupt
+
+ return 0;
+}
+
+int wmt_is_tsirq_enable(int num)
+{
+ int val = 0;
+
+ if(num > 15)
+ return 0;
+
+ if(num<4)
+ val = REG32_VAL(__GPIO_BASE+0x0300) & (1<<(num*8+7));
+ else if(num >= 4 && num < 8)
+ val = REG32_VAL(__GPIO_BASE+0x0304) & (1<<((num-4)*8+7));
+ else if(num >= 8 && num < 12)
+ val = REG32_VAL(__GPIO_BASE+0x0308) & (1<<((num-8)*8+7));
+ else
+ val = REG32_VAL(__GPIO_BASE+0x030C) & (1<<((num-12)*8+7));
+
+ return val?1:0;
+
+}
+
+int wmt_is_tsint(int num)
+{
+ if (num > 15)
+ {
+ return 0;
+ }
+ return (REG32_VAL(__GPIO_BASE+0x0360) & (1<<num)) ? 1: 0;
+}
+
+void wmt_clr_int(int num)
+{
+ if (num > 15)
+ {
+ return;
+ }
+ REG32_VAL(__GPIO_BASE+0x0360) = 1<<num;
+}
+
+int wmt_set_gpirq(int num, int type)
+{
+ int shift;
+ int offset;
+ unsigned long reg;
+
+ if(num >15)
+ return -1;
+ //if (num > 9)
+ //GPIO_PIN_SHARING_SEL_4BYTE_VAL &= ~BIT4; // gpio10,11 as gpio
+ REG32_VAL(__GPIO_BASE+0x0040) &= ~(1<<num);//|=(1<<num);// //enable gpio
+ REG32_VAL(__GPIO_BASE+0x0080) &= ~(1<<num); //set input
+ REG32_VAL(__GPIO_BASE+0x04c0) |= (1<<num); //pull down
+ REG32_VAL(__GPIO_BASE+0x0480) &= ~(1<<num); //enable pull up/down
+
+ //set gpio irq triger type
+ if(num < 4){//[0,3]
+ shift = num;
+ offset = 0x0300;
+ }else if(num >= 4 && num < 8){//[4,7]
+ shift = num-4;
+ offset = 0x0304;
+ }else if(num >= 8 && num < 12){//[8,11]
+ shift = num-8;
+ offset = 0x0308;
+ }else{// [12,15]
+ shift = num-12;
+ offset = 0x030C;
+ }
+
+ reg = REG32_VAL(__GPIO_BASE + offset);
+
+ switch(type){
+ case IRQ_TYPE_LEVEL_LOW:
+ reg &= ~(1<<(shift*8+2));
+ reg &= ~(1<<(shift*8+1));
+ reg &= ~(1<<(shift*8));
+ break;
+ case IRQ_TYPE_LEVEL_HIGH:
+ reg &= ~(1<<(shift*8+2));
+ reg &= ~(1<<(shift*8+1));
+ reg |= (1<<(shift*8));
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ reg &= ~(1<<(shift*8+2));
+ reg |= (1<<(shift*8+1));
+ reg &= ~(1<<(shift*8));
+ break;
+ case IRQ_TYPE_EDGE_RISING:
+ reg &= ~(1<<(shift*8+2));
+ reg |= (1<<(shift*8+1));
+ reg |= (1<<(shift*8));
+ break;
+ default://both edge
+ reg |= (1<<(shift*8+2));
+ reg &= ~(1<<(shift*8+1));
+ reg &= ~(1<<(shift*8));
+ break;
+
+ }
+ //reg |= 1<<(shift*8+7);//enable interrupt
+ reg &= ~(1<<(shift*8+7)); //disable int
+
+ REG32_VAL(__GPIO_BASE + offset) = reg;
+ REG32_VAL(__GPIO_BASE+0x0360) = 1<<num; //clear interrupt status
+ msleep(5);
+ return 0;
+}
+
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/sitronix/irq_gpio.h b/ANDROID_3.4.5/drivers/input/touchscreen/sitronix/irq_gpio.h
new file mode 100755
index 00000000..0232bd04
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/sitronix/irq_gpio.h
@@ -0,0 +1,13 @@
+#ifndef _LINUX_IRQ_GPIO_H
+#define _LINUX_IRQ_GPIO_H
+
+
+extern int wmt_enable_gpirq(int num);
+extern int wmt_disable_gpirq(int num);
+extern int wmt_is_tsirq_enable(int num);
+extern int wmt_is_tsint(int num);
+extern void wmt_clr_int(int num);
+extern int wmt_set_gpirq(int num, int type);
+
+
+#endif
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/sitronix/sitronix_i2c.c b/ANDROID_3.4.5/drivers/input/touchscreen/sitronix/sitronix_i2c.c
new file mode 100755
index 00000000..7b79aaf4
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/sitronix/sitronix_i2c.c
@@ -0,0 +1,817 @@
+/* drivers/input/touchscreen/sis_i2c.c
+ *
+ * Copyright (C) 2009 SiS, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/linkage.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <mach/wmt_iomux.h>
+#include <mach/hardware.h>
+#include <asm/uaccess.h>
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+#include "sitronix_i2c.h"
+#include "irq_gpio.h"
+
+struct sitronix_data *pContext=NULL;
+struct i2c_client *l_client=NULL;
+
+#ifdef TOUCH_KEY
+
+#define MENU_IDX 0
+#define HOME_IDX 1
+#define BACK_IDX 2
+#define SEARCH_IDX 3
+#define NUM_KEYS 4
+
+static int virtual_keys[NUM_KEYS] ={
+ KEY_BACK,
+ KEY_HOME,
+ KEY_MENU,
+ KEY_SEARCH
+};
+#endif
+
+#define I2C_BUS1 1
+
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void sitronix_early_suspend(struct early_suspend *h);
+static void sitronix_late_resume(struct early_suspend *h);
+#endif
+
+static int sitronix_read(struct sitronix_data *sitronix, u8 *rxdata, int length)
+{
+ int ret;
+ struct i2c_msg msg[2];
+
+ msg[0].addr = sitronix->addr;
+ msg[0].flags = 0 | I2C_M_NOSTART;
+ msg[0].len = 1;
+ msg[0].buf = rxdata;
+
+ msg[1].addr = sitronix->addr;
+ msg[1].flags = I2C_M_RD;
+ msg[1].len = length;
+ msg[1].buf = rxdata;
+
+ //ret = wmt_i2c_xfer_continue_if_4(msg, 2, I2C_BUS1);
+ ret = i2c_transfer(l_client->adapter, msg, 2);
+ if (ret <= 0)
+ dbg_err("msg i2c read error: %d\n", ret);
+
+ return ret;
+}
+
+#ifdef SITRONIX_DEBUG
+static int sitronix_write(struct sitronix_data *sitronix, u8 *txdata, int length)
+{
+ int ret;
+ struct i2c_msg msg[1];
+
+ msg[0].addr = sitronix->addr;
+ msg[0].flags = 0;
+ msg[0].len = length;
+ msg[0].buf = txdata;
+
+ //ret = wmt_i2c_xfer_continue_if_4(msg, 1, I2C_BUS1);
+ ret = i2c_transfer(l_client->adapter, msg, 1);
+ if (ret <= 0)
+ dbg_err("msg i2c read error: %d\n", ret);
+
+ return ret;
+}
+
+static int sitronix_get_fw_revision(struct sitronix_data *sitronix)
+{
+ int ret = 0;
+ uint8_t buffer[4]={FIRMWARE_REVISION_3,0};
+
+ ret = sitronix_read(sitronix, buffer, 4);
+ if (ret < 0){
+ dbg_err("read fw revision error (%d)\n", ret);
+ return ret;
+ }
+
+ memcpy(sitronix->fw_revision, buffer, 4);
+ printk("Fw Revision (hex): %x%x%x%x\n", buffer[0], buffer[1], buffer[2], buffer[3]);
+
+ return 0;
+}
+
+static int sitronix_get_max_touches(struct sitronix_data *sitronix)
+{
+ int ret = 0;
+ uint8_t buffer[1]={MAX_NUM_TOUCHES};
+
+ ret = sitronix_read(sitronix, buffer, 1);
+ if (ret < 0){
+ dbg_err("read max touches error (%d)\n", ret);
+ return ret;
+ }
+
+ sitronix->max_touches = buffer[0];
+ printk("max touches = %d \n",sitronix->max_touches);
+
+ return 0;
+}
+
+static int sitronix_get_protocol(struct sitronix_data *sitronix)
+{
+ int ret = 0;
+ uint8_t buffer[1]={I2C_PROTOCOL};
+
+ ret = sitronix_read(sitronix, buffer, 1);
+ if (ret < 0){
+ dbg_err("read i2c protocol error (%d)\n", ret);
+ return ret;
+ }
+
+ sitronix->touch_protocol_type = buffer[0] & I2C_PROTOCOL_BMSK;
+ sitronix->sensing_mode = (buffer[0] & (ONE_D_SENSING_CONTROL_BMSK << ONE_D_SENSING_CONTROL_SHFT)) >> ONE_D_SENSING_CONTROL_SHFT;
+ printk("i2c protocol = %d ,sensing mode = %d \n", sitronix->touch_protocol_type, sitronix->sensing_mode);
+
+ return 0;
+}
+
+static int sitronix_get_resolution(struct sitronix_data *sitronix)
+{
+ int ret = 0;
+ uint8_t buffer[3]={XY_RESOLUTION_HIGH};
+
+ ret = sitronix_read(sitronix, buffer, 3);
+ if (ret < 0){
+ dbg_err("read resolution error (%d)\n", ret);
+ return ret;
+ }
+
+ sitronix->resolution_x = ((buffer[0] & (X_RES_H_BMSK << X_RES_H_SHFT)) << 4) | buffer[1];
+ sitronix->resolution_y = ((buffer[0] & Y_RES_H_BMSK) << 8) | buffer[2];
+ printk("Resolution: %d x %d\n", sitronix->resolution_x, sitronix->resolution_y);
+
+ return 0;
+}
+
+static int sitronix_get_chip_id(struct sitronix_data *sitronix)
+{
+ int ret = 0;
+ uint8_t buffer[3]={CHIP_ID};
+
+ ret = sitronix_read(sitronix, buffer, 3);
+ if (ret < 0){
+ dbg_err("read Chip ID error (%d)\n", ret);
+ return ret;
+ }
+
+ if(buffer[0] == 0){
+ if(buffer[1] + buffer[2] > 32)
+ sitronix->chip_id = 2;
+ else
+ sitronix->chip_id = 0;
+ }else
+ sitronix->chip_id = buffer[0];
+
+ sitronix->Num_X = buffer[1];
+ sitronix->Num_Y = buffer[2];
+ printk("Chip ID = %d, Num_X = %d, Num_Y = %d\n", sitronix->chip_id, sitronix->Num_X, sitronix->Num_Y);
+
+ return 0;
+}
+
+static int sitronix_get_device_status(struct sitronix_data *sitronix)
+{
+ int ret = 0;
+ uint8_t buf[3]={FIRMWARE_VERSION,0};
+
+ ret = sitronix_read(sitronix, buf, 3);
+ if (ret < 0){
+ dbg_err("read resolution error (%d)\n", ret);
+ return ret;
+ }
+
+ printk("Firmware version:%02x, Status Reg:%02x,Ctrl Reg:%02x\n", buf[0], buf[1],buf[2]);
+ return 0;
+
+}
+
+static int sitronix_get_device_info(struct sitronix_data *sitronix)
+{
+ int ret = 0;
+
+ ret = sitronix_get_resolution(sitronix);
+ if(ret < 0) return ret;
+
+ ret = sitronix_get_chip_id(sitronix);
+ if(ret < 0) return ret;
+
+ ret = sitronix_get_fw_revision(sitronix);
+ if(ret < 0) return ret;
+
+ ret = sitronix_get_protocol(sitronix);
+ if(ret < 0) return ret;
+
+ ret = sitronix_get_max_touches(sitronix);
+ if(ret < 0) return ret;
+
+ ret = sitronix_get_device_status(sitronix);
+ if(ret < 0) return ret;
+
+ if((sitronix->fw_revision[0] == 0) && (sitronix->fw_revision[1] == 0)){
+ if(sitronix->touch_protocol_type == SITRONIX_RESERVED_TYPE_0){
+ sitronix->touch_protocol_type = SITRONIX_B_TYPE;
+ printk("i2c protocol (revised) = %d \n", sitronix->touch_protocol_type);
+ }
+ }
+
+ if(sitronix->touch_protocol_type == SITRONIX_A_TYPE)
+ sitronix->pixel_length = PIXEL_DATA_LENGTH_A;
+ else if(sitronix->touch_protocol_type == SITRONIX_B_TYPE){
+ sitronix->pixel_length = PIXEL_DATA_LENGTH_B;
+ sitronix->max_touches = 2;
+ printk("max touches (revised) = %d \n", sitronix->max_touches);
+ }
+
+ return 0;
+}
+#endif
+
+static void sitronix_read_work(struct work_struct *work)
+{
+ struct sitronix_data *sitronix= container_of(work, struct sitronix_data, read_work);
+ int ret = -1;
+ u8 buf[22] = {FINGERS,0};
+ u8 i = 0, fingers = 0, tskey = 0;
+ u16 px = 0, py = 0;
+ u16 x = 0, y = 0;
+
+ ret = sitronix_read(sitronix, buf,sizeof(buf));
+ if(ret <= 0){
+ dbg_err("get raw data failed!\n");
+ goto err_exit;
+ }
+
+ fingers = buf[0]&0x0f;
+ if( fingers ){
+ /* Report co-ordinates to the multi-touch stack */
+ for(i=0; i < fingers; i++){
+ if(sitronix->swap){
+ y = ((buf[i*4+2]<<4)&0x0700)|buf[i*4+3];
+ x = ((buf[i*4+2]<<8)&0x0700)|buf[i*4+4];
+ }else{
+ x = ((buf[i*4+2]<<4)&0x0700)|buf[i*4+3];
+ y = ((buf[i*4+2]<<8)&0x0700)|buf[i*4+4];
+ }
+
+ if(!(buf[i*4+2]&0x80)) continue; /*check valid bit */
+
+
+ if(x > sitronix->xresl ) x = sitronix->xresl ;
+ if(y > sitronix->yresl ) y = sitronix->yresl ;
+
+ px = x;
+ py = y;
+ if(sitronix->xch) px = sitronix->xresl - x;
+ if(sitronix->ych) py = sitronix->yresl - y;
+
+ if (sitronix->lcd_exchg) {
+ int tmp;
+ tmp = px;
+ px = py;
+ py = sitronix->xresl - tmp;
+ }
+
+ input_report_abs(sitronix->input_dev, ABS_MT_POSITION_X, px);
+ input_report_abs(sitronix->input_dev, ABS_MT_POSITION_Y, py);
+ input_report_abs(sitronix->input_dev, ABS_MT_TRACKING_ID, i+1);
+ input_mt_sync(sitronix->input_dev);
+ sitronix->penup = 0;
+ if(sitronix->dbg) printk("F%d,raw data: x=%-4d, y=%-4d; report data: px=%-4d, py=%-4d\n", i, x, y, px, py);
+ }
+ input_sync(sitronix->input_dev);
+
+ }
+ else if(!sitronix->penup){
+ dbg("pen up.\n");
+ sitronix->penup = 1;
+ input_mt_sync(sitronix->input_dev);
+ input_sync(sitronix->input_dev);
+ }
+
+ /* virtual keys */
+ tskey = buf[1];
+ if(tskey){
+ if(!sitronix->tkey_idx){
+ sitronix->tkey_idx = tskey;
+ input_report_key(sitronix->input_dev,virtual_keys[sitronix->tkey_idx>>1] , 1);
+ input_sync(sitronix->input_dev);
+ dbg("virtual key down, idx=%d\n",sitronix->tkey_idx);
+ }
+ }else{
+ if(sitronix->tkey_idx){
+ dbg("virtual key up , idx=%d\n",sitronix->tkey_idx);
+ input_report_key(sitronix->input_dev,virtual_keys[sitronix->tkey_idx>>1] , 0);
+ input_sync(sitronix->input_dev);
+ sitronix->tkey_idx = tskey;
+ }
+ }
+
+err_exit:
+ wmt_enable_gpirq(sitronix->irqgpio);
+ return;
+}
+
+
+static irqreturn_t sitronix_isr_handler(int irq, void *dev)
+{
+ struct sitronix_data *sitronix = dev;
+
+ if (wmt_is_tsint(sitronix->irqgpio))
+ {
+ wmt_clr_int(sitronix->irqgpio);
+ if (wmt_is_tsirq_enable(sitronix->irqgpio))
+ {
+ wmt_disable_gpirq(sitronix->irqgpio);
+ if(!sitronix->earlysus) queue_work(sitronix->workqueue, &sitronix->read_work);
+ }
+ return IRQ_HANDLED;
+ }
+ return IRQ_NONE;
+}
+
+static void sitronix_reset(struct sitronix_data *sitronix)
+{
+
+ gpio_set_value(sitronix->rstgpio, 1);
+ mdelay(5);
+ gpio_set_value(sitronix->rstgpio, 0);
+ mdelay(5);
+ gpio_set_value(sitronix->rstgpio, 1);
+ mdelay(5);
+
+ return;
+}
+
+static int sitronix_auto_clb(struct sitronix_data *sitronix)
+{
+ return 1;
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void sitronix_early_suspend(struct early_suspend *handler)
+{
+ struct sitronix_data *sitronix = container_of(handler, struct sitronix_data, early_suspend);
+ sitronix->earlysus = 1;
+ wmt_disable_gpirq(sitronix->irqgpio);
+ return;
+}
+
+static void sitronix_late_resume(struct early_suspend *handler)
+{
+ struct sitronix_data *sitronix = container_of(handler, struct sitronix_data, early_suspend);
+
+ sitronix->earlysus = 0;
+ sitronix_reset(sitronix);
+ msleep(200);
+
+ wmt_set_gpirq(sitronix->irqgpio, IRQ_TYPE_EDGE_FALLING);
+ wmt_enable_gpirq(sitronix->irqgpio);
+
+ return;
+}
+#endif //CONFIG_HAS_EARLYSUSPEND
+
+
+static int sitronix_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct sitronix_data *sitronix = platform_get_drvdata(pdev);
+ sitronix->earlysus = 1;
+ wmt_disable_gpirq(sitronix->irqgpio);
+ return 0;
+}
+
+static int sitronix_resume(struct platform_device *pdev)
+{
+ struct sitronix_data *sitronix = platform_get_drvdata(pdev);
+
+ sitronix->earlysus = 0;
+ sitronix_reset(sitronix);
+ msleep(200);
+
+ wmt_set_gpirq(sitronix->irqgpio, IRQ_TYPE_EDGE_FALLING);
+ wmt_enable_gpirq(sitronix->irqgpio);
+ return 0;
+}
+
+static ssize_t cat_dbg(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "dbg \n");
+}
+
+static ssize_t echo_dbg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct sitronix_data *sitronix = pContext;
+
+ sscanf(buf,"%d",&sitronix->dbg);
+
+ return count;
+}
+static DEVICE_ATTR(dbg, S_IRUGO | S_IWUSR, cat_dbg, echo_dbg);
+
+static ssize_t cat_clb(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "calibrate --echo 1 >clb \n");
+}
+
+static ssize_t echo_clb(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ int cal ;
+ struct sitronix_data *sitronix = pContext;
+
+ sscanf(buf, "%d", &cal);
+ if(cal){
+ if(sitronix_auto_clb(sitronix) <= 0) printk("Auto calibrate failed.\n");
+ }
+
+ return count;
+}
+static DEVICE_ATTR(clb, S_IRUGO | S_IWUSR, cat_clb, echo_clb);
+
+static struct attribute *sitronix_attributes[] = {
+ &dev_attr_clb.attr,
+ &dev_attr_dbg.attr,
+ NULL
+};
+
+static const struct attribute_group sitronix_group = {
+ .attrs = sitronix_attributes,
+};
+
+static int sitronix_sysfs_create_group(struct sitronix_data *sitronix, const struct attribute_group *group)
+{
+ int err;
+
+ sitronix->kobj = kobject_create_and_add("wmtts", NULL) ;
+ if(!sitronix->kobj){
+ dbg_err("kobj create failed.\n");
+ return -ENOMEM;
+ }
+
+ /* Register sysfs hooks */
+ err = sysfs_create_group(sitronix->kobj, group);
+ if (err < 0){
+ kobject_del(sitronix->kobj);
+ dbg_err("Create sysfs group failed!\n");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static void sitronix_sysfs_remove_group(struct sitronix_data *sitronix, const struct attribute_group *group)
+{
+ sysfs_remove_group(sitronix->kobj, group);
+ kobject_del(sitronix->kobj);
+ return;
+}
+
+static int sitronix_probe(struct platform_device *pdev)
+{
+ int i;
+ int err = 0;
+ struct sitronix_data *sitronix = platform_get_drvdata(pdev);
+
+ INIT_WORK(&sitronix->read_work, sitronix_read_work);
+ sitronix->workqueue = create_singlethread_workqueue(sitronix->name);
+ if (!sitronix->workqueue) {
+ err = -ESRCH;
+ goto exit_create_singlethread;
+ }
+
+ err = sitronix_sysfs_create_group(sitronix, &sitronix_group);
+ if(err < 0){
+ dbg("create sysfs group failed.\n");
+ goto exit_create_group;
+ }
+
+ sitronix->input_dev = input_allocate_device();
+ if (!sitronix->input_dev) {
+ err = -ENOMEM;
+ dbg("failed to allocate input device\n");
+ goto exit_input_dev_alloc_failed;
+ }
+
+ sitronix->input_dev->name = sitronix->name;
+ sitronix->input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ set_bit(INPUT_PROP_DIRECT, sitronix->input_dev->propbit);
+
+ if (sitronix->lcd_exchg) {
+ input_set_abs_params(sitronix->input_dev,
+ ABS_MT_POSITION_X, 0, sitronix->yresl, 0, 0);
+ input_set_abs_params(sitronix->input_dev,
+ ABS_MT_POSITION_Y, 0, sitronix->xresl, 0, 0);
+ } else {
+ input_set_abs_params(sitronix->input_dev,
+ ABS_MT_POSITION_X, 0, sitronix->xresl, 0, 0);
+ input_set_abs_params(sitronix->input_dev,
+ ABS_MT_POSITION_Y, 0, sitronix->yresl, 0, 0);
+ }
+ input_set_abs_params(sitronix->input_dev,
+ ABS_MT_TRACKING_ID, 0, 20, 0, 0);
+#ifdef TOUCH_KEY
+ for (i = 0; i <NUM_KEYS; i++)
+ set_bit(virtual_keys[i], sitronix->input_dev->keybit);
+
+ sitronix->input_dev->keycode = virtual_keys;
+ sitronix->input_dev->keycodesize = sizeof(unsigned int);
+ sitronix->input_dev->keycodemax = NUM_KEYS;
+#endif
+
+ err = input_register_device(sitronix->input_dev);
+ if (err) {
+ dbg_err("sitronix_ts_probe: failed to register input device.\n");
+ goto exit_input_register_device_failed;
+ }
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ sitronix->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+ sitronix->early_suspend.suspend = sitronix_early_suspend;
+ sitronix->early_suspend.resume = sitronix_late_resume;
+ register_early_suspend(&sitronix->early_suspend);
+#endif
+
+ if(request_irq(sitronix->irq, sitronix_isr_handler, IRQF_SHARED, sitronix->name, sitronix) < 0){
+ dbg_err("Could not allocate irq for ts_sitronix !\n");
+ err = -1;
+ goto exit_register_irq;
+ }
+
+ wmt_set_gpirq(sitronix->irqgpio, IRQ_TYPE_EDGE_FALLING);
+ wmt_enable_gpirq(sitronix->irqgpio);
+ sitronix_reset(sitronix);
+ msleep(200);
+#ifdef SITRONIX_DEBUG
+ sitronix_get_device_info(sitronix);
+#endif
+
+ return 0;
+
+exit_register_irq:
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&sitronix->early_suspend);
+#endif
+exit_input_register_device_failed:
+ input_free_device(sitronix->input_dev);
+exit_input_dev_alloc_failed:
+ sitronix_sysfs_remove_group(sitronix, &sitronix_group);
+exit_create_group:
+ cancel_work_sync(&sitronix->read_work);
+ destroy_workqueue(sitronix->workqueue);
+exit_create_singlethread:
+ //kfree(sitronix);
+ return err;
+}
+
+static int sitronix_remove(struct platform_device *pdev)
+{
+ struct sitronix_data *sitronix = platform_get_drvdata(pdev);
+
+ cancel_work_sync(&sitronix->read_work);
+ flush_workqueue(sitronix->workqueue);
+ destroy_workqueue(sitronix->workqueue);
+
+ free_irq(sitronix->irq, sitronix);
+ wmt_disable_gpirq(sitronix->irqgpio);
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&sitronix->early_suspend);
+#endif
+ input_unregister_device(sitronix->input_dev);
+
+ sitronix_sysfs_remove_group(sitronix, &sitronix_group);
+ //kfree(sitronix);
+
+ dbg("remove...\n");
+ return 0;
+}
+
+static void sitronix_release(struct device *device)
+{
+ return;
+}
+
+static struct platform_device sitronix_device = {
+ .name = DEV_SITRONIX,
+ .id = 0,
+ .dev = {.release = sitronix_release},
+};
+
+static struct platform_driver sitronix_driver = {
+ .driver = {
+ .name = DEV_SITRONIX,
+ .owner = THIS_MODULE,
+ },
+ .probe = sitronix_probe,
+ .remove = sitronix_remove,
+ .suspend = sitronix_suspend,
+ .resume = sitronix_resume,
+};
+
+static int check_touch_env(struct sitronix_data *sitronix)
+{
+ int len = 96;
+ int Enable;
+ char retval[96] = {0};
+ char *p=NULL;
+ int ret;
+
+ // Get u-boot parameter
+ if(wmt_getsyspara("wmt.io.touch", retval, &len)) return -EIO;
+
+ sscanf(retval,"%d:",&Enable);
+ //check touch enable
+ if(Enable == 0) return -ENODEV;
+
+ p = strchr(retval,':');
+ p++;
+
+ if(strncmp(p,"st1536",6)) return -ENODEV;
+
+ sitronix->name = DEV_SITRONIX;
+ sitronix->addr = SITRONIX_ADDR;
+ p = strchr(p,':');
+ p++;
+ sscanf(p,"%d:%d:%d:%d:%d:%d:%d",
+ &sitronix->xresl, &sitronix->yresl, &sitronix->irqgpio, &sitronix->rstgpio, &sitronix->swap, &sitronix->xch, &sitronix->ych);
+
+ sitronix->irq = IRQ_GPIO;
+ printk("%s reslx=%d, resly=%d, irqgpio_num=%d, rstgpio_num=%d, XYswap=%d, Xdirch=%d, Ydirch=%d\n", sitronix->name,
+ sitronix->xresl, sitronix->yresl, sitronix->irqgpio, sitronix->rstgpio, sitronix->swap, sitronix->xch, sitronix->ych);
+
+ sitronix->penup = 1;
+
+ memset(retval,0,sizeof(retval));
+ ret = wmt_getsyspara("wmt.display.fb0", retval, &len);
+ if (!ret) {
+ int tmp[6];
+ p = retval;
+ sscanf(p, "%d:[%d:%d:%d:%d:%d", &tmp[0], &tmp[1], &tmp[2], &tmp[3], &tmp[4], &tmp[5]);
+ if (tmp[4] > tmp[5])
+ sitronix->lcd_exchg = 1;
+ }
+
+ return 0;
+}
+
+struct i2c_board_info ts_i2c_board_info = {
+ .type = DEV_SITRONIX,
+ .flags = 0x00,
+ .addr = SITRONIX_ADDR,
+ .platform_data = NULL,
+ .archdata = NULL,
+ .irq = -1,
+};
+
+static int ts_i2c_register_device (void)
+{
+ struct i2c_board_info *ts_i2c_bi;
+ struct i2c_adapter *adapter = NULL;
+ //struct i2c_client *client = NULL;
+
+ ts_i2c_bi = &ts_i2c_board_info;
+ adapter = i2c_get_adapter(I2C_BUS1);/*in bus 1*/
+
+ if (NULL == adapter) {
+ printk("can not get i2c adapter, client address error\n");
+ return -1;
+ }
+ l_client = i2c_new_device(adapter, ts_i2c_bi);
+ if (l_client == NULL) {
+ printk("allocate i2c client failed\n");
+ return -1;
+ }
+ i2c_put_adapter(adapter);
+ return 0;
+}
+
+static void ts_i2c_unregister_device(void)
+{
+ if (l_client != NULL)
+ {
+ i2c_unregister_device(l_client);
+ l_client = NULL;
+ }
+}
+
+
+static int __init sitronix_init(void)
+{
+ int ret = -ENOMEM;
+ struct sitronix_data *sitronix=NULL;
+
+ if (ts_i2c_register_device()<0)
+ {
+ dbg("Error to run ts_i2c_register_device()!\n");
+ return -1;
+ }
+
+ sitronix = kzalloc(sizeof(struct sitronix_data), GFP_KERNEL);
+ if(!sitronix){
+ dbg_err("mem alloc failed.\n");
+ return -ENOMEM;
+ }
+
+ pContext = sitronix;
+ ret = check_touch_env(sitronix);
+ if(ret < 0)
+ goto exit_free_mem;
+
+ ret = gpio_request(sitronix->irqgpio, "ts_irq");
+ if (ret < 0) {
+ printk("gpio(%d) touchscreen irq request fail\n", sitronix->irqgpio);
+ goto exit_free_mem;
+ }
+
+ ret = gpio_request(sitronix->rstgpio, "ts_rst");
+ if (ret < 0) {
+ printk("gpio(%d) touchscreen reset request fail\n", sitronix->rstgpio);
+ goto exit_free_irqgpio;
+ }
+ gpio_direction_output(sitronix->rstgpio, 1);
+
+
+ ret = platform_device_register(&sitronix_device);
+ if(ret){
+ dbg_err("register platform drivver failed!\n");
+ goto exit_free_gpio;
+ }
+ platform_set_drvdata(&sitronix_device, sitronix);
+
+ ret = platform_driver_register(&sitronix_driver);
+ if(ret){
+ dbg_err("register platform device failed!\n");
+ goto exit_unregister_pdev;
+ }
+
+ return ret;
+
+exit_unregister_pdev:
+ platform_device_unregister(&sitronix_device);
+exit_free_gpio:
+
+ gpio_free(sitronix->rstgpio);
+exit_free_irqgpio:
+ gpio_free(sitronix->irqgpio);
+
+exit_free_mem:
+ kfree(sitronix);
+ pContext = NULL;
+ ts_i2c_unregister_device();
+ return ret;
+}
+
+static void sitronix_exit(void)
+{
+ struct sitronix_data *sitronix;
+
+ if(!pContext) return;
+
+ sitronix = pContext;
+
+ gpio_free(sitronix->irqgpio);
+ gpio_free(sitronix->rstgpio);
+
+
+ platform_driver_unregister(&sitronix_driver);
+ platform_device_unregister(&sitronix_device);
+ kfree(pContext);
+
+ ts_i2c_unregister_device();
+ return;
+}
+
+late_initcall(sitronix_init);
+module_exit(sitronix_exit);
+
+MODULE_DESCRIPTION("Sitronix Multi-Touch Driver");
+MODULE_LICENSE("GPL");
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/sitronix/sitronix_i2c.h b/ANDROID_3.4.5/drivers/input/touchscreen/sitronix/sitronix_i2c.h
new file mode 100755
index 00000000..8d3df91d
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/sitronix/sitronix_i2c.h
@@ -0,0 +1,137 @@
+#ifndef _LINUX_SIT_I2C_H
+#define _LINUX_SIT_I2C_H
+
+#define SITRONIX_ADDR 0x60
+#define DEV_SITRONIX "touch_sitronix"
+#define SITRONIX_MAX_SUPPORTED_POINT 5
+#define TOUCH_KEY
+
+struct sitronix_data {
+ u16 addr;
+ const char *name;
+
+ struct input_dev *input_dev;
+ struct work_struct read_work;
+ struct workqueue_struct *workqueue;
+ struct kobject *kobj;
+ #ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend early_suspend;
+#endif
+ int earlysus;
+
+ int xresl;
+ int yresl;
+
+ int irq;
+ int irqgpio;
+
+ int rstgpio;
+
+ int xch;
+ int ych;
+ int swap;
+ int lcd_exchg;
+
+ int penup;
+ int dbg;
+#ifdef TOUCH_KEY
+ //int tkey_pressed;
+ int tkey_idx;
+#endif
+ u8 fw_revision[4];
+ int resolution_x;
+ int resolution_y;
+ u8 max_touches;
+ u8 touch_protocol_type;
+ u8 chip_id;
+
+ u8 Num_X;
+ u8 Num_Y;
+ u8 sensing_mode;
+ u8 pixel_length;
+};
+
+typedef enum{
+ FIRMWARE_VERSION,
+ STATUS_REG,
+ DEVICE_CONTROL_REG,
+ TIMEOUT_TO_IDLE_REG,
+ XY_RESOLUTION_HIGH,
+ X_RESOLUTION_LOW,
+ Y_RESOLUTION_LOW,
+ FIRMWARE_REVISION_3 = 0x0C,
+ FIRMWARE_REVISION_2,
+ FIRMWARE_REVISION_1,
+ FIRMWARE_REVISION_0,
+ FINGERS,
+ KEYS_REG,
+ XY0_COORD_H,
+ X0_COORD_L,
+ Y0_COORD_L,
+ I2C_PROTOCOL = 0x3E,
+ MAX_NUM_TOUCHES,
+ DATA_0_HIGH,
+ DATA_0_LOW,
+ CHIP_ID = 0xF4,
+
+ PAGE_REG = 0xff,
+}RegisterOffset;
+
+
+typedef enum{
+ XY_COORD_H,
+ X_COORD_L,
+ Y_COORD_L,
+ PIXEL_DATA_LENGTH_B,
+ PIXEL_DATA_LENGTH_A,
+}PIXEL_DATA_FORMAT;
+
+#define X_RES_H_SHFT 4
+#define X_RES_H_BMSK 0xf
+#define Y_RES_H_SHFT 0
+#define Y_RES_H_BMSK 0xf
+#define FINGERS_SHFT 0
+#define FINGERS_BMSK 0xf
+#define X_COORD_VALID_SHFT 7
+#define X_COORD_VALID_BMSK 0x1
+#define X_COORD_H_SHFT 4
+#define X_COORD_H_BMSK 0x7
+#define Y_COORD_H_SHFT 0
+#define Y_COORD_H_BMSK 0x7
+
+typedef enum{
+ SITRONIX_RESERVED_TYPE_0,
+ SITRONIX_A_TYPE,
+ SITRONIX_B_TYPE,
+}I2C_PROTOCOL_TYPE;
+
+#define I2C_PROTOCOL_SHFT 0x0
+#define I2C_PROTOCOL_BMSK 0x3
+
+typedef enum{
+ SENSING_BOTH,
+ SENSING_X_ONLY,
+ SENSING_Y_ONLY,
+ SENSING_BOTH_NOT,
+}ONE_D_SENSING_CONTROL_MODE;
+
+#define ONE_D_SENSING_CONTROL_SHFT 0x2
+#define ONE_D_SENSING_CONTROL_BMSK 0x3
+
+extern int wmt_setsyspara(char *varname, unsigned char *varval);
+extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
+//extern int wmt_i2c_xfer_continue_if_4(struct i2c_msg *msg, unsigned int num,int bus_id);
+
+//#define SITRONIX_DEBUG
+
+#undef dbg
+#ifdef SITRONIX_DEBUG
+ #define dbg(fmt,args...) printk("DBG:%s_%d:"fmt,__FUNCTION__,__LINE__,##args)
+#else
+ #define dbg(fmt,args...)
+#endif
+
+#undef dbg_err
+#define dbg_err(fmt,args...) printk("ERR:%s_%d:"fmt,__FUNCTION__,__LINE__,##args)
+
+#endif /* _LINUX_SIS_I2C_H */
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/ssd253x_ts/Kconfig b/ANDROID_3.4.5/drivers/input/touchscreen/ssd253x_ts/Kconfig
new file mode 100755
index 00000000..a5d9aa73
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/ssd253x_ts/Kconfig
@@ -0,0 +1,16 @@
+#
+# SSD253x capacity touch screen driver configuration
+#
+config TOUCHSCREEN_SSD253X
+ tristate "SSD253X I2C Touchscreen Input Driver Support"
+ depends on ARCH_WMT
+ default y
+ help
+ Say Y here if you have an WMT based board with touchscreen
+ attached to it.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called s_wmt_ts_ssd253x.
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/ssd253x_ts/Makefile b/ANDROID_3.4.5/drivers/input/touchscreen/ssd253x_ts/Makefile
new file mode 100755
index 00000000..d78c8466
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/ssd253x_ts/Makefile
@@ -0,0 +1,32 @@
+KERNELDIR=../../../../
+CROSS = arm_1103_le-
+CC= $(CROSS)gcc
+LD= $(CROSS)ld
+STRIP = $(CROSS)strip
+
+DEBUG = n
+
+# Add your debugging flag (or not) to EXTRA_CFLAGS
+ifeq ($(DEBUG),y)
+# DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+DEBFLAGS = -O0 -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+
+else
+ DEBFLAGS = -O2 -Wall
+endif
+
+EXTRA_CFLAGS += $(DEBFLAGS)
+
+
+MY_MODULE_NAME=s_wmt_ts_ssd253x
+
+obj-m := $(MY_MODULE_NAME).o
+$(MY_MODULE_NAME)-objs := ssd253x-ts.o wmt_ts.o
+
+default:
+ $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules
+ $(STRIP) --strip-debug $(MY_MODULE_NAME).ko
+ rm -rf *.o *~ core .depend .*.cmd *.mod.c .tmp_versions *.order *.symvers
+
+clean:
+ rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.order *.symvers
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/ssd253x_ts/ssd253x-ts.c b/ANDROID_3.4.5/drivers/input/touchscreen/ssd253x_ts/ssd253x-ts.c
new file mode 100755
index 00000000..c02392cb
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/ssd253x_ts/ssd253x-ts.c
@@ -0,0 +1,1827 @@
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+//#include <asm/gpio.h>
+#include <asm/irq.h>
+#include <linux/irq.h>
+#include <asm/io.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+#include <mach/hardware.h>
+#include <linux/platform_device.h>
+#include <linux/suspend.h>
+#include <linux/slab.h>
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif /* CONFIG_HAS_EARLYSUSPEND */
+
+
+#include "ssd253x-ts.h"
+#include "wmt_ts.h"
+
+//#define CONFIG_TOUCHSCREEN_SSL_DEBUG
+#undef CONFIG_TOUCHSCREEN_SSL_DEBUG
+
+#define DEVICE_ID_REG 2
+#define VERSION_ID_REG 3
+#define AUTO_INIT_RST_REG 68
+#define EVENT_STATUS 121
+#define EVENT_MSK_REG 122
+#define IRQ_MSK_REG 123
+#define FINGER01_REG 124
+#define EVENT_STACK 128
+#define EVENT_FIFO_SCLR 135
+#define TIMESTAMP_REG 136
+#define SELFCAP_STATUS_REG 185
+
+#define ON_TOUCH_INT INT_EI11 //GPIO :set the interrupt
+#define DEVICE_NAME "touch_ssd253x"
+#define SSD253X_I2C_ADDR 0x48 //0x48
+
+// SSD2533 Setting
+// Touch Panel Example
+static struct ChipSetting* ssd253xcfgTable = NULL;
+static int l_cfglen = 0;
+
+static struct ChipSetting ssd253xcfgTable_default[]={
+{2,0x06,0x1B,0x28},
+{2,0xd7,0x00,0x00},
+{2,0xd8,0x00,0x07},
+{2,0xdb,0x00,0x01},
+{2,0x30,0x03,0x08},
+{2,0x34,0xd4,0x1e},
+{2,0x57,0x00,0x06},
+{2,0x40,0x00,0xc8},
+{2,0x41,0x00,0x30},
+{2,0x42,0x00,0xc0},
+{2,0x43,0x00,0x30},
+{2,0x44,0x00,0xc0},
+{2,0x45,0x00,0xc0},
+{2,0x46,0x00,0x0f},
+{2,0x5f,0x00,0x00},
+{2,0x2d,0x00,0x00},
+{2,0x66,0x1F,0x38},
+{2,0x67,0x1c,0x92},
+{2,0x25,0x00,0x02},
+};
+
+
+// For SSD2533 Bug Version Only //
+//#define SSD2533FIXEDCODE
+ struct ChipSetting ssd253xcfgTable1[]={
+{ 1, 0xA4, 0x00, 0x00}, //MCU prescaler default=01
+{ 1, 0xD4, 0x08, 0x00}, //Dummy Code
+{ 1, 0xD4, 0x08, 0x00}, //Set Osc frequency default=8, range 0 to F
+};
+
+ struct ChipSetting Reset[]={
+{ 0, 0x04, 0x00, 0x00}, // SSD2533
+};
+
+ struct ChipSetting Resume[]={
+{ 0, 0x04, 0x00, 0x00}, // SSD2533
+{ 1, 0x25, 0x12, 0x00}, // Set Operation Mode //Set from int setting
+};
+
+ struct ChipSetting Suspend[] ={
+{ 1, 0x25, 0x00, 0x00}, // Set Operation Mode
+{ 0, 0x05, 0x00, 0x00}, // SSD2533
+};
+
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void ssd253x_ts_early_suspend(struct early_suspend *h);
+static void ssd253x_ts_late_resume(struct early_suspend *h);
+#endif /* CONFIG_HAS_EARLYSUSPEND */
+
+static irqreturn_t ssd253x_ts_isr(int irq, void *dev_id);
+static enum hrtimer_restart ssd253x_ts_timer(struct hrtimer *timer);
+//extern int wmt_i2c_xfer_continue_if_4(struct i2c_msg *msg, unsigned int num,int bus_id);
+
+
+static int SSDS53X_SCREEN_MAX_X = 800;
+static int SSDS53X_SCREEN_MAX_Y = 480;
+
+
+
+enum{
+ IC_SSD2533 = 1,
+ IC_SSD2543,
+ IC_SSD2531
+};
+
+static int ic_flag;
+
+static struct workqueue_struct *ssd253x_wq;
+
+int Ssd_Timer1,Ssd_Timer2,Ssd_Timer_flag;
+
+struct ssl_ts_priv {
+ struct input_dev *input;
+ struct hrtimer timer;
+ struct work_struct ssl_work;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend early_suspend;
+#endif
+
+ int irq;
+ int use_irq;
+ int FingerNo;
+ int earlysus;
+
+ int FingerX[FINGERNO];
+ int FingerY[FINGERNO];
+ int FingerP[FINGERNO];
+
+ int Resolution;
+ int EventStatus;
+ int FingerDetect;
+
+ int sFingerX[FINGERNO];
+ int sFingerY[FINGERNO];
+ int pFingerX[FINGERNO];
+ int pFingerY[FINGERNO];
+};
+
+static struct ssl_ts_priv* l_ts = NULL;
+struct wmtts_device ssd253x_tsdev;
+static DECLARE_WAIT_QUEUE_HEAD(ts_penup_wait_queue);
+
+#define SD_INIT
+#ifdef SD_INIT
+#define TP_CHR "tp_chr"
+
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <asm/uaccess.h>
+
+static long tp_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
+static int tp_open(struct inode *inode, struct file *file);
+static int tp_release(struct inode *inode, struct file *file);
+static ssize_t tp_read(struct file *file, char __user *buf, size_t count,loff_t *offset);
+static ssize_t tp_write(struct file *file, const char __user *buf,size_t count, loff_t *offset);
+
+//void InitFromSD(struct i2c_client *client);
+
+//struct ChipSetting _ssd253xcfgTable[200];
+//int sd_init_size=0;
+
+
+//struct i2c_client *g_tp_client;
+
+#endif
+
+
+
+static int ReadRegister(/*struct i2c_client *client,*/uint8_t reg,int ByteNo)
+{
+ unsigned char buf[4];
+ struct i2c_msg msg[2];
+ int ret;
+ struct i2c_client* client = ts_get_i2c_client();
+
+ memset(buf, 0xFF, sizeof(buf));
+ msg[0].addr = SSD253X_I2C_ADDR;
+ msg[0].flags = 0 | I2C_M_NOSTART;
+ msg[0].len = 1;
+ msg[0].buf = &reg;
+
+ msg[1].addr = SSD253X_I2C_ADDR;
+ msg[1].flags = I2C_M_RD;
+ msg[1].len = ByteNo;
+ msg[1].buf = buf;
+
+ ret = i2c_transfer(client->adapter, msg, 2);
+ if (ret <= 0)
+ {
+ printk("read the address (0x%x) of the ssd253x fail, ret=%d.\n", reg, ret);
+ return -1;
+ }
+
+ if(ByteNo==1) return (int)((unsigned int)buf[0]<<0);
+ if(ByteNo==2) return (int)((unsigned int)buf[1]<<0)|((unsigned int)buf[0]<<8);
+ if(ByteNo==3) return (int)((unsigned int)buf[2]<<0)|((unsigned int)buf[1]<<8)|((unsigned int)buf[0]<<16);
+ if(ByteNo==4) return (int)((unsigned int)buf[3]<<0)|((unsigned int)buf[2]<<8)|((unsigned int)buf[1]<<16)|(buf[0]<<24);
+ return 0;
+}
+
+static int WriteRegister(/*struct i2c_client *client,*/uint8_t Reg,unsigned char Data1,unsigned char Data2,int ByteNo)
+{
+ struct i2c_msg msg;
+ unsigned char buf[4];
+ int ret;
+ struct i2c_client* client = ts_get_i2c_client();
+
+ buf[0]=Reg;
+ buf[1]=Data1;
+ buf[2]=Data2;
+ buf[3]=0;
+
+ msg.addr = SSD253X_I2C_ADDR;
+ msg.flags = 0;
+ msg.len = ByteNo+1;
+ msg.buf = (char *)buf;
+ ret = i2c_transfer(client->adapter, &msg, 1);
+ if (ret <= 0)
+ {
+ printk(KERN_ERR "write the address (0x%x) of the ssd25xx fail, ret=%d.\n", buf[0], ret);
+ return -1;
+ }
+ return 0;
+
+}
+
+int SSD253xdeviceInit1(void)
+{
+#ifdef SSD2533FIXEDCODE
+ int i;
+ mdelay(600); //SSD2533 ESD2 EEPROM VERSION
+ for(i=0;i<sizeof(ssd253xcfgTable1)/sizeof(ssd253xcfgTable1[0]);i++)
+ {
+ if (WriteRegister(ssd253xcfgTable1[i].Reg,
+ ssd253xcfgTable1[i].Data1,ssd253xcfgTable1[i].Data2,
+ ssd253xcfgTable1[i].No))
+ {
+ return -1;
+ }
+ }
+#endif
+ return 0;
+}
+
+int SSD253xdeviceInit(void)
+{
+ int i;
+
+ for(i=0;i<l_cfglen/*sizeof(ssd253xcfgTable)/sizeof(ssd253xcfgTable[0])*/;i++)
+ {
+ if (WriteRegister(ssd253xcfgTable[i].Reg,
+ ssd253xcfgTable[i].Data1,ssd253xcfgTable[i].Data2,
+ ssd253xcfgTable[i].No))
+ {
+ return -1;
+ }
+ if (0 == i)
+ {
+ msleep(300);
+ }
+ }
+ msleep(300);
+ return 0;
+}
+
+int deviceReset(void)
+{
+ int i;
+
+ i = 0;//just for remove warning message
+ wmt_rst_output(1);
+ mdelay(5);
+ wmt_rst_output(0);
+ mdelay(10);
+ wmt_rst_output(1);
+ msleep(200);
+
+ //if(ic_flag == IC_SSD2533){
+ for(i=0;i<sizeof(Reset)/sizeof(Reset[0]);i++)
+ {
+ if (WriteRegister(Reset[i].Reg,
+ Reset[i].Data1,Reset[i].Data2,
+ Reset[i].No))
+ {
+ return -1;
+ }
+ }
+ //}
+
+ mdelay(100);
+ if (SSD253xdeviceInit1())
+ {
+ return -1;
+ }
+ return 0;
+}
+
+int deviceResume(void)
+{
+ int i;
+ for(i=0;i<sizeof(Resume)/sizeof(Resume[0]);i++)
+ {
+ if (WriteRegister(Resume[i].Reg,
+ Resume[i].Data1,Resume[i].Data2,
+ Resume[i].No))
+ {
+ return -1;
+ }
+ mdelay(100);
+ }
+ return 0;
+}
+
+int deviceSuspend(void)
+{
+ int i;
+ //int timeout=10;
+ //int status;
+
+ for(i=0;i<sizeof(Suspend)/sizeof(Suspend[0]);i++)
+ {
+ if (WriteRegister(Suspend[i].Reg,
+ Suspend[i].Data1,Suspend[i].Data2,
+ Suspend[i].No))
+ {
+ return -1;
+ }
+ mdelay(100);
+ }
+ return 0;
+}
+
+#define Mode RunningAverageMode
+#define Dist RunningAverageDist
+void RunningAverage(unsigned short *xpos,unsigned short *ypos,int No,struct ssl_ts_priv *ssl_priv)
+{
+ int FilterMode[4][2]={{0,8},{5,3},{6,2},{7,1}};
+ int dx,dy;
+ int X,Y;
+
+ X=*xpos;
+ Y=*ypos;
+ if((ssl_priv->pFingerX[No]!=0x0FFF)&&(X!=0x0FFF))
+ {
+ dx=abs(ssl_priv->pFingerX[No]-X);
+ dy=abs(ssl_priv->pFingerY[No]-Y);
+ if(dx+dy<Dist*64)
+ {
+ ssl_priv->pFingerX[No]=(FilterMode[Mode][0]*ssl_priv->pFingerX[No]+FilterMode[Mode][1]*X)/8;
+ ssl_priv->pFingerY[No]=(FilterMode[Mode][0]*ssl_priv->pFingerY[No]+FilterMode[Mode][1]*Y)/8;
+ }
+ else
+ {
+ ssl_priv->pFingerX[No]=X;
+ ssl_priv->pFingerY[No]=Y;
+ }
+ }
+ else
+ {
+ ssl_priv->pFingerX[No]=X;
+ ssl_priv->pFingerY[No]=Y;
+ }
+ *xpos=ssl_priv->pFingerX[No];
+ *ypos=ssl_priv->pFingerY[No];
+}
+
+void FingerCheckSwap(int *FingerX,int *FingerY,int *FingerP,int FingerNo,int *sFingerX,int *sFingerY)
+{
+ int i,j;
+ int index1,index2;
+ int Vx,Vy;
+ int Ux,Uy;
+ int R1x,R1y;
+ int R2x,R2y;
+ for(i=0;i<FingerNo;i++)
+ {
+ index1=i;
+ if( FingerX[index1]!=0xFFF)
+ if(sFingerX[index1]!=0xFFF)
+ {
+ for(j=i+1;j<FingerNo+3;j++)
+ {
+ index2=j%FingerNo;
+ if( FingerX[index2]!=0xFFF)
+ if(sFingerX[index2]!=0xFFF)
+ {
+ Ux=sFingerX[index1]-sFingerX[index2];
+ Uy=sFingerY[index1]-sFingerY[index2];
+ Vx= FingerX[index1]- FingerX[index2];
+ Vy= FingerY[index1]- FingerY[index2];
+
+ R1x=Ux-Vx;
+ R1y=Uy-Vy;
+ R2x=Ux+Vx;
+ R2y=Uy+Vy;
+
+ R1x=R1x*R1x;
+ R1y=R1y*R1y;
+ R2x=R2x*R2x;
+ R2y=R2y*R2y;
+
+ if(R1x+R1y>R2x+R2y)
+ {
+ Ux=FingerX[index1];
+ Uy=FingerY[index1];
+ Vx=FingerP[index1];
+
+ FingerX[index1]=FingerX[index2];
+ FingerY[index1]=FingerY[index2];
+ FingerP[index1]=FingerP[index2];
+
+ FingerX[index2]=Ux;
+ FingerY[index2]=Uy;
+ FingerP[index2]=Vx;
+ }
+ break;
+ }
+ }
+ }
+ }
+ for(i=0;i<FingerNo;i++)
+ {
+ sFingerX[i]=FingerX[i];
+ sFingerY[i]=FingerY[i];
+ }
+}
+
+#ifdef USE_TOUCH_KEY
+static void ssd2533_ts_send_keyevent(struct ssl_ts_priv *ssl_priv,u8 btn_status, int downup)
+{
+
+ switch(btn_status & 0x0f)
+ {
+ case 0x01:
+ input_report_key(ssl_priv->input, KEY_SEARCH, downup);
+ break;
+ case 0x02:
+ input_report_key(ssl_priv->input, KEY_BACK, downup);
+ break;
+ case 0x04:
+ input_report_key(ssl_priv->input, KEY_HOME, downup);
+ break;
+ case 0x08:
+ input_report_key(ssl_priv->input, KEY_MENU, downup);
+ break;
+ default:
+ break;
+ }
+ dbg("send %x %x\n", btn_status, downup);
+}
+#endif
+
+// for ssd2533(no test)
+static int ssd253x_ts_cut_edge0(unsigned short pos,unsigned short x_y)
+{
+ u8 cut_value = 26; //26 cut_value < 32
+ if(pos == 0xfff)
+ {
+ return pos;
+ }
+ //printk("X: rude data %d\n",pos);
+ if(x_y) //xpos
+ {
+
+ if(pos < 16)
+ pos = cut_value + pos*(48 - cut_value) / 16;
+ else if(pos > (XPOS_MAX - 16) )
+ pos = XPOS_MAX + 16 + (pos - (XPOS_MAX -16))*(48 - cut_value) / 16;
+ else
+ pos = pos + 32;
+
+ pos = SSDS53X_SCREEN_MAX_X * pos / (DRIVENO * 64);
+ //printk("X: changed data %d\n",pos);
+ return pos;
+ }
+ else //ypos
+ {
+ if(pos < 16)
+ pos = cut_value + pos*(48 - cut_value) / 16;
+ else if(pos > (YPOS_MAX - 16) )
+ pos = YPOS_MAX + 16 + (pos - (YPOS_MAX -16))*(48 - cut_value) / 16;
+ else
+ pos = pos + 32;
+ //printk("Y: rude data %d\n",pos);
+ pos = SSDS53X_SCREEN_MAX_Y* pos / (SENSENO * 64);
+ //printk("Y: changed data %d\n",pos);
+ return pos;
+ }
+
+
+}
+
+// for ssd2532
+static int ssd253x_ts_cut_edge1(unsigned short pos,unsigned short x_y)
+{
+ u8 cut_value = 15; //cut_value < 32
+
+ if(pos == 0xfff){
+ return pos;
+ }
+
+ if(x_y){ //xpos 64-->96 //MAX=896
+ pos = pos + cut_value;//????????Ôµ
+ pos = SSDS53X_SCREEN_MAX_X * pos / (790+cut_value*2);//SSDS53X_SCREEN_MAX_X?????Ò±?Ôµ
+ return pos;
+ }else{ //ypos //MAX=576
+ pos = pos + cut_value;//?????ϱ?Ե
+ pos = SSDS53X_SCREEN_MAX_Y* pos / (470+cut_value*2);//SSDS53X_SCREEN_MAX_Y?????±?Ե
+ return pos;
+ }
+}
+
+// for ssd2532,8" ssd253x_pydctp80a1.ts
+// x_y:1--x,0--y
+static int ssd253x_ts_cut_edge2(unsigned short pos,unsigned short x_y)
+{
+ int tpos;
+
+ if (pos == 0xfff){
+ return pos;
+ }
+
+ tpos = pos;
+ if (x_y)
+ {
+ if (tpos<20)
+ {
+ tpos= tpos+18;
+ } else if (tpos>585)
+ {
+ tpos = tpos-18;
+ } else {
+ tpos = (tpos-20)*565/575+30;
+ }
+ pos = tpos;
+ return pos;
+ } else {
+ if (tpos <10)
+ {
+ tpos = tpos+10;
+ } else if (tpos >795)
+ {
+ tpos = 795;
+ } else {
+ tpos = (tpos-10)*775/785+20;
+ }
+ pos = tpos;
+ return pos;
+ }
+
+}
+// for ssd2532
+static int ssd253x_ts_cut_edge3(unsigned short pos,unsigned short x_y)
+{
+ u8 cut_value = 15;
+
+ if(pos == 0xfff){
+ return pos;
+ }
+
+ if(x_y){
+ pos = pos + cut_value;
+ pos = SSDS53X_SCREEN_MAX_X * pos / (896+cut_value*2);
+ return pos;
+ }else{
+ pos = pos + cut_value;
+ pos = SSDS53X_SCREEN_MAX_Y* pos / (576+cut_value*2);
+ return pos;
+ }
+}
+
+// for jun feng TP
+static int ssd253x_ts_cut_edge4(unsigned short pos,unsigned short x_y)
+{
+ unsigned short Cut_Edge_XLeft[64]={
+ 0x0008,0x0009,0x000B,0x000C,0x000D,0x000E,0x0010,0x0011,
+ 0x0012,0x0013,0x0015,0x0016,0x0017,0x0018,0x001A,0x001B,
+ 0x001C,0x001D,0x001F,0x0020,0x0021,0x0022,0x0024,0x0025,
+ 0x0026,0x0026,0x0027,0x0028,0x0029,0x002A,0x002B,0x002C,
+ 0x002C,0x002D,0x002E,0x002F,0x0030,0x0031,0x0032,0x0032,
+ 0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0038,0x0039,
+ 0x003A,0x003B,0x003C,0x003D,0x003E,0x003E,0x003F,0x0040,
+ 0x0041,0x0042,0x0043,0x0044,0x0044,0x0045,0x0046,0x0047
+ };
+
+ unsigned short Cut_Edge_XRight[64]={
+ 0x0318,0x0317,0x0315,0x0314,0x0313,0x0312,0x0310,0x030F,
+ 0x030E,0x030D,0x030B,0x030A,0x0309,0x0308,0x0306,0x0305,
+ 0x0304,0x0303,0x0301,0x0300,0x02FF,0x02FE,0x02FC,0x02FB,
+ 0x02FA,0x02FA,0x02F9,0x02F8,0x02F7,0x02F6,0x02F5,0x02F4,
+ 0x02F4,0x02F3,0x02F2,0x02F1,0x02F0,0x02EF,0x02EE,0x02EE,
+ 0x02ED,0x02EC,0x02EB,0x02EA,0x02E9,0x02E8,0x02E8,0x02E7,
+ 0x02E6,0x02E5,0x02E4,0x02E3,0x02E2,0x02E2,0x02E1,0x02E0,
+ 0x02DF,0x02DE,0x02DD,0x02DC,0x02DC,0x02DB,0x02DA,0x02D9
+ };
+
+ unsigned short Cut_Edge_YUp[64]={
+ 0x0006,0x0007,0x0008,0x000A,0x000B,0x000C,0x000D,0x000F,
+ 0x0010,0x0011,0x0012,0x0014,0x0015,0x0016,0x0017,0x0018,
+ 0x001A,0x001B,0x001C,0x001D,0x001F,0x0020,0x0021,0x0022,
+ 0x0022,0x0023,0x0024,0x0025,0x0025,0x0026,0x0027,0x0028,
+ 0x0029,0x0029,0x002A,0x002B,0x002C,0x002C,0x002D,0x002E,
+ 0x002F,0x0030,0x0030,0x0031,0x0032,0x0033,0x0033,0x0034,
+ 0x0035,0x0036,0x0037,0x0037,0x0038,0x0039,0x003A,0x003A,
+ 0x003B,0x003C,0x003D,0x003E,0x003E,0x003F,0x0040,0x0041
+ };
+
+ unsigned short Cut_Edge_YDown[64]={
+ 0x01DA,0x01D9,0x01D8,0x01D6,0x01D5,0x01D4,0x01D3,0x01D1,
+ 0x01D0,0x01CF,0x01CE,0x01CC,0x01CB,0x01CA,0x01C9,0x01C8,
+ 0x01C6,0x01C5,0x01C4,0x01C3,0x01C1,0x01C0,0x01BF,0x01BE,
+ 0x01BE,0x01BD,0x01BC,0x01BB,0x01BB,0x01BA,0x01B9,0x01B8,
+ 0x01B7,0x01B7,0x01B6,0x01B5,0x01B4,0x01B4,0x01B3,0x01B2,
+ 0x01B1,0x01B0,0x01B0,0x01AF,0x01AE,0x01AD,0x01AD,0x01AC,
+ 0x01AB,0x01AA,0x01A9,0x01A9,0x01A8,0x01A7,0x01A6,0x01A6,
+ 0x01A5,0x01A4,0x01A3,0x01A2,0x01A2,0x01A1,0x01A0,0x019F
+ };
+ int cut_value = 5; //cut_value < 32
+ if(pos == 0xfff)
+ {
+ return pos;
+ }
+ if(x_y) //xpos
+ {
+ dbg("X: Raw data %d\n",pos);
+ if (pos >=XPOS_MAX)
+ {
+ pos = XPOS_MAX;
+ }
+ if (pos<64)
+ {
+ pos = Cut_Edge_XLeft[pos]; //Left cut edge
+ }
+ else
+ if ((XPOS_MAX - pos) <64)
+ {
+ pos = Cut_Edge_XRight[XPOS_MAX - pos]; //Right cut edge
+ }
+ else
+ {
+ pos = pos + cut_value; //
+ pos = SSDS53X_SCREEN_MAX_X* pos / (790 + cut_value*2);//SSD253X_SCREEN_MAX_X|?????2????????|?
+ }
+ dbg("X: Cut edge data %d\n",pos);
+ return pos;
+ }
+ else //ypos
+ {
+
+ dbg("Y: Raw data %d\n",pos);
+ if (pos >=YPOS_MAX)
+ {
+ pos = YPOS_MAX;
+ }
+ if (pos<64)
+ {
+ pos = Cut_Edge_YUp[pos]; //Up cut edge
+ }
+ else
+ if ((YPOS_MAX - pos) <64)
+ {
+ pos = Cut_Edge_YDown[YPOS_MAX - pos]; //Down cut edge
+ }
+ else
+ {
+ pos = pos + cut_value; //
+ pos = SSDS53X_SCREEN_MAX_Y* pos / (470 + cut_value*2);//SSD253X_SCREEN_MAX_X|?????2????????|?
+ //tpos = pos;
+ //tpos = /*SSDS53X_SCREEN_MAX_Y*/ (800* pos) / (470 + cut_value*2);
+ dbg("XPOS_MAX=%d,\n", XPOS_MAX);
+ dbg("YPOS_MAX=%d,\n",YPOS_MAX);
+ dbg("Y: Cut edge data pos= %d,tpos=%d\n",pos,tpos);
+ }
+
+ return pos;
+ }
+
+
+}
+
+static int ssd253x_ts_cut_edge5(unsigned short pos,unsigned short x_y)
+{
+ unsigned short Cut_Edge_XLeft[64]={
+ 0x0008,0x0009,0x000B,0x000C,0x000D,0x000E,0x0010,0x0011,
+ 0x0012,0x0013,0x0015,0x0016,0x0017,0x0018,0x001A,0x001B,
+ 0x001C,0x001D,0x001F,0x0020,0x0021,0x0022,0x0024,0x0025,
+ 0x0026,0x0026,0x0027,0x0028,0x0029,0x002A,0x002B,0x002C,
+ 0x002C,0x002D,0x002E,0x002F,0x0030,0x0031,0x0032,0x0032,
+ 0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0038,0x0039,
+ 0x003A,0x003B,0x003C,0x003D,0x003E,0x003E,0x003F,0x0040,
+ 0x0041,0x0042,0x0043,0x0044,0x0044,0x0045,0x0046,0x0047
+ };
+
+ unsigned short Cut_Edge_XRight[64]={
+ 0x0318,0x0317,0x0315,0x0314,0x0313,0x0312,0x0310,0x030F,
+ 0x030E,0x030D,0x030B,0x030A,0x0309,0x0308,0x0306,0x0305,
+ 0x0304,0x0303,0x0301,0x0300,0x02FF,0x02FE,0x02FC,0x02FB,
+ 0x02FA,0x02FA,0x02F9,0x02F8,0x02F7,0x02F6,0x02F5,0x02F4,
+ 0x02F4,0x02F3,0x02F2,0x02F1,0x02F0,0x02EF,0x02EE,0x02EE,
+ 0x02ED,0x02EC,0x02EB,0x02EA,0x02E9,0x02E8,0x02E8,0x02E7,
+ 0x02E6,0x02E5,0x02E4,0x02E3,0x02E2,0x02E2,0x02E1,0x02E0,
+ 0x02DF,0x02DE,0x02DD,0x02DC,0x02DC,0x02DB,0x02DA,0x02D9
+ };
+
+ unsigned short Cut_Edge_YUp[64]={
+ 0x0006,0x0007,0x0008,0x000A,0x000B,0x000C,0x000D,0x000F,
+ 0x0010,0x0011,0x0012,0x0014,0x0015,0x0016,0x0017,0x0018,
+ 0x001A,0x001B,0x001C,0x001D,0x001F,0x0020,0x0021,0x0022,
+ 0x0022,0x0023,0x0024,0x0025,0x0025,0x0026,0x0027,0x0028,
+ 0x0029,0x0029,0x002A,0x002B,0x002C,0x002C,0x002D,0x002E,
+ 0x002F,0x0030,0x0030,0x0031,0x0032,0x0033,0x0033,0x0034,
+ 0x0035,0x0036,0x0037,0x0037,0x0038,0x0039,0x003A,0x003A,
+ 0x003B,0x003C,0x003D,0x003E,0x003E,0x003F,0x0040,0x0041
+ };
+
+ unsigned short Cut_Edge_YDown[64]={
+ 0x01DA,0x01D9,0x01D8,0x01D6,0x01D5,0x01D4,0x01D3,0x01D1,
+ 0x01D0,0x01CF,0x01CE,0x01CC,0x01CB,0x01CA,0x01C9,0x01C8,
+ 0x01C6,0x01C5,0x01C4,0x01C3,0x01C1,0x01C0,0x01BF,0x01BE,
+ 0x01BE,0x01BD,0x01BC,0x01BB,0x01BB,0x01BA,0x01B9,0x01B8,
+ 0x01B7,0x01B7,0x01B6,0x01B5,0x01B4,0x01B4,0x01B3,0x01B2,
+ 0x01B1,0x01B0,0x01B0,0x01AF,0x01AE,0x01AD,0x01AD,0x01AC,
+ 0x01AB,0x01AA,0x01A9,0x01A9,0x01A8,0x01A7,0x01A6,0x01A6,
+ 0x01A5,0x01A4,0x01A3,0x01A2,0x01A2,0x01A1,0x01A0,0x019F
+ };
+ u8 cut_value = 20; //cut_value < 32
+ if(pos == 0xfff)
+ {
+ return pos;
+ }
+ if(x_y) //xpos
+ {
+ dbg("X: Raw data %d\n",pos);
+ if (pos >=XPOS_MAX)
+ {
+ pos = XPOS_MAX;
+ }
+ if (pos<64)
+ {
+ pos = Cut_Edge_XLeft[pos]; //Left cut edge
+ }
+ else
+ if ((XPOS_MAX - pos) <64)
+ {
+ pos = Cut_Edge_XRight[XPOS_MAX - pos]; //Right cut edge
+ }
+ else
+ {
+ pos = pos + cut_value; //
+ pos = SSDS53X_SCREEN_MAX_X * pos / (XPOS_MAX + cut_value*2);//SSD253X_SCREEN_MAX_X|??????????|? }
+ dbg("X: Cut edge data %d\n",pos);
+ return pos;
+ }
+ }
+ else //ypos
+ {
+
+ dbg("Y: Raw data %d\n",pos);
+ if (pos >=YPOS_MAX)
+ {
+ pos = YPOS_MAX;
+ }
+ if (pos<64)
+ {
+ pos = Cut_Edge_YUp[pos]; //Up cut edge
+ }
+ else
+ if ((YPOS_MAX - pos) <64)
+ {
+ pos = Cut_Edge_YDown[YPOS_MAX - pos]; //Down cut edge
+ }
+ else
+ {
+ pos = pos + cut_value; //
+ pos = SSDS53X_SCREEN_MAX_Y * pos / (YPOS_MAX + cut_value*2);//SSD253X_SCREEN_MAX_X|??????????|? }
+ dbg("Y: Cut edge data %d\n",pos);
+ return pos;
+ }
+ }
+ return -1;
+}
+
+static int ssd253x_ts_cut_edge6(unsigned short pos,unsigned short x_y)
+{
+
+ #define XPOS_MAX_D (DRIVENO -EdgeDisable) *64
+ #define YPOS_MAX_D (SENSENO -EdgeDisable) *64
+ #undef SSD253X_SCREEN_MAX_X
+ #define SSD253X_SCREEN_MAX_X 800
+ #define SSD253X_SCREEN_MAX_Y 480
+
+ u8 cut_value = 20; //cut_value < 32
+ unsigned short Cut_Edge_XLeft[64]={
+ 0x0008,0x0009,0x000B,0x000C,0x000D,0x000E,0x0010,0x0011,
+ 0x0012,0x0013,0x0015,0x0016,0x0017,0x0018,0x001A,0x001B,
+ 0x001C,0x001D,0x001F,0x0020,0x0021,0x0022,0x0024,0x0025,
+ 0x0026,0x0026,0x0027,0x0028,0x0029,0x002A,0x002B,0x002C,
+ 0x002C,0x002D,0x002E,0x002F,0x0030,0x0031,0x0032,0x0032,
+ 0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0038,0x0039,
+ 0x003A,0x003B,0x003C,0x003D,0x003E,0x003E,0x003F,0x0040,
+ 0x0041,0x0042,0x0043,0x0044,0x0044,0x0045,0x0046,0x0047
+ };
+
+ unsigned short Cut_Edge_XRight[64]={
+ 0x0318,0x0317,0x0315,0x0314,0x0313,0x0312,0x0310,0x030F,
+ 0x030E,0x030D,0x030B,0x030A,0x0309,0x0308,0x0306,0x0305,
+ 0x0304,0x0303,0x0301,0x0300,0x02FF,0x02FE,0x02FC,0x02FB,
+ 0x02FA,0x02FA,0x02F9,0x02F8,0x02F7,0x02F6,0x02F5,0x02F4,
+ 0x02F4,0x02F3,0x02F2,0x02F1,0x02F0,0x02EF,0x02EE,0x02EE,
+ 0x02ED,0x02EC,0x02EB,0x02EA,0x02E9,0x02E8,0x02E8,0x02E7,
+ 0x02E6,0x02E5,0x02E4,0x02E3,0x02E2,0x02E2,0x02E1,0x02E0,
+ 0x02DF,0x02DE,0x02DD,0x02DC,0x02DC,0x02DB,0x02DA,0x02D9
+ };
+
+ unsigned short Cut_Edge_YUp[64]={
+ 0x0006,0x0007,0x0008,0x000A,0x000B,0x000C,0x000D,0x000F,
+ 0x0010,0x0011,0x0012,0x0014,0x0015,0x0016,0x0017,0x0018,
+ 0x001A,0x001B,0x001C,0x001D,0x001F,0x0020,0x0021,0x0022,
+ 0x0022,0x0023,0x0024,0x0025,0x0025,0x0026,0x0027,0x0028,
+ 0x0029,0x0029,0x002A,0x002B,0x002C,0x002C,0x002D,0x002E,
+ 0x002F,0x0030,0x0030,0x0031,0x0032,0x0033,0x0033,0x0034,
+ 0x0035,0x0036,0x0037,0x0037,0x0038,0x0039,0x003A,0x003A,
+ 0x003B,0x003C,0x003D,0x003E,0x003E,0x003F,0x0040,0x0041
+ };
+
+ unsigned short Cut_Edge_YDown[64]={
+ 0x01DA,0x01D9,0x01D8,0x01D6,0x01D5,0x01D4,0x01D3,0x01D1,
+ 0x01D0,0x01CF,0x01CE,0x01CC,0x01CB,0x01CA,0x01C9,0x01C8,
+ 0x01C6,0x01C5,0x01C4,0x01C3,0x01C1,0x01C0,0x01BF,0x01BE,
+ 0x01BE,0x01BD,0x01BC,0x01BB,0x01BB,0x01BA,0x01B9,0x01B8,
+ 0x01B7,0x01B7,0x01B6,0x01B5,0x01B4,0x01B4,0x01B3,0x01B2,
+ 0x01B1,0x01B0,0x01B0,0x01AF,0x01AE,0x01AD,0x01AD,0x01AC,
+ 0x01AB,0x01AA,0x01A9,0x01A9,0x01A8,0x01A7,0x01A6,0x01A6,
+ 0x01A5,0x01A4,0x01A3,0x01A2,0x01A2,0x01A1,0x01A0,0x019F
+ };
+
+
+ if(pos == 0xfff)
+ {
+ return pos;
+ }
+ if(x_y) //xpos
+ {
+ //#ifdef CONFIG_TS_CUTEDGE_DEBUG
+ dbg("X: Raw data %d\n",pos);
+ //#endif
+ if (pos >=XPOS_MAX_D)
+ {
+ pos = XPOS_MAX_D;
+ }
+ if (pos<64)
+ {
+ pos = Cut_Edge_XLeft[pos]; //Left cut edge
+ }
+ else
+ if ((XPOS_MAX_D - pos) <64)
+ {
+ pos = Cut_Edge_XRight[XPOS_MAX_D - pos]; //Right cut edge
+ }
+ else
+ {
+ pos = pos + cut_value; //
+ pos = SSD253X_SCREEN_MAX_X * pos / (XPOS_MAX_D + cut_value*2);//SSD253X_SCREEN_MAX_X|?????2????????|?
+ }
+ //#ifdef CONFIG_TS_CUTEDGE_DEBUG
+ dbg("X: Cut edge data %d\n",pos);
+ //#endif
+ return pos;
+ }
+ else //ypos
+ {
+
+ //#ifdef CONFIG_TS_CUTEDGE_DEBUG
+ dbg("Y: Raw data %d\n",pos);
+ //#endif
+ if (pos >=YPOS_MAX_D)
+ {
+ pos = YPOS_MAX_D;
+ }
+ if (pos<64)
+ {
+ pos = Cut_Edge_YUp[pos]; //Up cut edge
+ }
+ else
+ if ((YPOS_MAX_D - pos) <64)
+ {
+ pos = Cut_Edge_YDown[YPOS_MAX_D - pos]; //Down cut edge
+ }
+ else
+ {
+ pos = pos + cut_value; //
+ pos = SSD253X_SCREEN_MAX_Y * pos / (YPOS_MAX_D + cut_value*2);//SSD253X_SCREEN_MAX_X|?????2????????|?
+ }
+ //#ifdef CONFIG_TS_CUTEDGE_DEBUG
+ dbg("Y: Cut edge data %d\n",pos);
+ //#endif
+ return pos;
+ }
+ return -1;
+}
+
+static int ssd253x_ts_cut_edge8(unsigned short pos,unsigned short x_y)
+{
+
+ #define XPOS_MAX_D (DRIVENO -EdgeDisable) *64
+ #define YPOS_MAX_D (SENSENO -EdgeDisable) *64
+ #undef SSD253X_SCREEN_MAX_X
+ #define SSD253X_SCREEN_MAX_X 780
+ #undef SSD253X_SCREEN_MAX_Y
+ #define SSD253X_SCREEN_MAX_Y 470
+
+ u8 cut_value = 10;//30; //cut_value < 32
+ unsigned short Cut_Edge_XLeft[64]={
+ 0x0008,0x0009,0x000B,0x000C,0x000D,0x000E,0x0010,0x0011,
+ 0x0012,0x0013,0x0015,0x0016,0x0017,0x0018,0x001A,0x001B,
+ 0x001C,0x001D,0x001F,0x0020,0x0021,0x0022,0x0024,0x0025,
+ 0x0026,0x0026,0x0027,0x0028,0x0029,0x002A,0x002B,0x002C,
+ 0x002C,0x002D,0x002E,0x002F,0x0030,0x0031,0x0032,0x0032,
+ 0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0038,0x0039,
+ 0x003A,0x003B,0x003C,0x003D,0x003E,0x003E,0x003F,0x0040,
+ 0x0041,0x0042,0x0043,0x0044,0x0044,0x0045,0x0046,0x0047
+ };
+
+ unsigned short Cut_Edge_XRight[64]={
+ 0x0318,0x0317,0x0315,0x0314,0x0313,0x0312,0x0310,0x030F,
+ 0x030E,0x030D,0x030B,0x030A,0x0309,0x0308,0x0306,0x0305,
+ 0x0304,0x0303,0x0301,0x0300,0x02FF,0x02FE,0x02FC,0x02FB,
+ 0x02FA,0x02FA,0x02F9,0x02F8,0x02F7,0x02F6,0x02F5,0x02F4,
+ 0x02F4,0x02F3,0x02F2,0x02F1,0x02F0,0x02EF,0x02EE,0x02EE,
+ 0x02ED,0x02EC,0x02EB,0x02EA,0x02E9,0x02E8,0x02E8,0x02E7,
+ 0x02E6,0x02E5,0x02E4,0x02E3,0x02E2,0x02E2,0x02E1,0x02E0,
+ 0x02DF,0x02DE,0x02DD,0x02DC,0x02DC,0x02DB,0x02DA,0x02D9
+ };
+
+ unsigned short Cut_Edge_YUp[64]={
+ 0x0006,0x0007,0x0008,0x000A,0x000B,0x000C,0x000D,0x000F,
+ 0x0010,0x0011,0x0012,0x0014,0x0015,0x0016,0x0017,0x0018,
+ 0x001A,0x001B,0x001C,0x001D,0x001F,0x0020,0x0021,0x0022,
+ 0x0022,0x0023,0x0024,0x0025,0x0025,0x0026,0x0027,0x0028,
+ 0x0029,0x0029,0x002A,0x002B,0x002C,0x002C,0x002D,0x002E,
+ 0x002F,0x0030,0x0030,0x0031,0x0032,0x0033,0x0033,0x0034,
+ 0x0035,0x0036,0x0037,0x0037,0x0038,0x0039,0x003A,0x003A,
+ 0x003B,0x003C,0x003D,0x003E,0x003E,0x003F,0x0040,0x0041
+ };
+
+ unsigned short Cut_Edge_YDown[64]={
+ 0x01DA,0x01D9,0x01D8,0x01D6,0x01D5,0x01D4,0x01D3,0x01D1,
+ 0x01D0,0x01CF,0x01CE,0x01CC,0x01CB,0x01CA,0x01C9,0x01C8,
+ 0x01C6,0x01C5,0x01C4,0x01C3,0x01C1,0x01C0,0x01BF,0x01BE,
+ 0x01BE,0x01BD,0x01BC,0x01BB,0x01BB,0x01BA,0x01B9,0x01B8,
+ 0x01B7,0x01B7,0x01B6,0x01B5,0x01B4,0x01B4,0x01B3,0x01B2,
+ 0x01B1,0x01B0,0x01B0,0x01AF,0x01AE,0x01AD,0x01AD,0x01AC,
+ 0x01AB,0x01AA,0x01A9,0x01A9,0x01A8,0x01A7,0x01A6,0x01A6,
+ 0x01A5,0x01A4,0x01A3,0x01A2,0x01A2,0x01A1,0x01A0,0x019F
+ };
+
+
+ if(pos == 0xfff)
+ {
+ return pos;
+ }
+ if(x_y) //xpos
+ {
+ //#ifdef CONFIG_TS_CUTEDGE_DEBUG
+ dbg("X: Raw data %d\n",pos);
+ //#endif
+ if (pos >=XPOS_MAX_D)
+ {
+ pos = XPOS_MAX_D;
+ }
+ if (pos<64)
+ {
+ pos = Cut_Edge_XLeft[pos]; //Left cut edge
+ }
+ else
+ if ((XPOS_MAX_D - pos) <64)
+ {
+ pos = Cut_Edge_XRight[XPOS_MAX_D - pos]; //Right cut edge
+ }
+ else
+ {
+ pos = pos + cut_value; //
+ pos = SSD253X_SCREEN_MAX_X * pos / (XPOS_MAX_D + cut_value*2);//SSD253X_SCREEN_MAX_X|?????2????????|?
+ }
+ //#ifdef CONFIG_TS_CUTEDGE_DEBUG
+ dbg("X: Cut edge data %d\n",pos);
+ //#endif
+ return pos;
+ }
+ else //ypos
+ {
+
+ //#ifdef CONFIG_TS_CUTEDGE_DEBUG
+ dbg("Y: Raw data %d\n",pos);
+ //#endif
+ if (pos >=YPOS_MAX_D)
+ {
+ pos = YPOS_MAX_D;
+ }
+ if (pos<64)
+ {
+ pos = Cut_Edge_YUp[pos]; //Up cut edge
+ }
+ else
+ if ((YPOS_MAX_D - pos) <64)
+ {
+ pos = Cut_Edge_YDown[YPOS_MAX_D - pos]; //Down cut edge
+ }
+ else
+ {
+ pos = pos + cut_value; //
+ pos = SSD253X_SCREEN_MAX_Y * pos / (YPOS_MAX_D + cut_value*2);//SSD253X_SCREEN_MAX_X|?????2????????|?
+ }
+ //#ifdef CONFIG_TS_CUTEDGE_DEBUG
+ dbg("Y: Cut edge data %d\n",pos);
+ //#endif
+ return pos;
+ }
+}
+
+static int ssd253x_ts_cut_edge7(unsigned short pos,unsigned short x_y)
+{
+ unsigned short SENSENO_7 = 15;
+ unsigned short DRIVENO_7 = 20;
+ unsigned short EdgeDisable_7 = 1; // if Edge Disable, set it to 1, else reset to 0, OR SSD2533 set 0
+ unsigned short XPOS_MAX_7 = (DRIVENO_7 -EdgeDisable_7) *64;
+ unsigned short YPOS_MAX_7 = (SENSENO_7 -EdgeDisable_7) *64;
+
+ u8 cut_value = 10; //cut_value < 32
+ dbg("enter...\n");
+
+ if(pos == 0xfff)
+ {
+ return pos;
+ }
+ if(x_y) //xpos
+ {
+ if(pos < 16)
+ pos = cut_value + pos*(48 - cut_value) / 16;
+ else if(pos > (XPOS_MAX_7 - 16) )
+ pos = XPOS_MAX_7 + 16 + (pos - (XPOS_MAX_7 -16))*(48 - cut_value) / 16;
+ else
+ pos = pos + 32;
+ dbg("xpos_b:%d\n", pos);
+ pos = SSDS53X_SCREEN_MAX_X * pos / (DRIVENO_7 * 64);
+ dbg("xpos_a:%d\n", pos);
+ return pos;
+ }
+ else //ypos
+ {
+ if(pos < 16)
+ pos = cut_value + pos*(48 - cut_value) / 16;
+ else if(pos > (YPOS_MAX_7 - 16) )
+ pos = YPOS_MAX_7 + 16 + (pos - (YPOS_MAX_7 -16))*(48 - cut_value) / 16;
+ else
+ pos = pos + 32;
+ dbg("ypos_b:%d\n", pos);
+ pos = SSDS53X_SCREEN_MAX_Y* pos / (SENSENO_7 * 64);
+ dbg("ypos_a:%d\n", pos);
+ return pos;
+ }
+
+
+}
+
+
+static int ssd253x_ts_cut_edge(unsigned short pos,unsigned short x_y)
+{
+ switch (wmt_ts_get_cutedge())
+ {
+ case 0:
+ return ssd253x_ts_cut_edge0(pos,x_y);
+ break;
+ case 1:
+ return ssd253x_ts_cut_edge1(pos,x_y);
+ break;
+ case 2:
+ return ssd253x_ts_cut_edge2(pos,x_y);
+ break;
+ case 3:
+ return ssd253x_ts_cut_edge3(pos,x_y);
+ break;
+ case 4:
+ return ssd253x_ts_cut_edge4(pos,x_y);
+ break;
+ case 5:
+ return ssd253x_ts_cut_edge5(pos,x_y);
+ break;
+ case 6:
+ return ssd253x_ts_cut_edge6(pos,x_y);
+ break;
+ case 7:
+ return ssd253x_ts_cut_edge7(pos,x_y);
+ break;
+ case 8:
+ return ssd253x_ts_cut_edge8(pos,x_y);
+ break;
+ default:
+ return -1;
+ };
+}
+
+#ifdef USE_TOUCH_KEY
+static u8 btn_status_last = 0;
+#endif
+
+static void ssd253x_ts_work(struct work_struct *work)
+{
+ int i;
+ unsigned short xpos=0, ypos=0;
+ int tx,ty;
+ //width=0;
+ int FingerInfo;
+ int EventStatus;
+ int FingerX[FINGERNO];
+ int FingerY[FINGERNO];
+ int FingerP[FINGERNO];
+ int clrFlag=0;
+ int Ssd_Timer;
+ #ifdef USE_TOUCH_KEY
+ u8 btn_status;
+ u8 btn_status_last = 0;
+ #endif
+
+ struct ssl_ts_priv *ssl_priv = l_ts;
+
+ #ifdef USE_TOUCH_KEY
+ btn_status = ReadRegister(ssl_priv->client,SELFCAP_STATUS_REG, 1);
+ //#ifdef CONFIG_TOUCHSCREEN_SSL_DEBUG
+ dbg("btn pressed:%x\n", btn_status & 0x0f);
+ //#endif
+ if (btn_status_last != btn_status){
+ if(btn_status){
+ btn_status_last = btn_status;
+ ssd2533_ts_send_keyevent(ssl_priv,btn_status, 1);
+ dbg("send %x btn_status_last%d \n", btn_status,btn_status_last);
+ }
+ else{
+ ssd2533_ts_send_keyevent(ssl_priv,btn_status_last, 0);
+ btn_status_last = 0;
+ dbg("btn_status_last %x \n", btn_status_last);
+ }
+ return ;
+ }
+ #endif
+
+ Ssd_Timer = 0;
+ if(ic_flag == IC_SSD2533){
+ if(!Ssd_Timer_flag){
+ Ssd_Timer = ReadRegister(TIMESTAMP_REG,2);
+ if(!Ssd_Timer1){
+ Ssd_Timer1 = Ssd_Timer/1000;
+ }
+
+ Ssd_Timer2 = Ssd_Timer/1000;
+
+
+ if((Ssd_Timer2 - Ssd_Timer1) > 10){
+ WriteRegister(AUTO_INIT_RST_REG,0x00,0x00,1);
+ Ssd_Timer_flag = 1;
+ }
+ }
+ }
+
+ EventStatus = ReadRegister(EVENT_STATUS,2)>>4;
+ ssl_priv->FingerDetect=0;
+ for(i=0;i<ssl_priv->FingerNo;i++){
+ if((EventStatus>>i)&0x1){
+ FingerInfo=ReadRegister(FINGER01_REG+i,4);
+ xpos = ((FingerInfo>>4)&0xF00)|((FingerInfo>>24)&0xFF);
+ ypos = ((FingerInfo>>0)&0xF00)|((FingerInfo>>16)&0xFF);
+ dbg("raw data before cut, F%d:(%d,%d)\n",i,xpos,ypos);
+ if(xpos!=0xFFF){
+ ssl_priv->FingerDetect++;
+ if (wmt_ts_get_cutedge()>=0){
+ xpos = ssd253x_ts_cut_edge(xpos, 1);
+ ypos = ssd253x_ts_cut_edge(ypos, 0);
+ }
+ }else {
+ EventStatus=EventStatus&~(1<<i);
+ clrFlag=1;
+ }
+ }else{
+ xpos=ypos=0xFFF;
+ clrFlag=1;
+ }
+ FingerX[i]=xpos;
+ FingerY[i]=ypos;
+ }
+
+ if(ssl_priv->use_irq==1) wmt_enable_gpirq();
+ if(ssl_priv->use_irq==2)
+ {
+ if(ssl_priv->FingerDetect==0)
+ {
+ wmt_enable_gpirq();
+ } else {
+ hrtimer_start(&ssl_priv->timer, ktime_set(0, MicroTimeTInterupt), HRTIMER_MODE_REL);
+ }
+ }
+ if(ic_flag == IC_SSD2533){
+ if(clrFlag) WriteRegister(EVENT_FIFO_SCLR,0x01,0x00,1);
+ }
+
+ if(ssl_priv->input->id.product==0x2533)
+ if(ssl_priv->input->id.version==0x0101)
+ FingerCheckSwap(FingerX,FingerY,FingerP,ssl_priv->FingerNo,ssl_priv->sFingerX,ssl_priv->sFingerY);
+
+ // report data
+ for(i=0;i<ssl_priv->FingerNo;i++)
+ {
+ xpos=FingerX[i];
+ ypos=FingerY[i];
+ if(ssl_priv->input->id.product==0x2533){
+ if(ssl_priv->input->id.version==0x0101) RunningAverage(&xpos,&ypos,i,ssl_priv);
+ if(ssl_priv->input->id.version==0x0102) RunningAverage(&xpos,&ypos,i,ssl_priv);
+ }
+
+ if(xpos!=0xFFF)
+ {
+ dbg("raw data after cut, F%d:(%d,%d)\n",i,xpos,ypos);
+ switch (wmt_ts_get_xaxis())
+ {
+ case 1:
+ tx = ypos;
+ break;
+ case 0:
+ default:
+ tx = xpos;
+ break;
+ }
+
+ switch (wmt_ts_get_xdir())
+ {
+ case 1:
+ break;
+ case -1:
+ tx = SSDS53X_SCREEN_MAX_Y - tx;
+ break;
+ default:
+ break;
+ };
+
+ if (tx <0){
+ tx = 0;
+ } else if (tx >= SSDS53X_SCREEN_MAX_Y){
+ tx = SSDS53X_SCREEN_MAX_Y-1;
+ }
+ switch (wmt_ts_get_yaxis())
+ {
+
+ case 0:
+ ty = xpos;
+ break;
+ case 1:
+ default:
+ ty = ypos;
+ break;
+ }
+
+ switch (wmt_ts_get_ydir())
+ {
+ case 1:
+ break;
+ case -1:
+ ty = SSDS53X_SCREEN_MAX_X - ty;
+ default:
+ break;
+ }
+
+ if (ty < 0){
+ ty = 0;
+ } else if (ty >=SSDS53X_SCREEN_MAX_X){
+ ty = SSDS53X_SCREEN_MAX_X-1;
+ }
+
+ if (wmt_ts_get_lcdexchg()) {
+ int tmp;
+ tmp = tx;
+ tx = ty;
+ ty = wmt_ts_get_resolvX() - tmp;
+ }
+
+ ssd253x_tsdev.penup = 0;
+ input_report_abs(ssl_priv->input, ABS_MT_POSITION_X, tx);
+ input_report_abs(ssl_priv->input, ABS_MT_POSITION_Y, ty);
+ /*input_report_abs(ssl_priv->input, ABS_MT_POSITION_X, ty);
+ input_report_abs(ssl_priv->input, ABS_MT_POSITION_Y, tx);*/
+ input_mt_sync(ssl_priv->input);
+ dbg("report data x=%d,y=%d\n", tx, ty);
+
+ }
+ else if(ssl_priv->FingerX[i]!=0xFFF){
+ input_mt_sync(ssl_priv->input);
+ //printk("pen up...\n");
+ ssd253x_tsdev.penup = 1;
+ }
+
+ ssl_priv->FingerX[i]=FingerX[i];
+ ssl_priv->FingerY[i]=FingerY[i];
+ }
+
+ ssl_priv->EventStatus=EventStatus;
+ input_sync(ssl_priv->input);
+ if (1 == ssd253x_tsdev.penup){
+ wake_up(&ts_penup_wait_queue);
+ }
+
+}
+
+
+#define TPIC_INT_PLLLING 0
+#define TPIC_INT_INTERUPT 1
+#define TPIC_INT_HYBRID 2
+
+
+static int ssd253x_probe(struct platform_device *pdev)
+{
+ struct ssl_ts_priv *ssl_priv;
+ struct input_dev *ssl_input;
+ int error;
+ int i;
+ //unsigned int prescale;
+
+ //#ifdef SD_INIT
+ // g_tp_client = l_client;
+ //#endif
+
+ SSDS53X_SCREEN_MAX_X = wmt_ts_get_resolvY();
+ SSDS53X_SCREEN_MAX_Y = wmt_ts_get_resolvX();
+
+ ssl_priv = kzalloc(sizeof(*ssl_priv), GFP_KERNEL);
+ if (!ssl_priv)
+ {
+ errlog(" kzalloc Error!\n");
+ error=-ENODEV;
+ goto err0;
+ }
+ l_ts = ssl_priv;
+
+ ssl_input = input_allocate_device();
+ if (!ssl_input)
+ {
+ errlog(" ssd253x_ts_probe: input_allocate_device Error\n");
+ error=-ENODEV;
+ goto freealloc;
+ }
+ ssl_input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) | BIT_MASK(EV_SYN) ;
+ set_bit(INPUT_PROP_DIRECT,ssl_input->propbit);
+ ssl_input->name = DEVICE_NAME;
+ ssl_input->id.bustype = BUS_I2C;
+ ssl_input->id.vendor = 0x2878; // Modify for Vendor ID
+
+ ssl_priv->input = ssl_input;
+
+ ssl_priv->FingerNo=wmt_ts_get_fingernum();//FINGERNO;
+ ssl_priv->Resolution=64;
+
+ for(i=0;i<ssl_priv->FingerNo;i++)
+ {
+ ssl_priv->sFingerX[i]=0xFFF;
+ ssl_priv->sFingerY[i]=0xFFF;
+
+ // For Adaptive Running Average
+ ssl_priv->pFingerX[i]=0xFFF;
+ ssl_priv->pFingerY[i]=0xFFF;
+ }
+
+ deviceReset();
+ ssl_input->id.product = ReadRegister(DEVICE_ID_REG,2);
+ ssl_input->id.version = ReadRegister(VERSION_ID_REG,2);
+ ssl_input->id.product = ReadRegister(DEVICE_ID_REG,2);
+
+ ssl_input->id.version = ReadRegister(VERSION_ID_REG,2);
+ klog("SSL Touchscreen Device ID : 0x%04X\n",ssl_input->id.product);
+ klog("SSL Touchscreen Version ID : 0x%04X\n",ssl_input->id.version);
+
+ if(ssl_input->id.product == 0x2531){
+ ic_flag = IC_SSD2531;
+ }else if(ssl_input->id.product == 0x2533) {
+ ic_flag = IC_SSD2533;
+ }else if(ssl_input->id.product == 0x2543) {
+ ic_flag = IC_SSD2543;
+ }
+
+ if(ic_flag == IC_SSD2533) {
+ ssl_priv->use_irq = TPIC_INT_HYBRID;
+ }else if(ic_flag == IC_SSD2543) {
+ ssl_priv->use_irq = TPIC_INT_INTERUPT;
+ }
+
+ SSD253xdeviceInit();
+ if(ic_flag == IC_SSD2533) {
+ WriteRegister(EVENT_FIFO_SCLR,0x01,0x00,1); // clear Event FiFo
+ }
+
+
+ if(ssl_priv->input->id.product==0x2531)
+ ssl_priv->Resolution=32;
+ else if(ssl_priv->input->id.product==0x2533)
+ ssl_priv->Resolution=64;
+
+
+ if (wmt_ts_get_lcdexchg()) {
+ input_set_abs_params(ssl_input, ABS_MT_POSITION_X, 0,wmt_ts_get_resolvY(), 0, 0);
+ input_set_abs_params(ssl_input, ABS_MT_POSITION_Y, 0,wmt_ts_get_resolvX(), 0, 0);
+ } else {
+ input_set_abs_params(ssl_input, ABS_MT_POSITION_X, 0,wmt_ts_get_resolvX(), 0, 0);
+ input_set_abs_params(ssl_input, ABS_MT_POSITION_Y, 0,wmt_ts_get_resolvY(), 0, 0);
+ }
+
+#ifdef USE_TOUCH_KEY
+ set_bit(KEY_MENU, ssl_input->keybit);
+ set_bit(KEY_HOME, ssl_input->keybit);
+ set_bit(KEY_BACK, ssl_input->keybit);
+ set_bit(KEY_SEARCH, ssl_input->keybit);
+ #endif
+ error = input_register_device(ssl_input);
+ if(error)
+ {
+ errlog("input_register_device input Error!\n");
+ error=-ENODEV;
+ goto panel_init_fail;
+ }
+ if((ssl_priv->use_irq==0)||(ssl_priv->use_irq==2))
+ {
+ hrtimer_init(&ssl_priv->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ ssl_priv->timer.function = ssd253x_ts_timer;
+ //#ifdef CONFIG_TOUCHSCREEN_SSL_DEBUG
+ dbg(" ssd253x_ts_probe: timer_init OK!\n");
+ //#endif
+ }
+
+ ssd253x_wq = create_singlethread_workqueue("ssd253x_wq");
+ INIT_WORK(&ssl_priv->ssl_work, ssd253x_ts_work);
+ error = request_irq(wmt_get_tsirqnum(), ssd253x_ts_isr, IRQF_SHARED, "ssd253x_ts_q", l_ts);
+ if(error){
+ errlog("request_irq Error!\n");
+ error=-ENODEV;
+ goto freeque;
+ }
+
+ wmt_set_gpirq(IRQ_TYPE_EDGE_FALLING);
+ wmt_disable_gpirq();
+
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ ssl_priv->early_suspend.suspend = ssd253x_ts_early_suspend;
+ ssl_priv->early_suspend.resume = ssd253x_ts_late_resume;
+ ssl_priv->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN+2;
+ register_early_suspend(&ssl_priv->early_suspend);
+#endif
+ deviceResume();
+ wmt_enable_gpirq();
+ dbg("SSD253X init ok!\n");
+ return 0;
+
+freeque:
+ destroy_workqueue(ssd253x_wq);
+ input_unregister_device(ssl_input);
+panel_init_fail:
+ input_free_device(ssl_input);
+freealloc:
+ kfree(ssl_priv);
+err0:
+ //dev_set_drvdata(&client->dev, NULL);
+ return error;
+}
+
+static int ssd253x_remove(struct platform_device *pdev)
+{
+ struct ssl_ts_priv *ssl_priv = l_ts;
+
+ if((ssl_priv->use_irq==0)||(ssl_priv->use_irq==2)) hrtimer_cancel(&ssl_priv->timer);
+
+ //disable int
+ wmt_disable_gpirq();
+ //free irq
+ free_irq(wmt_get_tsirqnum(), l_ts);
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&ssl_priv->early_suspend);
+#endif
+ // free queue
+ cancel_work_sync (&ssl_priv->ssl_work);
+ flush_workqueue(ssd253x_wq);
+ destroy_workqueue(ssd253x_wq);
+ input_unregister_device(ssl_priv->input);
+ input_free_device(ssl_priv->input);
+ kfree(ssl_priv);
+ l_ts = NULL;
+ return 0;
+}
+
+
+/*
+static int ssd253x_ts_open(struct input_dev *dev)
+{
+ struct ssl_ts_priv *ssl_priv = l_ts;
+
+ deviceResume();
+ if(ssl_priv->use_irq)
+ {
+ wmt_enable_gpirq(); //(ssl_priv->irq);
+ } else {
+ hrtimer_start(&ssl_priv->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
+ }
+ return 0;
+}
+
+
+static void ssd253x_ts_close(struct input_dev *dev)
+{
+ struct ssl_ts_priv *ssl_priv = l_ts;
+
+ // disable interrupt
+ deviceSuspend();
+ if((ssl_priv->use_irq==0)||(ssl_priv->use_irq==2))
+ hrtimer_cancel(&ssl_priv->timer);
+ if((ssl_priv->use_irq==1)||(ssl_priv->use_irq==2))
+ wmt_disable_gpirq();//(ssl_priv->irq);
+}
+*/
+static int ssd253x_resume(struct platform_device *pdev)
+{
+ struct ssl_ts_priv *ssl_priv = l_ts;
+
+ wmt_disable_gpirq();
+ Ssd_Timer_flag = 0;
+ deviceReset();
+ SSD253xdeviceInit();
+ if(ic_flag == IC_SSD2533){
+ WriteRegister(EVENT_FIFO_SCLR,0x01,0x00,1); // clear Event FiFo
+ }
+ deviceResume();
+ wmt_set_gpirq(IRQ_TYPE_EDGE_FALLING);
+ wmt_enable_gpirq();
+
+ if(! ssl_priv->use_irq)
+ {
+ hrtimer_start(&ssl_priv->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
+ }
+ ssl_priv->earlysus = 0;
+ return 0;
+}
+
+static int ssd253x_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct ssl_ts_priv *ssl_priv = l_ts;
+
+ if((ssl_priv->use_irq==0)||(ssl_priv->use_irq==2)) hrtimer_cancel(&ssl_priv->timer);
+ // disable irq
+ wmt_disable_gpirq();
+ Ssd_Timer_flag = 0;
+ if(ic_flag == IC_SSD2533){
+ deviceSuspend();
+ }else if(ic_flag == IC_SSD2543){
+ deviceReset();
+ }
+ return 0;
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void ssd253x_ts_late_resume(struct early_suspend *h)
+{
+ struct ssl_ts_priv *ssl_priv = l_ts;
+
+ dbg("...\n");
+ if (ssl_priv->earlysus != 0)
+ {
+ wmt_disable_gpirq();
+ Ssd_Timer_flag = 0;
+ deviceReset();
+ SSD253xdeviceInit();
+ WriteRegister(EVENT_FIFO_SCLR,0x01,0x00,1); // clear Event FiFo
+ deviceResume();
+ wmt_set_gpirq(IRQ_TYPE_EDGE_FALLING);
+ wmt_enable_gpirq();
+
+ if(! ssl_priv->use_irq)
+ {
+ hrtimer_start(&ssl_priv->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
+ }
+ ssl_priv->earlysus = 0;
+ }
+}
+static void ssd253x_ts_early_suspend(struct early_suspend *h)
+{
+ struct ssl_ts_priv *ssl_priv = l_ts;
+
+ ssl_priv->earlysus = 1;
+ if((ssl_priv->use_irq==0)||(ssl_priv->use_irq==2)) hrtimer_cancel(&ssl_priv->timer);
+ // disable irq
+ wmt_disable_gpirq();
+ Ssd_Timer_flag = 0;
+ deviceSuspend();
+
+ return;
+}
+#endif
+
+
+static irqreturn_t ssd253x_ts_isr(int irq, void *dev_id)
+{
+ struct ssl_ts_priv *ssl_priv = l_ts;
+
+ if (wmt_is_tsint())
+ {
+ wmt_clr_int();
+ if (wmt_is_tsirq_enable())
+ {
+ wmt_disable_gpirq();
+ dbg("begin..\n");
+ if(!ssl_priv->earlysus)
+ {
+ queue_work(ssd253x_wq, &ssl_priv->ssl_work);
+ }
+ }
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_NONE;
+}
+
+static enum hrtimer_restart ssd253x_ts_timer(struct hrtimer *timer)
+{
+ struct ssl_ts_priv *ssl_priv = container_of(timer, struct ssl_ts_priv, timer);
+ #ifdef CONFIG_TOUCHSCREEN_SSL_DEBUG
+ printk("+-----------------------------------------+\n");
+ printk("| ssd253x_ts_timer! |\n");
+ printk("+-----------------------------------------+\n");
+ #endif
+ queue_work(ssd253x_wq, &ssl_priv->ssl_work);
+ if(ssl_priv->use_irq==0) hrtimer_start(&ssl_priv->timer, ktime_set(0, MicroTimeTInterupt), HRTIMER_MODE_REL);
+ return HRTIMER_NORESTART;
+}
+
+#ifdef SD_INIT
+static const struct file_operations tp_fops = {
+ .owner = THIS_MODULE,
+ .read = tp_read,
+ .write = tp_write,
+ .unlocked_ioctl = tp_ioctl,
+ .open = tp_open,
+ .release = tp_release,
+};
+
+static struct miscdevice misc = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = TP_CHR,
+ .fops = &tp_fops,
+};
+#endif
+
+
+static int ssd253x_init(void)
+{
+ char firmwname[60];
+ int i;
+
+ if (deviceReset() != 0)
+ return -1;
+ memset(firmwname,0,sizeof(firmwname));
+ wmt_ts_get_firmwname(firmwname);
+ i = read_firmwarefile(firmwname,&ssd253xcfgTable,0x100);
+ if (i <= 0)
+ {
+ l_cfglen = sizeof(ssd253xcfgTable_default)/sizeof(ssd253xcfgTable_default[0]);
+ ssd253xcfgTable = ssd253xcfgTable_default;
+ dbg("Using the default configure!\n");
+ } else {
+ l_cfglen = i;
+ }
+ Resume[1].No = ssd253xcfgTable[l_cfglen-1].No;
+ Resume[1].Reg = ssd253xcfgTable[l_cfglen-1].Reg;
+ Resume[1].Data1 = ssd253xcfgTable[l_cfglen-1].Data1;
+ Resume[1].Data2 = ssd253xcfgTable[l_cfglen-1].Data2;
+ if (SSD253xdeviceInit()!= 0)
+ {
+ if (i > 0)
+ {
+ kfree(ssd253xcfgTable);
+ }
+ return -1;
+ }
+ // init hardware
+
+#ifdef SD_INIT
+ misc_register(&misc);
+#endif
+
+
+ return 0;
+}
+
+static void ssd253x_exit(void)
+{
+ klog("remove the module\n");
+
+#ifdef SD_INIT
+ misc_deregister(&misc);
+#endif
+
+
+ if (ssd253xcfgTable != ssd253xcfgTable_default)
+ {
+ kfree(ssd253xcfgTable);
+ }
+
+}
+
+static int ssd253x_wait_penup(struct wmtts_device*tsdev)
+{
+ int ret = wait_event_interruptible(
+ ts_penup_wait_queue,
+ (1==tsdev->penup));
+ return ret;
+}
+
+
+struct wmtts_device raysen_tsdev = {
+ .driver_name = "ssd253x_ts",
+ .ts_id = "SSD253X",
+ .init = ssd253x_init,
+ .exit = ssd253x_exit,
+ .probe = ssd253x_probe,
+ .remove = ssd253x_remove,
+ .suspend = ssd253x_suspend,
+ .resume = ssd253x_resume,
+ .wait_penup = ssd253x_wait_penup,
+ .penup = 1,
+};
+
+#ifdef SD_INIT
+static long tp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ return 0;
+}
+
+static int tp_open(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+static int tp_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static ssize_t tp_read(struct file *file, char __user *buf, size_t count,loff_t *offset)
+{
+ char *kbuf;
+ uint8_t reg;
+ int ByteNo;
+ int readValue;
+ int i;
+
+ kbuf = kmalloc(count,GFP_KERNEL);
+
+ if(copy_from_user(kbuf,buf,1)) {
+ printk("no enough memory!\n");
+ return -1;
+ }
+
+ reg = (uint8_t)kbuf[0];
+ ByteNo = count;
+
+ readValue = ReadRegister( /*g_tp_client, */reg, ByteNo);
+
+ for(i = 0;i < ByteNo;i++){
+ kbuf[i] = (readValue>>(8*i)) & 0xff;
+ }
+
+ if(copy_to_user(buf,kbuf,count)) {
+ printk("no enough memory!\n");
+ return -1;
+ }
+
+ kfree(kbuf);
+
+ return count;
+}
+
+static ssize_t tp_write(struct file *file, const char __user *buf,size_t count, loff_t *offset)
+{
+ char *kbuf;
+
+ kbuf = kmalloc(count,GFP_KERNEL);
+
+ if(copy_from_user(kbuf,buf,count)) {
+ printk("no enough memory!\n");
+ return -1;
+ }
+
+ if(kbuf[1] == 0x01){
+ wmt_rst_output(0);
+ mdelay(5);
+ wmt_rst_output(1);
+ mdelay(20);
+ }
+ else
+ {
+ WriteRegister(/*g_tp_client,*/kbuf[1],kbuf[2],kbuf[3],kbuf[0]);
+ }
+
+ kfree(kbuf);
+
+ return count;
+}
+
+#endif
+
+
+
+
+MODULE_AUTHOR("Solomon Systech Ltd - Design Technology, Icarus Choi");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("ssd253x Touchscreen Driver 1.3");
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/ssd253x_ts/ssd253x-ts.h b/ANDROID_3.4.5/drivers/input/touchscreen/ssd253x_ts/ssd253x-ts.h
new file mode 100755
index 00000000..fe6edeae
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/ssd253x_ts/ssd253x-ts.h
@@ -0,0 +1,28 @@
+/**************************************************************
+ʹÓÃÇ°×¢ÒâͨµÀÊý£¬Çý¶¯Ä¬ÈÏʹÓÃͨµÀÊÇsense
+´óÓÚdrive·ñÔòÐèÒª½«Ê¹Óõ½µÄDRIVENOÓëSENSENOµ÷»»
+´ËÇé¿ö°üÀ¨0x66ºÍ0x67¼Ä´æÆ÷£¬µ«²»±ØÐ޸ġ£
+***************************************************************/
+#ifndef __SSD253X_20125181742_TS_H__
+#define __SSD253X_20125181742_TS_H__
+#define DRIVENO 15
+#define SENSENO 10
+#define EdgeDisable 1 // if Edge Disable, set it to 1, else reset to 0
+#define RunningAverageMode 2 //{0,8},{5,3},{6,2},{7,1}
+#define RunningAverageDist 4 // Threshold Between two consecutive points
+#define MicroTimeTInterupt 10000000 //20000000// 100Hz - 10,000,000us
+#define FINGERNO 10
+
+//#define USE_TOUCH_KEY
+
+#define USE_CUT_EDGE //0x8b must be 0x00; EdgeDisable set 0
+//#undef USE_CUT_EDGE
+
+#ifdef USE_CUT_EDGE
+ #define XPOS_MAX 576 //(DRIVENO - EdgeDisable) *64
+ #define YPOS_MAX 896 //(SENSENO - EdgeDisable) *64
+#endif
+
+
+
+#endif
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/ssd253x_ts/wmt_ts.c b/ANDROID_3.4.5/drivers/input/touchscreen/ssd253x_ts/wmt_ts.c
new file mode 100755
index 00000000..cf63ca13
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/ssd253x_ts/wmt_ts.c
@@ -0,0 +1,810 @@
+#include <linux/unistd.h>
+#include <linux/time.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+//#include <asm/semaphore.h>
+#include <linux/proc_fs.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/suspend.h>
+#include <linux/proc_fs.h>
+#include <linux/input.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <mach/hardware.h>
+#include <asm/uaccess.h>
+#include <linux/i2c.h>
+#include <linux/irq.h>
+
+#include <asm/uaccess.h>
+#include <linux/fs.h>
+#include <linux/syscalls.h>
+
+
+#include "wmt_ts.h"
+#include "ssd253x-ts.h"
+
+/////////////////////////////////////////////////////////////////
+
+// commands for ui
+#define TS_IOC_MAGIC 't'
+
+#define TS_IOCTL_CAL_START _IO(TS_IOC_MAGIC, 1)
+#define TS_IOCTL_CAL_DONE _IOW(TS_IOC_MAGIC, 2, int*)
+#define TS_IOCTL_GET_RAWDATA _IOR(TS_IOC_MAGIC, 3, int*)
+#define TS_IOCTL_CAL_QUIT _IOW(TS_IOC_MAGIC, 4, int*)
+#define TS_IOCTL_AUTO_CALIBRATION _IOW(TS_IOC_MAGIC, 5, int*)
+#define TS_IOC_MAXNR 5
+
+//
+#define TS_MAJOR 11
+#define TS_DRIVER_NAME "wmtts_touch"
+#define TS_NAME "wmtts"
+#define WMTTS_PROC_NAME "wmtts_config"
+
+#define EXT_GPIO0 0
+#define EXT_GPIO1 1
+#define EXT_GPIO2 2
+#define EXT_GPIO3 3
+#define EXT_GPIO4 4
+#define EXT_GPIO5 5
+#define EXT_GPIO6 6
+#define EXT_GPIO7 7
+
+typedef struct {
+ int a1;
+ int b1;
+ int c1;
+ int a2;
+ int b2;
+ int c2;
+ int delta;
+}CALIBRATION_PARAMETER, *PCALIBRATION_PARAMETER;
+
+
+static int lcd_exchg = 0;
+static int irq_gpio;
+static int rst_gpio;
+static int panelres_x;
+static int panelres_y;
+static int l_xaxis=0;
+static int l_xdirect=1;
+static int l_yaxis=1;
+static int l_ydirect=1;
+static int l_cutedge=-1;
+static DECLARE_WAIT_QUEUE_HEAD(queue);
+static CALIBRATION_PARAMETER g_CalcParam;
+static TS_EVENT g_evLast;
+static struct mutex cal_mutex;
+static DECLARE_WAIT_QUEUE_HEAD(ts_penup_wait_queue);
+
+extern struct wmtts_device raysen_tsdev;
+static struct wmtts_device* l_tsdev = &raysen_tsdev;
+static struct i2c_client *l_client=NULL;
+static int l_penup = 0; // 1-pen up,0-pen down
+static char l_firmid[21];
+
+/////////////////////////////////////////////////////
+// function declare
+/////////////////////////////////////////////////////
+extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
+extern int wmt_setsyspara(char *varname, unsigned char *varval);
+
+///////////////////////////////////////////////////////////////////////
+void TouchPanelCalibrateAPoint(
+ int UncalX, //@PARM The uncalibrated X coordinate
+ int UncalY, //@PARM The uncalibrated Y coordinate
+ int *pCalX, //@PARM The calibrated X coordinate
+ int *pCalY //@PARM The calibrated Y coordinate
+ )
+{
+ int x, y;
+ mutex_lock(&cal_mutex);
+ x = (g_CalcParam.a1 * UncalX + g_CalcParam.b1 * UncalY +
+ g_CalcParam.c1) / g_CalcParam.delta;
+ y = (g_CalcParam.a2 * UncalX + g_CalcParam.b2 * UncalY +
+ g_CalcParam.c2) / g_CalcParam.delta;
+
+//klog("afer(%d,%d)(%d,%d)\n", x,y,panelres_x,panelres_y);
+ if ( x < 0 )
+ x = 0;
+
+ if ( y < 0 )
+ y = 0;
+ if (x >= panelres_x)
+ x = panelres_x-1;
+ if (y >= panelres_y)
+ y = panelres_y-1;
+
+ *pCalX = x;
+ *pCalY = y;
+ mutex_unlock(&cal_mutex);
+ return;
+}
+
+static int parse_firmwarefile(const char* filedata, struct ChipSetting** firmarr, int maxlen)
+{
+ char endflag[]="/* End flag */";
+ const char* p = filedata;
+ int val[4];
+ int i = 0;
+ int j = 0;
+ const char* s = NULL;
+
+ // the first {
+ while (*p!='{') p++;
+ p++;
+ s = p;
+ // calculate the number of array
+ while (strncmp(p,endflag,strlen(endflag)))
+ {
+ if (*p=='{')
+ {
+ i++;
+ }
+ p++;
+ };
+ dbg("the number of arry:0x%x\n", i);
+ // alloc the memory for array
+ *firmarr = kzalloc(sizeof(struct ChipSetting)*i, GFP_KERNEL);
+ // parse the value of array
+ p = s;
+ j = 0;
+ while (strncmp(p,endflag,strlen(endflag)))
+ {
+ if (*p=='{')
+ {
+ memset(val,0,sizeof(val));
+ sscanf(p,"{%x,%x,%x,%x}",val,val+1,val+2,val+3);
+ (*firmarr)[j].No = val[0]&0x00FF;
+ (*firmarr)[j].Reg = val[1]&0x00FF;
+ (*firmarr)[j].Data1 = val[2]&0x00FF;
+ (*firmarr)[j].Data2 = val[3]&0x00FF;
+ dbg("arry[0x%x]:%x,%x,%x,%x\n",j,(*firmarr)[j].No,(*firmarr)[j].Reg,(*firmarr)[j].Data1,
+ (*firmarr)[j].Data2);
+ j++;
+ }
+ //p = strchr(p,'}');
+ p++;
+ if (j>=i-2)
+ {
+ dbg("%s",p);
+ }
+
+ };
+ if (i != j)
+ {
+ errlog("Error parsing file(the number of arry not match)!\n");
+ return -1;
+ };
+ dbg("paring firmware file end.\n");
+ return i;
+}
+
+
+static struct device* get_tp_device(void){
+ if(l_client == NULL){
+ errlog("l_client is NULL\n");
+ }
+ return &l_client->dev;
+}
+
+
+//filepath:the path of firmware file;
+//firmdata:store the data from firmware file;
+//maxlen: the max len of firmdata;
+//return:the number of firmware data,negative-parsing error.
+int read_firmwarefile(char* filepath, struct ChipSetting** firmdata, int maxlen)
+{
+ const u8 *data = NULL;
+ int i = 0;
+ int ret = -1;
+ const struct firmware* tpfirmware = NULL;
+
+ klog("ts config file:%s\n",filepath);
+
+
+ ret = request_firmware(&tpfirmware, filepath, get_tp_device());
+ if (ret < 0) {
+ errlog("Failed load tp firmware: %s ret=%d\n", filepath,ret);
+ goto err_end;
+ }
+
+ data = tpfirmware->data;
+
+ i = parse_firmwarefile(data,firmdata,maxlen);
+ if (i <= 0)
+ {
+ errlog("error to parse firmware file.\n");
+ ret = -1;
+ goto error_parse_fw;
+ }
+ ret = i;
+
+
+ dbg("success to read firmware file!\n");;
+
+error_parse_fw:
+ if(tpfirmware){
+ release_firmware(tpfirmware);
+ tpfirmware = NULL;
+ }
+err_end:
+ return ret;
+}
+
+
+ int wmt_ts_get_gpionum(void)
+{
+ return irq_gpio;
+}
+
+int wmt_ts_get_resetgpnum(void)
+{
+ return rst_gpio;
+}
+
+int wmt_ts_get_lcdexchg(void)
+{
+ return lcd_exchg;
+}
+
+int wmt_ts_get_resolvX(void)
+{
+ return panelres_x;
+}
+
+int wmt_ts_get_resolvY(void)
+{
+ return panelres_y;
+}
+
+int wmt_ts_get_xaxis(void)
+{
+ return l_xaxis;
+}
+
+int wmt_ts_get_xdir(void)
+{
+ return l_xdirect;
+}
+
+int wmt_ts_get_yaxis(void)
+{
+ return l_yaxis;
+}
+
+int wmt_ts_get_ydir(void)
+{
+ return l_ydirect;
+}
+
+int wmt_ts_get_cutedge(void)
+{
+ return l_cutedge;
+}
+
+void wmt_ts_get_firmwname(char* firmname)
+{
+ sprintf(firmname,"ssd253x_%s_cfg.tpf",l_firmid);
+}
+
+int wmt_ts_get_fingernum(void)
+{
+ if (!strcmp(l_firmid,"10rs10f1609043psy1"))
+ {
+ return 10;
+ }
+ return 5;
+}
+
+//up:1-pen up,0-pen down
+void wmt_ts_set_penup(int up)
+{
+ l_penup = up;
+}
+
+//
+int wmt_ts_wait_penup(void)
+{
+ int ret = wait_event_interruptible(
+ ts_penup_wait_queue,
+ (1==l_penup));
+ return ret;
+}
+
+// return:1-pen up,0-pen dwon
+int wmt_ts_ispenup(void)
+{
+ return l_penup;
+}
+
+
+void wmt_ts_wakeup_penup(void)
+{
+ wake_up(&ts_penup_wait_queue);
+}
+
+int wmt_is_tsirq_enable(void)
+{
+ int val = 0;
+ int num = irq_gpio;
+
+ if(num > 11)
+ return 0;
+
+ if(num<4)
+ val = REG32_VAL(__GPIO_BASE+0x0300) & (1<<(num*8+7));
+ else if(num >= 4 && num < 8)
+ val = REG32_VAL(__GPIO_BASE+0x0304) & (1<<((num-4)*8+7));
+ else
+ val = REG32_VAL(__GPIO_BASE+0x0308) & (1<<((num-8)*8+7));
+
+ return val?1:0;
+
+}
+
+int wmt_is_tsint(void)
+{
+ int num = irq_gpio;
+
+ if (num > 11)
+ {
+ return 0;
+ }
+ return (REG32_VAL(__GPIO_BASE+0x0360) & (1<<num)) ? 1: 0;
+}
+
+void wmt_clr_int(void)
+{
+ int num = irq_gpio;
+
+ if (num > 11)
+ {
+ return;
+ }
+ REG32_VAL(__GPIO_BASE+0x0360) = 1<<num;
+}
+
+void wmt_tsreset_init(void)
+{
+ int num = rst_gpio;
+
+ REG32_VAL(__GPIO_BASE+0x0040) |= (1<<num);//&= ~(1<<num); //enable gpio
+ REG32_VAL(__GPIO_BASE+0x00C0) &= ~(1<<num); // out low
+ REG32_VAL(__GPIO_BASE+0x0080) |= (1<<num); //output enable
+ msleep(10);
+ REG32_VAL(__GPIO_BASE+0x00C0) |= (1<<num); // out high
+}
+
+// enable:0-disable,1-enable
+void wmt_enable_rst_pull(int enable)
+{
+ if (enable)
+ {
+ REG32_VAL(__GPIO_BASE+0x0480) |= (1<<rst_gpio); //enable pull up/down
+ } else {
+ REG32_VAL(__GPIO_BASE+0x0480) &= ~(1<<rst_gpio); //disable pull up/down
+ }
+}
+
+// up:0-pull down,1-pull up
+void wmt_set_rst_pull(int up)
+{
+ if (up)
+ {
+ REG32_VAL(__GPIO_BASE+0x04c0) |= (1<<rst_gpio); //pull up
+ } else {
+ REG32_VAL(__GPIO_BASE+0x04c0) &= ~(1<<rst_gpio); //pull down
+ }
+}
+
+// high:0-low level,1-high level
+void wmt_rst_output(int high)
+{
+ REG32_VAL(__GPIO_BASE+0x0040) |= (1<<rst_gpio); //enable gpio
+ if (high)
+ {
+ REG32_VAL(__GPIO_BASE+0x00C0) |= (1<<rst_gpio); // high
+ } else {
+ REG32_VAL(__GPIO_BASE+0x00C0) &= ~(1<<rst_gpio); // low
+ }
+ REG32_VAL(__GPIO_BASE+0x0080) |= (1<<rst_gpio); //set output
+}
+
+void wmt_rst_input(void)
+{
+ REG32_VAL(__GPIO_BASE+0x0040) |= (1<<rst_gpio); //enable gpio
+ REG32_VAL(__GPIO_BASE+0x0080) &= ~(1<<rst_gpio); //set input
+}
+
+void wmt_set_intasgp(void)
+{
+ REG32_VAL(__GPIO_BASE+0x0040) |= (1<<irq_gpio); //enable gpio
+}
+
+// val:1--high,0-low
+void wmt_intgp_out(int val)
+{
+ if (val)
+ {
+ REG32_VAL(__GPIO_BASE+0x00C0) |= (1<<irq_gpio); // high
+ } else {
+ REG32_VAL(__GPIO_BASE+0x00C0) &= ~(1<<irq_gpio); // low
+ }
+ REG32_VAL(__GPIO_BASE+0x0080) |= (1<<irq_gpio); //set output
+}
+
+void wmt_ts_set_irqinput(void)
+{
+ int num = irq_gpio;
+
+ REG32_VAL(__GPIO_BASE+0x0040) |= (1<<num); //enable gpio
+ REG32_VAL(__GPIO_BASE+0x0080) &= ~(1<<num); //set input
+}
+
+unsigned int wmt_ts_irqinval(void)
+{
+ return REG32_VAL(__GPIO_BASE+0x0000)&(1<<irq_gpio);
+}
+
+int wmt_set_gpirq(int type)
+{
+ int shift;
+ int offset;
+ unsigned long reg;
+ int num = irq_gpio;
+
+ if(num >11)
+ return -1;
+ //if (num > 9)
+ //GPIO_PIN_SHARING_SEL_4BYTE_VAL &= ~BIT4; // gpio10,11 as gpio
+ REG32_VAL(__GPIO_BASE+0x0040) &= ~(1<<num); //enable gpio
+ REG32_VAL(__GPIO_BASE+0x0080) &= ~(1<<num); //set input
+ REG32_VAL(__GPIO_BASE+0x04c0) |= (1<<num); //pull down
+ REG32_VAL(__GPIO_BASE+0x0480) &= ~(1<<num); //enable pull up/down
+
+ //set gpio irq triger type
+ if(num < 4){//[0,3]
+ shift = num;
+ offset = 0x0300;
+ }else if(num >= 4 && num < 8){//[4,7]
+ shift = num-4;
+ offset = 0x0304;
+ }else{// [8,11]
+ shift = num-8;
+ offset = 0x0308;
+ }
+
+ reg = REG32_VAL(__GPIO_BASE + offset);
+
+ switch(type){
+ case IRQ_TYPE_LEVEL_LOW:
+ reg &= ~(1<<(shift*8+2));
+ reg &= ~(1<<(shift*8+1));
+ reg &= ~(1<<(shift*8));
+ break;
+ case IRQ_TYPE_LEVEL_HIGH:
+ reg &= ~(1<<(shift*8+2));
+ reg &= ~(1<<(shift*8+1));
+ reg |= (1<<(shift*8));
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ reg &= ~(1<<(shift*8+2));
+ reg |= (1<<(shift*8+1));
+ reg &= ~(1<<(shift*8));
+ break;
+ case IRQ_TYPE_EDGE_RISING:
+ reg &= ~(1<<(shift*8+2));
+ reg |= (1<<(shift*8+1));
+ reg |= (1<<(shift*8));
+ break;
+ default://both edge
+ reg |= (1<<(shift*8+2));
+ reg &= ~(1<<(shift*8+1));
+ reg &= ~(1<<(shift*8));
+ break;
+
+ }
+ //reg |= 1<<(shift*8+7);//enable interrupt
+ reg &= ~(1<<(shift*8+7)); //disable int
+
+ REG32_VAL(__GPIO_BASE + offset) = reg;
+ REG32_VAL(__GPIO_BASE+0x0360) = 1<<num; //clear interrupt status
+ msleep(5);
+ return 0;
+}
+
+int wmt_enable_gpirq(void)
+{
+ int num = irq_gpio;
+
+ if(num > 11)
+ return -1;
+
+ if(num<4)
+ REG32_VAL(__GPIO_BASE+0x0300) |= 1<<(num*8+7); //enable interrupt
+ else if(num >= 4 && num < 8)
+ REG32_VAL(__GPIO_BASE+0x0304) |= 1<<((num-4)*8+7); //enable interrupt
+ else
+ REG32_VAL(__GPIO_BASE+0x0308) |= 1<<((num-8)*8+7); //enable interrupt
+
+ return 0;
+}
+
+int wmt_disable_gpirq(void)
+{
+ int num = irq_gpio;
+
+ if(num > 11)
+ return -1;
+
+ if(num<4)
+ REG32_VAL(__GPIO_BASE+0x0300) &= ~(1<<(num*8+7)); //enable interrupt
+ else if(num >= 4 && num < 8)
+ REG32_VAL(__GPIO_BASE+0x0304) &= ~(1<<((num-4)*8+7)); //enable interrupt
+ else
+ REG32_VAL(__GPIO_BASE+0x0308) &= ~(1<<((num-8)*8+7)); //enable interrupt
+
+ return 0;
+}
+
+
+int wmt_get_tsirqnum(void)
+{
+ return IRQ_GPIO;
+}
+
+
+int wmt_ts_set_rawcoord(unsigned short x, unsigned short y)
+{
+ g_evLast.x = x;
+ g_evLast.y = y;
+ //dbg("raw(%d,%d)*\n", x, y);
+ return 0;
+}
+
+static void wmt_ts_platform_release(struct device *device)
+{
+ return;
+}
+
+static struct platform_device wmt_ts_plt_device = {
+ .name = TS_DRIVER_NAME,
+ .id = 0,
+ .dev = {
+ .release = wmt_ts_platform_release,
+ },
+// .num_resources = ARRAY_SIZE(wm9715_ts_resources),
+// .resource = wm9715_ts_resources,
+};
+
+static int wmt_ts_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ dbg("ts suspend....\n");
+ return l_tsdev->suspend(pdev, state);
+}
+static int wmt_ts_resume(struct platform_device *pdev)
+{
+ dbg("ts resume....\n");
+ return l_tsdev->resume(pdev);
+}
+
+static int wmt_ts_probe(struct platform_device *pdev)
+{
+
+ if (l_tsdev->probe != NULL)
+ return l_tsdev->probe(pdev);
+ else
+ return 0;
+}
+
+static int wmt_ts_remove(struct platform_device *pdev)
+{
+
+ if (l_tsdev->remove != NULL)
+ return l_tsdev->remove(pdev);
+ else
+ return 0;
+}
+
+static struct platform_driver wmt_ts_plt_driver = {
+ .driver = {
+ .name = TS_DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = wmt_ts_probe,
+ .remove = wmt_ts_remove,
+ .suspend = wmt_ts_suspend,
+ .resume = wmt_ts_resume,
+};
+
+static int wmt_check_touch_env(void)
+{
+ int ret = 0;
+ int len = 150;
+ char retval[150] = {0},*p=NULL;
+ int Enable=0,Gpio=0,PX=0,PY=0;
+ char* s=NULL;
+
+ // Get u-boot parameter
+ ret = wmt_getsyspara("wmt.io.touch", retval, &len);
+ if(ret){
+ errlog("Read wmt.io.touch Failed.\n");
+ return -EIO;
+ }
+ sscanf(retval,"%d:",&Enable);
+ //check touch enable
+ if(Enable == 0){
+ errlog("Touch Screen Is Disabled.\n");
+ return -ENODEV;
+ }
+
+ p = strchr(retval,':');
+ p++;
+ if(strncmp(p, l_tsdev->ts_id,strlen(l_tsdev->ts_id))){//check touch ID
+ errlog("[WMTENV] %s is not found\n", l_tsdev->ts_id);
+ return -ENODEV;
+ }
+ // get firmwareid
+ s = p+strlen(l_tsdev->ts_id)+1; //point to firmware id
+ p = strchr(p,':');
+ memset(l_firmid,0,sizeof(l_firmid));
+ len = p-s;
+ if (len>=20)
+ {
+ len = 19;
+ }
+ strncpy(l_firmid,s,len);
+ p++;
+ sscanf(p,"%d:%d:%d:%d:%d:%d:%d:%d:%d",&Gpio,&PX,&PY,&rst_gpio,
+ &l_xaxis,&l_xdirect,
+ &l_yaxis,&l_ydirect,
+ &l_cutedge);
+
+ irq_gpio = Gpio;
+ panelres_x = PX;
+ panelres_y = PY;
+ dbg("p.x=%d,p.y=%d,gpio=%d,resetgpio=%d,\nx-axis=%d,x_dir=%d,y-axis=%d,y_dir=%d,cutedge=%d\nfirmwareid:%s\n",
+ panelres_x, panelres_y, irq_gpio, rst_gpio,
+ l_xaxis,l_xdirect,l_yaxis,l_ydirect,l_cutedge,
+ l_firmid);
+
+ memset(retval,0,sizeof(retval));
+ ret = wmt_getsyspara("wmt.display.fb0", retval, &len);
+ if (!ret) {
+ int tmp[6];
+ p = retval;
+ sscanf(p, "%d:[%d:%d:%d:%d:%d", &tmp[0], &tmp[1], &tmp[2], &tmp[3], &tmp[4], &tmp[5]);
+ if (tmp[4] > tmp[5])
+ lcd_exchg = 1;
+ }
+
+ return 0;
+}
+
+struct i2c_board_info ts_i2c_board_info = {
+ .type = WMT_TS_I2C_NAME,
+ .flags = 0x00,
+ .addr = WMT_TS_I2C_ADDR,
+ .platform_data = NULL,
+ .archdata = NULL,
+ .irq = -1,
+};
+
+static int ts_i2c_register_device (void)
+{
+ struct i2c_board_info *ts_i2c_bi;
+ struct i2c_adapter *adapter = NULL;
+ //struct i2c_client *client = NULL;
+ ts_i2c_bi = &ts_i2c_board_info;
+ adapter = i2c_get_adapter(1);/*in bus 1*/
+
+ if (NULL == adapter) {
+ printk("can not get i2c adapter, client address error\n");
+ return -1;
+ }
+ l_client = i2c_new_device(adapter, ts_i2c_bi);
+ if (l_client == NULL) {
+ printk("allocate i2c client failed\n");
+ return -1;
+ }
+ i2c_put_adapter(adapter);
+ return 0;
+}
+
+static void ts_i2c_unregister_device(void)
+{
+ if (l_client != NULL)
+ {
+ i2c_unregister_device(l_client);
+ l_client = NULL;
+ }
+}
+
+struct i2c_client* ts_get_i2c_client(void)
+{
+ return l_client;
+}
+
+static int __init wmt_ts_init(void)
+{
+ int ret = 0;
+
+ if(wmt_check_touch_env())
+ return -ENODEV;
+
+ if (ts_i2c_register_device()<0)
+ {
+ dbg("Error to run ts_i2c_register_device()!\n");
+ return -1;
+ }
+ mutex_init(&cal_mutex);
+
+ if (l_tsdev->init() < 0){
+ dbg("Errors to init %s ts IC!!!\n", l_tsdev->ts_id);
+ ret = -1;
+ goto err_init;
+ }
+ // Create device node
+/* if (register_chrdev (TS_MAJOR, TS_NAME, &wmt_ts_fops)) {
+ printk (KERN_ERR "wmt touch: unable to get major %d\n", TS_MAJOR);
+ return -EIO;
+ }
+
+ l_dev_class = class_create(THIS_MODULE, TS_NAME);
+ if (IS_ERR(l_dev_class)){
+ ret = PTR_ERR(l_dev_class);
+ printk(KERN_ERR "Can't class_create touch device !!\n");
+ return ret;
+ }
+ l_clsdevice = device_create(l_dev_class, NULL, MKDEV(TS_MAJOR, 0), NULL, TS_NAME);
+ if (IS_ERR(l_clsdevice)){
+ ret = PTR_ERR(l_clsdevice);
+ printk(KERN_ERR "Failed to create device %s !!!",TS_NAME);
+ return ret;
+ }
+*/
+ // register device and driver of platform
+ ret = platform_device_register(&wmt_ts_plt_device);
+ if(ret){
+ errlog("wmt ts plat device register failed!\n");
+ return ret;
+ }
+ ret = platform_driver_register(&wmt_ts_plt_driver);
+ if(ret){
+ errlog("can not register platform_driver_register\n");
+ platform_device_unregister(&wmt_ts_plt_device);
+ return ret;
+ }
+
+ klog("%s driver init ok!\n",l_tsdev->ts_id);
+ return 0;
+err_init:
+ ts_i2c_unregister_device();
+ return ret;
+}
+
+static void __exit wmt_ts_exit(void)
+{
+ dbg("%s\n",__FUNCTION__);
+
+ l_tsdev->exit();
+ platform_driver_unregister(&wmt_ts_plt_driver);
+ platform_device_unregister(&wmt_ts_plt_device);
+ //device_destroy(l_dev_class, MKDEV(TS_MAJOR, 0));
+ //unregister_chrdev(TS_MAJOR, TS_NAME);
+ //class_destroy(l_dev_class);
+ mutex_destroy(&cal_mutex);
+ ts_i2c_unregister_device();
+}
+
+
+module_init(wmt_ts_init);
+module_exit(wmt_ts_exit);
+
+MODULE_LICENSE("GPL");
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/ssd253x_ts/wmt_ts.h b/ANDROID_3.4.5/drivers/input/touchscreen/ssd253x_ts/wmt_ts.h
new file mode 100755
index 00000000..3506773a
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/ssd253x_ts/wmt_ts.h
@@ -0,0 +1,116 @@
+
+#ifndef WMT_TSH_201010191758
+#define WMT_TSH_201010191758
+
+#include <linux/platform_device.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/suspend.h>
+#include <linux/i2c.h>
+#include <linux/firmware.h>
+
+
+//#define DEBUG_WMT_TS
+#undef dbg
+#ifdef DEBUG_WMT_TS
+#define dbg(fmt, args...) printk(KERN_ALERT "[%s]: " fmt, __FUNCTION__ , ## args)
+#else
+#define dbg(fmt, args...)
+#endif
+
+#undef errlog
+#undef klog
+#define errlog(fmt, args...) printk("[%s]: " fmt, __FUNCTION__, ## args)
+#define klog(fmt, args...) printk("[%s]: " fmt, __FUNCTION__, ## args)
+
+#define WMT_TS_I2C_NAME "ssd253x-ts"
+#define WMT_TS_I2C_ADDR 0x01
+
+//////////////////////////////data type///////////////////////////
+typedef struct {
+ short pressure;
+ short x;
+ short y;
+ //short millisecs;
+} TS_EVENT;
+
+struct wmtts_device
+{
+ //data
+ char* driver_name;
+ char* ts_id;
+ //function
+ int (*init)(void);
+ int (*probe)(struct platform_device *platdev);
+ int (*remove)(struct platform_device *pdev);
+ void (*exit)(void);
+ int (*suspend)(struct platform_device *pdev, pm_message_t state);
+ int (*resume)(struct platform_device *pdev);
+ int (*capacitance_calibrate)(void);
+ int (*wait_penup)(struct wmtts_device*tsdev); // waiting untill penup
+ int penup; // 0--pendown;1--penup
+
+};
+
+struct ChipSetting {
+ char No;
+ char Reg;
+ char Data1;
+ char Data2;
+};
+
+
+//////////////////////////function interface/////////////////////////
+extern int wmt_ts_get_gpionum(void);
+extern int wmt_ts_iscalibrating(void);
+extern int wmt_ts_get_resolvX(void);
+extern int wmt_ts_get_resolvY(void);
+extern int wmt_ts_set_rawcoord(unsigned short x, unsigned short y);
+extern int wmt_set_gpirq(int type);
+extern int wmt_get_tsirqnum(void);
+extern int wmt_disable_gpirq(void);
+extern int wmt_enable_gpirq(void);
+extern int wmt_is_tsirq_enable(void);
+extern int wmt_is_tsint(void);
+extern void wmt_clr_int(void);
+extern void wmt_tsreset_init(void);
+extern int wmt_ts_get_resetgpnum(void);
+extern int wmt_ts_get_lcdexchg(void);
+extern void wmt_enable_rst_pull(int enable);
+extern void wmt_set_rst_pull(int up);
+extern void wmt_rst_output(int high);
+extern void wmt_rst_input(void);
+extern void wmt_set_intasgp(void);
+extern void wmt_intgp_out(int val);
+extern void wmt_ts_set_irqinput(void);
+extern unsigned int wmt_ts_irqinval(void);
+extern void wmt_ts_set_penup(int up);
+extern int wmt_ts_wait_penup(void);
+extern void wmt_ts_wakeup_penup(void);
+extern struct i2c_client* ts_get_i2c_client(void);
+extern int wmt_ts_ispenup(void);
+extern int wmt_ts_get_xaxis(void);
+extern int wmt_ts_get_xdir(void);
+extern int wmt_ts_get_yaxis(void);
+extern int wmt_ts_get_ydir(void);
+extern int wmt_ts_get_cutedge(void);
+extern void wmt_ts_get_firmwname(char* firmname);
+extern int wmt_ts_get_fingernum(void);
+
+extern void TouchPanelCalibrateAPoint(
+ int UncalX, //@PARM The uncalibrated X coordinate
+ int UncalY, //@PARM The uncalibrated Y coordinate
+ int *pCalX, //@PARM The calibrated X coordinate
+ int *pCalY //@PARM The calibrated Y coordinate
+ );
+
+//filepath:the path of firmware file;
+//firmdata:store the data from firmware file;
+//maxlen: the max len of firmdata;
+//return:the number of firmware data,negative-parsing error.
+extern int read_firmwarefile(char* filepath, struct ChipSetting** firmdata, int maxlen);
+
+#endif
+
+
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/vt1609_ts/Makefile b/ANDROID_3.4.5/drivers/input/touchscreen/vt1609_ts/Makefile
new file mode 100755
index 00000000..b3e5b2d3
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/vt1609_ts/Makefile
@@ -0,0 +1,4 @@
+
+obj-$(CONFIG_TOUCHSCREEN_VT1609) := vt1609_dual.o vt1609_ts.o
+
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/vt1609_ts/vt1609_dual.c b/ANDROID_3.4.5/drivers/input/touchscreen/vt1609_ts/vt1609_dual.c
new file mode 100755
index 00000000..c88872e5
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/vt1609_ts/vt1609_dual.c
@@ -0,0 +1,692 @@
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+//#include <linux/spinlock.h>
+#include <linux/input.h>
+#include <linux/cdev.h>
+#include <linux/time.h>
+#include <linux/spi/spi.h>
+#include <linux/platform_device.h>
+#include <mach/hardware.h>
+#include <linux/gpio.h>
+#include <mach/wmt_iomux.h>
+#include "vt1609_ts.h"
+
+
+//#define _DEBUG_
+
+#undef dbg
+#ifdef _DEBUG_
+#define dbg(fmt, args...) printk(KERN_ERR "[%s][%d]: " fmt, __func__ , __LINE__, ## args)
+#else
+#define dbg(fmt, args...)
+#endif
+
+#undef dbg_err
+#define dbg_err(fmt, args...) printk(KERN_ERR "[%s][%d]##ERROR##: " fmt, __func__ , __LINE__, ## args)
+
+#define VT1609_DUAL_VERSION "1.1"
+
+#define DUAL_BUF_LENGTH 17
+#define SINGLE_BUF_LEN 5
+#define MAX_SAMPLE_NUM 5
+#define POLL_TOUT 100
+#define DX_DETLA 4
+#define DX_NUM 5
+
+#define VXY 17
+#define SCALE_X 4
+#define SCALE_Y 2
+#define FILTER_COUNT_T1 2
+#define FILTER_COUNT_T2 5
+#define FILTER_COUNT_2T1 5
+#define SAMPLE_COUNT 4
+#define THRESHOLD_DX 256
+#define THRESHOLD_XY 1300
+#define THRESHOLD_DUAL_CNT 1
+
+#define CHL_X1 0x01
+#define CHL_X2 0x02
+#define CHL_X3 0x03
+#define CHL_Y1 0x04
+#define CHL_Y2 0x05
+#define CHL_Y3 0x06
+
+static int vxy_max_updated = 0;
+static int vx_max = 0;
+static int vy_max = 0;
+
+static int dual_cnt = 0;
+static int prv_dx = 0;
+static int dx1 = 0, dx2 = 0;
+
+static int TwoCT = 0;
+static int FirstCT = 0;
+static int TouchCT = 0 ;
+static int OneTCAfter2 = 0;
+static int TwoTouchFlag = 0;
+static struct vt1603_ts_pos pre,fixpos;
+
+//extern struct vt1603_ts_drvdata *pContext;
+
+struct dual_avg_buf {
+ int num;
+ u32 data[DUAL_BUF_LENGTH];
+};
+
+static struct dual_avg_buf x_buf;
+static struct dual_avg_buf y_buf;
+static struct dual_avg_buf avg_buf;
+
+static int vt1603_ts_get_ux(int *para);
+static int vt1603_ts_get_uy(int *para);
+static int vt1603_ts_get_vx(int *para);
+static int vt1603_ts_get_vy(int *para);
+
+static inline void dual_buf_fill(struct dual_avg_buf *dual_buf, u32 data, int len)
+{
+ dual_buf->data[dual_buf->num % len] = data;
+ dual_buf->num++;
+
+ return ;
+}
+
+static inline u32 dual_buf_avg(struct dual_avg_buf *dual_buf, int len)
+{
+ int i, num;
+ u32 avg = 0;
+ int max, min;
+
+ num = (dual_buf->num < len)? dual_buf->num : len;
+
+ if(num == 1)
+ return dual_buf->data[0];
+ if(num == 2)
+ return (dual_buf->data[0]+dual_buf->data[1])/2;
+
+ max = dual_buf->data[0];
+ min = dual_buf->data[0];
+ for (i = 0; i < num; i++){
+ avg += dual_buf->data[i];
+
+ if(dual_buf->data[i] > max)
+ max = dual_buf->data[i];
+
+ if(dual_buf->data[i] < min)
+ min = dual_buf->data[i];
+ }
+
+ return (avg-max-min )/ (num-2);
+}
+
+static void dual_buf_init(struct dual_avg_buf *dual_buf)
+{
+ memset(dual_buf, 0x00, sizeof(struct dual_avg_buf));
+ return ;
+}
+
+static inline void vt1603_ts_report_dual_pos(struct vt1603_ts_drvdata *ts_drv,
+ struct vt1603_ts_pos *fst,struct vt1603_ts_pos *lst)
+{
+ struct vt1603_ts_pos p1 = *fst;
+ struct vt1603_ts_pos p2 = *lst;
+
+ vt1603_ts_pos_calibration(ts_drv,&p1);
+ vt1603_ts_pos_calibration(ts_drv,&p2);
+ //dbg("Caled pos1 (%d, %d), pos2 (%d, %d)\n", p1.x, p1.y, p2.x, p2.y);
+
+ input_report_abs(ts_drv->input, ABS_MT_POSITION_X, p1.x);
+ input_report_abs(ts_drv->input, ABS_MT_POSITION_Y, p1.y);
+ input_mt_sync(ts_drv->input);
+
+ input_report_abs(ts_drv->input, ABS_MT_POSITION_X, p2.x);
+ input_report_abs(ts_drv->input, ABS_MT_POSITION_Y, p2.y);
+ input_mt_sync(ts_drv->input);
+
+ input_sync(ts_drv->input);
+
+ return;
+}
+
+static inline void vt1603_ts_auto_mode(struct vt1603_ts_drvdata *ts_drv)
+{
+ vt1603_set_reg8(ts_drv, VT1603_PWC_REG, 0x08);
+ /* auto position conversion mode and panel type config */
+ vt1603_set_reg8(ts_drv, VT1603_CR_REG, BIT1);
+ /* disable pen up/down detection, it is a MUST opearetion */
+ vt1603_set_reg8(ts_drv, 0xC8, 0x7F);
+
+ return;
+}
+
+static inline int select_channel(struct vt1603_ts_drvdata *ts_drv,int chl)
+{
+ switch(chl){
+ case CHL_X1://select x1
+ vt1603_set_reg8(ts_drv, 0xc6, 0x12);
+ vt1603_set_reg8(ts_drv, 0xc7, 0x05);
+ break;
+ case CHL_X2://select x2
+ vt1603_set_reg8(ts_drv, 0xc6, 0x12);
+ vt1603_set_reg8(ts_drv, 0xc7, 0x04);
+ break;
+ case CHL_X3://select x3
+ vt1603_set_reg8(ts_drv, 0xc6, 0x12);
+ vt1603_set_reg8(ts_drv, 0xc7, 0x00);
+ break;
+ case CHL_Y1://select y1
+ vt1603_set_reg8(ts_drv, 0xc6, 0x21);
+ vt1603_set_reg8(ts_drv, 0xc7, 0x07);
+ break;
+ case CHL_Y2://select y2
+ vt1603_set_reg8(ts_drv, 0xc6, 0x21);
+ vt1603_set_reg8(ts_drv, 0xc7, 0x06);
+ break;
+ case CHL_Y3://select y3
+ vt1603_set_reg8(ts_drv, 0xc6, 0x21);
+ vt1603_set_reg8(ts_drv, 0xc7, 0x03);
+ break;
+ default://default select x1
+ vt1603_set_reg8(ts_drv, 0xc6, 0x12);
+ vt1603_set_reg8(ts_drv, 0xc7, 0x05);
+ break;
+ }
+
+ return 0;
+}
+
+static inline int select_x_channel(struct vt1603_ts_drvdata *ts_drv,int chl)
+{
+ switch(chl){
+ case CHL_X1://select x1
+ vt1603_set_reg8(ts_drv, 0xc6, 0x21);
+ vt1603_set_reg8(ts_drv, 0xc7, 0x07);
+ break;
+ case CHL_X2://select x2
+ vt1603_set_reg8(ts_drv, 0xc6, 0x21);
+ vt1603_set_reg8(ts_drv, 0xc7, 0x06);
+ break;
+ case CHL_X3://select x3
+ vt1603_set_reg8(ts_drv, 0xc6, 0x21);
+ vt1603_set_reg8(ts_drv, 0xc7, 0x03);
+ break;
+ case CHL_Y1://select y1
+ vt1603_set_reg8(ts_drv, 0xc6, 0x12);
+ vt1603_set_reg8(ts_drv, 0xc7, 0x05);
+
+ break;
+ case CHL_Y2://select y2
+ vt1603_set_reg8(ts_drv, 0xc6, 0x12);
+ vt1603_set_reg8(ts_drv, 0xc7, 0x04);
+ break;
+ case CHL_Y3://select y3
+ vt1603_set_reg8(ts_drv, 0xc6, 0x12);
+ vt1603_set_reg8(ts_drv, 0xc7, 0x00);
+ break;
+ default://default select x1
+ vt1603_set_reg8(ts_drv, 0xc6, 0x12);
+ vt1603_set_reg8(ts_drv, 0xc7, 0x05);
+ break;
+ }
+
+ return 0;
+}
+
+static inline int get_channel_data(struct vt1603_ts_drvdata *ts_drv,int chl)
+{
+ int i = 0;
+ int sum = 0;
+ int buf[MAX_SAMPLE_NUM] = {0};
+ u32 now = 0;
+ u8 tmp = 0;
+
+ if(ts_drv->dual_dev.exch)
+ select_x_channel(ts_drv,chl);
+ else
+ select_channel(ts_drv,chl);
+
+ for (i = 0; i < ts_drv->dual_dev.SAMPLE_CNT; i++) {
+ vt1603_clrbits(ts_drv, VT1603_INTS_REG, 0x0f);
+ vt1603_set_reg8(ts_drv, VT1603_CR_REG, 0x10);
+ udelay(100);
+ now = jiffies;
+ while (time_before(jiffies, now + msecs_to_jiffies(POLL_TOUT))) {
+ tmp = vt1603_get_reg8(ts_drv, VT1603_INTS_REG);
+ if (tmp & BIT0) {
+ buf[i] = vt1603_get_reg8(ts_drv, 0xce);
+ tmp = (vt1603_get_reg8(ts_drv, 0xcf) & 0x0f);
+ buf[i] |= (tmp << 8);
+ sum += buf[i];
+ goto next;
+ }
+ }
+ printk("VT1609 %s timeout!\n", __func__);
+ return 0;
+
+ next:
+ ;//printk("CHL %d buf[%d] is %d\n", chl, i, buf[i]);
+ }
+
+ return sum/ts_drv->dual_dev.SAMPLE_CNT;
+
+}
+
+
+static inline int vt1603_get_paramters(struct vt1603_ts_drvdata *ts_drv, int *para)
+{
+ /* change to manual mode now */
+ vt1603_set_reg8(ts_drv, VT1603_CR_REG, 0x00);
+ /* set prechare to 0x10 */
+ vt1603_set_reg8(ts_drv, VT1603_TSPC_REG, 0x10);
+ /* get parameters now */
+ para[0] = get_channel_data(ts_drv, CHL_X1);
+ para[1] = get_channel_data(ts_drv, CHL_X2);
+ para[2] = get_channel_data(ts_drv, CHL_Y1);
+ para[3] = get_channel_data(ts_drv, CHL_Y2);
+
+ para[4] = get_channel_data(ts_drv, CHL_X3);
+ para[5] = get_channel_data(ts_drv, CHL_Y3);
+
+ /* reset adc, this is a MUST operation */
+ vt1603_set_reg8(ts_drv, 0xc8, 0x8f);
+ vt1603_set_reg8(ts_drv, 0xc0, BIT6 | BIT5 | BIT0);
+
+ return 0;
+}
+
+static int vt1603_get_vxy(struct vt1603_ts_drvdata *ts_drv, int *vx, int *vy)
+{
+ int i;
+ int xbuf[5] ={0}, ybuf[5] ={0};
+ int sum_vx = 0,sum_vy = 0;
+ int max_vx = 0,min_vx = 0;
+ int max_vy = 0,min_vy = 0;
+
+ /* change to manual mode now */
+ vt1603_set_reg8(ts_drv, VT1603_CR_REG, 0x00);
+ /* set prechare to 0x10 */
+ vt1603_set_reg8(ts_drv, VT1603_TSPC_REG, 0x10);
+ for(i=0; i<5; i++){
+ xbuf[i] = get_channel_data(ts_drv,CHL_X3);
+ ybuf[i] = get_channel_data(ts_drv,CHL_Y3);
+ sum_vx += xbuf[i];
+ sum_vy += ybuf[i];
+ }
+
+ max_vx = min_vx = xbuf[0];
+ max_vy = min_vy = ybuf[0];
+
+ for(i=0; i<5; i++){
+ if(xbuf[i] > max_vx)
+ max_vx = xbuf[i];
+
+ if(xbuf[i] < min_vx)
+ min_vx = xbuf[i];
+
+ if(ybuf[i] > max_vy)
+ max_vy = ybuf[i];
+
+ if(ybuf[i] < min_vy)
+ min_vy = ybuf[i];
+ }
+ *vx = (sum_vx - max_vx - min_vx)/3;
+ *vy = (sum_vy - max_vy - min_vy)/3;
+ dbg("updated vx_max=%d; vy_max=%d\n",*vx, *vy);
+ /* reset adc, this is a MUST operation */
+ vt1603_set_reg8(ts_drv, 0xc8, 0x8f);
+ vt1603_set_reg8(ts_drv, 0xc0, BIT6 | BIT5 | BIT0);
+
+ return 0;
+}
+
+static inline int vt1603_ts_get_ux(int *para)
+{
+ return abs(para[1] - para[0]);
+}
+
+static inline int vt1603_ts_get_uy(int *para)
+{
+ return abs(para[3] - para[2]);
+}
+
+static inline int vt1603_ts_get_vx(int *para)
+{
+ return abs(vx_max - para[4]);
+}
+
+static inline int vt1603_ts_get_vy(int *para)
+{
+ return abs(vy_max - para[5]);
+}
+
+static inline int vt1603_ts_nTouch(struct vt1603_ts_drvdata *ts_drv, int *para)
+{
+ int ux, uy, vx, vy;
+
+ ux = vt1603_ts_get_ux(para);
+ uy = vt1603_ts_get_uy(para);
+ vx = vt1603_ts_get_vx(para);
+ vy = vt1603_ts_get_vy(para);
+ //printk("ux:%-3d, uy:%-3d, vx:%-3d, vy:%-3d\n", ux, uy, vx, vy);
+
+ if ((vx <= 5) && (vy <= 5)){
+ dual_cnt = 0;
+ return Single_TOUCH;
+ }else if ((vx >= ts_drv->dual_dev.vxy) || (vy >= ts_drv->dual_dev.vxy)){
+ dual_cnt++;
+ //printk("ux:%-3d, uy:%-3d, vx:%-3d, vy:%-3d\n", ux, uy, vx, vy);
+ return (dual_cnt > THRESHOLD_DUAL_CNT)? Multi_TOUCH : Single_TOUCH;
+ }else if (((vx > 5) || (vy > 5)) && ((ux >= 2 * ts_drv->dual_dev.vxy) || (uy >= 2 * ts_drv->dual_dev.vxy))){
+ dual_cnt++;
+ //printk("ux:%-3d, uy:%-3d, vx:%-3d, vy:%-3d\n", ux, uy, vx, vy);
+ return (dual_cnt > THRESHOLD_DUAL_CNT)? Multi_TOUCH : Single_TOUCH;
+ }else{
+ dual_cnt = 0;
+ return Single_TOUCH;
+ }
+
+}
+
+static int pos_fix(const int limit, int p)
+{
+ if (p > limit) p = limit;
+ if (p < 0) p = 0;
+
+ return (u16)(p & 0xffff);
+}
+
+static int vt1603_ts_update_vxy(struct vt1603_ts_drvdata *ts_drv, int *vx, int *vy)
+{
+ u8 val;
+ int timeout = 100;
+
+ val = vt1603_get_reg8(ts_drv, VT1603_CR_REG);
+ while (timeout-- && val != 0x02) {
+ msleep(20);
+ val = vt1603_get_reg8(ts_drv, VT1603_CR_REG);
+ }
+
+ if(!timeout){
+ dbg_err("get vx_max/vy_max failed!\n");
+ goto out;
+ }
+
+ vt1603_get_vxy(ts_drv, vx,vy);
+ dbg("update vx_max:%d, vy_max:%d\n", vx_max, vy_max);
+
+out:
+ vt1603_set_reg8(ts_drv, VT1603_INTS_REG, 0x0F);
+
+ return 0;
+}
+
+void vt1603_ts_dual_support(struct work_struct* dwork)
+{
+ int nTouch = 0;
+ int para[6] = { 0 };
+ //unsigned long flags = 0;
+ int vx = 0, vy = 0, dx = 0;
+ struct vt1603_ts_pos p,pos1, pos2;
+ struct vt1603_ts_drvdata *ts_drv = NULL;
+ u8 int_sts = 0;
+
+ ts_drv = container_of(dwork, struct vt1603_ts_drvdata, dual_work.work);
+
+ //spin_lock_irqsave(&ts_drv->spinlock, flags);
+ mutex_lock(&ts_drv->ts_mutex);
+
+ int_sts = vt1603_get_reg8(ts_drv, VT1603_INTS_REG);
+ if (int_sts & BIT4 || ts_drv->earlysus) {
+ if (jiffies_to_msecs(jiffies - ts_drv->ts_stamp) < TS_DEBOUNCE && !ts_drv->earlysus) {
+ dbg("vt1603 ts debouncing?...\n");
+ //vt1603_clr_ts_irq(ts_drv, int_sts & 0x0F);
+ goto next_loop;
+ }
+ dbg("======= penup ======\n");
+
+ /* update vx_max/vy_max only when first penup */
+ if(!vxy_max_updated){
+ vxy_max_updated ++;
+ vt1603_ts_update_vxy(ts_drv, &vx_max, &vy_max);
+ }
+ vt1603_ts_auto_mode(ts_drv);
+ /* vt1603 gpio1 as IRQ output */
+ vt1603_set_reg8(ts_drv, VT1603_ISEL_REG36, 0x04);
+ input_mt_sync(ts_drv->input);
+ input_sync(ts_drv->input);
+ ts_drv->pen_state = TS_PENUP_STATE;
+ #ifdef TOUCH_KEY
+ vt1603_ts_report_key(ts_drv);
+ #endif
+ dual_buf_init(&avg_buf);
+ dual_buf_init(&x_buf);
+ dual_buf_init(&y_buf);
+
+ dx2 = 0;
+ dx1 = 0;
+ pre.x = 0;
+ pre.y = 0;
+ FirstCT = 0;
+ TwoCT = 0;
+ TouchCT = None_TOUCH;
+ OneTCAfter2 = 0;
+ TwoTouchFlag = 0;
+ vt1603_clr_ts_irq(ts_drv, int_sts & 0x0F);
+
+ if(!ts_drv->earlysus)
+ wmt_gpio_unmask_irq(ts_drv->intgpio);
+
+ //spin_unlock_irqrestore(&ts_drv->spinlock, flags);
+ mutex_unlock(&ts_drv->ts_mutex);
+
+ return;
+ }
+
+ ts_drv->ts_stamp = jiffies;
+ ts_drv->pen_state = TS_PENDOWN_STATE;
+ vt1603_get_paramters(ts_drv, para);
+ vt1603_ts_auto_mode(ts_drv);
+ //vt1603_clr_ts_irq(ts_drv, 0x0F & int_sts);
+
+ nTouch = vt1603_ts_nTouch(ts_drv, para);
+ if(nTouch == Single_TOUCH){
+ p.x = (para[0] + para[1]) / 2;
+ p.y = (para[2] + para[3]) / 2;
+
+ if(TwoTouchFlag ==0 && FirstCT < ts_drv->dual_dev.F1_CNT){
+ FirstCT ++;
+ dbg("Filter First %d Single Touch\n",FirstCT);
+ goto next_loop;
+
+ }else if(TwoTouchFlag == 1 && OneTCAfter2 < ts_drv->dual_dev.F2T1_CNT){
+ dbg("Filter First %d pointer when back to single touch from dual touch\n",OneTCAfter2);
+ dx1 = 0;
+ dx2 = 0;
+ TwoCT = 0;
+ OneTCAfter2 ++;
+ dual_buf_init(&x_buf);
+ dual_buf_init(&y_buf);
+ dual_buf_init(&avg_buf);
+ goto next_loop;
+
+ }else if(p.x > vx_max || p.y > vy_max){
+ dbg("Pos (%d,%d) beyond vx_max or vy_max\n",p.x,p.y);
+ goto next_loop;
+
+ }else if((pre.x!=0 && pre.y!=0) && (abs(pre.x-p.x) > THRESHOLD_XY||abs(pre.y-p.y) > THRESHOLD_XY )){
+ dbg("Threhold Filter Pos (%-4d,%-4d) ,dx=%-4d,dy=%-4d\n",p.x,p.y,abs(pre.x-p.x),abs(pre.y-p.y));
+ pre.x = p.x;
+ pre.y = p.y;
+ goto next_loop;
+
+ }else{
+ dual_buf_fill(&x_buf, p.x, SINGLE_BUF_LEN);
+ dual_buf_fill(&y_buf, p.y, SINGLE_BUF_LEN);
+ p.x = dual_buf_avg(&x_buf, SINGLE_BUF_LEN);
+ p.y = dual_buf_avg(&y_buf, SINGLE_BUF_LEN);
+ dbg("Report PHY Pos (%-4d,%-4d)\n",p.x,p.y);
+ pre.x = p.x;
+ pre.y = p.y;
+ #ifdef TOUCH_KEY
+ if(vt1603_ts_get_key(ts_drv, p))
+ goto next_loop;
+ #endif
+
+ vt1603_ts_report_pos(ts_drv, &p);
+
+ TwoCT = 0;
+ TouchCT = Single_TOUCH;
+ OneTCAfter2 = 0;
+ TwoTouchFlag = 0;
+ goto next_loop;
+ }
+ }
+ else if(nTouch == Multi_TOUCH){
+ vx = vt1603_ts_get_vx(para);
+ vy = vt1603_ts_get_vy(para);
+ dx = ts_drv->dual_dev.scale_y * vy + ts_drv->dual_dev.scale_x * vx;
+
+ if(dx1 && dx2)
+ dx = (dx+dx1+dx2)/3;
+ dx2 = dx1;
+ dx1 = dx;
+ dbg("vx=%-3d, vy=%-3d, dx=%-d, Ddx=%-3d\n",vx,vy,dx,abs(prv_dx-dx));
+
+ if(TwoCT < ts_drv->dual_dev.F2_CNT){
+ TwoCT ++;
+ dual_buf_init(&avg_buf);
+ dbg("Filter The First %d Dual Touch\n",TwoCT);
+ goto next_loop;
+
+ }else if (prv_dx!=0 && (abs(prv_dx - dx) > ts_drv->dual_dev.THR_MAX_DX)){
+ dbg("Threhold Filter Dual Touch dx=%d\n",abs(prv_dx - dx) );
+ prv_dx = dx;
+ goto next_loop;
+
+ }else{
+ //process and report dual touch data
+ dual_buf_fill(&avg_buf, dx, DUAL_BUF_LENGTH);
+ dx = dual_buf_avg(&avg_buf, DUAL_BUF_LENGTH);
+
+ if(abs(prv_dx - dx) < ts_drv->dual_dev.THR_MIN_DX){
+ //printk("Replace with last dx Ddx=%d\n",abs(prv_dx - dx));
+ dx = prv_dx;
+ }
+
+ if(TwoTouchFlag==0 && TouchCT==Single_TOUCH){//Single Touch ->Multi Touch
+ fixpos = pre;
+ //printk("Touch(%-4d,%-4d) 1--->2\n",pre.x,pre.y);
+ }else if(TwoTouchFlag==0 && TouchCT==None_TOUCH){//Multi Touch from the beginning
+ fixpos.x = vx_max/2;
+ fixpos.y = vy_max/2;
+ //printk("Touch(%-4d,%-4d) 2--->2\n",pos1.x, pos1.y);
+ }
+
+ pos1 = fixpos;
+ pos2.x = fixpos.x;
+ if(fixpos.y > vy_max/2)
+ pos2.y = pos_fix(vy_max, (fixpos.y - 150 - dx*DX_DETLA/DX_NUM));
+ else
+ pos2.y = pos_fix(vy_max, (fixpos.y + 150 + dx*DX_DETLA/DX_NUM));
+
+ dbg("PHY dx=%d, pos1.y=%d, pos2.y=%d\n", dx, pos1.y, pos2.y);
+ vt1603_ts_report_dual_pos(ts_drv, &pos1, &pos2);
+
+ prv_dx = dx;
+ TouchCT = Multi_TOUCH;
+ TwoTouchFlag = 1;
+ OneTCAfter2 = 0;
+ #ifdef TOUCH_KEY
+ if(ts_drv->touch_key_used && ts_drv->ledgpio >= 0)
+ set_key_led_gpio(ts_drv,HIGH);
+ #endif
+ goto next_loop;
+ }
+ }
+ else{
+ dbg_err("Main Loop Error!\n");
+ }
+
+next_loop:
+ queue_delayed_work(ts_drv->workqueue, &ts_drv->dual_work, msecs_to_jiffies(20));
+ vt1603_clr_ts_irq(ts_drv, 0x0f);
+ //spin_unlock_irqrestore(&ts_drv->spinlock, flags);
+ mutex_unlock(&ts_drv->ts_mutex);
+
+ return ;
+}
+
+int vt1603_dual_init(struct vt1603_ts_drvdata *ts_drv)
+{
+ int ret = 0;
+ //unsigned long flags = 0;
+ int retries = 20;
+ u8 val = 0;
+
+ if (ts_drv == NULL) {
+ printk(KERN_ERR "VT1609 TouchScreen Driver Does Not Exsit!\n");
+ ret = -1;
+ goto out;
+ }
+
+ //spin_lock_irqsave(&ts_drv->spinlock, flags);
+ mutex_lock(&ts_drv->ts_mutex);
+
+ while (retries--) {
+ val = vt1603_get_reg8(ts_drv, VT1603_INTS_REG);
+ if ((val & BIT4) == 0) {
+ printk(KERN_ERR "Do not keep in touching, when vt1609 driver to be installed!\n");
+ msleep(20);
+ continue ;
+ }
+
+ val = vt1603_get_reg8(ts_drv, VT1603_CR_REG);
+ if ( val != 0x02) {
+ printk(KERN_ERR "VT1609 is not working in TS mode now!reg: C1=0x%02x\n",val);
+ msleep(10);
+ continue;
+ }
+
+ break ;
+ }
+
+ if (retries == 0) {
+ printk(KERN_ERR "Enable VT1609 Dual Touch Support Failed!\n");
+ ret = -1;
+ goto out;
+ }
+
+
+ vt1603_set_reg8(ts_drv, VT1603_CDPR_REG, 0x04);
+ vt1603_set_reg8(ts_drv, VT1603_TSPC_REG, 0x10);
+ vt1603_get_vxy(ts_drv, &vx_max, &vy_max);
+ vt1603_ts_auto_mode(ts_drv);
+ vt1603_clr_ts_irq(ts_drv, BIT0 | BIT2 | BIT3);
+
+ dual_buf_init(&avg_buf);
+ dual_buf_init(&x_buf);
+ dual_buf_init(&y_buf);
+
+ printk("VT1609 Dual Touch vx_max=%d,vy_max=%d, vxy=%d ver=%s\n",vx_max, vy_max,ts_drv->dual_dev.vxy,VT1609_DUAL_VERSION);
+out:
+ vt1603_clr_ts_irq(ts_drv, 0x0f);
+ //spin_unlock_irqrestore(&ts_drv->spinlock, flags);
+ mutex_unlock(&ts_drv->ts_mutex);
+
+ return ret;
+}
+
+void vt1603_dual_exit(struct vt1603_ts_drvdata *ts_drv)
+{
+ vt1603_set_reg8(ts_drv, VT1603_CDPR_REG, ts_drv->pdata->sclk_div);
+ vt1603_set_reg8(ts_drv, VT1603_TSPC_REG, 0x20);
+ printk("VT1609 Dual Touch Support Disabled.\n");
+
+ return ;
+}
+
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/vt1609_ts/vt1609_ts.c b/ANDROID_3.4.5/drivers/input/touchscreen/vt1609_ts/vt1609_ts.c
new file mode 100755
index 00000000..f41634fc
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/vt1609_ts/vt1609_ts.c
@@ -0,0 +1,1481 @@
+/*
+ * vt1603_mt_i2c.c: VT1603A Touch-Panel Controller and SAR-ADC Driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * History: 2011.Jan.21st, version: 1.00
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+//#include <linux/spinlock.h>
+#include <linux/input.h>
+#include <linux/random.h>
+#include <linux/cdev.h>
+#include <asm/uaccess.h>
+#include <linux/i2c.h>
+#include <linux/spi/spi.h>
+#include <linux/platform_device.h>
+#include <mach/hardware.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <mach/wmt_iomux.h>
+
+#include "vt1609_ts.h"
+
+
+//#define VT1609_DEBUG
+
+#undef dbg
+#ifdef VT1609_DEBUG
+#define dbg(fmt, args...) printk(KERN_ERR "[%s][%d]: " fmt, __func__ , __LINE__, ##args)
+#else
+#define dbg(fmt, args...)
+#endif
+
+static struct vt1603_fifo px;
+static struct vt1603_fifo py;
+static struct class *vt1603_ts_class;
+static struct vt1603_ts_pos pre_pos;
+static struct vt1603_ts_cal_info g_CalcParam;
+struct vt1603_ts_drvdata *pContext = NULL;
+
+static int vt1603_ts_isPendown(struct vt1603_ts_drvdata *ts_drv);
+static void vt1603_ts_dev_cleanup(struct vt1603_ts_drvdata *ts_drv);
+
+#ifdef TOUCH_KEY
+static unsigned int key_codes[TOUCH_KEY_NUM] = {
+ [0] = KEY_SEARCH,
+ [1] = KEY_BACK,
+ [2] = KEY_HOME,
+ [3] = KEY_MENU,
+};
+#endif
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void vt1603ts_early_suspend(struct early_suspend *h);
+static void vt1603ts_late_resume(struct early_suspend *h);
+#endif
+
+#ifdef TOUCH_KEY
+static int setup_led_gpio(struct vt1603_ts_drvdata *ts_drv)
+{
+ if (ts_drv->ledgpio >= 0)
+ gpio_direction_output(ts_drv->ledgpio, 0);
+
+ return 0;
+}
+
+int set_key_led_gpio(struct vt1603_ts_drvdata *ts_drv, int val)
+{
+ if (ts_drv->ledgpio >= 0) {
+ if(val)
+ gpio_direction_output(ts_drv->ledgpio, 1);
+ else
+ gpio_direction_output(ts_drv->ledgpio, 0);
+ }
+
+ return 0;
+}
+
+static void led_timer_func(unsigned long data)
+{
+ set_key_led_gpio((struct vt1603_ts_drvdata *)data,LOW);
+ return;
+}
+
+#endif
+
+
+/*
+ * vt1603_set_reg8 - set register value of vt1603
+ * @ts_drv: vt1603 driver data
+ * @reg: vt1603 register address
+ * @val: value register will be set
+ */
+inline int vt1603_set_reg8(struct vt1603_ts_drvdata *ts_drv, u8 reg, u8 val)
+{
+ int ret =0;
+ if (ts_drv->tdev)
+ ret = ts_drv->tdev->reg_write(ts_drv->tdev,reg,val);
+
+ if(ret)
+ printk("vt1609 ts write error, errno%d\n", ret);
+
+ return ret;
+}
+
+/*
+ * vt1603_get_reg8 - get register value of vt1603
+ * @ts_drv: vt1603 driver data
+ * @reg: vt1603 register address
+ */
+inline u8 vt1603_get_reg8(struct vt1603_ts_drvdata *ts_drv, u8 reg)
+{
+ u8 val = 0;
+ int ret = 0;
+
+ if (ts_drv->tdev)
+ ret = ts_drv->tdev->reg_read(ts_drv->tdev,reg,&val);
+
+ if (ret)
+ printk("vt1609 ts read error, errno%d\n", ret);
+
+ return val;
+}
+
+
+#ifdef VT1609_DEBUG
+/*
+ * vt1603_reg_dump - dubug function, for dump vt1603 related registers
+ * @ts_drv: vt1603 driver data
+ */
+static void vt1603_reg_dump(struct vt1603_ts_drvdata *ts_drv)
+{
+ u8 i;
+ for (i = 0; i < 15; i++)
+ dbg("reg[%d]:0x%02X, reg[%d]:0x%02X\n",
+ i, vt1603_get_reg8(ts_drv, i), i + 0xC0, vt1603_get_reg8(ts_drv, i + 0xC0));
+}
+#endif
+
+/*
+ * vt1603_setbits - write bit1 to related register's bit
+ * @ts_drv: vt1603 driver data
+ * @reg: vt1603 register address
+ * @mask: bit setting mask
+ */
+inline void vt1603_setbits(struct vt1603_ts_drvdata *ts_drv, u8 reg, u8 mask)
+{
+ u8 tmp = 0;
+ tmp = vt1603_get_reg8(ts_drv, reg) | mask;
+ vt1603_set_reg8(ts_drv, reg, tmp);
+
+ return;
+}
+
+
+/*
+ * vt1603_clrbits - write bit0 to related register's bit
+ * @ts_drv: vt1603 driver data
+ * @reg: vt1603 register address
+ * @mask:bit setting mask
+ */
+inline void vt1603_clrbits(struct vt1603_ts_drvdata *ts_drv, u8 reg, u8 mask)
+{
+ u8 tmp = vt1603_get_reg8(ts_drv, reg) & (~mask);
+ vt1603_set_reg8(ts_drv, reg, tmp);
+
+ return;
+}
+
+/*
+ * vt1603_clr_ts_irq - clear touch panel pen down/up and
+ * conversion end/timeout interrupts
+ * @ts_drv: vt1603 driver data
+ * @mask: which interrupt will be cleared
+ */
+inline int vt1603_clr_ts_irq(struct vt1603_ts_drvdata *ts_drv, u8 mask)
+{
+ vt1603_setbits(ts_drv, VT1603_INTS_REG, mask);
+ return 0;
+}
+
+
+/*
+ * Enable I2S CLK, wmt-i2s.c have done this.
+ */
+static void vt1603_ts_clk_enable(void)
+{
+#if 0
+ /* set to 11.288MHz */
+ auto_pll_divisor(DEV_I2S, CLK_ENABLE , 0, 0);
+ auto_pll_divisor(DEV_I2S, SET_PLLDIV, 1, 11288);
+ /*clock = auto_pll_divisor(DEV_I2S, GET_FREQ , 0, 0);
+ info("%s : clock=%d \n" , __func__, clock);*/
+
+ /* Enable BIT4:ARFP clock, BIT3:ARF clock */
+ PMCEU_VAL |= (BIT4 | BIT3);
+
+ /* Enable BIT2:AUD clock */
+ PMCE3_VAL |= BIT2;
+
+ /* disable GPIO and Pull Down mode */
+ GPIO_CTRL_GP10_I2S_BYTE_VAL &= ~0xFF;
+ GPIO_CTRL_GP27_BYTE_VAL &= ~(BIT0 | BIT1 | BIT2);
+
+ GPIO_PULL_EN_GP10_I2S_BYTE_VAL &= ~0xFF;
+ GPIO_PULL_EN_GP27_BYTE_VAL &= ~(BIT0 | BIT1 | BIT2);
+
+ /* set to 2ch input, 2ch output */
+ GPIO_PIN_SHARING_SEL_4BYTE_VAL &= ~(BIT3 | BIT17 | BIT19 | BIT20 | BIT22);
+ GPIO_PIN_SHARING_SEL_4BYTE_VAL |= (BIT0 | BIT2 | BIT16 | BIT18 | BIT21);
+#endif
+ return;
+}
+
+/*
+ * vt1603_setup_ts_mode - switch to VT1603 TS mode
+ * @ts_drv: vt1603 driver data
+ */
+static int vt1603_setup_ts_mode(struct vt1603_ts_drvdata *ts_drv)
+{
+ int ret = 0;
+ struct vt1603_ts_platform_data *ts_pdata;
+
+ ts_pdata = ts_drv->pdata;
+ ret |= vt1603_set_reg8(ts_drv, VT1603_CDPR_REG, ts_pdata->sclk_div);
+ if (ts_pdata->panel_type == PANEL_TYPE_4WIRED)
+ ret |= vt1603_set_reg8(ts_drv, VT1603_CR_REG, BIT1);
+ else
+ ret |= vt1603_set_reg8(ts_drv, VT1603_CR_REG, BIT1 | BIT0);
+
+ vt1603_clr_ts_irq(ts_drv, 0x0f);
+
+ return (ret < 0)? -1 : 0;
+
+}
+
+
+static int vt1603_fifo_push(struct vt1603_fifo *Fifo, int Data)
+{
+ Fifo->buf[Fifo->head] = Data;
+ Fifo->head++;
+ if(Fifo->head >= VT1603_FIFO_LEN){
+ Fifo->head = 0;
+ Fifo->full = 1;
+ }
+
+ return 0;
+}
+
+static int vt1603_fifo_avg(struct vt1603_fifo Fifo, int *Data)
+{
+ int i=0;
+ int Sum=0,Max=0,Min=0;
+
+ if(!Fifo.full && !Fifo.head)//FIFO is empty
+ return 0;
+
+ if(!Fifo.full ){
+ for(i=0; i<Fifo.head; i++)
+ Sum += Fifo.buf[i];
+
+ *Data = Sum/Fifo.head;
+ return 0;
+ }
+
+ Max = Fifo.buf[0];
+ Min = Fifo.buf[0];
+ for(i=0; i<VT1603_FIFO_LEN; i++){
+ Sum += Fifo.buf[i];
+
+ if(Max < Fifo.buf[i])
+ Max = Fifo.buf[i];
+
+ if(Min > Fifo.buf[i])
+ Min = Fifo.buf[i];
+ }
+ Sum -= Max;
+ Sum -= Min;
+ *Data = Sum/(VT1603_FIFO_LEN-2);
+
+ return 0;
+
+}
+
+
+inline int vt1603_ts_pos_calibration(struct vt1603_ts_drvdata *ts_drv,struct vt1603_ts_pos *to_cal)
+{
+ int x, y;
+
+ x = (g_CalcParam.a1 * to_cal->x + g_CalcParam.b1 * to_cal->y +
+ g_CalcParam.c1) / g_CalcParam.delta;
+ y = (g_CalcParam.a2 * to_cal->x + g_CalcParam.b2 * to_cal->y +
+ g_CalcParam.c2) / g_CalcParam.delta;
+
+ /* pos check */
+ if (x < 0)
+ x = 0;
+ if (y < 0)
+ y = 0;
+ if (x > ts_drv->resl_x)
+ x = ts_drv->resl_x - 1;
+ if (y > ts_drv->resl_y)
+ y = ts_drv->resl_y - 1;
+
+ if (ts_drv->lcd_exchg) {
+ int tmp;
+ tmp = x;
+ x = y;
+ y = ts_drv->resl_x - tmp;
+ }
+
+ to_cal->x = x;
+ to_cal->y = y;
+
+ return 0;
+}
+
+static inline void vt1603_ts_set_rawdata(struct vt1603_ts_drvdata *ts_drv,struct vt1603_ts_pos *pos)
+{
+ ts_drv->raw_x = pos->x;
+ ts_drv->raw_y = pos->y;
+
+ return;
+}
+
+inline void vt1603_ts_report_pos(struct vt1603_ts_drvdata *ts_drv, struct vt1603_ts_pos *pos)
+{
+ vt1603_ts_set_rawdata(ts_drv,pos);
+ vt1603_ts_pos_calibration(ts_drv,pos);
+
+ input_report_abs(ts_drv->input, ABS_MT_POSITION_X, pos->x);
+ input_report_abs(ts_drv->input, ABS_MT_POSITION_Y, pos->y);
+ input_mt_sync(ts_drv->input);
+ input_sync(ts_drv->input);
+
+ return;
+}
+
+#ifdef TOUCH_KEY
+void vt1603_ts_report_key(struct vt1603_ts_drvdata *ts_drv)
+{
+ if(ts_drv->touch_key_used ){
+
+ if(ts_drv->ledgpio >= 0 )
+ mod_timer(&ts_drv->led_timer, jiffies+10*HZ);
+
+ if(ts_drv->key_pressed && ts_drv->key_idx < _MAX_NUM ){
+ input_report_key(ts_drv->input, key_codes[ts_drv->key_idx], 1);
+ input_sync(ts_drv->input);
+ input_report_key(ts_drv->input, key_codes[ts_drv->key_idx], 0);
+ input_sync(ts_drv->input);
+ dbg("report as key event %d \n",ts_drv->key_idx);
+ }
+ }
+
+ return;
+}
+
+inline int vt1603_ts_get_key(struct vt1603_ts_drvdata *ts_drv,struct vt1603_ts_pos pos)
+{
+ if(ts_drv->touch_key_used){
+
+ if(pos.y > ts_drv->tsc_key.low && pos.y < ts_drv->tsc_key.upper){
+
+ ts_drv->key_pressed = 1;
+ if(pos.x>(ts_drv->tsc_key.key[_SEARCH].pos-ts_drv->tsc_key.delta) &&
+ pos.x<(ts_drv->tsc_key.key[_SEARCH].pos+ts_drv->tsc_key.delta)){
+ ts_drv->key_idx = ts_drv->tsc_key.key[_SEARCH].idx;
+ }
+ else if(pos.x>(ts_drv->tsc_key.key[_BACK].pos-ts_drv->tsc_key.delta) &&
+ pos.x<(ts_drv->tsc_key.key[_BACK].pos+ts_drv->tsc_key.delta)){
+ ts_drv->key_idx = ts_drv->tsc_key.key[_BACK].idx;
+ }
+ else if(pos.x>(ts_drv->tsc_key.key[_HOME].pos-ts_drv->tsc_key.delta) &&
+ pos.x<(ts_drv->tsc_key.key[_HOME].pos+ts_drv->tsc_key.delta)){
+ ts_drv->key_idx = ts_drv->tsc_key.key[_HOME].idx;
+ }
+ else if(pos.x>(ts_drv->tsc_key.key[_MENU].pos-ts_drv->tsc_key.delta) &&
+ pos.x<(ts_drv->tsc_key.key[_MENU].pos+ts_drv->tsc_key.delta)){
+ ts_drv->key_idx = ts_drv->tsc_key.key[_MENU].idx;
+ }
+ else{
+ ts_drv->key_idx = _MAX_NUM;
+ }
+
+ if(ts_drv->key_idx < _MAX_NUM && ts_drv->ledgpio >= 0)
+ set_key_led_gpio(ts_drv,HIGH);
+
+ return 1;
+ }
+
+ if(ts_drv->ledgpio >= 0)
+ set_key_led_gpio(ts_drv,HIGH);
+ }
+
+ ts_drv->key_pressed= 0;
+
+ return 0 ;
+}
+
+#endif
+
+
+/*
+ * vt1603_ts_get_pos - get touch panel touched position from vt1603
+ * conversion register
+ * @ts_drv: vt1603 driver data
+ * @pos: vt1603 touch panel touched point conversion data
+ */
+static inline void vt1603_ts_get_pos(struct vt1603_ts_drvdata *ts_drv, struct vt1603_ts_pos *pos)
+{
+ u8 datal, datah;
+
+ /* get x-position */
+ datal = vt1603_get_reg8(ts_drv, VT1603_XPL_REG);
+ datah = vt1603_get_reg8(ts_drv, VT1603_XPH_REG);
+ pos->x = ADC_DATA(datal, datah);
+
+ /* get y-positin */
+ datal = vt1603_get_reg8(ts_drv, VT1603_YPL_REG);
+ datah = vt1603_get_reg8(ts_drv, VT1603_YPH_REG);
+ pos->y = ADC_DATA(datal, datah);
+ vt1603_clr_ts_irq(ts_drv, BIT0);
+
+ return;
+}
+
+/*
+ * vt1603_ts_isPendown - get touch panel pen state from vt1603
+ * interrup status register
+ * @ts_drv: vt1603 driver data
+ */
+static inline int vt1603_ts_isPendown(struct vt1603_ts_drvdata *ts_drv)
+{
+ u8 state = vt1603_get_reg8(ts_drv, VT1603_INTS_REG);
+
+ if (state & BIT4)
+ return TS_PENUP_STATE;
+ else
+ return TS_PENDOWN_STATE;
+}
+
+
+static inline int vt1603_pos_avg(struct vt1603_ts_pos *pos)
+{
+ vt1603_fifo_push(&px, pos->x);
+ vt1603_fifo_push(&py, pos->y);
+ vt1603_fifo_avg(px, &pos->x);
+ vt1603_fifo_avg(py, &pos->y);
+
+ return 0;
+}
+
+static int vt1603_pos_cleanup(void)
+{
+ px.full = 0;
+ px.head = 0;
+
+ py.full = 0;
+ py.head = 0;
+
+ return 0;
+}
+
+static void vt1603_read_loop(struct work_struct* dwork)
+{
+ struct vt1603_ts_drvdata *ts_drv=NULL;
+ struct vt1603_ts_pos pos;
+
+ ts_drv = container_of(dwork, struct vt1603_ts_drvdata, read_work.work);
+ ts_drv->pen_state= vt1603_ts_isPendown(ts_drv);
+ if((ts_drv->pen_state == TS_PENUP_STATE) ||ts_drv->earlysus){
+ vt1603_clr_ts_irq(ts_drv, 0x0F);
+ if(jiffies_to_msecs(jiffies - ts_drv->ts_stamp) < 80 && !ts_drv->earlysus){
+ //dbg("Debounceing@@@@@@@@\n");
+ goto next_loop;
+ }
+
+ dbg("============== penup ==============\n");
+ vt1603_set_reg8(ts_drv, VT1603_ISEL_REG36, 0x04);/* vt1603 gpio1 as IRQ output */
+ input_mt_sync(ts_drv->input);
+ input_sync(ts_drv->input);
+ #ifdef TOUCH_KEY
+ vt1603_ts_report_key(ts_drv);
+ #endif
+ pre_pos.x = 0;
+ pre_pos.y = 0;
+ ts_drv->hcnt = 0;
+ vt1603_pos_cleanup();
+
+ if(!ts_drv->earlysus)
+ wmt_gpio_unmask_irq(ts_drv->intgpio);
+
+ return;
+ }
+
+ ts_drv->ts_stamp = jiffies;
+ vt1603_ts_get_pos(ts_drv, &pos);
+
+ //Filter the first N point
+ if(ts_drv->hcnt < VT1603_FILTER_HEAD_COUNT){
+ ts_drv->hcnt++;
+ goto next_loop;
+ }
+
+ /* ƽ»¬Â˲¨*/
+ if((pre_pos.x != 0 && pre_pos.y != 0)&&(abs(pre_pos.x-pos.x) > VT1603_JITTER_THRESHOLD||abs(pre_pos.y-pos.y) > VT1603_JITTER_THRESHOLD)){
+ pre_pos.x = pos.x;
+ pre_pos.y = pos.y;
+ goto next_loop;
+ }
+#ifdef TOUCH_KEY
+ if(vt1603_ts_get_key(ts_drv,pos))
+ goto next_loop;
+#endif
+
+ vt1603_pos_avg(&pos);
+ pre_pos.x = pos.x;
+ pre_pos.y = pos.y;
+
+ dbg("x=%d, y=%d\n",pos.x,pos.y);
+ vt1603_ts_report_pos(ts_drv, &pos);
+
+next_loop:
+ queue_delayed_work(ts_drv->workqueue, &ts_drv->read_work, 20*HZ/1000);
+
+ return;
+}
+
+
+static void vt1603_ts_work(struct work_struct *work)
+{
+ int int_sts;
+ //unsigned long flags;
+ struct vt1603_ts_drvdata *ts_drv=pContext;
+
+ //spin_lock_irqsave(&ts_drv->spinlock, flags);
+ mutex_lock(&ts_drv->ts_mutex);
+ int_sts = vt1603_get_reg8(ts_drv, VT1603_INTS_REG);
+ dbg("+++++++ ts int status 0x%02x +++++++\n",int_sts);
+
+ if ((int_sts & BIT4) == 0 || (int_sts & BIT1) == BIT1){
+ if(ts_drv->pen_state == TS_PENUP_STATE){
+ vt1603_set_reg8(ts_drv, VT1603_ISEL_REG36, 0x03);/* vt1603 gpio1 as logic high output */
+ ts_drv->pen_state = TS_PENDOWN_STATE;
+ ts_drv->ts_stamp = jiffies;
+ vt1603_setup_ts_mode(ts_drv);
+ dbg("============= pendown =============\n");
+ vt1603_pos_cleanup();
+ if(ts_drv->dual_enable)
+ vt1603_ts_dual_support(&ts_drv->dual_work.work);
+ else
+ vt1603_read_loop(&ts_drv->read_work.work);
+
+ vt1603_clr_ts_irq(ts_drv, int_sts&0x0f);
+ //spin_unlock_irqrestore(&ts_drv->spinlock, flags);
+ mutex_unlock(&ts_drv->ts_mutex);
+
+ return;
+ }
+ }
+
+ vt1603_clr_ts_irq(ts_drv, int_sts&0x0f);
+ //spin_unlock_irqrestore(&ts_drv->spinlock, flags);
+ mutex_unlock(&ts_drv->ts_mutex);
+ wmt_gpio_unmask_irq(ts_drv->intgpio);
+
+ return ;
+}
+
+
+static irqreturn_t vt1603_ts_isr(int irq, void *dev_id)
+{
+ struct vt1603_ts_drvdata *ts_drv = dev_id;
+
+ if(!gpio_irqstatus(ts_drv->intgpio) ||
+ !is_gpio_irqenable(ts_drv->intgpio))
+ return IRQ_NONE;
+
+ wmt_gpio_ack_irq(ts_drv->intgpio);
+ wmt_gpio_mask_irq(ts_drv->intgpio);
+ schedule_work(&ts_drv->work);
+ dbg("@@@@@@@ touch irq @@@@@@@\n");
+
+ return IRQ_HANDLED;
+}
+
+static int vt1603_register_input(struct vt1603_ts_drvdata * ts_drv)
+{
+ if(strcmp(ts_drv->dev_id,"VT1609"))
+ ts_drv->input->name = "vt1603-touch";
+ else
+ ts_drv->input->name = "vt1609-touch";
+
+ ts_drv->input->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ ts_drv->input->propbit[0] = BIT_MASK(INPUT_PROP_DIRECT);
+
+#ifdef TOUCH_KEY
+ if(ts_drv->touch_key_used){
+ int i;
+ for (i = 0; i < TOUCH_KEY_NUM; i++)
+ set_bit(key_codes[i], ts_drv->input->keybit);
+
+ ts_drv->input->keycode = key_codes;
+ ts_drv->input->keycodesize = sizeof(unsigned int);
+ ts_drv->input->keycodemax = TOUCH_KEY_NUM;
+ }
+#endif
+ if (ts_drv->lcd_exchg) {
+ input_set_abs_params(ts_drv->input, ABS_MT_POSITION_X, 0, ts_drv->resl_y, 0, 0);
+ input_set_abs_params(ts_drv->input, ABS_MT_POSITION_Y, 0, ts_drv->resl_x, 0, 0);
+ } else {
+ input_set_abs_params(ts_drv->input, ABS_MT_POSITION_X, 0, ts_drv->resl_x, 0, 0);
+ input_set_abs_params(ts_drv->input, ABS_MT_POSITION_Y, 0, ts_drv->resl_y, 0, 0);
+ }
+
+ input_register_device(ts_drv->input);
+ return 0;
+}
+
+
+/*
+ * vt1603_ts_calibration - vt1603 self calibration routine
+ * @ts_drv: vt1603 driver data
+ */
+static void vt1603_ts_calibration(struct vt1603_ts_drvdata *ts_drv)
+{
+ unsigned char i, j, tmp;
+ unsigned char cal[5][8] = {{0}};
+ unsigned int cal_sum[8] = {0};
+ struct vt1603_ts_platform_data *ts_pdata;
+
+ dbg("Enter\n");
+ ts_pdata = ts_drv->pdata;
+ for (j = 0; j < 5; j++) {
+ tmp = BIT6 | BIT0 | (ts_pdata->cal_sel << 4);
+ vt1603_set_reg8(ts_drv, VT1603_CCCR_REG, tmp);
+ msleep(100);
+ for (i = 0; i < 8; i++)
+ cal[j][i] = vt1603_get_reg8(ts_drv, VT1603_ERR8_REG + i);
+ }
+ for (i = 0; i < 8; i++) {
+ for (j = 0; j < 5; j++)
+ cal_sum[i] += cal[j][i];
+ tmp = (u8)cal_sum[i]/5;
+ vt1603_set_reg8(ts_drv, VT1603_DBG8_REG + i, tmp);
+ }
+
+ dbg("Exit\n");
+ return ;
+}
+
+/*
+ * vt1603_ts_reset - reset vt1603, auto postition conversion mode,
+ * do self calibration if enable
+ * @ts_drv: vt1603 driver data
+ */
+static void vt1603_ts_reset(struct vt1603_ts_drvdata * ts_drv)
+{
+ struct vt1603_ts_platform_data *ts_pdata;
+ ts_pdata = ts_drv->pdata;
+
+ /* power control enable */
+ vt1603_set_reg8(ts_drv, VT1603_PWC_REG, 0x18);
+ /* begin calibrate if calibration enable */
+ if ((ts_pdata != NULL) && (ts_pdata->cal_en == CALIBRATION_ENABLE)) {
+ vt1603_ts_calibration(ts_drv);
+ }
+
+ /* clock divider */
+ vt1603_set_reg8(ts_drv, VT1603_CDPR_REG, ts_pdata->sclk_div);
+
+ /* clean debug register,for some 2 layer PCB machine enter debug mode unexpected */
+ vt1603_set_reg8(ts_drv, VT1603_DCR_REG, 0x00);
+
+ vt1603_set_reg8(ts_drv, VT1603_INTEN_REG, BIT1);//Just Enable pendown IRQ
+
+ /* auto position conversion mode and panel type config */
+ if (ts_pdata->panel_type== PANEL_TYPE_4WIRED)
+ vt1603_set_reg8(ts_drv, VT1603_CR_REG, BIT1);
+ else
+ vt1603_set_reg8(ts_drv, VT1603_CR_REG, BIT1 | BIT0);
+
+ /* interrupt control, pen up/down detection enable */
+ vt1603_set_reg8(ts_drv, VT1603_INTCR_REG, 0xff);
+
+ /* mask other module interrupts */
+ vt1603_set_reg8(ts_drv, VT1603_IMASK_REG27, 0xff);
+ vt1603_set_reg8(ts_drv, VT1603_IMASK_REG28, 0xFF);
+ vt1603_set_reg8(ts_drv, VT1603_IMASK_REG29, 0xFF);
+ /* reset headphone detect irq */
+ vt1603_set_reg8(ts_drv, VT1603_IMASK_REG27, 0xfd);
+
+ if (ts_pdata->irq_type == HIGH_ACTIVE|| ts_pdata->irq_type == RISING_EDGE_ACTIVE)
+ vt1603_clrbits(ts_drv, VT1603_IPOL_REG33, BIT5);
+ else
+ vt1603_setbits(ts_drv, VT1603_IPOL_REG33, BIT5);
+
+ vt1603_set_reg8(ts_drv, VT1603_ISEL_REG36, 0x04);/* vt1603 gpio1 as IRQ output */
+ /* clear irq */
+ vt1603_clr_ts_irq(ts_drv, 0x0F);
+
+ return;
+}
+
+
+static struct vt1603_ts_platform_data vt1603_ts_pdata = {
+ .panel_type = PANEL_TYPE_4WIRED,
+ .cal_en = CALIBRATION_DISABLE,
+ .cal_sel = 0x00,
+ .shift = 0x00,
+ .sclk_div = 0x08,
+ .irq_type = LOW_ACTIVE,
+};
+
+struct delayed_work resume_work;
+static void vt1603_resume_work(struct work_struct* dwork)
+{
+ struct vt1603_ts_drvdata *ts_drv = pContext;
+ ts_drv->pen_state = TS_PENUP_STATE;
+
+ /* must ensure mclk is available */
+ vt1603_ts_clk_enable();
+ /* vt1603 ts hardware resume */
+ vt1603_ts_reset(ts_drv);
+ /* clear irq before enale gpio irq */
+ vt1603_clr_ts_irq(ts_drv, 0x0f );
+
+ gpio_direction_input(ts_drv->intgpio);
+ wmt_gpio_set_irq_type(ts_drv->intgpio, IRQ_TYPE_EDGE_FALLING);
+ wmt_gpio_unmask_irq(ts_drv->intgpio);
+ #ifdef TOUCH_KEY
+ if(ts_drv->touch_key_used && ts_drv->ledgpio >= 0)
+ setup_led_gpio(ts_drv);
+#endif
+#ifdef VT1609_DEBUG
+ /* 4. dump vt1603 to ensure setting ok */
+ vt1603_reg_dump(ts_drv);
+#endif
+}
+static __devinit int
+vt1603_ts_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct vt1603_ts_drvdata *ts_drv = pContext;
+ struct vt1603_ts_platform_data *ts_pdata = NULL;
+
+ ts_pdata = &vt1603_ts_pdata;
+
+ ts_drv->pdata = ts_pdata;
+ ts_drv->pen_state = TS_PENUP_STATE;
+ ts_drv->tdev = dev_get_platdata(&pdev->dev);
+
+ //spin_lock_init(&ts_drv->spinlock);
+ mutex_init(&ts_drv->ts_mutex);
+
+ dev_set_drvdata(&pdev->dev, ts_drv);
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ ts_drv->earlysuspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+ ts_drv->earlysuspend.suspend = vt1603ts_early_suspend;
+ ts_drv->earlysuspend.resume = vt1603ts_late_resume;
+ register_early_suspend(&ts_drv->earlysuspend);
+#endif
+ /* 1. mclk enable */
+ vt1603_ts_clk_enable();
+ /* 2.vt1603 touch-panel and sar-adc module reset */
+ vt1603_ts_reset(ts_drv);
+
+#ifdef VT1609_DEBUG
+ /* 4. dump vt1603 to ensure setting ok */
+ vt1603_reg_dump(ts_drv);
+#endif
+ /* initial battery if battery detection enable */
+ /* initial temperature if temperature detection enable */
+
+ /* request iuput device */
+ ts_drv->input = input_allocate_device();
+ if (!ts_drv->input) {
+ printk("vt1603_ts: alloc input device failed");
+ ret = -ENOMEM;
+ goto release_driver_data;
+ }
+ vt1603_register_input(ts_drv);
+
+ INIT_DELAYED_WORK(&ts_drv->read_work, vt1603_read_loop);
+ INIT_DELAYED_WORK(&ts_drv->dual_work, vt1603_ts_dual_support);
+ INIT_DELAYED_WORK(&resume_work, vt1603_resume_work);
+ ts_drv->workqueue = create_singlethread_workqueue("vt160x-touch");
+ if(!ts_drv->workqueue){
+ printk("vt160x create singlethread work queue failed!\n");
+ goto release_driver_data;
+ }
+
+ INIT_WORK(&ts_drv->work, vt1603_ts_work);
+
+ if (request_irq(ts_drv->gpio_irq, vt1603_ts_isr, IRQF_SHARED, "vt160x-touch", ts_drv)) {
+ printk("vt160x_ts: request IRQ %d failed\n", ts_drv->gpio_irq);
+ ret = -ENODEV;
+ }
+
+ wmt_gpio_set_irq_type(ts_drv->intgpio, IRQ_TYPE_EDGE_FALLING);
+ wmt_gpio_unmask_irq(ts_drv->intgpio);
+
+#ifdef TOUCH_KEY
+ if(ts_drv->touch_key_used && ts_drv->ledgpio >= 0)
+ setup_led_gpio(ts_drv);
+#endif
+
+ dbg("%s Touch Screen Driver Installed!\n",ts_drv->dev_id);
+ return ret;
+
+release_driver_data:
+ kfree(ts_drv);
+ ts_drv = NULL;
+
+ return ret;
+}
+
+static __devexit int
+vt1603_ts_remove(struct platform_device *pdev)
+{
+ struct vt1603_ts_drvdata *ts_drv;
+ ts_drv = dev_get_drvdata(&pdev->dev);
+
+ dbg("Enter\n");
+
+ wmt_gpio_mask_irq(ts_drv->intgpio);
+ if(ts_drv->dual_enable)
+ vt1603_dual_exit(ts_drv);
+
+ /* input unregister */
+ input_unregister_device(ts_drv->input);
+ cancel_work_sync(&ts_drv->work);
+ cancel_delayed_work_sync(&ts_drv->dual_work);
+ cancel_delayed_work_sync(&ts_drv->read_work);
+ destroy_workqueue(ts_drv->workqueue);
+ vt1603_ts_dev_cleanup(ts_drv);
+#ifdef TOUCH_KEY
+ if(ts_drv->touch_key_used && ts_drv->ledgpio >= 0)
+ del_timer_sync(&ts_drv->led_timer);
+#endif
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&ts_drv->earlysuspend);
+#endif
+ /* free vt1603 driver data */
+ dev_set_drvdata(&pdev->dev, NULL);
+ mutex_destroy(&ts_drv->ts_mutex);
+ free_irq(ts_drv->gpio_irq,ts_drv);
+ kfree(ts_drv);
+ ts_drv = NULL;
+
+ dbg("Exit\n");
+ return 0;
+}
+
+#ifdef CONFIG_PM
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+
+static void
+vt1603ts_early_suspend(struct early_suspend *h)
+{
+ struct vt1603_ts_drvdata *ts_drv = pContext;
+
+ dbg("Enter\n");
+
+ wmt_gpio_mask_irq(ts_drv->intgpio);
+#ifdef TOUCH_KEY
+ if(ts_drv->touch_key_used && ts_drv->ledgpio >= 0){
+ del_timer_sync(&ts_drv->led_timer);
+ set_key_led_gpio(ts_drv,LOW);
+ }
+#endif
+
+ ts_drv->earlysus = 1;
+ dbg("Exit\n");
+ return;
+}
+
+static void
+vt1603ts_late_resume(struct early_suspend *h)
+{
+ struct vt1603_ts_drvdata *ts_drv = pContext;
+
+ dbg("Enter\n");
+ ts_drv->pen_state = TS_PENUP_STATE;
+
+ /* must ensure mclk is available */
+ vt1603_ts_clk_enable();
+ /* vt1603 ts hardware resume */
+ vt1603_ts_reset(ts_drv);
+ /* clear irq before enale gpio irq */
+ vt1603_clr_ts_irq(ts_drv, 0x0f );
+
+ ts_drv->earlysus = 0;
+ //wmt_gpio_set_irq_type(ts_drv->intgpio, IRQ_TYPE_EDGE_FALLING);
+ wmt_gpio_unmask_irq(ts_drv->intgpio);
+ #ifdef TOUCH_KEY
+ if(ts_drv->touch_key_used && ts_drv->ledgpio >= 0)
+ setup_led_gpio(ts_drv);
+ dbg("Exit\n");
+#endif
+
+ return;
+}
+
+#endif
+
+static int
+vt1603_ts_suspend(struct platform_device *pdev, pm_message_t message)
+{
+ struct vt1603_ts_drvdata *ts_drv = dev_get_drvdata(&pdev->dev);
+
+ dbg("Enter\n");
+#ifdef VT1609_DEBUG
+ /* 4. dump vt1603 to ensure setting ok */
+ vt1603_reg_dump(ts_drv);
+#endif
+
+ ts_drv = dev_get_drvdata(&pdev->dev);
+
+ wmt_gpio_mask_irq(ts_drv->intgpio);
+#ifdef TOUCH_KEY
+ if(ts_drv->touch_key_used && ts_drv->ledgpio >= 0){
+ set_key_led_gpio(ts_drv,LOW);
+ del_timer_sync(&ts_drv->led_timer);
+ }
+#endif
+
+ dbg("Exit\n");
+ return 0;
+}
+
+static int
+vt1603_ts_resume(struct platform_device *pdev)
+{
+ //struct vt1603_ts_drvdata *ts_drv = dev_get_drvdata(&pdev->dev);
+
+ dbg("Enter\n");
+ //delay resume work because some resources were closed by audio driver.
+ schedule_delayed_work(&resume_work, HZ);
+#if 0
+ ts_drv->pen_state = TS_PENUP_STATE;
+
+ /* must ensure mclk is available */
+ vt1603_ts_clk_enable();
+ /* vt1603 ts hardware resume */
+ vt1603_ts_reset(ts_drv);
+ /* clear irq before enale gpio irq */
+ vt1603_clr_ts_irq(ts_drv, 0x0f );
+
+ gpio_direction_input(ts_drv->intgpio);
+ wmt_gpio_set_irq_type(ts_drv->intgpio, IRQ_TYPE_EDGE_FALLING);
+ wmt_gpio_unmask_irq(ts_drv->intgpio);
+ #ifdef TOUCH_KEY
+ if(ts_drv->touch_key_used && ts_drv->ledgpio >= 0)
+ setup_led_gpio(ts_drv);
+#endif
+#ifdef VT1609_DEBUG
+ /* 4. dump vt1603 to ensure setting ok */
+ vt1603_reg_dump(ts_drv);
+#endif
+#endif
+ dbg("Exit\n");
+
+ return 0;
+}
+
+#else
+#define vt1603_ts_suspend NULL
+#define vt1603_ts_resume NULL
+#endif
+
+
+static struct platform_driver vt1603_driver = {
+ .driver = {
+ .name = VT1603_DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = vt1603_ts_probe,
+ .remove = vt1603_ts_remove,
+ .suspend = vt1603_ts_suspend,
+ .resume = vt1603_ts_resume,
+};
+
+static int vt1603_ts_dev_open(struct inode *inode, struct file *filp)
+{
+ struct vt1603_ts_drvdata *ts_drv;
+
+ dbg("Enter\n");
+
+ ts_drv = container_of(inode->i_cdev, struct vt1603_ts_drvdata , cdev);
+ if (ts_drv == NULL) {
+ printk("can not get vt1603_ts driver data\n");
+ return -ENODATA;
+ }
+ filp->private_data = ts_drv;
+
+ dbg("Exit\n");
+ return 0;
+}
+
+static int vt1603_ts_dev_close(struct inode *inode, struct file *filp)
+{
+ struct vt1603_ts_drvdata *ts_drv;
+
+ dbg("Enter\n");
+
+ ts_drv = container_of(inode->i_cdev, struct vt1603_ts_drvdata , cdev);
+ if (ts_drv == NULL) {
+ printk("can not get vt1603_ts driver data\n");
+ return -ENODATA;
+ }
+
+ dbg("Exit\n");
+ return 0;
+}
+
+static long vt1603_ts_dev_ioctl(struct file *filp,unsigned int cmd, unsigned long arg)
+{
+ int ret = 0;
+ int nBuff[7] = { 0 };
+ char env_val[96] = { 0 };
+ struct vt1603_ts_drvdata *ts_drv;
+
+ dbg("Enter\n");
+ /* check type and command number */
+ if (_IOC_TYPE(cmd) != VT1603_TS_IOC_MAGIC)
+ return -ENOTTY;
+
+ ts_drv = filp->private_data;
+ switch (cmd) {
+ case VT1603_TS_IOC_CAL_DONE:
+ copy_from_user(nBuff, (unsigned int *)arg, 7 * sizeof(int));
+ g_CalcParam.a1 = nBuff[0];
+ g_CalcParam.b1 = nBuff[1];
+ g_CalcParam.c1 = nBuff[2];
+ g_CalcParam.a2 = nBuff[3];
+ g_CalcParam.b2 = nBuff[4];
+ g_CalcParam.c2 = nBuff[5];
+ g_CalcParam.delta = nBuff[6];
+
+ if (g_CalcParam.delta == 0)
+ g_CalcParam.delta = 1;
+
+ sprintf(env_val, "%d %d %d %d %d %d %d",
+ nBuff[0], nBuff[1], nBuff[2], nBuff[3], nBuff[4], nBuff[5], nBuff[6]);
+
+ wmt_setsyspara("wmt.io.ts.2dcal", env_val);
+ printk("TOUCH CAL DONE: [%s]\n", env_val);
+ break;
+
+ case VT1603_TS_IOC_CAL_RAWDATA:
+ nBuff[0] = ts_drv->raw_x;
+ nBuff[1] = ts_drv->raw_y;
+ copy_to_user((unsigned int *)arg, nBuff, 2 * sizeof(int));
+ printk("TOUCH CAL RAWDATA: x=%-4d, y=%-4d \n", nBuff[0], nBuff[1]);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ dbg("Exit\n");
+ return ret;
+}
+
+static struct file_operations vt1603_ts_fops = {
+ .owner = THIS_MODULE,
+ .open = vt1603_ts_dev_open,
+ .unlocked_ioctl = vt1603_ts_dev_ioctl,
+ .release = vt1603_ts_dev_close,
+};
+
+
+static int vt1603_ts_dev_setup(struct vt1603_ts_drvdata *ts_drv)
+{
+ dev_t dev_no = 0;
+ int ret = 0;
+ struct device *dev = NULL;
+
+ dbg("Enter\n");
+ if (VT1603_TS_DEV_MAJOR) {
+ ts_drv->major = VT1603_TS_DEV_MAJOR;
+ ts_drv->minor = 0;
+ dev_no = MKDEV(ts_drv->major, ts_drv->minor);
+ ret = register_chrdev_region(dev_no, VT1603_TS_NR_DEVS, DEV_NAME);
+ } else {
+ ret = alloc_chrdev_region(&dev_no, 0, VT1603_TS_NR_DEVS, DEV_NAME);
+ ts_drv->major = MAJOR(dev_no);
+ ts_drv->minor = MINOR(dev_no);
+ dbg("vt1603_ts device major = %d, minor = %d \n", ts_drv->major,ts_drv->minor);
+ }
+
+ if (ret < 0) {
+ printk("can not get major %d\n", ts_drv->major);
+ goto out;
+ }
+
+ cdev_init(&ts_drv->cdev, &vt1603_ts_fops);
+
+ ts_drv->cdev.owner = THIS_MODULE;
+ ts_drv->cdev.ops = &vt1603_ts_fops;
+ ret = cdev_add(&ts_drv->cdev, dev_no, VT1603_TS_NR_DEVS);
+ if (ret) {
+ printk("add char dev for vt1603 ts failed\n");
+ goto release_region;
+ }
+
+ vt1603_ts_class = class_create(THIS_MODULE, ts_drv->dev_id);
+ if (IS_ERR(vt1603_ts_class)) {
+ printk("create vt1603_ts class failed\n");
+ ret = PTR_ERR(vt1603_ts_class);
+ goto release_cdev;
+ }
+
+ dev = device_create(vt1603_ts_class, NULL, dev_no, NULL, DEV_NAME);
+ if (IS_ERR(dev)) {
+ printk("create device for vt160x ts failed\n");
+ ret = PTR_ERR(dev);
+ goto release_class;
+ }
+
+ dbg("Exit\n");
+ return ret;
+
+release_class:
+ class_destroy(vt1603_ts_class);
+ vt1603_ts_class = NULL;
+release_cdev:
+ cdev_del(&ts_drv->cdev);
+release_region:
+ unregister_chrdev_region(dev_no, VT1603_TS_NR_DEVS);
+out:
+ return ret;
+}
+
+static void vt1603_ts_dev_cleanup(struct vt1603_ts_drvdata *ts_drv)
+{
+ dev_t dev_no = MKDEV(ts_drv->major, ts_drv->minor);
+
+ dbg("Enter\n");
+ cdev_del(&ts_drv->cdev);
+ unregister_chrdev_region(dev_no, VT1603_TS_NR_DEVS);
+ device_destroy(vt1603_ts_class, dev_no);
+ class_destroy(vt1603_ts_class);
+ dbg("Exit\n");
+}
+
+#ifdef TOUCH_KEY
+static int parse_touch_key_env(struct vt1603_ts_drvdata *ts_drv)
+{
+ int i = 0;
+ int ret = 0;
+ int len = 96;
+ char retval[96] = {0};
+ char *p = NULL;
+
+ ret = wmt_getsyspara("wmt.ts.vkey", retval, &len);
+ if(ret){
+ printk("Read wmt.ts.vkey Failed.\n");
+ return -EIO;
+ }
+
+ sscanf(retval,"%d:%d:%d:%d", &ts_drv->tsc_key.key_num,
+ &ts_drv->tsc_key.low, &ts_drv->tsc_key.upper, &ts_drv->tsc_key.delta);
+
+ if(!ts_drv->tsc_key.key_num){
+ printk("tsc key number is zero!\n");
+ return -EIO;
+ }
+
+ p = retval;
+ i = 4;
+ while(i--){
+ p = strchr(p,':');
+ p++;
+ }
+
+ for(i = 0; i < ts_drv->tsc_key.key_num; i++){
+ sscanf(p,"%d_%d",&ts_drv->tsc_key.key[i].pos,&ts_drv->tsc_key.key[i].idx );
+ p = strchr(p,':');
+ p++;
+ }
+
+ dbg("%d:%d:%d:%d:%d_%d:%d_%d:%d_%d:%d_%d\n",
+ ts_drv->tsc_key.key_num,
+ ts_drv->tsc_key.low,
+ ts_drv->tsc_key.upper,
+ ts_drv->tsc_key.delta,
+ ts_drv->tsc_key.key[0].pos,
+ ts_drv->tsc_key.key[0].idx,
+ ts_drv->tsc_key.key[1].pos,
+ ts_drv->tsc_key.key[1].idx,
+ ts_drv->tsc_key.key[2].pos,
+ ts_drv->tsc_key.key[2].idx,
+ ts_drv->tsc_key.key[3].pos,
+ ts_drv->tsc_key.key[3].idx);
+
+ return 0;
+
+}
+#endif
+
+static int parse_dual_env(struct vt1603_ts_drvdata *ts_drv)
+{
+ int ret = 0;
+ int len = 96;
+ char retval[96] = {0};
+
+ len = sizeof(retval);
+ ret = wmt_getsyspara("wmt.io.vt1609", retval, &len);
+ if(ret){
+ //printk("wmt.io.vt1609 not set, use default parameter.\n");
+ ts_drv->dual_dev.vxy = 17;
+ ts_drv->dual_dev.scale_x = 4;
+ ts_drv->dual_dev.scale_y = 2;
+ ts_drv->dual_dev.F1_CNT = 2;
+ ts_drv->dual_dev.F2_CNT = 7;
+ ts_drv->dual_dev.F2T1_CNT = 15;
+ ts_drv->dual_dev.SAMPLE_CNT = 1;
+ ts_drv->dual_dev.THR_MIN_DX = 13;
+ ts_drv->dual_dev.THR_MAX_DX = 256;
+ ts_drv->dual_dev.exch = 0;
+
+ return 0;
+ }
+
+ sscanf(retval,"%d:%d:%d:%d:%d:%d:%d:%d:%d:%d", &ts_drv->dual_dev.vxy,
+ &ts_drv->dual_dev.scale_x,
+ &ts_drv->dual_dev.scale_y,
+ &ts_drv->dual_dev.F1_CNT,
+ &ts_drv->dual_dev.F2_CNT,
+ &ts_drv->dual_dev.F2T1_CNT,
+ &ts_drv->dual_dev.SAMPLE_CNT,
+ &ts_drv->dual_dev.THR_MIN_DX,
+ &ts_drv->dual_dev.THR_MAX_DX,
+ &ts_drv->dual_dev.exch);
+ /*
+ printk("%d:%d:%d:%d:%d:%d:%d:%d:%d\n",
+ ts_drv->dual_dev.vxy,
+ ts_drv->dual_dev.scale_x,
+ ts_drv->dual_dev.scale_y,
+ ts_drv->dual_dev.F1_CNT,
+ ts_drv->dual_dev.F2_CNT ,
+ ts_drv->dual_dev.F2T1_CNT ,
+ ts_drv->dual_dev.SAMPLE_CNT ,
+ ts_drv->dual_dev.THR_MIN_DX ,
+ ts_drv->dual_dev.THR_MAX_DX),
+ ts_drv->dual_dev.exch;
+ */
+ return 0;
+}
+
+static int vt1603_uboot_env_check(struct vt1603_ts_drvdata *ts_drv)
+{
+ int nBuff[7] = {0};
+ int i = 0, Enable = 0;
+ int intgpio=0;
+ int ledgpio=-1;
+ int reslx=480,resly=800;
+ int ret=0,len = 96;
+ char retval[96] = {0};
+ char *p=NULL;
+
+ // Get u-boot parameter
+ ret = wmt_getsyspara("wmt.io.touch", retval, &len);
+ if(ret){
+ printk("Read wmt.io.touch Failed.\n");
+ return -EIO;
+ }
+
+ sscanf(retval,"%d:",&Enable);
+ //check touch enable
+ if(Enable == 0){
+ printk("System touchscreen is disbaled.\n");
+ return -ENODEV;
+ }
+
+ p = strchr(retval,':');
+ p++;
+ if(strncmp(p,"vt1603",6) == 0){//check touch ID
+ strcpy(ts_drv->dev_id, "VT1603A");
+ }
+ else if(strncmp(p,"vt1609",6) == 0){//check touch ID
+ ts_drv->dual_enable = 1;
+ strcpy(ts_drv->dev_id, "VT1609");
+ parse_dual_env(ts_drv);
+ }
+ else{
+ printk("Vt1609 touchscreen driver disabled.\n");
+ return -ENODEV;
+ }
+
+ p = strchr(p,':');
+ p++;
+ sscanf(p,"%d:%d:%d:%d",&reslx, &resly, &intgpio, &ledgpio);
+
+ ts_drv->resl_x = reslx;
+ ts_drv->resl_y = resly;
+
+ ts_drv->intgpio = intgpio;
+
+ ts_drv->ledgpio = ledgpio;
+
+ ts_drv->gpio_irq = IRQ_GPIO;
+
+ printk("%s-Touch: reslx=%d resly=%d, Interrupt GPIO%d , Virtual Touch Key Led GPIO%d\n",ts_drv->dev_id,
+ ts_drv->resl_x, ts_drv->resl_y, ts_drv->intgpio, ts_drv->ledgpio);
+
+ len = sizeof(retval);
+ memset(retval, 0, sizeof(retval));
+
+ ret = wmt_getsyspara("wmt.io.ts.2dcal", retval, &len);
+ if(ret){
+ printk("Read env wmt.io.ts.2dcal Failed.\n");
+ //return -EIO;
+ }
+
+ for (i = 0; i < sizeof(retval); i++) {
+ if (retval[i] == ' ' || retval[i] == ',' || retval[i] == ':')
+ retval[i] = '\0';
+ }
+
+ p = retval;
+ for (i = 0; (i < 7) && (p < (retval + sizeof(retval))); ) {
+ if (*p == '\0')
+ p++;
+ else {
+ sscanf(p, "%d", &nBuff[i]);
+ p = p + strlen(p);
+ i++;
+ }
+ }
+ dbg("Touchscreen Calibrate Data: [%d %d %d %d %d %d %d]\n",
+ nBuff[0], nBuff[1], nBuff[2], nBuff[3], nBuff[4], nBuff[5], nBuff[6]);
+
+ g_CalcParam.a1 = nBuff[0];
+ g_CalcParam.b1 = nBuff[1];
+ g_CalcParam.c1 = nBuff[2];
+ g_CalcParam.a2 = nBuff[3];
+ g_CalcParam.b2 = nBuff[4];
+ g_CalcParam.c2 = nBuff[5];
+ g_CalcParam.delta = nBuff[6];
+
+ if(g_CalcParam.delta == 0)
+ g_CalcParam.delta = 1;
+
+ memset(retval,0,sizeof(retval));
+ ret = wmt_getsyspara("wmt.display.fb0", retval, &len);
+ if (!ret) {
+ int tmp[6];
+ p = retval;
+ sscanf(p, "%d:[%d:%d:%d:%d:%d", &tmp[0], &tmp[1], &tmp[2], &tmp[3], &tmp[4], &tmp[5]);
+ if (tmp[4] > tmp[5])
+ ts_drv->lcd_exchg = 1;
+ }
+
+ return 0;
+}
+
+static int gpio_resource_request(void)
+{
+ if (gpio_request(pContext->intgpio, "ts_irq") < 0) {
+ printk("gpio(%d) touchscreen interrupt request fail\n", pContext->intgpio);
+ return -EIO;
+ }
+ gpio_direction_input(pContext->intgpio);
+
+ if (pContext->ledgpio >= 0) {
+ if (gpio_request(pContext->ledgpio, "ts_led") < 0) {
+ printk("gpio(%d) touchscreen led gpio request fail\n", pContext->ledgpio);
+ gpio_free(pContext->intgpio);
+ return -EIO;
+ }
+ gpio_direction_output(pContext->ledgpio, 0);
+ }
+
+ return 0;
+}
+static void gpio_resource_free(void)
+{
+ gpio_free(pContext->intgpio);
+ if (pContext->ledgpio >= 0)
+ gpio_free(pContext->ledgpio);
+}
+
+
+static int __init vt1603_ts_init(void)
+{
+ int ret = 0;
+ struct vt1603_ts_drvdata *ts_drv = NULL;
+
+ dbg("Enter\n");
+ ts_drv = kzalloc(sizeof(struct vt1603_ts_drvdata), GFP_KERNEL);
+ if (!ts_drv) {
+ printk("vt160x ts: alloc driver data failed\n");
+ return -ENOMEM;
+ }
+ pContext = ts_drv;
+ ret = vt1603_uboot_env_check(ts_drv);
+ if (ret) {//vt1603 touch disabled
+ goto out;
+ }else{//vt1603 touch enabled
+ if (gpio_resource_request())
+ goto out;
+ ret = vt1603_ts_dev_setup(ts_drv);//only touch calibrate need dev node
+ if (ret) {
+ printk("##ERR## vt160x ts create device node failed.\n");
+ goto freegpio;
+ }
+
+#ifdef TOUCH_KEY
+ if(!parse_touch_key_env(ts_drv)){
+ ts_drv->touch_key_used = 1;
+ if(ts_drv->ledgpio >= 0){//touch virtual key back light led enabled
+ init_timer(&ts_drv->led_timer);
+ ts_drv->led_timer.function = led_timer_func;
+ ts_drv->led_timer.data = (unsigned long) ts_drv;
+ }
+ }
+#endif
+ }
+
+ ret = platform_driver_register(&vt1603_driver);
+ if(ret){
+ printk("vt160x platform driver register failed!.\n");
+ goto release_dev;
+ }
+
+ if(ts_drv->dual_enable)
+ vt1603_dual_init(ts_drv);
+
+ dbg("Exit\n");
+ return ret;
+
+release_dev:
+ vt1603_ts_dev_cleanup(ts_drv);
+freegpio:
+ gpio_resource_free();
+out:
+ kfree(ts_drv);
+
+ return ret;
+}
+//module_init(vt1603_ts_init);
+late_initcall(vt1603_ts_init);
+static void __exit vt1603_ts_exit(void)
+{
+ dbg("Enter\n");
+
+ platform_driver_unregister(&vt1603_driver);
+ gpio_resource_free();
+
+ dbg("Exit\n");
+}
+module_exit(vt1603_ts_exit);
+
+MODULE_DESCRIPTION("VT1603A/VT1609 TouchScreen Driver");
+MODULE_LICENSE("GPL");
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/vt1609_ts/vt1609_ts.h b/ANDROID_3.4.5/drivers/input/touchscreen/vt1609_ts/vt1609_ts.h
new file mode 100755
index 00000000..31210579
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/vt1609_ts/vt1609_ts.h
@@ -0,0 +1,301 @@
+#ifndef __VT1603_TS_H__
+#define __VT1603_TS_H__
+#include <linux/mfd/vt1603/core.h>
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+
+#define DEV_NAME "wmtts"
+#define VT1603_DRIVER_NAME "vt1603-touch"
+
+#undef abs
+#define abs(x) (((x)>0)?(x):(-(x)))
+
+#define FALSE 0
+#define TRUE 1
+#define VT1603_TS_NR_DEVS 1
+#define VT1603_TS_DEV_MAJOR 160
+#define TS_DEBOUNCE 50
+#define VT1603_FILTER_HEAD_COUNT 2
+#define VT1603_JITTER_THRESHOLD 1200//µ¥µãÇ°ºó2µãÖ®¼äµÄx/y ±ä»¯×î´óÈÝÐíÖµ
+
+#define None_TOUCH 0x00
+#define Single_TOUCH 0x01
+#define Multi_TOUCH 0x02
+
+#define ADC_DATA(low, high) ((((high) & 0x0F) << 8) + (low))
+
+/* touch panel type config */
+#define PANEL_TYPE_4WIRED 0x10
+#define PANEL_TYPE_5WIRED 0x11
+
+/* enable calibration or not */
+#define CALIBRATION_ENABLE 0x01
+#define CALIBRATION_DISABLE 0x00
+
+/* VT1603 working mode */
+#define VT1603_TS_MODE BIT1
+#define VT1603_TEMP_MODE BIT2
+#define VT1603_BAT_MODE BIT3
+
+/* VT1603 touch panel state */
+#define TS_PENDOWN_STATE 0x00
+#define TS_PENUP_STATE 0x01
+
+struct vt1603_ts_pos {
+ int x;
+ int y;
+};
+
+#define VT1603_FIFO_LEN 3
+struct vt1603_fifo{
+ int head;
+ int full;
+ int buf[VT1603_FIFO_LEN];
+};
+
+#define I2C_BUS 0x00
+#define SPI_BUS 0x01
+
+#define VT1603_SPI_FIX_CS 0x00
+#define VT1603_SPI_FAKE_CS 0x03
+#define VT1603_SPI_BUS_0 0x00
+#define VT1603_SPI_BUS_1 0x01
+#define VT1603_MAX_SPI_CLK (20*1000*1000)
+#define SPI_DEFAULT_CLK (4*1000*1000)
+#define IDLE_DATA_NUM 5
+
+#define VT1603_I2C_FIX_ADDR 0x1A
+#define VT1603_I2C_FAKE_ADDR 0xFF
+#define VT1603_TS_I2C_WCMD 0x00
+#define VT1603_TS_I2C_RCMD 0x01
+#define VT1603_TS_I2C_RWCMD 0x02
+#define VT1603_I2C_BUS_0 0x00
+#define VT1603_I2C_BUS_1 0x01
+
+///////////////////////////////
+//#define TOUCH_KEY
+#define KEY_DETLA 300
+#define TOUCH_KEY_NUM 4
+#define TOUCH_KEY_LED_GPIO 4
+
+#define HIGH 1
+#define LOW 0
+
+struct tsc_key{
+ int pos;
+ int idx;
+};
+
+struct tsc_key_st{
+ int key_num;
+ int low;
+ int upper;
+ int delta;
+ struct tsc_key key[TOUCH_KEY_NUM];
+};
+
+enum key_idx{
+ _SEARCH,
+ _BACK,
+ _HOME,
+ _MENU,
+ _MAX_NUM,
+};
+/////////////////////////
+
+enum gpio_irq_type {
+ HIGH_ACTIVE = 0,
+ LOW_ACTIVE = 1,
+ RISING_EDGE_ACTIVE = 3,
+ FALLING_EDGE_ACTIVE = 4,
+ UNKOWN_TYPE = 0xFF
+};
+
+/*
+ * vt1603_ts_platform_data - vt1603 configuration data
+ * @panel_type: touch panel type: 4-wired or 5-wired
+ * @cal_en: enable calibration circuit or not
+ * @cal_sel: calibratin capacitor control bits
+ * @shfit: conversion data shfit
+ * @sclk_div: initial value of sclk dividor if mclk = 12.288MHZ 0x04 = 200ksps 0x08 = 100ksps
+ * @soc_gpio_irq: soc gpio interrupts, connect with vt1603 gpio1
+ */
+struct vt1603_ts_platform_data {
+ u8 panel_type;
+ u8 cal_en;
+ u8 cal_sel:2;
+ u8 shift;
+ u8 sclk_div;
+ int soc_gpio_irq;
+ int gpio_num;
+ enum gpio_irq_type irq_type;
+};
+
+struct vt1609_dual_st{
+ int vxy;
+
+ int scale_x;
+ int scale_y;
+
+ int F1_CNT;
+ int F2_CNT;
+ int F2T1_CNT;
+ int SAMPLE_CNT;
+
+ int THR_MIN_DX;
+ int THR_MAX_DX;
+
+ int exch;
+};
+
+struct vt1603_ts_drvdata {
+ struct vt1603 *tdev;
+ //spinlock_t spinlock;
+ struct mutex ts_mutex;
+ struct input_dev *input;
+ struct work_struct work;
+ struct delayed_work read_work;
+ struct delayed_work dual_work;
+ struct workqueue_struct *workqueue;
+ struct vt1603_ts_platform_data *pdata;
+
+ int earlysus;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend earlysuspend;
+#endif
+ char dev_id[32];
+
+ struct cdev cdev;
+ int major;
+ int minor;
+
+ int gpio_irq;
+
+ int intgpio;
+
+ u8 pen_state;
+ int ts_stamp;
+ int hcnt;
+
+ int resl_x;
+ int resl_y;
+ int lcd_exchg;
+
+ int raw_x;
+ int raw_y;
+
+ int dual_enable;
+ struct vt1609_dual_st dual_dev;
+
+ int ledgpio;
+#ifdef TOUCH_KEY
+ int key_idx;
+ int key_pressed;
+ int touch_key_used;
+ struct timer_list led_timer;
+ struct tsc_key_st tsc_key;
+#endif
+
+};
+
+/* VT1603 Register address */
+#define VT1603_BTHD_REG 0x78
+#define VT1603_BCLK_REG 0x88
+#define VT1603_BAEN_REG 0x04
+
+#define VT1603_PWC_REG 0xC0
+#define VT1603_CR_REG 0xC1
+#define VT1603_CCCR_REG 0xC2
+#define VT1603_CDPR_REG 0xC3
+#define VT1603_TSPC_REG 0xC4
+#define VT1603_AMCR_REG 0xC7
+#define VT1603_INTCR_REG 0xC8
+#define VT1603_INTEN_REG 0xC9
+#define VT1603_INTS_REG 0xCA
+#define VT1603_DCR_REG 0xCB
+
+#define VT1603_TODCL_REG 0xCC
+#define VT1603_TODCH_REG 0xCD
+
+#define VT1603_DATL_REG 0xCE
+#define VT1603_DATH_REG 0xCF
+
+#define VT1603_XPL_REG 0xD0
+#define VT1603_XPH_REG 0xD1
+#define VT1603_YPL_REG 0xD2
+#define VT1603_YPH_REG 0xD3
+
+#define VT1603_BATL_REG 0xD4
+#define VT1603_BATH_REG 0xD5
+
+#define VT1603_TEMPL_REG 0xD6
+#define VT1603_TEMPH_REG 0xD7
+
+#define VT1603_ERR8_REG 0xD8
+#define VT1603_ERR7_REG 0xD9
+#define VT1603_ERR6_REG 0xDA
+#define VT1603_ERR5_REG 0xDB
+#define VT1603_ERR4_REG 0xDC
+#define VT1603_ERR3_REG 0xDD
+#define VT1603_ERR2_REG 0xDE
+#define VT1603_ERR1_REG 0xDF
+
+#define VT1603_DBG8_REG 0xE0
+#define VT1603_DBG7_REG 0xE1
+#define VT1603_DBG6_REG 0xE2
+#define VT1603_DBG5_REG 0xE3
+#define VT1603_DBG4_REG 0xE4
+#define VT1603_DBG3_REG 0xE5
+#define VT1603_DBG2_REG 0xE6
+#define VT1603_DBG1_REG 0xE7
+
+/* for VT1603 GPIO1 interrupt setting */
+#define VT1603_IMASK_REG27 27
+#define VT1603_IMASK_REG28 28
+#define VT1603_IMASK_REG29 29
+#define VT1603_IPOL_REG33 33
+#define VT1603_ISEL_REG36 36
+
+struct vt1603_ts_cal_info {
+ int a1;
+ int b1;
+ int c1;
+ int a2;
+ int b2;
+ int c2;
+ int delta;
+};
+
+/* VT1603 TS and SAR-ADC IOCTL */
+#define VT1603_TS_IOC_MAGIC 't'
+
+/* for touch screen calibration */
+#define VT1603_TS_IOC_CAL_START _IO(VT1603_TS_IOC_MAGIC, 1)
+#define VT1603_TS_IOC_CAL_DONE _IOW(VT1603_TS_IOC_MAGIC, 2, int *)
+#define VT1603_TS_IOC_CAL_RAWDATA _IOR(VT1603_TS_IOC_MAGIC, 3, int *)
+#define VT1603_TS_IOC_CAL_QUIT _IOW(VT1603_TS_IOC_MAGIC, 4, int *)
+
+extern int wmt_setsyspara(char *varname, unsigned char *varval);
+extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlenex);
+
+int vt1603_clr_ts_irq(struct vt1603_ts_drvdata *ts_drv, u8 mask);
+int vt1603_set_reg8(struct vt1603_ts_drvdata *ts_drv, u8 reg, u8 val);
+u8 vt1603_get_reg8(struct vt1603_ts_drvdata *ts_drv, u8 reg);
+void vt1603_setbits(struct vt1603_ts_drvdata *ts_drv, u8 reg, u8 mask);
+void vt1603_clrbits(struct vt1603_ts_drvdata *ts_drv, u8 reg, u8 mask);
+
+void vt1603_ts_report_pos(struct vt1603_ts_drvdata *ts_drv, struct vt1603_ts_pos *pos);
+int vt1603_ts_pos_calibration(struct vt1603_ts_drvdata *ts_drv,struct vt1603_ts_pos *to_cal);
+
+#ifdef TOUCH_KEY
+void vt1603_ts_report_key(struct vt1603_ts_drvdata *ts_drv);
+int vt1603_ts_get_key(struct vt1603_ts_drvdata *ts_drv,struct vt1603_ts_pos pos);
+int set_key_led_gpio(struct vt1603_ts_drvdata *ts_drv,int val);
+#endif
+
+int vt1603_dual_init(struct vt1603_ts_drvdata *ts_drv);
+void vt1603_dual_exit(struct vt1603_ts_drvdata *ts_drv);
+void vt1603_ts_dual_support(struct work_struct* work);
+
+#endif /* __VT1603_TS_H__ */
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/zet6221_ts/Kconfig b/ANDROID_3.4.5/drivers/input/touchscreen/zet6221_ts/Kconfig
new file mode 100755
index 00000000..3bf6dcc3
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/zet6221_ts/Kconfig
@@ -0,0 +1,16 @@
+#
+# ZET6221 capacity touch screen driver configuration
+#
+config TOUCHSCREEN_ZET6221
+ tristate "ZEITEC ZET6221 I2C Capacitive Touchscreen Input Driver Support"
+ depends on ARCH_WMT
+ default y
+ help
+ Say Y here if you have an WMT based board with touchscreen
+ attached to it.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called s_wmt_ts_zet6221
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/zet6221_ts/Makefile b/ANDROID_3.4.5/drivers/input/touchscreen/zet6221_ts/Makefile
new file mode 100755
index 00000000..102fb212
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/zet6221_ts/Makefile
@@ -0,0 +1,32 @@
+KERNELDIR=../../../../
+CROSS = arm_1103_le-
+CC= $(CROSS)gcc
+LD= $(CROSS)ld
+STRIP = $(CROSS)strip
+
+DEBUG = n
+
+# Add your debugging flag (or not) to EXTRA_CFLAGS
+ifeq ($(DEBUG),y)
+# DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+DEBFLAGS = -O0 -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+
+else
+ DEBFLAGS = -O2 -Wall
+endif
+
+EXTRA_CFLAGS += $(DEBFLAGS)
+
+
+MY_MODULE_NAME=s_wmt_ts_zet6221
+
+obj-m := $(MY_MODULE_NAME).o
+$(MY_MODULE_NAME)-objs := zet6221_i2c.o wmt_ts.o zet6221_downloader.o
+
+default:
+ $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules
+ $(STRIP) --strip-debug $(MY_MODULE_NAME).ko
+ rm -rf *.o *~ core .depend .*.cmd *.mod.c .tmp_versions *.order *.symvers modules.builtin
+
+clean:
+ rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.order *.symvers modules.builtin \ No newline at end of file
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/zet6221_ts/wmt_ts.c b/ANDROID_3.4.5/drivers/input/touchscreen/zet6221_ts/wmt_ts.c
new file mode 100755
index 00000000..bfc65e7f
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/zet6221_ts/wmt_ts.c
@@ -0,0 +1,833 @@
+#include <linux/unistd.h>
+#include <linux/time.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+//#include <asm/semaphore.h>
+#include <linux/proc_fs.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/suspend.h>
+#include <linux/input.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <mach/hardware.h>
+#include <linux/i2c.h>
+#include <linux/irq.h>
+#include <linux/firmware.h>
+
+#include <asm/uaccess.h>
+#include <linux/fs.h>
+#include <linux/syscalls.h>
+
+#include "wmt_ts.h"
+#include "zet6221_ts.h"
+
+/////////////////////////////////////////////////////////////////
+
+// commands for ui
+#define TS_IOC_MAGIC 't'
+
+#define TS_IOCTL_CAL_START _IO(TS_IOC_MAGIC, 1)
+#define TS_IOCTL_CAL_DONE _IOW(TS_IOC_MAGIC, 2, int*)
+#define TS_IOCTL_GET_RAWDATA _IOR(TS_IOC_MAGIC, 3, int*)
+#define TS_IOCTL_CAL_QUIT _IOW(TS_IOC_MAGIC, 4, int*)
+#define TS_IOCTL_AUTO_CALIBRATION _IOW(TS_IOC_MAGIC, 5, int*)
+#define TS_IOC_MAXNR 5
+
+#define TP_INFOR_ARRAY_SIZE (sizeof(l_tpinfor)/sizeof(l_tpinfor[1]))
+//
+#define TS_MAJOR 11
+#define TS_DRIVER_NAME "wmtts_touch"
+#define TS_NAME "wmtts"
+#define WMTTS_PROC_NAME "wmtts_config"
+
+#define EXT_GPIO0 0
+#define EXT_GPIO1 1
+#define EXT_GPIO2 2
+#define EXT_GPIO3 3
+#define EXT_GPIO4 4
+#define EXT_GPIO5 5
+#define EXT_GPIO6 6
+#define EXT_GPIO7 7
+
+
+
+typedef struct {
+ int a1;
+ int b1;
+ int c1;
+ int a2;
+ int b2;
+ int c2;
+ int delta;
+}CALIBRATION_PARAMETER, *PCALIBRATION_PARAMETER;
+
+
+static int irq_gpio;
+static int rst_gpio;
+static int panelres_x;
+static int panelres_y;
+static int s_download_option;
+static int s_high_Impendence_mode;
+static int lcd_exchg = 0;
+
+
+static DECLARE_WAIT_QUEUE_HEAD(queue);
+static DECLARE_WAIT_QUEUE_HEAD(ts_penup_wait_queue);
+
+extern struct wmtts_device zet6221_tsdev;
+static struct wmtts_device* l_tsdev = &zet6221_tsdev;
+struct proc_dir_entry* l_tsproc = NULL;
+static struct i2c_client *l_client=NULL;
+static int l_penup = 1; // 1-pen up,0-pen down
+int earlysus_en = 0;
+
+struct tp_infor
+{
+ //enum tp_type type;
+ char name[64];
+ //unsigned int i2caddr;
+ unsigned int xaxis; //0: x,1: x swap with y
+ unsigned int xdir; // 1: positive,-1: revert
+ unsigned int ydir; // 1: positive,-1: revert
+ unsigned int max_finger_num;
+};
+
+static int l_tpindex = -1;
+static struct tp_infor l_tpinfor[1];
+
+/////////////////////////////////////////////////////
+// function declare
+/////////////////////////////////////////////////////
+extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
+extern int wmt_setsyspara(char *varname, unsigned char *varval);
+static int ts_writeproc( struct file *file,
+ const char *buffer,
+ unsigned long count,
+ void *data );
+static int ts_readproc(char *page, char **start, off_t off,
+ int count, int *eof, void *data);
+///////////////////////////////////////////////////////////////////////
+
+void wmt_ts_get_firmwname(char* firmname)
+{
+ int offset = 0;
+ offset = strlen(l_tsdev->ts_id);
+ switch(ic_model){
+ case ZET6223:
+ l_tpinfor[l_tpindex].name[offset] = '2';
+ l_tpinfor[l_tpindex].name[offset+1] = '3';
+ break;
+ case ZET6231:
+ l_tpinfor[l_tpindex].name[offset] = '3';
+ l_tpinfor[l_tpindex].name[offset+1] = '1';
+ break;
+ case ZET6251:
+ l_tpinfor[l_tpindex].name[offset] = '5';
+ l_tpinfor[l_tpindex].name[offset+1] = '1';
+ break;
+ case ZET6221:
+ default:
+ l_tpinfor[l_tpindex].name[offset] = '2';
+ l_tpinfor[l_tpindex].name[offset+1] = '1';
+ break;
+ }
+ sprintf(firmname,"%s_fw.bin",l_tpinfor[l_tpindex].name);
+}
+
+unsigned int wmt_ts_get_xaxis(void)
+{
+ return l_tpinfor[l_tpindex].xaxis;
+}
+
+unsigned int wmt_ts_get_xdir(void)
+{
+ return l_tpinfor[l_tpindex].xdir;
+}
+
+unsigned int wmt_ts_get_ydir(void)
+{
+ return l_tpinfor[l_tpindex].ydir;
+}
+
+unsigned int wmt_ts_get_maxfingernum(void)
+{
+ return l_tpinfor[l_tpindex].max_finger_num;
+}
+
+
+int wmt_ts_load_firmware(char* firmwarename, unsigned char** firmdata, int* fwlen)
+{
+ const struct firmware *fw_entry;
+ if(request_firmware(&fw_entry, firmwarename, &l_client->dev)!=0) {
+ printk(KERN_ERR "cat't request firmware\n");
+ return -1;
+ }
+ if (fw_entry->size <= 0) {
+ printk(KERN_ERR "load firmware error\n");
+ release_firmware(fw_entry);
+ return -1;
+ }
+
+ //*firmdata = kzalloc(fw_entry->size + 1, GFP_KERNEL);
+ memcpy(*firmdata, fw_entry->data, fw_entry->size);
+ *fwlen = fw_entry->size;
+ release_firmware(fw_entry);
+
+ return 0;
+}
+
+
+
+ int wmt_ts_get_gpionum(void)
+{
+ return irq_gpio;
+}
+
+int wmt_ts_get_resetgpnum(void)
+{
+ return rst_gpio;
+}
+
+int wmt_ts_get_lcdexchg(void)
+{
+ return lcd_exchg;
+}
+
+int wmt_ts_get_resolvX(void)
+{
+ return panelres_x;
+}
+
+int wmt_ts_get_resolvY(void)
+{
+ return panelres_y;
+}
+
+//up:1-pen up,0-pen down
+void wmt_ts_set_penup(int up)
+{
+ l_penup = up;
+}
+
+//
+int wmt_ts_wait_penup(void)
+{
+ int ret = wait_event_interruptible(
+ ts_penup_wait_queue,
+ (1==l_penup));
+ return ret;
+}
+
+// return:1-pen up,0-pen dwon
+int wmt_ts_ispenup(void)
+{
+ return l_penup;
+}
+
+
+void wmt_ts_wakeup_penup(void)
+{
+ wake_up(&ts_penup_wait_queue);
+}
+
+int wmt_is_tsirq_enable(void)
+{
+ int val = 0;
+ int num = irq_gpio;
+
+ if(num > 11)
+ return 0;
+
+ if(num<4)
+ val = REG32_VAL(__GPIO_BASE+0x0300) & (1<<(num*8+7));
+ else if(num >= 4 && num < 8)
+ val = REG32_VAL(__GPIO_BASE+0x0304) & (1<<((num-4)*8+7));
+ else
+ val = REG32_VAL(__GPIO_BASE+0x0308) & (1<<((num-8)*8+7));
+
+ return val?1:0;
+
+}
+
+int wmt_is_tsint(void)
+{
+ int num = irq_gpio;
+
+ if (num > 11)
+ {
+ return 0;
+ }
+ return (REG32_VAL(__GPIO_BASE+0x0360) & (1<<num)) ? 1: 0;
+}
+
+void wmt_clr_int(void)
+{
+ int num = irq_gpio;
+
+ if (num > 11)
+ {
+ return;
+ }
+ REG32_VAL(__GPIO_BASE+0x0360) = 1<<num;
+}
+
+void wmt_tsreset_init(void)
+{
+ int num = rst_gpio;
+
+ REG32_VAL(__GPIO_BASE+0x0040) |= (1<<num);//&= ~(1<<num); //enable gpio
+ REG32_VAL(__GPIO_BASE+0x00C0) &= ~(1<<num); // out low
+ REG32_VAL(__GPIO_BASE+0x0080) |= (1<<num); //output enable
+ msleep(10);
+ REG32_VAL(__GPIO_BASE+0x00C0) |= (1<<num); // out high
+}
+
+// enable:0-disable,1-enable
+void wmt_enable_rst_pull(int enable)
+{
+ if (enable)
+ {
+ REG32_VAL(__GPIO_BASE+0x0480) |= (1<<rst_gpio); //enable pull up/down
+ } else {
+ REG32_VAL(__GPIO_BASE+0x0480) &= ~(1<<rst_gpio); //disable pull up/down
+ }
+}
+
+// up:0-pull down,1-pull up
+void wmt_set_rst_pull(int up)
+{
+ if (up)
+ {
+ REG32_VAL(__GPIO_BASE+0x04c0) |= (1<<rst_gpio); //pull up
+ } else {
+ REG32_VAL(__GPIO_BASE+0x04c0) &= ~(1<<rst_gpio); //pull down
+ }
+}
+
+// high:0-low level,1-high level
+void wmt_rst_output(int high)
+{
+ REG32_VAL(__GPIO_BASE+0x0040) |= (1<<rst_gpio); //enable gpio
+ if (high)
+ {
+ REG32_VAL(__GPIO_BASE+0x00C0) |= (1<<rst_gpio); // high
+ } else {
+ REG32_VAL(__GPIO_BASE+0x00C0) &= ~(1<<rst_gpio); // low
+ }
+ REG32_VAL(__GPIO_BASE+0x0080) |= (1<<rst_gpio); //set output
+}
+
+void wmt_rst_input(void)
+{
+ REG32_VAL(__GPIO_BASE+0x0040) |= (1<<rst_gpio); //enable gpio
+ REG32_VAL(__GPIO_BASE+0x0080) &= ~(1<<rst_gpio); //set input
+}
+
+void wmt_set_intasgp(void)
+{
+ REG32_VAL(__GPIO_BASE+0x0040) |= (1<<irq_gpio); //enable gpio
+}
+
+// val:1--high,0-low
+void wmt_intgp_out(int val)
+{
+ if (val)
+ {
+ REG32_VAL(__GPIO_BASE+0x00C0) |= (1<<irq_gpio); // high
+ } else {
+ REG32_VAL(__GPIO_BASE+0x00C0) &= ~(1<<irq_gpio); // low
+ }
+ REG32_VAL(__GPIO_BASE+0x0080) |= (1<<irq_gpio); //set output
+}
+
+void wmt_ts_set_irqinput(void)
+{
+ int num = irq_gpio;
+
+ REG32_VAL(__GPIO_BASE+0x0040) |= (1<<num); //enable gpio
+ REG32_VAL(__GPIO_BASE+0x0080) &= ~(1<<num); //set input
+}
+
+unsigned int wmt_ts_irqinval(void)
+{
+ return REG32_VAL(__GPIO_BASE+0x0000)&(1<<irq_gpio);
+}
+
+int wmt_set_gpirq(int type)
+{
+ int shift;
+ int offset;
+ unsigned long reg;
+ int num = irq_gpio;
+
+ if(num >11)
+ return -1;
+ //if (num > 9)
+ //GPIO_PIN_SHARING_SEL_4BYTE_VAL &= ~BIT4; // gpio10,11 as gpio
+ REG32_VAL(__GPIO_BASE+0x0040) &= ~(1<<num);//|=(1<<num);// //enable gpio
+ REG32_VAL(__GPIO_BASE+0x0080) &= ~(1<<num); //set input
+ REG32_VAL(__GPIO_BASE+0x04c0) |= (1<<num); //pull down
+ REG32_VAL(__GPIO_BASE+0x0480) &= ~(1<<num); //enable pull up/down
+
+ //set gpio irq triger type
+ if(num < 4){//[0,3]
+ shift = num;
+ offset = 0x0300;
+ }else if(num >= 4 && num < 8){//[4,7]
+ shift = num-4;
+ offset = 0x0304;
+ }else{// [8,11]
+ shift = num-8;
+ offset = 0x0308;
+ }
+
+ reg = REG32_VAL(__GPIO_BASE + offset);
+
+ switch(type){
+ case IRQ_TYPE_LEVEL_LOW:
+ reg &= ~(1<<(shift*8+2));
+ reg &= ~(1<<(shift*8+1));
+ reg &= ~(1<<(shift*8));
+ break;
+ case IRQ_TYPE_LEVEL_HIGH:
+ reg &= ~(1<<(shift*8+2));
+ reg &= ~(1<<(shift*8+1));
+ reg |= (1<<(shift*8));
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ reg &= ~(1<<(shift*8+2));
+ reg |= (1<<(shift*8+1));
+ reg &= ~(1<<(shift*8));
+ break;
+ case IRQ_TYPE_EDGE_RISING:
+ reg &= ~(1<<(shift*8+2));
+ reg |= (1<<(shift*8+1));
+ reg |= (1<<(shift*8));
+ break;
+ default://both edge
+ reg |= (1<<(shift*8+2));
+ reg &= ~(1<<(shift*8+1));
+ reg &= ~(1<<(shift*8));
+ break;
+
+ }
+ //reg |= 1<<(shift*8+7);//enable interrupt
+ reg &= ~(1<<(shift*8+7)); //disable int
+
+ REG32_VAL(__GPIO_BASE + offset) = reg;
+ REG32_VAL(__GPIO_BASE+0x0360) = 1<<num; //clear interrupt status
+ msleep(5);
+ return 0;
+}
+
+int wmt_enable_gpirq(void)
+{
+ int num = irq_gpio;
+
+ if(num > 11)
+ return -1;
+
+ if(num<4)
+ REG32_VAL(__GPIO_BASE+0x0300) |= 1<<(num*8+7); //enable interrupt
+ else if(num >= 4 && num < 8)
+ REG32_VAL(__GPIO_BASE+0x0304) |= 1<<((num-4)*8+7); //enable interrupt
+ else
+ REG32_VAL(__GPIO_BASE+0x0308) |= 1<<((num-8)*8+7); //enable interrupt
+
+ return 0;
+}
+
+int wmt_disable_gpirq(void)
+{
+ int num = irq_gpio;
+
+ if(num > 11)
+ return -1;
+
+ if(num<4)
+ REG32_VAL(__GPIO_BASE+0x0300) &= ~(1<<(num*8+7)); //enable interrupt
+ else if(num >= 4 && num < 8)
+ REG32_VAL(__GPIO_BASE+0x0304) &= ~(1<<((num-4)*8+7)); //enable interrupt
+ else
+ REG32_VAL(__GPIO_BASE+0x0308) &= ~(1<<((num-8)*8+7)); //enable interrupt
+
+ return 0;
+}
+
+
+int wmt_get_tsirqnum(void)
+{
+ return IRQ_GPIO;
+}
+
+static void wmt_ts_platform_release(struct device *device)
+{
+ return;
+}
+
+static struct platform_device wmt_ts_plt_device = {
+ .name = TS_DRIVER_NAME,
+ .id = 0,
+ .dev = {
+ .release = wmt_ts_platform_release,
+ },
+// .num_resources = ARRAY_SIZE(wm9715_ts_resources),
+// .resource = wm9715_ts_resources,
+};
+
+static int wmt_ts_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ dbg("ts suspend....\n");
+ return l_tsdev->suspend(pdev, state);
+}
+static int wmt_ts_resume(struct platform_device *pdev)
+{
+ dbg("ts resume....\n");
+ return l_tsdev->resume(pdev);
+}
+
+static int wmt_ts_probe(struct platform_device *pdev)
+{
+ l_tsproc= create_proc_entry(WMTTS_PROC_NAME, 0666, NULL/*&proc_root*/);
+ if (l_tsproc != NULL)
+ {
+ l_tsproc->read_proc = ts_readproc;
+ l_tsproc->write_proc = ts_writeproc;
+ }
+
+ if (l_tsdev->probe != NULL)
+ return l_tsdev->probe(pdev);
+ else
+ return 0;
+}
+
+static int wmt_ts_remove(struct platform_device *pdev)
+{
+ if (l_tsproc != NULL)
+ {
+ remove_proc_entry(WMTTS_PROC_NAME, NULL);
+ l_tsproc = NULL;
+ }
+
+ if (l_tsdev->remove != NULL)
+ return l_tsdev->remove(pdev);
+ else
+ return 0;
+}
+
+static struct platform_driver wmt_ts_plt_driver = {
+ .driver = {
+ .name = TS_DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = wmt_ts_probe,
+ .remove = wmt_ts_remove,
+ .suspend = wmt_ts_suspend,
+ .resume = wmt_ts_resume,
+};
+
+static int ts_writeproc( struct file *file,
+ const char *buffer,
+ unsigned long count,
+ void *data )
+{
+ int calibrate = 0;
+ int val = 0;
+
+ if (sscanf(buffer, "calibrate=%d\n", &calibrate))
+ {
+ if (1 == calibrate)
+ {
+ if((l_tsdev->capacitance_calibrate != NULL) &&
+ (0 == l_tsdev->capacitance_calibrate()))
+ {
+ printk(KERN_ALERT "%s calibration successfully!\n", l_tsdev->ts_id);
+ } else {
+ printk(KERN_ALERT "%s calibration failed!\n", l_tsdev->ts_id);
+ }
+ }
+ } else if (sscanf(buffer, "reset=%d\n", &val))
+ {
+
+ }
+ return count;
+}
+
+static int ts_readproc(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int len = 0;
+
+ len = sprintf(page,
+ "echo calibrate=1 > /proc/wmtts_config to calibrate ts.\n");
+ return len;
+}
+
+
+int is_high_impendence_mode(void)
+{
+ return s_high_Impendence_mode;
+}
+
+int get_download_option(void)
+{
+ return s_download_option;
+}
+
+
+static int wmt_check_touch_env(void)
+{
+ int ret = 0;
+ int len = 96, i = 0;
+ char retval[200] = {0},*p=NULL,*s=NULL;
+ int Enable=0;
+ int val,val1;
+
+ // Get u-boot parameter
+ ret = wmt_getsyspara("wmt.io.touch", retval, &len);
+ if(ret){
+ errlog("Read wmt.io.touch Failed.\n");
+ return -EIO;
+ }
+ memset(l_tpinfor,0,sizeof(l_tpinfor[0]));
+
+ p = retval;
+ sscanf(p,"%d:", &Enable);
+ p = strchr(p,':');p++;
+ s = strchr(p,':');
+ strncpy(l_tpinfor[0].name,p, (s-p));
+ p = s+1;
+ dbg("ts_name=%s\n", l_tpinfor[0].name);
+
+ ret = sscanf(p,"%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
+ &irq_gpio,&panelres_x,&panelres_y,&rst_gpio,
+ &(l_tpinfor[0].xaxis),&(l_tpinfor[0].xdir),&(l_tpinfor[0].ydir),
+ &(l_tpinfor[0].max_finger_num),&s_high_Impendence_mode,&s_download_option);
+
+ if (ret < 8)
+ {
+ dbg("Wrong format ts u-boot param(%d)!\nwmt.io.touch=%s\n",ret,retval);
+ return -ENODEV;
+ }
+
+ //check touch enable
+ if(Enable == 0){
+ errlog("Touch Screen Is Disabled.\n");
+ return -ENODEV;
+ }
+
+
+ /*p = strchr(retval,':');
+ p++;
+ if(strncmp(p, l_tsdev->ts_id,strlen(l_tsdev->ts_id))){//check touch ID
+ //errlog(" %s!=====\n", l_tsdev->ts_id);
+ return -ENODEV;
+ }*/
+
+ //sscanf(p,"%s:", );
+ if (strstr(l_tpinfor[0].name, l_tsdev->ts_id) == NULL)
+ {
+ errlog("Can't find %s%s!\n", l_tsdev->ts_id,"xx");
+ return -ENODEV;
+ }
+ l_tpindex = 0;
+
+/*
+ p = strchr(p,':');
+ p++;
+ sscanf(p,"%d:%d:%d:%d",&irq_gpio,&panelres_x,&panelres_y,&rst_gpio);
+
+ */
+ klog("p.x = %d, p.y = %d, gpio=%d, resetgpio=%d,xaxis=%d,xdir=%d,ydri=%d,maxfingernum=%d,high_Impendence_mode=%d,s_download_option=%d\n",
+ panelres_x, panelres_y, irq_gpio, rst_gpio,
+ l_tpinfor[0].xaxis,l_tpinfor[0].xdir,l_tpinfor[0].ydir,
+ l_tpinfor[0].max_finger_num,s_high_Impendence_mode,s_download_option);
+
+ // parse touch key param
+ memset(retval,0,sizeof(retval));
+ ret = wmt_getsyspara("wmt.io.tskeyindex", retval, &len);
+ if(ret){
+ dbg("no touch key!\n");
+ //return -EIO;
+ } else {
+ p = retval;
+ // the number of touch key
+ sscanf(retval,"%d:", &val);
+ dbg("tskey num:%d\n",val);
+ p = strchr(p,':');
+ p++;
+ // touch key range
+ for (i=0;i<val;i++)
+ {
+ sscanf(p,"%d:",&val1);
+ p = strchr(p,':');
+ p++;
+ zet6221_set_tskey(i, val1);
+ dbg("key%d:(%d)\n",i,val1);
+ };
+ }
+
+ memset(retval,0,sizeof(retval));
+ ret = wmt_getsyspara("wmt.touch.earlysus", retval, &len);
+ if(!ret) {
+ p = retval;
+ sscanf(p, "%d", &earlysus_en);
+ }
+
+
+ memset(retval,0,sizeof(retval));
+ ret = wmt_getsyspara("wmt.display.fb0", retval, &len);
+ if (!ret) {
+ int tmp[6];
+ p = retval;
+ sscanf(p, "%d:[%d:%d:%d:%d:%d", &tmp[0], &tmp[1], &tmp[2], &tmp[3], &tmp[4], &tmp[5]);
+ if (tmp[4] > tmp[5])
+ lcd_exchg = 1;
+ }
+
+/* memset(retval,0,sizeof(retval));
+ ret = wmt_getsyspara("wmt.io.ts.2dcal", retval, &len);
+ if(ret){
+ errlog("Read env wmt.io.ts.2dcal Failed.\n ");
+ //return -EIO;
+ }
+ i = 0;
+ while(i < sizeof(retval)){
+ if(retval[i]==' ' || retval[i]==',' || retval[i]==':')
+ retval[i] = '\0';
+ i++;
+ }
+
+ i = 0;
+ p = retval;
+ while(i<7 && p < (retval + sizeof(retval))){
+ if(*p == '\0')
+ p++;
+ else{
+ sscanf(p,"%d",&nBuff[i]);
+ //printk("%d\n",nBuff[i]);
+ p=p+strlen(p);
+ i++;
+ }
+ }
+ //sscanf(retval,"%d %d %d %d %d %d %d %d",&nBuff[0],&nBuff[1],&nBuff[2],&nBuff[3],&nBuff[4],&nBuff[5],&nBuff[6]);
+ dbg("Tsc calibrate init data: [%d %d %d %d %d %d %d]\n",nBuff[0],nBuff[1],nBuff[2],nBuff[3],nBuff[4],nBuff[5],nBuff[6]);
+
+ g_CalcParam.a1 = nBuff[0];
+ g_CalcParam.b1 = nBuff[1];
+ g_CalcParam.c1 = nBuff[2];
+ g_CalcParam.a2 = nBuff[3];
+ g_CalcParam.b2 = nBuff[4];
+ g_CalcParam.c2 = nBuff[5];
+ g_CalcParam.delta = nBuff[6];
+
+ if(g_CalcParam.delta == 0)
+ g_CalcParam.delta =1;//avoid divide by zero
+*/
+ return 0;
+}
+
+struct i2c_board_info ts_i2c_board_info = {
+ .type = WMT_TS_I2C_NAME,
+ .flags = 0x00,
+ .addr = WMT_TS_I2C_ADDR,
+ .platform_data = NULL,
+ .archdata = NULL,
+ .irq = -1,
+};
+
+static int ts_i2c_register_device (void)
+{
+ struct i2c_board_info *ts_i2c_bi;
+ struct i2c_adapter *adapter = NULL;
+ //struct i2c_client *client = NULL;
+ ts_i2c_bi = &ts_i2c_board_info;
+ adapter = i2c_get_adapter(1);/*in bus 1*/
+
+ if (NULL == adapter) {
+ printk("can not get i2c adapter, client address error\n");
+ return -1;
+ }
+ l_client = i2c_new_device(adapter, ts_i2c_bi);
+ if (l_client == NULL) {
+ printk("allocate i2c client failed\n");
+ return -1;
+ }
+ i2c_put_adapter(adapter);
+ return 0;
+}
+
+static void ts_i2c_unregister_device(void)
+{
+ if (l_client != NULL)
+ {
+ i2c_unregister_device(l_client);
+ l_client = NULL;
+ }
+}
+
+struct i2c_client* ts_get_i2c_client(void)
+{
+ return l_client;
+}
+
+static int __init wmt_ts_init(void)
+{
+ int ret = 0;
+
+ if(wmt_check_touch_env())
+ return -ENODEV;
+
+ //ts_i2c_board_info.addr = l_tpinfor[l_tpindex].i2caddr;
+ if (ts_i2c_register_device()<0)
+ {
+ dbg("Error to run ts_i2c_register_device()!\n");
+ return -1;
+ }
+
+ if (l_tsdev->init() < 0){
+ dbg("Errors to init %s ts IC!!!\n", l_tsdev->ts_id);
+ ret = -1;
+ goto err_init;
+ }
+
+ // register device and driver of platform
+ ret = platform_device_register(&wmt_ts_plt_device);
+ if(ret){
+ errlog("wmt ts plat device register failed!\n");
+ return ret;
+ }
+ ret = platform_driver_register(&wmt_ts_plt_driver);
+ if(ret){
+ errlog("can not register platform_driver_register\n");
+ platform_device_unregister(&wmt_ts_plt_device);
+ return ret;
+ }
+
+ klog("%s driver init ok!\n",l_tsdev->ts_id);
+ return 0;
+err_init:
+ ts_i2c_unregister_device();
+ return ret;
+}
+
+static void __exit wmt_ts_exit(void)
+{
+ dbg("%s\n",__FUNCTION__);
+
+ l_tsdev->exit();
+ platform_driver_unregister(&wmt_ts_plt_driver);
+ platform_device_unregister(&wmt_ts_plt_device);
+ ts_i2c_unregister_device();
+}
+
+
+module_init(wmt_ts_init);
+module_exit(wmt_ts_exit);
+
+MODULE_LICENSE("GPL");
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/zet6221_ts/wmt_ts.h b/ANDROID_3.4.5/drivers/input/touchscreen/zet6221_ts/wmt_ts.h
new file mode 100755
index 00000000..cab70586
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/zet6221_ts/wmt_ts.h
@@ -0,0 +1,149 @@
+
+#ifndef WMT_TSH_201010191758
+#define WMT_TSH_201010191758
+
+#include <linux/platform_device.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/suspend.h>
+#include <linux/i2c.h>
+
+
+//#define DEBUG_WMT_TS
+#ifdef DEBUG_WMT_TS
+#undef dbg
+#define dbg(fmt, args...) printk(KERN_ALERT "[%s]: " fmt, __FUNCTION__ , ## args)
+
+//#define dbg(fmt, args...) if (kpadall_isrundbg()) printk(KERN_ALERT "[%s]: " fmt, __FUNCTION__, ## args)
+
+#else
+#define dbg(fmt, args...)
+#endif
+
+#undef errlog
+#undef klog
+#define errlog(fmt, args...) printk("[%s]: " fmt, __FUNCTION__, ## args)
+#define klog(fmt, args...) printk("[%s]: " fmt, __FUNCTION__, ## args)
+
+#define WMT_TS_I2C_NAME "zet6221-ts"
+#define WMT_TS_I2C_ADDR 0x76
+
+
+#ifndef dim
+#define dim(x) (sizeof(x) / sizeof(x[0]))
+#endif
+
+extern int earlysus_en;
+
+//////////////////////////////data type///////////////////////////
+typedef struct {
+ short pressure;
+ short x;
+ short y;
+ //short millisecs;
+} TS_EVENT;
+
+struct wmtts_device
+{
+ //data
+ char* driver_name;
+ char* ts_id;
+ //function
+ int (*init)(void);
+ int (*probe)(struct platform_device *platdev);
+ int (*remove)(struct platform_device *pdev);
+ void (*exit)(void);
+ int (*suspend)(struct platform_device *pdev, pm_message_t state);
+ int (*resume)(struct platform_device *pdev);
+ int (*capacitance_calibrate)(void);
+ int (*wait_penup)(struct wmtts_device*tsdev); // waiting untill penup
+ int penup; // 0--pendown;1--penup
+
+};
+
+enum {
+ ZET6221 = 0,
+ ZET6231,
+ ZET6223,
+ ZET6251,
+};
+extern u8 ic_model;
+extern unsigned char* flash_buffer;
+extern int l_fwlen;
+
+
+//////////////////////////function interface/////////////////////////
+extern int wmt_ts_get_gpionum(void);
+extern int wmt_ts_iscalibrating(void);
+extern int wmt_ts_get_resolvX(void);
+extern int wmt_ts_get_resolvY(void);
+extern int wmt_set_gpirq(int type);
+extern int wmt_get_tsirqnum(void);
+extern int wmt_disable_gpirq(void);
+extern int wmt_enable_gpirq(void);
+extern int wmt_is_tsirq_enable(void);
+extern int wmt_is_tsint(void);
+extern void wmt_clr_int(void);
+extern void wmt_tsreset_init(void);
+extern int wmt_ts_get_resetgpnum(void);
+extern int wmt_ts_get_lcdexchg(void);
+extern void wmt_enable_rst_pull(int enable);
+extern void wmt_set_rst_pull(int up);
+extern void wmt_rst_output(int high);
+extern void wmt_rst_input(void);
+extern void wmt_set_intasgp(void);
+extern void wmt_intgp_out(int val);
+extern void wmt_ts_set_irqinput(void);
+extern unsigned int wmt_ts_irqinval(void);
+extern void wmt_ts_set_penup(int up);
+extern int wmt_ts_wait_penup(void);
+extern void wmt_ts_wakeup_penup(void);
+extern struct i2c_client* ts_get_i2c_client(void);
+extern int wmt_ts_ispenup(void);
+extern unsigned int wmt_ts_get_maxfingernum(void);
+extern unsigned int wmt_ts_get_ictype(void);
+extern unsigned int wmt_ts_get_xaxis(void);
+extern unsigned int wmt_ts_get_xdir(void);
+extern unsigned int wmt_ts_get_ydir(void);
+// short
+extern unsigned int wmt_ts_get_touchheight(void);
+// long
+extern unsigned int wmt_ts_get_touchwidth(void);
+extern void wmt_ts_get_firmwname(char* firmname);
+extern int wmt_ts_load_firmware(char* firmwarename, unsigned char** firmdata, int* fwlen);
+
+
+
+
+extern void TouchPanelCalibrateAPoint(
+ int UncalX, //@PARM The uncalibrated X coordinate
+ int UncalY, //@PARM The uncalibrated Y coordinate
+ int *pCalX, //@PARM The calibrated X coordinate
+ int *pCalY //@PARM The calibrated Y coordinate
+ );
+
+//filepath:the path of firmware file;
+//firmdata:store the data from firmware file;
+//maxlen: the max len of firmdata;
+//return:the length of firmware data,negative-parsing error.
+//extern
+u8 zet6221_ts_sfr(struct i2c_client *client);
+int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
+
+
+#define HIGH_IMPENDENCE_MODE 0
+#define NOT_HIGH_IMPENDENCE_MODE 1
+
+extern int is_high_impendence_mode(void);
+
+
+#define FORCE_DOWNLOAD 1
+#define FORCE_CANCEL_DOWNLOAD 2
+extern int get_download_option(void);
+
+
+
+#endif
+
+
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/zet6221_ts/zet6221_downloader.c b/ANDROID_3.4.5/drivers/input/touchscreen/zet6221_ts/zet6221_downloader.c
new file mode 100755
index 00000000..ac51aa21
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/zet6221_ts/zet6221_downloader.c
@@ -0,0 +1,1209 @@
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+//#include "zet6221_fw.h"
+
+#include "wmt_ts.h"
+
+#define ZET6221_DOWNLOADER_NAME "zet6221_downloader"
+#define FEATURE_FW_CHECK_SUM 1
+//#define High_Impendence_Mode
+
+#define TS_INT_GPIO S3C64XX_GPN(9) /*s3c6410*/
+#define TS_RST_GPIO S3C64XX_GPN(10) /*s3c6410*/
+#define RSTPIN_ENABLE
+
+#define GPIO_LOW 0
+#define GPIO_HIGH 1
+
+//static u8 fw_version0;
+//static u8 fw_version1;
+
+//#define debug_mode 1
+//#define DPRINTK(fmt,args...) do { if (debug_mode) printk(KERN_EMERG "[%s][%d] "fmt"\n", __FUNCTION__, __LINE__, ##args);} while(0)
+
+static unsigned char zeitec_zet6221_page[131] __initdata;
+static unsigned char zeitec_zet6221_page_in[131] __initdata;
+unsigned char* flash_buffer = NULL;
+int l_fwlen = 0;
+
+//static u16 fb[8] = {0x3EEA,0x3EED,0x3EF0,0x3EF3,0x3EF6,0x3EF9,0x3EFC,0x3EFF};
+static u16 fb[8] = {0x3DF1,0x3DF4,0x3DF7,0x3DFA,0x3EF6,0x3EF9,0x3EFC,0x3EFF};
+static u16 fb21[8] = {0x3DF1,0x3DF4,0x3DF7,0x3DFA,0x3EF6,0x3EF9,0x3EFC,0x3EFF};
+static u16 fb23[8] = {0x7BFC,0x7BFD,0x7BFE,0x7BFF,0x7C04,0x7C05,0x7C06,0x7C07};
+u8 ic_model = 0;
+
+extern int zet6221_i2c_write_tsdata(struct i2c_client *client, u8 *data, u8 length);
+extern int zet6221_i2c_read_tsdata(struct i2c_client *client, u8 *data, u8 length);
+extern u8 pc[];
+
+
+
+
+/************************load firmwre data from file************************/
+int zet6221_load_fw(void)
+{
+ char fwname[256] = {0};
+ int ret = -1;
+ wmt_ts_get_firmwname(fwname);
+ ret = wmt_ts_load_firmware(fwname, &flash_buffer, &l_fwlen);
+ if(!ret) {
+ printk("Success load fw_file: %s, length %d\n", fwname, l_fwlen);
+ printk("%x,%x,%x,%x\n", flash_buffer[0], flash_buffer[1], flash_buffer[2], flash_buffer[3]);
+ printk("%x,%x,%x,%x\n", flash_buffer[l_fwlen-4], flash_buffer[l_fwlen-3], flash_buffer[l_fwlen-2], flash_buffer[l_fwlen-1]);
+ }
+ return ret;
+}
+
+/***********************free firmware memory*******************************/
+int zet6221_free_fwmem(void)
+{
+ if (l_fwlen > 0 && flash_buffer != NULL )
+ {
+ kfree(flash_buffer);
+ flash_buffer = NULL;
+ l_fwlen = 0;
+ }
+ return 0;
+}
+//#define I2C_CTPM_ADDRESS (0x76)
+
+/***********************************************************************
+[function]:
+ callback: write data to ctpm by i2c interface,implemented by special user;
+[parameters]:
+ client[in] :i2c client structure;
+ bt_ctpm_addr[in] :the address of the ctpm;
+ pbt_buf[in] :data buffer;
+ dw_lenth[in] :the length of the data buffer;
+[return]:
+ 1 :success;
+ 0 :fail;
+************************************************************************/
+int i2c_write_interface(struct i2c_client *client, u8 bt_ctpm_addr, u8* pbt_buf, u16 dw_lenth)
+{
+ struct i2c_msg msg;
+ msg.addr = bt_ctpm_addr;
+ msg.flags = 0;
+ msg.len = dw_lenth;
+ msg.buf = pbt_buf;
+ return i2c_transfer(client->adapter,&msg, 1);
+}
+
+/***********************************************************************
+[function]:
+ callback: read data from ctpm by i2c interface,implemented by special user;
+[parameters]:
+ client[in] :i2c client structure;
+ bt_ctpm_addr[in] :the address of the ctpm;
+ pbt_buf[out] :data buffer;
+ dw_lenth[in] :the length of the data buffer;
+[return]:
+ 1 :success;
+ 0 :fail;
+************************************************************************/
+int i2c_read_interface(struct i2c_client *client, u8 bt_ctpm_addr, u8* pbt_buf, u16 dw_lenth)
+{
+ struct i2c_msg msg;
+ msg.addr = bt_ctpm_addr;
+ msg.flags = I2C_M_RD;
+ msg.len = dw_lenth;
+ msg.buf = pbt_buf;
+ return i2c_transfer(client->adapter,&msg, 1);
+}
+
+/***********************************************************************
+ [function]:
+ callback: check version;
+ [parameters]:
+ void
+
+ [return]:
+ 0: different 1: same;
+************************************************************************/
+u8 zet6221_ts_version(void)
+{
+ int i;
+
+ if(pc == NULL){
+ errlog(" pc is NULL\n");
+ return 0;
+ }
+ if( flash_buffer == NULL ){
+ errlog("flash_buffer \n");
+ return 0;
+ }
+
+#if 1
+ dbg("pc: ");
+ for(i=0;i<8;i++){
+ dbg("%02x ",pc[i]);
+ }
+ dbg("\n");
+
+ dbg("src: ");
+ for(i=0;i<8;i++){
+ dbg("%02x ", flash_buffer[fb[i]]);
+ }
+ dbg("\n");
+#endif
+
+ mdelay(20);
+
+ for(i=0;i<8;i++)
+ if(pc[i]!= flash_buffer[fb[i]])
+ return 0;
+ return 1;
+}
+
+
+/***********************************************************************
+ [function]:
+ callback: send password 1K (ZET6223)
+ [parameters]:
+ client[in]: struct i2c_client — represent an I2C slave device;
+
+ [return]:
+ 1;
+************************************************************************/
+u8 zet6221_ts_sndpwd_1k(struct i2c_client *client)
+{
+ u8 ts_sndpwd_cmd[3] = {0x20,0xB9,0xA3};
+
+ int ret;
+
+#if defined(I2C_CTPM_ADDRESS)
+ ret=i2c_write_interface(client, I2C_CTPM_ADDRESS, ts_sndpwd_cmd, 3);
+#else
+ ret=zet6221_i2c_write_tsdata(client, ts_sndpwd_cmd, 3);
+#endif
+
+
+ return 1;
+}
+
+
+/***********************************************************************
+ [function]:
+ callback: send password;
+ [parameters]:
+ client[in]: struct i2c_client ???represent an I2C slave device;
+
+ [return]:
+ 1;
+************************************************************************/
+u8 zet6221_ts_sndpwd(struct i2c_client *client)
+{
+ u8 ts_sndpwd_cmd[3] = {0x20,0xC5,0x9D};
+
+ int ret;
+
+#if defined(I2C_CTPM_ADDRESS)
+ ret=i2c_write_interface(client, I2C_CTPM_ADDRESS, ts_sndpwd_cmd, 3);
+#else
+ ret=zet6221_i2c_write_tsdata(client, ts_sndpwd_cmd, 3);
+#endif
+
+ return 1;
+}
+
+u8 zet622x_ts_option(struct i2c_client *client)
+{
+ u8 ts_cmd[1] = {0x27};
+ u8 ts_cmd_erase[1] = {0x28};
+ u8 ts_in_data[16] = {0};
+ u8 ts_out_data[18] = {0};
+ int ret;
+ u16 model;
+ int i;
+ u8 high_impendence_data = 0;
+ const u8 HIGH_IMPENDENCE_MODE_DATA = 0xf1;
+ const u8 NOT_HIGH_IMPENDENCE_MODE_DATA = 0xf2;
+
+
+ dbg("zet622x_ts_option++\n");
+
+ wmt_rst_output(0);
+ msleep(10);
+ //send password
+ zet6221_ts_sndpwd(client);
+ msleep(100);
+
+
+
+#if defined(I2C_CTPM_ADDRESS)
+ ret=i2c_write_interface(client, I2C_CTPM_ADDRESS, ts_cmd, dim(ts_cmd));
+#else
+ ret=zet6221_i2c_write_tsdata(client, ts_cmd, dim(ts_cmd));
+#endif
+ msleep(2);
+
+
+#if defined(I2C_CTPM_ADDRESS)
+ ret=i2c_read_interface(client, I2C_CTPM_ADDRESS, ts_in_data, dim(ts_in_data));
+#else
+ ret=zet6221_i2c_read_tsdata(client, ts_in_data, dim(ts_in_data));
+#endif
+ //msleep(2);
+
+ dbg("command %02x recv:\n",ts_cmd[0]);
+ for(i=0;i<16;i++)
+ {
+ dbg("%02x ",ts_in_data[i]);
+ }
+ dbg("\n");
+ // zet6231 recv: ff ff fc 30 ff 80 31 62 ff ff ff ff ff ff ff ff
+
+ model = 0x0;
+ model = ts_in_data[7];
+ model = (model << 8) | ts_in_data[6];
+
+ switch(model) {
+ case 0xFFFF:
+ ret = 1;
+ ic_model = ZET6221;
+ for(i=0;i<8;i++)
+ {
+ fb[i]=fb21[i];
+ }
+
+ if( is_high_impendence_mode() == HIGH_IMPENDENCE_MODE ){
+ high_impendence_data = HIGH_IMPENDENCE_MODE_DATA;
+ }else if( is_high_impendence_mode() == NOT_HIGH_IMPENDENCE_MODE ) {
+ high_impendence_data = NOT_HIGH_IMPENDENCE_MODE_DATA;
+ }
+
+ //#if defined(High_Impendence_Mode)
+ if(ts_in_data[2] != high_impendence_data)
+ {
+
+ if(zet6221_ts_sfr(client)==0)
+ {
+ return 0;
+ }
+
+ #if defined(I2C_CTPM_ADDRESS)
+ ret=i2c_write_interface(client, I2C_CTPM_ADDRESS, ts_cmd_erase, dim(ts_cmd_erase));
+ #else
+ ret=zet6221_i2c_write_tsdata(client, ts_cmd_erase, dim(ts_cmd_erase));
+ #endif
+
+ msleep(100);
+ dbg("erase ret=%d \n",ret);
+
+
+ for(i=2;i<18;i++)
+ {
+ ts_out_data[i]=ts_in_data[i-2];
+ }
+ ts_out_data[0] = 0x21;
+ ts_out_data[1] = 0xc5;
+ ts_out_data[4] = high_impendence_data;
+
+ #if defined(I2C_CTPM_ADDRESS)
+ ret=i2c_write_interface(client, I2C_CTPM_ADDRESS, ts_out_data, 18);
+ #else
+ ret=zet6221_i2c_write_tsdata(client, ts_out_data, 18);
+ #endif
+
+ msleep(100);
+ dbg("write out data, ret=%d\n",ret);
+
+
+
+ #if defined(I2C_CTPM_ADDRESS)
+ ret=i2c_write_interface(client, I2C_CTPM_ADDRESS, ts_cmd, 1);
+ #else
+ ret=zet6221_i2c_write_tsdata(client, ts_cmd, 1);
+ #endif
+
+ msleep(2);
+
+ dbg("send %02x\n",ts_cmd[0]);
+
+
+ #if defined(I2C_CTPM_ADDRESS)
+ ret=i2c_read_interface(client, I2C_CTPM_ADDRESS, ts_in_data, 16);
+ #else
+ ret=zet6221_i2c_read_tsdata(client, ts_in_data, 16);
+ #endif
+ //msleep(2);
+ dbg("command %02x recv:\n",ts_cmd[0]);
+ for(i=0;i<16;i++)
+ {
+ dbg("%02x ",ts_in_data[i]);
+ }
+ dbg("\n");
+
+ }
+
+ //#endif
+
+
+
+ break;
+ case 0x6223:
+ ret = 1;
+ ic_model = ZET6223;
+ for(i=0;i<8;i++)
+ {
+ fb[i]=fb23[i];
+ }
+ break;
+ case 0x6231:
+ ret = 1;
+ ic_model = ZET6231;
+ for(i=0;i<8;i++)
+ {
+ fb[i]=fb23[i];
+ }
+ break;
+ case 0x6251:
+ ic_model = ZET6251;
+ for(i=0;i<8;i++)
+ {
+ fb[i] = fb23[i];
+ }
+ break;
+ default:
+ errlog("Notice: can't detect the TP IC,use ZET6231 default\n");
+ ret = 1;
+ ic_model = ZET6231;
+ for(i=0;i<8;i++)
+ {
+ fb[i]=fb23[i];
+ }
+ break;
+
+ }
+
+ wmt_rst_output(1);
+ msleep(10);
+
+ dbg("zet622x_ts_option-- ret:%d\n",ret);
+ return ret;
+}
+/***********************************************************************
+ [function]:
+ callback: set/check sfr information;
+ [parameters]:
+ client[in]: struct i2c_client ???represent an I2C slave device;
+
+ [return]:
+ 1;
+************************************************************************/
+u8 zet6221_ts_sfr(struct i2c_client *client)
+{
+ u8 ts_cmd[1] = {0x2C};
+ u8 ts_in_data[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+ u8 ts_cmd17[17] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+ //u8 ts_sfr_data[16] = {0x18,0x76,0x27,0x27,0xFF,0x03,0x8E,0x14,0x00,0x38,0x82,0xEC,0x00,0x00,0x7d,0x03};
+ int ret;
+ int i;
+
+ dbg("zet6221_ts_sfr++");
+#if defined(I2C_CTPM_ADDRESS)
+ ret=i2c_write_interface(client, I2C_CTPM_ADDRESS, ts_cmd, 1);
+#else
+ ret=zet6221_i2c_write_tsdata(client, ts_cmd, 1);
+#endif
+ msleep(10);
+ dbg("sfr cmd : 0x%02x \n",ts_cmd[0]);
+
+
+
+ dbg("sfr rcv : \n");
+
+#if defined(I2C_CTPM_ADDRESS)
+ ret=i2c_read_interface(client, I2C_CTPM_ADDRESS, ts_in_data, 16);
+#else
+ ret=zet6221_i2c_read_tsdata(client, ts_in_data, 16);
+#endif
+ msleep(10);
+
+ if(ts_in_data[14]!=0x3D && ts_in_data[14]!=0x7D)
+ {
+ return 0;
+ }
+
+ for(i=0;i<16;i++)
+ {
+ ts_cmd17[i+1]=ts_in_data[i];
+ dbg("[%d]%02x\n",i,ts_in_data[i]);
+ }
+
+ dbg("\n");
+
+ // need to check 0x3D to open write function
+ if(ts_in_data[14]!=0x3D)
+ {
+ ts_cmd17[15]=0x3D;
+
+ ts_cmd17[0]=0x2B;
+
+#if defined(I2C_CTPM_ADDRESS)
+ ret=i2c_write_interface(client, I2C_CTPM_ADDRESS, ts_cmd17, 17);
+#else
+ ret=zet6221_i2c_write_tsdata(client, ts_cmd17, 17);
+#endif
+
+ if(ret<0)
+ {
+ errlog("enable sfr(0x3D) failed!\n");
+ return 0;
+ }
+
+ }
+ dbg("zet6221_ts_sfr--");
+ return 1;
+}
+
+/***********************************************************************
+ [function]:
+ callback: mass erase flash;
+ [parameters]:
+ client[in]: struct i2c_client ???represent an I2C slave device;
+
+ [return]:
+ 1;
+************************************************************************/
+u8 zet6221_ts_masserase(struct i2c_client *client)
+{
+ u8 ts_cmd[1] = {0x24};
+
+ int ret;
+
+#if defined(I2C_CTPM_ADDRESS)
+ ret=i2c_write_interface(client, I2C_CTPM_ADDRESS, ts_cmd, 1);
+#else
+ ret=zet6221_i2c_write_tsdata(client, ts_cmd, 1);
+#endif
+
+ return 1;
+}
+
+/***********************************************************************
+ [function]:
+ callback: erase flash by page;
+ [parameters]:
+ client[in]: struct i2c_client ???represent an I2C slave device;
+
+ [return]:
+ 1;
+************************************************************************/
+u8 zet6221_ts_pageerase(struct i2c_client *client,int npage)
+{
+ u8 ts_cmd[3] = {0x23,0x00,0x00};
+ u8 len = 0;
+ int ret;
+
+ switch(ic_model)
+ {
+ case ZET6221:
+ ts_cmd[1]=npage;
+ len=2;
+ break;
+ case ZET6231:
+ case ZET6223:
+ case ZET6251:
+ ts_cmd[1]=npage & 0xff;
+ ts_cmd[2]=npage >> 8;
+ len=3;
+ break;
+ default:
+ ts_cmd[1]=npage & 0xff;
+ ts_cmd[2]=npage >> 8;
+ len=3;
+ break;
+ }
+#if defined(I2C_CTPM_ADDRESS)
+ ret=i2c_write_interface(client, I2C_CTPM_ADDRESS, ts_cmd, len);
+#else
+ ret=zet6221_i2c_write_tsdata(client, ts_cmd, len);
+#endif
+ msleep(2);
+
+ return 1;
+}
+
+/***********************************************************************
+ [function]:
+ callback: reset mcu;
+ [parameters]:
+ client[in]: struct i2c_client ???represent an I2C slave device;
+
+ [return]:
+ 1;
+************************************************************************/
+u8 zet6221_ts_resetmcu(struct i2c_client *client)
+{
+ u8 ts_cmd[1] = {0x29};
+
+ int ret;
+
+#if defined(I2C_CTPM_ADDRESS)
+ ret=i2c_write_interface(client, I2C_CTPM_ADDRESS, ts_cmd, 1);
+#else
+ ret=zet6221_i2c_write_tsdata(client, ts_cmd, 1);
+#endif
+
+ return 1;
+}
+
+
+#define CMD_PROG_CHECK_SUM (0x36)
+#define CMD_PROG_GET_CHECK_SUM (0x37)
+///***********************************************************************
+/// [function]: zet622x_cmd_read_check_sum
+/// [parameters]: client, page_id, buf
+/// [return]: int
+///************************************************************************
+int zet622x_cmd_read_check_sum(struct i2c_client *client, int page_id, u8 * buf)
+{
+ int ret;
+ int cmd_len = 3;
+
+ buf[0]= CMD_PROG_CHECK_SUM;
+ buf[1]= (u8)(page_id) & 0xff;
+ buf[2]= (u8)(page_id >> 8);
+ ret=zet6221_i2c_write_tsdata(client, buf, cmd_len);
+ if(ret<=0)
+ {
+ printk("[ZET]: Read check sum fail");
+ return ret;
+ }
+
+ buf[0]= CMD_PROG_GET_CHECK_SUM;
+ cmd_len = 1;
+ ret=zet6221_i2c_write_tsdata(client, buf, cmd_len);
+ if(ret<=0)
+ {
+ printk("[ZET]: Read check sum fail");
+ return ret;
+ }
+
+ cmd_len = 1;
+ ret = zet6221_i2c_read_tsdata(client, buf, cmd_len);
+ if(ret<=0)
+ {
+ printk("[ZET]: Read check sum fail");
+ return ret;
+ }
+ return 1;
+}
+
+
+/***********************************************************************
+ [function]:
+ callback: start HW function;
+ [parameters]:
+ client[in]: struct i2c_client ???represent an I2C slave device;
+
+ [return]:
+ 1;
+************************************************************************/
+u8 zet6221_ts_hwcmd(struct i2c_client *client)
+{
+ u8 ts_cmd[1] = {0xB9};
+
+ int ret;
+
+#if defined(I2C_CTPM_ADDRESS)
+ ret=i2c_write_interface(client, I2C_CTPM_ADDRESS, ts_cmd, 1);
+#else
+ ret=zet6221_i2c_write_tsdata(client, ts_cmd, 1);
+#endif
+
+ return 1;
+}
+
+/***********************************************************************
+update FW
+************************************************************************/
+int __init zet6221_downloader( struct i2c_client *client )
+{
+ int BufLen=0;
+ int BufPage=0;
+ int BufIndex=0;
+ int ret;
+ int i;
+
+ int nowBufLen=0;
+ int nowBufPage=0;
+ int nowBufIndex=0;
+ int retryCount=0;
+ int retryTimes = 0;
+
+ int i2cLength=0;
+ int bufOffset=0;
+
+ dbg("zet6221_downloader++\n");
+
+begin_download:
+
+#if defined(RSTPIN_ENABLE)
+ //reset mcu
+ //gpio_direction_output(TS_RST_GPIO, GPIO_LOW);
+ wmt_rst_output(0);
+ msleep(5);
+#else
+ zet6221_ts_hwcmd(client);
+ msleep(200);
+#endif
+ //send password
+ //send password
+ ret = zet6221_ts_sndpwd(client);
+ dbg("zet6221_ts_sndpwd ret=%d\n",ret);
+ msleep(100);
+
+/*****compare version*******/
+
+ //0~3
+ memset(zeitec_zet6221_page_in,0x00,131);
+ switch(ic_model)
+ {
+ case ZET6221:
+ zeitec_zet6221_page_in[0]=0x25;
+ zeitec_zet6221_page_in[1]=(fb[0] >> 7);//(fb[0]/128);
+
+ i2cLength=2;
+ break;
+ case ZET6231:
+ case ZET6223:
+ case ZET6251:
+ default:
+ zeitec_zet6221_page_in[0]=0x25;
+ zeitec_zet6221_page_in[1]=(fb[0] >> 7) & 0xff; //(fb[0]/128);
+ zeitec_zet6221_page_in[2]=(fb[0] >> 7) >> 8; //(fb[0]/128);
+
+ i2cLength=3;
+ break;
+ }
+#if defined(I2C_CTPM_ADDRESS)
+ ret=i2c_write_interface(client, I2C_CTPM_ADDRESS, zeitec_zet6221_page_in, i2cLength);
+#else
+ ret=zet6221_i2c_write_tsdata(client, zeitec_zet6221_page_in, i2cLength);
+ dbg("write_ret =%d, i2caddr=0x%x\n", ret, client->addr);
+#endif
+ msleep(2);
+
+ zeitec_zet6221_page_in[0]=0x0;
+ zeitec_zet6221_page_in[1]=0x0;
+ zeitec_zet6221_page_in[2]=0x0;
+#if defined(I2C_CTPM_ADDRESS)
+ ret=i2c_read_interface(client, I2C_CTPM_ADDRESS, zeitec_zet6221_page_in, 128);
+#else
+ ret=zet6221_i2c_read_tsdata(client, zeitec_zet6221_page_in, 128);
+ dbg("read_ret =%d, i2caddr=0x%x\n", ret, client->addr);
+#endif
+
+ //printk("page=%d ",(fb[0] >> 7)); //(fb[0]/128));
+ for(i=0;i<4;i++)
+ {
+ pc[i]=zeitec_zet6221_page_in[(fb[i] & 0x7f)]; //[(fb[i]%128)];
+ dbg("offset[%d]=%d ",i,(fb[i] & 0x7f)); //(fb[i]%128));
+ }
+ dbg("\n");
+
+
+ // 4~7
+ memset(zeitec_zet6221_page_in,0x00,131);
+ switch(ic_model)
+ {
+ case ZET6221:
+ zeitec_zet6221_page_in[0]=0x25;
+ zeitec_zet6221_page_in[1]=(fb[4] >> 7);//(fb[4]/128);
+
+ i2cLength=2;
+ break;
+ case ZET6231:
+ case ZET6223:
+ case ZET6251:
+ zeitec_zet6221_page_in[0]=0x25;
+ zeitec_zet6221_page_in[1]=(fb[4] >> 7) & 0xff; //(fb[4]/128);
+ zeitec_zet6221_page_in[2]=(fb[4] >> 7) >> 8; //(fb[4]/128);
+
+ i2cLength=3;
+ break;
+ }
+#if defined(I2C_CTPM_ADDRESS)
+ ret=i2c_write_interface(client, I2C_CTPM_ADDRESS, zeitec_zet6221_page_in, i2cLength);
+#else
+ ret=zet6221_i2c_write_tsdata(client, zeitec_zet6221_page_in, i2cLength);
+ dbg("write_ret =%d, i2caddr=0x%x\n", ret, client->addr);
+#endif
+
+ zeitec_zet6221_page_in[0]=0x0;
+ zeitec_zet6221_page_in[1]=0x0;
+ zeitec_zet6221_page_in[2]=0x0;
+#if defined(I2C_CTPM_ADDRESS)
+ ret=i2c_read_interface(client, I2C_CTPM_ADDRESS, zeitec_zet6221_page_in, 128);
+#else
+ ret=zet6221_i2c_read_tsdata(client, zeitec_zet6221_page_in, 128);
+ dbg("read_ret =%d, i2caddr=0x%x\n", ret, client->addr);
+#endif
+
+ //printk("page=%d ",(fb[4] >> 7)); //(fb[4]/128));
+ for(i=4;i<8;i++)
+ {
+ pc[i]=zeitec_zet6221_page_in[(fb[i] & 0x7f)]; //[(fb[i]%128)];
+ dbg("offset[%d]=%d ",i,(fb[i] & 0x7f)); //(fb[i]%128));
+ }
+ dbg("\n");
+
+#if 1 // need to check
+ //page 127
+ memset(zeitec_zet6221_page_in,0x00,130);
+ zeitec_zet6221_page_in[0]=0x25;
+ zeitec_zet6221_page_in[1]=127;
+#if defined(I2C_CTPM_ADDRESS)
+ ret=i2c_write_interface(client, I2C_CTPM_ADDRESS, zeitec_zet6221_page_in, 2);
+#else
+ ret=zet6221_i2c_write_tsdata(client, zeitec_zet6221_page_in, 2);
+#endif
+
+ zeitec_zet6221_page_in[0]=0x0;
+ zeitec_zet6221_page_in[1]=0x0;
+#if defined(I2C_CTPM_ADDRESS)
+ ret=i2c_read_interface(client, I2C_CTPM_ADDRESS, zeitec_zet6221_page_in, 128);
+#else
+ ret=zet6221_i2c_read_tsdata(client, zeitec_zet6221_page_in, 128);
+#endif
+
+ for(i=0;i<128;i++)
+ {
+ // 0x3F80 = 16256 = 128x127, means skipped the first 127 page (0-126) ,use the page 127.
+ if(0x3F80+i < l_fwlen/*sizeof(flash_buffer)/sizeof(char)*/) //l_fwlen: the bytes of data read from firmware file
+ {
+ if(zeitec_zet6221_page_in[i]!=flash_buffer[0x3F80+i])
+ {
+ errlog("page 127 [%d] doesn't match! continue to download! retry times:%d\n",i,retryTimes);
+ if( retryTimes++ >= 20){ // retry 20 times ,quit
+ errlog("May be I2C comunication is error\n");
+ goto exit_download;
+ }
+ goto proc_sfr;
+ }
+ }
+ }
+
+#endif
+
+ if( get_download_option() == FORCE_DOWNLOAD ){
+ errlog("FORCE_DOWNLOAD\n");
+ goto proc_sfr;
+ }
+ if( get_download_option() == FORCE_CANCEL_DOWNLOAD ){
+ errlog("FORCE_CANCEL_DOWNLOAD\n");
+ goto exit_download;
+ }
+ if(zet6221_ts_version()!=0){
+ klog("tp version is the same,no need to download\n");
+ goto exit_download;
+ }
+
+
+
+/*****compare version*******/
+proc_sfr:
+ //sfr
+ if(zet6221_ts_sfr(client)==0)
+ {
+
+#if 1
+
+#if defined(RSTPIN_ENABLE)
+
+ //gpio_direction_output(TS_RST_GPIO, GPIO_HIGH);
+ wmt_rst_output(1);
+ msleep(20);
+
+ //gpio_direction_output(TS_RST_GPIO, GPIO_LOW);
+ wmt_rst_output(0);
+ msleep(20);
+
+ //gpio_direction_output(TS_RST_GPIO, GPIO_HIGH);
+ wmt_rst_output(1);
+#else
+ zet6221_ts_resetmcu(client);
+#endif
+ msleep(20);
+ errlog("zet6221_ts_sfr error, download again\n");
+ goto begin_download;
+
+#endif
+
+ }
+ msleep(20);
+
+ /// Fix the bug that page#504~#512 failed to write
+ if(ic_model == ZET6223)
+ {
+ zet6221_ts_sndpwd_1k(client);
+ }
+
+ //erase
+ if(BufLen==0)
+ {
+ //mass erase
+ dbg( "mass erase\n");
+ zet6221_ts_masserase(client);
+ msleep(200);
+
+ BufLen=l_fwlen;/*sizeof(flash_buffer)/sizeof(char)*/;
+ }else
+ {
+ zet6221_ts_pageerase(client,BufPage);
+ msleep(200);
+ }
+
+
+ while(BufLen>0)
+ {
+download_page:
+
+ memset(zeitec_zet6221_page,0x00,131);
+
+ klog( "Start: write page%d\n",BufPage);
+ nowBufIndex=BufIndex;
+ nowBufLen=BufLen;
+ nowBufPage=BufPage;
+
+ switch(ic_model)
+ {
+ case ZET6221:
+ bufOffset = 2;
+ i2cLength=130;
+
+ zeitec_zet6221_page[0]=0x22;
+ zeitec_zet6221_page[1]=BufPage;
+ break;
+ case ZET6231:
+ case ZET6223:
+ case ZET6251:
+ default:
+ bufOffset = 3;
+ i2cLength=131;
+
+ zeitec_zet6221_page[0]=0x22;
+ zeitec_zet6221_page[1]=BufPage & 0xff;
+ zeitec_zet6221_page[2]=BufPage >> 8;
+ break;
+ }
+ if(BufLen>128)
+ {
+ for(i=0;i<128;i++)
+ {
+ zeitec_zet6221_page[i+bufOffset]=flash_buffer[BufIndex];
+ BufIndex+=1;
+ }
+ zeitec_zet6221_page[0]=0x22;
+ zeitec_zet6221_page[1]=BufPage;
+ BufLen-=128;
+ }
+ else
+ {
+ for(i=0;i<BufLen;i++)
+ {
+ zeitec_zet6221_page[i+bufOffset]=flash_buffer[BufIndex];
+ BufIndex+=1;
+ }
+ zeitec_zet6221_page[0]=0x22;
+ zeitec_zet6221_page[1]=BufPage;
+ BufLen=0;
+ }
+
+#if defined(I2C_CTPM_ADDRESS)
+ ret=i2c_write_interface(client, I2C_CTPM_ADDRESS, zeitec_zet6221_page, i2cLength);
+#else
+ ret=zet6221_i2c_write_tsdata(client, zeitec_zet6221_page, i2cLength);
+#endif
+ //msleep(200);
+ msleep(2);
+
+#if 1
+
+ memset(zeitec_zet6221_page_in,0x00,131);
+ switch(ic_model)
+ {
+ case ZET6221:
+ zeitec_zet6221_page_in[0]=0x25;
+ zeitec_zet6221_page_in[1]=BufPage;
+
+ i2cLength=2;
+ break;
+ case ZET6231:
+ case ZET6223:
+ case ZET6251:
+ default:
+ zeitec_zet6221_page_in[0]=0x25;
+ zeitec_zet6221_page_in[1]=BufPage & 0xff;
+ zeitec_zet6221_page_in[2]=BufPage >> 8;
+
+ i2cLength=3;
+ break;
+ }
+#if defined(I2C_CTPM_ADDRESS)
+ ret=i2c_write_interface(client, I2C_CTPM_ADDRESS, zeitec_zet6221_page_in, i2cLength);
+#else
+ ret=zet6221_i2c_write_tsdata(client, zeitec_zet6221_page_in, i2cLength);
+#endif
+ msleep(2);
+
+ zeitec_zet6221_page_in[0]=0x0;
+ zeitec_zet6221_page_in[1]=0x0;
+ zeitec_zet6221_page_in[2]=0x0;
+#if defined(I2C_CTPM_ADDRESS)
+ ret=i2c_read_interface(client, I2C_CTPM_ADDRESS, zeitec_zet6221_page_in, 128);
+#else
+ ret=zet6221_i2c_read_tsdata(client, zeitec_zet6221_page_in, 128);
+#endif
+
+ for(i=0;i<128;i++)
+ {
+ if(i < nowBufLen)
+ {
+ if(zeitec_zet6221_page[i+bufOffset]!=zeitec_zet6221_page_in[i])
+ {
+ BufIndex=nowBufIndex;
+ BufLen=nowBufLen;
+ BufPage=nowBufPage;
+
+ if(retryCount < 5)
+ {
+ retryCount++;
+ goto download_page;
+ }else
+ {
+ //BufIndex=0;
+ //BufLen=0;
+ //BufPage=0;
+ retryCount=0;
+
+#if defined(RSTPIN_ENABLE)
+ //gpio_direction_output(TS_RST_GPIO, GPIO_HIGH);
+ wmt_rst_output(1);
+ msleep(20);
+
+ //gpio_direction_output(TS_RST_GPIO, GPIO_LOW);
+ wmt_rst_output(0);
+ msleep(20);
+
+ //gpio_direction_output(TS_RST_GPIO, GPIO_HIGH);
+ wmt_rst_output(1);
+#else
+ zet6221_ts_resetmcu(client);
+#endif
+ msleep(20);
+ goto begin_download;
+ }
+
+ }
+ }
+ }
+
+#endif
+ retryCount=0;
+ BufPage+=1;
+ }
+
+exit_download:
+
+#if defined(RSTPIN_ENABLE)
+ //gpio_direction_output(TS_RST_GPIO, GPIO_HIGH);
+ wmt_rst_output(1);
+ msleep(100);
+#endif
+
+ zet6221_ts_resetmcu(client);
+ msleep(100);
+
+ dbg("zet6221_downloader--\n");
+ return 1;
+
+
+}
+
+int zet622x_resume_downloader(struct i2c_client *client)
+{
+ int ret = 0;
+
+ int BufLen=0;
+ int BufPage=0;
+ int BufIndex=0;
+ int bufOffset = 0;
+
+ int nowBufLen=0;
+ int nowBufPage=0;
+ int nowBufIndex=0;
+
+ int i2cLength = 0;
+
+ int i = 0;
+
+ u8 bPageBuf[256];
+
+#ifdef FEATURE_FW_CHECK_SUM
+ u8 get_check_sum = 0;
+ u8 check_sum = 0;
+ int retry_count = 0;
+ u8 tmp_data[16];
+#endif ///< for FEATURE_FW_CHECK_SUM
+
+
+ ///-------------------------------------------------------------///
+ /// 1. Set RST=LOW
+ ///-------------------------------------------------------------///
+ wmt_rst_output(0);
+ msleep(20);
+ //printk("RST = LOW\n");
+
+ ///-------------------------------------------------------------///
+ /// Send password
+ ///-------------------------------------------------------------///
+ ret = zet6221_ts_sndpwd(client);
+ if(ret<=0)
+ {
+ return ret;
+ }
+
+ //printk("AAA\n");
+ BufLen=l_fwlen;/*sizeof(flash_buffer)/sizeof(char)*/;
+ //printk("BBB%d\n",BufLen);
+
+ while(BufLen>0)
+ {
+ /// memset(zeitec_zet622x_page, 0x00, 131);
+ nowBufIndex=BufIndex;
+ nowBufLen=BufLen;
+ nowBufPage=BufPage;
+
+ switch(ic_model)
+ {
+ case ZET6251:
+ bufOffset = 3;
+ i2cLength=131;
+
+ bPageBuf[0]=0x22;
+ bPageBuf[1]=BufPage & 0xff;
+ bPageBuf[2]=BufPage >> 8;
+ break;
+ }
+
+ if(BufLen>128)
+ {
+ for(i=0;i<128;i++)
+ {
+ bPageBuf[i + bufOffset] = flash_buffer[BufIndex];
+ BufIndex += 1;
+ }
+
+ BufLen = BufLen - 128;
+ }
+ else
+ {
+ for(i=0;i<BufLen;i++)
+ {
+ bPageBuf[i+bufOffset]=flash_buffer[BufIndex];
+ BufIndex+=1;
+ }
+
+ BufLen=0;
+ }
+
+#ifdef FEATURE_FW_CHECK_SUM
+LABEL_RETRY_DOWNLOAD_PAGE:
+#endif ///< for FEATURE_FW_CHECK_SUM
+
+ ret=zet6221_i2c_write_tsdata(client, bPageBuf, i2cLength);
+
+ if(ic_model!= ZET6251)
+ {
+ msleep(50);
+ }
+
+#ifdef FEATURE_FW_CHECK_SUM
+ ///---------------------------------///
+ /// Get check sum
+ ///---------------------------------///
+ for(i=0;i<128;i++)
+ {
+ if(i == 0)
+ {
+ check_sum = bPageBuf[i + bufOffset];
+ }
+ else
+ {
+ check_sum = check_sum ^ bPageBuf[i + bufOffset];
+ }
+ }
+
+ ///---------------------------------///
+ /// Read check sum
+ ///---------------------------------///
+ memset(tmp_data, 0, 16);
+ ret = zet622x_cmd_read_check_sum(client, BufPage, &tmp_data[0]);
+ if(ret<=0)
+ {
+ return ret;
+ }
+ get_check_sum = tmp_data[0];
+
+ //printk("[ZET]: page=%3d ,Check sum : %x ,get check sum : %x\n", BufPage, check_sum, get_check_sum);
+ if(check_sum != get_check_sum)
+ {
+
+ if(retry_count < 5)
+ {
+ retry_count++;
+ goto LABEL_RETRY_DOWNLOAD_PAGE;
+ }
+ else
+ {
+ retry_count = 0;
+ wmt_rst_output(1);
+ msleep(20);
+ wmt_rst_output(0);
+ msleep(20);
+ wmt_rst_output(1);
+ msleep(20);
+ printk("[ZET] zet622x_resume_downloader fail\n");
+ return ret;
+ }
+
+ }
+ retry_count = 0;
+#endif ///< for FEATURE_FW_CHECK_SUM
+
+ BufPage+=1;
+ }
+
+ printk("[ZET] zet622x_resume_downloader OK\n");
+ //printk("RST = HIGH\n");
+
+ ///-------------------------------------------------------------///
+ /// reset_mcu command
+ ///-------------------------------------------------------------///
+ zet6221_ts_resetmcu(client);
+ msleep(10);
+
+ ///-------------------------------------------------------------///
+ /// SET RST=HIGH
+ ///-------------------------------------------------------------///
+ wmt_rst_output(1);
+ msleep(20);
+
+ ///-------------------------------------------------------------///
+ /// RST toggle
+ ///-------------------------------------------------------------///
+ wmt_rst_output(0);
+ msleep(2);
+
+ wmt_rst_output(1);
+ msleep(2);
+
+ return ret;
+}
+
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/zet6221_ts/zet6221_i2c.c b/ANDROID_3.4.5/drivers/input/touchscreen/zet6221_ts/zet6221_i2c.c
new file mode 100755
index 00000000..31818510
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/zet6221_ts/zet6221_i2c.c
@@ -0,0 +1,2786 @@
+/* drivers/input/touchscreen/zet6221_i2c.c
+ * 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.
+ * ZEITEC Semiconductor Co., Ltd
+ * Tel: +886-3-579-0045
+ * Fax: +886-3-579-9960
+ * http://www.zeitecsemi.com
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/platform_device.h>
+#include <linux/jiffies.h>
+#include <linux/io.h>
+#include <linux/kthread.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/wakelock.h>
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <asm/uaccess.h>
+
+#include <linux/input/mt.h>
+#include "wmt_ts.h"
+#include <linux/power/wmt_battery.h>
+#include "../../../video/backlight/wmt_bl.h"
+
+
+//fw update.
+//#include "zet6221_fw.h"
+
+/* -------------- global variable definition -----------*/
+#define _MACH_MSM_TOUCH_H_
+
+#define ZET_TS_ID_NAME "zet6221-ts"
+
+#define MJ5_TS_NAME "touch_zet6221"
+
+//#define TS_INT_GPIO S3C64XX_GPN(9) /*s3c6410*/
+//#define TS1_INT_GPIO AT91_PIN_PB17 /*AT91SAM9G45 external*/
+//#define TS1_INT_GPIO AT91_PIN_PA27 /*AT91SAM9G45 internal*/
+//#define TS_RST_GPIO S3C64XX_GPN(10)
+
+//#define MT_TYPE_B
+
+#define TS_RST_GPIO
+#define X_MAX 800 //1024
+#define Y_MAX 480 //576
+#define FINGER_NUMBER 5
+#define KEY_NUMBER 3 //0
+//#define P_MAX 1
+#define P_MAX 255 //modify 2013-1-1
+#define D_POLLING_TIME 25000
+#define U_POLLING_TIME 25000
+#define S_POLLING_TIME 100
+#define REPORT_POLLING_TIME 3
+#define RETRY_DOWNLOAD_TIMES 2
+
+#define MAX_KEY_NUMBER 8
+#define MAX_FINGER_NUMBER 16
+#define TRUE 1
+#define FALSE 0
+
+//#define debug_mode 1
+//#define DPRINTK(fmt,args...) do { if (debug_mode) printk(KERN_EMERG "[%s][%d] "fmt"\n", __FUNCTION__, __LINE__, ##args);} while(0)
+
+//#define TRANSLATE_ENABLE 1
+#define TOPRIGHT 0
+#define TOPLEFT 1
+#define BOTTOMRIGHT 2
+#define BOTTOMLEFT 3
+#define ORIGIN BOTTOMRIGHT
+
+#define TIME_CHECK_CHARGE 3000
+
+#define I2C_MAJOR 126
+#define I2C_MINORS 256
+
+
+///=============================================================================================///
+/// IOCTL control Definition
+///=============================================================================================///
+#define ZET_IOCTL_CMD_FLASH_READ (20)
+#define ZET_IOCTL_CMD_FLASH_WRITE (21)
+#define ZET_IOCTL_CMD_RST (22)
+#define ZET_IOCTL_CMD_RST_HIGH (23)
+#define ZET_IOCTL_CMD_RST_LOW (24)
+
+#define ZET_IOCTL_CMD_DYNAMIC (25)
+
+#define ZET_IOCTL_CMD_FW_FILE_PATH_GET (26)
+#define ZET_IOCTL_CMD_FW_FILE_PATH_SET (27)
+
+#define ZET_IOCTL_CMD_MDEV (28)
+#define ZET_IOCTL_CMD_MDEV_GET (29)
+
+#define ZET_IOCTL_CMD_TRAN_TYPE_PATH_GET (30)
+#define ZET_IOCTL_CMD_TRAN_TYPE_PATH_SET (31)
+
+#define ZET_IOCTL_CMD_IDEV (32)
+#define ZET_IOCTL_CMD_IDEV_GET (33)
+
+#define ZET_IOCTL_CMD_MBASE (34)
+#define ZET_IOCTL_CMD_MBASE_GET (35)
+
+#define ZET_IOCTL_CMD_INFO_SET (36)
+#define ZET_IOCTL_CMD_INFO_GET (37)
+
+#define ZET_IOCTL_CMD_TRACE_X_SET (38)
+#define ZET_IOCTL_CMD_TRACE_X_GET (39)
+
+#define ZET_IOCTL_CMD_TRACE_Y_SET (40)
+#define ZET_IOCTL_CMD_TRACE_Y_GET (41)
+
+#define ZET_IOCTL_CMD_IBASE (42)
+#define ZET_IOCTL_CMD_IBASE_GET (43)
+
+#define ZET_IOCTL_CMD_DRIVER_VER_GET (44)
+#define ZET_IOCTL_CMD_MBASE_EXTERN_GET (45)
+
+#define IOCTL_MAX_BUF_SIZE (1024)
+
+///----------------------------------------------------///
+/// IOCTL ACTION
+///----------------------------------------------------///
+#define IOCTL_ACTION_NONE (0)
+#define IOCTL_ACTION_FLASH_DUMP (1<<0)
+
+static int ioctl_action = IOCTL_ACTION_NONE;
+
+///=============================================================================================///
+/// Transfer type
+///=============================================================================================///
+#define TRAN_TYPE_DYNAMIC (0x00)
+#define TRAN_TYPE_MUTUAL_SCAN_BASE (0x01)
+#define TRAN_TYPE_MUTUAL_SCAN_DEV (0x02)
+#define TRAN_TYPE_INIT_SCAN_BASE (0x03)
+#define TRAN_TYPE_INIT_SCAN_DEV (0x04)
+#define TRAN_TYPE_KEY_MUTUAL_SCAN_BASE (0x05)
+#define TRAN_TYPE_KEY_MUTUAL_SCAN_DEV (0x06)
+#define TRAN_TYPE_KEY_DATA (0x07)
+#define TRAN_TYPE_MTK_TYPE (0x0A)
+#define TRAN_TYPE_FOCAL_TYPE (0x0B)
+
+///=============================================================================================///
+/// TP Trace
+///=============================================================================================///
+#define TP_DEFAULT_ROW (10)
+#define TP_DEFAULT_COL (15)
+
+#define DRIVER_VERSION "$Revision: 44 $"
+//static char const *revision="$Revision: 44 $";
+
+///=============================================================================================///
+/// Macro Definition
+///=============================================================================================///
+#define MAX_FLASH_BUF_SIZE (0x10000)
+
+///---------------------------------------------------------------------------------///
+/// 18. IOCTRL Debug
+///---------------------------------------------------------------------------------///
+#define FEATURE_IDEV_OUT_ENABLE
+#define FEATURE_MBASE_OUT_ENABLE
+#define FEATURE_MDEV_OUT_ENABLE
+#define FEATURE_INFO_OUT_EANBLE
+#define FEATURE_IBASE_OUT_ENABLE
+
+
+
+///-------------------------------------///
+/// firmware save / load
+///-------------------------------------///
+u32 data_offset = 0;
+struct inode *inode = NULL;
+mm_segment_t old_fs;
+
+char driver_version[128];
+
+//#define FW_FILE_NAME "/vendor/modules/zet62xx.bin"
+char fw_file_name[128];
+///-------------------------------------///
+/// Transmit Type Mode Path parameters
+///-------------------------------------///
+/// External SD-Card could be
+/// "/mnt/sdcard/"
+/// "/mnt/extsd/"
+///-------------------------------------///
+
+// It should be the path where adb tools can push files in
+#define TRAN_MODE_FILE_PATH "/data/local/tmp/"
+char tran_type_mode_file_name[128];
+u8 *tran_data = NULL;
+
+///-------------------------------------///
+/// Mutual Dev Mode parameters
+///-------------------------------------///
+/// External SD-Card could be
+/// "/mnt/sdcard/zetmdev"
+/// "/mnt/extsd/zetmdev"
+///-------------------------------------///
+#ifdef FEATURE_MDEV_OUT_ENABLE
+ #define MDEV_FILE_NAME "zetmdev"
+ #define MDEV_MAX_FILE_ID (10)
+ #define MDEV_MAX_DATA_SIZE (2048)
+///-------------------------------------///
+/// mutual dev variables
+///-------------------------------------///
+ u8 *mdev_data = NULL;
+ int mdev_file_id = 0;
+#endif ///< FEATURE_MDEV_OUT_ENABLE
+
+///-------------------------------------///
+/// Initial Base Mode parameters
+///-------------------------------------///
+/// External SD-Card could be
+/// "/mnt/sdcard/zetibase"
+/// "/mnt/extsd/zetibase"
+///-------------------------------------///
+#ifdef FEATURE_IBASE_OUT_ENABLE
+ #define IBASE_FILE_NAME "zetibase"
+ #define IBASE_MAX_FILE_ID (10)
+ #define IBASE_MAX_DATA_SIZE (512)
+
+///-------------------------------------///
+/// initial base variables
+///-------------------------------------///
+ u8 *ibase_data = NULL;
+ int ibase_file_id = 0;
+#endif ///< FEATURE_IBASE_OUT_ENABLE
+
+///-------------------------------------///
+/// Initial Dev Mode parameters
+///-------------------------------------///
+/// External SD-Card could be
+/// "/mnt/sdcard/zetidev"
+/// "/mnt/extsd/zetidev"
+///-------------------------------------///
+#ifdef FEATURE_IDEV_OUT_ENABLE
+ #define IDEV_FILE_NAME "zetidev"
+ #define IDEV_MAX_FILE_ID (10)
+ #define IDEV_MAX_DATA_SIZE (512)
+
+///-------------------------------------///
+/// initial dev variables
+///-------------------------------------///
+ u8 *idev_data = NULL;
+ int idev_file_id = 0;
+#endif ///< FEATURE_IDEV_OUT_ENABLE
+
+///-------------------------------------///
+/// Mutual Base Mode parameters
+///-------------------------------------///
+/// External SD-Card could be
+/// "/mnt/sdcard/zetmbase"
+/// "/mnt/extsd/zetmbase"
+///-------------------------------------///
+#ifdef FEATURE_MBASE_OUT_ENABLE
+ #define MBASE_FILE_NAME "zetmbase"
+ #define MBASE_MAX_FILE_ID (10)
+ #define MBASE_MAX_DATA_SIZE (2048)
+
+///-------------------------------------///
+/// mutual base variables
+///-------------------------------------///
+ u8 *mbase_data = NULL;
+ int mbase_file_id = 0;
+#endif ///< FEATURE_MBASE_OUT_ENABLE
+
+///-------------------------------------///
+/// infomation variables
+///-------------------------------------///
+#ifdef FEATURE_INFO_OUT_EANBLE
+ #define INFO_MAX_DATA_SIZE (64)
+ #define INFO_DATA_SIZE (17)
+ #define ZET6221_INFO (0x00)
+ #define ZET6231_INFO (0x0B)
+ #define ZET6223_INFO (0x0D)
+ #define ZET6251_INFO (0x0C)
+ #define UNKNOW_INFO (0xFF)
+ u8 *info_data = NULL;
+#endif ///< FEATURE_INFO_OUT_EANBLE
+///-------------------------------------///
+/// Default transfer type
+///-------------------------------------///
+u8 transfer_type = TRAN_TYPE_DYNAMIC;
+
+///-------------------------------------///
+/// Default TP TRACE
+///-------------------------------------///
+int row = TP_DEFAULT_ROW;
+int col = TP_DEFAULT_COL;
+
+struct msm_ts_platform_data {
+ unsigned int x_max;
+ unsigned int y_max;
+ unsigned int pressure_max;
+};
+
+struct zet6221_tsdrv {
+ struct i2c_client *i2c_ts;
+ struct work_struct work1;
+ struct input_dev *input;
+ struct timer_list polling_timer;
+ struct delayed_work work; // for polling
+ struct workqueue_struct *queue;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend early_suspend;
+#endif
+ unsigned int gpio; /* GPIO used for interrupt of TS1*/
+ unsigned int irq;
+ unsigned int x_max;
+ unsigned int y_max;
+ unsigned int pressure_max;
+};
+
+struct i2c_dev
+{
+ struct list_head list;
+ struct i2c_adapter *adap;
+ struct device *dev;
+};
+
+static struct i2c_dev *zet_i2c_dev;
+static struct class *i2c_dev_class;
+static LIST_HEAD (i2c_dev_list);
+static DEFINE_SPINLOCK(i2c_dev_list_lock);
+
+struct zet6221_tsdrv * l_ts = NULL;
+static int l_suspend = 0; // 1:suspend, 0:normal state
+
+//static int resetCount = 0; //albert++ 20120807
+
+
+//static u16 polling_time = S_POLLING_TIME;
+
+static int l_powermode = -1;
+static struct mutex i2c_mutex;
+static struct wake_lock downloadWakeLock;
+
+
+//static int __devinit zet6221_ts_probe(struct i2c_client *client, const struct i2c_device_id *id);
+//static int __devexit zet6221_ts_remove(struct i2c_client *dev);
+extern int register_bl_notifier(struct notifier_block *nb);
+
+extern int unregister_bl_notifier(struct notifier_block *nb);
+
+extern int zet6221_downloader( struct i2c_client *client/*, unsigned short ver, unsigned char * data */);
+extern int zet622x_resume_downloader(struct i2c_client *client);
+extern u8 zet6221_ts_version(void);
+extern u8 zet6221_ts_get_report_mode_t(struct i2c_client *client);
+extern u8 zet622x_ts_option(struct i2c_client *client);
+extern int zet6221_load_fw(void);
+extern int zet6221_free_fwmem(void);
+
+void zet6221_ts_charger_mode_disable(void);
+void zet6221_ts_charger_mode(void);
+static int zet_fw_size(void);
+static void zet_fw_save(char *file_name);
+static void zet_fw_load(char *file_name);
+static void zet_fw_init(void);
+#ifdef FEATURE_MDEV_OUT_ENABLE
+static void zet_mdev_save(char *file_name);
+#endif ///< FEATURE_MDEV_OUT_ENABLE
+#ifdef FEATURE_IDEV_OUT_ENABLE
+static void zet_idev_save(char *file_name);
+#endif ///< FEATURE_IDEV_OUT_ENABLE
+#ifdef FEATURE_IBASE_OUT_ENABLE
+static void zet_ibase_save(char *file_name);
+#endif ///< FEATURE_IBASE_OUT_ENABLE
+#ifdef FEATURE_MBASE_OUT_ENABLE
+static void zet_mbase_save(char *file_name);
+#endif ///< FEATURE_MBASE_OUT_ENABLE
+static void zet_information_save(char *file_name);
+
+static struct task_struct *resume_download_task;
+
+
+
+//static int filterCount = 0;
+//static u32 filterX[MAX_FINGER_NUMBER][2], filterY[MAX_FINGER_NUMBER][2];
+
+//static u8 key_menu_pressed = 0x1;
+//static u8 key_back_pressed = 0x1;
+//static u8 key_search_pressed = 0x1;
+
+static u16 ResolutionX=X_MAX;
+static u16 ResolutionY=Y_MAX;
+static u16 FingerNum=0;
+static u16 KeyNum=0;
+static int bufLength=0;
+static u8 xyExchange=0;
+static u16 inChargerMode = 0;
+static struct i2c_client *this_client;
+struct workqueue_struct *ts_wq = NULL;
+static int l_tskey[4][2] = {
+ {KEY_BACK,0},
+ {KEY_MENU,0},
+ {KEY_HOME,0},
+ {KEY_SEARCH,0},
+};
+
+u8 pc[8];
+// {IC Model, FW Version, FW version,Codebase Type=0x08, Customer ID, Project ID, Config Board No, Config Serial No}
+
+//Touch Screen
+/*static const struct i2c_device_id zet6221_ts_idtable[] = {
+ { ZET_TS_ID_NAME, 0 },
+ { }
+};
+
+static struct i2c_driver zet6221_ts_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = ZET_TS_ID_NAME,
+ },
+ .probe = zet6221_ts_probe,
+ .remove = __devexit_p(zet6221_ts_remove),
+ .id_table = zet6221_ts_idtable,
+};
+*/
+
+void zet6221_set_tskey(int index,int key)
+{
+ l_tskey[index][0] = key;
+}
+
+
+void check_charger(void)
+{
+ mutex_lock(&i2c_mutex);
+ if (!wmt_charger_is_dc_plugin())
+ {
+ klog("disable_mode\n");
+ zet6221_ts_charger_mode_disable();
+ } else {
+ klog("charge mode\n");
+ zet6221_ts_charger_mode();
+ }
+ mutex_unlock(&i2c_mutex);
+ l_powermode = wmt_charger_is_dc_plugin();
+}
+
+
+void check_charger_polling(void)
+{
+ if(l_suspend == 1)
+ {
+ return;
+ }
+
+ if (wmt_charger_is_dc_plugin() != l_powermode)
+ {
+ check_charger();
+ }
+
+ ///-------------------------------------------------------------------///
+ /// IOCTL Action
+ ///-------------------------------------------------------------------///
+ if(ioctl_action & IOCTL_ACTION_FLASH_DUMP)
+ {
+ printk("[ZET]: IOCTL_ACTION: Dump flash\n");
+ zet_fw_save(fw_file_name);
+ ioctl_action &= ~IOCTL_ACTION_FLASH_DUMP;
+ }
+
+ return;
+}
+
+
+
+//extern unsigned int wmt_bat_is_batterypower(void);
+/***********************************************************************
+ [function]:
+ callback: Timer Function if there is no interrupt fuction;
+ [parameters]:
+ arg[in]: arguments;
+ [return]:
+ NULL;
+************************************************************************/
+
+static void polling_timer_func(struct work_struct *work)
+{
+ struct zet6221_tsdrv *ts = l_ts;
+ //schedule_work(&ts->work1);
+ //queue_work(ts_wq,&ts->work1);
+ //dbg("check mode!\n");
+/*
+ if (wmt_bat_is_batterypower() != l_powermode)
+ {
+ mutex_lock(&i2c_mutex);
+ if (wmt_bat_is_batterypower())
+ {
+ klog("disable_mode\n");
+ zet6221_ts_charger_mode_disable();
+ } else {
+ klog("charge mode\n");
+ zet6221_ts_charger_mode();
+ }
+ mutex_unlock(&i2c_mutex);
+ l_powermode = wmt_bat_is_batterypower();
+ }
+*/
+
+ check_charger_polling();
+ queue_delayed_work(ts->queue, &ts->work, msecs_to_jiffies(TIME_CHECK_CHARGE));
+
+
+ //mod_timer(&ts->polling_timer,jiffies + msecs_to_jiffies(TIME_CHECK_CHARGE));
+}
+
+
+
+///**********************************************************************
+/// [function]: zet622x_i2c_get_free_dev
+/// [parameters]: adap
+/// [return]: void
+///**********************************************************************
+static struct i2c_dev *zet622x_i2c_get_free_dev(struct i2c_adapter *adap)
+{
+ struct i2c_dev *i2c_dev;
+
+ if (adap->nr >= I2C_MINORS)
+ {
+ printk("[ZET] : i2c-dev:out of device minors (%d) \n",adap->nr);
+ return ERR_PTR (-ENODEV);
+ }
+
+ i2c_dev = kzalloc(sizeof(*i2c_dev), GFP_KERNEL);
+ if (!i2c_dev)
+ {
+ return ERR_PTR(-ENOMEM);
+ }
+ i2c_dev->adap = adap;
+
+ spin_lock(&i2c_dev_list_lock);
+ list_add_tail(&i2c_dev->list, &i2c_dev_list);
+ spin_unlock(&i2c_dev_list_lock);
+
+ return i2c_dev;
+}
+
+///**********************************************************************
+/// [function]: zet622x_i2c_dev_get_by_minor
+/// [parameters]: index
+/// [return]: i2c_dev
+///**********************************************************************
+static struct i2c_dev *zet622x_i2c_dev_get_by_minor(unsigned index)
+{
+ struct i2c_dev *i2c_dev;
+ spin_lock(&i2c_dev_list_lock);
+
+ list_for_each_entry(i2c_dev, &i2c_dev_list, list)
+ {
+ printk(" [ZET] : line = %d ,i2c_dev->adapt->nr = %d,index = %d.\n",__LINE__,i2c_dev->adap->nr,index);
+ if(i2c_dev->adap->nr == index)
+ {
+ goto LABEL_FOUND;
+ }
+ }
+ i2c_dev = NULL;
+
+LABEL_FOUND:
+ spin_unlock(&i2c_dev_list_lock);
+
+ return i2c_dev ;
+}
+
+
+
+//extern int wmt_i2c_xfer_continue_if_4(struct i2c_msg *msg, unsigned int num,int bus_id);
+/***********************************************************************
+ [function]:
+ callback: read data by i2c interface;
+ [parameters]:
+ client[in]: struct i2c_client �represent an I2C slave device;
+ data [out]: data buffer to read;
+ length[in]: data length to read;
+ [return]:
+ Returns negative errno, else the number of messages executed;
+************************************************************************/
+int zet6221_i2c_read_tsdata(struct i2c_client *client, u8 *data, u8 length)
+{
+ struct i2c_msg msg;
+ msg.addr = client->addr;
+ msg.flags = I2C_M_RD;
+ msg.len = length;
+ msg.buf = data;
+ return i2c_transfer(client->adapter,&msg, 1);
+
+ /*int rc = 0;
+
+ memset(data, 0, length);
+ rc = i2c_master_recv(client, data, length);
+ if (rc <= 0)
+ {
+ errlog("error!\n");
+ return -EINVAL;
+ } else if (rc != length)
+ {
+ dbg("want:%d,real:%d\n", length, rc);
+ }
+ return rc;*/
+}
+
+/***********************************************************************
+ [function]:
+ callback: write data by i2c interface;
+ [parameters]:
+ client[in]: struct i2c_client �represent an I2C slave device;
+ data [out]: data buffer to write;
+ length[in]: data length to write;
+ [return]:
+ Returns negative errno, else the number of messages executed;
+************************************************************************/
+int zet6221_i2c_write_tsdata(struct i2c_client *client, u8 *data, u8 length)
+{
+ struct i2c_msg msg;
+ msg.addr = client->addr;
+ msg.flags = 0;
+ msg.len = length;
+ msg.buf = data;
+ return i2c_transfer(client->adapter,&msg, 1);
+
+ /*int ret = i2c_master_recv(client, data, length);
+ if (ret <= 0)
+ {
+ errlog("error!\n");
+ }
+ return ret;
+ */
+}
+
+/***********************************************************************
+ [function]:
+ callback: coordinate traslating;
+ [parameters]:
+ px[out]: value of X axis;
+ py[out]: value of Y axis;
+ p [in]: pressed of released status of fingers;
+ [return]:
+ NULL;
+************************************************************************/
+void touch_coordinate_traslating(u32 *px, u32 *py, u8 p)
+{
+ int i;
+ u8 pressure;
+
+ #if ORIGIN == TOPRIGHT
+ for(i=0;i<MAX_FINGER_NUMBER;i++){
+ pressure = (p >> (MAX_FINGER_NUMBER-i-1)) & 0x1;
+ if(pressure)
+ {
+ px[i] = X_MAX - px[i];
+ }
+ }
+ #elif ORIGIN == BOTTOMRIGHT
+ for(i=0;i<MAX_FINGER_NUMBER;i++){
+ pressure = (p >> (MAX_FINGER_NUMBER-i-1)) & 0x1;
+ if(pressure)
+ {
+ px[i] = X_MAX - px[i];
+ py[i] = Y_MAX - py[i];
+ }
+ }
+ #elif ORIGIN == BOTTOMLEFT
+ for(i=0;i<MAX_FINGER_NUMBER;i++){
+ pressure = (p >> (MAX_FINGER_NUMBER-i-1)) & 0x1;
+ if(pressure)
+ {
+ py[i] = Y_MAX - py[i];
+ }
+ }
+ #endif
+}
+
+/***********************************************************************
+ [function]:
+ callback: reset function;
+ [parameters]:
+ void;
+ [return]:
+ void;
+************************************************************************/
+void ctp_reset(void)
+{
+#if defined(TS_RST_GPIO)
+ //reset mcu
+ /* gpio_direction_output(TS_RST_GPIO, 1);
+ msleep(1);
+ gpio_direction_output(TS_RST_GPIO, 0);
+ msleep(10);
+ gpio_direction_output(TS_RST_GPIO, 1);
+ msleep(20);*/
+ wmt_rst_output(1);
+ msleep(1);
+ wmt_rst_output(0);
+ msleep(10);
+ wmt_rst_output(1);
+ msleep(5);
+ dbg("has done\n");
+#else
+ u8 ts_reset_cmd[1] = {0xb0};
+ zet6221_i2c_write_tsdata(this_client, ts_reset_cmd, 1);
+#endif
+
+}
+
+
+///**********************************************************************
+/// [function]: zet622x_ts_parse_mutual_dev
+/// [parameters]: client
+/// [return]: u8
+///**********************************************************************
+#ifdef FEATURE_MDEV_OUT_ENABLE
+u8 zet622x_ts_parse_mutual_dev(struct i2c_client *client)
+{
+ int mdev_packet_size = (row+2) * (col + 2);
+ int ret = 0;
+ int idx = 0;
+ int len = mdev_packet_size;
+ char mdev_file_name_out[128];
+
+ int step_size = col + 2;
+
+ while(len > 0)
+ {
+ if(len < step_size)
+ {
+ step_size = len;
+ }
+
+ ret = zet6221_i2c_read_tsdata(client, &tran_data[idx], step_size);
+ len -= step_size;
+ idx += step_size;
+ }
+
+ sprintf(mdev_file_name_out, "%s%s%02d.bin", tran_type_mode_file_name, MDEV_FILE_NAME, mdev_file_id);
+ zet_mdev_save(mdev_file_name_out);
+ mdev_file_id = (mdev_file_id +1)% (MDEV_MAX_FILE_ID);
+ return ret;
+}
+#endif ///< FEATURE_MDEV_OUT_ENABLE
+
+///**********************************************************************
+/// [function]: zet622x_ts_parse_initial_base
+/// [parameters]: client
+/// [return]: u8
+///**********************************************************************
+#ifdef FEATURE_IBASE_OUT_ENABLE
+u8 zet622x_ts_parse_initial_base(struct i2c_client *client)
+{
+ int ibase_packet_size = (row + col) * 2;
+ int ret = 0;
+ int idx = 0;
+ int len = ibase_packet_size;
+ char ibase_file_name_out[128];
+
+ int step_size = ibase_packet_size;
+
+ while(len > 0)
+ {
+ ret = zet6221_i2c_read_tsdata(client, &tran_data[idx], step_size);
+ len -= step_size;
+ }
+ sprintf(ibase_file_name_out, "%s%s%02d.bin", tran_type_mode_file_name, IBASE_FILE_NAME, ibase_file_id);
+ zet_ibase_save(ibase_file_name_out);
+ ibase_file_id = (ibase_file_id +1)% (IBASE_MAX_FILE_ID);
+ return ret;
+}
+#endif ///< FEATURE_IBASE_OUT_ENABLE
+
+///**********************************************************************
+/// [function]: zet622x_ts_parse_initial_dev
+/// [parameters]: client
+/// [return]: u8
+///**********************************************************************
+#ifdef FEATURE_IDEV_OUT_ENABLE
+u8 zet622x_ts_parse_initial_dev(struct i2c_client *client)
+{
+ int idev_packet_size = (row + col);
+ int ret = 0;
+ int idx = 0;
+ int len = idev_packet_size;
+ char idev_file_name_out[128];
+
+ int step_size = idev_packet_size;
+
+ while(len > 0)
+ {
+ ret = zet6221_i2c_read_tsdata(client, &tran_data[idx], step_size);
+ len -= step_size;
+ }
+ sprintf(idev_file_name_out, "%s%s%02d.bin", tran_type_mode_file_name, IDEV_FILE_NAME, idev_file_id);
+ zet_idev_save(idev_file_name_out);
+ idev_file_id = (idev_file_id +1)% (IDEV_MAX_FILE_ID);
+ return ret;
+}
+#endif ///< FEATURE_IDEV_OUT_ENABLE
+
+///**********************************************************************
+/// [function]: zet622x_ts_parse_mutual_base
+/// [parameters]: client
+/// [return]: u8
+///**********************************************************************
+#ifdef FEATURE_MBASE_OUT_ENABLE
+u8 zet622x_ts_parse_mutual_base(struct i2c_client *client)
+{
+ int mbase_packet_size = (row * col * 2);
+ int ret = 0;
+ int idx = 0;
+ int len = mbase_packet_size;
+ char mbase_file_name_out[128];
+
+ int step_size = col*2;
+
+ while(len > 0)
+ {
+ if(len < step_size)
+ {
+ step_size = len;
+ }
+
+ ret = zet6221_i2c_read_tsdata(client, &tran_data[idx], step_size);
+ len -= step_size;
+ idx += step_size;
+ }
+ sprintf(mbase_file_name_out, "%s%s%02d.bin",tran_type_mode_file_name, MBASE_FILE_NAME, mbase_file_id);
+ zet_mbase_save(mbase_file_name_out);
+ mbase_file_id = (mbase_file_id +1)% (MBASE_MAX_FILE_ID);
+ return ret;
+}
+#endif ///< FEATURE_MBASE_OUT_ENABLE
+
+/***********************************************************************
+ [function]:
+ callback: read finger information from TP;
+ [parameters]:
+ client[in]: struct i2c_client �represent an I2C slave device;
+ x[out]: values of X axis;
+ y[out]: values of Y axis;
+ z[out]: values of Z axis;
+ pr[out]: pressed of released status of fingers;
+ ky[out]: pressed of released status of keys;
+ [return]:
+ Packet ID;
+************************************************************************/
+u8 zet6221_ts_get_xy_from_panel(struct i2c_client *client, u32 *x, u32 *y, u32 *z, u32 *pr, u32 *ky)
+{
+ u8 ts_data[70];
+ int ret;
+ int i;
+
+ memset(ts_data,0,70);
+
+ ret=zet6221_i2c_read_tsdata(client, ts_data, bufLength);
+
+ *pr = ts_data[1];
+ *pr = (*pr << 8) | ts_data[2];
+
+ for(i=0;i<FingerNum;i++)
+ {
+ x[i]=(u8)((ts_data[3+4*i])>>4)*256 + (u8)ts_data[(3+4*i)+1];
+ y[i]=(u8)((ts_data[3+4*i]) & 0x0f)*256 + (u8)ts_data[(3+4*i)+2];
+ z[i]=(u8)((ts_data[(3+4*i)+3]) & 0x0f);
+ }
+
+ //if key enable
+ if(KeyNum > 0)
+ *ky = ts_data[3+4*FingerNum];
+
+ return ts_data[0];
+}
+
+/***********************************************************************
+ [function]:
+ callback: get dynamic report information;
+ [parameters]:
+ client[in]: struct i2c_client �represent an I2C slave device;
+
+ [return]:
+ 1;
+************************************************************************/
+u8 zet6221_ts_get_report_mode(struct i2c_client *client)
+{
+ u8 ts_report_cmd[1] = {0xb2};
+ //u8 ts_reset_cmd[1] = {0xb0};
+ u8 ts_in_data[17] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+
+ int ret;
+ int i;
+ int count=0;
+
+ ret=zet6221_i2c_write_tsdata(client, ts_report_cmd, 1);
+
+ if (ret > 0)
+ {
+ while(1)
+ {
+ msleep(1);
+
+ //if (gpio_get_value(TS_INT_GPIO) == 0)
+ if (wmt_ts_irqinval() == 0)
+ {
+ dbg( "int low\n");
+ ret=zet6221_i2c_read_tsdata(client, ts_in_data, 17);
+
+ if(ret > 0)
+ {
+
+ for(i=0;i<8;i++)
+ {
+ pc[i]=ts_in_data[i] & 0xff;
+ }
+
+ if(pc[3] != 0x08)
+ {
+ errlog("=============== zet6221_ts_get_report_mode report error ===============\n");
+ return 0;
+ }
+
+ xyExchange = (ts_in_data[16] & 0x8) >> 3;
+ if(xyExchange == 1)
+ {
+ ResolutionY= ts_in_data[9] & 0xff;
+ ResolutionY= (ResolutionY << 8)|(ts_in_data[8] & 0xff);
+ ResolutionX= ts_in_data[11] & 0xff;
+ ResolutionX= (ResolutionX << 8) | (ts_in_data[10] & 0xff);
+ }
+ else
+ {
+ ResolutionX = ts_in_data[9] & 0xff;
+ ResolutionX = (ResolutionX << 8)|(ts_in_data[8] & 0xff);
+ ResolutionY = ts_in_data[11] & 0xff;
+ ResolutionY = (ResolutionY << 8) | (ts_in_data[10] & 0xff);
+ }
+
+ FingerNum = (ts_in_data[15] & 0x7f);
+ KeyNum = (ts_in_data[15] & 0x80);
+
+ if(KeyNum==0)
+ bufLength = 3+4*FingerNum;
+ else
+ bufLength = 3+4*FingerNum+1;
+
+ //DPRINTK( "bufLength=%d\n",bufLength);
+
+ break;
+
+ }else
+ {
+ errlog ("=============== zet6221_ts_get_report_mode read error ===============\n");
+ return 0;
+ }
+
+ }else
+ {
+ //DPRINTK( "int high\n");
+ if(count++ > 30)
+ {
+ errlog ("=============== zet6221_ts_get_report_mode time out ===============\n");
+ return 0;
+ }
+
+ }
+ }
+
+ }
+ return 1;
+}
+
+#if 0
+static int zet6221_is_ts(struct i2c_client *client)
+{
+ /*u8 ts_in_data[17] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+
+ ctp_reset();
+ if (zet6221_i2c_read_tsdata(client, ts_in_data, 17) <= 0)
+ {
+ return 0;
+ }
+ return 1;*/
+ return 1;
+}
+#endif
+
+/***********************************************************************
+ [function]:
+ callback: get dynamic report information with timer delay;
+ [parameters]:
+ client[in]: struct i2c_client represent an I2C slave device;
+
+ [return]:
+ 1;
+************************************************************************/
+
+u8 zet6221_ts_get_report_mode_t(struct i2c_client *client)
+{
+ u8 ts_report_cmd[1] = {0xb2};
+ u8 ts_in_data[17] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+
+ int ret;
+ int i;
+
+ ret=zet6221_i2c_write_tsdata(client, ts_report_cmd, 1);
+ msleep(10);
+
+ dbg("ret=%d,i2c_addr=0x%x\n", ret, client->addr);
+ if (ret > 0)
+ {
+ //mdelay(10);
+ //msleep(10);
+ dbg("=============== zet6221_ts_get_report_mode_t ===============\n");
+ ret=zet6221_i2c_read_tsdata(client, ts_in_data, 17);
+
+ if(ret > 0)
+ {
+
+ for(i=0;i<8;i++)
+ {
+ pc[i]=ts_in_data[i] & 0xff;
+ }
+
+ if(pc[3] != 0x08)
+ {
+ errlog("=============== zet6221_ts_get_report_mode_t report error ===============\n");
+ return 0;
+ }
+
+ xyExchange = (ts_in_data[16] & 0x8) >> 3;
+ if(xyExchange == 1)
+ {
+ ResolutionY= ts_in_data[9] & 0xff;
+ ResolutionY= (ResolutionY << 8)|(ts_in_data[8] & 0xff);
+ ResolutionX= ts_in_data[11] & 0xff;
+ ResolutionX= (ResolutionX << 8) | (ts_in_data[10] & 0xff);
+ }
+ else
+ {
+ ResolutionX = ts_in_data[9] & 0xff;
+ ResolutionX = (ResolutionX << 8)|(ts_in_data[8] & 0xff);
+ ResolutionY = ts_in_data[11] & 0xff;
+ ResolutionY = (ResolutionY << 8) | (ts_in_data[10] & 0xff);
+ }
+
+ FingerNum = (ts_in_data[15] & 0x7f);
+ KeyNum = (ts_in_data[15] & 0x80);
+ inChargerMode = (ts_in_data[16] & 0x2) >> 1;
+
+ if(KeyNum==0)
+ bufLength = 3+4*FingerNum;
+ else
+ bufLength = 3+4*FingerNum+1;
+
+ }else
+ {
+ errlog ("=============== zet6221_ts_get_report_mode_t READ ERROR ===============\n");
+ return 0;
+ }
+
+ }else
+ {
+ errlog("=============== zet6221_ts_get_report_mode_t WRITE ERROR ===============\n");
+ return 0;
+ }
+ return 1;
+}
+
+/***********************************************************************
+ [function]:
+ callback: interrupt function;
+ [parameters]:
+ irq[in]: irq value;
+ dev_id[in]: dev_id;
+
+ [return]:
+ NULL;
+************************************************************************/
+static irqreturn_t zet6221_ts_interrupt(int irq, void *dev_id)
+{
+ struct zet6221_tsdrv *ts_drv = dev_id;
+ int j = 0;
+ if (wmt_is_tsint())
+ {
+ wmt_clr_int();
+ if (wmt_is_tsirq_enable() && l_suspend == 0)
+ {
+ wmt_disable_gpirq();
+ dbg("begin..\n");
+ //if (!work_pending(&l_tsdata.pen_event_work))
+ if (wmt_ts_irqinval() == 0)
+ {
+ queue_work(ts_wq, &ts_drv->work1);
+ } else {
+ if(KeyNum > 0)
+ {
+ //if (0 == ky)
+ {
+ for (j=0;j<4;j++)
+ {
+ if (l_tskey[j][1] != 0)
+ {
+ l_tskey[j][1] = 0;
+ }
+ }
+ dbg("finish one key report!\n");
+ }
+ }
+ wmt_enable_gpirq();
+ }
+ }
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_NONE;
+
+ /*//polling_time = D_POLLING_TIME;
+
+ if (gpio_get_value(TS_INT_GPIO) == 0)
+ {
+ // IRQ is triggered by FALLING code here
+ struct zet6221_tsdrv *ts_drv = dev_id;
+ schedule_work(&ts_drv->work1);
+ //DPRINTK("TS1_INT_GPIO falling\n");
+ }else
+ {
+ //DPRINTK("TS1_INT_GPIO raising\n");
+ }
+
+ return IRQ_HANDLED;*/
+}
+
+/***********************************************************************
+ [function]:
+ callback: touch information handler;
+ [parameters]:
+ _work[in]: struct work_struct;
+
+ [return]:
+ NULL;
+************************************************************************/
+static void zet6221_ts_work(struct work_struct *_work)
+{
+ u32 x[MAX_FINGER_NUMBER], y[MAX_FINGER_NUMBER], z[MAX_FINGER_NUMBER], pr, ky, points;
+ u32 px,py,pz;
+ u8 ret;
+ u8 pressure;
+ int i,j;
+ int tx,ty;
+ int xmax,ymax;
+ int realnum = 0;
+ struct zet6221_tsdrv *ts =
+ container_of(_work, struct zet6221_tsdrv, work1);
+
+ struct i2c_client *tsclient1 = ts->i2c_ts;
+
+ if(l_suspend == 1)
+ {
+ return;
+ }
+
+ if (bufLength == 0)
+ {
+ wmt_enable_gpirq();
+ return;
+ }
+ /*if(resetCount == 1)
+ {
+ resetCount = 0;
+ wmt_enable_gpirq();
+ return;
+ }*/
+
+ //if (gpio_get_value(TS_INT_GPIO) != 0)
+ if (wmt_ts_irqinval() != 0)
+ {
+ /* do not read when IRQ is triggered by RASING*/
+ //DPRINTK("INT HIGH\n");
+ dbg("INT HIGH....\n");
+ wmt_enable_gpirq();
+ return;
+ }
+
+ ///-------------------------------------------///
+ /// Transfer Type : Mutual Dev Mode
+ ///-------------------------------------------///
+#ifdef FEATURE_MDEV_OUT_ENABLE
+ if(transfer_type == TRAN_TYPE_MUTUAL_SCAN_DEV)
+ {
+ zet622x_ts_parse_mutual_dev(tsclient1);
+ wmt_enable_gpirq();
+ return;
+ }
+#endif ///< FEATURE_MDEV_OUT_ENABLE
+
+ ///-------------------------------------------///
+ /// Transfer Type : Initial Base Mode
+ ///-------------------------------------------///
+#ifdef FEATURE_IBASE_OUT_ENABLE
+ if(transfer_type == TRAN_TYPE_INIT_SCAN_BASE)
+ {
+ zet622x_ts_parse_initial_base(tsclient1);
+ wmt_enable_gpirq();
+ return;
+ }
+#endif ///< FEATURE_IBASE_OUT_ENABLE
+
+ ///-------------------------------------------///
+ /// Transfer Type : Initial Dev Mode
+ ///-------------------------------------------///
+#ifdef FEATURE_IDEV_OUT_ENABLE
+ if(transfer_type == TRAN_TYPE_INIT_SCAN_DEV)
+ {
+ zet622x_ts_parse_initial_dev(tsclient1);
+ wmt_enable_gpirq();
+ return;
+ }
+#endif ///< TRAN_TYPE_INIT_SCAN_DEV
+
+ ///-------------------------------------------///
+ /// Transfer Type : Mutual Base Mode
+ ///-------------------------------------------///
+#ifdef FEATURE_MBASE_OUT_ENABLE
+ if(transfer_type == TRAN_TYPE_MUTUAL_SCAN_BASE)
+ {
+ zet622x_ts_parse_mutual_base(tsclient1);
+ wmt_enable_gpirq();
+ return;
+ }
+#endif ///< FEATURE_MBASE_OUT_ENABLE
+
+ mutex_lock(&i2c_mutex);
+ ret = zet6221_ts_get_xy_from_panel(tsclient1, x, y, z, &pr, &ky);
+ mutex_unlock(&i2c_mutex);
+
+ if(ret == 0x3C)
+ {
+
+ dbg( "x1= %d, y1= %d x2= %d, y2= %d [PR] = %d [KY] = %d\n", x[0], y[0], x[1], y[1], pr, ky);
+
+ points = pr;
+
+ #if defined(TRANSLATE_ENABLE)
+ touch_coordinate_traslating(x, y, points);
+ #endif
+ realnum = 0;
+
+ for(i=0;i<FingerNum;i++){
+ pressure = (points >> (MAX_FINGER_NUMBER-i-1)) & 0x1;
+ dbg( "valid=%d pressure[%d]= %d x= %d y= %d\n",points , i, pressure,x[i],y[i]);
+
+ if(pressure)
+ {
+ px = x[i];
+ py = y[i];
+ pz = z[i];
+
+ dbg("raw%d(%d,%d) xaxis:%d ResolutionX:%d ResolutionY:%d\n", i, px, py,wmt_ts_get_xaxis(),ResolutionX,ResolutionY);
+
+ //input_report_abs(ts->input, ABS_MT_TRACKING_ID, i);
+ //input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR, P_MAX);
+ //input_report_abs(ts->input, ABS_MT_POSITION_X, x[i]);
+ //input_report_abs(ts->input, ABS_MT_POSITION_Y, y[i]);
+ if (wmt_ts_get_xaxis() == 0)
+ {
+ tx = px;
+ ty = py;
+ xmax = ResolutionX;
+ ymax = ResolutionY;
+ } else {
+ tx = py;
+ ty = px;
+ xmax = ResolutionY;
+ ymax = ResolutionX;
+ }
+ if (wmt_ts_get_xdir() == -1)
+ {
+ tx = xmax - tx;
+ }
+ if (wmt_ts_get_ydir() == -1)
+ {
+ ty = ymax - ty;
+ }
+ //tx = ResolutionY - py;
+ //ty = px;
+ dbg("rpt%d(%d,%d)\n", i, tx, ty);
+ //add for cross finger 2013-1-10
+ #ifdef MT_TYPE_B
+ input_mt_slot(ts->input, i);
+ input_mt_report_slot_state(ts->input, MT_TOOL_FINGER,true);
+ #endif
+ input_report_abs(ts->input, ABS_MT_TRACKING_ID, i);
+ //input_report_key(ts->input, BTN_TOUCH, 1);
+ //input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR, pz);
+ //*******************************
+
+ if (wmt_ts_get_lcdexchg()) {
+ int tmp;
+ tmp = tx;
+ tx = ty;
+ ty = ResolutionY - tmp;
+ }
+
+ input_report_abs(ts->input, ABS_MT_POSITION_X, tx /*px*/);
+ input_report_abs(ts->input, ABS_MT_POSITION_Y, ty /*py*/);
+
+ #ifndef MT_TYPE_B
+ input_mt_sync(ts->input);
+ #endif
+ realnum++;
+ if (wmt_ts_ispenup())
+ {
+ wmt_ts_set_penup(0);
+ }
+
+ }else
+ {
+ //input_report_abs(ts->input, ABS_MT_TRACKING_ID, i);
+ //input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR, 0);
+ //input_mt_sync(ts->input);
+ #ifdef MT_TYPE_B
+ input_mt_slot(ts->input, i);
+ input_mt_report_slot_state(ts->input, MT_TOOL_FINGER,false);
+ input_report_abs(ts->input, ABS_MT_TRACKING_ID, -1);
+ #endif //add cross finger 2013-1-10
+ dbg("p%d not pen down\n",i);
+ }
+ }
+
+ #ifdef MT_TYPE_B
+ input_mt_report_pointer_emulation(ts->input, true);
+ #endif //add finger cross 2013-1-10
+ //printk("<<<realnum %d\n", realnum);
+ if (realnum != 0)
+ {
+ input_sync(ts->input);
+ dbg("report one point group\n");
+ } else if (!wmt_ts_ispenup())
+ {//********here no finger press 2013-1-10
+ //add 2013-1-10 cross finger issue!
+ #ifdef MT_TYPE_B
+ for(i=0;i<FingerNum;i++){
+ input_mt_slot(ts->input, i);
+ input_mt_report_slot_state(ts->input, MT_TOOL_FINGER,false);
+ input_report_abs(ts->input, ABS_MT_TRACKING_ID, -1);
+ }
+ input_mt_report_pointer_emulation(ts->input, true);
+ #else
+ //input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR, 0);
+ //input_mt_sync(ts->input);
+ //input_report_abs(ts->input, ABS_MT_TRACKING_ID, -1);
+ //input_report_key(ts->input, BTN_TOUCH, 0);
+ #endif
+ //**********************************
+ input_mt_sync(ts->input);
+ input_sync(ts->input);
+ dbg("real pen up!\n");
+ wmt_ts_set_penup(1);
+ }
+
+ if(KeyNum > 0)
+ {
+ //for(i=0;i<MAX_KEY_NUMBER;i++)
+ if (0 == ky)
+ {
+ for (j=0;j<4;j++)
+ {
+ if (l_tskey[j][1] != 0)
+ {
+ l_tskey[j][1] = 0;
+ }
+ }
+ dbg("finish one key report!\n");
+ } else {
+ for(i=0;i<4;i++)
+ {
+ pressure = ky & ( 0x01 << i );
+ if (pressure)
+ {
+ dbg("key%d\n", i);
+ if (0 == l_tskey[i][1])
+ {
+ l_tskey[i][1] = 1; // key down
+ input_report_key(ts->input, l_tskey[i][0], 1);
+ input_report_key(ts->input, l_tskey[i][0], 0);
+ input_sync(ts->input);
+ dbg("report key_%d\n", l_tskey[i][0]);
+ break;
+ }
+ }
+
+ }
+ }
+ }
+
+ dbg("normal end...\n");
+ }else {
+ dbg("do nothing!\n");
+ if(KeyNum > 0)
+ {
+ //if (0 == ky)
+ {
+ for (j=0;j<4;j++)
+ {
+ if (l_tskey[j][1] != 0)
+ {
+ l_tskey[j][1] = 0;
+ }
+ }
+ dbg("finish one key report!\n");
+ }
+ }
+ }
+ wmt_enable_gpirq();
+
+}
+
+/***********************************************************************
+ [function]:
+ callback: charger mode enable;
+ [parameters]:
+ void
+
+ [return]:
+ void
+************************************************************************/
+void zet6221_ts_charger_mode()
+{
+ //struct zet6221_tsdrv *zet6221_ts;
+ u8 ts_write_charge_cmd[1] = {0xb5};
+ int ret=0;
+ ret=zet6221_i2c_write_tsdata(this_client, ts_write_charge_cmd, 1);
+}
+EXPORT_SYMBOL_GPL(zet6221_ts_charger_mode);
+
+/***********************************************************************
+ [function]:
+ callback: charger mode disable;
+ [parameters]:
+ void
+
+ [return]:
+ void
+************************************************************************/
+void zet6221_ts_charger_mode_disable(void)
+{
+ //struct zet6221_tsdrv *zet6221_ts;
+ u8 ts_write_cmd[1] = {0xb6};
+ int ret=0;
+ ret=zet6221_i2c_write_tsdata(this_client, ts_write_cmd, 1);
+}
+EXPORT_SYMBOL_GPL(zet6221_ts_charger_mode_disable);
+
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void ts_early_suspend(struct early_suspend *handler)
+{
+ //Sleep Mode
+/* u8 ts_sleep_cmd[1] = {0xb1};
+ int ret=0;
+ ret=zet6221_i2c_write_tsdata(this_client, ts_sleep_cmd, 1);
+ return;
+ */
+ wmt_disable_gpirq();
+ l_suspend = 1;
+ //del_timer(&l_ts->polling_timer);
+
+}
+
+static void ts_late_resume(struct early_suspend *handler)
+{
+ resetCount = 1;
+ //if (l_suspend != 0)
+ {
+ //wmt_disable_gpirq();
+ //ctp_reset();
+ //wmt_set_gpirq(IRQ_TYPE_EDGE_FALLING);
+ wmt_enable_gpirq();
+ l_suspend = 0;
+ }
+ //l_powermode = -1;
+ //mod_timer(&l_ts->polling_timer,jiffies + msecs_to_jiffies(TIME_CHECK_CHARGE));
+
+}
+#endif
+static int zet_ts_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ wmt_disable_gpirq();
+ l_suspend = 1;
+ return 0;
+}
+
+
+/***********************************************************************
+ [function]:
+ resume_download_thread
+ [parameters]:
+ arg
+
+ [return]:
+ int;
+************************************************************************/
+int resume_download_thread(void *arg)
+{
+ char fw_name[64];
+ wake_lock(&downloadWakeLock);
+ sprintf(fw_name, "%szet62xx.bin", tran_type_mode_file_name);
+ zet_fw_load(fw_name);
+ //printk("Thread : Enter\n");
+// if((iRomType == ROM_TYPE_SRAM) ||
+// (iRomType == ROM_TYPE_OTP)) //SRAM,OTP
+ // {
+ zet622x_resume_downloader(this_client);
+ check_charger();
+ l_suspend = 0;
+ //printk("zet622x download OK\n");
+ // }
+ //printk("Thread : Leave\n");
+ wake_unlock(&downloadWakeLock);
+ return 0;
+}
+
+static int zet_ts_resume(struct platform_device *pdev)
+{
+ wmt_disable_gpirq();
+ ctp_reset();
+
+ if(ic_model == ZET6251) {
+ //upload bin to flash_buffer, just for debug
+ resume_download_task = kthread_create(resume_download_thread, NULL , "resume_download");
+ if(IS_ERR(resume_download_task)) {
+ errlog("cread thread failed\n");
+ }
+ wake_up_process(resume_download_task);
+ } else {
+ check_charger();
+ l_suspend = 0;
+ }
+
+ wmt_set_gpirq(IRQ_TYPE_EDGE_FALLING);
+ if (!earlysus_en)
+ wmt_enable_gpirq();
+
+ ///--------------------------------------///
+ /// Set transfer type to dynamic mode
+ ///--------------------------------------///
+ transfer_type = TRAN_TYPE_DYNAMIC;
+
+ return 0;
+}
+
+
+///**********************************************************************
+/// [function]: zet622x_ts_set_transfer_type
+/// [parameters]: void
+/// [return]: void
+///**********************************************************************
+int zet622x_ts_set_transfer_type(u8 bTransType)
+{
+ u8 ts_cmd[10] = {0xC1, 0x02, TRAN_TYPE_DYNAMIC, 0x55, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x00};
+ int ret = 0;
+ ts_cmd[2] = bTransType;
+ ret = zet6221_i2c_write_tsdata(this_client, ts_cmd, 10);
+ return ret;
+}
+
+
+///**********************************************************************
+/// [function]: zet622x_ts_set_transfer_type
+/// [parameters]: void
+/// [return]: void
+///**********************************************************************
+#ifdef FEATURE_INFO_OUT_EANBLE
+int zet622x_ts_set_info_type(void)
+{
+ int ret = 1;
+ char info_file_name_out[128];
+
+ /// ic type
+ switch(ic_model)
+ {
+ case ZET6221:
+ tran_data[0] = ZET6221_INFO;
+ break;
+ case ZET6223:
+ tran_data[0] = ZET6223_INFO;
+ break;
+ case ZET6231:
+ tran_data[0] = ZET6231_INFO;
+ break;
+ case ZET6251:
+ tran_data[0] = ZET6251_INFO;
+ break;
+ default:
+ tran_data[0] = UNKNOW_INFO;
+ break;
+ }
+
+ /// resolution
+ if(xyExchange== 1)
+ {
+ tran_data[16] = 0x8;
+ tran_data[9] = ((ResolutionY >> 8)&0xFF);
+ tran_data[8] = (ResolutionY &0xFF);
+ tran_data[11] = ((ResolutionX >> 8)&0xFF);
+ tran_data[10] = (ResolutionX &0xFF);
+ }
+ else
+ {
+ tran_data[16] = 0x00;
+ tran_data[9] = ((ResolutionX >> 8)&0xFF);
+ tran_data[8] = (ResolutionX &0xFF);
+ tran_data[11] = ((ResolutionY >> 8)&0xFF);
+ tran_data[10] = (ResolutionY &0xFF);
+ }
+
+ /// trace X
+ tran_data[13] = TP_DEFAULT_COL; ///< trace x
+ /// trace Y
+ tran_data[14] = TP_DEFAULT_ROW; ///< trace y
+
+ if(KeyNum > 0)
+ {
+ tran_data[15] = (0x80 | FingerNum);
+ }
+ else
+ {
+ tran_data[15] = FingerNum;
+ }
+
+ sprintf(info_file_name_out, "%sinfo.bin",tran_type_mode_file_name);
+ zet_information_save(info_file_name_out);
+
+ printk("[ZET] : ic:%d, traceX:%d, traceY:%d\n", tran_data[0],tran_data[13],tran_data[14]);
+ return ret;
+}
+#endif ///< FEATURE_INFO_OUT_EANBLE
+
+///***********************************************************************
+/// [function]: zet_mdev_save
+/// [parameters]: char *
+/// [return]: void
+///************************************************************************
+static void zet_mdev_save(char *file_name)
+{
+ struct file *fp;
+ int data_total_len = (row+2) * (col + 2);
+
+ ///-------------------------------------------------------///
+ /// create the file that stores the mutual dev data
+ ///-------------------------------------------------------///
+ fp = filp_open(file_name, O_RDWR | O_CREAT, 0644);
+ if(IS_ERR(fp))
+ {
+ printk("[ZET] : Failed to open %s\n", file_name);
+ return;
+ }
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ vfs_write(fp, tran_data, data_total_len, &(fp->f_pos));
+ memcpy(mdev_data, tran_data, data_total_len);
+ set_fs(old_fs);
+ filp_close(fp, 0);
+
+ return;
+}
+
+///***********************************************************************
+/// [function]: zet_idev_save
+/// [parameters]: char *
+/// [return]: void
+///************************************************************************
+#ifdef FEATURE_IDEV_OUT_ENABLE
+static void zet_idev_save(char *file_name)
+{
+ struct file *fp;
+ int data_total_len = (row + col);
+
+ ///-------------------------------------------------------///
+ /// create the file that stores the initial dev data
+ ///-------------------------------------------------------///
+ fp = filp_open(file_name, O_RDWR | O_CREAT, 0644);
+ if(IS_ERR(fp))
+ {
+ printk("[ZET] : Failed to open %s\n", file_name);
+ return;
+ }
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ vfs_write(fp, tran_data, data_total_len, &(fp->f_pos));
+ memcpy(idev_data, tran_data, data_total_len);
+ set_fs(old_fs);
+ filp_close(fp, 0);
+
+ return;
+}
+#endif ///< FEATURE_IDEV_OUT_ENABLE
+
+///***********************************************************************
+/// [function]: zet_ibase_save
+/// [parameters]: char *
+/// [return]: void
+///************************************************************************
+#ifdef FEATURE_IBASE_OUT_ENABLE
+static void zet_ibase_save(char *file_name)
+{
+ struct file *fp;
+ int data_total_len = (row + col) * 2;
+
+ ///-------------------------------------------------------///
+ /// create the file that stores the initial base data
+ ///-------------------------------------------------------///
+ fp = filp_open(file_name, O_RDWR | O_CREAT, 0644);
+ if(IS_ERR(fp))
+ {
+ printk("[ZET] : Failed to open %s\n", file_name);
+ return;
+ }
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ vfs_write(fp, tran_data, data_total_len, &(fp->f_pos));
+ memcpy(ibase_data, tran_data, data_total_len);
+ set_fs(old_fs);
+ filp_close(fp, 0);
+
+ return;
+}
+#endif ///< FEATURE_IBASE_OUT_ENABLE
+
+///***********************************************************************
+/// [function]: zet_mbase_save
+/// [parameters]: char *
+/// [return]: void
+///************************************************************************
+#ifdef FEATURE_MBASE_OUT_ENABLE
+static void zet_mbase_save(char *file_name)
+{
+ struct file *fp;
+ int data_total_len = (row * col * 2);
+
+ ///-------------------------------------------------------///
+ /// create the file that stores the mutual base data
+ ///-------------------------------------------------------///
+ fp = filp_open(file_name, O_RDWR | O_CREAT, 0644);
+ if(IS_ERR(fp))
+ {
+ printk("[ZET] : Failed to open %s\n", file_name);
+ return;
+ }
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ vfs_write(fp, tran_data, data_total_len, &(fp->f_pos));
+ memcpy(mbase_data, tran_data, data_total_len);
+ set_fs(old_fs);
+ filp_close(fp, 0);
+
+ return;
+}
+#endif ///< FEATURE_MBASE_OUT_ENABLE
+
+///***********************************************************************
+/// [function]: zet_information_save
+/// [parameters]: char *
+/// [return]: void
+///************************************************************************
+#ifdef FEATURE_INFO_OUT_EANBLE
+static void zet_information_save(char *file_name)
+{
+ struct file *fp;
+ int data_total_len = INFO_DATA_SIZE;
+
+ ///-------------------------------------------------------///
+ /// create the file that stores the mutual base data
+ ///-------------------------------------------------------///
+ fp = filp_open(file_name, O_RDWR | O_CREAT, 0644);
+ if(IS_ERR(fp))
+ {
+ printk("[ZET] : Failed to open %s\n", file_name);
+ return;
+ }
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ vfs_write(fp, tran_data, data_total_len, &(fp->f_pos));
+ memcpy(info_data, tran_data, data_total_len);
+ set_fs(old_fs);
+ filp_close(fp, 0);
+
+ return;
+}
+#endif ///< FEATURE_INFO_OUT_EANBLE
+
+///************************************************************************
+/// [function]: zet_dv_set_file_name
+/// [parameters]: void
+/// [return]: void
+///************************************************************************
+static void zet_dv_set_file_name(char *file_name)
+{
+ strcpy(driver_version, file_name);
+}
+
+///************************************************************************
+/// [function]: zet_fw_set_file_name
+/// [parameters]: void
+/// [return]: void
+///************************************************************************
+static void zet_fw_set_file_name(void)//char *file_name)
+{
+ char fwname[256] = {0};
+ wmt_ts_get_firmwname(fwname);
+ sprintf(fw_file_name,"/system/etc/firmware/%s",fwname);
+ //strcpy(fw_file_name, file_name);
+}
+
+///************************************************************************
+/// [function]: zet_mdev_set_file_name
+/// [parameters]: void
+/// [return]: void
+///************************************************************************
+static void zet_tran_type_set_file_name(char *file_name)
+{
+ strcpy(tran_type_mode_file_name, file_name);
+}
+
+
+///***********************************************************************
+/// [function]: zet_fw_size
+/// [parameters]: void
+/// [return]: void
+///************************************************************************
+static int zet_fw_size(void)
+{
+ int flash_total_len = 0x8000;
+
+ switch(ic_model)
+ {
+ case ZET6221:
+ flash_total_len = 0x4000;
+ break;
+ case ZET6223:
+ flash_total_len = 0x10000;
+ break;
+ case ZET6231:
+ case ZET6251:
+ default:
+ flash_total_len = 0x8000;
+ break;
+ }
+
+ return flash_total_len;
+}
+
+
+///***********************************************************************
+/// [function]: zet_fw_save
+/// [parameters]: file name
+/// [return]: void
+///************************************************************************
+static void zet_fw_save(char *file_name)
+{
+ struct file *fp;
+ int flash_total_len = 0;
+
+ fp = filp_open(file_name, O_RDWR | O_CREAT, 0644);
+ if(IS_ERR(fp))
+ {
+ printk("[ZET] : Failed to open %s\n", file_name);
+ return;
+ }
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ flash_total_len = zet_fw_size();
+ printk("[ZET] : flash_total_len = 0x%04x\n",flash_total_len );
+
+ vfs_write(fp, flash_buffer, flash_total_len, &(fp->f_pos));
+
+ set_fs(old_fs);
+
+ filp_close(fp, 0);
+
+
+ return;
+}
+
+///***********************************************************************
+/// [function]: zet_fw_load
+/// [parameters]: file name
+/// [return]: void
+///************************************************************************
+static void zet_fw_load(char *file_name)
+{
+ int file_length = 0;
+ struct file *fp;
+ loff_t *pos;
+
+ //printk("[ZET]: find %s\n", file_name);
+ fp = filp_open(file_name, O_RDONLY, 0644);
+ if(IS_ERR(fp))
+ {
+ //printk("[ZET]: No firmware file detected\n");
+ return;
+ }
+
+ ///----------------------------///
+ /// Load from file
+ ///----------------------------///
+ printk("[ZET]: Load from %s\n", file_name);
+
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ /// Get file size
+ inode = fp->f_dentry->d_inode;
+ file_length = (int)inode->i_size;
+ //l_fwlen = file_length;
+
+ pos = &(fp->f_pos);
+
+ vfs_read(fp, &flash_buffer[0], file_length, pos);
+
+ //file_length
+ set_fs(old_fs);
+ filp_close(fp, 0);
+
+
+}
+
+///************************************************************************
+/// [function]: zet_fw_init
+/// [parameters]: void
+/// [return]: void
+///************************************************************************
+static void zet_fw_init(void)
+{
+ //int i;
+
+ if(flash_buffer == NULL)
+ {
+ flash_buffer = kmalloc(MAX_FLASH_BUF_SIZE, GFP_KERNEL);
+ }
+
+ ///---------------------------------------------///
+ /// Init the mutual dev buffer
+ ///---------------------------------------------///
+ if(mdev_data== NULL)
+ {
+ mdev_data = kmalloc(MDEV_MAX_DATA_SIZE, GFP_KERNEL);
+ }
+ if(idev_data== NULL)
+ {
+ idev_data = kmalloc(IDEV_MAX_DATA_SIZE, GFP_KERNEL);
+ }
+
+ if(mbase_data== NULL)
+ {
+ mbase_data = kmalloc(MBASE_MAX_DATA_SIZE, GFP_KERNEL);
+ }
+ if(ibase_data== NULL)
+ {
+ ibase_data = kmalloc(IBASE_MAX_DATA_SIZE, GFP_KERNEL);
+ }
+
+ if(tran_data == NULL)
+ {
+ tran_data = kmalloc(MBASE_MAX_DATA_SIZE, GFP_KERNEL);
+ }
+
+ if(info_data == NULL)
+ {
+ info_data = kmalloc(INFO_MAX_DATA_SIZE, GFP_KERNEL);
+ }
+
+ /*printk("[ZET]: Load from header\n");
+
+ if(ic_model == ZET6221)
+ {
+ for(i = 0 ; i < sizeof(zeitec_zet6221_firmware) ; i++)
+ {
+ flash_buffer[i] = zeitec_zet6221_firmware[i];
+ }
+ }
+ else if(ic_model == ZET6223)
+ {
+ for(i = 0 ; i < sizeof(zeitec_zet6223_firmware) ; i++)
+ {
+ flash_buffer[i] = zeitec_zet6223_firmware[i];
+ }
+ }
+ else if(ic_model == ZET6231)
+ {
+ for(i = 0 ; i < sizeof(zeitec_zet6231_firmware) ; i++)
+ {
+ flash_buffer[i] = zeitec_zet6231_firmware[i];
+ }
+ }
+ else if(ic_model == ZET6251)
+ {
+ for(i = 0 ; i < sizeof(zeitec_zet6251_firmware) ; i++)
+ {
+ flash_buffer[i] = zeitec_zet6251_firmware[i];
+ }
+ }
+
+ /// Load firmware from bin file
+ zet_fw_load(fw_file_name);*/
+}
+
+///************************************************************************
+/// [function]: zet_fw_exit
+/// [parameters]: void
+/// [return]: void
+///************************************************************************
+static void zet_fw_exit(void)
+{
+ ///---------------------------------------------///
+ /// free mdev_data
+ ///---------------------------------------------///
+ if(mdev_data!=NULL)
+ {
+ kfree(mdev_data);
+ mdev_data = NULL;
+ }
+
+ if(idev_data!=NULL)
+ {
+ kfree(idev_data);
+ idev_data = NULL;
+ }
+
+ if(mbase_data!=NULL)
+ {
+ kfree(mbase_data);
+ mbase_data = NULL;
+ }
+
+ if(ibase_data!=NULL)
+ {
+ kfree(ibase_data);
+ ibase_data = NULL;
+ }
+
+ if(tran_data != NULL)
+ {
+ kfree(tran_data);
+ tran_data = NULL;
+ }
+
+ if(info_data != NULL)
+ {
+ kfree(info_data);
+ info_data = NULL;
+ }
+
+
+ ///---------------------------------------------///
+ /// free flash buffer
+ ///---------------------------------------------///
+ if(flash_buffer!=NULL)
+ {
+ kfree(flash_buffer);
+ flash_buffer = NULL;
+}
+
+}
+
+///************************************************************************
+/// [function]: zet_fops_open
+/// [parameters]: file
+/// [return]: int
+///************************************************************************
+static int zet_fops_open(struct inode *inode, struct file *file)
+{
+ int subminor;
+ int ret = 0;
+ struct i2c_client *client;
+ struct i2c_adapter *adapter;
+ struct i2c_dev *i2c_dev;
+
+ subminor = iminor(inode);
+ printk("[ZET] : ZET_FOPS_OPEN , subminor=%d\n",subminor);
+
+ i2c_dev = zet622x_i2c_dev_get_by_minor(subminor);
+ if (!i2c_dev)
+ {
+ printk("error i2c_dev\n");
+ return -ENODEV;
+ }
+
+ adapter = i2c_get_adapter(i2c_dev->adap->nr);
+ if(!adapter)
+ {
+ return -ENODEV;
+ }
+
+ client = kzalloc(sizeof(*client), GFP_KERNEL);
+
+ if(!client)
+ {
+ i2c_put_adapter(adapter);
+ ret = -ENOMEM;
+ }
+ snprintf(client->name, I2C_NAME_SIZE, "pctp_i2c_ts%d", adapter->nr);
+ //client->driver = &zet622x_i2c_driver;
+ client->driver = this_client->driver;
+ client->adapter = adapter;
+ file->private_data = client;
+
+ return 0;
+}
+
+
+///************************************************************************
+/// [function]: zet_fops_release
+/// [parameters]: inode, file
+/// [return]: int
+///************************************************************************
+static int zet_fops_release (struct inode *inode, struct file *file)
+{
+ struct i2c_client *client = file->private_data;
+
+ printk("[ZET] : zet_fops_release -> line : %d\n",__LINE__ );
+
+ i2c_put_adapter(client->adapter);
+ kfree(client);
+ file->private_data = NULL;
+ return 0;
+}
+
+///************************************************************************
+/// [function]: zet_fops_read
+/// [parameters]: file, buf, count, ppos
+/// [return]: size_t
+///************************************************************************
+static ssize_t zet_fops_read(struct file *file, char __user *buf, size_t count,
+ loff_t *ppos)
+{
+ int i;
+ int iCnt = 0;
+ char str[256];
+ int len = 0;
+
+ printk("[ZET] : zet_fops_read -> line : %d\n",__LINE__ );
+
+ ///-------------------------------///
+ /// Print message
+ ///-------------------------------///
+ sprintf(str, "Please check \"%s\"\n", fw_file_name);
+ len = strlen(str);
+
+ ///-------------------------------///
+ /// if read out
+ ///-------------------------------///
+ if(data_offset >= len)
+ {
+ return 0;
+ }
+
+ for(i = 0 ; i < count-1 ; i++)
+ {
+ buf[i] = str[data_offset];
+ buf[i+1] = 0;
+ iCnt++;
+ data_offset++;
+ if(data_offset >= len)
+ {
+ break;
+ }
+ }
+
+ ///-------------------------------///
+ /// Save file
+ ///-------------------------------///
+ if(data_offset == len)
+ {
+ zet_fw_save(fw_file_name);
+ }
+ return iCnt;
+}
+
+///************************************************************************
+/// [function]: zet_fops_write
+/// [parameters]: file, buf, count, ppos
+/// [return]: size_t
+///************************************************************************
+static ssize_t zet_fops_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ printk("[ZET]: zet_fops_write -> %s\n", buf);
+ data_offset = 0;
+ return count;
+}
+
+///************************************************************************
+/// [function]: ioctl
+/// [parameters]: file , cmd , arg
+/// [return]: long
+///************************************************************************
+static long zet_fops_ioctl(struct file *file, unsigned int cmd, unsigned long arg )
+{
+ u8 __user * user_buf = (u8 __user *) arg;
+
+ u8 buf[IOCTL_MAX_BUF_SIZE];
+ int data_size;
+
+ if(copy_from_user(buf, user_buf, IOCTL_MAX_BUF_SIZE))
+ {
+ printk("[ZET]: zet_ioctl: copy_from_user fail\n");
+ return 0;
+ }
+
+ printk("[ZET]: zet_ioctl -> cmd = %d, %02x, %02x\n", cmd, buf[0], buf[1]);
+
+ if(cmd == ZET_IOCTL_CMD_FLASH_READ)
+ {
+ printk("[ZET]: zet_ioctl -> ZET_IOCTL_CMD_FLASH_DUMP cmd = %d, file=%s\n", cmd, (char *)buf);
+ ioctl_action |= IOCTL_ACTION_FLASH_DUMP;
+ }
+ else if(cmd == ZET_IOCTL_CMD_FLASH_WRITE)
+ {
+ printk("[ZET]: zet_ioctl -> ZET_IOCTL_CMD_FLASH_WRITE cmd = %d\n", cmd);
+ { //upload bin to flash_buffer
+ char fw_name[64];
+ sprintf(fw_name, "%szet62xx.bin", tran_type_mode_file_name);
+ zet_fw_load(fw_name);
+ }
+ zet622x_resume_downloader(this_client);
+ }
+ else if(cmd == ZET_IOCTL_CMD_RST)
+ {
+ printk("[ZET]: zet_ioctl -> ZET_IOCTL_CMD_RST cmd = %d\n", cmd);
+ //ctp_reset();
+ wmt_rst_output(1);
+
+ wmt_rst_output(0);
+ msleep(20);
+ wmt_rst_output(1);
+
+ transfer_type = TRAN_TYPE_DYNAMIC;
+ }
+ else if(cmd == ZET_IOCTL_CMD_RST_HIGH)
+ {
+ wmt_rst_output(1);
+ }
+ else if(cmd == ZET_IOCTL_CMD_RST_LOW)
+ {
+ wmt_rst_output(0);
+ }
+ else if(cmd == ZET_IOCTL_CMD_MDEV)
+ {
+ ///---------------------------------------------------///
+ /// set mutual dev mode
+ ///---------------------------------------------------///
+ zet622x_ts_set_transfer_type(TRAN_TYPE_MUTUAL_SCAN_DEV);
+ transfer_type = TRAN_TYPE_MUTUAL_SCAN_DEV;
+
+ }
+ else if(cmd == ZET_IOCTL_CMD_IBASE)
+ {
+ ///---------------------------------------------------///
+ /// set initial base mode
+ ///---------------------------------------------------///
+ zet622x_ts_set_transfer_type(TRAN_TYPE_INIT_SCAN_BASE);
+ transfer_type = TRAN_TYPE_INIT_SCAN_BASE;
+
+ }
+#ifdef FEATURE_IDEV_OUT_ENABLE
+ else if(cmd == ZET_IOCTL_CMD_IDEV)
+ {
+ ///---------------------------------------------------///
+ /// set initial dev mode
+ ///---------------------------------------------------///
+ zet622x_ts_set_transfer_type(TRAN_TYPE_INIT_SCAN_DEV);
+ transfer_type = TRAN_TYPE_INIT_SCAN_DEV;
+
+ }
+#endif ///< FEATURE_IDEV_OUT_ENABLE
+#ifdef FEATURE_MBASE_OUT_ENABLE
+ else if(cmd == ZET_IOCTL_CMD_MBASE)
+ {
+ ///---------------------------------------------------///
+ /// set Mutual Base mode
+ ///---------------------------------------------------///
+ zet622x_ts_set_transfer_type(TRAN_TYPE_MUTUAL_SCAN_BASE);
+ transfer_type = TRAN_TYPE_MUTUAL_SCAN_BASE;
+
+ }
+#endif ///< FEATURE_MBASE_OUT_ENABLE
+ else if(cmd == ZET_IOCTL_CMD_DYNAMIC)
+ {
+ zet622x_ts_set_transfer_type(TRAN_TYPE_DYNAMIC);
+ transfer_type = TRAN_TYPE_DYNAMIC;
+ }
+ else if(cmd == ZET_IOCTL_CMD_FW_FILE_PATH_GET)
+ {
+ memset(buf, 0x00, 64);
+ strcpy(buf, fw_file_name);
+ printk("[ZET]: zet_ioctl: Get FW_FILE_NAME = %s\n", buf);
+ }
+ else if(cmd == ZET_IOCTL_CMD_FW_FILE_PATH_SET)
+ {
+ strcpy(fw_file_name, buf);
+ printk("[ZET]: zet_ioctl: set FW_FILE_NAME = %s\n", buf);
+
+ }
+ else if(cmd == ZET_IOCTL_CMD_MDEV_GET)
+ {
+ data_size = (row+2)*(col+2);
+ memcpy(buf, mdev_data, data_size);
+ printk("[ZET]: zet_ioctl: Get MDEV data size=%d\n", data_size);
+ }
+ else if(cmd == ZET_IOCTL_CMD_TRAN_TYPE_PATH_SET)
+ {
+ strcpy(tran_type_mode_file_name, buf);
+ printk("[ZET]: zet_ioctl: Set ZET_IOCTL_CMD_TRAN_TYPE_PATH_ = %s\n", buf);
+ }
+ else if(cmd == ZET_IOCTL_CMD_TRAN_TYPE_PATH_GET)
+ {
+ memset(buf, 0x00, 64);
+ strcpy(buf, tran_type_mode_file_name);
+ printk("[ZET]: zet_ioctl: Get ZET_IOCTL_CMD_TRAN_TYPE_PATH = %s\n", buf);
+ }
+ else if(cmd == ZET_IOCTL_CMD_IDEV_GET)
+ {
+ data_size = (row + col);
+ memcpy(buf, idev_data, data_size);
+ printk("[ZET]: zet_ioctl: Get IDEV data size=%d\n", data_size);
+ }
+ else if(cmd == ZET_IOCTL_CMD_IBASE_GET)
+ {
+ data_size = (row + col)*2;
+ memcpy(buf, ibase_data, data_size);
+ printk("[ZET]: zet_ioctl: Get IBASE data size=%d\n", data_size);
+ }
+ else if(cmd == ZET_IOCTL_CMD_MBASE_GET)
+ {
+ data_size = (row*col*2);
+ if(data_size > IOCTL_MAX_BUF_SIZE)
+ {
+ data_size = IOCTL_MAX_BUF_SIZE;
+ }
+ memcpy(buf, mbase_data, data_size);
+ printk("[ZET]: zet_ioctl: Get MBASE data size=%d\n", data_size);
+ }
+ else if(cmd == ZET_IOCTL_CMD_INFO_SET)
+ {
+ printk("[ZET]: zet_ioctl: ZET_IOCTL_CMD_INFO_SET\n");
+ zet622x_ts_set_info_type();
+ }
+ else if(cmd == ZET_IOCTL_CMD_INFO_GET)
+ {
+ data_size = INFO_DATA_SIZE;
+ memcpy(buf, info_data, data_size);
+ printk("[ZET]: zet_ioctl: Get INFO data size=%d,IC: %x,X:%d,Y:%d\n", data_size, info_data[0], info_data[13], info_data[14]);
+ }
+ else if(cmd == ZET_IOCTL_CMD_TRACE_X_SET)
+ {
+ printk("[ZET]: zet_ioctl: ZET_IOCTL_CMD_TRACE_X_SET\n");
+ }
+ else if(cmd == ZET_IOCTL_CMD_TRACE_X_GET)
+ {
+ printk("[ZET]: zet_ioctl: Get TRACEX data\n");
+ }
+ else if(cmd == ZET_IOCTL_CMD_TRACE_Y_SET)
+ {
+ printk("[ZET]: zet_ioctl: ZET_IOCTL_CMD_TRACE_Y_SET\n");
+ }
+ else if(cmd == ZET_IOCTL_CMD_TRACE_Y_GET)
+ {
+ printk("[ZET]: zet_ioctl: Get TRACEY data \n");
+ }
+ else if(cmd == ZET_IOCTL_CMD_DRIVER_VER_GET)
+ {
+ memset(buf, 0x00, 64);
+ strcpy(buf, driver_version);
+ printk("[ZET]: zet_ioctl: Get DRIVER_VERSION = %s\n", buf);
+ printk("[ZET]: zet_ioctl: Get SVN = %s\n", DRIVER_VERSION);
+ }
+ else if(cmd == ZET_IOCTL_CMD_MBASE_EXTERN_GET)
+ {
+ data_size = (row*col*2) - IOCTL_MAX_BUF_SIZE;
+ if(data_size < 1)
+ {
+ data_size = 1;
+ }
+ memcpy(buf, (mbase_data+IOCTL_MAX_BUF_SIZE), data_size);
+ printk("[ZET]: zet_ioctl: Get MBASE extern data size=%d\n", data_size);
+ }
+
+ if(copy_to_user(user_buf, buf, IOCTL_MAX_BUF_SIZE))
+ {
+ printk("[ZET]: zet_ioctl: copy_to_user fail\n");
+ return 0;
+ }
+
+ return 0;
+}
+
+///************************************************************************
+/// file_operations
+///************************************************************************
+static const struct file_operations zet622x_ts_fops =
+{
+ .owner = THIS_MODULE,
+ .open = zet_fops_open,
+ .read = zet_fops_read,
+ .write = zet_fops_write,
+ .unlocked_ioctl = zet_fops_ioctl,
+ .compat_ioctl = zet_fops_ioctl,
+ .release = zet_fops_release,
+};
+
+static int zet6221_ts_probe(struct i2c_client *client/*, const struct i2c_device_id *id*/)
+{
+ int result = -1;
+ int count = 0;
+ int download_count = 0;
+ int download_ok = 0;
+ struct input_dev *input_dev;
+ struct device *dev;
+
+
+ struct zet6221_tsdrv *zet6221_ts;
+
+ dbg( "[TS] zet6221_ts_probe \n");
+
+ zet6221_ts = kzalloc(sizeof(struct zet6221_tsdrv), GFP_KERNEL);
+ l_ts = zet6221_ts;
+ zet6221_ts->i2c_ts = client;
+ //zet6221_ts->gpio = TS_INT_GPIO; /*s3c6410*/
+ //zet6221_ts->gpio = TS1_INT_GPIO;
+
+ this_client = client;
+
+ i2c_set_clientdata(client, zet6221_ts);
+
+ //client->driver = &zet6221_ts_driver;
+ ts_wq = create_singlethread_workqueue("zet6221ts_wq");
+ if (!ts_wq)
+ {
+ errlog("Failed to create workqueue!\n");
+ goto err_create_wq;
+ }
+
+ INIT_WORK(&zet6221_ts->work1, zet6221_ts_work);
+
+ input_dev = input_allocate_device();
+ if (!input_dev || !zet6221_ts) {
+ result = -ENOMEM;
+ goto fail_alloc_mem;
+ }
+
+ //i2c_set_clientdata(client, zet6221_ts);
+
+ input_dev->name = MJ5_TS_NAME;
+ input_dev->phys = "zet6221_touch/input0";
+ input_dev->id.bustype = BUS_HOST;
+ input_dev->id.vendor = 0x0001;
+ input_dev->id.product = 0x0002;
+ input_dev->id.version = 0x0100;
+//bootloader
+ zet622x_ts_option(client);
+ msleep(100);
+
+ download_count = 0;
+ download_ok = 0;
+ zet_fw_init();
+ do{
+ if (zet6221_load_fw())
+ {
+ errlog("Can't load the firmware of zet62xx!\n");
+ } else {
+ zet6221_downloader(client);
+ //ctp_reset(); //cancel it? need to check
+ }
+ udelay(100);
+
+ count=0;
+ do{
+ ctp_reset();
+
+ if(zet6221_ts_get_report_mode_t(client)==0) //get IC info by delay
+ {
+ ResolutionX = X_MAX;
+ ResolutionY = Y_MAX;
+ FingerNum = FINGER_NUMBER;
+ KeyNum = KEY_NUMBER;
+ if(KeyNum==0)
+ bufLength = 3+4*FingerNum;
+ else
+ bufLength = 3+4*FingerNum+1;
+ errlog("[warning] zet6221_ts_get_report_mode_t report error!!use default value\n");
+ }else
+ {
+ if(zet6221_ts_version()==1) // zet6221_ts_version() depends on zet6221_downloader()
+ // cancel download firmware, need to comment it.
+ {
+ dbg("get report mode ok!\n");
+ download_ok = 1;
+ }
+ }
+ count++;
+ }while(count<REPORT_POLLING_TIME && download_ok != 1 );
+ download_count++;
+ }while( download_count < RETRY_DOWNLOAD_TIMES && download_ok != 1 );
+
+ errlog( "ResolutionX=%d ResolutionY=%d FingerNum=%d KeyNum=%d\n",ResolutionX,ResolutionY,FingerNum,KeyNum);
+
+ input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+ if (wmt_ts_get_lcdexchg()) {
+ input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, ResolutionX, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, ResolutionY, 0, 0);
+ } else {
+ input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, ResolutionY, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, ResolutionX, 0, 0);
+ }
+
+ set_bit(KEY_BACK, input_dev->keybit);
+ set_bit(KEY_HOME, input_dev->keybit);
+ set_bit(KEY_MENU, input_dev->keybit);
+
+ //*******************************add 2013-1-10
+ set_bit(ABS_MT_TRACKING_ID, input_dev->absbit);
+ //set_bit(ABS_MT_TOUCH_MAJOR, input_dev->absbit);
+ input_set_abs_params(input_dev,ABS_MT_TRACKING_ID, 0, FingerNum, 0, 0);
+ //input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, P_MAX, 0, 0);
+ //set_bit(BTN_TOUCH, input_dev->keybit);
+
+ #ifdef MT_TYPE_B
+ input_mt_init_slots(input_dev, FingerNum);
+ #endif
+ //set_bit(KEY_SEARCH, input_dev->keybit);
+
+ //input_dev->evbit[0] = BIT(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ //input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+
+ result = input_register_device(input_dev);
+ if (result)
+ goto fail_ip_reg;
+
+ zet6221_ts->input = input_dev;
+
+ input_set_drvdata(zet6221_ts->input, zet6221_ts);
+ mutex_init(&i2c_mutex);
+ wake_lock_init(&downloadWakeLock, WAKE_LOCK_SUSPEND, "resume_download");
+ zet6221_ts->queue = create_singlethread_workqueue("ts_check_charge_queue");
+ INIT_DELAYED_WORK(&zet6221_ts->work, polling_timer_func);
+
+ //setup_timer(&zet6221_ts->polling_timer, polling_timer_func, (unsigned long)zet6221_ts);
+ //mod_timer(&zet6221_ts->polling_timer,jiffies + msecs_to_jiffies(TIME_CHECK_CHARGE));
+
+
+ //s3c6410
+ //result = gpio_request(zet6221_ts->gpio, "GPN");
+ wmt_set_gpirq(IRQ_TYPE_EDGE_FALLING);
+ wmt_disable_gpirq();
+ /*result = gpio_request(zet6221_ts->gpio, "GPN");
+ if (result)
+ goto gpio_request_fail;
+ */
+
+ zet6221_ts->irq = wmt_get_tsirqnum();//gpio_to_irq(zet6221_ts->gpio);
+ dbg( "[TS] zet6221_ts_probe.gpid_to_irq [zet6221_ts->irq=%d]\n",zet6221_ts->irq);
+
+ result = request_irq(zet6221_ts->irq, zet6221_ts_interrupt,IRQF_SHARED /*IRQF_TRIGGER_FALLING*/,
+ ZET_TS_ID_NAME, zet6221_ts);
+ if (result)
+ {
+ errlog("Can't alloc ts irq=%d\n", zet6221_ts->irq);
+ goto request_irq_fail;
+ }
+
+
+ ///-----------------------------------------------///
+ /// Set the default firmware bin file name & mutual dev file name
+ ///-----------------------------------------------///
+ zet_dv_set_file_name(DRIVER_VERSION);
+ zet_fw_set_file_name();//FW_FILE_NAME);
+ zet_tran_type_set_file_name(TRAN_MODE_FILE_PATH);
+
+ ///---------------------------------///
+ /// Set file operations
+ ///---------------------------------///
+ result = register_chrdev(I2C_MAJOR, "zet_i2c_ts", &zet622x_ts_fops);
+ if(result)
+ {
+ printk(KERN_ERR "%s:register chrdev failed\n",__FILE__);
+ goto fail_register_chrdev;
+ }
+ ///---------------------------------///
+ /// Create device class
+ ///---------------------------------///
+ i2c_dev_class = class_create(THIS_MODULE,"zet_i2c_dev");
+ if(IS_ERR(i2c_dev_class))
+ {
+ result = PTR_ERR(i2c_dev_class);
+ goto fail_create_class;
+ }
+ ///--------------------------------------------///
+ /// Get a free i2c dev
+ ///--------------------------------------------///
+ zet_i2c_dev = zet622x_i2c_get_free_dev(client->adapter);
+ if(IS_ERR(zet_i2c_dev))
+ {
+ result = PTR_ERR(zet_i2c_dev);
+ goto fail_get_free_dev;
+ }
+ dev = device_create(i2c_dev_class, &client->adapter->dev,
+ MKDEV(I2C_MAJOR,client->adapter->nr), NULL, "zet62xx_ts%d", client->adapter->nr);
+ if(IS_ERR(dev))
+ {
+ result = PTR_ERR(dev);
+ goto fail_create_device;
+ }
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ zet6221_ts->early_suspend.suspend = ts_early_suspend,
+ zet6221_ts->early_suspend.resume = ts_late_resume,
+ zet6221_ts->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB + 1;//,EARLY_SUSPEND_LEVEL_DISABLE_FB + 2;
+ register_early_suspend(&zet6221_ts->early_suspend);
+#endif
+ //disable_irq(zet6221_ts->irq);
+ ctp_reset();
+ wmt_enable_gpirq();
+ queue_delayed_work(zet6221_ts->queue, &zet6221_ts->work, msecs_to_jiffies(TIME_CHECK_CHARGE));
+ //mod_timer(&zet6221_ts->polling_timer,jiffies + msecs_to_jiffies(TIME_CHECK_CHARGE));
+ dbg("ok\n");
+ return 0;
+
+fail_create_device:
+ kfree(zet_i2c_dev);
+fail_get_free_dev:
+ class_destroy(i2c_dev_class);
+fail_create_class:
+ unregister_chrdev(I2C_MAJOR, "zet_i2c_ts");
+fail_register_chrdev:
+ free_irq(zet6221_ts->irq, zet6221_ts);
+request_irq_fail:
+ destroy_workqueue(zet6221_ts->queue);
+ cancel_delayed_work_sync(&zet6221_ts->work);
+ //gpio_free(zet6221_ts->gpio);
+//gpio_request_fail:
+ free_irq(zet6221_ts->irq, zet6221_ts);
+ wake_lock_destroy(&downloadWakeLock);
+ input_unregister_device(input_dev);
+ input_dev = NULL;
+fail_ip_reg:
+fail_alloc_mem:
+ input_free_device(input_dev);
+ destroy_workqueue(ts_wq);
+ cancel_work_sync(&zet6221_ts->work1);
+ zet_fw_exit();
+err_create_wq:
+ kfree(zet6221_ts);
+ return result;
+}
+
+static int zet6221_ts_remove(void /*struct i2c_client *dev*/)
+{
+ struct zet6221_tsdrv *zet6221_ts = l_ts;//i2c_get_clientdata(dev);
+
+ //del_timer(&zet6221_ts->polling_timer);
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&zet6221_ts->early_suspend);
+#endif
+ wmt_disable_gpirq();
+ device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR,this_client->adapter->nr));
+ kfree(zet_i2c_dev);
+ class_destroy(i2c_dev_class);
+ unregister_chrdev(I2C_MAJOR, "zet_i2c_ts");
+ free_irq(zet6221_ts->irq, zet6221_ts);
+ //gpio_free(zet6221_ts->gpio);
+ //del_timer_sync(&zet6221_ts->polling_timer);
+ destroy_workqueue(zet6221_ts->queue);
+ cancel_delayed_work_sync(&zet6221_ts->work);
+ input_unregister_device(zet6221_ts->input);
+ wake_lock_destroy(&downloadWakeLock);
+ cancel_work_sync(&zet6221_ts->work1);
+ destroy_workqueue(ts_wq);
+ zet_fw_exit();
+ kfree(zet6221_ts);
+
+ return 0;
+}
+
+static int wmt_wakeup_bl_notify(struct notifier_block *nb, unsigned long event,
+ void *dummy)
+{
+ //printk("get notify\n");
+ switch (event) {
+ case BL_CLOSE:
+ l_suspend = 1;
+ //printk("\nclose backlight\n\n");
+ //printk("disable irq\n\n");
+ wmt_disable_gpirq();
+ break;
+ case BL_OPEN:
+ l_suspend = 0;
+ //printk("\nopen backlight\n\n");
+ //printk("enable irq\n\n");
+ wmt_enable_gpirq();
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block wmt_bl_notify = {
+ .notifier_call = wmt_wakeup_bl_notify,
+};
+
+static int zet6221_ts_init(void)
+{
+ //u8 ts_data[70];
+ //int ret;
+
+ /*ctp_reset();
+ memset(ts_data,0,70);
+ ret=zet6221_i2c_read_tsdata(ts_get_i2c_client(), ts_data, 8);
+ if (ret <= 0)
+ {
+ dbg("Can't find zet6221!\n");
+ return -1;
+ }
+ if (!zet6221_is_ts(ts_get_i2c_client()))
+ {
+ dbg("isn't zet6221!\n");
+ return -1;
+ }*/
+ if (zet6221_ts_probe(ts_get_i2c_client()))
+ {
+ return -1;
+ }
+ if (earlysus_en)
+ register_bl_notifier(&wmt_bl_notify);
+ //i2c_add_driver(&zet6221_ts_driver);
+ return 0;
+}
+//module_init(zet6221_ts_init);
+
+static void zet6221_ts_exit(void)
+{
+ zet6221_ts_remove();
+ if (earlysus_en)
+ unregister_bl_notifier(&wmt_bl_notify);
+ //i2c_del_driver(&zet6221_ts_driver);
+}
+//module_exit(zet6221_ts_exit);
+
+void zet6221_set_ts_mode(u8 mode)
+{
+ dbg( "[Touch Screen]ts mode = %d \n", mode);
+}
+//EXPORT_SYMBOL_GPL(zet6221_set_ts_mode);
+
+struct wmtts_device zet6221_tsdev = {
+ .driver_name = WMT_TS_I2C_NAME,
+ .ts_id = "ZET62",
+ .init = zet6221_ts_init,
+ .exit = zet6221_ts_exit,
+ .suspend = zet_ts_suspend,
+ .resume = zet_ts_resume,
+};
+
+
+MODULE_DESCRIPTION("ZET6221 I2C Touch Screen driver");
+MODULE_LICENSE("GPL v2");
diff --git a/ANDROID_3.4.5/drivers/input/touchscreen/zet6221_ts/zet6221_ts.h b/ANDROID_3.4.5/drivers/input/touchscreen/zet6221_ts/zet6221_ts.h
new file mode 100755
index 00000000..671bb29d
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/touchscreen/zet6221_ts/zet6221_ts.h
@@ -0,0 +1,6 @@
+#ifndef ZET6221_TSH_201010191758
+#define ZET6221_TSH_201010191758
+
+extern void zet6221_set_tskey(int index,int key);
+
+#endif