📄 digi.c
字号:
* Description: support touch pannel interrupt,since MX1 and MX21 adopted different ADC chip,in MX1,AD7843 will * generate interrupt according to level trigger configuration, so can generate one interrupt to * detect pen down, then reconfigure it to generate pen up interrupt.But in MX21, the AD7873 will * have the pen irq line reassert after each pen sample is taken. It will deassert when you take a * sample. When the pen is down, we disable the interrupt and take a sample every 20ms. Before we * take the sample, we check if the pen irq line is deasserted. If it is deasserted, then this means * the pen is up. */static void digi_isr(int irq, void *dev_id, struct pt_regs *regs){ if(((_reg_GPIO_ISR(GPIOC) & _reg_GPIO_IMR(GPIOC))&0x00004000)!=0) { touch_pan_clear_inter(); //tasklet_schedule(&digi_tasklet); touch_pan_disable_inter(); pen_timer.expires = jiffies + HZ/50 + 2*HZ/100; add_timer(&pen_timer); pen_timer_status = 1; //INFO("Pen Interrupt\n"); } return;}/*** Function Name: digi_tasklet_action* Input : data* Output : none* Description : The tasklet function used in MX1.* **/static void digi_tasklet_action(unsigned long data){ //#ifdef CONFIG_ARCH_MX1ADS u32 newX; u32 newY; u32 maxDelay; newX = TPNL_PEN_UPVALUE; maxDelay = 0;// save_flags(touchflags);// cli(); //check the interrupt polarity to see it is pen up or down. if(touch_pan_check_int_pol())//it is pen down { if((_reg_GPIO_SSR(GPIOC) & 0x00004000) == 0)//judge if is pen down { return; } //then just change the interrupt polarity to be pen up touch_pan_set_neg_inter(); //check if the pen sampling timer is in use if(pen_timer_status!=0)//in use { //then just change the interrupt polarity to be pen up return; } else //no sampling timer { //9/8 Karen touch_pan_disable_inter(); //end 9/8 //read data with MAX delay from ADC touch_pan_read_data(&newX, &newY); while((newX == TPNL_PEN_UPVALUE)&&(maxDelay <= 50)) { touch_pan_read_data(&newX, &newY); maxDelay++; } if(newX == TPNL_PEN_UPVALUE) { //clear the interrupt bit// FAILED("TouchPanIsr: error always PEN_UP \n"); return; } TRACE("TouchPanIsr:get pendata x= %d, y=%d \n",newX,newY); add_x_y(newX, newY, PENDOWN); wake_up_interruptible(&digi_wait); if(ts_fasync) kill_fasync(&ts_fasync, SIGIO, POLL_IN); //then just change the interrupt polarity to be pen up //then just change the interrupt polarity to be pen up touch_pan_set_neg_inter(); spin_lock_irq(&pen_lock); pen_timer.expires = jiffies + HZ/50 + 2*HZ/100; add_timer(&pen_timer); pen_timer_status = 1; spin_unlock_irq (&pen_lock); return; } } else//pen up interrupt { if((_reg_GPIO_SSR(GPIOC) & 0x00004000) != 0) //value is high { return; } //check if the pen sampling timer is in use if(pen_timer_status!=0)//in use { //disable pen down interrupt //get Pen up TRACE("TouchPanIsr:get pen up 0,0,penup \n"); add_x_y(0, 0, PENUP); // if there is a pen up, shall tell apps to handle the event, and it shall // be data there if (!NODATA()) { wake_up_interruptible(&digi_wait); if(ts_fasync) kill_fasync(&ts_fasync, SIGIO, POLL_IN); } //release timer spin_lock_irq(&pen_lock); pen_timer_status = 0; del_timer(&pen_timer); spin_unlock_irq(&pen_lock); touch_pan_set_pos_inter();//set polarity to detach pen down } else //no timer {// FAILED("TouchPanIsr :pen up, no timer \n"); } return; }//#endif }/****************************************************************************** * Function Name: digi_sam_callback * * Input: : * * Value Returned: * * Description: spi sampling timer call back * *****************************************************************************/static void digi_sam_callback(unsigned long data){ u32 newX,newY; u32 maxDelay; maxDelay = 0; newX = TPNL_PEN_UPVALUE;// save_flags(samflags);// cli(); if(pen_timer_status !=0) mod_timer(&pen_timer, jiffies + HZ/50 + 2*HZ/100);#ifdef CONFIG_ARCH_MX2ADS if((_reg_GPIO_SSR(GPIOC) & 0x00004000) == 0)//judge if is pen down#endif#ifdef CONFIG_ARCH_MX1ADS if((REG_PD_SSR & 0x80000000) == 0)//judge if is pen down#endif { if(pen_timer_status!=0)//in use { //get Pen up add_x_y(0, 0, PENUP); // if there is a pen up, shall tell apps to handle the event, and it shall be data there if (!NODATA()) { wake_up_interruptible(&digi_wait); if(ts_fasync) kill_fasync(&ts_fasync, SIGIO, POLL_IN); } //release timer spin_lock_irq(&pen_lock); pen_timer_status = 0; del_timer(&pen_timer); spin_unlock_irq(&pen_lock);#ifdef CONFIG_ARCH_MX2ADS touch_pan_set_pos_inter();#endif#ifdef CONFIG_ARCH_MX1ADS touch_pan_set_pos_inter();//set polarity to detach pen down#endif touch_pan_clear_inter(); //9/8 Karen touch_pan_enable_inter(); //end 9/8 } return; }#ifdef CONFIG_ARCH_MX2ADS if((_reg_GPIO_SSR(GPIOC) & 0x00004000) != 0)//positive,it is pen down //if(!touch_pan_check_int_pol())//positive,it is pen down#endif#ifdef CONFIG_ARCH_MX1ADS if(!touch_pan_check_int_pol())//positive,it is pen down#endif { //read data with MAX delay from ADC while((newX == TPNL_PEN_UPVALUE)&&(maxDelay <= 100)) { touch_pan_read_data(&newX, &newY); maxDelay++; } if(newX == TPNL_PEN_UPVALUE) {// FAILED("SpiSamCallback: error always PEN_UP \n"); return; } //add element into buffer add_x_y(newX, newY, PENDOWN); //printk("newx = %d,newy = %d\n",newX,newY); wake_up_interruptible(&digi_wait); if(ts_fasync) kill_fasync(&ts_fasync, SIGIO, POLL_IN); return; } else { FAILED(" error to call me \n"); return; }}/************************************************Misc functions for SPI *************************************************/void spi_init(void){ int datarate,i; int cs; datarate = 0x8;//1024 cs = 0x0;//ss0 //cspi1_mosi--pd31 output //cspi1_miso--pd30 input //cspi1_sclk--pd29 output //cspi1_ss0 --pd28,output it connect with pen_cs_b _reg_GPIO_GIUS(GPIOD) &= 0x0fffffff; _reg_GPIO_GPR(GPIOD) &= 0x0fffffff; _reg_GPIO_DDIR(GPIOD) |= 0xb0000000; _reg_GPIO_DDIR(GPIOD) &= 0xbfffffff; //reset spi1 *((P_U32)CSPI1_RESETREG1) = 0x00000001; for(i=0;i<20000;i++); // use 32.768kHz *((P_U32)CSPI1_PERIODREG1) = 0x00008000; //bit19,18 CS[1:0], bit 17~14 datarate[3:0] *((P_U32)CSPI1_CONTROLREG1) |= (cs<<18); *((P_U32)CSPI1_CONTROLREG1) |= (datarate<<14); *((P_U32)CSPI1_CONTROLREG1) |= 0x00000c07;//ss low active, 8 bit transfer,master mode _reg_CRM_PCCR0 |= 0x00000010;}//To polling when Spi transfer is not finishedstatic void spi_poll_done(void){ //here should poll the IRQ bit in IRQ reg to see while(!(*((P_U32)CSPI1_INTREG1) & SPI_TE_INT_BIT));//transfer FIFO is empty udelay(20); /* Reset SPI IRQ bit */ *((P_U32)CSPI1_INTREG1) &= SPI_TE_INT_BIT; udelay(20); //wait until XCH bit is clear, hence exchange is complete while(!(*((P_U32)CSPI1_CONTROLREG1) & SPI_XCH_BIT)); udelay(20);}static int spi_tx_fifo_empty(void){ int ret; ret = *((P_U32)CSPI1_INTREG1) & SPI_TE_INT_BIT; //printk("tx_ret = 0x%x\n",ret); //for(i=0;i<10000;i++); udelay(20); return ret;}static int spi_rx_fifo_data_ready(void){ int ret; ret = *((P_U32)CSPI1_INTREG1) & SPI_RR_INT_BIT; //for(i=0;i<10000;i++); udelay(20); //printk("rx_ret = 0x%x\n",ret); return ret;}static unsigned int spi_exchange_data(unsigned int dataTx){ while(!spi_tx_fifo_empty()); *((P_U32)CSPI1_TXDATAREG1) = dataTx; //transfer data *((P_U32)CSPI1_CONTROLREG1) |= SPI_XCH_BIT; // exchange data while(!spi_rx_fifo_data_ready()); return *((P_U32)CSPI1_RXDATAREG1);}void spi_flush_fifo(void){ U32 i,j; for(i=0;i<8;i++) { if(*((P_U32)CSPI1_INTREG1)&SPI_RR_INT_BIT) j = *((P_U32)CSPI1_RXDATAREG1); }}static void spi_tx_data(u16 data){ /* ensure data will not be transmitted while writing to SPI */ *((P_U32)CSPI1_CONTROLREG1) &= SPI_XCH_MASK; *((P_U32)CSPI1_CONTROLREG1) |= SPI_EN_BIT; *((P_U32)CSPI1_TXDATAREG1) = (u32)data;//transfer data *((P_U32)CSPI1_CONTROLREG1) |= SPI_XCH_BIT; spi_poll_done(); *((P_U32)CSPI1_CONTROLREG1) &= SPI_XCH_MASK;}/****************************************************************************** * Function Name: check_device * * Input: inode : * Value Returned: int : Return status.If no error, return 0. * * Description: verify if the inode is a correct inode * *****************************************************************************/static int check_device(struct inode *pInode){ int minor; kdev_t dev = pInode->i_rdev; if( MAJOR(dev) != g_digi_major) {// printk("DIGI: check_device bad major = %d\n",MAJOR(dev) ); return -1; } minor = MINOR(dev); if ( minor < MAX_ID ) return minor; else { // printk("DIGI: check_device bad minor = %d\n",minor ); return -1; }}/**************************************************Misc functions for buffer***************************************************//* local buffer for store data * a new feature is read block, assume the buffer is a continuous buffer * so, if there is enough data, read data from current position to * buffer end, then next time, from buffer head to data end. -- the buffer * is a loop buffer. */ts_event_t * buffer;#define BUFLEN 250#define BUFSIZE (BUFLEN*sizeof(ts_event_t))#define NEXTI(i) {i=(i==BUFLEN-1)?0:i+1;}#define GETNEXTI(i) ((i==BUFLEN-1)?0:i+1)#define BLKEND(i) ((i)==0)#if 1#define DSIZE() ((wptr<rptr)?(BUFLEN-rptr):(wptr-rptr))#else#define DSIZE() ((wptr<rptr)?(BUFLEN-rptr+wptr):(wptr-rptr))#endif/****************************************************************************** * Function Name: init_buf * * Input: void : * Value Returned: int : Return status.If no error, return 0. * * Description: init the loop buffer for store data read out from spi FIFO * and shall be copied to user * *****************************************************************************/static int init_buf(void){ buffer = (ts_event_t*) vmalloc(BUFSIZE); if(!buffer){// printk(KERN_ERR"no enough kernel memory for spi data buffer\n"); return -1; } rptr = wptr = 0; return 1;}/****************************************************************************** * Function Name: add_x_y * * Input: i : * Value Returned: void : * * Description: add pen data to buffer * *****************************************************************************/static void add_x_y(unsigned x, unsigned y, unsigned flag){ if (GETNEXTI(wptr) == rptr) return; buffer[wptr].x = x; buffer[wptr].y = y;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -