From 7869732ee366bedd19df6590e1bf883a3699ca23 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Sat, 3 Nov 2018 16:20:23 +0800 Subject: [PATCH] drivers/input/touchscreen: remove unused xpt2046 driver Change-Id: Id8140d167c7aebd7d1bb6de451a275897a49a3f7 Signed-off-by: Tao Huang --- drivers/input/touchscreen/calib_iface_ts.c | 228 ---- drivers/input/touchscreen/calibration_ts.c | 655 ---------- drivers/input/touchscreen/calibration_ts.h | 59 - drivers/input/touchscreen/largenum_ts.c | 602 --------- drivers/input/touchscreen/largenum_ts.h | 152 --- drivers/input/touchscreen/xpt2046_cbn_ts.c | 1046 ---------------- drivers/input/touchscreen/xpt2046_cbn_ts.h | 66 - drivers/input/touchscreen/xpt2046_ts.c | 1032 ---------------- drivers/input/touchscreen/xpt2046_ts.h | 66 - .../input/touchscreen/xpt2046_ts_320X480.c | 1016 --------------- drivers/input/touchscreen/xpt2046_tslib_ts.c | 1099 ----------------- drivers/input/touchscreen/xpt2046_tslib_ts.h | 66 - 12 files changed, 6087 deletions(-) delete mode 100644 drivers/input/touchscreen/calib_iface_ts.c delete mode 100755 drivers/input/touchscreen/calibration_ts.c delete mode 100755 drivers/input/touchscreen/calibration_ts.h delete mode 100755 drivers/input/touchscreen/largenum_ts.c delete mode 100755 drivers/input/touchscreen/largenum_ts.h delete mode 100755 drivers/input/touchscreen/xpt2046_cbn_ts.c delete mode 100755 drivers/input/touchscreen/xpt2046_cbn_ts.h delete mode 100755 drivers/input/touchscreen/xpt2046_ts.c delete mode 100755 drivers/input/touchscreen/xpt2046_ts.h delete mode 100755 drivers/input/touchscreen/xpt2046_ts_320X480.c delete mode 100755 drivers/input/touchscreen/xpt2046_tslib_ts.c delete mode 100755 drivers/input/touchscreen/xpt2046_tslib_ts.h diff --git a/drivers/input/touchscreen/calib_iface_ts.c b/drivers/input/touchscreen/calib_iface_ts.c deleted file mode 100644 index e7da932ec062..000000000000 --- a/drivers/input/touchscreen/calib_iface_ts.c +++ /dev/null @@ -1,228 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Export interface in /sys/class/touchpanel for calibration. - * - * Yongle Lai @ Rockchip - 2010-07-26 - */ -#include -#include -#include -#include -#include - -#include "calibration_ts.h" - -/* - * The sys nodes for touch panel calibration depends on controller's name, - * such as: /sys/bus/spi/drivers/xpt2046_ts/touchadc - * If we use another TP controller (not xpt2046_ts), the above path will - * be unavailable which will cause calibration to be fail. - * - * Another choice is: - * sys/devices/platform/rockchip_spi_master/spi0.0/driver/touchadc - * this path request the TP controller will be the first device of SPI. - * - * To make TP calibration module in Android be universal, we create - * a class named touchpanel as the path for calibration interfaces. - */ - -/* - * TPC driver depended. - */ -extern volatile struct adc_point gADPoint; -#ifdef TS_PRESSURE -extern volatile int gZvalue[3]; -#endif - -#if 0 -#if defined(CONFIG_MACH_RK2818INFO_IT50) && defined(CONFIG_TOUCHSCREEN_XPT2046_CBN_SPI) - int screen_x[5] = { 50, 750, 50, 750, 400}; - int screen_y[5] = { 40, 40, 440, 440, 240}; - int uncali_x_default[5] = { 3735, 301, 3754, 290, 1993 }; - int uncali_y_default[5] = { 3442, 3497, 413, 459, 1880 }; -#elif defined(CONFIG_MACH_RK2818INFO) && defined(CONFIG_TOUCHSCREEN_XPT2046_CBN_SPI) - int screen_x[5] = { 50, 750, 50, 750, 400}; - int screen_y[5] = { 40, 40, 440, 440, 240}; - int uncali_x_default[5] = { 438, 565, 3507, 3631, 2105 }; - int uncali_y_default[5] = { 3756, 489, 3792, 534, 2159 }; -#elif (defined(CONFIG_MACH_RAHO) || defined(CONFIG_MACH_RAHOSDK) || defined(CONFIG_MACH_RK2818INFO))&& defined(CONFIG_TOUCHSCREEN_XPT2046_320X480_CBN_SPI) - int screen_x[5] = { 50, 270, 50, 270, 160}; - int screen_y[5] = { 40, 40, 440, 440, 240}; - int uncali_x_default[5] = { 812, 3341, 851, 3371, 2183 }; - int uncali_y_default[5] = { 442, 435, 3193, 3195, 2004 }; -#elif defined(CONFIG_MACH_Z5) && defined(CONFIG_TOUCHSCREEN_XPT2046_CBN_SPI) - int uncali_x_default[5] = { 3267, 831, 3139, 715, 1845 }; - int uncali_y_default[5] = { 3638, 3664, 564, 591, 2087 }; - int screen_x[5] = { 70, 410, 70, 410, 240}; - int screen_y[5] = { 50, 50, 740, 740, 400}; -#endif -#endif -int screen_x[5] = { 0 }; -int screen_y[5] = { 0 }; -int uncali_x_default[5] = { 0 }; -int uncali_y_default[5] = { 0 }; -int uncali_x[5] = { 0 }; -int uncali_y[5] = { 0 }; - -static ssize_t touch_mode_show(struct class *cls, char *_buf) -{ - int count; - - count = sprintf(_buf,"TouchCheck:%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", - uncali_x[0], uncali_y[0], - uncali_x[1], uncali_y[1], - uncali_x[2], uncali_y[2], - uncali_x[3], uncali_y[3], - uncali_x[4], uncali_y[4]); - - printk("buf: %s", _buf); - - return count; -} - -static ssize_t touch_mode_store(struct class *cls, const char *_buf, size_t _count) -{ - int i, j = 0; - char temp[5]; - - //printk("Read data from Android: %s\n", _buf); - - for (i = 0; i < 5; i++) - { - strncpy(temp, _buf + 5 * (j++), 4); - uncali_x[i] = simple_strtol(temp, NULL, 10); - strncpy(temp, _buf + 5 * (j++), 4); - uncali_y[i] = simple_strtol(temp, NULL, 10); - printk("SN=%d uncali_x=%d uncali_y=%d\n", - i, uncali_x[i], uncali_y[i]); - } - - return _count; -} - -//This code is Touch adc simple value -static ssize_t touch_adc_show(struct class *cls,char *_buf) -{ - printk("ADC show: x=%d y=%d\n", gADPoint.x, gADPoint.y); - - return sprintf(_buf, "%d,%d\n", gADPoint.x, gADPoint.y); -} - -static ssize_t touch_cali_status(struct class *cls, char *_buf) -{ - int ret; - - ret = TouchPanelSetCalibration(4, screen_x, screen_y, uncali_x, uncali_y); - if (ret == 1){ - memcpy(uncali_x_default, uncali_x, sizeof(uncali_x)); - memcpy(uncali_y_default, uncali_y, sizeof(uncali_y)); - printk("touch_cali_status-0--%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", - uncali_x_default[0], uncali_y_default[0], - uncali_x_default[1], uncali_y_default[1], - uncali_x_default[2], uncali_y_default[2], - uncali_x_default[3], uncali_y_default[3], - uncali_x_default[4], uncali_y_default[4]); - ret = sprintf(_buf, "successful\n"); - } - else{ - printk("touchpal calibration failed, use default value.\n"); - ret = TouchPanelSetCalibration(4, screen_x, screen_y, uncali_x_default, uncali_y_default); - printk("touch_cali_status-1---%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", - uncali_x_default[0], uncali_y_default[0], - uncali_x_default[1], uncali_y_default[1], - uncali_x_default[2], uncali_y_default[2], - uncali_x_default[3], uncali_y_default[3], - uncali_x_default[4], uncali_y_default[4]); - if (ret == 1){ - ret = sprintf(_buf, "recovery\n"); - } - else{ - ret = sprintf(_buf, "fail\n"); - } - } - - //printk("Calibration status: _buf=<%s", _buf); - - return ret; -} -#ifdef TS_PRESSURE -static ssize_t touch_pressure(struct class *cls,char *_buf) -{ - printk("enter %s gADPoint.x==%d,gADPoint.y==%d\n",__FUNCTION__,gADPoint.x,gADPoint.y); - return sprintf(_buf,"%d,%d,%d\n",gZvalue[0],gZvalue[1],gZvalue[2]); -} -#endif - -static struct class *tp_class = NULL; - -static CLASS_ATTR(touchcheck, 0666, touch_mode_show, touch_mode_store); -static CLASS_ATTR(touchadc, 0666, touch_adc_show, NULL); -static CLASS_ATTR(calistatus, 0666, touch_cali_status, NULL); -#ifdef TS_PRESSURE -static CLASS_ATTR(pressure, 0666, touch_pressure, NULL); -#endif - -int tp_calib_iface_init(int *x,int *y,int *uncali_x, int *uncali_y) -{ - int ret = 0; - int err = 0; - - tp_class = class_create(THIS_MODULE, "touchpanel"); - if (IS_ERR(tp_class)) - { - printk("Create class touchpanel failed.\n"); - return -ENOMEM; - } - - memcpy(screen_x,x,5*sizeof(int)); - memcpy(screen_y,y,5*sizeof(int)); - memcpy(uncali_x_default,uncali_x,5*sizeof(int)); - memcpy(uncali_y_default,uncali_y,5*sizeof(int)); - - err = TouchPanelSetCalibration(4, screen_x, screen_y, uncali_x_default, uncali_y_default); - printk("tp_calib_iface_init---%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", - uncali_x_default[0], uncali_y_default[0], - uncali_x_default[1], uncali_y_default[1], - uncali_x_default[2], uncali_y_default[2], - uncali_x_default[3], uncali_y_default[3], - uncali_x_default[4], uncali_y_default[4]); - if (err == 1){ - printk("Auto set calibration successfully.\n"); - } else { - printk("Auto set calibraion failed, reset data again please !"); - } - - /* - * Create ifaces for TP calibration. - */ - ret = class_create_file(tp_class, &class_attr_touchcheck); - ret += class_create_file(tp_class, &class_attr_touchadc); - ret += class_create_file(tp_class, &class_attr_calistatus); -#ifdef TS_PRESSURE - ret += class_create_file(tp_class, &class_attr_pressure); -#endif - if (ret) - { - printk("Fail to class ifaces for TP calibration.\n"); - } - - return ret; -} - -void tp_calib_iface_exit(void) -{ - class_remove_file(tp_class, &class_attr_touchcheck); - class_remove_file(tp_class, &class_attr_touchadc); - class_remove_file(tp_class, &class_attr_calistatus); -#ifdef TS_PRESSURE - class_remove_file(tp_class, &class_attr_pressure); -#endif - class_destroy(tp_class); -} - -//module_init(tp_calib_iface_init); -//module_exit(tp_calib_iface_exit); - -MODULE_AUTHOR("Yongle Lai"); -MODULE_DESCRIPTION("XPT2046 TPC driver @ Rockchip"); -MODULE_LICENSE("GPL"); diff --git a/drivers/input/touchscreen/calibration_ts.c b/drivers/input/touchscreen/calibration_ts.c deleted file mode 100755 index 70f611154c5a..000000000000 --- a/drivers/input/touchscreen/calibration_ts.c +++ /dev/null @@ -1,655 +0,0 @@ -/* - * drivers/input/touchscreen/calibration_ts.c - calibration for rk2818 spi xpt2046 device and console - * - * Copyright (C) 2010 ROCKCHIP, 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 -#include - -#include "calibration_ts.h" -#include "largenum_ts.h" - -#define MAX_POINT_ERROR 6 - -typedef struct { - PLARGENUM pa11, pa12, pa13; - PLARGENUM pa21, pa22, pa23; - PLARGENUM pa31, pa32, pa33; -} MATRIX33, *PMATRIX33; - -typedef struct { - int a1; - int b1; - int c1; - int a2; - int b2; - int c2; - int delta; -} -CALIBRATION_PARAMETER, *PCALIBRATION_PARAMETER; - -static unsigned char v_Calibrated = 0; -static CALIBRATION_PARAMETER v_CalcParam ={ - .a1 =18670 , - .b1 =98, - .c1 = -2230109, - .a2 = 291, - .b2 = 12758, - .c2 = -5118934, - .delta = 91931, -}; -static CALIBRATION_PARAMETER v_CalcParam_bak = { - .a1=17704 , - .b1=-20, - .c1= -1460283, - .a2 = 382, - .b2 = 12685, - .c2 = -5595261, - .delta = 88403, -}; -unsigned char -ErrorAnalysis( - int cCalibrationPoints, //@PARM The number of calibration points - int *pScreenXBuffer, //@PARM List of screen X coords displayed - int *pScreenYBuffer, //@PARM List of screen Y coords displayed - int *pUncalXBuffer, //@PARM List of X coords collected - int *pUncalYBuffer //@PARM List of Y coords collected - ); - -void -ComputeMatrix33( - PLARGENUM pResult, - PMATRIX33 pMatrix - ); - -unsigned char -TouchPanelSetCalibration( - int cCalibrationPoints, //@PARM The number of calibration points - int *pScreenXBuffer, //@PARM List of screen X coords displayed - int *pScreenYBuffer, //@PARM List of screen Y coords displayed - int *pUncalXBuffer, //@PARM List of X coords collected - int *pUncalYBuffer //@PARM List of Y coords collected - ) -{ - LARGENUM a11; - LARGENUM a21, a22; - LARGENUM a31, a32, a33; - LARGENUM b11, b12, b13; - LARGENUM b21, b22, b23; - LARGENUM lnScreenX; - LARGENUM lnScreenY; - LARGENUM lnTouchX; - LARGENUM lnTouchY; - LARGENUM lnTemp; - LARGENUM delta; - LARGENUM a1, b1, c1; - LARGENUM a2, b2, c2; - MATRIX33 Matrix; - int cShift; - int minShift; - int i; - - - //DEBUGMSG(1,(__TEXT("calibrating %d point set\r\n"), cCalibrationPoints)); - - // - // If the calibration data is being cleared, set the flag so - // that the conversion operation is a noop. - // - - if ( cCalibrationPoints == 0 ) - { - v_Calibrated = 0; - return 1; - } - - // - // Compute these large numbers - // - LargeNumSet(&a11, 0); - LargeNumSet(&a21, 0); - LargeNumSet(&a31, 0); - LargeNumSet(&a22, 0); - LargeNumSet(&a32, 0); - LargeNumSet(&a33, cCalibrationPoints); - LargeNumSet(&b11, 0); - LargeNumSet(&b12, 0); - LargeNumSet(&b13, 0); - LargeNumSet(&b21, 0); - LargeNumSet(&b22, 0); - LargeNumSet(&b23, 0); - for(i=0; i minShift){ - minShift = cShift; - } - cShift = LargeNumBits(&b1) - MAX_COEFF_PRECISION; - if(cShift > minShift){ - minShift = cShift; - } - cShift = LargeNumBits(&a2) - MAX_COEFF_PRECISION; - if(cShift > minShift){ - minShift = cShift; - } - cShift = LargeNumBits(&b2) - MAX_COEFF_PRECISION; - if(cShift > minShift){ - minShift = cShift; - } - cShift = LargeNumBits(&c1) - MAX_TERM_PRECISION; - if(cShift > minShift){ - minShift = cShift; - } - cShift = LargeNumBits(&c2) - MAX_TERM_PRECISION; - if(cShift > minShift){ - minShift = cShift; - } - cShift = LargeNumBits(&delta) - 31; - if(cShift > minShift){ - minShift = cShift; - } - - // - // Now, shift count is determined, shift all the numbers - // right to obtain the 32-bit signed values - // - if(minShift){ - LargeNumRAShift(&a1, minShift); - LargeNumRAShift(&a2, minShift); - LargeNumRAShift(&b1, minShift); - LargeNumRAShift(&b2, minShift); - LargeNumRAShift(&c1, minShift); - LargeNumRAShift(&c2, minShift); - LargeNumRAShift(&delta, minShift); - } - v_CalcParam.a1 = a1.u.s32.u[0]; - v_CalcParam.b1 = b1.u.s32.u[0]; - v_CalcParam.c1 = c1.u.s32.u[0]; - v_CalcParam.a2 = a2.u.s32.u[0]; - v_CalcParam.b2 = b2.u.s32.u[0]; - v_CalcParam.c2 = c2.u.s32.u[0]; - v_CalcParam.delta = delta.u.s32.u[0]; - - // Don't allow delta to be zero, since it gets used as a divisor - if( ! v_CalcParam.delta ) - { - //RETAILMSG(1,(__TEXT("TouchPanelSetCalibration: delta of 0 invalid\r\n"))); - //RETAILMSG(1,(__TEXT("\tCalibration failed.\r\n"))); - v_CalcParam.delta = 1; // any non-zero value to prevents DivByZero traps later - v_Calibrated = 0; - } - else - v_Calibrated = 1; - - return ErrorAnalysis( - cCalibrationPoints, - pScreenXBuffer, - pScreenYBuffer, - pUncalXBuffer, - pUncalYBuffer - ); -} - -void -ComputeMatrix33( - PLARGENUM pResult, - PMATRIX33 pMatrix - ) -{ - LARGENUM lnTemp; - - LargeNumMult(pMatrix->pa11, pMatrix->pa22, &lnTemp); - LargeNumMult(pMatrix->pa33, &lnTemp, pResult); - LargeNumMult(pMatrix->pa21, pMatrix->pa32, &lnTemp); - LargeNumMult(pMatrix->pa13, &lnTemp, &lnTemp); - LargeNumAdd(pResult, &lnTemp, pResult); - LargeNumMult(pMatrix->pa12, pMatrix->pa23, &lnTemp); - LargeNumMult(pMatrix->pa31, &lnTemp, &lnTemp); - LargeNumAdd(pResult, &lnTemp, pResult); - LargeNumMult(pMatrix->pa13, pMatrix->pa22, &lnTemp); - LargeNumMult(pMatrix->pa31, &lnTemp, &lnTemp); - LargeNumSub(pResult, &lnTemp, pResult); - LargeNumMult(pMatrix->pa12, pMatrix->pa21, &lnTemp); - LargeNumMult(pMatrix->pa33, &lnTemp, &lnTemp); - LargeNumSub(pResult, &lnTemp, pResult); - LargeNumMult(pMatrix->pa23, pMatrix->pa32, &lnTemp); - LargeNumMult(pMatrix->pa11, &lnTemp, &lnTemp); - LargeNumSub(pResult, &lnTemp, pResult); -} - -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; - - if ( v_Calibrated ) - { - - // - // Note the *4 in the expression below. This is a workaround - // on behalf of gwe. It provides a form of - // sub-pixel accuracy desirable for inking - // - x = (v_CalcParam.a1 * UncalX + v_CalcParam.b1 * UncalY + - v_CalcParam.c1) * 4 / v_CalcParam.delta; - y = (v_CalcParam.a2 * UncalX + v_CalcParam.b2 * UncalY + - v_CalcParam.c2) * 4 / v_CalcParam.delta; - } - else{ - x = (v_CalcParam_bak.a1 * UncalX + v_CalcParam_bak.b1 * UncalY + - v_CalcParam_bak.c1) * 4 / v_CalcParam_bak.delta; - y = (v_CalcParam_bak.a2 * UncalX + v_CalcParam_bak.b2 * UncalY + - v_CalcParam_bak.c2) * 4 / v_CalcParam_bak.delta; - } - if ( x < 0 ){ - x = 0; - } - - if (y < 0 ){ - y = 0; - } - - *pCalX = x; - *pCalY = y; -} - -unsigned char -ErrorAnalysis( - int cCalibrationPoints, //@PARM The number of calibration points - int *pScreenXBuffer, //@PARM List of screen X coords displayed - int *pScreenYBuffer, //@PARM List of screen Y coords displayed - int *pUncalXBuffer, //@PARM List of X coords collected - int *pUncalYBuffer //@PARM List of Y coords collected - ) -{ - int i; - unsigned int maxErr, err; - int x,y; - int dx,dy; - unsigned int errThreshold = MAX_POINT_ERROR; // Can be overridden by registry entry -#if 0 - unsigned int status, ValType, ValLen; - - //HKEY regKey; - - - // See if there is a Maximum Calibration Error specified in the registry - //status = RegOpenKeyEx( - // HKEY_LOCAL_MACHINE, - // __TEXT("HARDWARE\\DEVICEMAP\\TOUCH"), - // 0, - // 0, - // ®Key); - if ( status == ERROR_SUCCESS ) { - ValLen = sizeof(errThreshold); - status = RegQueryValueEx( - regKey, - __TEXT("MaxCalError"), - NULL, - &ValType, - (PUCHAR)&errThreshold, - &ValLen); - // We don't care what happened. Either we have a new value or we have the default value. - RegCloseKey(regKey); - } - - RETAILMSG(1,(__TEXT("Maximum Allowed Error %d:\r\n"), - errThreshold)); - DEBUGMSG(1,(__TEXT("Calibration Results:\r\n"))); -#endif - - maxErr = 0; - //DEBUGMSG(1,(__TEXT(" Screen => Mapped\r\n"))); - for(i=0; i (%4d, %4d)\n", - //DEBUGMSG(1,(__TEXT("(%4d, %4d) => (%4d, %4d)\r\n"), - pScreenXBuffer[i], - pScreenYBuffer[i], - x, - y - ); - - dx = x - pScreenXBuffer[i]; - dy = y - pScreenYBuffer[i]; - err = dx * dx + dy * dy; - if(err > maxErr){ - maxErr = err; - } - } - //DEBUGMSG(1,(__TEXT("Maximum error (square of Euclidean distance in screen units) = %u\r\n"), - // maxErr - // )); - - if (maxErr < (errThreshold * errThreshold)) - { - printk(" v_CalcParam.a1=%d \n" - "v_CalcParam.b1=%d\n" - "v_CalcParam.c1= %d\n" - " v_CalcParam.a2 = %d\n" - " v_CalcParam.b2 = %d\n" - " v_CalcParam.c2 = %d\n" - "v_CalcParam.delta = %d\n", - v_CalcParam.a1 , \ - v_CalcParam.b1 , \ - v_CalcParam.c1 , \ - v_CalcParam.a2 , \ - v_CalcParam.b2, \ - v_CalcParam.c2 , \ - v_CalcParam.delta); - return 1; - } - else - { - memset(&v_CalcParam, 0, sizeof(v_CalcParam)); - v_Calibrated = 0; - v_CalcParam.a1 = v_CalcParam_bak.a1; - v_CalcParam.b1 = v_CalcParam_bak.b1 ; - v_CalcParam.c1= v_CalcParam_bak.c1; - v_CalcParam.a2 = v_CalcParam_bak.a2; - v_CalcParam.b2 = v_CalcParam_bak.b2; - v_CalcParam.c2 = v_CalcParam_bak.c2; - v_CalcParam.delta= v_CalcParam_bak.delta; - return 0; - } -} - -#define FILTER_BUF_LEN 8 -typedef struct -{ - unsigned short x; - unsigned short y; -}P; -static P sTouchFilterBuff[FILTER_BUF_LEN]; -static int sBuffIndex = 0; -static P sReportFilter = {0,0}; -void ClearBuff(void) -{ - memset(sTouchFilterBuff,0,FILTER_BUF_LEN*sizeof(P)); - sReportFilter.x = 0; - sReportFilter.y = 0; - sBuffIndex = 0; -} -void addToBuff(int* x,int* y) -{ - int index; - index=sBuffIndex++%FILTER_BUF_LEN; - sTouchFilterBuff[index].x = *x; - sTouchFilterBuff[index].y = *y; -} -#define TS_ERR_TDOWN -1 -#define TS_ERR_LOWBUF -2 -//#define TS_MINX 138 -//#define TS_MINY 375 -//#define TS_MAXX 3935 -//#define TS_MAXY 3920 -//#define TS_xISVALID(x) (x>=TS_MINX&&x<=TS_MAXX) -#define TS_isINVALID(X,Y) (X==4095||Y==4095||X==0||Y==0) -#define ABS(x) ((x)>0?(x):-(x)) -static P spoint; -int TouchFilter(unsigned short* x,unsigned short* y,bool isdown) -{ -#if 1 - int ret = 0; - if(isdown==0&&sBuffIndex==0) - { - spoint.x = *x; - spoint.y = *y; - ClearBuff(); - ret=TS_ERR_TDOWN; - } - if(!TS_isINVALID(*x,*y)) - addToBuff(x,y); - if(sBuffIndexx-p1->x)<60||ABS(p->y-p1->y)<60) - { - *x=spoint.x; - *y=spoint.y; - //printk("p(%d,%d) p1(%d,%d)\n",p->x,p->y,p1->x,p1->y); - //ret=-3; - break; - } - p++; - p1++; - if(++index>=FILTER_BUF_LEN-1)break; - } - spoint.x=*x; - spoint.y=*y; - } - -#else - int ret = 0; - if(isdown==0&&sBuffIndex==0) - { - ClearBuff(); - ret=TS_ERR_TDOWN; - } - if(!TS_isINVALID(x,y)) - addToBuff(x,y); - if(sBuffIndex=FILTER_BUF_LEN)break; - } - *x = adp.x/FILTER_BUF_LEN; - *y = adp.y/FILTER_BUF_LEN; - } -#endif - return ret; - -} - -#define SLAP_X 2 -#define SLAP_Y 0 -void TouchReportFilter(unsigned short* x,unsigned short* y) -{ - if((sReportFilter.x==0&&sReportFilter.y==0)|| - (ABS(sReportFilter.x - *x)>SLAP_X&&ABS(sReportFilter.y - *y)>SLAP_Y)) - { - sReportFilter.x = *x; - sReportFilter.y = *y; - } - *x = sReportFilter.x; - *y = sReportFilter.y; -} -#if 0 -int main(void) -{ - unsigned char ret; - int cali_num = 4; - int screen_x[4], screen_y[4]; - int uncali_x[4], uncali_y[4]; - int tst_uncali_x, tst_uncali_y, tst_cali_x, tst_cali_y; - - screen_x[0] = 15; screen_y[0] = 15; - screen_x[1] = 15; screen_y[1] = 465; - screen_x[2] = 785; screen_y[2] = 15; - screen_x[3] = 785; screen_y[3] = 465; - - uncali_x[0] = 173; uncali_y[0] = 417; - uncali_x[1] = 148; uncali_y[1] = 3867; - uncali_x[2] = 3903; uncali_y[2] = 365; - uncali_x[3] = 3924; uncali_y[3] = 3863; - - ret = TouchPanelSetCalibration(4, screen_x, - screen_y, uncali_x, uncali_y); - if (ret == 1) - printf("TouchPanelSetCalibration OK.\n"); - else - printf("TouchPanelSetCalibration FAIL.\n"); - - tst_uncali_x = 2033; - tst_uncali_y = 2132; - - TouchPanelCalibrateAPoint(tst_uncali_x, tst_uncali_y, - &tst_cali_x, &tst_cali_y); - - printf("(%d, %d) >> (%d, %d)\n", tst_uncali_x, tst_uncali_y, - tst_cali_x/4, tst_cali_y/4); - - tst_uncali_x = 170; - tst_uncali_y = 418; - - TouchPanelCalibrateAPoint(tst_uncali_x, tst_uncali_y, - &tst_cali_x, &tst_cali_y); - - printf("(%d, %d) >> (%d, %d)\n", tst_uncali_x, tst_uncali_y, - tst_cali_x/4, tst_cali_y/4); - - tst_uncali_x = 500; - tst_uncali_y = 707; - - TouchPanelCalibrateAPoint(tst_uncali_x, tst_uncali_y, - &tst_cali_x, &tst_cali_y); - - printf("(%d, %d) >> (%d, %d)\n", tst_uncali_x, tst_uncali_y, - tst_cali_x/4, tst_cali_y/4); - - tst_uncali_x = 3636; - tst_uncali_y = 2150; - - TouchPanelCalibrateAPoint(tst_uncali_x, tst_uncali_y, - &tst_cali_x, &tst_cali_y); - - printf("(%d, %d) >> (%d, %d)\n", tst_uncali_x, tst_uncali_y, - tst_cali_x/4, tst_cali_y/4); - - return 0; -} -#endif - diff --git a/drivers/input/touchscreen/calibration_ts.h b/drivers/input/touchscreen/calibration_ts.h deleted file mode 100755 index 795d7b48a071..000000000000 --- a/drivers/input/touchscreen/calibration_ts.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * drivers/input/touchscreen/calibration_ts.h - * - * Copyright (C) 2010 ROCKCHIP, 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. - */ - -#ifndef __DRIVERS_TOUCHSCREEN_CALIBRATION_TS_H -#define __DRIVERS_TOUCHSCREEN_CALIBRATION_TS_H - -struct adc_point -{ - int x; - int y; -}; - -#define TWO_DIMENSIONAL_CALIBRATION 1 - -#define ADC_PRECISION 12 // Precision of ADC output (in bits) -#define MAX_TERM_PRECISION 27 // Reserve 1 bit for sign and two bits for - // three terms (there are three terms in - // each of x and y mapping functions.) - -// -// All a1, a2, b1, and b2 must have less than MAX_COEFF_PRECISION bits since -// they all are multiplied with either an X or a Y to form a term. -// Both c1 and c2 can have up to MAX_TERM_PRECISION since they each alone -// forms a term. -// -#define MAX_COEFF_PRECISION (MAX_TERM_PRECISION - ADC_PRECISION) - -unsigned char -TouchPanelSetCalibration( - int cCalibrationPoints, //@PARM The number of calibration points - int *pScreenXBuffer, //@PARM List of screen X coords displayed - int *pScreenYBuffer, //@PARM List of screen Y coords displayed - int *pUncalXBuffer, //@PARM List of X coords collected - int *pUncalYBuffer //@PARM List of Y coords collected - ); - -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 tp_calib_iface_init(int *x,int *y,int *uncali_x, int *uncali_y); -void tp_calib_iface_exit(void); -#endif diff --git a/drivers/input/touchscreen/largenum_ts.c b/drivers/input/touchscreen/largenum_ts.c deleted file mode 100755 index eacae6988d0c..000000000000 --- a/drivers/input/touchscreen/largenum_ts.c +++ /dev/null @@ -1,602 +0,0 @@ -/* - * drivers/input/touchscreen/largenum_ts.c - largenum for rk2818 spi xpt2046 device and console - * - * Copyright (C) 2010 ROCKCHIP, 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 - -#include "largenum_ts.h" - -unsigned int -LargeNumSignedFormat( - PLARGENUM pNum - ); - -PLARGENUM -LargeNumSet( - PLARGENUM pNum, - int n - ) -{ - int i; - - if(n < 0){ - pNum->u.s32.u[0] = -n; - pNum->fNegative = 1; - } else{ - pNum->u.s32.u[0] = n; - pNum->fNegative=0; - } - for(i=1; iu.s32.u[i] = 0; - } - return pNum; -} - -unsigned char -IsLargeNumNotZero( - PLARGENUM pNum - ) -{ - int i; - - for(i=0; iu.s32.u[i]){ - return 1; - } - } - return 0; -} - -unsigned char -IsLargeNumNegative( - PLARGENUM pNum - ) -{ - return (pNum->fNegative ? 1 : 0); - -} - -unsigned char -IsLargeNumMagGreaterThan( - PLARGENUM pNum1, - PLARGENUM pNum2 - ) -{ - int i; - - for(i=SIZE_OF_LARGENUM-1; i>=0; i--){ - if(pNum1->u.s32.u[i] > pNum2->u.s32.u[i]){ - return 1; - } else if(pNum1->u.s32.u[i] < pNum2->u.s32.u[i]){ - return 0; - } - } - return 0; -} - -unsigned char -IsLargeNumMagLessThan( - PLARGENUM pNum1, - PLARGENUM pNum2 - ) -{ - int i; - - for(i=SIZE_OF_LARGENUM-1; i>=0; i--){ - if(pNum1->u.s32.u[i] < pNum2->u.s32.u[i]){ - return 1; - } else if(pNum1->u.s32.u[i] > pNum2->u.s32.u[i]){ - return 0; - } - } - return 0; -} - -PLARGENUM -LargeNumMagInc( - PLARGENUM pNum - ) -{ - unsigned int c; - int i; - - c = 1; - for(i=0; iu.s32.u[i] += c; - if(pNum->u.s32.u[i]){ - c = 0; - } - } - return pNum; -} - -PLARGENUM -LargeNumMagAdd( - PLARGENUM pNum1, - PLARGENUM pNum2, - PLARGENUM pResult - ) -{ - unsigned int c; - unsigned int i; - unsigned int a; - unsigned int b; - - c = 0; - for(i=0; iu.s32.u[i]; - b = pNum2->u.s32.u[i]; - pResult->u.s32.u[i] = a + b + c; - if(c){ - if(pResult->u.s32.u[i] <= a){ - c = 1; - } else { - c = 0; - } - - } else { - if(pResult->u.s32.u[i] < a){ - c = 1; - } else { - c = 0; - } - - } - } - return pResult; -} - -PLARGENUM -LargeNumMagSub( - PLARGENUM pNum1, - PLARGENUM pNum2, - PLARGENUM pResult - ) -{ - unsigned int c; - unsigned int i; - unsigned int a; - unsigned int b; - - c = 1; - for(i=0; iu.s32.u[i]; - b = ~(pNum2->u.s32.u[i]); - pResult->u.s32.u[i] = a + b + c; - if(c){ - if(pResult->u.s32.u[i] <= a){ - c = 1; - } else { - c = 0; - } - - } else { - if(pResult->u.s32.u[i] < a){ - c = 1; - } else { - c = 0; - } - - } - } - return pResult; -} - -PLARGENUM -LargeNumAdd( - PLARGENUM pNum1, - PLARGENUM pNum2, - PLARGENUM pResult - ) -{ - unsigned char fNegative1; - unsigned char fNegative2; - - fNegative1 = IsLargeNumNegative(pNum1); - fNegative2 = IsLargeNumNegative(pNum2); - - if(fNegative1 != fNegative2){ - if(IsLargeNumMagGreaterThan(pNum1, pNum2)){ - LargeNumMagSub(pNum1, pNum2, pResult); - } else { - LargeNumMagSub(pNum2, pNum1, pResult); - fNegative1 = !fNegative1; - } - } else { - LargeNumMagAdd(pNum1, pNum2, pResult); - } - if(!IsLargeNumNotZero(pResult)){ - pResult->fNegative = 0; - } else { - pResult->fNegative = fNegative1; - } - return pResult; -} - -PLARGENUM -LargeNumSub( - PLARGENUM pNum1, - PLARGENUM pNum2, - PLARGENUM pResult - ) -{ - unsigned char fNegative1; - unsigned char fNegative2; - - fNegative1 = IsLargeNumNegative(pNum1); - fNegative2 = IsLargeNumNegative(pNum2); - - if(fNegative1 == fNegative2){ - if(IsLargeNumMagGreaterThan(pNum1, pNum2)){ - LargeNumMagSub(pNum1, pNum2, pResult); - } else { - LargeNumMagSub(pNum2, pNum1, pResult); - fNegative1 = !fNegative1; - } - } else { - LargeNumMagAdd(pNum1, pNum2, pResult); - } - if(!IsLargeNumNotZero(pResult)){ - pResult->fNegative = 0; - } else { - pResult->fNegative = fNegative1; - } - return pResult; -} - -PLARGENUM -LargeNumMulUint32( - unsigned int a, - unsigned int b, - PLARGENUM pResult - ) -{ - unsigned int a1, a0; - unsigned int b1, b0; - unsigned int r0; - unsigned int r1; - unsigned int r2; - unsigned int c; - int i; - - a1 = a >> 16; - a0 = a & 0xffff; - b1 = b >> 16; - b0 = b & 0xffff; - - r0 = a0 * b0; - r1 = a1 * b0 + a0 * b1; - r2 = a1 * b1; - - pResult->u.s32.u[0] = (r1 << 16) + r0; - if(pResult->u.s32.u[0] < r0){ - c = 1; - } else { - c = 0; - } - pResult->u.s32.u[1] = r2 + (r1 >> 16) + c; - for(i=2; iu.s32.u[i] = 0; - } - pResult->fNegative = 0; - - return pResult; -} - -PLARGENUM -LargeNumMulInt32( - int a, - int b, - PLARGENUM pResult - ) -{ - unsigned char fNegativeA; - unsigned char fNegativeB; - - if(a < 0){ - fNegativeA = 1; - a = -a; - } else { - fNegativeA = 0; - } - - if(b < 0){ - fNegativeB = 1; - b = -b; - } else { - fNegativeB = 0; - } - - LargeNumMulUint32(a, b, pResult); - - if(!IsLargeNumNotZero(pResult)){ - pResult->fNegative = 0; - } else { - if(fNegativeA != fNegativeB){ - pResult->fNegative = 1; - } - } - return pResult; -} - -PLARGENUM -LargeNumMult( - PLARGENUM pNum1, - PLARGENUM pNum2, - PLARGENUM pResult - ) -{ - LARGENUM lNumTemp; - LARGENUM lNumSum; - LARGENUM lNumCarry; - int i; - int j; - - LargeNumSet(&lNumCarry, 0); - for(i=0; iu.s32.u[j], pNum2->u.s32.u[i-j], &lNumTemp); - LargeNumMagAdd(&lNumTemp, &lNumSum, &lNumSum); - } - LargeNumMagAdd(&lNumCarry, &lNumSum, &lNumSum); - for(j=0; ju.s32.u[i] = lNumSum.u.s32.u[0]; - } - - if(!IsLargeNumNotZero(pResult)){ - pResult->fNegative = 0; - } else { - pResult->fNegative = (pNum1->fNegative != pNum2->fNegative); - } - return pResult; -} - -unsigned int -LargeNumSignedFormat( - PLARGENUM pNum - ) -{ - int i; - unsigned int c; - - if(IsLargeNumNegative(pNum)){ - c = 1; - for(i=0; iu.s32.u[i] = ~(pNum->u.s32.u[i]) + c; - if(pNum->u.s32.u[i]){ - c = 0; - } - } - return 0xffffffff; - } else { - return 0; - } -} - -void -LargeNumRAShift( - PLARGENUM pNum, - int count - ) -{ - int shift32; - int countLeft; - unsigned int filler; - int i; - int j; - - filler = LargeNumSignedFormat(pNum); - - shift32 = count / 32; - - if(shift32 > (SIZE_OF_LARGENUM - 1)){ - for(i=0; iu.s32.u[i] = filler; - } - return; - } - - count %= 32; - countLeft = 32 - count; - for(i=0, j=shift32;;){ - pNum->u.s32.u[i] = (pNum->u.s32.u[j] >> count); - if(j<(SIZE_OF_LARGENUM-1)){ - j++; - if (countLeft < 32) { - // Shifting by >= 32 is undefined. - pNum->u.s32.u[i] |= pNum->u.s32.u[j] << countLeft; - } - i++; - } else { - if (countLeft < 32) { - // Shifting by >= 32 is undefined. - pNum->u.s32.u[i] |= filler << countLeft; - } - i++; - break; - } - } - - for(; iu.s32.u[i] = filler; - } -} - -unsigned int -LargeNumDivInt32( - PLARGENUM pNum, - int divisor, - PLARGENUM pResult - ) -{ - unsigned int s[2*SIZE_OF_LARGENUM]; - unsigned int r; - unsigned int q; - unsigned int d; - unsigned char sd; - int i; - - for(i=0; i<2*SIZE_OF_LARGENUM; i++){ - s[i] = pNum->u.s16.s[i]; - } - - if(divisor < 0){ - divisor = -divisor; - sd = 1; - } else if(divisor == 0){ - // - // This is a divide-by-zero error - // - for(i=0; iu.s32.u[i] = 0xffffffff; - } - return 0xffffffff; - } else { - sd = 0; - } - - r = 0; - for(i=(2*SIZE_OF_LARGENUM-1); i>=0; i--){ - d = (r << 16) + s[i]; - q = d / divisor; - r = d - q * divisor; - s[i] = q; - } - - for(i=0; i<2*SIZE_OF_LARGENUM; i++){ - pResult->u.s16.s[i] = s[i]; - } - - if(pNum->fNegative){ - LargeNumMagInc(pResult); - r = divisor - r; - if(sd == 0 && IsLargeNumNotZero(pResult)){ - pResult->fNegative = 1; - } else { - pResult->fNegative = 0; - } - - } else { - if(sd && IsLargeNumNotZero(pResult)){ - pResult->fNegative = 1; - } else { - pResult->fNegative = 0; - } - } - - return r; -} - -int -LargeNumBits( - PLARGENUM pNum - ) -{ - static unsigned int LargeNumMask[32] = { - 0x00000001, - 0x00000002, - 0x00000004, - 0x00000008, - 0x00000010, - 0x00000020, - 0x00000040, - 0x00000080, - 0x00000100, - 0x00000200, - 0x00000400, - 0x00000800, - 0x00001000, - 0x00002000, - 0x00004000, - 0x00008000, - 0x00010000, - 0x00020000, - 0x00040000, - 0x00080000, - 0x00100000, - 0x00200000, - 0x00400000, - 0x00800000, - 0x01000000, - 0x02000000, - 0x04000000, - 0x08000000, - 0x10000000, - 0x20000000, - 0x40000000, - 0x80000000, - }; - - int i; - int j; - unsigned int u; - - for(i=(SIZE_OF_LARGENUM-1); i>=0; i--){ - u = pNum->u.s32.u[i]; - if(u){ - for(j=31; j>=0; j--){ - if(u & (LargeNumMask[j])){ - return i * 32 + j + 1; - } - } - } - } - return 0; -} - -char * -LargeNumToAscii( - PLARGENUM pNum - ) -{ - static char buf[SIZE_OF_LARGENUM * 10 + 2]; - LARGENUM lNum; - char *p; - char *q; - unsigned int r; - int s; - - p = buf + sizeof(buf) - 1; - *p= 0; - - lNum = *pNum; - - s = pNum->fNegative; - lNum.fNegative = 0; - - while(IsLargeNumNotZero(&lNum)){ - r = LargeNumDivInt32(&lNum, 10, &lNum); - p--; - *p = r + '0'; - } - - q = buf; - - if(s){ - *q++='-'; - } - while(*p){ - //ASSERT(q <= p); - //PREFAST_SUPPRESS(394, "q is <= p"); - *q++ = *p++; - } - - if((q == buf) || (s && q == &(buf[1]))){ - *q++ = '0'; - } - *q = 0; - return buf; -} diff --git a/drivers/input/touchscreen/largenum_ts.h b/drivers/input/touchscreen/largenum_ts.h deleted file mode 100755 index e0489ac31947..000000000000 --- a/drivers/input/touchscreen/largenum_ts.h +++ /dev/null @@ -1,152 +0,0 @@ -/* - * drivers/input/touchscreen/largenum_ts.h - * - * Copyright (C) 2010 ROCKCHIP, 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. - */ - -#ifndef LARGENUM_TS_H -#define LARGENUM_TS_H - -#define SIZE_OF_LARGENUM 3 - -typedef struct -{ - unsigned char fNegative; - union - { - struct - { - unsigned short s[2 * SIZE_OF_LARGENUM]; - } - s16; - - struct - { - unsigned int u[SIZE_OF_LARGENUM]; - } - s32; - - } - u; -} -LARGENUM, *PLARGENUM; - -// -// Function prototypes -// -PLARGENUM -LargeNumSet( - PLARGENUM pNum, - int n - ); - -unsigned char -IsLargeNumNotZero( - PLARGENUM pNum - ); - -unsigned char -IsLargeNumNegative( - PLARGENUM pNum - ); - -unsigned char -IsLargeNumMagGreaterThan( - PLARGENUM pNum1, - PLARGENUM pNum2 - ); - -unsigned char -IsLargeNumMagLessThan( - PLARGENUM pNum1, - PLARGENUM pNum2 - ); - -PLARGENUM -LargeNumMagInc( - PLARGENUM pNum - ); - -char * -LargeNumToAscii( - PLARGENUM pNum - ); - - -PLARGENUM -LargeNumMagAdd( - PLARGENUM pNum1, - PLARGENUM pNum2, - PLARGENUM pResult - ); - -PLARGENUM -LargeNumMagSub( - PLARGENUM pNum1, - PLARGENUM pNum2, - PLARGENUM pResult - ); - -PLARGENUM -LargeNumAdd( - PLARGENUM pNum1, - PLARGENUM pNum2, - PLARGENUM pResult - ); - -PLARGENUM -LargeNumSub( - PLARGENUM pNum1, - PLARGENUM pNum2, - PLARGENUM pResult - ); - -PLARGENUM -LargeNumMulUint32( - unsigned int a, - unsigned int b, - PLARGENUM pResult - ); - -PLARGENUM -LargeNumMulInt32( - int a, - int b, - PLARGENUM pResult - ); - -PLARGENUM -LargeNumMult( - PLARGENUM pNum1, - PLARGENUM pNum2, - PLARGENUM pResult - ); - -void -LargeNumRAShift( - PLARGENUM pNum, - int count - ); - -unsigned int -LargeNumDivInt32( - PLARGENUM pNum, - int divisor, - PLARGENUM pResult - ); - -int -LargeNumBits( - PLARGENUM pNum - ); - -#endif /* LARGENUM_TS_H */ diff --git a/drivers/input/touchscreen/xpt2046_cbn_ts.c b/drivers/input/touchscreen/xpt2046_cbn_ts.c deleted file mode 100755 index 99712d6520a2..000000000000 --- a/drivers/input/touchscreen/xpt2046_cbn_ts.c +++ /dev/null @@ -1,1046 +0,0 @@ -/* - * drivers/input/touchscreen/xpt2046_ts.c - driver for rk29 spi xpt2046 device and console - * - * Copyright (C) 2011 ROCKCHIP, 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_HAS_EARLYSUSPEND -#include -#endif -#include "xpt2046_cbn_ts.h" -#include "calibration_ts.h" -/* - * This code has been heavily tested on a Nokia 770, and lightly - * tested on other xpt2046 devices (OSK/Mistral, Lubbock). - * TSC2046 is just newer xpt2046 silicon. - * Support for ads7843 tested on Atmel at91sam926x-EK. - * Support for ads7845 has only been stubbed in. - * - * IRQ handling needs a workaround because of a shortcoming in handling - * edge triggered IRQs on some platforms like the OMAP1/2. These - * platforms don't handle the ARM lazy IRQ disabling properly, thus we - * have to maintain our own SW IRQ disabled status. This should be - * removed as soon as the affected platform's IRQ handling is fixed. - * - * app note sbaa036 talks in more detail about accurate sampling... - * that ought to help in situations like LCDs inducing noise (which - * can also be helped by using synch signals) and more generally. - * This driver tries to utilize the measures described in the app - * note. The strength of filtering can be set in the board-* specific - * files. - */ -#define XPT2046_DEBUG 0 -#if XPT2046_DEBUG - #define xpt2046printk(msg...) printk(msg); -#else - #define xpt2046printk(msg...) -#endif - -#define TS_POLL_DELAY (10 * 1000000) /* ns delay before the first sample */ -#define TS_POLL_PERIOD (20 * 1000000) /* ns delay between samples */ - -/* this driver doesn't aim at the peak continuous sample rate */ -#define SAMPLE_BITS (8 /*cmd*/ + 16 /*sample*/ + 2 /* before, after */) - -struct ts_event { - /* For portability, we can't read 12 bit values using SPI (which - * would make the controller deliver them as native byteorder u16 - * with msbs zeroed). Instead, we read them as two 8-bit values, - * *** WHICH NEED BYTESWAPPING *** and range adjustment. - */ - u16 x; - u16 y; - int ignore; -}; - -/* - * We allocate this separately to avoid cache line sharing issues when - * driver is used with DMA-based SPI controllers (like atmel_spi) on - * systems where main memory is not DMA-coherent (most non-x86 boards). - */ -struct xpt2046_packet { - u8 read_x, read_y, pwrdown; - u16 dummy; /* for the pwrdown read */ - struct ts_event tc; -}; - -struct xpt2046 { - struct input_dev *input; - char phys[32]; - char name[32]; - char pendown_iomux_name[IOMUX_NAME_SIZE]; - struct spi_device *spi; - - u16 model; - u16 x_min, x_max; - u16 y_min, y_max; - u16 debounce_max; - u16 debounce_tol; - u16 debounce_rep; - u16 penirq_recheck_delay_usecs; - bool swap_xy; - - struct xpt2046_packet *packet; - - struct spi_transfer xfer[18]; - struct spi_message msg[5]; - struct spi_message *last_msg; - int msg_idx; - int read_cnt; - int read_rep; - int last_read; - int pendown_iomux_mode; - int touch_virtualkey_length; - spinlock_t lock; - struct hrtimer timer; - unsigned pendown:1; /* P: lock */ - unsigned pending:1; /* P: lock */ -// FIXME remove "irq_disabled" - unsigned irq_disabled:1; /* P: lock */ - unsigned disabled:1; - unsigned is_suspended:1; - - int (*filter)(void *data, int data_idx, int *val); - void *filter_data; - void (*filter_cleanup)(void *data); - int (*get_pendown_state)(void); - int gpio_pendown; - - void (*wait_for_sync)(void); -#ifdef CONFIG_HAS_EARLYSUSPEND - struct early_suspend early_suspend; -#endif -}; - -/* leave chip selected when we're done, for quicker re-select? */ -#if 0 -#define CS_CHANGE(xfer) ((xfer).cs_change = 1) -#else -#define CS_CHANGE(xfer) ((xfer).cs_change = 0) -#endif - -/*--------------------------------------------------------------------------*/ - -/* The xpt2046 has touchscreen and other sensors. - * Earlier xpt2046 chips are somewhat compatible. - */ -#define XPT2046_START (1 << 7) -#define XPT2046_A2A1A0_d_y (1 << 4) /* differential */ -#define XPT2046_A2A1A0_d_z1 (3 << 4) /* differential */ -#define XPT2046_A2A1A0_d_z2 (4 << 4) /* differential */ -#define XPT2046_A2A1A0_d_x (5 << 4) /* differential */ -#define XPT2046_A2A1A0_temp0 (0 << 4) /* non-differential */ -#define XPT2046_A2A1A0_vbatt (2 << 4) /* non-differential */ -#define XPT2046_A2A1A0_vaux (6 << 4) /* non-differential */ -#define XPT2046_A2A1A0_temp1 (7 << 4) /* non-differential */ -#define XPT2046_8_BIT (1 << 3) -#define XPT2046_12_BIT (0 << 3) -#define XPT2046_SER (1 << 2) /* non-differential */ -#define XPT2046_DFR (0 << 2) /* differential */ -#define XPT2046_PD10_PDOWN (0 << 0) /* lowpower mode + penirq */ -#define XPT2046_PD10_ADC_ON (1 << 0) /* ADC on */ -#define XPT2046_PD10_REF_ON (2 << 0) /* vREF on + penirq */ -#define XPT2046_PD10_ALL_ON (3 << 0) /* ADC + vREF on */ - -#define MAX_12BIT ((1<<12)-1) - -/* leave ADC powered up (disables penirq) between differential samples */ -#define READ_12BIT_DFR(x, adc, vref) (XPT2046_START | XPT2046_A2A1A0_d_ ## x \ - | XPT2046_12_BIT | XPT2046_DFR | \ - (adc ? XPT2046_PD10_ADC_ON : 0) | (vref ? XPT2046_PD10_REF_ON : 0)) - -#define READ_Y(vref) (READ_12BIT_DFR(y, 1, vref)) -#define READ_Z1(vref) (READ_12BIT_DFR(z1, 1, vref)) -#define READ_Z2(vref) (READ_12BIT_DFR(z2, 1, vref)) - -#define READ_X(vref) (READ_12BIT_DFR(x, 1, vref)) -#define PWRDOWN (READ_12BIT_DFR(y, 0, 0)) /* LAST */ - -/* single-ended samples need to first power up reference voltage; - * we leave both ADC and VREF powered - */ -#define READ_12BIT_SER(x) (XPT2046_START | XPT2046_A2A1A0_ ## x \ - | XPT2046_12_BIT | XPT2046_SER) - -#define REF_ON (READ_12BIT_DFR(x, 1, 1)) -#define REF_OFF (READ_12BIT_DFR(y, 0, 0)) - -/*--------------------------------------------------------------------------*/ -/* - * touchscreen sensors use differential conversions. - */ - -struct dfr_req { - u8 command; - u8 pwrdown; - u16 dummy; /* for the pwrdown read */ - __be16 sample; - struct spi_message msg; - struct spi_transfer xfer[4]; -}; - -volatile struct adc_point gADPoint; - -static void xpt2046_enable(struct xpt2046 *ts); -static void xpt2046_disable(struct xpt2046 *ts); -static int xpt2046_verifyAndConvert(struct xpt2046 *ts,int adx, int ady,int *x, int *y) -{ - xpt2046printk("%s:(%d/%d)\n",__FUNCTION__,*x, *y); - - if((*x< ts->x_min) || (*x > ts->x_max)) - return 1; - - if((*y< ts->y_min) || (*y > ts->y_max + ts->touch_virtualkey_length)) - return 1; - - - return 0; -} -static int device_suspended(struct device *dev) -{ - struct xpt2046 *ts = dev_get_drvdata(dev); - return ts->is_suspended || ts->disabled; -} - -static int xpt2046_read12_dfr(struct device *dev, unsigned command) -{ - struct spi_device *spi = to_spi_device(dev); - struct xpt2046 *ts = dev_get_drvdata(dev); - struct dfr_req *req = kzalloc(sizeof *req, GFP_KERNEL); - int status; - - if (!req) - return -ENOMEM; - - spi_message_init(&req->msg); - - /* take sample */ - req->command = (u8) command; - req->xfer[0].tx_buf = &req->command; - req->xfer[0].len = 1; - spi_message_add_tail(&req->xfer[0], &req->msg); - - req->xfer[1].rx_buf = &req->sample; - req->xfer[1].len = 2; - spi_message_add_tail(&req->xfer[1], &req->msg); - - /* converter in low power mode & enable PENIRQ */ - req->pwrdown= PWRDOWN; - req->xfer[2].tx_buf = &req->pwrdown; - req->xfer[2].len = 1; - spi_message_add_tail(&req->xfer[2], &req->msg); - - req->xfer[3].rx_buf = &req->dummy; - req->xfer[3].len = 2; - CS_CHANGE(req->xfer[3]); - spi_message_add_tail(&req->xfer[3], &req->msg); - - ts->irq_disabled = 1; - disable_irq(spi->irq); - status = spi_sync(spi, &req->msg); - ts->irq_disabled = 0; - enable_irq(spi->irq); - - if (status == 0) { - /* on-wire is a must-ignore bit, a BE12 value, then padding */ - status = be16_to_cpu(req->sample); - status = status >> 3; - status &= 0x0fff; - xpt2046printk("***>%s:status=%d\n",__FUNCTION__,status); - } - - kfree(req); - return status; -} - - - -/*--------------------------------------------------------------------------*/ - -static int get_pendown_state(struct xpt2046 *ts) -{ - if (ts->get_pendown_state) - return ts->get_pendown_state(); - - return !gpio_get_value(ts->gpio_pendown); -} - -static void null_wait_for_sync(void) -{ - -} - -/* - * PENIRQ only kicks the timer. The timer only reissues the SPI transfer, - * to retrieve touchscreen status. - * - * The SPI transfer completion callback does the real work. It reports - * touchscreen events and reactivates the timer (or IRQ) as appropriate. - */ -static void xpt2046_rx(void *xpt) -{ - struct xpt2046 *ts = xpt; - struct xpt2046_packet *packet = ts->packet; - unsigned Rt = 1; - u16 x, y; - int cal_x,cal_y; - /* xpt2046_rx_val() did in-place conversion (including byteswap) from - * on-the-wire format as part of debouncing to get stable readings. - */ - x = packet->tc.x; - y = packet->tc.y; - - xpt2046printk("***>%s:x=%d,y=%d\n",__FUNCTION__,x,y); - - /* range filtering */ - if (x == MAX_12BIT) - x = 0; - - /* Sample found inconsistent by debouncing or pressure is beyond - * the maximum. Don't report it to user space, repeat at least - * once more the measurement - */ - if (packet->tc.ignore) { - - xpt2046printk("***>%s:ignored=%d\n",__FUNCTION__,packet->tc.ignore); - - hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), - HRTIMER_MODE_REL); - return; - } - - /* Maybe check the pendown state before reporting. This discards - * false readings when the pen is lifted. - */ - if (ts->penirq_recheck_delay_usecs) { - udelay(ts->penirq_recheck_delay_usecs); - if (!get_pendown_state(ts)) - { - xpt2046printk("***>%s:get_pendown_state(ts)==0,discard false reading\n",__FUNCTION__); - Rt = 0; - } - } - - /* NOTE: We can't rely on the pressure to determine the pen down - * state, even this controller has a pressure sensor. The pressure - * value can fluctuate for quite a while after lifting the pen and - * in some cases may not even settle at the expected value. - * - * The only safe way to check for the pen up condition is in the - * timer by reading the pen signal state (it's a GPIO _and_ IRQ). - */ - if (Rt) { - struct input_dev *input = ts->input; - - TouchPanelCalibrateAPoint(x, y, &cal_x, &cal_y); - - cal_x = cal_x / 4; - cal_y = cal_y / 4; - gADPoint.x = x; - gADPoint.y = y; - - if (ts->swap_xy) - swap(cal_x, cal_y); - - if(xpt2046_verifyAndConvert(ts,cal_x,cal_y,&cal_x,&cal_y)) - { - xpt2046printk("***>%s:xpt2046_verifyAndConvert fail\n",__FUNCTION__); - goto out; - } - - if (!ts->pendown) { - input_report_key(input, BTN_TOUCH, 1); - ts->pendown = 1; - xpt2046printk("***>%s:input_report_key(pen down)\n",__FUNCTION__); - } - - input_report_abs(input, ABS_X, cal_x); - input_report_abs(input, ABS_Y, cal_y); - - input_sync(input); - xpt2046printk("***>%s:input_report_abs(%4d/%4d)\n",__FUNCTION__,cal_x, cal_y); - } -out: - hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), - HRTIMER_MODE_REL); -} - -static int xpt2046_debounce(void *xpt, int data_idx, int *val) -{ - struct xpt2046 *ts = xpt; - static int average_val[2]; - - - xpt2046printk("***>%s:%d,%d,%d,%d,%d,%d,%d,%d\n",__FUNCTION__, - data_idx,ts->last_read, - ts->read_cnt,ts->debounce_max, - abs(ts->last_read - *val),ts->debounce_tol, - ts->read_rep,ts->debounce_rep); - - /* discard the first sample. */ - //on info_it50, the top-left area(1cmx1cm top-left square ) is not responding cause the first sample is invalid, @sep 17th - if(!ts->read_cnt) - { - //udelay(100); - ts->read_cnt++; - return XPT2046_FILTER_REPEAT; - } - if(*val == 4095 || *val == 0) - { - ts->read_cnt = 0; - ts->last_read = 0; - memset(average_val,0,sizeof(average_val)); - xpt2046printk("***>%s:*val == 4095 || *val == 0\n",__FUNCTION__); - return XPT2046_FILTER_IGNORE; - } - - - if (ts->read_cnt==1 || (abs(ts->last_read - *val) > ts->debounce_tol)) { - /* Start over collecting consistent readings. */ - ts->read_rep = 1; - average_val[data_idx] = *val; - /* Repeat it, if this was the first read or the read - * wasn't consistent enough. */ - if (ts->read_cnt < ts->debounce_max) { - ts->last_read = *val; - ts->read_cnt++; - return XPT2046_FILTER_REPEAT; - } else { - /* Maximum number of debouncing reached and still - * not enough number of consistent readings. Abort - * the whole sample, repeat it in the next sampling - * period. - */ - ts->read_cnt = 0; - ts->last_read = 0; - memset(average_val,0,sizeof(average_val)); - xpt2046printk("***>%s:XPT2046_FILTER_IGNORE\n",__FUNCTION__); - return XPT2046_FILTER_IGNORE; - } - } - else { - average_val[data_idx] += *val; - - if (++ts->read_rep >= ts->debounce_rep) { - /* Got a good reading for this coordinate, - * go for the next one. */ - ts->read_cnt = 0; - ts->read_rep = 0; - ts->last_read = 0; - *val = average_val[data_idx]/(ts->debounce_rep); - return XPT2046_FILTER_OK; - } else { - /* Read more values that are consistent. */ - ts->read_cnt++; - - return XPT2046_FILTER_REPEAT; - } - } -} - -static int xpt2046_no_filter(void *xpt, int data_idx, int *val) -{ - return XPT2046_FILTER_OK; -} - -static void xpt2046_rx_val(void *xpt) -{ - struct xpt2046 *ts = xpt; - struct xpt2046_packet *packet = ts->packet; - struct spi_message *m; - struct spi_transfer *t; - int val; - int action; - int status; - - m = &ts->msg[ts->msg_idx]; - t = list_entry(m->transfers.prev, struct spi_transfer, transfer_list); - - /* adjust: on-wire is a must-ignore bit, a BE12 value, then padding; - * built from two 8 bit values written msb-first. - */ - val = (be16_to_cpup((__be16 *)t->rx_buf) >> 3) & 0x0fff; - - xpt2046printk("***>%s:value=%d\n",__FUNCTION__,val); - - action = ts->filter(ts->filter_data, ts->msg_idx, &val); - switch (action) { - case XPT2046_FILTER_REPEAT: - break; - case XPT2046_FILTER_IGNORE: - packet->tc.ignore = 1; - /* Last message will contain xpt2046_rx() as the - * completion function. - */ - m = ts->last_msg; - break; - case XPT2046_FILTER_OK: - *(u16 *)t->rx_buf = val; - packet->tc.ignore = 0; - m = &ts->msg[++ts->msg_idx]; - break; - default: - BUG(); - } - ts->wait_for_sync(); - status = spi_async(ts->spi, m); - if (status) - dev_err(&ts->spi->dev, "spi_async --> %d\n", - status); -} - -static enum hrtimer_restart xpt2046_timer(struct hrtimer *handle) -{ - struct xpt2046 *ts = container_of(handle, struct xpt2046, timer); - int status = 0; - - spin_lock(&ts->lock); - - if (unlikely(!get_pendown_state(ts) || - device_suspended(&ts->spi->dev))) { - if (ts->pendown) { - struct input_dev *input = ts->input; - input_report_key(input, BTN_TOUCH, 0); - input_sync(input); - - ts->pendown = 0; - - xpt2046printk("***>%s:input_report_key(The touchscreen up)\n",__FUNCTION__); - } - - /* measurement cycle ended */ - if (!device_suspended(&ts->spi->dev)) { - xpt2046printk("***>%s:device_suspended==0\n",__FUNCTION__); - ts->irq_disabled = 0; - enable_irq(ts->spi->irq); - } - ts->pending = 0; - } else { - /* pen is still down, continue with the measurement */ - xpt2046printk("***>%s:pen is still down, continue with the measurement\n",__FUNCTION__); - ts->msg_idx = 0; - ts->wait_for_sync(); - status = spi_async(ts->spi, &ts->msg[0]); - if (status) - dev_err(&ts->spi->dev, "spi_async --> %d\n", status); - } - - spin_unlock(&ts->lock); - return HRTIMER_NORESTART; -} - -static irqreturn_t xpt2046_irq(int irq, void *handle) -{ - struct xpt2046 *ts = handle; - unsigned long flags; - - xpt2046printk("***>%s.....%s.....%d\n",__FILE__,__FUNCTION__,__LINE__); - - spin_lock_irqsave(&ts->lock, flags); - - if (likely(get_pendown_state(ts))) { - if (!ts->irq_disabled) { - /* The ARM do_simple_IRQ() dispatcher doesn't act - * like the other dispatchers: it will report IRQs - * even after they've been disabled. We work around - * that here. (The "generic irq" framework may help...) - */ - ts->irq_disabled = 1; - disable_irq_nosync(ts->spi->irq); - ts->pending = 1; - hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_DELAY), - HRTIMER_MODE_REL); - } - } - spin_unlock_irqrestore(&ts->lock, flags); - - return IRQ_HANDLED; -} - -/*--------------------------------------------------------------------------*/ - -/* Must be called with ts->lock held */ -static void xpt2046_disable(struct xpt2046 *ts) -{ - if (ts->disabled) - return; - - ts->disabled = 1; - - /* are we waiting for IRQ, or polling? */ - if (!ts->pending) { - ts->irq_disabled = 1; - disable_irq(ts->spi->irq); - } else { - /* the timer will run at least once more, and - * leave everything in a clean state, IRQ disabled - */ - while (ts->pending) { - spin_unlock_irq(&ts->lock); - msleep(1); - spin_lock_irq(&ts->lock); - } - } - - /* we know the chip's in lowpower mode since we always - * leave it that way after every request - */ -} - -/* Must be called with ts->lock held */ -static void xpt2046_enable(struct xpt2046 *ts) -{ - if (!ts->disabled) - return; - - ts->disabled = 0; - ts->irq_disabled = 0; - enable_irq(ts->spi->irq); -} - -static int xpt2046_pSuspend(struct xpt2046 *ts) -{ - spin_lock_irq(&ts->lock); - - ts->is_suspended = 1; - xpt2046_disable(ts); - - spin_unlock_irq(&ts->lock); - - return 0; -} - -static int xpt2046_pResume(struct xpt2046 *ts) -{ - spin_lock_irq(&ts->lock); - - ts->is_suspended = 0; - xpt2046_enable(ts); - - spin_unlock_irq(&ts->lock); - - return 0; -} - -#if !defined(CONFIG_HAS_EARLYSUSPEND) -static int xpt2046_suspend(struct spi_device *spi, pm_message_t message) -{ - struct xpt2046 *ts = dev_get_drvdata(&spi->dev); - - printk("xpt2046_suspend\n"); - - xpt2046_pSuspend(ts); - - return 0; -} - -static int xpt2046_resume(struct spi_device *spi) -{ - struct xpt2046 *ts = dev_get_drvdata(&spi->dev); - - printk("xpt2046_resume\n"); - - xpt2046_pResume(ts); - - return 0; -} - -#elif defined(CONFIG_HAS_EARLYSUSPEND) -static void xpt2046_early_suspend(struct early_suspend *h) -{ - struct xpt2046 *ts; - ts = container_of(h, struct xpt2046, early_suspend); - - printk("xpt2046_suspend early\n"); - - xpt2046_pSuspend(ts); - - return; -} - -static void xpt2046_late_resume(struct early_suspend *h) -{ - struct xpt2046 *ts; - ts = container_of(h, struct xpt2046, early_suspend); - - printk("xpt2046_resume late\n"); - - xpt2046_pResume(ts); - - return; -} -#endif - -static int __devinit setup_pendown(struct spi_device *spi, struct xpt2046 *ts) -{ - struct xpt2046_platform_data *pdata = spi->dev.platform_data; - int err; - - /* REVISIT when the irq can be triggered active-low, or if for some - * reason the touchscreen isn't hooked up, we don't need to access - * the pendown state. - */ - if (!pdata->get_pendown_state && !gpio_is_valid(pdata->gpio_pendown)) { - dev_err(&spi->dev, "no get_pendown_state nor gpio_pendown?\n"); - return -EINVAL; - } - - if (pdata->get_pendown_state) { - ts->get_pendown_state = pdata->get_pendown_state; - return 0; - } - - if (pdata->io_init) { - err = pdata->io_init(); - if (err) - dev_err(&spi->dev, "xpt2046 io_init fail\n"); - } - - ts->gpio_pendown = pdata->gpio_pendown; - strcpy(ts->pendown_iomux_name,pdata->pendown_iomux_name); - ts->pendown_iomux_mode = pdata->pendown_iomux_mode; - - rk29_mux_api_set(ts->pendown_iomux_name,pdata->pendown_iomux_mode); - err = gpio_request(pdata->gpio_pendown, "xpt2046_pendown"); - if (err) { - dev_err(&spi->dev, "failed to request pendown GPIO%d\n", - pdata->gpio_pendown); - return err; - } - - err = gpio_pull_updown(pdata->gpio_pendown, GPIOPullUp); - if (err) { - dev_err(&spi->dev, "failed to pullup pendown GPIO%d\n", - pdata->gpio_pendown); - return err; - } - ts->gpio_pendown = pdata->gpio_pendown; - return 0; -} - -static int __devinit xpt2046_probe(struct spi_device *spi) -{ - struct xpt2046 *ts; - struct xpt2046_packet *packet; - struct input_dev *input_dev; - struct xpt2046_platform_data *pdata = spi->dev.platform_data; - struct spi_message *m; - struct spi_transfer *x; - int vref; - int err; - - if (!spi->irq) { - dev_dbg(&spi->dev, "no IRQ?\n"); - return -ENODEV; - } - else{ - spi->irq = gpio_to_irq(spi->irq); - dev_dbg(&spi->dev, "no IRQ?\n"); - } - - if (!pdata) { - dev_err(&spi->dev, "empty platform_data\n"); - return -EFAULT; - } - - /* don't exceed max specified sample rate */ - if (spi->max_speed_hz > (125000 * SAMPLE_BITS)) { - dev_dbg(&spi->dev, "f(sample) %d KHz?\n", - (spi->max_speed_hz/SAMPLE_BITS)/1000); - return -EINVAL; - } - - /* We'd set TX wordsize 8 bits and RX wordsize to 13 bits ... except - * that even if the hardware can do that, the SPI controller driver - * may not. So we stick to very-portable 8 bit words, both RX and TX. - */ - spi->bits_per_word = 8; - spi->mode = SPI_MODE_0; - err = spi_setup(spi); - if (err < 0) - return err; - - ts = kzalloc(sizeof(struct xpt2046), GFP_KERNEL); - packet = kzalloc(sizeof(struct xpt2046_packet), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!ts || !packet || !input_dev) { - err = -ENOMEM; - goto err_free_mem; - } - - dev_set_drvdata(&spi->dev, ts); - - ts->packet = packet; - ts->spi = spi; - ts->input = input_dev; - ts->swap_xy = pdata->swap_xy; - - hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - ts->timer.function = xpt2046_timer; - - spin_lock_init(&ts->lock); - - ts->model = pdata->model ? : 2046; - - if (pdata->filter != NULL) { - if (pdata->filter_init != NULL) { - err = pdata->filter_init(pdata, &ts->filter_data); - if (err < 0) - goto err_free_mem; - } - ts->filter = pdata->filter; - ts->filter_cleanup = pdata->filter_cleanup; - } else if (pdata->debounce_max) { - ts->debounce_max = pdata->debounce_max; - if (ts->debounce_max < pdata->debounce_rep) - ts->debounce_max = pdata->debounce_rep; - ts->debounce_tol = pdata->debounce_tol; - ts->debounce_rep = pdata->debounce_rep; - ts->filter = xpt2046_debounce; - ts->filter_data = ts; - } else - ts->filter = xpt2046_no_filter; - - err = setup_pendown(spi, ts); - if (err) - goto err_cleanup_filter; - - if (pdata->penirq_recheck_delay_usecs) - ts->penirq_recheck_delay_usecs = - pdata->penirq_recheck_delay_usecs; - - ts->wait_for_sync = pdata->wait_for_sync ? : null_wait_for_sync; - ts->x_min = pdata->x_min; - ts->x_max = pdata->x_max; - ts->y_min = pdata->y_min; - ts->y_max = pdata->y_max; - - - ts->touch_virtualkey_length = pdata->touch_virtualkey_length; - - snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&spi->dev)); - snprintf(ts->name, sizeof(ts->name), "xpt%d-touchscreen", ts->model); - - input_dev->name = ts->name; - input_dev->phys = ts->phys; - input_dev->dev.parent = &spi->dev; - - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); - input_set_abs_params(input_dev, ABS_X, - ts->x_min ? : 0, - ts->x_max ? : MAX_12BIT, - 0, 0); - input_set_abs_params(input_dev, ABS_Y, - ts->y_min ? : 0, - ts->y_max ? : MAX_12BIT, - 0, 0); - - vref = pdata->keep_vref_on; - - tp_calib_iface_init(pdata->screen_x,pdata->screen_y,pdata->uncali_x_default,pdata->uncali_y_default); - /* set up the transfers to read touchscreen state; this assumes we - * use formula #2 for pressure, not #3. - */ - m = &ts->msg[0]; - x = ts->xfer; - - spi_message_init(m); - - /* y- still on; turn on only y+ (and ADC) */ - packet->read_y = READ_Y(vref); - x->tx_buf = &packet->read_y; - x->len = 1; - spi_message_add_tail(x, m); - - x++; - x->rx_buf = &packet->tc.y; - x->len = 2; - spi_message_add_tail(x, m); - - m->complete = xpt2046_rx_val; - m->context = ts; - - m++; - spi_message_init(m); - - /* turn y- off, x+ on, then leave in lowpower */ - x++; - packet->read_x = READ_X(vref); - x->tx_buf = &packet->read_x; - x->len = 1; - spi_message_add_tail(x, m); - - x++; - x->rx_buf = &packet->tc.x; - x->len = 2; - spi_message_add_tail(x, m); - - m->complete = xpt2046_rx_val; - m->context = ts; - - /* power down */ - m++; - spi_message_init(m); - - x++; - packet->pwrdown = PWRDOWN; - x->tx_buf = &packet->pwrdown; - x->len = 1; - spi_message_add_tail(x, m); - - x++; - x->rx_buf = &packet->dummy; - x->len = 2; - CS_CHANGE(*x); - spi_message_add_tail(x, m); - - m->complete = xpt2046_rx; - m->context = ts; - - ts->last_msg = m; - - if (request_irq(spi->irq, xpt2046_irq, IRQF_TRIGGER_FALLING, - spi->dev.driver->name, ts)) { - xpt2046printk("%s:trying pin change workaround on irq %d\n",__FUNCTION__,spi->irq); - err = request_irq(spi->irq, xpt2046_irq, - IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, - spi->dev.driver->name, ts); - if (err) { - dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq); - goto err_free_gpio; - } - } - xpt2046printk("***>%s:touchscreen irq %d\n",__FUNCTION__,spi->irq); - - /* take a first sample, leaving nPENIRQ active and vREF off; avoid - * the touchscreen, in case it's not connected. - */ - xpt2046_read12_dfr(&spi->dev,READ_X(1)); - - err = input_register_device(input_dev); - if (err) - goto err_remove_attr_group; - -#ifdef CONFIG_HAS_EARLYSUSPEND - ts->early_suspend.suspend = xpt2046_early_suspend; - ts->early_suspend.resume = xpt2046_late_resume; - ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; - register_early_suspend(&ts->early_suspend); -#endif - - xpt2046printk("xpt2046_ts: driver initialized\n"); - return 0; - - err_remove_attr_group: - free_irq(spi->irq, ts); - err_free_gpio: - if (ts->gpio_pendown != -1) - gpio_free(ts->gpio_pendown); - err_cleanup_filter: - if (ts->filter_cleanup) - ts->filter_cleanup(ts->filter_data); - err_free_mem: - input_free_device(input_dev); - kfree(packet); - kfree(ts); - return err; -} - - -static int __devexit xpt2046_remove(struct spi_device *spi) -{ - struct xpt2046 *ts = dev_get_drvdata(&spi->dev); - - input_unregister_device(ts->input); - -#if !defined(CONFIG_HAS_EARLYSUSPEND) - xpt2046_suspend(spi, PMSG_SUSPEND); -#elif defined(CONFIG_HAS_EARLYSUSPEND) - xpt2046_early_suspend(&ts->early_suspend); - unregister_early_suspend(&ts->early_suspend); -#endif - - free_irq(ts->spi->irq, ts); - /* suspend left the IRQ disabled */ - enable_irq(ts->spi->irq); - - if (ts->gpio_pendown != -1) - gpio_free(ts->gpio_pendown); - - if (ts->filter_cleanup) - ts->filter_cleanup(ts->filter_data); - - kfree(ts->packet); - kfree(ts); - - tp_calib_iface_exit(); - - dev_dbg(&spi->dev, "unregistered touchscreen\n"); - return 0; -} - -static struct spi_driver xpt2046_driver = { - .driver = { - .name = "xpt2046_ts", - .bus = &spi_bus_type, - .owner = THIS_MODULE, - }, - .probe = xpt2046_probe, - .remove = __devexit_p(xpt2046_remove), -#ifndef CONFIG_HAS_EARLYSUSPEND - .suspend = xpt2046_suspend, - .resume = xpt2046_resume, -#endif -}; - -static int __init xpt2046_init(void) -{ - int ret; - gADPoint.x = 0; - gADPoint.y = 0; - - xpt2046printk("Touch panel drive XPT2046 driver init...\n"); - ret = spi_register_driver(&xpt2046_driver); - if (ret) - { - printk("Register XPT2046 driver failed.\n"); - return ret; - } - - return 0; - -} - - -static void __exit xpt2046_exit(void) -{ - xpt2046printk("Touch panel drive XPT2046 driver exit...\n"); - spi_unregister_driver(&xpt2046_driver); -} -module_init(xpt2046_init); -module_exit(xpt2046_exit); - -MODULE_DESCRIPTION("rk29xx spi xpt2046 TouchScreen Driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("spi:xpt2046"); diff --git a/drivers/input/touchscreen/xpt2046_cbn_ts.h b/drivers/input/touchscreen/xpt2046_cbn_ts.h deleted file mode 100755 index d2b30bd494b0..000000000000 --- a/drivers/input/touchscreen/xpt2046_cbn_ts.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * drivers/input/touchscreen/xpt2046_cbn_ts.h - * - * Copyright (C) 2010 ROCKCHIP, 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. - */ - -#ifndef __DRIVERS_TOUCHSCREEN_XPT2046_CBN_TS_H -#define __DRIVERS_TOUCHSCREEN_XPT2046_CBN_TS_H - -#define IOMUX_NAME_SIZE 20 - -enum xpt2046_filter { - XPT2046_FILTER_OK, - XPT2046_FILTER_REPEAT, - XPT2046_FILTER_IGNORE, -}; - -struct xpt2046_platform_data { - u16 model; /* 2046. */ - bool keep_vref_on; /* set to keep vref on for differential - * measurements as well */ - bool swap_xy; /* swap x and y axes */ - - /* If set to non-zero, after samples are taken this delay is applied - * and penirq is rechecked, to help avoid false events. This value - * is affected by the material used to build the touch layer. - */ - u16 penirq_recheck_delay_usecs; - - u16 x_min, x_max; - u16 y_min, y_max; - - u16 debounce_max; /* max number of additional readings - * per sample */ - u16 debounce_tol; /* tolerance used for filtering */ - u16 debounce_rep; /* additional consecutive good readings - * required after the first two */ - int gpio_pendown; /* the GPIO used to decide the pendown - * state if get_pendown_state == NULL - */ - char pendown_iomux_name[IOMUX_NAME_SIZE]; - int pendown_iomux_mode; - int touch_virtualkey_length; - int screen_x[5]; - int screen_y[5]; - int uncali_x_default[5]; - int uncali_y_default[5]; - int (*get_pendown_state)(void); - int (*filter_init) (struct xpt2046_platform_data *pdata, - void **filter_data); - int (*filter) (void *filter_data, int data_idx, int *val); - void (*filter_cleanup)(void *filter_data); - void (*wait_for_sync)(void); - int (* io_init)(void); - int (* io_deinit)(void); -}; -#endif diff --git a/drivers/input/touchscreen/xpt2046_ts.c b/drivers/input/touchscreen/xpt2046_ts.c deleted file mode 100755 index 418a863f5198..000000000000 --- a/drivers/input/touchscreen/xpt2046_ts.c +++ /dev/null @@ -1,1032 +0,0 @@ -/* - * drivers/input/touchscreen/xpt2046_ts.c - driver for rk29 spi xpt2046 device and console - * - * Copyright (C) 2011 ROCKCHIP, 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_HAS_EARLYSUSPEND -#include -#endif -#include "xpt2046_ts.h" - -/* - * This code has been heavily tested on a Nokia 770, and lightly - * tested on other xpt2046 devices (OSK/Mistral, Lubbock). - * TSC2046 is just newer xpt2046 silicon. - * Support for ads7843 tested on Atmel at91sam926x-EK. - * Support for ads7845 has only been stubbed in. - * - * IRQ handling needs a workaround because of a shortcoming in handling - * edge triggered IRQs on some platforms like the OMAP1/2. These - * platforms don't handle the ARM lazy IRQ disabling properly, thus we - * have to maintain our own SW IRQ disabled status. This should be - * removed as soon as the affected platform's IRQ handling is fixed. - * - * app note sbaa036 talks in more detail about accurate sampling... - * that ought to help in situations like LCDs inducing noise (which - * can also be helped by using synch signals) and more generally. - * This driver tries to utilize the measures described in the app - * note. The strength of filtering can be set in the board-* specific - * files. - */ -#define XPT2046_DEBUG 0 -#if XPT2046_DEBUG - #define xpt2046printk(msg...) printk(msg); -#else - #define xpt2046printk(msg...) -#endif - -#define TS_POLL_DELAY (10 * 1000000) /* ns delay before the first sample */ -#define TS_POLL_PERIOD (20 * 1000000) /* ns delay between samples */ - -/* this driver doesn't aim at the peak continuous sample rate */ -#define SAMPLE_BITS (8 /*cmd*/ + 16 /*sample*/ + 2 /* before, after */) - -struct ts_event { - /* For portability, we can't read 12 bit values using SPI (which - * would make the controller deliver them as native byteorder u16 - * with msbs zeroed). Instead, we read them as two 8-bit values, - * *** WHICH NEED BYTESWAPPING *** and range adjustment. - */ - u16 x; - u16 y; - int ignore; -}; - -/* - * We allocate this separately to avoid cache line sharing issues when - * driver is used with DMA-based SPI controllers (like atmel_spi) on - * systems where main memory is not DMA-coherent (most non-x86 boards). - */ -struct xpt2046_packet { - u8 read_x, read_y, pwrdown; - u16 dummy; /* for the pwrdown read */ - struct ts_event tc; -}; - -struct xpt2046 { - struct input_dev *input; - char phys[32]; - char name[32]; - char pendown_iomux_name[IOMUX_NAME_SIZE]; - struct spi_device *spi; - - u16 model; - u16 x_min, x_max; - u16 y_min, y_max; - u16 debounce_max; - u16 debounce_tol; - u16 debounce_rep; - u16 penirq_recheck_delay_usecs; - bool swap_xy; - - struct xpt2046_packet *packet; - - struct spi_transfer xfer[18]; - struct spi_message msg[5]; - struct spi_message *last_msg; - int msg_idx; - int read_cnt; - int read_rep; - int last_read; - int pendown_iomux_mode; - int touch_ad_top; - int touch_ad_bottom; - int touch_ad_left; - int touch_ad_right; - int touch_virtualkey_length; - spinlock_t lock; - struct hrtimer timer; - unsigned pendown:1; /* P: lock */ - unsigned pending:1; /* P: lock */ -// FIXME remove "irq_disabled" - unsigned irq_disabled:1; /* P: lock */ - unsigned disabled:1; - unsigned is_suspended:1; - - int (*filter)(void *data, int data_idx, int *val); - void *filter_data; - void (*filter_cleanup)(void *data); - int (*get_pendown_state)(void); - int gpio_pendown; - - void (*wait_for_sync)(void); -#ifdef CONFIG_HAS_EARLYSUSPEND - struct early_suspend early_suspend; -#endif -}; - -/* leave chip selected when we're done, for quicker re-select? */ -#if 0 -#define CS_CHANGE(xfer) ((xfer).cs_change = 1) -#else -#define CS_CHANGE(xfer) ((xfer).cs_change = 0) -#endif - -/*--------------------------------------------------------------------------*/ - -/* The xpt2046 has touchscreen and other sensors. - * Earlier xpt2046 chips are somewhat compatible. - */ -#define XPT2046_START (1 << 7) -#define XPT2046_A2A1A0_d_y (1 << 4) /* differential */ -#define XPT2046_A2A1A0_d_z1 (3 << 4) /* differential */ -#define XPT2046_A2A1A0_d_z2 (4 << 4) /* differential */ -#define XPT2046_A2A1A0_d_x (5 << 4) /* differential */ -#define XPT2046_A2A1A0_temp0 (0 << 4) /* non-differential */ -#define XPT2046_A2A1A0_vbatt (2 << 4) /* non-differential */ -#define XPT2046_A2A1A0_vaux (6 << 4) /* non-differential */ -#define XPT2046_A2A1A0_temp1 (7 << 4) /* non-differential */ -#define XPT2046_8_BIT (1 << 3) -#define XPT2046_12_BIT (0 << 3) -#define XPT2046_SER (1 << 2) /* non-differential */ -#define XPT2046_DFR (0 << 2) /* differential */ -#define XPT2046_PD10_PDOWN (0 << 0) /* lowpower mode + penirq */ -#define XPT2046_PD10_ADC_ON (1 << 0) /* ADC on */ -#define XPT2046_PD10_REF_ON (2 << 0) /* vREF on + penirq */ -#define XPT2046_PD10_ALL_ON (3 << 0) /* ADC + vREF on */ - -#define MAX_12BIT ((1<<12)-1) - -/* leave ADC powered up (disables penirq) between differential samples */ -#define READ_12BIT_DFR(x, adc, vref) (XPT2046_START | XPT2046_A2A1A0_d_ ## x \ - | XPT2046_12_BIT | XPT2046_DFR | \ - (adc ? XPT2046_PD10_ADC_ON : 0) | (vref ? XPT2046_PD10_REF_ON : 0)) - -#define READ_Y(vref) (READ_12BIT_DFR(y, 1, vref)) -#define READ_Z1(vref) (READ_12BIT_DFR(z1, 1, vref)) -#define READ_Z2(vref) (READ_12BIT_DFR(z2, 1, vref)) - -#define READ_X(vref) (READ_12BIT_DFR(x, 1, vref)) -#define PWRDOWN (READ_12BIT_DFR(y, 0, 0)) /* LAST */ - -/* single-ended samples need to first power up reference voltage; - * we leave both ADC and VREF powered - */ -#define READ_12BIT_SER(x) (XPT2046_START | XPT2046_A2A1A0_ ## x \ - | XPT2046_12_BIT | XPT2046_SER) - -#define REF_ON (READ_12BIT_DFR(x, 1, 1)) -#define REF_OFF (READ_12BIT_DFR(y, 0, 0)) - -/*--------------------------------------------------------------------------*/ -/* - * touchscreen sensors use differential conversions. - */ - -struct dfr_req { - u8 command; - u8 pwrdown; - u16 dummy; /* for the pwrdown read */ - __be16 sample; - struct spi_message msg; - struct spi_transfer xfer[4]; -}; - -static void xpt2046_enable(struct xpt2046 *ts); -static void xpt2046_disable(struct xpt2046 *ts); -static int xpt2046_verifyAndConvert(struct xpt2046 *ts,u16 adx, u16 ady,u16 *x, u16 *y) -{ - *x = ts->x_max * (ts->touch_ad_left - adx)/(ts->touch_ad_left - ts->touch_ad_right); - *y = ts->y_max * (ts->touch_ad_top - ady)/(ts->touch_ad_top - ts->touch_ad_bottom); - - xpt2046printk("%s:(%d/%d)\n",__FUNCTION__,*x, *y); - - if((*x< ts->x_min) || (*x > ts->x_max)) - return 1; - - if((*y< ts->y_min) || (*y > ts->y_max + ts->touch_virtualkey_length)) - return 1; - - - return 0; -} -static int device_suspended(struct device *dev) -{ - struct xpt2046 *ts = dev_get_drvdata(dev); - return ts->is_suspended || ts->disabled; -} - -static int xpt2046_read12_dfr(struct device *dev, unsigned command) -{ - struct spi_device *spi = to_spi_device(dev); - struct xpt2046 *ts = dev_get_drvdata(dev); - struct dfr_req *req = kzalloc(sizeof *req, GFP_KERNEL); - int status; - - if (!req) - return -ENOMEM; - - spi_message_init(&req->msg); - - /* take sample */ - req->command = (u8) command; - req->xfer[0].tx_buf = &req->command; - req->xfer[0].len = 1; - spi_message_add_tail(&req->xfer[0], &req->msg); - - req->xfer[1].rx_buf = &req->sample; - req->xfer[1].len = 2; - spi_message_add_tail(&req->xfer[1], &req->msg); - - /* converter in low power mode & enable PENIRQ */ - req->pwrdown= PWRDOWN; - req->xfer[2].tx_buf = &req->pwrdown; - req->xfer[2].len = 1; - spi_message_add_tail(&req->xfer[2], &req->msg); - - req->xfer[3].rx_buf = &req->dummy; - req->xfer[3].len = 2; - CS_CHANGE(req->xfer[3]); - spi_message_add_tail(&req->xfer[3], &req->msg); - - ts->irq_disabled = 1; - disable_irq(spi->irq); - status = spi_sync(spi, &req->msg); - ts->irq_disabled = 0; - enable_irq(spi->irq); - - if (status == 0) { - /* on-wire is a must-ignore bit, a BE12 value, then padding */ - status = be16_to_cpu(req->sample); - status = status >> 3; - status &= 0x0fff; - xpt2046printk("***>%s:status=%d\n",__FUNCTION__,status); - } - - kfree(req); - return status; -} - - - -/*--------------------------------------------------------------------------*/ - -static int get_pendown_state(struct xpt2046 *ts) -{ - if (ts->get_pendown_state) - return ts->get_pendown_state(); - - return !gpio_get_value(ts->gpio_pendown); -} - -static void null_wait_for_sync(void) -{ - -} - -/* - * PENIRQ only kicks the timer. The timer only reissues the SPI transfer, - * to retrieve touchscreen status. - * - * The SPI transfer completion callback does the real work. It reports - * touchscreen events and reactivates the timer (or IRQ) as appropriate. - */ -static void xpt2046_rx(void *xpt) -{ - struct xpt2046 *ts = xpt; - struct xpt2046_packet *packet = ts->packet; - unsigned Rt = 1; - u16 x, y; - - /* xpt2046_rx_val() did in-place conversion (including byteswap) from - * on-the-wire format as part of debouncing to get stable readings. - */ - x = packet->tc.x; - y = packet->tc.y; - - xpt2046printk("***>%s:x=%d,y=%d\n",__FUNCTION__,x,y); - - /* range filtering */ - if (x == MAX_12BIT) - x = 0; - - /* Sample found inconsistent by debouncing or pressure is beyond - * the maximum. Don't report it to user space, repeat at least - * once more the measurement - */ - if (packet->tc.ignore) { - - xpt2046printk("***>%s:ignored=%d\n",__FUNCTION__,packet->tc.ignore); - - hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), - HRTIMER_MODE_REL); - return; - } - - /* Maybe check the pendown state before reporting. This discards - * false readings when the pen is lifted. - */ - if (ts->penirq_recheck_delay_usecs) { - udelay(ts->penirq_recheck_delay_usecs); - if (!get_pendown_state(ts)) - { - xpt2046printk("***>%s:get_pendown_state(ts)==0,discard false reading\n",__FUNCTION__); - Rt = 0; - } - } - - /* NOTE: We can't rely on the pressure to determine the pen down - * state, even this controller has a pressure sensor. The pressure - * value can fluctuate for quite a while after lifting the pen and - * in some cases may not even settle at the expected value. - * - * The only safe way to check for the pen up condition is in the - * timer by reading the pen signal state (it's a GPIO _and_ IRQ). - */ - if (Rt) { - struct input_dev *input = ts->input; - - if (ts->swap_xy) - swap(x, y); - - if(xpt2046_verifyAndConvert(ts,x,y,&x,&y)) - { - xpt2046printk("***>%s:xpt2046_verifyAndConvert fail\n",__FUNCTION__); - goto out; - } - - if (!ts->pendown) { - input_report_key(input, BTN_TOUCH, 1); - ts->pendown = 1; - xpt2046printk("***>%s:input_report_key(pen down)\n",__FUNCTION__); - } - - input_report_abs(input, ABS_X, x); - input_report_abs(input, ABS_Y, y); - - input_sync(input); - xpt2046printk("***>%s:input_report_abs(%4d/%4d)\n",__FUNCTION__,x, y); - } -out: - hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), - HRTIMER_MODE_REL); -} - -static int xpt2046_debounce(void *xpt, int data_idx, int *val) -{ - struct xpt2046 *ts = xpt; - static int average_val[2]; - - - xpt2046printk("***>%s:%d,%d,%d,%d,%d,%d,%d,%d\n",__FUNCTION__, - data_idx,ts->last_read, - ts->read_cnt,ts->debounce_max, - abs(ts->last_read - *val),ts->debounce_tol, - ts->read_rep,ts->debounce_rep); - - /* discard the first sample. */ - //on info_it50, the top-left area(1cmx1cm top-left square ) is not responding cause the first sample is invalid, @sep 17th - if(!ts->read_cnt) - { - //udelay(100); - ts->read_cnt++; - return XPT2046_FILTER_REPEAT; - } - if(*val == 4095 || *val == 0) - { - ts->read_cnt = 0; - ts->last_read = 0; - memset(average_val,0,sizeof(average_val)); - xpt2046printk("***>%s:*val == 4095 || *val == 0\n",__FUNCTION__); - return XPT2046_FILTER_IGNORE; - } - - - if (ts->read_cnt==1 || (abs(ts->last_read - *val) > ts->debounce_tol)) { - /* Start over collecting consistent readings. */ - ts->read_rep = 1; - average_val[data_idx] = *val; - /* Repeat it, if this was the first read or the read - * wasn't consistent enough. */ - if (ts->read_cnt < ts->debounce_max) { - ts->last_read = *val; - ts->read_cnt++; - return XPT2046_FILTER_REPEAT; - } else { - /* Maximum number of debouncing reached and still - * not enough number of consistent readings. Abort - * the whole sample, repeat it in the next sampling - * period. - */ - ts->read_cnt = 0; - ts->last_read = 0; - memset(average_val,0,sizeof(average_val)); - xpt2046printk("***>%s:XPT2046_FILTER_IGNORE\n",__FUNCTION__); - return XPT2046_FILTER_IGNORE; - } - } - else { - average_val[data_idx] += *val; - - if (++ts->read_rep >= ts->debounce_rep) { - /* Got a good reading for this coordinate, - * go for the next one. */ - ts->read_cnt = 0; - ts->read_rep = 0; - ts->last_read = 0; - *val = average_val[data_idx]/(ts->debounce_rep); - return XPT2046_FILTER_OK; - } else { - /* Read more values that are consistent. */ - ts->read_cnt++; - - return XPT2046_FILTER_REPEAT; - } - } -} - -static int xpt2046_no_filter(void *xpt, int data_idx, int *val) -{ - return XPT2046_FILTER_OK; -} - -//#define spi_async(a,b) -static void xpt2046_rx_val(void *xpt) -{ - struct xpt2046 *ts = xpt; - struct xpt2046_packet *packet = ts->packet; - struct spi_message *m; - struct spi_transfer *t; - int val; - int action; - int status; - - m = &ts->msg[ts->msg_idx]; - t = list_entry(m->transfers.prev, struct spi_transfer, transfer_list); - - /* adjust: on-wire is a must-ignore bit, a BE12 value, then padding; - * built from two 8 bit values written msb-first. - */ - val = (be16_to_cpup((__be16 *)t->rx_buf) >> 3) & 0x0fff; - - xpt2046printk("***>%s:value=%d\n",__FUNCTION__,val); - - action = ts->filter(ts->filter_data, ts->msg_idx, &val); - switch (action) { - case XPT2046_FILTER_REPEAT: - break; - case XPT2046_FILTER_IGNORE: - packet->tc.ignore = 1; - /* Last message will contain xpt2046_rx() as the - * completion function. - */ - m = ts->last_msg; - break; - case XPT2046_FILTER_OK: - *(u16 *)t->rx_buf = val; - packet->tc.ignore = 0; - m = &ts->msg[++ts->msg_idx]; - break; - default: - BUG(); - } - ts->wait_for_sync(); - status = spi_async(ts->spi, m); - if (status) - dev_err(&ts->spi->dev, "spi_async --> %d\n", - status); -} - -static enum hrtimer_restart xpt2046_timer(struct hrtimer *handle) -{ - struct xpt2046 *ts = container_of(handle, struct xpt2046, timer); - int status = 0; - - spin_lock(&ts->lock); - - if (unlikely(!get_pendown_state(ts) || - device_suspended(&ts->spi->dev))) { - if (ts->pendown) { - struct input_dev *input = ts->input; - input_report_key(input, BTN_TOUCH, 0); - input_sync(input); - - ts->pendown = 0; - - xpt2046printk("***>%s:input_report_key(The touchscreen up)\n",__FUNCTION__); - } - - /* measurement cycle ended */ - if (!device_suspended(&ts->spi->dev)) { - xpt2046printk("***>%s:device_suspended==0\n",__FUNCTION__); - ts->irq_disabled = 0; - enable_irq(ts->spi->irq); - } - ts->pending = 0; - } else { - /* pen is still down, continue with the measurement */ - xpt2046printk("***>%s:pen is still down, continue with the measurement\n",__FUNCTION__); - ts->msg_idx = 0; - ts->wait_for_sync(); - status = spi_async(ts->spi, &ts->msg[0]); - if (status) - dev_err(&ts->spi->dev, "spi_async --> %d\n", status); - } - - spin_unlock(&ts->lock); - return HRTIMER_NORESTART; -} - -static irqreturn_t xpt2046_irq(int irq, void *handle) -{ - struct xpt2046 *ts = handle; - unsigned long flags; - - xpt2046printk("***>%s.....%s.....%d\n",__FILE__,__FUNCTION__,__LINE__); - - spin_lock_irqsave(&ts->lock, flags); - - if (likely(get_pendown_state(ts))) { - if (!ts->irq_disabled) { - /* The ARM do_simple_IRQ() dispatcher doesn't act - * like the other dispatchers: it will report IRQs - * even after they've been disabled. We work around - * that here. (The "generic irq" framework may help...) - */ - ts->irq_disabled = 1; - disable_irq_nosync(ts->spi->irq); - ts->pending = 1; - hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_DELAY), - HRTIMER_MODE_REL); - } - } - spin_unlock_irqrestore(&ts->lock, flags); - - return IRQ_HANDLED; -} - -/*--------------------------------------------------------------------------*/ - -/* Must be called with ts->lock held */ -static void xpt2046_disable(struct xpt2046 *ts) -{ - if (ts->disabled) - return; - - ts->disabled = 1; - - /* are we waiting for IRQ, or polling? */ - if (!ts->pending) { - ts->irq_disabled = 1; - disable_irq(ts->spi->irq); - } else { - /* the timer will run at least once more, and - * leave everything in a clean state, IRQ disabled - */ - while (ts->pending) { - spin_unlock_irq(&ts->lock); - msleep(1); - spin_lock_irq(&ts->lock); - } - } - - /* we know the chip's in lowpower mode since we always - * leave it that way after every request - */ -} - -/* Must be called with ts->lock held */ -static void xpt2046_enable(struct xpt2046 *ts) -{ - if (!ts->disabled) - return; - - ts->disabled = 0; - ts->irq_disabled = 0; - enable_irq(ts->spi->irq); -} - -static int xpt2046_pSuspend(struct xpt2046 *ts) -{ - spin_lock_irq(&ts->lock); - - ts->is_suspended = 1; - xpt2046_disable(ts); - - spin_unlock_irq(&ts->lock); - - return 0; -} - -static int xpt2046_pResume(struct xpt2046 *ts) -{ - spin_lock_irq(&ts->lock); - - ts->is_suspended = 0; - xpt2046_enable(ts); - - spin_unlock_irq(&ts->lock); - - return 0; -} - -#if !defined(CONFIG_HAS_EARLYSUSPEND) -static int xpt2046_suspend(struct spi_device *spi, pm_message_t message) -{ - struct xpt2046 *ts = dev_get_drvdata(&spi->dev); - - printk("xpt2046_suspend\n"); - - xpt2046_pSuspend(ts); - - return 0; -} - -static int xpt2046_resume(struct spi_device *spi) -{ - struct xpt2046 *ts = dev_get_drvdata(&spi->dev); - - printk("xpt2046_resume\n"); - - xpt2046_pResume(ts); - - return 0; -} - -#elif defined(CONFIG_HAS_EARLYSUSPEND) -static void xpt2046_early_suspend(struct early_suspend *h) -{ - struct xpt2046 *ts; - ts = container_of(h, struct xpt2046, early_suspend); - - printk("xpt2046_suspend early\n"); - - xpt2046_pSuspend(ts); - - return; -} - -static void xpt2046_late_resume(struct early_suspend *h) -{ - struct xpt2046 *ts; - ts = container_of(h, struct xpt2046, early_suspend); - - printk("xpt2046_resume late\n"); - - xpt2046_pResume(ts); - - return; -} -#endif - -static int __devinit setup_pendown(struct spi_device *spi, struct xpt2046 *ts) -{ - struct xpt2046_platform_data *pdata = spi->dev.platform_data; - int err; - - /* REVISIT when the irq can be triggered active-low, or if for some - * reason the touchscreen isn't hooked up, we don't need to access - * the pendown state. - */ - if (!pdata->get_pendown_state && !gpio_is_valid(pdata->gpio_pendown)) { - dev_err(&spi->dev, "no get_pendown_state nor gpio_pendown?\n"); - return -EINVAL; - } - - if (pdata->get_pendown_state) { - ts->get_pendown_state = pdata->get_pendown_state; - return 0; - } - - if (pdata->io_init) { - err = pdata->io_init(); - if (err) - dev_err(&spi->dev, "xpt2046 io_init fail\n"); - } - - ts->gpio_pendown = pdata->gpio_pendown; - strcpy(ts->pendown_iomux_name,pdata->pendown_iomux_name); - ts->pendown_iomux_mode = pdata->pendown_iomux_mode; - - rk29_mux_api_set(ts->pendown_iomux_name,pdata->pendown_iomux_mode); - err = gpio_request(pdata->gpio_pendown, "xpt2046_pendown"); - if (err) { - dev_err(&spi->dev, "failed to request pendown GPIO%d\n", - pdata->gpio_pendown); - return err; - } - - err = gpio_pull_updown(pdata->gpio_pendown, GPIOPullUp); - if (err) { - dev_err(&spi->dev, "failed to pullup pendown GPIO%d\n", - pdata->gpio_pendown); - return err; - } - ts->gpio_pendown = pdata->gpio_pendown; - return 0; -} - -static int __devinit xpt2046_probe(struct spi_device *spi) -{ - struct xpt2046 *ts; - struct xpt2046_packet *packet; - struct input_dev *input_dev; - struct xpt2046_platform_data *pdata = spi->dev.platform_data; - struct spi_message *m; - struct spi_transfer *x; - int vref; - int err; - - if (!spi->irq) { - dev_dbg(&spi->dev, "no IRQ?\n"); - return -ENODEV; - } - else{ - spi->irq = gpio_to_irq(spi->irq); - dev_dbg(&spi->dev, "no IRQ?\n"); - } - - if (!pdata) { - dev_err(&spi->dev, "empty platform_data\n"); - return -EFAULT; - } - - /* don't exceed max specified sample rate */ - if (spi->max_speed_hz > (125000 * SAMPLE_BITS)) { - dev_dbg(&spi->dev, "f(sample) %d KHz?\n", - (spi->max_speed_hz/SAMPLE_BITS)/1000); - return -EINVAL; - } - - /* We'd set TX wordsize 8 bits and RX wordsize to 13 bits ... except - * that even if the hardware can do that, the SPI controller driver - * may not. So we stick to very-portable 8 bit words, both RX and TX. - */ - spi->bits_per_word = 8; - spi->mode = SPI_MODE_0; - err = spi_setup(spi); - if (err < 0) - return err; - - ts = kzalloc(sizeof(struct xpt2046), GFP_KERNEL); - packet = kzalloc(sizeof(struct xpt2046_packet), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!ts || !packet || !input_dev) { - err = -ENOMEM; - goto err_free_mem; - } - - dev_set_drvdata(&spi->dev, ts); - - ts->packet = packet; - ts->spi = spi; - ts->input = input_dev; - ts->swap_xy = pdata->swap_xy; - - hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - ts->timer.function = xpt2046_timer; - - spin_lock_init(&ts->lock); - - ts->model = pdata->model ? : 2046; - - if (pdata->filter != NULL) { - if (pdata->filter_init != NULL) { - err = pdata->filter_init(pdata, &ts->filter_data); - if (err < 0) - goto err_free_mem; - } - ts->filter = pdata->filter; - ts->filter_cleanup = pdata->filter_cleanup; - } else if (pdata->debounce_max) { - ts->debounce_max = pdata->debounce_max; - if (ts->debounce_max < pdata->debounce_rep) - ts->debounce_max = pdata->debounce_rep; - ts->debounce_tol = pdata->debounce_tol; - ts->debounce_rep = pdata->debounce_rep; - ts->filter = xpt2046_debounce; - ts->filter_data = ts; - } else - ts->filter = xpt2046_no_filter; - - err = setup_pendown(spi, ts); - if (err) - goto err_cleanup_filter; - - if (pdata->penirq_recheck_delay_usecs) - ts->penirq_recheck_delay_usecs = - pdata->penirq_recheck_delay_usecs; - - ts->wait_for_sync = pdata->wait_for_sync ? : null_wait_for_sync; - ts->x_min = pdata->x_min; - ts->x_max = pdata->x_max; - ts->y_min = pdata->y_min; - ts->y_max = pdata->y_max; - - ts->touch_ad_top = pdata->touch_ad_top; - ts->touch_ad_bottom= pdata->touch_ad_bottom; - ts->touch_ad_left= pdata->touch_ad_left; - ts->touch_ad_right= pdata->touch_ad_right; - - ts->touch_virtualkey_length = pdata->touch_virtualkey_length; - - snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&spi->dev)); - snprintf(ts->name, sizeof(ts->name), "xpt%d-touchscreen", ts->model); - - input_dev->name = ts->name; - input_dev->phys = ts->phys; - input_dev->dev.parent = &spi->dev; - - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); - input_set_abs_params(input_dev, ABS_X, - ts->x_min ? : 0, - ts->x_max ? : MAX_12BIT, - 0, 0); - input_set_abs_params(input_dev, ABS_Y, - ts->y_min ? : 0, - ts->y_max ? : MAX_12BIT, - 0, 0); - - vref = pdata->keep_vref_on; - - /* set up the transfers to read touchscreen state; this assumes we - * use formula #2 for pressure, not #3. - */ - m = &ts->msg[0]; - x = ts->xfer; - - spi_message_init(m); - - /* y- still on; turn on only y+ (and ADC) */ - packet->read_y = READ_Y(vref); - x->tx_buf = &packet->read_y; - x->len = 1; - spi_message_add_tail(x, m); - - x++; - x->rx_buf = &packet->tc.y; - x->len = 2; - spi_message_add_tail(x, m); - - m->complete = xpt2046_rx_val; - m->context = ts; - - m++; - spi_message_init(m); - - /* turn y- off, x+ on, then leave in lowpower */ - x++; - packet->read_x = READ_X(vref); - x->tx_buf = &packet->read_x; - x->len = 1; - spi_message_add_tail(x, m); - - x++; - x->rx_buf = &packet->tc.x; - x->len = 2; - spi_message_add_tail(x, m); - - m->complete = xpt2046_rx_val; - m->context = ts; - - /* power down */ - m++; - spi_message_init(m); - - x++; - packet->pwrdown = PWRDOWN; - x->tx_buf = &packet->pwrdown; - x->len = 1; - spi_message_add_tail(x, m); - - x++; - x->rx_buf = &packet->dummy; - x->len = 2; - CS_CHANGE(*x); - spi_message_add_tail(x, m); - - m->complete = xpt2046_rx; - m->context = ts; - - ts->last_msg = m; - - if (request_irq(spi->irq, xpt2046_irq, IRQF_TRIGGER_FALLING, - spi->dev.driver->name, ts)) { - xpt2046printk("%s:trying pin change workaround on irq %d\n",__FUNCTION__,spi->irq); - err = request_irq(spi->irq, xpt2046_irq, - IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, - spi->dev.driver->name, ts); - if (err) { - dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq); - goto err_free_gpio; - } - } - xpt2046printk("***>%s:touchscreen irq %d\n",__FUNCTION__,spi->irq); - - /* take a first sample, leaving nPENIRQ active and vREF off; avoid - * the touchscreen, in case it's not connected. - */ - xpt2046_read12_dfr(&spi->dev,READ_X(1)); - - err = input_register_device(input_dev); - if (err) - goto err_remove_attr_group; - -#ifdef CONFIG_HAS_EARLYSUSPEND - ts->early_suspend.suspend = xpt2046_early_suspend; - ts->early_suspend.resume = xpt2046_late_resume; - ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; - register_early_suspend(&ts->early_suspend); -#endif - - xpt2046printk("xpt2046_ts: driver initialized\n"); - return 0; - - err_remove_attr_group: - free_irq(spi->irq, ts); - err_free_gpio: - if (ts->gpio_pendown != -1) - gpio_free(ts->gpio_pendown); - err_cleanup_filter: - if (ts->filter_cleanup) - ts->filter_cleanup(ts->filter_data); - err_free_mem: - input_free_device(input_dev); - kfree(packet); - kfree(ts); - return err; -} - -static int __devexit xpt2046_remove(struct spi_device *spi) -{ - struct xpt2046 *ts = dev_get_drvdata(&spi->dev); - - input_unregister_device(ts->input); - -#if !defined(CONFIG_HAS_EARLYSUSPEND) - xpt2046_suspend(spi, PMSG_SUSPEND); -#elif defined(CONFIG_HAS_EARLYSUSPEND) - xpt2046_early_suspend(&ts->early_suspend); - unregister_early_suspend(&ts->early_suspend); -#endif - - free_irq(ts->spi->irq, ts); - /* suspend left the IRQ disabled */ - enable_irq(ts->spi->irq); - - if (ts->gpio_pendown != -1) - gpio_free(ts->gpio_pendown); - - if (ts->filter_cleanup) - ts->filter_cleanup(ts->filter_data); - - kfree(ts->packet); - kfree(ts); - - dev_dbg(&spi->dev, "unregistered touchscreen\n"); - return 0; -} - -static struct spi_driver xpt2046_driver = { - .driver = { - .name = "xpt2046_ts", - .bus = &spi_bus_type, - .owner = THIS_MODULE, - }, - .probe = xpt2046_probe, - .remove = __devexit_p(xpt2046_remove), -#ifndef CONFIG_HAS_EARLYSUSPEND - .suspend = xpt2046_suspend, - .resume = xpt2046_resume, -#endif -}; -extern int spi_register_driver(struct spi_driver *sdrv); -static int __init xpt2046_init(void) -{ - return spi_register_driver(&xpt2046_driver); -} - - -static void __exit xpt2046_exit(void) -{ - xpt2046printk("Touch panel drive XPT2046 driver exit...\n"); - spi_unregister_driver(&xpt2046_driver); -} -module_init(xpt2046_init); -module_exit(xpt2046_exit); - -MODULE_DESCRIPTION("rk29xx spi xpt2046 TouchScreen Driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("spi:xpt2046"); diff --git a/drivers/input/touchscreen/xpt2046_ts.h b/drivers/input/touchscreen/xpt2046_ts.h deleted file mode 100755 index 1a04afec62d4..000000000000 --- a/drivers/input/touchscreen/xpt2046_ts.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * drivers/input/touchscreen/xpt2046_ts.h - * - * Copyright (C) 2010 ROCKCHIP, 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. - */ - -#ifndef __DRIVERS_TOUCHSCREEN_XPT2046_TS_H -#define __DRIVERS_TOUCHSCREEN_XPT2046_TS_H - -#define IOMUX_NAME_SIZE 40 - -enum xpt2046_filter { - XPT2046_FILTER_OK, - XPT2046_FILTER_REPEAT, - XPT2046_FILTER_IGNORE, -}; - -struct xpt2046_platform_data { - u16 model; /* 2046. */ - bool keep_vref_on; /* set to keep vref on for differential - * measurements as well */ - bool swap_xy; /* swap x and y axes */ - - /* If set to non-zero, after samples are taken this delay is applied - * and penirq is rechecked, to help avoid false events. This value - * is affected by the material used to build the touch layer. - */ - u16 penirq_recheck_delay_usecs; - - u16 x_min, x_max; - u16 y_min, y_max; - - u16 debounce_max; /* max number of additional readings - * per sample */ - u16 debounce_tol; /* tolerance used for filtering */ - u16 debounce_rep; /* additional consecutive good readings - * required after the first two */ - int gpio_pendown; /* the GPIO used to decide the pendown - * state if get_pendown_state == NULL - */ - char pendown_iomux_name[IOMUX_NAME_SIZE]; - int pendown_iomux_mode; - int touch_ad_top; - int touch_ad_bottom; - int touch_ad_left; - int touch_ad_right; - int touch_virtualkey_length; - int (*get_pendown_state)(void); - int (*filter_init) (struct xpt2046_platform_data *pdata, - void **filter_data); - int (*filter) (void *filter_data, int data_idx, int *val); - void (*filter_cleanup)(void *filter_data); - void (*wait_for_sync)(void); - int (* io_init)(void); - int (* io_deinit)(void); -}; -#endif diff --git a/drivers/input/touchscreen/xpt2046_ts_320X480.c b/drivers/input/touchscreen/xpt2046_ts_320X480.c deleted file mode 100755 index e2628e211976..000000000000 --- a/drivers/input/touchscreen/xpt2046_ts_320X480.c +++ /dev/null @@ -1,1016 +0,0 @@ -/* - * drivers/input/touchscreen/xpt2046_ts.c - driver for rk29 spi xpt2046 device and console - * - * Copyright (C) 2011 ROCKCHIP, 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "xpt2046_ts.h" - -/* - * This code has been heavily tested on a Nokia 770, and lightly - * tested on other xpt2046 devices (OSK/Mistral, Lubbock). - * TSC2046 is just newer xpt2046 silicon. - * Support for ads7843 tested on Atmel at91sam926x-EK. - * Support for ads7845 has only been stubbed in. - * - * IRQ handling needs a workaround because of a shortcoming in handling - * edge triggered IRQs on some platforms like the OMAP1/2. These - * platforms don't handle the ARM lazy IRQ disabling properly, thus we - * have to maintain our own SW IRQ disabled status. This should be - * removed as soon as the affected platform's IRQ handling is fixed. - * - * app note sbaa036 talks in more detail about accurate sampling... - * that ought to help in situations like LCDs inducing noise (which - * can also be helped by using synch signals) and more generally. - * This driver tries to utilize the measures described in the app - * note. The strength of filtering can be set in the board-* specific - * files. - */ -#define XPT2046_DEBUG 0 -#if XPT2046_DEBUG - #define xpt2046printk(msg...) printk(msg); -#else - #define xpt2046printk(msg...) -#endif -#define LCD_MAX_LENGTH 596 -#define LCD_MAX_WIDTH 320 -#define PT2046_TOUCH_AD_LEFT 256 -#define PT2046_TOUCH_AD_RIGHT 3870 -#define PT2046_TOUCH_AD_TOP 380 -#define PT2046_TOUCH_AD_BOTTOM 3658 -#define AD_TO_X(adx) (LCD_MAX_WIDTH * ( adx - PT2046_TOUCH_AD_TOP ) / ( PT2046_TOUCH_AD_BOTTOM - PT2046_TOUCH_AD_TOP )) -#define AD_TO_Y(ady) (LCD_MAX_LENGTH * ( ady - PT2046_TOUCH_AD_LEFT ) / ( PT2046_TOUCH_AD_RIGHT - PT2046_TOUCH_AD_LEFT )) - -#define TS_POLL_DELAY (10 * 1000000) /* ns delay before the first sample */ -#define TS_POLL_PERIOD (20 * 1000000) /* ns delay between samples */ - -#define DEBOUNCE_REPTIME 3 -/* this driver doesn't aim at the peak continuous sample rate */ -#define SAMPLE_BITS (8 /*cmd*/ + 16 /*sample*/ + 2 /* before, after */) - -struct ts_event { - /* For portability, we can't read 12 bit values using SPI (which - * would make the controller deliver them as native byteorder u16 - * with msbs zeroed). Instead, we read them as two 8-bit values, - * *** WHICH NEED BYTESWAPPING *** and range adjustment. - */ - u16 x; - u16 y; - int ignore; -}; - -/* - * We allocate this separately to avoid cache line sharing issues when - * driver is used with DMA-based SPI controllers (like atmel_spi) on - * systems where main memory is not DMA-coherent (most non-x86 boards). - */ -struct xpt2046_packet { - u8 read_x, read_y, pwrdown; - u16 dummy; /* for the pwrdown read */ - struct ts_event tc; -}; - -struct xpt2046 { - struct input_dev *input; - char phys[32]; - char name[32]; - - struct spi_device *spi; - - u16 model; - bool swap_xy; - - struct xpt2046_packet *packet; - - struct spi_transfer xfer[18]; - struct spi_message msg[5]; - struct spi_message *last_msg; - int msg_idx; - int read_cnt; - int read_rep; - int last_read; - - u16 debounce_max; - u16 debounce_tol; - u16 debounce_rep; - - u16 penirq_recheck_delay_usecs; - - spinlock_t lock; - struct hrtimer timer; - unsigned pendown:1; /* P: lock */ - unsigned pending:1; /* P: lock */ -// FIXME remove "irq_disabled" - unsigned irq_disabled:1; /* P: lock */ - unsigned disabled:1; - unsigned is_suspended:1; - - int (*filter)(void *data, int data_idx, int *val); - void *filter_data; - void (*filter_cleanup)(void *data); - int (*get_pendown_state)(void); - int gpio_pendown; - - void (*wait_for_sync)(void); -}; - -/* leave chip selected when we're done, for quicker re-select? */ -#if 0 -#define CS_CHANGE(xfer) ((xfer).cs_change = 1) -#else -#define CS_CHANGE(xfer) ((xfer).cs_change = 0) -#endif - -/*--------------------------------------------------------------------------*/ - -/* The xpt2046 has touchscreen and other sensors. - * Earlier xpt2046 chips are somewhat compatible. - */ -#define XPT2046_START (1 << 7) -#define XPT2046_A2A1A0_d_y (1 << 4) /* differential */ -#define XPT2046_A2A1A0_d_z1 (3 << 4) /* differential */ -#define XPT2046_A2A1A0_d_z2 (4 << 4) /* differential */ -#define XPT2046_A2A1A0_d_x (5 << 4) /* differential */ -#define XPT2046_A2A1A0_temp0 (0 << 4) /* non-differential */ -#define XPT2046_A2A1A0_vbatt (2 << 4) /* non-differential */ -#define XPT2046_A2A1A0_vaux (6 << 4) /* non-differential */ -#define XPT2046_A2A1A0_temp1 (7 << 4) /* non-differential */ -#define XPT2046_8_BIT (1 << 3) -#define XPT2046_12_BIT (0 << 3) -#define XPT2046_SER (1 << 2) /* non-differential */ -#define XPT2046_DFR (0 << 2) /* differential */ -#define XPT2046_PD10_PDOWN (0 << 0) /* lowpower mode + penirq */ -#define XPT2046_PD10_ADC_ON (1 << 0) /* ADC on */ -#define XPT2046_PD10_REF_ON (2 << 0) /* vREF on + penirq */ -#define XPT2046_PD10_ALL_ON (3 << 0) /* ADC + vREF on */ - -#define MAX_12BIT ((1<<12)-1) - -/* leave ADC powered up (disables penirq) between differential samples */ -#define READ_12BIT_DFR(x, adc, vref) (XPT2046_START | XPT2046_A2A1A0_d_ ## x \ - | XPT2046_12_BIT | XPT2046_DFR | \ - (adc ? XPT2046_PD10_ADC_ON : 0) | (vref ? XPT2046_PD10_REF_ON : 0)) - -#define READ_Y(vref) (READ_12BIT_DFR(y, 1, vref)) -#define READ_Z1(vref) (READ_12BIT_DFR(z1, 1, vref)) -#define READ_Z2(vref) (READ_12BIT_DFR(z2, 1, vref)) - -#define READ_X(vref) (READ_12BIT_DFR(x, 1, vref)) -#define PWRDOWN (READ_12BIT_DFR(y, 0, 0)) /* LAST */ - -/* single-ended samples need to first power up reference voltage; - * we leave both ADC and VREF powered - */ -#define READ_12BIT_SER(x) (XPT2046_START | XPT2046_A2A1A0_ ## x \ - | XPT2046_12_BIT | XPT2046_SER) - -#define REF_ON (READ_12BIT_DFR(x, 1, 1)) -#define REF_OFF (READ_12BIT_DFR(y, 0, 0)) - -/*--------------------------------------------------------------------------*/ -/* - * touchscreen sensors use differential conversions. - */ - -struct dfr_req { - u8 command; - u8 pwrdown; - u16 dummy; /* for the pwrdown read */ - __be16 sample; - struct spi_message msg; - struct spi_transfer xfer[4]; -}; - -//add by zhao -#define LEN_TO_PIX(x) (unsigned int)( 320 * (x) / 47 ) -#define KEY1_X 6.3 -#define KEY2_X 17.8 -#define KEY3_X 29.3 -#define KEY4_X 40.8 -#define KEY_RADIUS 4 - -#define KEY_TOP 511 -#define KEY_BOTTOM 567 - -#define KEY1_LEFT LEN_TO_PIX(KEY1_X - KEY_RADIUS) -#define KEY1_RIGHT LEN_TO_PIX(KEY1_X + KEY_RADIUS) -#define KEY2_LEFT LEN_TO_PIX(KEY2_X - KEY_RADIUS) -#define KEY2_RIGHT LEN_TO_PIX(KEY2_X + KEY_RADIUS) -#define KEY3_LEFT LEN_TO_PIX(KEY3_X - KEY_RADIUS) -#define KEY3_RIGHT LEN_TO_PIX(KEY3_X + KEY_RADIUS) -#define KEY4_LEFT LEN_TO_PIX(KEY4_X - KEY_RADIUS) -#define KEY4_RIGHT LEN_TO_PIX(KEY4_X + KEY_RADIUS) - - struct KeyInfo -{ - unsigned int left; - unsigned int right; - int key; - int status; - -}; - -static struct KeyInfo panel_key_info[]={ -{KEY1_LEFT, KEY1_RIGHT, KEY_HOME, 0}, -{KEY2_LEFT, KEY2_RIGHT, KEY_MENU, 0}, -{KEY3_LEFT, KEY3_RIGHT, KEY_BACK, 0}, -{KEY4_LEFT, KEY4_RIGHT, KEY_SEARCH, 0}, -}; -//end by zhao - -static void xpt2046_enable(struct xpt2046 *ts); -static void xpt2046_disable(struct xpt2046 *ts); - -static int device_suspended(struct device *dev) -{ - struct xpt2046 *ts = dev_get_drvdata(dev); - return ts->is_suspended || ts->disabled; -} - -static int xpt2046_read12_dfr(struct device *dev, unsigned command) -{ - struct spi_device *spi = to_spi_device(dev); - struct xpt2046 *ts = dev_get_drvdata(dev); - struct dfr_req *req = kzalloc(sizeof *req, GFP_KERNEL); - int status; - - if (!req) - return -ENOMEM; - - spi_message_init(&req->msg); - - /* take sample */ - req->command = (u8) command; - req->xfer[0].tx_buf = &req->command; - req->xfer[0].len = 1; - spi_message_add_tail(&req->xfer[0], &req->msg); - - req->xfer[1].rx_buf = &req->sample; - req->xfer[1].len = 2; - //xpt2046printk("-------------1 sample 0x%x,command=%x--------------------\n",req->sample,(u8)command); //add by zhao - spi_message_add_tail(&req->xfer[1], &req->msg); - - /* converter in low power mode & enable PENIRQ */ - req->pwrdown= PWRDOWN; - req->xfer[2].tx_buf = &req->pwrdown; - req->xfer[2].len = 1; - spi_message_add_tail(&req->xfer[2], &req->msg); - - req->xfer[3].rx_buf = &req->dummy; - req->xfer[3].len = 2; - CS_CHANGE(req->xfer[3]); - spi_message_add_tail(&req->xfer[3], &req->msg); - - ts->irq_disabled = 1; - disable_irq(spi->irq); - status = spi_sync(spi, &req->msg); - ts->irq_disabled = 0; - enable_irq(spi->irq); - //xpt2046printk("-------------2 sample 0x%x-----------------\n",req->sample); //add by zhao - if (status == 0) { - /* on-wire is a must-ignore bit, a BE12 value, then padding */ - status = be16_to_cpu(req->sample); - status = status >> 3; - status &= 0x0fff; - xpt2046printk("***>%s:status=%d\n",__FUNCTION__,status); - } - - kfree(req); - return status; -} - - - -/*--------------------------------------------------------------------------*/ - -static int get_pendown_state(struct xpt2046 *ts) -{ - if (ts->get_pendown_state) - return ts->get_pendown_state(); - - return !gpio_get_value(ts->gpio_pendown); -} - -static void null_wait_for_sync(void) -{ - -} - -/* - * PENIRQ only kicks the timer. The timer only reissues the SPI transfer, - * to retrieve touchscreen status. - * - * The SPI transfer completion callback does the real work. It reports - * touchscreen events and reactivates the timer (or IRQ) as appropriate. - */ - -static void xpt2046_rx(void *xpt) -{ - struct xpt2046 *ts = xpt; - struct xpt2046_platform_data *pdata = ts->spi->dev.platform_data; - struct xpt2046_packet *packet = ts->packet; - unsigned Rt = 1; - u16 x, y; - u8 i; - /* xpt2046_rx_val() did in-place conversion (including byteswap) from - * on-the-wire format as part of debouncing to get stable readings. - */ - x = packet->tc.x; - y = packet->tc.y; - - xpt2046printk("***>%s:x=%d,y=%d\n",__FUNCTION__,x,y); - - /* range filtering */ - if (x == MAX_12BIT) - x = 0; - - /* Sample found inconsistent by debouncing or pressure is beyond - * the maximum. Don't report it to user space, repeat at least - * once more the measurement - */ - if (packet->tc.ignore) { - - xpt2046printk("***>%s:ignored=%d\n",__FUNCTION__,packet->tc.ignore); - - hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), - HRTIMER_MODE_REL); - return; - } - - /* Maybe check the pendown state before reporting. This discards - * false readings when the pen is lifted. - */ - if (ts->penirq_recheck_delay_usecs) { - udelay(ts->penirq_recheck_delay_usecs); - if (!get_pendown_state(ts)) - { - xpt2046printk("***>%s:get_pendown_state(ts)==0,discard false reading\n",__FUNCTION__); - Rt = 0; - } - } - - /* NOTE: We can't rely on the pressure to determine the pen down - * state, even this controller has a pressure sensor. The pressure - * value can fluctuate for quite a while after lifting the pen and - * in some cases may not even settle at the expected value. - * - * The only safe way to check for the pen up condition is in the - * timer by reading the pen signal state (it's a GPIO _and_ IRQ). - */ - if (Rt) { - struct input_dev *input = ts->input; -/* if (!ts->pendown) { - input_report_key(input, BTN_TOUCH, 1); - ts->pendown = 1; - xpt2046printk("***>%s:input_report_key(pen down)\n",__FUNCTION__); - } -*/ - x = AD_TO_X(x); - y = AD_TO_Y(y); - - if (ts->swap_xy) - swap(x, y); - - //add by zhao - if ((y > KEY_TOP) && (y < KEY_BOTTOM)) - { - for (i = 0; i < ARRAY_SIZE(panel_key_info); i++) - { - if ((x > panel_key_info[i].left) && (x < panel_key_info[i].right)) - { - panel_key_info[i].status = 1; - input_report_key(input, panel_key_info[i].key,1); - input_sync(input); - xpt2046printk("***>%s:input_report_key(%2d)(%4d , %4d)\n",__FUNCTION__,panel_key_info[i].key, x, y); - } - } - - } - else if (y <= pdata->y_max) - { - if (!ts->pendown) { - input_report_key(input, BTN_TOUCH, 1); - ts->pendown = 1; - xpt2046printk("***>%s:input_report_key(pen down)\n",__FUNCTION__); - } - input_report_abs(input, ABS_X, x); - input_report_abs(input, ABS_Y, y); - input_sync(input); - xpt2046printk("***>%s:input_report_abs(%4d , %4d)\n",__FUNCTION__,x, y); - } - - } - - hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), - HRTIMER_MODE_REL); -} - -static int xpt2046_debounce(void *xpt, int data_idx, int *val) -{ - struct xpt2046 *ts = xpt; - static int average_val[2]; - - -/* xpt2046printk("***>%s:data_idx=%d,last_read=%d,read_cnt=%d,debounce_max=%d,last_read=%d,debounce_tol=%d,read_rep=%d,debounce_rep=%d\n",__FUNCTION__, - data_idx,ts->last_read, - ts->read_cnt,ts->debounce_max, - abs(ts->last_read - *val),ts->debounce_tol, - ts->read_rep,ts->debounce_rep); -*/ - if(*val == 4095 || *val == 0) - { - ts->read_cnt = 0; - ts->last_read = 0; - memset(average_val,0,sizeof(average_val)); - xpt2046printk("***>%s:*val == 4095 || *val == 0\n",__FUNCTION__); - return XPT2046_FILTER_IGNORE; - } - /* discard the first sample. */ - if(!ts->read_cnt) - { - ts->read_cnt++; - return XPT2046_FILTER_REPEAT; - } - - if (ts->read_cnt==1 || (abs(ts->last_read - *val) > ts->debounce_tol)) { - /* Start over collecting consistent readings. */ - ts->read_rep = 1; - average_val[data_idx] = *val; - /* Repeat it, if this was the first read or the read - * wasn't consistent enough. */ - if (ts->read_cnt < ts->debounce_max) { - ts->last_read = *val; - ts->read_cnt++; - return XPT2046_FILTER_REPEAT; - } else { - /* Maximum number of debouncing reached and still - * not enough number of consistent readings. Abort - * the whole sample, repeat it in the next sampling - * period. - */ - ts->read_cnt = 0; - ts->last_read = 0; - memset(average_val,0,sizeof(average_val)); - xpt2046printk("***>%s:XPT2046_FILTER_IGNORE\n",__FUNCTION__); - return XPT2046_FILTER_IGNORE; - } - } - else { - average_val[data_idx] += *val; - - if (++ts->read_rep >= ts->debounce_rep) { - /* Got a good reading for this coordinate, - * go for the next one. */ - ts->read_cnt = 0; - ts->read_rep = 0; - ts->last_read = 0; - *val = average_val[data_idx]/(ts->debounce_rep); - return XPT2046_FILTER_OK; - } else { - /* Read more values that are consistent. */ - ts->read_cnt++; - - return XPT2046_FILTER_REPEAT; - } - } -} - -static int xpt2046_no_filter(void *xpt, int data_idx, int *val) -{ - return XPT2046_FILTER_OK; -} - -static void xpt2046_rx_val(void *xpt) -{ - struct xpt2046 *ts = xpt; - struct xpt2046_packet *packet = ts->packet; - struct spi_message *m; - struct spi_transfer *t; - int val; - int action; - int status; - - m = &ts->msg[ts->msg_idx]; - t = list_entry(m->transfers.prev, struct spi_transfer, transfer_list); - - /* adjust: on-wire is a must-ignore bit, a BE12 value, then padding; - * built from two 8 bit values written msb-first. - */ - val = (be16_to_cpup((__be16 *)t->rx_buf) >> 3) & 0x0fff; - -// xpt2046printk("***>%s:value=%d, x=%d, y=%d, rx_buf=%d\n",__FUNCTION__,val,packet->tc.x,packet->tc.y,*(u16 *)t->rx_buf); - - action = ts->filter(ts->filter_data, ts->msg_idx, &val); - switch (action) { - case XPT2046_FILTER_REPEAT: - break; - case XPT2046_FILTER_IGNORE: - packet->tc.ignore = 1; - /* Last message will contain xpt2046_rx() as the - * completion function. - */ - m = ts->last_msg; - break; - case XPT2046_FILTER_OK: - *(u16 *)t->rx_buf = val; - packet->tc.ignore = 0; - m = &ts->msg[++ts->msg_idx]; - break; - default: - BUG(); - } - ts->wait_for_sync(); - status = spi_async(ts->spi, m); - if (status) - dev_err(&ts->spi->dev, "spi_async --> %d\n", - status); -} - -static enum hrtimer_restart xpt2046_timer(struct hrtimer *handle) -{ - struct xpt2046 *ts = container_of(handle, struct xpt2046, timer); - int status = 0; - int i; - - spin_lock(&ts->lock); - - if (unlikely(!get_pendown_state(ts) || - device_suspended(&ts->spi->dev))) { - //add by zhao - struct input_dev *input = ts->input; - for(i = 0; i < ARRAY_SIZE(panel_key_info); i++) - { - if (panel_key_info[i].status) - { - input_report_key(input, panel_key_info[i].key, 0); - panel_key_info[i].status = 0; - input_sync(input); - xpt2046printk("***>%s:input_report_key(KEY up)\n",__FUNCTION__); - } - } - - if (ts->pendown) { - input_report_key(input, BTN_TOUCH, 0); - input_sync(input); - ts->pendown = 0; - - xpt2046printk("***>%s:input_report_key(The touchscreen up)\n",__FUNCTION__); - } - - /* measurement cycle ended */ - if (!device_suspended(&ts->spi->dev)) { - xpt2046printk("***>%s:device_suspended==0\n",__FUNCTION__); - ts->irq_disabled = 0; - enable_irq(ts->spi->irq); - } - ts->pending = 0; - } else { - /* pen is still down, continue with the measurement */ - xpt2046printk("***>%s:pen is still down, continue with the measurement\n",__FUNCTION__); - ts->msg_idx = 0; - ts->wait_for_sync(); - status = spi_async(ts->spi, &ts->msg[0]); - if (status) - dev_err(&ts->spi->dev, "spi_async --> %d\n", status); - } - - spin_unlock(&ts->lock); - return HRTIMER_NORESTART; -} - -static irqreturn_t xpt2046_irq(int irq, void *handle) -{ - struct xpt2046 *ts = handle; - unsigned long flags; - xpt2046printk("\n-----------xpt2046_irq------------------\n"); - xpt2046printk("***>%s.....%s.....%d\n",__FILE__,__FUNCTION__,__LINE__); - - spin_lock_irqsave(&ts->lock, flags); - - if (likely(get_pendown_state(ts))) { - if (!ts->irq_disabled) { - /* The ARM do_simple_IRQ() dispatcher doesn't act - * like the other dispatchers: it will report IRQs - * even after they've been disabled. We work around - * that here. (The "generic irq" framework may help...) - */ - ts->irq_disabled = 1; - disable_irq_nosync(ts->spi->irq); - ts->pending = 1; - hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_DELAY), - HRTIMER_MODE_REL); - } - } - spin_unlock_irqrestore(&ts->lock, flags); - - return IRQ_HANDLED; -} - -/*--------------------------------------------------------------------------*/ - -/* Must be called with ts->lock held */ -static void xpt2046_disable(struct xpt2046 *ts) -{ - if (ts->disabled) - return; - - ts->disabled = 1; - - /* are we waiting for IRQ, or polling? */ - if (!ts->pending) { - ts->irq_disabled = 1; - disable_irq(ts->spi->irq); - } else { - /* the timer will run at least once more, and - * leave everything in a clean state, IRQ disabled - */ - while (ts->pending) { - spin_unlock_irq(&ts->lock); - msleep(1); - spin_lock_irq(&ts->lock); - } - } - - /* we know the chip's in lowpower mode since we always - * leave it that way after every request - */ -} - -/* Must be called with ts->lock held */ -static void xpt2046_enable(struct xpt2046 *ts) -{ - if (!ts->disabled) - return; - - ts->disabled = 0; - ts->irq_disabled = 0; - enable_irq(ts->spi->irq); -} - -static int xpt2046_suspend(struct spi_device *spi, pm_message_t message) -{ - struct xpt2046 *ts = dev_get_drvdata(&spi->dev); - - spin_lock_irq(&ts->lock); - - ts->is_suspended = 1; - xpt2046_disable(ts); - - spin_unlock_irq(&ts->lock); - - return 0; - -} - -static int xpt2046_resume(struct spi_device *spi) -{ - struct xpt2046 *ts = dev_get_drvdata(&spi->dev); - - spin_lock_irq(&ts->lock); - - ts->is_suspended = 0; - xpt2046_enable(ts); - - spin_unlock_irq(&ts->lock); - - return 0; -} - -static int __devinit setup_pendown(struct spi_device *spi, struct xpt2046 *ts) -{ - struct xpt2046_platform_data *pdata = spi->dev.platform_data; - int err; - - /* REVISIT when the irq can be triggered active-low, or if for some - * reason the touchscreen isn't hooked up, we don't need to access - * the pendown state. - */ - if (!pdata->get_pendown_state && !gpio_is_valid(pdata->gpio_pendown)) { - dev_err(&spi->dev, "no get_pendown_state nor gpio_pendown?\n"); - return -EINVAL; - } - - if (pdata->get_pendown_state) { - ts->get_pendown_state = pdata->get_pendown_state; - return 0; - } - - if (pdata->io_init) { - err = pdata->io_init(); - if (err) - dev_err(&spi->dev, "xpt2046 io_init fail\n"); - } - - err = gpio_request(pdata->gpio_pendown, "xpt2046_pendown"); - if (err) { - dev_err(&spi->dev, "failed to request pendown GPIO%d\n", - pdata->gpio_pendown); - return err; - } - - err = gpio_direction_input(pdata->gpio_pendown); - if (err) { - dev_err(&spi->dev, "failed to switch GPIO to input%d\n", - pdata->gpio_pendown); - return err; - } - - gpio_pull_updown(pdata->gpio_pendown,GPIOPullUp); - - ts->gpio_pendown = pdata->gpio_pendown; - return 0; -} - - -static int __devinit xpt2046_probe(struct spi_device *spi) -{ - struct xpt2046 *ts; - struct xpt2046_packet *packet; - struct input_dev *input_dev; - struct xpt2046_platform_data *pdata = spi->dev.platform_data; - struct spi_message *m; - struct spi_transfer *x; - int vref; - int err; - int i; - - if (!spi->irq) { - dev_dbg(&spi->dev, "no IRQ?\n"); - return -ENODEV; - } - else{ - spi->irq = gpio_to_irq(spi->irq); - dev_dbg(&spi->dev, "no IRQ?\n"); - } - - if (!pdata) { - dev_err(&spi->dev, "empty platform_data\n"); - return -EFAULT; - } - - /* don't exceed max specified sample rate */ - if (spi->max_speed_hz > (125000 * SAMPLE_BITS)) { - dev_dbg(&spi->dev, "f(sample) %d KHz?\n", - (spi->max_speed_hz/SAMPLE_BITS)/1000); - return -EINVAL; - } - - /* We'd set TX wordsize 8 bits and RX wordsize to 13 bits ... except - * that even if the hardware can do that, the SPI controller driver - * may not. So we stick to very-portable 8 bit words, both RX and TX. - */ - spi->bits_per_word = 8; - spi->mode = SPI_MODE_0; - err = spi_setup(spi); - if (err < 0) - return err; - - ts = kzalloc(sizeof(struct xpt2046), GFP_KERNEL); - packet = kzalloc(sizeof(struct xpt2046_packet), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!ts || !packet || !input_dev) { - err = -ENOMEM; - goto err_free_mem; - } - - dev_set_drvdata(&spi->dev, ts); - - ts->packet = packet; - ts->spi = spi; - ts->input = input_dev; - ts->swap_xy = pdata->swap_xy; - - hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - ts->timer.function = xpt2046_timer; - - spin_lock_init(&ts->lock); - - ts->model = pdata->model ? : 2046; - - if (pdata->filter != NULL) { - if (pdata->filter_init != NULL) { - err = pdata->filter_init(pdata, &ts->filter_data); - if (err < 0) - goto err_free_mem; - } - ts->filter = pdata->filter; - ts->filter_cleanup = pdata->filter_cleanup; - } else if (pdata->debounce_max) { - ts->debounce_max = pdata->debounce_max; - if (ts->debounce_max < pdata->debounce_rep) - ts->debounce_max = pdata->debounce_rep; - ts->debounce_tol = pdata->debounce_tol; - ts->debounce_rep = pdata->debounce_rep; - ts->filter = xpt2046_debounce; - ts->filter_data = ts; - } else - ts->filter = xpt2046_no_filter; - - err = setup_pendown(spi, ts); - if (err) - goto err_cleanup_filter; - - if (pdata->penirq_recheck_delay_usecs) - ts->penirq_recheck_delay_usecs = - pdata->penirq_recheck_delay_usecs; - - ts->wait_for_sync = pdata->wait_for_sync ? : null_wait_for_sync; - - snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&spi->dev)); - snprintf(ts->name, sizeof(ts->name), "XPT%d Touchscreen", ts->model); - - input_dev->name = ts->name; - input_dev->phys = ts->phys; - input_dev->dev.parent = &spi->dev; - - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); - //add by zhao - for (i = 0; i < ARRAY_SIZE(panel_key_info); i++) - set_bit(panel_key_info[i].key, input_dev->keybit); - clear_bit(0, input_dev->keybit); - //end - input_set_abs_params(input_dev, ABS_X, - pdata->x_min ? : 0, - pdata->x_max ? : MAX_12BIT, - 0, 0); - input_set_abs_params(input_dev, ABS_Y, - pdata->y_min ? : 0, - pdata->y_max ? : MAX_12BIT, - 0, 0); - - vref = pdata->keep_vref_on; - - /* set up the transfers to read touchscreen state; this assumes we - * use formula #2 for pressure, not #3. - */ - m = &ts->msg[0]; - x = ts->xfer; - - spi_message_init(m); - - /* y- still on; turn on only y+ (and ADC) */ - packet->read_y = READ_Y(vref); - xpt2046printk("-------------read Y 0x%x\n",packet->read_y); //add by zhao - x->tx_buf = &packet->read_y; - x->len = 1; - spi_message_add_tail(x, m); - - x++; - x->rx_buf = &packet->tc.y; - x->len = 2; - spi_message_add_tail(x, m); - - m->complete = xpt2046_rx_val; - m->context = ts; - - m++; - spi_message_init(m); - - /* turn y- off, x+ on, then leave in lowpower */ - x++; - packet->read_x = READ_X(vref); - xpt2046printk("-------------read X 0x%x\n",packet->read_x); //add by zhao - x->tx_buf = &packet->read_x; - x->len = 1; - spi_message_add_tail(x, m); - - x++; - x->rx_buf = &packet->tc.x; - x->len = 2; - spi_message_add_tail(x, m); - - m->complete = xpt2046_rx_val; - m->context = ts; - - /* power down */ - m++; - spi_message_init(m); - - x++; - packet->pwrdown = PWRDOWN; - x->tx_buf = &packet->pwrdown; - x->len = 1; - spi_message_add_tail(x, m); - - x++; - x->rx_buf = &packet->dummy; - x->len = 2; - CS_CHANGE(*x); - spi_message_add_tail(x, m); - - m->complete = xpt2046_rx; - m->context = ts; - - ts->last_msg = m; - xpt2046printk("***>%s:touchscreen irq %d\n",__FUNCTION__,spi->irq); - if (request_irq(spi->irq, xpt2046_irq, IRQF_TRIGGER_FALLING, - spi->dev.driver->name, ts)) { - printk("%s:trying pin change workaround on irq %d\n",__FUNCTION__,spi->irq); - err = request_irq(spi->irq, xpt2046_irq, - IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, - spi->dev.driver->name, ts); - if (err) { - dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq); - goto err_free_gpio; - } - } - - /* take a first sample, leaving nPENIRQ active and vREF off; avoid - * the touchscreen, in case it's not connected. - */ - xpt2046_read12_dfr(&spi->dev,READ_X(1)); - - err = input_register_device(input_dev); - if (err) - goto err_remove_attr_group; - printk("xpt2046_ts: driver initialized\n"); - return 0; - - err_remove_attr_group: - free_irq(spi->irq, ts); - err_free_gpio: - if (ts->gpio_pendown != -1) - gpio_free(ts->gpio_pendown); - err_cleanup_filter: - if (ts->filter_cleanup) - ts->filter_cleanup(ts->filter_data); - err_free_mem: - input_free_device(input_dev); - kfree(packet); - kfree(ts); - return err; -} - -static int __devexit xpt2046_remove(struct spi_device *spi) -{ - struct xpt2046 *ts = dev_get_drvdata(&spi->dev); - - input_unregister_device(ts->input); - - xpt2046_suspend(spi, PMSG_SUSPEND); - - free_irq(ts->spi->irq, ts); - /* suspend left the IRQ disabled */ - enable_irq(ts->spi->irq); - - if (ts->gpio_pendown != -1) - gpio_free(ts->gpio_pendown); - - if (ts->filter_cleanup) - ts->filter_cleanup(ts->filter_data); - - kfree(ts->packet); - kfree(ts); - - dev_dbg(&spi->dev, "unregistered touchscreen\n"); - return 0; -} - -static struct spi_driver xpt2046_driver = { - .driver = { - .name = "xpt2046_ts", - .bus = &spi_bus_type, - .owner = THIS_MODULE, - }, - .probe = xpt2046_probe, - .remove = __devexit_p(xpt2046_remove), - .suspend = xpt2046_suspend, - .resume = xpt2046_resume, -}; - -static int __init xpt2046_init(void) -{ - return spi_register_driver(&xpt2046_driver); -} -late_initcall_sync(xpt2046_init); - -static void __exit xpt2046_exit(void) -{ - spi_unregister_driver(&xpt2046_driver); -} -module_exit(xpt2046_exit); - -MODULE_DESCRIPTION("rk2818 spi xpt2046 TouchScreen Driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("spi:xpt2046"); diff --git a/drivers/input/touchscreen/xpt2046_tslib_ts.c b/drivers/input/touchscreen/xpt2046_tslib_ts.c deleted file mode 100755 index fdb9851a0fc2..000000000000 --- a/drivers/input/touchscreen/xpt2046_tslib_ts.c +++ /dev/null @@ -1,1099 +0,0 @@ -/* - * drivers/input/touchscreen/xpt2046_ts.c - driver for rk29 spi xpt2046 device and console - * - * Copyright (C) 2011 ROCKCHIP, 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_HAS_EARLYSUSPEND -#include -#endif -#include "xpt2046_tslib_ts.h" -#include "ts_lib/tslib.h" -/* - * This code has been heavily tested on a Nokia 770, and lightly - * tested on other xpt2046 devices (OSK/Mistral, Lubbock). - * TSC2046 is just newer xpt2046 silicon. - * Support for ads7843 tested on Atmel at91sam926x-EK. - * Support for ads7845 has only been stubbed in. - * - * IRQ handling needs a workaround because of a shortcoming in handling - * edge triggered IRQs on some platforms like the OMAP1/2. These - * platforms don't handle the ARM lazy IRQ disabling properly, thus we - * have to maintain our own SW IRQ disabled status. This should be - * removed as soon as the affected platform's IRQ handling is fixed. - * - * app note sbaa036 talks in more detail about accurate sampling... - * that ought to help in situations like LCDs inducing noise (which - * can also be helped by using synch signals) and more generally. - * This driver tries to utilize the measures described in the app - * note. The strength of filtering can be set in the board-* specific - * files. - */ -#define XPT2046_DEBUG 0 -#if XPT2046_DEBUG - #define xpt2046printk(msg...) printk(msg); -#else - #define xpt2046printk(msg...) -#endif - -#define TS_POLL_DELAY (10) /* ns delay before the first sample */ -#define TS_POLL_PERIOD (20) /* ns delay between samples */ - -/* this driver doesn't aim at the peak continuous sample rate */ -#define SAMPLE_BITS (8 /*cmd*/ + 16 /*sample*/ + 2 /* before, after */) - -struct ts_event { - /* For portability, we can't read 12 bit values using SPI (which - * would make the controller deliver them as native byteorder u16 - * with msbs zeroed). Instead, we read them as two 8-bit values, - * *** WHICH NEED BYTESWAPPING *** and range adjustment. - */ - u16 x; - u16 y; - int ignore; -}; - -/* - * We allocate this separately to avoid cache line sharing issues when - * driver is used with DMA-based SPI controllers (like atmel_spi) on - * systems where main memory is not DMA-coherent (most non-x86 boards). - */ -struct xpt2046_packet { - u8 read_x, read_y, pwrdown; - u16 dummy; /* for the pwrdown read */ - struct ts_event tc; -}; - -struct xpt2046 { - struct input_dev *input; - char phys[32]; - char name[32]; - char pendown_iomux_name[IOMUX_NAME_SIZE]; - struct spi_device *spi; - - u16 model; - u16 x_min, x_max; - u16 y_min, y_max; - u16 debounce_max; - u16 debounce_tol; - u16 debounce_rep; - u16 penirq_recheck_delay_usecs; - bool swap_xy; - - struct xpt2046_packet *packet; - - struct spi_transfer xfer[18]; - struct spi_message msg[5]; - struct spi_message *last_msg; - int msg_idx; - int read_cnt; - int read_rep; - int last_read; - int pendown_iomux_mode; - int touch_ad_top; - int touch_ad_bottom; - int touch_ad_left; - int touch_ad_right; - int touch_virtualkey_length; - spinlock_t lock; - struct delayed_work d_work; - struct tslib_info tslib_info; - unsigned pendown:1; /* P: lock */ - unsigned pending:1; /* P: lock */ -// FIXME remove "irq_disabled" - unsigned irq_disabled:1; /* P: lock */ - unsigned disabled:1; - unsigned is_suspended:1; - - int (*filter)(void *data, int data_idx, int *val); - void *filter_data; - void (*filter_cleanup)(void *data); - int (*get_pendown_state)(void); - int gpio_pendown; - - void (*wait_for_sync)(void); -#ifdef CONFIG_HAS_EARLYSUSPEND - struct early_suspend early_suspend; -#endif -}; - -/* leave chip selected when we're done, for quicker re-select? */ -#if 0 -#define CS_CHANGE(xfer) ((xfer).cs_change = 1) -#else -#define CS_CHANGE(xfer) ((xfer).cs_change = 0) -#endif - -/*--------------------------------------------------------------------------*/ - -/* The xpt2046 has touchscreen and other sensors. - * Earlier xpt2046 chips are somewhat compatible. - */ -#define XPT2046_START (1 << 7) -#define XPT2046_A2A1A0_d_y (1 << 4) /* differential */ -#define XPT2046_A2A1A0_d_z1 (3 << 4) /* differential */ -#define XPT2046_A2A1A0_d_z2 (4 << 4) /* differential */ -#define XPT2046_A2A1A0_d_x (5 << 4) /* differential */ -#define XPT2046_A2A1A0_temp0 (0 << 4) /* non-differential */ -#define XPT2046_A2A1A0_vbatt (2 << 4) /* non-differential */ -#define XPT2046_A2A1A0_vaux (6 << 4) /* non-differential */ -#define XPT2046_A2A1A0_temp1 (7 << 4) /* non-differential */ -#define XPT2046_8_BIT (1 << 3) -#define XPT2046_12_BIT (0 << 3) -#define XPT2046_SER (1 << 2) /* non-differential */ -#define XPT2046_DFR (0 << 2) /* differential */ -#define XPT2046_PD10_PDOWN (0 << 0) /* lowpower mode + penirq */ -#define XPT2046_PD10_ADC_ON (1 << 0) /* ADC on */ -#define XPT2046_PD10_REF_ON (2 << 0) /* vREF on + penirq */ -#define XPT2046_PD10_ALL_ON (3 << 0) /* ADC + vREF on */ - -#define MAX_12BIT ((1<<12)-1) - -/* leave ADC powered up (disables penirq) between differential samples */ -#define READ_12BIT_DFR(x, adc, vref) (XPT2046_START | XPT2046_A2A1A0_d_ ## x \ - | XPT2046_12_BIT | XPT2046_DFR | \ - (adc ? XPT2046_PD10_ADC_ON : 0) | (vref ? XPT2046_PD10_REF_ON : 0)) - -#define READ_Y(vref) (READ_12BIT_DFR(y, 1, vref)) -#define READ_Z1(vref) (READ_12BIT_DFR(z1, 1, vref)) -#define READ_Z2(vref) (READ_12BIT_DFR(z2, 1, vref)) - -#define READ_X(vref) (READ_12BIT_DFR(x, 1, vref)) -#define PWRDOWN (READ_12BIT_DFR(y, 0, 0)) /* LAST */ - -/* single-ended samples need to first power up reference voltage; - * we leave both ADC and VREF powered - */ -#define READ_12BIT_SER(x) (XPT2046_START | XPT2046_A2A1A0_ ## x \ - | XPT2046_12_BIT | XPT2046_SER) - -#define REF_ON (READ_12BIT_DFR(x, 1, 1)) -#define REF_OFF (READ_12BIT_DFR(y, 0, 0)) - -/*--------------------------------------------------------------------------*/ -/* - * touchscreen sensors use differential conversions. - */ - -struct dfr_req { - u8 command; - u8 pwrdown; - u16 dummy; /* for the pwrdown read */ - __be16 sample; - struct spi_message msg; - struct spi_transfer xfer[4]; -}; -static DECLARE_WAIT_QUEUE_HEAD(wq_ts); -static int wq_condition_ts = 1; - -static void xpt2046_enable(struct xpt2046 *ts); -static void xpt2046_disable(struct xpt2046 *ts); -static int xpt2046_verifyAndConvert(struct xpt2046 *ts,int adx, int ady,int *x, int *y) -{ - *x = ts->x_max * (ts->touch_ad_left - adx)/(ts->touch_ad_left - ts->touch_ad_right); - *y = ts->y_max * (ts->touch_ad_top - ady)/(ts->touch_ad_top - ts->touch_ad_bottom); - - xpt2046printk("%s:(%d/%d)\n",__FUNCTION__,*x, *y); - - if((*x< ts->x_min) || (*x > ts->x_max)) - return 1; - - if((*y< ts->y_min) || (*y > ts->y_max + ts->touch_virtualkey_length)) - return 1; - - - return 0; -} -static int device_suspended(struct device *dev) -{ - struct xpt2046 *ts = dev_get_drvdata(dev); - return ts->is_suspended || ts->disabled; -} - -static int xpt2046_read12_dfr(struct device *dev, unsigned command) -{ - struct spi_device *spi = to_spi_device(dev); - struct xpt2046 *ts = dev_get_drvdata(dev); - struct dfr_req *req = kzalloc(sizeof *req, GFP_KERNEL); - int status; - - if (!req) - return -ENOMEM; - - spi_message_init(&req->msg); - - /* take sample */ - req->command = (u8) command; - req->xfer[0].tx_buf = &req->command; - req->xfer[0].len = 1; - spi_message_add_tail(&req->xfer[0], &req->msg); - - req->xfer[1].rx_buf = &req->sample; - req->xfer[1].len = 2; - spi_message_add_tail(&req->xfer[1], &req->msg); - - /* converter in low power mode & enable PENIRQ */ - req->pwrdown= PWRDOWN; - req->xfer[2].tx_buf = &req->pwrdown; - req->xfer[2].len = 1; - spi_message_add_tail(&req->xfer[2], &req->msg); - - req->xfer[3].rx_buf = &req->dummy; - req->xfer[3].len = 2; - CS_CHANGE(req->xfer[3]); - spi_message_add_tail(&req->xfer[3], &req->msg); - - ts->irq_disabled = 1; - disable_irq(spi->irq); - status = spi_sync(spi, &req->msg); - ts->irq_disabled = 0; - enable_irq(spi->irq); - - if (status == 0) { - /* on-wire is a must-ignore bit, a BE12 value, then padding */ - status = be16_to_cpu(req->sample); - status = status >> 3; - status &= 0x0fff; - xpt2046printk("***>%s:status=%d\n",__FUNCTION__,status); - } - - kfree(req); - return status; -} - - - -/*--------------------------------------------------------------------------*/ - -static int get_pendown_state(struct xpt2046 *ts) -{ - if (ts->get_pendown_state) - return ts->get_pendown_state(); - - return !gpio_get_value(ts->gpio_pendown); -} - -static void null_wait_for_sync(void) -{ - -} - -/* - * PENIRQ only kicks the timer. The timer only reissues the SPI transfer, - * to retrieve touchscreen status. - * - * The SPI transfer completion callback does the real work. It reports - * touchscreen events and reactivates the timer (or IRQ) as appropriate. - */ -static void xpt2046_rx(void *xpt) -{ - /* xpt2046_rx_val() did in-place conversion (including byteswap) from - * on-the-wire format as part of debouncing to get stable readings. - */ - wq_condition_ts= 1; - wake_up(&wq_ts); - - return; -} - -static int xpt2046_debounce(void *xpt, int data_idx, int *val) -{ - struct xpt2046 *ts = xpt; - static int average_val[2]; - - - xpt2046printk("***>%s:%d,%d,%d,%d,%d,%d,%d,%d\n",__FUNCTION__, - data_idx,ts->last_read, - ts->read_cnt,ts->debounce_max, - abs(ts->last_read - *val),ts->debounce_tol, - ts->read_rep,ts->debounce_rep); - - /* discard the first sample. */ - //on info_it50, the top-left area(1cmx1cm top-left square ) is not responding cause the first sample is invalid, @sep 17th - if(!ts->read_cnt) - { - //udelay(100); - ts->read_cnt++; - return XPT2046_FILTER_REPEAT; - } - if(*val == 4095 || *val == 0) - { - ts->read_cnt = 0; - ts->last_read = 0; - memset(average_val,0,sizeof(average_val)); - xpt2046printk("***>%s:*val == 4095 || *val == 0\n",__FUNCTION__); - return XPT2046_FILTER_IGNORE; - } - /* discard the first sample. */ -/* if(!ts->read_cnt) - { - ts->read_cnt++; - return XPT2046_FILTER_REPEAT; - } -move discard ahead */ - - if (ts->read_cnt==1 || (abs(ts->last_read - *val) > ts->debounce_tol)) { - /* Start over collecting consistent readings. */ - ts->read_rep = 1; - average_val[data_idx] = *val; - /* Repeat it, if this was the first read or the read - * wasn't consistent enough. */ - if (ts->read_cnt < ts->debounce_max) { - ts->last_read = *val; - ts->read_cnt++; - return XPT2046_FILTER_REPEAT; - } else { - /* Maximum number of debouncing reached and still - * not enough number of consistent readings. Abort - * the whole sample, repeat it in the next sampling - * period. - */ - ts->read_cnt = 0; - ts->last_read = 0; - memset(average_val,0,sizeof(average_val)); - xpt2046printk("***>%s:XPT2046_FILTER_IGNORE\n",__FUNCTION__); - return XPT2046_FILTER_IGNORE; - } - } - else { - average_val[data_idx] += *val; - - if (++ts->read_rep >= ts->debounce_rep) { - /* Got a good reading for this coordinate, - * go for the next one. */ - ts->read_cnt = 0; - ts->read_rep = 0; - ts->last_read = 0; - *val = average_val[data_idx]/(ts->debounce_rep); - return XPT2046_FILTER_OK; - } else { - /* Read more values that are consistent. */ - ts->read_cnt++; - - return XPT2046_FILTER_REPEAT; - } - } -} - -static int xpt2046_no_filter(void *xpt, int data_idx, int *val) -{ - return XPT2046_FILTER_OK; -} - -static void xpt2046_rx_val(void *xpt) -{ - struct xpt2046 *ts = xpt; - struct xpt2046_packet *packet = ts->packet; - struct spi_message *m; - struct spi_transfer *t; - int val; - int action; - int status; - - m = &ts->msg[ts->msg_idx]; - t = list_entry(m->transfers.prev, struct spi_transfer, transfer_list); - - /* adjust: on-wire is a must-ignore bit, a BE12 value, then padding; - * built from two 8 bit values written msb-first. - */ - val = (be16_to_cpup((__be16 *)t->rx_buf) >> 3) & 0x0fff; - - xpt2046printk("***>%s:value=%d\n",__FUNCTION__,val); - - action = ts->filter(ts->filter_data, ts->msg_idx, &val); - switch (action) { - case XPT2046_FILTER_REPEAT: - break; - case XPT2046_FILTER_IGNORE: - packet->tc.ignore = 1; - /* Last message will contain xpt2046_rx() as the - * completion function. - */ - m = ts->last_msg; - break; - case XPT2046_FILTER_OK: - *(u16 *)t->rx_buf = val; - packet->tc.ignore = 0; - m = &ts->msg[++ts->msg_idx]; - break; - default: - BUG(); - } - ts->wait_for_sync(); - status = spi_async(ts->spi, m); - if (status) - dev_err(&ts->spi->dev, "spi_async --> %d\n", - status); -} - -int xpt2046_get_raw_data(struct tslib_info *info, struct ts_sample *samp, int nr) -{ - - struct xpt2046 *ts = container_of((void *)info, struct xpt2046, tslib_info); - struct xpt2046_packet *packet = ts->packet; - int status = 0; - memset(samp, 0, sizeof(struct ts_sample)*nr); - - wq_condition_ts = 0; - - ts->msg_idx = 0; - ts->wait_for_sync(); - status = spi_async(ts->spi, &ts->msg[0]); - if (status) - dev_err(&ts->spi->dev, "spi_async --> %d\n", status); - - xpt2046printk("xpt2046_get_raw_data:wait_event \n"); - if(!wait_event_timeout(wq_ts, wq_condition_ts, msecs_to_jiffies(100))) - { - samp->x = 4095; - samp->y = 4095; - samp->pressure = 0; - return 1; - } - - samp->x = packet->tc.x; - samp->y = packet->tc.y; - samp->pressure = !(packet->tc.ignore); - //xpt2046printk("xpt2046_get_raw_data:samp->x=%d,samp->y=%d,samp->pressure=%d \n", - //samp->x,samp->y,samp->pressure); - return 1; -} - -static void xpt2046_report(struct xpt2046 *ts) -{ - struct ts_sample samp[3]; - struct xpt2046_packet *packet = ts->packet; - int ret,Rt=1; - int x = 0,y =0,z = 0; - - ret = dejitter_read(&ts->tslib_info, samp, 1); - - xpt2046printk("***>%s:ret=%d,samp[0].x=%d,samp[0].y=%d,samp[0].pressure=%d\n", - __FUNCTION__,ret,samp[0].x,samp[0].y,samp[0].pressure); - if(ret == 1){ - x = samp[0].x; - y = samp[0].y; - z = samp[0].pressure; - } - else if(ret == 2){ - x = (samp[0].x + samp[1].x) / 2; - y = (samp[0].y + samp[1].y) / 2; - z = (samp[0].pressure + samp[1].pressure) / 2; - } - else if(ret ==3){ - x = (samp[0].x + samp[1].x + samp[2].x)/3; - y = (samp[0].y + samp[1].y + samp[2].y)/3; - z = (samp[0].pressure + samp[1].pressure + samp[2].pressure)/3; - } - else{ - printk("no sampe\n"); - goto out; - } - - if(z == 0) - { - xpt2046printk("***>%s:z == 0\n",__FUNCTION__); - goto out; - } - - /* range filtering */ - if (x == MAX_12BIT) - x = 0; - - /* Sample found inconsistent by debouncing or pressure is beyond - * the maximum. Don't report it to user space, repeat at least - * once more the measurement - */ - if (packet->tc.ignore) { - xpt2046printk("***>%s:ignored=%d\n",__FUNCTION__,packet->tc.ignore); - schedule_delayed_work(&ts->d_work, msecs_to_jiffies(TS_POLL_PERIOD)); - return; - } - - /* Maybe check the pendown state before reporting. This discards - * false readings when the pen is lifted. - */ - if (ts->penirq_recheck_delay_usecs) { - udelay(ts->penirq_recheck_delay_usecs); - if (!get_pendown_state(ts)) - { - xpt2046printk("***>%s:get_pendown_state(ts)==0,discard false reading\n",__FUNCTION__); - Rt = 0; - } - } - - /* NOTE: We can't rely on the pressure to determine the pen down - * state, even this controller has a pressure sensor. The pressure - * value can fluctuate for quite a while after lifting the pen and - * in some cases may not even settle at the expected value. - * - * The only safe way to check for the pen up condition is in the - * timer by reading the pen signal state (it's a GPIO _and_ IRQ). - */ - if (Rt) { - struct input_dev *input = ts->input; - - if (ts->swap_xy) - swap(x, y); - if(xpt2046_verifyAndConvert(ts,x,y,&x,&y)) - { - xpt2046printk("***>%s:xpt2046_verifyAndConvert fail\n",__FUNCTION__); - goto out; - } - - if (!ts->pendown) { - input_report_key(input, BTN_TOUCH, 1); - ts->pendown = 1; - xpt2046printk("***>%s:input_report_key(pen down)\n",__FUNCTION__); - } - - input_report_abs(input, ABS_X, x); - input_report_abs(input, ABS_Y, y); - - input_sync(input); - xpt2046printk("***>%s:input_report_abs(%4d/%4d)\n",__FUNCTION__,x, y); - } - -out: - schedule_delayed_work(&ts->d_work, msecs_to_jiffies(TS_POLL_PERIOD)); - - return; -} - -static void xpt2046_dwork_handler(struct work_struct *work) -{ - struct xpt2046 *ts = (struct xpt2046 *)container_of(work, struct xpt2046, d_work.work); - - spin_lock(&ts->lock); - - if (unlikely(!get_pendown_state(ts) || - device_suspended(&ts->spi->dev))) { - if (ts->pendown) { - struct input_dev *input = ts->input; - variance_clear(&ts->tslib_info); - input_report_key(input, BTN_TOUCH, 0); - input_sync(input); - - ts->pendown = 0; - - xpt2046printk("***>%s:input_report_key(The touchscreen up)\n",__FUNCTION__); - } - - /* measurement cycle ended */ - if (!device_suspended(&ts->spi->dev)) { - xpt2046printk("***>%s:device_suspended==0\n",__FUNCTION__); - ts->irq_disabled = 0; - enable_irq(ts->spi->irq); - } - ts->pending = 0; - } else { - /* pen is still down, continue with the measurement */ - xpt2046printk("***>%s:pen is still down, continue with the measurement\n",__FUNCTION__); - spin_unlock(&ts->lock); - xpt2046_report(ts); - return; - } - - spin_unlock(&ts->lock); - return; -} -static irqreturn_t xpt2046_irq(int irq, void *handle) -{ - struct xpt2046 *ts = handle; - unsigned long flags; - - xpt2046printk("***>%s.....%s.....%d\n",__FILE__,__FUNCTION__,__LINE__); - - spin_lock_irqsave(&ts->lock, flags); - - if (likely(get_pendown_state(ts))) { - if (!ts->irq_disabled) { - /* The ARM do_simple_IRQ() dispatcher doesn't act - * like the other dispatchers: it will report IRQs - * even after they've been disabled. We work around - * that here. (The "generic irq" framework may help...) - */ - ts->irq_disabled = 1; - disable_irq_nosync(ts->spi->irq); - ts->pending = 1; - schedule_delayed_work(&ts->d_work, msecs_to_jiffies(TS_POLL_DELAY)); - } - } - spin_unlock_irqrestore(&ts->lock, flags); - - return IRQ_HANDLED; -} - -/*--------------------------------------------------------------------------*/ - -/* Must be called with ts->lock held */ -static void xpt2046_disable(struct xpt2046 *ts) -{ - if (ts->disabled) - return; - - ts->disabled = 1; - - /* are we waiting for IRQ, or polling? */ - if (!ts->pending) { - ts->irq_disabled = 1; - disable_irq(ts->spi->irq); - } else { - /* the timer will run at least once more, and - * leave everything in a clean state, IRQ disabled - */ - while (ts->pending) { - spin_unlock_irq(&ts->lock); - msleep(1); - spin_lock_irq(&ts->lock); - } - } - - /* we know the chip's in lowpower mode since we always - * leave it that way after every request - */ -} - -/* Must be called with ts->lock held */ -static void xpt2046_enable(struct xpt2046 *ts) -{ - if (!ts->disabled) - return; - - ts->disabled = 0; - ts->irq_disabled = 0; - enable_irq(ts->spi->irq); -} - -static int xpt2046_pSuspend(struct xpt2046 *ts) -{ - spin_lock_irq(&ts->lock); - - ts->is_suspended = 1; - xpt2046_disable(ts); - - spin_unlock_irq(&ts->lock); - - return 0; -} - -static int xpt2046_pResume(struct xpt2046 *ts) -{ - spin_lock_irq(&ts->lock); - - ts->is_suspended = 0; - xpt2046_enable(ts); - - spin_unlock_irq(&ts->lock); - - return 0; -} - -#if !defined(CONFIG_HAS_EARLYSUSPEND) -static int xpt2046_suspend(struct spi_device *spi, pm_message_t message) -{ - struct xpt2046 *ts = dev_get_drvdata(&spi->dev); - - printk("xpt2046_suspend\n"); - - xpt2046_pSuspend(ts); - - return 0; -} - -static int xpt2046_resume(struct spi_device *spi) -{ - struct xpt2046 *ts = dev_get_drvdata(&spi->dev); - - printk("xpt2046_resume\n"); - - xpt2046_pResume(ts); - - return 0; -} - -#elif defined(CONFIG_HAS_EARLYSUSPEND) -static void xpt2046_early_suspend(struct early_suspend *h) -{ - struct xpt2046 *ts; - ts = container_of(h, struct xpt2046, early_suspend); - - printk("xpt2046_suspend early\n"); - - xpt2046_pSuspend(ts); - - return; -} - -static void xpt2046_late_resume(struct early_suspend *h) -{ - struct xpt2046 *ts; - ts = container_of(h, struct xpt2046, early_suspend); - - printk("xpt2046_resume late\n"); - - xpt2046_pResume(ts); - - return; -} -#endif - -static int __devinit setup_pendown(struct spi_device *spi, struct xpt2046 *ts) -{ - struct xpt2046_platform_data *pdata = spi->dev.platform_data; - int err; - - /* REVISIT when the irq can be triggered active-low, or if for some - * reason the touchscreen isn't hooked up, we don't need to access - * the pendown state. - */ - if (!pdata->get_pendown_state && !gpio_is_valid(pdata->gpio_pendown)) { - dev_err(&spi->dev, "no get_pendown_state nor gpio_pendown?\n"); - return -EINVAL; - } - - if (pdata->get_pendown_state) { - ts->get_pendown_state = pdata->get_pendown_state; - return 0; - } - - if (pdata->io_init) { - err = pdata->io_init(); - if (err) - dev_err(&spi->dev, "xpt2046 io_init fail\n"); - } - - ts->gpio_pendown = pdata->gpio_pendown; - strcpy(ts->pendown_iomux_name,pdata->pendown_iomux_name); - ts->pendown_iomux_mode = pdata->pendown_iomux_mode; - - rk29_mux_api_set(ts->pendown_iomux_name,pdata->pendown_iomux_mode); - err = gpio_request(pdata->gpio_pendown, "xpt2046_pendown"); - if (err) { - dev_err(&spi->dev, "failed to request pendown GPIO%d\n", - pdata->gpio_pendown); - return err; - } - - err = gpio_pull_updown(pdata->gpio_pendown, GPIOPullUp); - if (err) { - dev_err(&spi->dev, "failed to pullup pendown GPIO%d\n", - pdata->gpio_pendown); - return err; - } - ts->gpio_pendown = pdata->gpio_pendown; - return 0; -} - -static int __devinit xpt2046_probe(struct spi_device *spi) -{ - struct xpt2046 *ts; - struct xpt2046_packet *packet; - struct input_dev *input_dev; - struct xpt2046_platform_data *pdata = spi->dev.platform_data; - struct spi_message *m; - struct spi_transfer *x; - int vref; - int err; - - if (!spi->irq) { - dev_dbg(&spi->dev, "no IRQ?\n"); - return -ENODEV; - } - else{ - spi->irq = gpio_to_irq(spi->irq); - dev_dbg(&spi->dev, "no IRQ?\n"); - } - - if (!pdata) { - dev_err(&spi->dev, "empty platform_data\n"); - return -EFAULT; - } - - /* don't exceed max specified sample rate */ - if (spi->max_speed_hz > (125000 * SAMPLE_BITS)) { - dev_dbg(&spi->dev, "f(sample) %d KHz?\n", - (spi->max_speed_hz/SAMPLE_BITS)/1000); - return -EINVAL; - } - - /* We'd set TX wordsize 8 bits and RX wordsize to 13 bits ... except - * that even if the hardware can do that, the SPI controller driver - * may not. So we stick to very-portable 8 bit words, both RX and TX. - */ - spi->bits_per_word = 8; - spi->mode = SPI_MODE_0; - err = spi_setup(spi); - if (err < 0) - return err; - - ts = kzalloc(sizeof(struct xpt2046), GFP_KERNEL); - packet = kzalloc(sizeof(struct xpt2046_packet), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!ts || !packet || !input_dev) { - err = -ENOMEM; - goto err_free_mem; - } - - dev_set_drvdata(&spi->dev, ts); - - ts->packet = packet; - ts->spi = spi; - ts->input = input_dev; - ts->swap_xy = pdata->swap_xy; - - INIT_DELAYED_WORK(&ts->d_work, xpt2046_dwork_handler); - - tslib_init(&ts->tslib_info, xpt2046_get_raw_data); - - spin_lock_init(&ts->lock); - - ts->model = pdata->model ? : 2046; - - if (pdata->filter != NULL) { - if (pdata->filter_init != NULL) { - err = pdata->filter_init(pdata, &ts->filter_data); - if (err < 0) - goto err_free_mem; - } - ts->filter = pdata->filter; - ts->filter_cleanup = pdata->filter_cleanup; - } else if (pdata->debounce_max) { - ts->debounce_max = pdata->debounce_max; - if (ts->debounce_max < pdata->debounce_rep) - ts->debounce_max = pdata->debounce_rep; - ts->debounce_tol = pdata->debounce_tol; - ts->debounce_rep = pdata->debounce_rep; - ts->filter = xpt2046_debounce; - ts->filter_data = ts; - } else - ts->filter = xpt2046_no_filter; - - err = setup_pendown(spi, ts); - if (err) - goto err_cleanup_filter; - - if (pdata->penirq_recheck_delay_usecs) - ts->penirq_recheck_delay_usecs = - pdata->penirq_recheck_delay_usecs; - - ts->wait_for_sync = pdata->wait_for_sync ? : null_wait_for_sync; - ts->x_min = pdata->x_min; - ts->x_max = pdata->x_max; - ts->y_min = pdata->y_min; - ts->y_max = pdata->y_max; - - ts->touch_ad_top = pdata->touch_ad_top; - ts->touch_ad_bottom= pdata->touch_ad_bottom; - ts->touch_ad_left= pdata->touch_ad_left; - ts->touch_ad_right= pdata->touch_ad_right; - - ts->touch_virtualkey_length = pdata->touch_virtualkey_length; - - snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&spi->dev)); - snprintf(ts->name, sizeof(ts->name), "xpt%d-touchscreen", ts->model); - - input_dev->name = ts->name; - input_dev->phys = ts->phys; - input_dev->dev.parent = &spi->dev; - - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); - input_set_abs_params(input_dev, ABS_X, - ts->x_min ? : 0, - ts->x_max ? : MAX_12BIT, - 0, 0); - input_set_abs_params(input_dev, ABS_Y, - ts->y_min ? : 0, - ts->y_max ? : MAX_12BIT, - 0, 0); - - vref = pdata->keep_vref_on; - - /* set up the transfers to read touchscreen state; this assumes we - * use formula #2 for pressure, not #3. - */ - m = &ts->msg[0]; - x = ts->xfer; - - spi_message_init(m); - - /* y- still on; turn on only y+ (and ADC) */ - packet->read_y = READ_Y(vref); - x->tx_buf = &packet->read_y; - x->len = 1; - spi_message_add_tail(x, m); - - x++; - x->rx_buf = &packet->tc.y; - x->len = 2; - spi_message_add_tail(x, m); - - m->complete = xpt2046_rx_val; - m->context = ts; - - m++; - spi_message_init(m); - - /* turn y- off, x+ on, then leave in lowpower */ - x++; - packet->read_x = READ_X(vref); - x->tx_buf = &packet->read_x; - x->len = 1; - spi_message_add_tail(x, m); - - x++; - x->rx_buf = &packet->tc.x; - x->len = 2; - spi_message_add_tail(x, m); - - m->complete = xpt2046_rx_val; - m->context = ts; - - /* power down */ - m++; - spi_message_init(m); - - x++; - packet->pwrdown = PWRDOWN; - x->tx_buf = &packet->pwrdown; - x->len = 1; - spi_message_add_tail(x, m); - - x++; - x->rx_buf = &packet->dummy; - x->len = 2; - CS_CHANGE(*x); - spi_message_add_tail(x, m); - - m->complete = xpt2046_rx; - m->context = ts; - - ts->last_msg = m; - - if (request_irq(spi->irq, xpt2046_irq, IRQF_TRIGGER_FALLING, - spi->dev.driver->name, ts)) { - xpt2046printk("%s:trying pin change workaround on irq %d\n",__FUNCTION__,spi->irq); - err = request_irq(spi->irq, xpt2046_irq, - IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, - spi->dev.driver->name, ts); - if (err) { - dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq); - goto err_free_gpio; - } - } - xpt2046printk("***>%s:touchscreen irq %d\n",__FUNCTION__,spi->irq); - - /* take a first sample, leaving nPENIRQ active and vREF off; avoid - * the touchscreen, in case it's not connected. - */ - xpt2046_read12_dfr(&spi->dev,READ_X(1)); - - err = input_register_device(input_dev); - if (err) - goto err_remove_attr_group; - -#ifdef CONFIG_HAS_EARLYSUSPEND - ts->early_suspend.suspend = xpt2046_early_suspend; - ts->early_suspend.resume = xpt2046_late_resume; - ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; - register_early_suspend(&ts->early_suspend); -#endif - - xpt2046printk("xpt2046_ts: driver initialized\n"); - return 0; - - err_remove_attr_group: - free_irq(spi->irq, ts); - err_free_gpio: - if (ts->gpio_pendown != -1) - gpio_free(ts->gpio_pendown); - err_cleanup_filter: - if (ts->filter_cleanup) - ts->filter_cleanup(ts->filter_data); - err_free_mem: - input_free_device(input_dev); - kfree(packet); - kfree(ts); - return err; -} - -static int __devexit xpt2046_remove(struct spi_device *spi) -{ - struct xpt2046 *ts = dev_get_drvdata(&spi->dev); - - input_unregister_device(ts->input); - -#if !defined(CONFIG_HAS_EARLYSUSPEND) - xpt2046_suspend(spi, PMSG_SUSPEND); -#elif defined(CONFIG_HAS_EARLYSUSPEND) - xpt2046_early_suspend(&ts->early_suspend); - unregister_early_suspend(&ts->early_suspend); -#endif - - free_irq(ts->spi->irq, ts); - /* suspend left the IRQ disabled */ - enable_irq(ts->spi->irq); - - if (ts->gpio_pendown != -1) - gpio_free(ts->gpio_pendown); - - if (ts->filter_cleanup) - ts->filter_cleanup(ts->filter_data); - - kfree(ts->packet); - kfree(ts); - - dev_dbg(&spi->dev, "unregistered touchscreen\n"); - return 0; -} - -static struct spi_driver xpt2046_driver = { - .driver = { - .name = "xpt2046_ts", - .bus = &spi_bus_type, - .owner = THIS_MODULE, - }, - .probe = xpt2046_probe, - .remove = __devexit_p(xpt2046_remove), -#ifndef CONFIG_HAS_EARLYSUSPEND - .suspend = xpt2046_suspend, - .resume = xpt2046_resume, -#endif -}; - -static int __init xpt2046_init(void) -{ - return spi_register_driver(&xpt2046_driver); -} -module_init(xpt2046_init); - -static void __exit xpt2046_exit(void) -{ - spi_unregister_driver(&xpt2046_driver); -} -module_exit(xpt2046_exit); - -MODULE_DESCRIPTION("rk29xx spi xpt2046 TouchScreen Driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("spi:xpt2046"); diff --git a/drivers/input/touchscreen/xpt2046_tslib_ts.h b/drivers/input/touchscreen/xpt2046_tslib_ts.h deleted file mode 100755 index 3c3b90f2bbf9..000000000000 --- a/drivers/input/touchscreen/xpt2046_tslib_ts.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * drivers/input/touchscreen/xpt2046_ts.h - * - * Copyright (C) 2010 ROCKCHIP, 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. - */ - -#ifndef __DRIVERS_TOUCHSCREEN_XPT2046_TS_H -#define __DRIVERS_TOUCHSCREEN_XPT2046_TS_H - -#define IOMUX_NAME_SIZE 20 - -enum xpt2046_filter { - XPT2046_FILTER_OK, - XPT2046_FILTER_REPEAT, - XPT2046_FILTER_IGNORE, -}; - -struct xpt2046_platform_data { - u16 model; /* 2046. */ - bool keep_vref_on; /* set to keep vref on for differential - * measurements as well */ - bool swap_xy; /* swap x and y axes */ - - /* If set to non-zero, after samples are taken this delay is applied - * and penirq is rechecked, to help avoid false events. This value - * is affected by the material used to build the touch layer. - */ - u16 penirq_recheck_delay_usecs; - - u16 x_min, x_max; - u16 y_min, y_max; - - u16 debounce_max; /* max number of additional readings - * per sample */ - u16 debounce_tol; /* tolerance used for filtering */ - u16 debounce_rep; /* additional consecutive good readings - * required after the first two */ - int gpio_pendown; /* the GPIO used to decide the pendown - * state if get_pendown_state == NULL - */ - char pendown_iomux_name[IOMUX_NAME_SIZE]; - int pendown_iomux_mode; - int touch_ad_top; - int touch_ad_bottom; - int touch_ad_left; - int touch_ad_right; - int touch_virtualkey_length; - int (*get_pendown_state)(void); - int (*filter_init) (struct xpt2046_platform_data *pdata, - void **filter_data); - int (*filter) (void *filter_data, int data_idx, int *val); - void (*filter_cleanup)(void *filter_data); - void (*wait_for_sync)(void); - int (* io_init)(void); - int (* io_deinit)(void); -}; -#endif