⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ep93xx_ts.c

📁 非常珍贵的LINUX下的专门针对CIRRUS公司的EP93XX平台的驱动源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
}/* * ep93xx_hw_shutdown * */static voidep93xx_hw_shutdown(void){    unsigned int uiKTDIV;        DPRINTK("ep93xx_hw_shutdown\n");	    sTouch.state = TS_STATE_STOPPED;	Stop_Timer2();    /*     * Disable the scanning engine.     */	outl( 0, TSSetup );	outl( 0, TSSetup2 );    /*     * Clear the TSEN bit in KTDIV so that we are disabling the clock     * for the touchscreen.     */        uiKTDIV = inl(SYSCON_KTDIV);    uiKTDIV &= ~SYSCON_KTDIV_TSEN;    SysconSetLocked( SYSCON_KTDIV, uiKTDIV );    } /* ep93xx_hw_shutdown */static void ep93xx_timer2_isr(int irq, void *dev_id, struct pt_regs *regs){    DPRINTK("%d", (int)sTouch.state );    switch( sTouch.state )    {        case TS_STATE_STOPPED:			TS_Hardware_Scan_Mode();            break;                    //        // Get the Z1 value for pressure measurement and set up		// the switch register for getting the Z2 measurement.        //        case TS_STATE_Z1:		    Set_Timer2_uSec( EP93XX_TS_ADC_DELAY_USEC );            sTouch.uiZ1 = ADCGetData( 2, 200 );            ep93xx_ts_set_direct( sSwitchSettings.uiSwitchZ2 );            sTouch.state = TS_STATE_Z2;            break;                //        // Get the Z2 value for pressure measurement and set up		// the switch register for getting the Y measurement.        //        case TS_STATE_Z2:            sTouch.uiZ2 = ADCGetData( 2, 200 );            ep93xx_ts_set_direct( sSwitchSettings.uiYSample );            sTouch.state = TS_STATE_Y;			break;				//        // Get the Y value and set up the switch register for 		// getting the X measurement.        //        case TS_STATE_Y:            sTouch.uiY = ADCGetData( 4, 20 );            ep93xx_ts_set_direct( sSwitchSettings.uiXSample );            sTouch.state = TS_STATE_X;            break;                //        // Read the X value.  This is the last of the 4 adc values        // we need so we continue on to process the data.        //        case TS_STATE_X:            Stop_Timer2();                        sTouch.uiX = ADCGetData( 4, 20 );            			outl( 0xaa, TSSWLock );			outl( sSwitchSettings.uiDischarge, TSDirect );                        sTouch.state = TS_STATE_DONE;                    /*             * Process this set of ADC readings.             */            ProcessPointData();                        break;        //		// Shouldn't get here.  But if we do, we can recover...		//		case TS_STATE_DONE:			TS_Hardware_Scan_Mode();            break;    }     //    // Clear the timer2 interrupt.    //	outl( 1, TIMER2CLEAR );}/*--------------------------------------------------------------------- * ProcessPointData * * This routine processes the ADC data into usable point data and then * puts the driver into hw or sw scanning mode before returning. * * We calculate inverse pressure (lower number = more pressure) then * do a hystheresis with the two pressure values 'light' and 'heavy'. * * If we are above the light, we have pen up. * If we are below the heavy we have pen down. * As long as the pressure stays below the light, pen stays down. * When we get above the light again, pen goes back up. * */static void ProcessPointData(void){    int  bValidPoint = 0;    unsigned int   uiXDiff, uiYDiff, uiInvPressureDiff;    unsigned int   uiInvPressure;    //    // Calculate the current pressure.    //    uiInvPressure = CalculateInvPressure();    DPRINTK(" X=0x%x, Y=0x%x, Z1=0x%x, Z2=0x%x, InvPressure=0x%x",            sTouch.uiX, sTouch.uiY, sTouch.uiZ1, sTouch.uiZ2, uiInvPressure ); 	//	// If pen pressure is so light that it is greater than the 'max' setting	// then we consider this to be a pen up.	//    if( uiInvPressure >= TS_LIGHT_INV_PRESSURE )	{		DPRINTK(" -- up \n");		bCurrentPenDown = 0;        ee93xx_ts_evt_add( 0, guiLastX, guiLastY );		TS_Hardware_Scan_Mode();		return;	}    //	// Hystheresis:    // If the pen pressure is hard enough to be less than the 'min' OR	// the pen is already down and is still less than the 'max'...	//    if( (uiInvPressure < TS_HEAVY_INV_PRESSURE) ||        ( bCurrentPenDown && (uiInvPressure < TS_LIGHT_INV_PRESSURE) )  )    {        if( bCurrentPenDown )        {            //            // If pen was previously down, check the difference between            // the last sample and this one... if the difference between             // samples is too great, ignore the sample.            //            uiXDiff = abs(guiLastX - sTouch.uiX);            uiYDiff = abs(guiLastY - sTouch.uiY);			uiInvPressureDiff = abs(guiLastInvPressure - uiInvPressure);			            if( (uiXDiff < TS_MAX_VALID_XY_CHANGE) && 			    (uiYDiff < TS_MAX_VALID_XY_CHANGE) &&				(uiInvPressureDiff < TS_MAX_VALID_PRESSURE_CHANGE) )            {				DPRINTK(" -- valid(two) \n");                bValidPoint = 1;            }			else			{				DPRINTK(" -- INvalid(two) \n");			}        }        else        {			DPRINTK(" -- valid \n");            bValidPoint = 1;        }                /*         * If either the pen was put down or dragged make a note of it.         */        if( bValidPoint )        {	        guiLastX = sTouch.uiX;	        guiLastY = sTouch.uiY;			guiLastInvPressure = uiInvPressure;			bCurrentPenDown = 1;            ee93xx_ts_evt_add( 1, sTouch.uiX, sTouch.uiY );        }        TS_Soft_Scan_Mode();		return;    }	DPRINTK(" -- fallout \n");	TS_Hardware_Scan_Mode();}static void ep93xx_ts_set_direct( unsigned int uiADCSwitch ){    unsigned int uiResult;        //    // Set the switch settings in the direct register.    //	outl( 0xaa, TSSWLock );	outl( uiADCSwitch, TSDirect );    //    // Read and throw away the first sample.    //    do {        uiResult = inl(TSXYResult);    } while( !(uiResult & TSXYRESULT_SDR) );    }static unsigned int ADCGetData(     unsigned int uiSamples,     unsigned int uiMaxDiff ){    unsigned int   uiResult, uiValue, uiCount, uiLowest, uiHighest, uiSum, uiAve;    do    {        //        //Initialize our values.        //        uiLowest        = 0xfffffff;        uiHighest       = 0;        uiSum           = 0;                for( uiCount = 0 ; uiCount < uiSamples ; uiCount++ )        {            //            // Read the touch screen four more times and average.            //            do {		        uiResult = inl(TSXYResult);            } while( !(uiResult & TSXYRESULT_SDR) );                        uiValue = (uiResult & TSXYRESULT_AD_MASK) >> TSXYRESULT_AD_SHIFT;            uiValue = ((uiValue >> 4) + ((1 + TSXYRESULT_X_MASK)>>1))  & TSXYRESULT_X_MASK;             //            // Add up the values.            //            uiSum += uiValue;            //            // Get the lowest and highest values.            //            if( uiValue < uiLowest )            {                uiLowest = uiValue;            }            if( uiValue > uiHighest )            {                uiHighest = uiValue;            }        }    } while( (uiHighest - uiLowest) > uiMaxDiff );    //    // Calculate the Average value.    //    uiAve = uiSum / uiSamples;    return uiAve;    }//****************************************************************************// CalculateInvPressure//****************************************************************************// Is the Touch Valid.  Touch is not valid if the X or Y value is not // in range and the pressure is not  enough.// // Touch resistance can be measured by the following formula:////          Rx * X *     Z2// Rtouch = --------- * (-- - 1)//           4096        Z1//// This is simplified in the ration of Rtouch to Rx.  The lower the value, the// higher the pressure.////                     Z2// InvPressure =  X * (-- - 1)//                     Z1//static unsigned int CalculateInvPressure(void){    unsigned int   uiInvPressure;    //    // Check to see if the point is valid.    //    if( sTouch.uiZ1 < MIN_Z1_VALUE )    {        uiInvPressure = 0x10000;    }    //    // Can omit the pressure calculation if you need to get rid of the division.    //    else    {        uiInvPressure = ((sTouch.uiX * sTouch.uiZ2) / sTouch.uiZ1) - sTouch.uiX;    }        return uiInvPressure;}//****************************************************************************// TS_Hardware_Scan_Mode//****************************************************************************// Enables the ep93xx ts scanning engine so that when the pen goes down// we will get an interrupt.// //static void TS_Hardware_Scan_Mode(void){    unsigned int   uiDevCfg;    DPRINTK("S\n");    //	// Disable the soft scanning engine.	//	sTouch.state = TS_STATE_STOPPED;    Stop_Timer2();        //    // Clear the TIN (Touchscreen INactive) bit so we can go to    // automatic scanning mode.    //    uiDevCfg = inl( SYSCON_DEVCFG );    SysconSetLocked( SYSCON_DEVCFG, (uiDevCfg & ~SYSCON_DEVCFG_TIN) );        //    // Enable the touch screen scanning state machine by setting    // the ENABLE bit.    //	outl( (TSSETUP_DEFAULT | TSSETUP_ENABLE), TSSetup );    //    // Set the flag to show that we are in interrupt mode.    //    gScanningMode = TS_MODE_HARDWARE_SCAN;    //    // Initialize TSSetup2 register.    //	outl( TSSETUP2_DEFAULT, TSSetup2 );}//****************************************************************************// TS_Soft_Scan_Mode//****************************************************************************// Sets the touch screen to manual polling mode.// //static void TS_Soft_Scan_Mode(void){    unsigned int   uiDevCfg;    DPRINTK("M\n");    if( gScanningMode != TS_MODE_SOFT_SCAN )    {        //        // Disable the touch screen scanning state machine by clearing        // the ENABLE bit.        //		outl( TSSETUP_DEFAULT, TSSetup );        //        // Set the TIN bit so we can do manual touchscreen polling.        //        uiDevCfg = inl( SYSCON_DEVCFG );        SysconSetLocked( SYSCON_DEVCFG, (uiDevCfg | SYSCON_DEVCFG_TIN) );        }    //	// Set the switch register up for the first ADC reading	//	ep93xx_ts_set_direct( sSwitchSettings.uiSwitchZ1 );		//	// Initialize our software state machine to know which ADC	// reading to take	//    sTouch.state = TS_STATE_Z1;		//	// Set the timer so after a mSec or two settling delay it will 	// take the first ADC reading.	//     Set_Timer2_uSec( EP93XX_TS_PER_POINT_DELAY_USEC );        //    // Note that we are in sw scanning mode not hw scanning mode.    //    gScanningMode = TS_MODE_SOFT_SCAN;}static void Set_Timer2_uSec( unsigned int uiDelay_uSec ){    unsigned int uiClockTicks;    /*     * Stop timer 2     */	outl( 0, TIMER2CONTROL );    uiClockTicks = ((uiDelay_uSec * 508) + 999) / 1000;    outl( uiClockTicks, TIMER2LOAD );    outl( uiClockTicks, TIMER2VALUE );    /*     * Set up Timer 2 for 508 kHz clock and periodic mode.     */     outl( 0xC8, TIMER2CONTROL );}static void Stop_Timer2(void){    outl( 0, TIMER2CONTROL );}/* * Initialization and exit routines */int __initep93xx_ts_init(void){    int retval;    DPRINTK("ep93xx_ts_init\n");    retval = request_irq( IRQ_TOUCH, ep93xx_ts_isr,	SA_INTERRUPT, "ep93xx_ts", 0);    if( retval )    {        printk(KERN_WARNING "ep93xx_ts: failed to get touchscreen IRQ\n");        return retval;    }    retval = request_irq( IRQ_TIMER2, ep93xx_timer2_isr,                        SA_INTERRUPT, "ep93xx_timer2", 0);    if( retval )    {        printk(KERN_WARNING "ep93xx_ts: failed to get timer2 IRQ\n");        return retval;    }    misc_register(&ep93xx_ts_miscdev);    sTouch.state = TS_STATE_STOPPED;	gScanningMode = TS_MODE_UN_INITIALIZED;        printk(KERN_NOTICE "EP93xx touchscreen driver configured for 4-wire operation\n");    return 0;}void __exitep93xx_ts_exit(void){    DPRINTK("ep93xx_ts_exit\n");        Stop_Timer2();    free_irq(IRQ_TOUCH, 0);    free_irq(IRQ_TIMER2, 0);        misc_deregister(&ep93xx_ts_miscdev);}module_init(ep93xx_ts_init);module_exit(ep93xx_ts_exit);MODULE_DESCRIPTION("Cirrus EP93xx touchscreen driver");MODULE_SUPPORTED_DEVICE("touchscreen/ep93xx");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -