210电阻屏驱动

#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/platform_device.h>
#include <linux/clk.h>
#include <asm/io.h>
#include <asm/irq.h>
static struct input_dev *s3c_ts_dev;
static struct timer_list ts_timer;


static struct timer_list ts_timer;

struct qt210_ts_regs {
	unsigned long tsadccon0;
	unsigned long tscon0;
	unsigned long tsdly0;
	unsigned long tsdatx0;
	unsigned long tsdaty0;
	unsigned long tspenstat0;
	unsigned long clrintadc0;
	unsigned long not;
	unsigned long clrintpen0;
	};
struct qt210_ts_regs *qt210_ts_regs;
static void enter_wait_pen_down_mode(void)
{
	printk(KERN_DEBUG"%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
	qt210_ts_regs->tscon0=0xd3;
		
}

static void enter_wait_pen_up_mode(void)
{
	printk(KERN_DEBUG"%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
	qt210_ts_regs->tscon0=0x1d3;
}

static void enter_measure_xy_mode(void)
{
	printk(KERN_DEBUG"%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
	qt210_ts_regs->tscon0=0x5C;
}

static void start_adc(void)
{
	printk(KERN_DEBUG"%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
	qt210_ts_regs->tsadccon0 |=(1<<0);
}


static int s3c_filter_ts(int x[], int y[])
{
	#define ERR_LIMIT 10
		printk(KERN_DEBUG"%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
	int avr_x, avr_y;
	int det_x, det_y;

	avr_x = (x[0] + x[1])/2;
	avr_y = (y[0] + y[1])/2;

	det_x = (x[2] > avr_x) ? (x[2] - avr_x) : (avr_x - x[2]);
	det_y = (y[2] > avr_y) ? (y[2] - avr_y) : (avr_y - y[2]);

	if ((det_x > ERR_LIMIT) || (det_y > ERR_LIMIT))
		return 0;
	printk(KERN_DEBUG"%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
	avr_x = (x[1] + x[2])/2;
	avr_y = (y[1] + y[2])/2;

	det_x = (x[3] > avr_x) ? (x[3] - avr_x) : (avr_x - x[3]);
	det_y = (y[3] > avr_y) ? (y[3] - avr_y) : (avr_y - y[3]);

	if ((det_x > ERR_LIMIT) || (det_y > ERR_LIMIT))
		return 0;
		printk(KERN_DEBUG"%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
	return 1;
}	

static void s3c_ts_timer_function(unsigned long data)
{
	if(qt210_ts_regs->tsdatx0&(1<<15))
	{
			printk(KERN_DEBUG"%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
		input_report_abs(s3c_ts_dev, ABS_PRESSURE, 0);
		input_report_key(s3c_ts_dev, BTN_TOUCH, 0);
		input_sync(s3c_ts_dev);
		enter_wait_pen_down_mode();
	}
	else
	{
		printk(KERN_DEBUG"%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
		enter_measure_xy_mode();
		start_adc();
		printk(KERN_DEBUG"%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
	}
}	
static irqreturn_t pen_down_up_irq(int irq, void *dev_id)
{
	printk(KERN_DEBUG"%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
	if(qt210_ts_regs->tsdatx0&(1<<15))//up
	{
		input_report_abs(s3c_ts_dev, ABS_PRESSURE, 0);
		input_report_key(s3c_ts_dev, BTN_TOUCH, 0);
		input_sync(s3c_ts_dev);
		enter_wait_pen_up_mode();
		printk(KERN_DEBUG"%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
	}
	else//down
	{
		printk(KERN_DEBUG"%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
		enter_measure_xy_mode();
		start_adc();
		printk(KERN_DEBUG"%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
	}
	return IRQ_HANDLED;
}	
static irqreturn_t adc_irq(int irq,void *dev)
{
	static int cnt=0;
	static int x[4],y[4];
	int adcdat0,adcdat1;
	adcdat0=qt210_ts_regs->tsdatx0;
	adcdat1=qt210_ts_regs->tsdaty0;
	printk(KERN_DEBUG"%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
	if (qt210_ts_regs->tsdatx0 & (1<<15))
	{
		printk(KERN_DEBUG"%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
		/* 已经松开 */
		cnt = 0;
		input_report_abs(s3c_ts_dev, ABS_PRESSURE, 0);
		input_report_key(s3c_ts_dev, BTN_TOUCH, 0);
		input_sync(s3c_ts_dev);
		enter_wait_pen_down_mode();
	}
	else
	{
		printk(KERN_DEBUG"%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
		/* 优化措施3: 多次测量求平均值 */
		x[cnt] = adcdat0 & 0x3ff;
		y[cnt] = adcdat1 & 0x3ff;
		++cnt;
		if (cnt == 4)
		{
			printk(KERN_DEBUG"%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
			/* 优化措施4: 软件过滤 */
			if (s3c_filter_ts(x, y))
			{			
				input_report_abs(s3c_ts_dev, ABS_X, (x[0]+x[1]+x[2]+x[3])/4);
				input_report_abs(s3c_ts_dev, ABS_Y, (y[0]+y[1]+y[2]+y[3])/4);
			
				input_report_abs(s3c_ts_dev, ABS_PRESSURE, 1);
				input_report_key(s3c_ts_dev, BTN_TOUCH, 1);
				input_sync(s3c_ts_dev);
				printk("x = %d, y = %d\n", (x[0]+x[1]+x[2]+x[3])/4, (y[0]+y[1]+y[2]+y[3])/4);
			}
			cnt = 0;
			enter_wait_pen_up_mode();

			/* 启动定时器处理长按/滑动的情况 */
			mod_timer(&ts_timer, jiffies + HZ/100);
		}
		else
		{
			printk(KERN_DEBUG"%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
			enter_measure_xy_mode();
			start_adc();
		}		
	
	}
	return IRQ_HANDLED;
}	

static int qt210_touch_init()
{
	struct clk *clk;
	/* 1. 分配一个input_dev结构体 */
	unsigned long tsadccon1;
	s3c_ts_dev =input_allocate_device();

	/* 2. 设置 */
	/* 2.1 能产生哪类事件 */
	
	/* 2.2 能产生这类事件里的哪些事件 */
	set_bit(EV_KEY, s3c_ts_dev->evbit);
	set_bit(EV_ABS, s3c_ts_dev->evbit);

	/* 2.2 能产生这类事件里的哪些事件 */
	set_bit(BTN_TOUCH, s3c_ts_dev->keybit);

	input_set_abs_params(s3c_ts_dev, ABS_X, 0, 0xFFF, 0, 0);
	input_set_abs_params(s3c_ts_dev, ABS_Y, 0, 0xFFF, 0, 0);
	input_set_abs_params(s3c_ts_dev, ABS_PRESSURE, 0, 1, 0, 0);
	input_register_device(s3c_ts_dev);

	 /* 4. 硬件相关的操作 */
	/* 4.1 使能时钟(CLKCON[15]) */
	clk = clk_get(NULL, "adc");
	if (!clk || IS_ERR(clk)) {
		printk(KERN_INFO "failed to get adc clock source\n");
	}
	clk_enable(clk);
	qt210_ts_regs =ioremap(0xE1700000 ,sizeof(struct qt210_ts_regs) );
	tsadccon1	=ioremap(0xE1701000 ,4 );
	tsadccon1|=(1<<17);
	printk("%d",sizeof(struct qt210_ts_regs))	;
	
	

	qt210_ts_regs->tsadccon0&=~((0xff << 6) | (1<<2)|(1<<17));
	qt210_ts_regs->tsadccon0|=(1<<14)|(65<<6)|(1<<16);

	qt210_ts_regs->tsdly0=0xffff;
		/* 优化措施5: 使用定时器处理长按,滑动的情况
	 * 
	 */
	 request_irq(IRQ_TC ,pen_down_up_irq,IRQF_SHARED,"ts_pen",NULL);
	request_irq(IRQ_ADC,adc_irq,IRQF_SHARED,"adc",NULL);
	init_timer(&ts_timer);
	ts_timer.function= s3c_ts_timer_function;
	add_timer(&ts_timer);
	printk(KERN_DEBUG"%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
	enter_wait_pen_down_mode();
	printk(KERN_DEBUG"%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
	
	return 0;
}
static void qt210_touch_exit()
{
	free_irq(IRQ_TC, NULL);
	free_irq(IRQ_ADC, NULL);
	input_unregister_device(s3c_ts_dev);
	input_free_device(s3c_ts_dev);
	del_timer(&ts_timer);

}
module_init(qt210_touch_init);
module_exit(qt210_touch_exit);
MODULE_LICENSE("GPL");

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值