#include <mach/hardware.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <mach/clock.h>
#include <linux/slab.h>
#include "os.h"
#include "tscr.h"
#include "tsc.h"
#include <linux/interrupt.h>
#include <asm/gpio.h>
#include <mach/clock.h>
#include "i2c.h"
#include <linux/timer.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/init.h>
#include <linux/serio.h>
#include <linux/delay.h>
#include <linux/hwmon.h>
#include <linux/timer.h>
#include <linux/platform_device.h>
#include <mach/hardware.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <asm/gpio.h>
#include <mach/clock.h>
#define u8 unsigned char
#define u32 unsigned int
#define s32 signed int
//#define KEY_HOME 102
//#define KEY_BACK 158
//#define KEY_MENU 139
#define TP_I2C_DEVICE_ID 0xc0
#define REPORT_PACKET_LENGTH 8
#define X_MAX 2047
#define Y_MAX 2047
#define AUO_INT_LOW 1
#define TOUCH_INT_PIN GPIO_NUM(3,17)
#define down 0
#define up 1
static int lx,ly,lx1,ly1;
int ON_TOUCH_INT;
int resx=0,resy=0;
static int pendown = 0;
static int penup=0;
static uint32_t irq;
/* struct of touch information to the middleware or applications */
typedef struct
{
u32 u32X; /* X coordinate, 0~2047 */
u32 u32Y; /* Y coordinate, 0~2047 */
u8 u8Finger; /* Number of fingers in the touch event */
u32 u32Dis_X; /* X distance between two fingers */
u32 u32Dis_Y; /* Y distance between two fingers. This value could be negative */
} TOUCH_DATA_st;
/* Structure for Input Type*/
struct auo_tp2_ts{
struct input_dev * dev;
int xpos;
int ypos;
char phys[32]; //for raw data or others
};
static struct auo_tp2_ts *mic_ts;
static struct work_struct work;
static struct workqueue_struct *wq;
static void microwell_tsc_work(struct work_struct *work);
#if 1
struct timer_list CY_timer;
void Delay(int ms)
{
unsigned long j,stamp_1;
j=jiffies;
stamp_1=j+ ms*HZ/1000;
while(1)
{
j=jiffies;
if(j>=stamp_1)
return ;
}
}
/
/// @brief Calculate the 8-bit checksum of the given data array
/// @author Chao-Cheng Wen
/// @param[in] msg the pointer to the data
/// @param[in] s32Length the length of the data in bytes
///
/// Calculate the 8-bit checksum of the given data array. This is a
/// simple algorithm to make the sum of data and checksum to be zero.
/// The porblem of zero-lossage exists in this algorithm.
/
u8 Calculate_8BitsChecksum( u8 *msg, s32 s32Length )
{
s32 s32Checksum = 0;
s32 i;
for ( i = 0 ; i < s32Length; i++ )
{
s32Checksum += msg[i];
}
//printk("_in Calculate_8BitsChecksum____________calc_checksum=0x%x\n___________",( -s32Checksum ) & 0xFF );
return (u8)( ( -s32Checksum ) & 0xFF );
}
int Msctpc_getData(struct input_dev *inputp, TOUCH_DATA_st *touchData);
void timer_callback()
{
CY_timer.expires = jiffies + 1000;
add_timer(&CY_timer);
printk("i am in: timer_callback\n");
}
static int timer_start(void)
{
init_timer(&CY_timer);
CY_timer.expires = 1000;
add_timer(&CY_timer);
return 0;
}
static int timer_init(void)
{
init_timer(&CY_timer);
CY_timer.expires = 1000;
CY_timer.function = timer_callback;
add_timer(&CY_timer);
return 0;
}
#endif
void delay()
{
int i,j;
for(i=0;i<1000;i++)
for(j=0;j<1000;j++);
}
#define BH_TIMER
// added by andely 2009-12-29
#include <linux/spinlock.h>
// added by andely 2010-03-08
// CONFIG_SSLTSC_FOR_BATTERY defined in kernel configure file
#ifdef CONFIG_SSLTSC_FOR_BATTERY
#warning "ssltsc.ko only define for Battery detect!!!"
#else
#warning "ssltsc.ko define for Battery detect and TSC function!!!"
#endif
#define PRESSURE_SUPPORT 1
#define TSC_RST_TIMEOUT 0x100
#define TSC_MSR_VAL 0x80
#define TSC_WUR_VAL 0x100
#define TSC_MASK_VAL 0x00FF00FF
#define SUPPLY 3347
#define MMT_VBAT (0x00 << 4)
#define MMT_AUX (0x03 << 4)
#define MMT_AUX1 (0x04 << 4)
#define TSC_EN (0x01 << 0)
#define TSC_RST (0x01 << 1)
#define TSC_GO (0x01 << 2)
#define ISR_DR (0x01 << 0)
#define TSC_CAL_RESET "reset"
#define TSC_CAL_SHOW "show"
#define PT_BUF_LEN 3
#define TSC_X_MAX 0x3FF
#define TSC_Y_MAX 0x3FF
tsc_t buf[PT_BUF_LEN];
int pt_out=0,pt_shift=0;
static tsc_cal_t calibrate ={1,0,0,0,1,0,1};
typedef struct
{
tsc_t hw;
uint32_t xpos;
uint32_t ypos;
uint32_t xold;
uint32_t yold;
uint32_t xup;
uint32_t yup;
char phys[32];
TOUCH_DATA_st *touchData;
uint32_t irq;
spinlock_t spin_lock;
struct input_dev *input_dev;
/* n us delay between samples. */
uint32_t poll_period;
/* TSC bottom half. */
#ifdef BH_TIMER
struct hrtimer timer;
#elif defined BH_WQ
struct workqueue_struct *wq;
struct work_struct work;
#endif
uint32_t pen_touch; //Last pen state: 1> pen down, 0>pen up.
uint32_t count;
/* debounce fliter */
uint32_t read_cnt;
uint32_t read_rep;
uint32_t debounce_max;
int32_t last_read_x, last_read_y;
int32_t debounce_tol_x, debounce_tol_y;
uint32_t debounce_tol_p;
uint32_t debounce_rep;
uint32_t filter_en;
int (*filter) (void *data, int32_t * val_x, int32_t * val_y,
uint32_t * val_p);
} ssltsc_ctx;
#define ADC_TIMEOUT 1000
#define ADC_TIMES 100
#define sample_period (10*1000000)
uint32_t g_vbat_val;
static ssltsc_ctx ts;
static tsc_cfg_p cfg; /* TSC configuration. */
int Msctpc_getData(struct input_dev *inputp, TOUCH_DATA_st *touchData)
{
u8 val[REPORT_PACKET_LENGTH] = {0};
int i=0;int key=0;
int errnum=0;
u8 Checksum = 0;
touchData->u32X = 0;
touchData->u32Y = 0;
touchData->u32Dis_X = 0;
touchData->u32Dis_Y = 0;
touchData->u8Finger = 0;
penup=0;
pendown=0;
while(errnum<5)
{
lx=2048;
ly=2048;
/* Read 8-bytes data from the TP controller. */
/* By default, the TP controller supports 120k SCL rate and duty cycle is 50% */
// Msctpc_ReadI2C( TP_I2C_DEVICE_ID, &val[0], REPORT_PACKET_LENGTH );
Msctpc_ReadI2C_Seq(TP_I2C_DEVICE_ID, &val[0], REPORT_PACKET_LENGTH );
Checksum = Calculate_8BitsChecksum( val, (REPORT_PACKET_LENGTH-1) );
if ( ( Checksum == val[7] && val[0] == 0x52 ) ) // Check the packet ID(0x52)and checksum
{
printk("***********************\n");
for(i=0;i<REPORT_PACKET_LENGTH ;i++)
{
if(i%8==0)
printk("\n");
printk("*0x%x\t",val[i]);
}
printk("***********************\n");
// key=0;
if(val[5]==0x1)//menu
{
if(key==0)
{
key=KEY_MENU;
input_report_key (inputp, KEY_MENU, 1);
printk("menu\n");
input_sync(inputp);
}
continue;
}
else if(val[5]==0x2)//home
{
if(key==0)
{
key=KEY_HOME;
input_report_key (inputp, KEY_HOME, 1);
printk("home\n");
input_sync(inputp);
}
continue;
}
else if(val[5]==0x4)//back
{
if(key==0)
{
key=KEY_BACK;
input_report_key (inputp, KEY_BACK, 1);
printk("back\n");
input_sync(inputp);
}
continue;
}
/* parsing the coordinate report packet */
/* MSG20XX EVK report format */
/*
* +---------------------------------+
* byte[0] | Packet ID ( 0x52 ) |
* +----------------+----------------+
* byte[1] | u32X[11:8] | u32Y[11:8] |
* +---------------------------------+
* byte[2] | u32X[7:0] |
* +---------------------------------+
* byte[3] | u32Y[7:0] |
* +----------------+----------------+
* byte[4] | u32Dis_X[11:8] | u32Dis_Y[11:8] |
* +----------------+----------------+
* byte[5] | u32Dis_X[7:0] |
* +---------------------------------+
* byte[6] | u32Dis_Y[7:0] |
* +---------------------------------+
* byte[7] | Checksum |
* +---------------------------------+
*/
touchData->u32X = ( val[1] & 0xF0 ) << 4 | val[2];
touchData->u32Y = ( val[1] & 0x0F )<< 8 | val[3];
touchData->u32Dis_X = ( val[4] & 0xF0 ) << 4 | val[5];
touchData->u32Dis_Y = ( val[4] & 0x0F ) << 8 | val[6];
if ( touchData->u32X == 0xFFF && touchData->u32Y == 0xFFF && touchData->u32Dis_X == 0x000&& touchData->u32Dis_Y == 0xFF )
{
penup=1;
input_report_abs(inputp, ABS_X,-100);
input_report_abs(inputp, ABS_Y, 0);
input_report_abs (inputp, ABS_PRESSURE, 1);
input_report_key (inputp, BTN_TOUCH, 0);
printk("one report:x=%d,y=%d\, up\n",lx,ly);
input_report_abs(inputp, ABS_PRESSURE, 0);
printk("<<<<<<<<<<<pen up!!!!!!!!!,btn=0,pressure=0,sync\n");
input_sync(inputp);
printk(" >in Msctpc_getData >>>>>>>>>>Touch-End event\n");
return 0; /* The coordinate report stands for a Touch-End event */
/* Inform the OS or system mailbox that the Touch-End event happened */
}
else
{
//printk(" >>in Msctpc_getData >>>>>>>>>Touch-On-Panel event\n");
lx=touchData->u32X;
ly=touchData->u32Y;
printk("read one : x=%d,y=%d\n",lx,ly);
errnum=0;
/* The coordinate report stands for Touch-On-Panel event */
if ( touchData->u32Dis_X == 0 && touchData->u32Dis_Y == 0 )
{
/* If the distance values are zero, the TP detects one-finger-touch event */
//printk(">>>>in Msctpc_getData >>>>>>>>>>>>one finger\n");
touchData->u8Finger = 1;
if(X_MAX==1023)
{
lx=1023-(lx>>1);
ly=ly>>1;
}
else if(X_MAX==2047)
{
lx=2047-lx;
}
if(pendown==0)
{
input_report_key (inputp, BTN_TOUCH, 1);
printk("<<<<<<<<<<<pen down!!!!!!!!!,btn_touch=1\n");
}
input_report_abs(inputp, ABS_X,(lx));
input_report_abs(inputp, ABS_Y, ly);
pendown=1;
input_report_abs (inputp, ABS_PRESSURE, 1);
input_sync(inputp);
printk("<x,y,pressure=1,sync\n");
printk("after calibrate and report down: x=%d,y=%d\n",lx,ly);
continue;
//Msctpc_getData(inputp, touchData);
}
else if ( touchData->u32Dis_X <= 2047 && touchData->u32Dis_Y <= 2047 )
{
/* If the distance values are valid, the TP detects two-finger-touch event */
//printk(">>>>in Msctpc_getData >>>>>>>two finger\n");
touchData->u8Finger = 2;
/*
lx1=touchData->u32X+touchData->u32Dis_X;
ly1=touchData->u32Y+touchData->u32Dis_Y;
input_report_abs(inputp, ABS_MT_POSITION_X,1023-(lx>>1));
input_report_abs(inputp, ABS_MT_POSITION_Y, ly>>1);
input_report_abs(inputp,ABS_MT_TOUCH_MAJOR, 1);
printk("two mulit report1:x=%d,y=%d\,finger=1\n",1023-(lx>>1),ly>>1);
input_mt_sync(inputp);
input_report_abs(inputp, ABS_MT_POSITION_X,1023-(lx1>>1));
input_report_abs(inputp, ABS_MT_POSITION_Y, ly1>>1);
printk("two mulit report2:x=%d,y=%d\,finger=1\n",1023-(lx1>>1),ly1>>1);
input_report_abs(inputp,ABS_MT_TOUCH_MAJOR, 1);
input_mt_sync(inputp);
input_sync(inputp);
printk("two -r\n");
continue;
*/
//Msctpc_getData(inputp, touchData);
}
else
{
/* Fetal error */
printk("in Msctpc_getData :Fetal error,discard the data\n");
return -1;
/* Discard the invalid coordinate reports due to fetal error. */
}
}
}
else
{
printk("in Msctpc_getData :Packet error happened. \n");
errnum++;
//
/* Packet error happened. */
/* Check I2C signal quality and I2C master codes */
}
}
if(pendown==1)
{
input_report_key (inputp, BTN_TOUCH, 0);
input_report_abs (inputp, ABS_PRESSURE, 0);
input_sync(inputp);
printk("<<<<<<<<<<<pen up!!!!!!!!!,btn_touch=0,pressure=0,sync\n");
}
if(key>0)
{
input_report_key (inputp, key, 0);
printk("%d release\n",key);
input_sync(inputp);
}
//enable_irq(ts.irq);
return -2;
}
static char *ssltsc_name = "SSL TouchScreen";
static int pen_up_flg=0;
static float ax = 4.3268f;
static float bx = 29.3883f;
static float ay = 3.86444f;
static float by = 32.08083f;
static int use_flag = 0;
#if (defined CONFIG_ARCH_OPTIMUS_REPLOID || defined CONFIG_ARCH_OPTIMUS_REPLOID3)
/* debounce fliter */
#define X_LIMIT 0x3
#define Y_LIMIT 0x3
#define P_LIMIT 0x144
//#define P_LIMIT 0xFFFF // Disable the Pressure filter.
#define TSC_DEBUNCE_MAX 10
#define TSC_DEBUNCE_REP 2
#define TS_POLL_PERIOD (10 * 1000) /* us delay between samples */
#else
/* debounce fliter */
#define X_LIMIT 0xA
#define Y_LIMIT 0xA
#define P_LIMIT 0x1cc
//#define P_LIMIT 0xFFFF // Disable the Pressure filter.
#define TSC_DEBUNCE_MAX 10
#define TSC_DEBUNCE_REP 2
#define TS_POLL_PERIOD (20 * 1000) /* us delay between samples */
#endif
//#define TS_POLL_PERIOD (5 * 1000) /* us delay between samples */
#define IRQ_TSC OPTIMUS_IRQ_TSC
#define SSL_TSC_REG_ADDR OPTIMUS_IO_TSC
#define TSC_GET_CLK_IN() optimus_get_pclk();//OPTIMUS_CLK_PER1
#ifndef CONFIG_SSLTSC_FOR_BATTERY
static int ssltsc_debounce (void *ads, int *val_x, int *val_y,
uint32_t * val_p);
static int ssltsc_no_filter (void *ads, int *val_x, int *val_y,
uint32_t * val_p);
static ssize_t ssltsc_parameter_show (struct device *dev,
struct device_attribute *attr, char *buf);
static ssize_t ssltsc_parameter_store (struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count);
static DEVICE_ATTR (parameter, 0664, ssltsc_parameter_show,
ssltsc_parameter_store);
#endif
static ssize_t ssltsc_vbat_show (struct device *dev,
struct device_attribute *attr, char *buf);
static DEVICE_ATTR (vbat, 0664, ssltsc_vbat_show, NULL);
static ssize_t ssltsc_calibrate_set (struct device *dev,
struct device_attribute *attr, char *buf);
static DEVICE_ATTR (calibrate, 0664, NULL, ssltsc_calibrate_set);
static struct attribute_group ssltsc_attr_group = {
.attrs = ssltsc_attributes,
};
EXPORT_SYMBOL(ssltsc_vbat);
static ssize_t ssltsc_vbat_show (struct device *dev,
struct device_attribute *attr, char *buf)
{
uint32_t voltage = ssltsc_vbat();
return sprintf (buf, "%d\n", voltage);
}
void ssl_calibrate_for_Android(int32_t *x, int32_t *y)
{
int32_t tx,ty;
tx=*x;
ty=*y;
*x=(calibrate.a*tx + calibrate.b *ty +calibrate.c) / calibrate.div;
*y=(calibrate.d*tx + calibrate.e *ty +calibrate.f) / calibrate.div;
if ( *x < 0 ) *x = 0;
if ( *y < 0 ) *y = 0;
if ( *x > TSC_X_MAX ) *x = TSC_X_MAX;
if ( *y > TSC_Y_MAX ) *y = TSC_Y_MAX;
}
static ssize_t ssltsc_calibrate_set (struct device *dev,
struct device_attribute *attr, char *buf)
{
int32_t a,b,c,d,e,f,div;
uint32_t x,y;
db_tsc("get the argument: %s\n", buf);
if (strncmp(buf,TSC_CAL_RESET,sizeof(TSC_CAL_RESET)-1)==0)
{
db_tsc("will reset the calibration data\n");
calibrate.a=1;
calibrate.b=0;
calibrate.c=0;
calibrate.d=0;
calibrate.e=1;
calibrate.f=0;
calibrate.div=1;
goto _exit;
}
if (strncmp(buf,TSC_CAL_SHOW,sizeof(TSC_CAL_SHOW)-1)==0)
{
x=100;y=200;
ssl_calibrate_for_Android(&x, &y);
printk("(100,200) -> (%d, %d)\n", x,y);
x=900;y=200;
ssl_calibrate_for_Android(&x, &y);
printk("(900,200) -> (%d, %d)\n", x,y);
x=100;y=800;
ssl_calibrate_for_Android(&x, &y);
printk("(100,800) -> (%d, %d)\n", x,y);
x=900;y=800;
ssl_calibrate_for_Android(&x, &y);
printk("(900,800) -> (%d, %d)\n", x,y);
goto _exit;
}
sscanf(buf,"%d %d %d %d %d %d %d",&a,&b,&c,&d,&e,&f,&div);
if (0==div)
{
db_err("canot set the div to 0!\n");
goto _exit;
}
calibrate.a=a;
calibrate.b=b;
calibrate.c=c;
calibrate.d=d;
calibrate.e=e;
calibrate.f=f;
calibrate.div=div;
_exit:
printk("calibration data:\n %d %d %d %d %d %d %d\n",calibrate.a, calibrate.b,\
calibrate.c,calibrate.d, calibrate.e,calibrate.f,calibrate.div);
return -1;
}
#ifndef CONFIG_SSLTSC_FOR_BATTERY
static ssize_t ssltsc_parameter_show (struct device *dev,
struct device_attribute *attr, char *buf)
{
uint32_t clk, pclk;
pclk = TSC_GET_CLK_IN ();
db_tsc ("parameter show. pclk=%d Hz\n", pclk);
clk = TSC_FROM_DIV (pclk, cfg->div);
return sprintf (buf,
"<SSL TSC parameter 1>\n<debounce>\n filter: %s, (x/y/p): %d/%d/%d/, repeat:%d, max:%d\n<sampling>\n clk:%d Hz, poll:%d us, power mode:0x%x\n",
ts.filter_en ? "yes" : "no", ts.debounce_tol_x,
ts.debounce_tol_y, ts.debounce_tol_p, ts.debounce_rep,
ts.debounce_max, clk, ts.poll_period, cfg->pmd);
}
static int ssltsc_no_filter (void *ads, int *val_x, int *val_y,
uint32_t * val_p)
{
return TSC_FILTER_OK;
}
/*
* This function have these feature:
* 1. while the first data is ready, that means pen down.
* 2. while data action, that means need to sync event handler.
* 3. while pen up, sync pen up event. And wait for pen down even.
*
**/
#ifdef BH_TIMER
static enum hrtimer_restart ssltsc_timer (struct hrtimer *handle)
{
ssltsc_ctx *ts_dev = container_of(handle, ssltsc_ctx, timer);
//struct input_dev *dev;
uint32_t delay;
int touchstate;//high is release
printk("in ssltsc_timer\n");
spin_lock_irq(ts_dev->spin_lock);
printk("0s\n");
ts_dev->touchData=kzalloc(sizeof(TOUCH_DATA_st), GFP_KERNEL);
Msctpc_getData( ts_dev->input_dev,ts_dev->touchData );
spin_unlock_irq(ts_dev->spin_lock);
return HRTIMER_NORESTART;
}
#elif defined BH_WQ
static void ssltsc_worker (struct work_struct *work)
{
uint32_t delay;
ssltsc_bottom_half ();
/* Delay each even. If not, the interrupt come up frequently. At least it will delay 10 ms as 1 jiffes=10ms */
delay = ts.poll_period / 1000000 * HZ; // us to jiffes.
if (!delay)
delay = 1;
schedule_timeout_uninterruptible (delay);
enable_irq (ts.irq);
if (pen_up_flg)
{
queue_work (ts.wq, &ts.work);
schedule_timeout_uninterruptible (delay);
}
}
#endif
#endif
static tsc_err tsc_isr_cy (tsc_p t)
{
//disable_irq(ON_TOUCH_INT);
int i;
int sumx=0,sumy=0;
return TSC_ERR_NONE;
}
static irqreturn_t ssltsc_irq (int irq, void *dev_id)
{
uint32_t ret, bf_en;
debounce_ret deb_ret;
uint32_t irq_flags;
printk(">>>>>>>>>enter irq...........\n");
spin_lock_irq(&ts.spin_lock);
hrtimer_start (&ts.timer, ktime_set(0,sample_period),HRTIMER_MODE_REL);
spin_unlock_irq(&ts.spin_lock);
return IRQ_HANDLED;
}
/*
* The functions for inserting/removing us as a module.
*/
static int __init ssltsc_probe (struct platform_device *dev)
{
int err;
struct input_dev *input_dev;
/* Initialise tsc_t structure. */
memset (&ts, 0, sizeof (tsc_t));
printk("in ssltsc_probe,%d\n",gpio_get_value(TOUCH_INT_PIN));
ts.hw.reg =
(void __iomem *) ioremap_nocache (SSL_TSC_REG_ADDR, sizeof (tscr_t));
if (ts.hw.reg == NULL)
{
db_err ("Failed to remap register block \n");
err = -ENOMEM;
goto l_iomap;
}
/* Initial TSC module */
err = (int) tsc_init (&ts.hw);
if (err)
{
db_err ("init tsc failed.\n");
goto l_tsc_init;
}
pendown = 0;
#ifndef CONFIG_SSLTSC_FOR_BATTERY
#ifdef BH_TIMER
#warning "timer bottom half."
/*initial timer. */
hrtimer_init (&ts.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
ts.timer.function = ssltsc_timer;
db_tsc ("timer bottom half.\n");
#elif defined BH_WQ
#warning "work queue bottom half."
/*initial work queue. */
INIT_WORK (&ts.work, ssltsc_worker);
ts.wq = create_singlethread_workqueue (dev->name);
db_tsc ("work queue bottom half.\n");
if (!ts.wq)
{
db_err ("create wq fail.\n");
err = -EBUSY;
goto l_wq_err;
}
#elif defined BH_NONE
#warning "NO bottom half."
db_tsc ("no bottom half.\n");
#else
#error "****** NO define bottom half.********"
#endif
#endif
platform_set_drvdata(dev, &ts);
#ifndef CONFIG_SSLTSC_FOR_BATTERY
/*initial input system. */
input_dev = input_allocate_device ();
if (!input_dev)
{
printk (KERN_ERR "Unable to allocate the input device !!\n");
err = -ENOMEM;
goto l_input_dev;
}
ts.input_dev = input_dev;
ts.input_dev->evbit[0] =
BIT_MASK (EV_SYN) | BIT_MASK (EV_KEY) | BIT_MASK (EV_ABS);
ts.input_dev->keybit[BIT_WORD (BTN_TOUCH)] = BIT_MASK (BTN_TOUCH);
ts.input_dev->keybit[BIT_WORD (KEY_HOME)] = BIT_MASK (KEY_HOME);
ts.input_dev->keybit[BIT_WORD (KEY_BACK)] = BIT_MASK(KEY_BACK)|BIT_MASK(KEY_MENU);
ts.input_dev->name = ssltsc_name;
snprintf(ts.phys,sizeof(ts.phys),"%s/input0",dev_name(dev));
ts.input_dev->phys = ts.phys;
input_set_abs_params (ts.input_dev, ABS_X, 0, X_MAX, 0, 0);
input_set_abs_params (ts.input_dev, ABS_Y, 0, Y_MAX, 0, 0);
input_set_abs_params (ts.input_dev, ABS_PRESSURE, 0, 1, 0, 0);
//input_set_abs_params(ts.input_dev, ABS_HAT0X, 0, X_MAX, 0, 0);
//input_set_abs_params(ts.input_dev, ABS_HAT0Y, 0,Y_MAX, 0, 0);
/* All went ok, so register to the input system */
err = input_register_device (ts.input_dev);
if (err)
{
db_err ("register input system failed (%d).\n", err);
goto l_reg_input;
}
/* Initial debounce paramter */
ts.debounce_max = TSC_DEBUNCE_MAX;
ts.debounce_tol_x = X_LIMIT;
ts.debounce_tol_y = Y_LIMIT;
ts.debounce_tol_p = P_LIMIT;
ts.debounce_rep = TSC_DEBUNCE_REP;
ts.filter_en = 1;
ts.filter = ssltsc_debounce;
ts.poll_period = TS_POLL_PERIOD;
cfg = &ssltsc_default_cfg;
#else
/* Initial debounce paramter */
ts.debounce_max = 10;
ts.debounce_tol_x = X_LIMIT;
ts.debounce_tol_y = Y_LIMIT;
ts.debounce_tol_p = P_LIMIT;
ts.debounce_rep = 4;
//ts.debounce_rep = 2;
ts.filter_en = 1;
ts.filter = NULL;
ts.poll_period = TS_POLL_PERIOD;
cfg = &ssltsc_default_cfg;
ts.input_dev = NULL;
#endif
err = (int) tsc_cfg (&ts.hw, cfg);
if (err)
{
db_err ("cfg tsc failed.\n");
goto l_tsc_cfg;
}
spin_lock_init(&ts.spin_lock);
ON_TOUCH_INT = gpio_to_irq(TOUCH_INT_PIN);
if (AUO_INT_LOW)
{
set_irq_type(irq, IRQ_TYPE_EDGE_FALLING);
}
else
{
set_irq_type(irq, IRQ_TYPE_EDGE_RISING);
}
if (request_irq(ON_TOUCH_INT, ssltsc_irq, IRQF_DISABLED|IRQF_TRIGGER_FALLING, "ssltsc", ts.input_dev))
{
printk("request_irq erro\n");
return -1;
}
else
{
printk(">>>>>end request_irq\n");
}
/* Create sysfs attributes to monitor TSC. */
err = sysfs_create_group (&dev->dev.kobj, &ssltsc_attr_group);
if (err)
{
db_err ("Can't create sysfs attributes!\n ");
goto l_sysfs;
}
printk (KERN_INFO "%s successfully loaded \n", ssltsc_name);
return 0;
/*Error */
l_sysfs:
free_irq (IRQ_TSC, ts.input_dev);
l_irq:
l_tsc_cfg:
input_unregister_device (ts.input_dev);
l_reg_input:
//input_free_device (ts.input_dev);
l_input_dev:
#ifdef BH_WQ
destroy_workqueue (ts.wq);
l_wq_err:
#endif
tsc_exit (&ts.hw);
l_tsc_init:
iounmap (ts.hw.reg);
l_iomap:
db_err ("loaded fail.(%d)\n", err);
return err;
}
static int ssltsc_remove (struct platform_device *dev)
{
/* Remove sysfs attributes */
sysfs_remove_group (&dev->dev.kobj, &ssltsc_attr_group);
/* free irq. */
free_irq (IRQ_TSC, ts.input_dev);
/* free timer. */
#ifdef BH_WQ
flush_workqueue (ts.wq);
destroy_workqueue (ts.wq);
#endif
/* free module. */
tsc_exit (&ts.hw);
#ifndef CONFIG_SSLTSC_FOR_BATTERY
/* free input system. */
input_unregister_device (ts.input_dev);
//input_free_device (ts.input_dev);
#endif
/* free memory. */
iounmap (ts.hw.reg);
return 0;
}
void ssltsc_device_release (struct device *dev)
{
return;
}
static struct platform_device ssltsc_device = {
.name = "ssltsc",
.id = -1,
.dev = {
.release = ssltsc_device_release,
}
};
static struct platform_driver ssltsc_driver = {
.driver = {
.name = "ssltsc",
.owner = THIS_MODULE,
},
.probe = ssltsc_probe,
.remove = ssltsc_remove,
};
int __init ssltsc_init (void)
{
int ret;
db_tsc ("insmod ssltsc.\n");
#if 1 //device
ret = platform_device_register (&ssltsc_device);
if (ret)
return ret;
#endif
return platform_driver_register (&ssltsc_driver);
}
void __exit ssltsc_exit (void)
{
platform_driver_unregister (&ssltsc_driver);
#if 1 //device
platform_device_unregister (&ssltsc_device);
#endif
db_tsc ("rmmod ssltsc.\n");
}
module_init (ssltsc_init);
module_exit (ssltsc_exit);
MODULE_AUTHOR ("Spiritwen@solomon-systech.com");
MODULE_DESCRIPTION ("Optimus TSC Device Driver");
MODULE_LICENSE ("GPL");
msg2033触摸屏驱动可模拟KEY_HOME KEY_BACK KEY_MENU
最新推荐文章于 2022-01-13 11:15:49 发布