📄 s3c2410-ts.c
字号:
return; case PEN_SAMPLE: for ( index_ret = 0; index_ret < 4; index_ret++) { ADCTSC = (ADCTSC&~(7))|(4);/* Auto Conversion Mode & No Operation Mode */ ADCCON |= 0x1; while(ADCCON&0x1); /* sure that Enable_start is low */ while(!(ADCCON&0x8000)) /* End of A/D Conversion */ /* Reading DATA */ if(index_ret != 0) { dev->samples[index_ret-1].y = 0x3ff&ADCDAT0; dev->samples[index_ret-1].x = 0x3ff&ADCDAT1; } } ADCTSC = (ADCTSC&~(7))|(3); /*Normal ADC Conversion & Waiting for Interrupt Mode */ break; default: } if (pen_data.state==PEN_SAMPLE){ index_ret = data_processing(); if ( index_ret) { /* discard the data */ ts_timer_operation(TTIMER_START); return; } else { ts_timer_operation(TTIMER_START); /* Store the character only if there is room */ dev->d.total++; if ( nhead != dev->d.tail ) { event->x = dev->cur_data.x; event->y = dev->cur_data.y; event->pressure = DOWN_PRESS; dev->d.head = nhead; if ( dev->d.async_queue ) kill_fasync( &dev->d.async_queue, SIGIO, POLL_IN ); wake_up_interruptible( &dev->d.waitq ); dev->d.processed++; } else { dev->d.dropped++; } } } /* * conform to Specification for Generic Touch Screen Driver */ else { /* pen_data.state == PEN_UP */ dev->d.total++; if ( nhead != dev->d.tail ) { event->x = dev->last_data.x; event->y = dev->last_data.y; event->pressure = UP_PRESS; dev->d.head = nhead; if ( dev->d.async_queue ) kill_fasync( &dev->d.async_queue, SIGIO, POLL_IN ); wake_up_interruptible( &dev->d.waitq ); dev->d.processed++; } else { dev->d.dropped++; } }}static ssize_t s3c2410_ts_read(struct file *filp, char *buf, size_t count, loff_t *l){ struct s3c2410_ts_device *dev = (struct s3c2410_ts_device *) filp->private_data; if (count < sizeof(struct s3c2410_ts_event)) return -EINVAL; do { if (down_interruptible(&dev->d.lock)) return -ERESTARTSYS; while ( dev->d.head == dev->d.tail ) { up(&dev->d.lock); if ( filp->f_flags & O_NONBLOCK ) return -EAGAIN; if ( wait_event_interruptible( dev->d.waitq, (dev->d.head != dev->d.tail) ) ) return -ERESTARTSYS; if ( down_interruptible(&dev->d.lock)) return -ERESTARTSYS; } } while (0); if ( copy_to_user(buf, &dev->buf[dev->d.tail], sizeof(struct s3c2410_ts_event)) ) { up(&dev->d.lock); return -EFAULT; } dev->d.tail = INCBUF(dev->d.tail, MOUSEBUF_SIZE); up(&dev->d.lock); return sizeof(struct s3c2410_ts_event);}static unsigned int s3c2410_ts_poll(struct file *filp, poll_table *wait){ struct s3c2410_ts_general *dev = (struct s3c2410_ts_general *) filp->private_data; poll_wait(filp, &dev->waitq, wait); return (dev->head == dev->tail ? 0 : (POLLIN | POLLRDNORM));}/* * */static int s3c2410_ts_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){ int RetVal = 0; if (0) printk(__FUNCTION__ ": cmd=%x\n",cmd); switch (cmd) { case TS_GET_CAL: if ( copy_to_user((void *)arg, &global_ts.cal, sizeof(struct s3c2410_ts_calibration))) RetVal = -EFAULT; break; case TS_SET_CAL: if ( copy_from_user(&global_ts.cal, (void *) arg, sizeof(struct s3c2410_ts_calibration))) RetVal = -EFAULT; break; case 0xaa: /* get the ts justified data from user */ if ( copy_from_user(&cfg_data, (void *) arg, sizeof(struct config_data))) RetVal = -EFAULT; break; case 0xbb: /* put the ts justified data to user */ if ( copy_to_user((void *)arg, &cfg_data, sizeof(struct config_data))) RetVal = -EFAULT; break; case 0xcc: /* set the ts to begin justify */ global_ts_justified = 0; break; case 0xdd: /* get the ts justify status, 1 -- ok, 0 -- justifing */ if ( copy_to_user((void *)arg, &global_ts_justified, sizeof(int))) RetVal = -EFAULT; break; default: printk(__FUNCTION__ ": UNKNOWN IOCTL COMMAND=0x%08X\n",cmd); } /* * Future ioctl goes here */ return RetVal;}static int s3c2410_ts_open(struct inode *inode, struct file *filp){ struct s3c2410_ts_general *dev ; filp->private_data = &global_ts; dev = (struct s3c2410_ts_general *) filp->private_data; if ( dev->usage_count++ == 0 ) /* We're the first open - clear the buffer */ dev->tail = dev->head; if (0) printk(__FUNCTION__ " usage=%d\n", dev->usage_count); MOD_INC_USE_COUNT; return 0;}/* * invoked to add files to or remove files from the list of * interested processes when the FASYNC flag changes for an open file * */static int s3c2410_ts_fasync(int fd, struct file *filp, int mode){ /* Private * dev = filp->private_data; * fasyhc_helper(fd,filp,on,&dev->async_queue) * */ struct s3c2410_ts_general *dev = (struct s3c2410_ts_general *) filp->private_data; if (0) printk(__FUNCTION__ ": mode %x\n", mode ); return fasync_helper(fd, filp, mode, &dev->async_queue);}static int s3c2410_ts_release(struct inode *inode, struct file *filp){ struct s3c2410_ts_general *dev = (struct s3c2410_ts_general *) filp->private_data; dev->usage_count--; if (0) printk(__FUNCTION__ " usage=%d\n", dev->usage_count); filp->f_op->fasync( -1, filp, 0 ); /* Remove ourselves from the async list */ MOD_DEC_USE_COUNT; return 0;}static struct file_operations s3c2410_ts_fops = { owner: THIS_MODULE, read: s3c2410_ts_read, poll: s3c2410_ts_poll, ioctl: s3c2410_ts_ioctl, open: s3c2410_ts_open, release: s3c2410_ts_release, fasync: s3c2410_ts_fasync,};static int ts_timer_operation(enum ts_timer tt){ int RetVal=0; switch(tt) { case TTIMER_SETUP: TCFG0 |= SYS_TIMER01_PRESCALER; TCFG1 = (TCFG1&~(0xf<<4))|(SYS_TIMER1_MUX<<4); TCNTB1 = (TOUCH_RESCHED_PERIOD*PCLK)/ ((SYS_TIMER01_PRESCALER +1)*(SYS_TIMER1_DIVIDER)*1000); TCMPB1 = 0; TCON = (TCON&~(0xf00))|(0xA<<8); /* the auto reload ,manual update for Timer 1 */ TCON = (TCON&~(0xf00))|(0<<8); /* Stop and clear manual update for Timer1 */ if ((RetVal = request_irq(IRQ_TIMER1,touch_timer_irq ,SA_INTERRUPT,g_ts_timer_id,NULL))) { printk(KERN_WARNING "s3c2410_ts timer : failed to get IRQ\n"); return RetVal; } return RetVal; case TTIMER_START: TCON = (TCON&~(0xf00))|(0xA<<8); TCON = (TCON&~(0xf00))|(1<<8); /* Start */ break; case TTIMER_STOP: TCON = (TCON&~(0xf00))|(0<<8); /* Stop */ break; } return RetVal; /* success */}static int gMajor; /* Dynamic major for now */int __init s3c2410_ts_init_module(void){ int retval; struct s3c2410_ts_general *dev; dev = (struct s3c2410_ts_general *)&global_ts; /* Duplicated Code Sorry *^^* * Setup GPIOs for touch * GPGCON/GPGUP see include/asm/arch-s3c2410/uncomress.h * GPG15,14,13,12 */ //laputa append for AD converting freq calculate retval = s3c2410_get_bus_clk(GET_PCLK); PreScale_n = (int)( retval / ADC_FREQ ) - 1 ; printk("Prescale = %d\n", PreScale_n); //laputa end 030918 /* set gpio to XP, YM, YP and YM */ set_gpio_ctrl(GPIO_YPON); set_gpio_ctrl(GPIO_YMON); set_gpio_ctrl(GPIO_XPON); set_gpio_ctrl(GPIO_XMON); /* * Down,YM:GND,YP:AIN5,XM:Hi-z,XP:AIN7,XP pullup En,Auto,Waiting for interrupt mode * If auto mode, the SEL_MUX don't care */ ADCTSC=(0<<8)|(1<<7)|(1<<6)|(0<<5)|(1<<4)|(0<<3)|(0<<2)|(3); /* ADC Start or Interval Delay */ ADCDLY=ADC_DELAY_TIME; /* Enable Prescaler,Prescaler,AIN5/7 fix,Normal,Disable read start,No operation */ ADCCON = (1<<14)|(/*ADCPRS*/PreScale_n<<6)|(7<<3)|(0<<2)|(0<<1)|(0); if ((retval = request_irq(IRQ_ADC_DONE, ts_down_interrupt ,SA_INTERRUPT,g_ts_id, ts_down_interrupt))) { printk(KERN_WARNING "s3c2410_ts: failed to get IRQ\n"); return retval; } retval = request_irq(IRQ_TC, ts_up_interrupt, SA_INTERRUPT, g_ts_id, ts_up_interrupt); if (retval) return retval; gMajor = devfs_register_chrdev(0, H3600_TS_MODULE_NAME, &s3c2410_ts_fops); if (gMajor < 0) { printk(__FUNCTION__ ": can't get major number\n"); return gMajor; } /*----------------------------------------*/ dev->head = 0; dev->tail = 0; init_waitqueue_head( &dev->waitq ); init_MUTEX( &dev->lock ); dev->async_queue = NULL; pen_data.state = PEN_DOWN; /*----------------------------------------*/ if(ts_timer_operation(TTIMER_SETUP)) printk(KERN_NOTICE " !!!!! TOUCH TIMER SETUP FAILED \n"); printk(KERN_NOTICE "Loading S3C2410 Touch Screen Driver, major = %d \n", gMajor); return 0;}void __exit s3c2410_ts_cleanup_module(void){ printk(__FUNCTION__ ": S3C2410 Touch Screen Exit !!! \n"); free_irq(IRQ_TIMER1,g_ts_id); free_irq(IRQ_ADC_DONE,g_ts_id); free_irq(IRQ_TC,g_ts_timer_id); /* * Direct Disable IRQ ADC rINTMSK<= IRQ_ADC */ devfs_unregister_chrdev(gMajor, H3600_TS_MODULE_NAME);}module_init(s3c2410_ts_init_module);module_exit(s3c2410_ts_cleanup_module);MODULE_AUTHOR("SW.LEE <hitchcar@sec.samsung.com>");MODULE_DESCRIPTION("S3c2410 touchscreen driver");MODULE_SUPPORTED_DEVICE("touchscreen/s3c2410");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -