S3C2440驱动篇之触摸屏驱动分析

2024-06-14  

一.硬件简介

S3C2440触摸屏接口与ADC接口集成在一起,触摸屏X、Y坐标所产生的模拟信号通过通道7、5输入,2440提供触摸屏接口有4种处理模式:普通转换模式、分离的X/Y轴坐标转换模式、自动X/Y轴坐标转换模式、等待中断模式。具体参考2440硬件手册16章。


二.驱动实现

下面是触摸屏驱动源码,其中使用了linux输入子系统input。暂时还没研究这一块,想深入了解可参考相关资料。

  1. #include    

  2. #include    

  3. #include    

  4. #include    

  5. #include    

  6. #include    

  7. #include    

  8. #include    

  9. #include    

  10. #include    

  11. #include    

  12. #include    

  13. #include    

  14. #include    

  15. #include    

  16.   

  17. #define S3C2410TSVERSION 0x0101   

  18. #define DEVICE_NAME "YC2440_TS"   

  19.   

  20. //定义一个WAIT4INT宏,该宏将对ADC触摸屏控制寄存器进行操作S3C2410_ADCTSC_YM_SEN这些宏都定义在regs-adc.h中   

  21. #define WAIT4INT(x) (((x)>>8)|S3C2410_ADCTSC_YM_SEN|S3C2410_ADCTSC_YP_SEN|S3C2410_ADCTSC_XP_SEN|S3C2410_ADCTSC_XY_PST(3))   

  22. #define AUTOPST (S3C2410_ADCTSC_YM_SEN|S3C2410_ADCTSC_YP_SEN|S3C2410_ADCTSC_XP_SEN|   

  23.         S3C2410_ADCTSC_AUTO_PST|S3C2410_ADCTSC_XY_PST(0))  

  24.   

  25. static struct input_dev *dev;  //输入设备结构体   

  26. static long xp;    //记录转换后的X、Y坐标值   

  27. static long yp;  

  28. static int count;  

  29.   

  30. extern struct semaphore ADC_LOCK;  //在ADC驱动中定义的信号量   

  31. static int ownADC = 0;  

  32.   

  33. static struct clk *adc_clk;  

  34.   

  35. static void __iomem *base_addr;  

  36. //touch_timer_fire函数分三块执行,下面1、2、3分别实现不同功能   

  37. static void touch_timer_fire(unsigned long data)  

  38. {        

  39.     unsigned long data0;  

  40.     unsigned long data1;  

  41.     int updown;  

  42.   

  43.     data0 = ioread32(base_addr+S3C2410_ADCDAT0);  

  44.     data1 = ioread32(base_addr+S3C2410_ADCDAT1);  

  45.        //判断触摸屏是按下、抬起状态   

  46.     updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN));  

  47.          

  48.     if(updown)                    

  49.     {  

  50.         if(count != 0)     //1.如果触摸屏按下,并且ADC已转换,则报告事件、数据   

  51.         {  

  52.             long tmp;  

  53.               

  54.             tmp = xp;  

  55.             xp = yp;  

  56.             yp = tmp;  

  57.   

  58.             xp >>= 2;  

  59.             yp >>= 2;  

  60.   

  61. #ifdef CONFIG_TOUCHSCREEN_DEBUG    

  62.             struct timeval tv;  

  63.             do_gettimeofday(&tv);  

  64.             printk(KERN_DEBUG "T:%06d, X:%03d, Y:%03dn",(int)tv.tv_usec,xp,yp);  

  65. #endif   

  66.   

  67.             input_report_abs(dev,ABS_X,xp);  

  68.             input_report_abs(dev,ABS_Y,yp);  

  69.   

  70.             input_report_key(dev,BTN_TOUCH,1);  

  71.             input_report_abs(dev,ABS_PRESSURE,1);  

  72.             input_sync(dev);    //等待接收方受到数据后回复确认,用于同步   

  73.         }  

  74.         //2.如果触摸屏按下,并且没有ADC转换,则启动ADC转换   

  75.         xp = 0;  

  76.         yp = 0;  

  77.         count = 0;  

  78.   

  79.         iowrite32(S3C2410_ADCTSC_PULL_UP_DISABLE|AUTOPST,base_addr+S3C2410_ADCTSC);  

  80.         iowrite32(ioread32(base_addr+S3C2410_ADCCON)|S3C2410_ADCCON_ENABLE_START,base_addr+S3C2410_ADCCON);  

  81.     }  

  82.     else    //3.如果触摸屏抬起状态,则报告事件、数据,重置等待按下状态   

  83.     {  

  84.         count = 0;  

  85.   

  86.         input_report_key(dev,BTN_TOUCH,0);  

  87.         input_report_abs(dev,ABS_PRESSURE,0);  

  88.         input_sync(dev);  

  89.   

  90.         iowrite32(WAIT4INT(0),base_addr+S3C2410_ADCTSC);    //将触摸屏重新设置为等待中断状态   

  91.   

  92.         if(ownADC)        //如果触摸屏抬起,www.linuxidc.com就意味着这一次的操作结束,所以就释放ADC资源的占有   

  93.         {  

  94.             printk(KERN_INFO "upn");  

  95.             ownADC = 0;  

  96.             up(&ADC_LOCK);  

  97.         }  

  98.     }  

  99. }  

  100. //定义并初始化了一个定时器touch_timer,定时器服务程序为touch_timer_fire   

  101. static struct timer_list touch_timer=TIMER_INITIALIZER(touch_timer_fire,0,0);  

  102.   

  103. static irqreturn_t stylus_updown(int irq,void *dev_id)  //触摸屏中断服务程序,触摸屏按下、抬起执行   

  104. {  

  105.     unsigned long data0;  

  106.     unsigned long data1;  

  107.     int updown;  

  108.   

  109.     if(down_trylock(&ADC_LOCK)==0)  

  110.     {  

  111.         ownADC = 1;  

  112.         data0 = ioread32(base_addr+S3C2410_ADCDAT0);  

  113.         data1 = ioread32(base_addr+S3C2410_ADCDAT1);  

  114.   

  115.         updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN));  

  116.   

  117.         if(updown)  

  118.         {      //如果触摸屏按下,则执行touch_timer_fire的功能2   

  119.             printk(KERN_INFO "downn");  

  120.             touch_timer_fire(0);      

  121.         }  

  122.         else  

  123.         {      //如果抬起,结束一次操作,释放相应资源   

  124.             printk(KERN_INFO "up-irqn");  

  125.             ownADC = 0;  

  126.             up(&ADC_LOCK);  

  127.         }  

  128.     }  

  129.     return IRQ_HANDLED;  

  130. }  

  131.   

  132. static irqreturn_t stylus_action(int irq,void *dev_id)    //ADC中断服务程序   

  133. {  

  134.     unsigned long data0;  

  135.     unsigned long data1;  

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。