#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");
210电阻屏驱动
最新推荐文章于 2022-04-13 09:47:05 发布