现在的位置: 首页 > 综合 > 正文

msg2033触摸屏驱动可模拟KEY_HOME KEY_BACK KEY_MENU

2013年04月24日 ⁄ 综合 ⁄ 共 19637字 ⁄ 字号 评论关闭
#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");

抱歉!评论已关闭.