s3c2440 linux 觸控螢幕驅動

來源:互聯網
上載者:User

主機:VM - redhat 9.0

開發板:FL2440,linux-2.6.12

arm-linux-gcc:3.4.1

代碼中的第90行,若不支援拖拽,則可以擷取到筆觸座標,但是LCD上的表徵圖沒有響應,不知什麼原因。

#include <linux/config.h>#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/init.h>#include <linux/device.h>#include <linux/miscdevice.h>#include <linux/delay.h>#include <linux/poll.h>#include <linux/spinlock.h>#include <linux/interrupt.h>#include <linux/delay.h>#include <linux/devfs_fs_kernel.h>#include <asm/hardware/clock.h>#include <asm/hardware.h>#include <asm/io.h>#include <asm/arch/regs-gpio.h>// YM_SEN輸出磁碟機使能,XP_SEN,YP_SEN輸出磁碟機禁止// S3C2410_ADCTSC_XY_PST(3) -- 手動測量X、Y方向,等待中斷模式// x=0, 將ADCTSC[8]設定為0,即檢測筆尖落下中斷訊號#define WAIT4INT(x)  (((x)<<8) | \     S3C2410_ADCTSC_YM_SEN | S3C2410_ADCTSC_YP_SEN | S3C2410_ADCTSC_XP_SEN | \     S3C2410_ADCTSC_XY_PST(3))     /* ADCTSC Register Bits */#define S3C2410_ADCTSC_YM_SEN(1<<7)#define S3C2410_ADCTSC_YP_SEN(1<<6)#define S3C2410_ADCTSC_XM_SEN(1<<5)#define S3C2410_ADCTSC_XP_SEN(1<<4)#define S3C2410_ADCTSC_PULL_UP_DISABLE(1<<3)#define S3C2410_ADCTSC_AUTO_PST(1<<2)#define S3C2410_ADCTSC_XY_PST(x)(((x)&0x3)<<0)/* ADCCON Register Bits */#define S3C2410_ADCCON_ECFLG(1<<15)#define S3C2410_ADCCON_PRSCEN(1<<14)#define S3C2410_ADCCON_PRSCVL(x)(((x)&0xFF)<<6)#define S3C2410_ADCCON_PRSCVLMASK(0xFF<<6)#define S3C2410_ADCCON_SELMUX(x)(((x)&0x7)<<3)#define S3C2410_ADCCON_MUXMASK(0x7<<3)#define S3C2410_ADCCON_STDBM(1<<2)#define S3C2410_ADCCON_READ_START(1<<1)#define S3C2410_ADCCON_ENABLE_START(1<<0)#define S3C2410_ADCCON_STARTMASK(0x3<<0)#ifdef S3C2410_ADCCON#undef S3C2410_ADCCON#endif#ifdef S3C2410_ADCTSC#undef S3C2410_ADCTSC#endif#ifdef S3C2410_ADCDLY#undef S3C2410_ADCDLY#endif#ifdef S3C2410_ADCDAT0#undef S3C2410_ADCDAT0#endif#ifdef S3C2410_ADCDAT1#undef S3C2410_ADCDAT1#endif#ifdef S3C2410_PA_ADC#undef S3C2410_PA_ADC#endif#define S3C2410_PA_ADC   (0x58000000) static void __iomem *base_addr;#define S3C2410_ADCCON (base_addr+(0x00))#define S3C2410_ADCTSC (base_addr+(0x04))#define S3C2410_ADCDLY (base_addr+(0x08))#define S3C2410_ADCDAT0 (base_addr+(0x0c))#define S3C2410_ADCDAT1 (base_addr+(0x10))#ifdef CONFIG_PM#include <linux/pm.h>#endif// 支援拖拽// 若不支援拖拽,則可以擷取到筆觸座標,但是LCD上的表徵圖沒有響應。// 可以看到read介面被調用到,不知為何表徵圖沒有響應。#define HOOK_FOR_DRAG//#defineDEBUG#ifdef DEBUG#define DPRINTKprintk#else#define DPRINTK#endiftypedef struct {  unsigned short pressure;  unsigned short x;  unsigned short y;  unsigned short pad;} TS_RET;typedef struct {  int xscale;  int xtrans;  int yscale;  int ytrans;  int xyswap;} TS_CAL;#define PEN_UP        0#define PEN_DOWN1#define PEN_FLEETING2#define MAX_TS_BUF16/* how many do we want to buffer */#undef USE_ASYNC#define DEVICE_NAME"s3c2410-ts"#define TSRAW_MINOR1typedef struct {unsigned int penStatus;/* PEN_UP, PEN_DOWN, PEN_SAMPLE */TS_RET buf[MAX_TS_BUF];/* protect against overrun */unsigned int head, tail;/* head and tail for queued events */wait_queue_head_t wq;spinlock_t lock;#ifdef USE_ASYNCstruct fasync_struct *aq;#endif#ifdef CONFIG_PMstruct pm_dev *pm_dev;#endif} TS_DEV;static TS_DEV tsdev;#define BUF_HEAD(tsdev.buf[tsdev.head])#define BUF_TAIL(tsdev.buf[tsdev.tail])#define INCBUF(x,mod) ((++(x)) & ((mod) - 1))static int tsMajor = 0;static void (*tsEvent)(void);#ifdef HOOK_FOR_DRAG#define TS_TIMER_DELAY  (HZ/100) /* 10 ms */static struct timer_list ts_timer;#endif// pick-up regs val from 2.4.18&2440// YM_SEN輸出磁碟機使能,XP上拉使能,正常ADC轉換,檢測筆尖落下中斷訊號,等待中斷模式#define wait_down_int()__raw_writel(0x000000d3,S3C2410_ADCTSC)// YM_SEN輸出磁碟機使能,XP上拉使能,正常ADC轉換,檢測筆尖抬起中斷訊號,等待中斷模式#define wait_up_int()__raw_writel(0x000001d3, S3C2410_ADCTSC)// XM_SEN、XP_SEN輸出磁碟機使能,XP上拉禁止,正常ADC轉換,X方向測量模式#define mode_x_axis()__raw_writel(0x00000069, S3C2410_ADCTSC)// 相當於__raw_writel(0x00000068, S3C2410_ADCTSC),即// XM_SEN、YP_SEN使能,XP上拉禁止,正常ADC轉換,無操作模式#define mode_x_axis_n()__raw_writel(XP_EXTVLT | XM_GND | YP_AIN | YM_HIZ | \XP_PULL_UP_DIS | XP_PST(NOP_MODE), S3C2410_ADCTSC)// YM_SEN、YP_SEN使能,XP上拉禁止,正常ADC轉換,Y方向測量模式#define mode_y_axis()__raw_writel(0x0000009a, S3C2410_ADCTSC)// __raw_writel(0x00007ffa, S3C2410_ADCCON); -- A/D轉換器預分頻器使能,預分頻值0xff,類比輸入通道SEL_MUX為XP,正常工作模式,使能讀啟動操作// __raw_readl(S3C2410_ADCDAT0); -- 讀取ADCDAT)的值#define start_adc_x()do {__raw_writel(0x00007ffa, S3C2410_ADCCON); \__raw_readl(S3C2410_ADCDAT0); } while(0)// 怎麼跟start_adc_x()配置一樣?應該為0x00007fea?#define start_adc_y()do {__raw_writel(0x00007ffa, S3C2410_ADCCON); \__raw_readl(S3C2410_ADCDAT1); } while(0)// 禁止讀啟動操作,即READ_START位置0#define disable_ts_adc()__raw_writel(__raw_readl(S3C2410_ADCCON)&0xfffffffd, S3C2410_ADCCON)static int adc_state = 0;static int x, y;/* touch screen coorinates */#ifdef HOOK_FOR_DRAG    #defineRT_BT_EMU_TM((HZ>>1)+(HZ>>2))//0.75S    //static u16 ts_r_x[5];    //static u16 ts_r_y[5];    //static u16 ts_r_idx;    //static u16 ts_r_beg;    static u32 dn_start;#endifstatic void tsEvent_raw(void){DPRINTK("@@@@@@@@ tvEvent_raw() @@@@@@@@@\n");if (tsdev.penStatus == PEN_DOWN){//u16 i, j;#ifdef HOOK_FOR_DRAG ts_timer.expires = jiffies + TS_TIMER_DELAY;add_timer(&ts_timer);#endifBUF_HEAD.x = x;BUF_HEAD.y = y;#ifdef HOOK_FOR_DRAG                BUF_HEAD.pressure = ((jiffies - dn_start) >= RT_BT_EMU_TM) ? PEN_FLEETING : PEN_DOWN;#else                BUF_HEAD.pressure = PEN_DOWN;#endif}/* if (tsdev.penStatus == PEN_DOWN) */else{#ifdef HOOK_FOR_DRAG del_timer(&ts_timer);#endifBUF_HEAD.x = x;BUF_HEAD.y = y;BUF_HEAD.pressure = PEN_UP;}tsdev.head = INCBUF(tsdev.head, MAX_TS_BUF);DPRINTK("@@@@@@@@ wake_up_interruptible() in tvEvent_raw() @@@@@@@@@\n");wake_up_interruptible(&(tsdev.wq));#ifdef USE_ASYNCif (tsdev.aq)kill_fasync(&(tsdev.aq), SIGIO, POLL_IN);#endif#ifdef CONFIG_PMpm_access(tsdev.pm_dev);#endif}static int tsRead(TS_RET * ts_ret){spin_lock_irq(&(tsdev.lock));ts_ret->x = BUF_TAIL.x;ts_ret->y = BUF_TAIL.y;ts_ret->pressure = BUF_TAIL.pressure;tsdev.tail = INCBUF(tsdev.tail, MAX_TS_BUF);spin_unlock_irq(&(tsdev.lock));return sizeof(TS_RET);}static ssize_t s3c2410_ts_read(struct file *filp, char *buffer, size_t count, loff_t *ppos){TS_RET ts_ret;retry: if (tsdev.head != tsdev.tail){int count;count = tsRead(&ts_ret);if (count){printk("@@@@@ ts_ret.x: %hd, ts_ret.y: %hd @@@@@@@\n", ts_ret.x, ts_ret.y);    copy_to_user(buffer, (char *)&ts_ret, count);}return count;} else{if (filp->f_flags & O_NONBLOCK)return -EAGAIN;interruptible_sleep_on(&(tsdev.wq));if (signal_pending(current))return -ERESTARTSYS;goto retry;}return sizeof(TS_RET);}#ifdef USE_ASYNCstatic int s3c2410_ts_fasync(int fd, struct file *filp, int mode) {return fasync_helper(fd, filp, mode, &(tsdev.aq));}#endifstatic unsigned int s3c2410_ts_poll(struct file *filp, struct poll_table_struct *wait){poll_wait(filp, &(tsdev.wq), wait);return (tsdev.head == tsdev.tail) ? 0 : (POLLIN | POLLRDNORM); }static inline void start_ts_adc(void){adc_state = 0;mode_x_axis();start_adc_x();}static inline void s3c2410_get_XY(void){if (adc_state == 0){ adc_state = 1;disable_ts_adc();y = __raw_readl(S3C2410_ADCDAT1) & 0x3ff;       //x:f04 y:f0e dh  by pht.mode_y_axis();start_adc_y();}else if (adc_state == 1){ adc_state = 0;disable_ts_adc();x = __raw_readl(S3C2410_ADCDAT0) & 0x3ff;         //y:f04 x:f0e dh by pht.printk("@@@@@@ PEN DOWN: x: %d, y: %d @@@@@@\n", x, y);wait_up_int();tsdev.penStatus = PEN_DOWN;tsEvent();}}static irqreturn_t s3c2410_isr_adc(int irq, void *dev_id, struct pt_regs *reg){DPRINTK("@@@@@@@@ s3c2410_isr_adc() @@@@@@@@\n");spin_lock_irq(&(tsdev.lock));if (tsdev.penStatus == PEN_UP){DPRINTK("@@@@@@ s3c2410_isr_adc 1 @@@@@@\n");            s3c2410_get_XY();}#ifdef HOOK_FOR_DRAGelse{DPRINTK("@@@@@@ s3c2410_isr_adc 2 @@@@@@\n");            s3c2410_get_XY();}#endifspin_unlock_irq(&(tsdev.lock));return IRQ_HANDLED;}static irqreturn_t s3c2410_isr_tc(int irq, void *dev_id, struct pt_regs *reg){DPRINTK("@@@@@@@@ s3c2410_isr_tc() @@@@@@@@\n");spin_lock_irq(&(tsdev.lock));if (tsdev.penStatus == PEN_UP){DPRINTK("@@@@@@@@ s3c2410_isr_tc 1 @@@@@@@@\n");#ifdef HOOK_FOR_DRAG  dn_start = jiffies; // add by gzliu#endif  start_ts_adc();}else{  tsdev.penStatus = PEN_UP;DPRINTK("@@@@@@@@ s3c2410_isr_tc 2 @@@@@@@@\n");printk("@@@@@@@ PEN UP: x: %d, y: %d @@@@@@@\n", x, y);  wait_down_int();  tsEvent();}spin_unlock_irq(&(tsdev.lock));return IRQ_HANDLED;}#ifdef HOOK_FOR_DRAGstatic void ts_timer_handler(unsigned long data){spin_lock_irq(&(tsdev.lock));if (tsdev.penStatus == PEN_DOWN){start_ts_adc();}spin_unlock_irq(&(tsdev.lock));}#endifstatic int s3c2410_ts_open(struct inode *inode, struct file *filp){tsdev.head = tsdev.tail = 0;tsdev.penStatus = PEN_UP;#ifdef HOOK_FOR_DRAG init_timer(&ts_timer);ts_timer.function = ts_timer_handler;#endiftsEvent = tsEvent_raw;init_waitqueue_head(&(tsdev.wq));//MOD_INC_USE_COUNT;return 0;}static int s3c2410_ts_release(struct inode *inode, struct file *filp){#ifdef HOOK_FOR_DRAGdel_timer(&ts_timer);#endif//MOD_DEC_USE_COUNT;return 0;}static struct file_operations s3c2410_fops = {owner:THIS_MODULE,open:s3c2410_ts_open,read:s3c2410_ts_read,release:s3c2410_ts_release,#ifdef USE_ASYNCfasync:s3c2410_ts_fasync,#endifpoll:s3c2410_ts_poll,};void tsEvent_dummy(void) {}#ifdef CONFIG_PMstatic int s3c2410_ts_pm_callback(struct pm_dev *pm_dev, pm_request_t req,    void *data) {    switch (req) {case PM_SUSPEND:tsEvent = tsEvent_dummy;break;case PM_RESUME:tsEvent = tsEvent_raw;wait_down_int();break;    }    return 0;}#endifstatic struct clk*adc_clock;static int __init s3c2410ts_probe(struct device *dev){int ret; tsEvent = tsEvent_dummy;DPRINTK("@@@@@@@@@@ s3c2410ts_probe @@@@@@@@@@\n");ret = register_chrdev(0, DEVICE_NAME, &s3c2410_fops);if (ret < 0) {  printk(DEVICE_NAME " can't get major number\n");  return ret;}tsMajor = ret;adc_clock = clk_get(NULL, "adc");if (!adc_clock) {printk(KERN_ERR "failed to get adc clock source\n");return -ENOENT;}clk_use(adc_clock);clk_enable(adc_clock);base_addr = ioremap(S3C2410_PA_ADC, 0x20);__raw_writel(WAIT4INT(0), S3C2410_ADCTSC);__raw_writel(30000, S3C2410_ADCDLY);// 30000--20000ret = request_irq(IRQ_ADC, s3c2410_isr_adc, SA_INTERRUPT, DEVICE_NAME, s3c2410_isr_adc);if (ret)    goto adc_failed;ret = request_irq(IRQ_TC, s3c2410_isr_tc, SA_INTERRUPT, DEVICE_NAME, s3c2410_isr_tc);if (ret)    goto tc_failed;/* Wait for touch screen interrupts */wait_down_int();        #ifdef CONFIG_DEVFS_FSdevfs_mk_dir("touchscreen");devfs_mk_cdev(MKDEV(tsMajor, TSRAW_MINOR), S_IFCHR|S_IRUGO|S_IWUSR, "touchscreen/%s", "0raw");#endif#ifdef CONFIG_PMtsdev.pm_dev = pm_register(PM_DEBUG_DEV, PM_USER_INPUT, s3c2410_ts_pm_callback);#endifreturn 0; tc_failed:    {            printk(KERN_ERR "tc failed!!!!!!!!!!!!!\n");     free_irq(IRQ_ADC, s3c2410_isr_adc);} adc_failed:     {            printk(KERN_ERR "adc failed!!!!!!!!!!!!!\n");     return ret; }}static struct device_driver s3c2410ts_driver = {.name= DEVICE_NAME,.bus= &platform_bus_type,.probe= s3c2410ts_probe,#ifdef CONFIG_PM.suspend= s3c2410ts_suspend,.resume= s3c2410ts_resume,#endif};static int __init s3c2410ts_init(void){int ret;printk("@@@@@@@@ s3c2410ts init() @@@@@@@\n");ret = driver_register(&s3c2410ts_driver);if(ret){            printk("register %s driver failed, return code is %d\n", DEVICE_NAME, ret);        }else{    printk("@@@@@@@ register %s driver success, return code is %d @@@@@@@@@@\n", DEVICE_NAME, ret);}return ret;}static void __exit s3c2410ts_exit(void){#ifdef CONFIG_DEVFS_FSdevfs_remove("touchscreen/%d", 0);devfs_remove("touchscreen");#endifunregister_chrdev(tsMajor, DEVICE_NAME);#ifdef CONFIG_PMpm_unregister(tsdev.pm_dev);#endiffree_irq(IRQ_ADC, s3c2410_isr_adc);free_irq(IRQ_TC, s3c2410_isr_tc);driver_unregister(&s3c2410ts_driver);}module_init(s3c2410ts_init);module_exit(s3c2410ts_exit);

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.