2006-11-17 01:07:26 -05:00
/*
* Philips UCB1400 touchscreen driver
*
* Author : Nicolas Pitre
* Created : September 25 , 2006
* Copyright : MontaVista Software , Inc .
*
2008-08-03 21:34:08 +01:00
* Spliting done by : Marek Vasut < marek . vasut @ gmail . com >
2011-03-30 22:57:33 -03:00
* If something doesn ' t work and it worked before spliting , e - mail me ,
2008-08-03 21:34:08 +01:00
* dont bother Nicolas please ; - )
*
2006-11-17 01:07:26 -05:00
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*
* This code is heavily based on ucb1x00 - * . c copyrighted by Russell King
* covering the UCB1100 , UCB1200 and UCB1300 . . Support for the UCB1400 has
* been made separate from ucb1x00 - core / ucb1x00 - ts on Russell ' s request .
*/
# include <linux/module.h>
# include <linux/init.h>
# include <linux/delay.h>
2012-01-04 22:18:42 -08:00
# include <linux/sched.h>
# include <linux/wait.h>
2006-11-17 01:07:26 -05:00
# include <linux/input.h>
# include <linux/device.h>
# include <linux/interrupt.h>
2008-08-03 21:34:08 +01:00
# include <linux/ucb1400.h>
2006-11-17 01:07:26 -05:00
2012-01-04 22:18:42 -08:00
# define UCB1400_TS_POLL_PERIOD 10 /* ms */
2012-01-13 09:32:20 +10:30
static bool adcsync ;
2007-04-12 01:35:43 -04:00
static int ts_delay = 55 ; /* us */
static int ts_delay_pressure ; /* us */
2006-11-17 01:07:26 -05:00
/* Switch to interrupt mode. */
2012-01-04 22:18:42 -08:00
static void ucb1400_ts_mode_int ( struct ucb1400_ts * ucb )
2006-11-17 01:07:26 -05:00
{
2012-01-04 22:18:42 -08:00
ucb1400_reg_write ( ucb - > ac97 , UCB_TS_CR ,
2006-11-17 01:07:26 -05:00
UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |
UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
UCB_TS_CR_MODE_INT ) ;
}
/*
* Switch to pressure mode , and read pressure . We don ' t need to wait
* here , since both plates are being driven .
*/
2012-01-04 22:18:31 -08:00
static unsigned int ucb1400_ts_read_pressure ( struct ucb1400_ts * ucb )
2006-11-17 01:07:26 -05:00
{
2008-08-03 21:34:08 +01:00
ucb1400_reg_write ( ucb - > ac97 , UCB_TS_CR ,
2006-11-17 01:07:26 -05:00
UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |
UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA ) ;
2012-01-04 22:18:42 -08:00
2007-04-12 01:35:43 -04:00
udelay ( ts_delay_pressure ) ;
2012-01-04 22:18:42 -08:00
2008-08-03 21:34:08 +01:00
return ucb1400_adc_read ( ucb - > ac97 , UCB_ADC_INP_TSPY , adcsync ) ;
2006-11-17 01:07:26 -05:00
}
/*
* Switch to X position mode and measure Y plate . We switch the plate
* configuration in pressure mode , then switch to position mode . This
* gives a faster response time . Even so , we need to wait about 55u s
* for things to stabilise .
*/
2012-01-04 22:18:31 -08:00
static unsigned int ucb1400_ts_read_xpos ( struct ucb1400_ts * ucb )
2006-11-17 01:07:26 -05:00
{
2008-08-03 21:34:08 +01:00
ucb1400_reg_write ( ucb - > ac97 , UCB_TS_CR ,
2006-11-17 01:07:26 -05:00
UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA ) ;
2008-08-03 21:34:08 +01:00
ucb1400_reg_write ( ucb - > ac97 , UCB_TS_CR ,
2006-11-17 01:07:26 -05:00
UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA ) ;
2008-08-03 21:34:08 +01:00
ucb1400_reg_write ( ucb - > ac97 , UCB_TS_CR ,
2006-11-17 01:07:26 -05:00
UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA ) ;
2007-04-12 01:35:43 -04:00
udelay ( ts_delay ) ;
2006-11-17 01:07:26 -05:00
2008-08-03 21:34:08 +01:00
return ucb1400_adc_read ( ucb - > ac97 , UCB_ADC_INP_TSPY , adcsync ) ;
2006-11-17 01:07:26 -05:00
}
/*
* Switch to Y position mode and measure X plate . We switch the plate
* configuration in pressure mode , then switch to position mode . This
* gives a faster response time . Even so , we need to wait about 55u s
* for things to stabilise .
*/
2012-01-04 22:18:31 -08:00
static int ucb1400_ts_read_ypos ( struct ucb1400_ts * ucb )
2006-11-17 01:07:26 -05:00
{
2008-08-03 21:34:08 +01:00
ucb1400_reg_write ( ucb - > ac97 , UCB_TS_CR ,
2006-11-17 01:07:26 -05:00
UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA ) ;
2008-08-03 21:34:08 +01:00
ucb1400_reg_write ( ucb - > ac97 , UCB_TS_CR ,
2006-11-17 01:07:26 -05:00
UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA ) ;
2008-08-03 21:34:08 +01:00
ucb1400_reg_write ( ucb - > ac97 , UCB_TS_CR ,
2006-11-17 01:07:26 -05:00
UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA ) ;
2007-04-12 01:35:43 -04:00
udelay ( ts_delay ) ;
2006-11-17 01:07:26 -05:00
2008-08-03 21:34:08 +01:00
return ucb1400_adc_read ( ucb - > ac97 , UCB_ADC_INP_TSPX , adcsync ) ;
2006-11-17 01:07:26 -05:00
}
/*
* Switch to X plate resistance mode . Set MX to ground , PX to
* supply . Measure current .
*/
2012-01-04 22:18:31 -08:00
static unsigned int ucb1400_ts_read_xres ( struct ucb1400_ts * ucb )
2006-11-17 01:07:26 -05:00
{
2008-08-03 21:34:08 +01:00
ucb1400_reg_write ( ucb - > ac97 , UCB_TS_CR ,
2006-11-17 01:07:26 -05:00
UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA ) ;
2008-08-03 21:34:08 +01:00
return ucb1400_adc_read ( ucb - > ac97 , 0 , adcsync ) ;
2006-11-17 01:07:26 -05:00
}
/*
* Switch to Y plate resistance mode . Set MY to ground , PY to
* supply . Measure current .
*/
2012-01-04 22:18:31 -08:00
static unsigned int ucb1400_ts_read_yres ( struct ucb1400_ts * ucb )
2006-11-17 01:07:26 -05:00
{
2008-08-03 21:34:08 +01:00
ucb1400_reg_write ( ucb - > ac97 , UCB_TS_CR ,
2006-11-17 01:07:26 -05:00
UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA ) ;
2008-08-03 21:34:08 +01:00
return ucb1400_adc_read ( ucb - > ac97 , 0 , adcsync ) ;
2006-11-17 01:07:26 -05:00
}
2012-01-04 22:18:42 -08:00
static int ucb1400_ts_pen_up ( struct ucb1400_ts * ucb )
2006-11-17 01:07:26 -05:00
{
2012-01-04 22:18:42 -08:00
unsigned short val = ucb1400_reg_read ( ucb - > ac97 , UCB_TS_CR ) ;
2009-07-12 20:51:25 -07:00
2008-08-03 21:34:08 +01:00
return val & ( UCB_TS_CR_TSPX_LOW | UCB_TS_CR_TSMX_LOW ) ;
2006-11-17 01:07:26 -05:00
}
2012-01-04 22:18:42 -08:00
static void ucb1400_ts_irq_enable ( struct ucb1400_ts * ucb )
2006-11-17 01:07:26 -05:00
{
2012-01-04 22:18:42 -08:00
ucb1400_reg_write ( ucb - > ac97 , UCB_IE_CLEAR , UCB_IE_TSPX ) ;
ucb1400_reg_write ( ucb - > ac97 , UCB_IE_CLEAR , 0 ) ;
ucb1400_reg_write ( ucb - > ac97 , UCB_IE_FAL , UCB_IE_TSPX ) ;
2006-11-17 01:07:26 -05:00
}
2012-01-04 22:18:42 -08:00
static void ucb1400_ts_irq_disable ( struct ucb1400_ts * ucb )
2006-11-17 01:07:26 -05:00
{
2012-01-04 22:18:42 -08:00
ucb1400_reg_write ( ucb - > ac97 , UCB_IE_FAL , 0 ) ;
2006-11-17 01:07:26 -05:00
}
2012-01-04 22:18:42 -08:00
static void ucb1400_ts_report_event ( struct input_dev * idev , u16 pressure , u16 x , u16 y )
2006-11-17 01:07:26 -05:00
{
input_report_abs ( idev , ABS_X , x ) ;
input_report_abs ( idev , ABS_Y , y ) ;
input_report_abs ( idev , ABS_PRESSURE , pressure ) ;
2009-03-04 01:12:49 -08:00
input_report_key ( idev , BTN_TOUCH , 1 ) ;
2006-11-17 01:07:26 -05:00
input_sync ( idev ) ;
}
static void ucb1400_ts_event_release ( struct input_dev * idev )
{
input_report_abs ( idev , ABS_PRESSURE , 0 ) ;
2009-03-04 01:12:49 -08:00
input_report_key ( idev , BTN_TOUCH , 0 ) ;
2006-11-17 01:07:26 -05:00
input_sync ( idev ) ;
}
2012-01-04 22:18:42 -08:00
static void ucb1400_clear_pending_irq ( struct ucb1400_ts * ucb )
2006-11-17 01:07:26 -05:00
{
unsigned int isr ;
2008-08-03 21:34:08 +01:00
isr = ucb1400_reg_read ( ucb - > ac97 , UCB_IE_STATUS ) ;
ucb1400_reg_write ( ucb - > ac97 , UCB_IE_CLEAR , isr ) ;
ucb1400_reg_write ( ucb - > ac97 , UCB_IE_CLEAR , 0 ) ;
2006-11-17 01:07:26 -05:00
2009-08-20 22:30:54 -07:00
if ( isr & UCB_IE_TSPX )
2012-01-04 22:18:42 -08:00
ucb1400_ts_irq_disable ( ucb ) ;
2009-08-20 22:30:54 -07:00
else
2012-01-04 22:18:42 -08:00
dev_dbg ( & ucb - > ts_idev - > dev ,
" ucb1400: unexpected IE_STATUS = %#x \n " , isr ) ;
2006-11-17 01:07:26 -05:00
}
2012-01-04 22:18:42 -08:00
/*
* A restriction with interrupts exists when using the ucb1400 , as
* the codec read / write routines may sleep while waiting for codec
* access completion and uses semaphores for access control to the
* AC97 bus . Therefore the driver is forced to use threaded interrupt
* handler .
*/
static irqreturn_t ucb1400_irq ( int irqnr , void * devid )
2006-11-17 01:07:26 -05:00
{
2012-01-04 22:18:42 -08:00
struct ucb1400_ts * ucb = devid ;
unsigned int x , y , p ;
bool penup ;
2006-11-17 01:07:26 -05:00
2012-01-04 22:18:42 -08:00
if ( unlikely ( irqnr ! = ucb - > irq ) )
return IRQ_NONE ;
2006-11-17 01:07:26 -05:00
2012-01-04 22:18:42 -08:00
ucb1400_clear_pending_irq ( ucb ) ;
2006-11-17 01:07:26 -05:00
2012-01-04 22:18:42 -08:00
/* Start with a small delay before checking pendown state */
msleep ( UCB1400_TS_POLL_PERIOD ) ;
2006-11-17 01:07:26 -05:00
2012-01-04 22:18:42 -08:00
while ( ! ucb - > stopped & & ! ( penup = ucb1400_ts_pen_up ( ucb ) ) ) {
2006-11-17 01:07:26 -05:00
2008-08-03 21:34:08 +01:00
ucb1400_adc_enable ( ucb - > ac97 ) ;
2006-11-17 01:07:26 -05:00
x = ucb1400_ts_read_xpos ( ucb ) ;
y = ucb1400_ts_read_ypos ( ucb ) ;
p = ucb1400_ts_read_pressure ( ucb ) ;
2008-08-03 21:34:08 +01:00
ucb1400_adc_disable ( ucb - > ac97 ) ;
2006-11-17 01:07:26 -05:00
2012-01-04 22:18:42 -08:00
ucb1400_ts_report_event ( ucb - > ts_idev , p , x , y ) ;
2006-11-17 01:07:26 -05:00
2012-01-04 22:18:42 -08:00
wait_event_timeout ( ucb - > ts_wait , ucb - > stopped ,
msecs_to_jiffies ( UCB1400_TS_POLL_PERIOD ) ) ;
2006-11-17 01:07:26 -05:00
}
2012-01-04 22:18:42 -08:00
ucb1400_ts_event_release ( ucb - > ts_idev ) ;
2006-11-17 01:07:26 -05:00
2012-01-04 22:18:42 -08:00
if ( ! ucb - > stopped ) {
/* Switch back to interrupt mode. */
ucb1400_ts_mode_int ( ucb ) ;
ucb1400_ts_irq_enable ( ucb ) ;
}
return IRQ_HANDLED ;
2006-11-17 01:07:26 -05:00
}
2012-01-04 22:18:42 -08:00
static void ucb1400_ts_stop ( struct ucb1400_ts * ucb )
2006-11-17 01:07:26 -05:00
{
2012-01-04 22:18:42 -08:00
/* Signal IRQ thread to stop polling and disable the handler. */
ucb - > stopped = true ;
mb ( ) ;
wake_up ( & ucb - > ts_wait ) ;
disable_irq ( ucb - > irq ) ;
2006-11-17 01:07:26 -05:00
2012-01-04 22:18:42 -08:00
ucb1400_ts_irq_disable ( ucb ) ;
ucb1400_reg_write ( ucb - > ac97 , UCB_TS_CR , 0 ) ;
}
/* Must be called with ts->lock held */
static void ucb1400_ts_start ( struct ucb1400_ts * ucb )
{
/* Tell IRQ thread that it may poll the device. */
ucb - > stopped = false ;
mb ( ) ;
ucb1400_ts_mode_int ( ucb ) ;
ucb1400_ts_irq_enable ( ucb ) ;
enable_irq ( ucb - > irq ) ;
2006-11-17 01:07:26 -05:00
}
static int ucb1400_ts_open ( struct input_dev * idev )
{
2008-08-03 21:34:08 +01:00
struct ucb1400_ts * ucb = input_get_drvdata ( idev ) ;
2006-11-17 01:07:26 -05:00
2012-01-04 22:18:42 -08:00
ucb1400_ts_start ( ucb ) ;
2006-11-17 01:07:26 -05:00
2012-01-04 22:18:42 -08:00
return 0 ;
2006-11-17 01:07:26 -05:00
}
static void ucb1400_ts_close ( struct input_dev * idev )
{
2008-08-03 21:34:08 +01:00
struct ucb1400_ts * ucb = input_get_drvdata ( idev ) ;
2006-11-17 01:07:26 -05:00
2012-01-04 22:18:42 -08:00
ucb1400_ts_stop ( ucb ) ;
2006-11-17 01:07:26 -05:00
}
# ifndef NO_IRQ
# define NO_IRQ 0
# endif
/*
* Try to probe our interrupt , rather than relying on lots of
* hard - coded machine dependencies .
*/
2012-01-04 22:18:51 -08:00
static int __devinit ucb1400_ts_detect_irq ( struct ucb1400_ts * ucb ,
struct platform_device * pdev )
2006-11-17 01:07:26 -05:00
{
unsigned long mask , timeout ;
mask = probe_irq_on ( ) ;
/* Enable the ADC interrupt. */
2008-08-03 21:34:08 +01:00
ucb1400_reg_write ( ucb - > ac97 , UCB_IE_RIS , UCB_IE_ADC ) ;
ucb1400_reg_write ( ucb - > ac97 , UCB_IE_FAL , UCB_IE_ADC ) ;
ucb1400_reg_write ( ucb - > ac97 , UCB_IE_CLEAR , 0xffff ) ;
ucb1400_reg_write ( ucb - > ac97 , UCB_IE_CLEAR , 0 ) ;
2006-11-17 01:07:26 -05:00
/* Cause an ADC interrupt. */
2008-08-03 21:34:08 +01:00
ucb1400_reg_write ( ucb - > ac97 , UCB_ADC_CR , UCB_ADC_ENA ) ;
ucb1400_reg_write ( ucb - > ac97 , UCB_ADC_CR , UCB_ADC_ENA | UCB_ADC_START ) ;
2006-11-17 01:07:26 -05:00
/* Wait for the conversion to complete. */
timeout = jiffies + HZ / 2 ;
2008-08-03 21:34:08 +01:00
while ( ! ( ucb1400_reg_read ( ucb - > ac97 , UCB_ADC_DATA ) &
UCB_ADC_DAT_VALID ) ) {
2006-11-17 01:07:26 -05:00
cpu_relax ( ) ;
if ( time_after ( jiffies , timeout ) ) {
2012-01-04 22:18:51 -08:00
dev_err ( & pdev - > dev , " timed out in IRQ probe \n " ) ;
2006-11-17 01:07:26 -05:00
probe_irq_off ( mask ) ;
return - ENODEV ;
}
}
2008-08-03 21:34:08 +01:00
ucb1400_reg_write ( ucb - > ac97 , UCB_ADC_CR , 0 ) ;
2006-11-17 01:07:26 -05:00
/* Disable and clear interrupt. */
2008-08-03 21:34:08 +01:00
ucb1400_reg_write ( ucb - > ac97 , UCB_IE_RIS , 0 ) ;
ucb1400_reg_write ( ucb - > ac97 , UCB_IE_FAL , 0 ) ;
ucb1400_reg_write ( ucb - > ac97 , UCB_IE_CLEAR , 0xffff ) ;
ucb1400_reg_write ( ucb - > ac97 , UCB_IE_CLEAR , 0 ) ;
2006-11-17 01:07:26 -05:00
/* Read triggered interrupt. */
ucb - > irq = probe_irq_off ( mask ) ;
if ( ucb - > irq < 0 | | ucb - > irq = = NO_IRQ )
return - ENODEV ;
return 0 ;
}
2012-01-04 22:18:42 -08:00
static int __devinit ucb1400_ts_probe ( struct platform_device * pdev )
2006-11-17 01:07:26 -05:00
{
2012-01-04 22:18:42 -08:00
struct ucb1400_ts * ucb = pdev - > dev . platform_data ;
2008-08-03 21:34:08 +01:00
int error , x_res , y_res ;
2009-08-20 22:05:53 -07:00
u16 fcsr ;
2006-11-17 01:07:26 -05:00
2008-08-03 21:34:08 +01:00
ucb - > ts_idev = input_allocate_device ( ) ;
if ( ! ucb - > ts_idev ) {
2006-11-17 01:07:26 -05:00
error = - ENOMEM ;
2008-08-03 21:34:08 +01:00
goto err ;
2006-11-17 01:07:26 -05:00
}
2009-11-08 19:45:54 -08:00
/* Only in case the IRQ line wasn't supplied, try detecting it */
if ( ucb - > irq < 0 ) {
2012-01-04 22:18:51 -08:00
error = ucb1400_ts_detect_irq ( ucb , pdev ) ;
2009-11-08 19:45:54 -08:00
if ( error ) {
2012-01-04 22:18:51 -08:00
dev_err ( & pdev - > dev , " IRQ probe failed \n " ) ;
2009-11-08 19:45:54 -08:00
goto err_free_devs ;
}
2006-11-17 01:07:26 -05:00
}
2012-01-04 22:18:51 -08:00
dev_dbg ( & pdev - > dev , " found IRQ %d \n " , ucb - > irq ) ;
2006-11-17 01:07:26 -05:00
2008-08-03 21:34:08 +01:00
init_waitqueue_head ( & ucb - > ts_wait ) ;
input_set_drvdata ( ucb - > ts_idev , ucb ) ;
2007-04-12 01:34:08 -04:00
2012-01-04 22:18:42 -08:00
ucb - > ts_idev - > dev . parent = & pdev - > dev ;
2008-08-03 21:34:08 +01:00
ucb - > ts_idev - > name = " UCB1400 touchscreen interface " ;
ucb - > ts_idev - > id . vendor = ucb1400_reg_read ( ucb - > ac97 ,
AC97_VENDOR_ID1 ) ;
ucb - > ts_idev - > id . product = ucb - > id ;
ucb - > ts_idev - > open = ucb1400_ts_open ;
ucb - > ts_idev - > close = ucb1400_ts_close ;
2009-03-04 01:12:49 -08:00
ucb - > ts_idev - > evbit [ 0 ] = BIT_MASK ( EV_ABS ) | BIT_MASK ( EV_KEY ) ;
ucb - > ts_idev - > keybit [ BIT_WORD ( BTN_TOUCH ) ] = BIT_MASK ( BTN_TOUCH ) ;
2006-11-17 01:07:26 -05:00
2009-08-20 22:05:53 -07:00
/*
* Enable ADC filter to prevent horrible jitter on Colibri .
* This also further reduces jitter on boards where ADCSYNC
* pin is connected .
*/
fcsr = ucb1400_reg_read ( ucb - > ac97 , UCB_FCSR ) ;
ucb1400_reg_write ( ucb - > ac97 , UCB_FCSR , fcsr | UCB_FCSR_AVE ) ;
2008-08-03 21:34:08 +01:00
ucb1400_adc_enable ( ucb - > ac97 ) ;
2006-11-17 01:07:26 -05:00
x_res = ucb1400_ts_read_xres ( ucb ) ;
y_res = ucb1400_ts_read_yres ( ucb ) ;
2008-08-03 21:34:08 +01:00
ucb1400_adc_disable ( ucb - > ac97 ) ;
2012-01-04 22:18:51 -08:00
dev_dbg ( & pdev - > dev , " x/y = %d/%d \n " , x_res , y_res ) ;
2006-11-17 01:07:26 -05:00
2008-08-03 21:34:08 +01:00
input_set_abs_params ( ucb - > ts_idev , ABS_X , 0 , x_res , 0 , 0 ) ;
input_set_abs_params ( ucb - > ts_idev , ABS_Y , 0 , y_res , 0 , 0 ) ;
input_set_abs_params ( ucb - > ts_idev , ABS_PRESSURE , 0 , 0 , 0 , 0 ) ;
2006-11-17 01:07:26 -05:00
2012-01-04 22:18:42 -08:00
ucb1400_ts_stop ( ucb ) ;
error = request_threaded_irq ( ucb - > irq , NULL , ucb1400_irq ,
IRQF_TRIGGER_RISING | IRQF_ONESHOT ,
" UCB1400 " , ucb ) ;
if ( error ) {
2012-01-04 22:18:51 -08:00
dev_err ( & pdev - > dev ,
" unable to grab irq%d: %d \n " , ucb - > irq , error ) ;
2012-01-04 22:18:42 -08:00
goto err_free_devs ;
}
2008-08-03 21:34:08 +01:00
error = input_register_device ( ucb - > ts_idev ) ;
2006-11-17 01:07:26 -05:00
if ( error )
goto err_free_irq ;
return 0 ;
2008-08-03 21:34:08 +01:00
err_free_irq :
2006-11-17 01:07:26 -05:00
free_irq ( ucb - > irq , ucb ) ;
2008-08-03 21:34:08 +01:00
err_free_devs :
input_free_device ( ucb - > ts_idev ) ;
err :
2006-11-17 01:07:26 -05:00
return error ;
}
2012-01-04 22:18:42 -08:00
static int __devexit ucb1400_ts_remove ( struct platform_device * pdev )
2006-11-17 01:07:26 -05:00
{
2012-01-04 22:18:42 -08:00
struct ucb1400_ts * ucb = pdev - > dev . platform_data ;
2006-11-17 01:07:26 -05:00
free_irq ( ucb - > irq , ucb ) ;
input_unregister_device ( ucb - > ts_idev ) ;
2012-01-04 22:18:22 -08:00
2006-11-17 01:07:26 -05:00
return 0 ;
}
2012-01-04 22:17:57 -08:00
# ifdef CONFIG_PM_SLEEP
2012-01-04 22:18:42 -08:00
static int ucb1400_ts_suspend ( struct device * dev )
{
struct ucb1400_ts * ucb = dev - > platform_data ;
struct input_dev * idev = ucb - > ts_idev ;
mutex_lock ( & idev - > mutex ) ;
if ( idev - > users )
ucb1400_ts_start ( ucb ) ;
mutex_unlock ( & idev - > mutex ) ;
return 0 ;
}
2012-01-04 22:17:57 -08:00
static int ucb1400_ts_resume ( struct device * dev )
2008-08-03 21:34:08 +01:00
{
2012-01-04 22:17:57 -08:00
struct ucb1400_ts * ucb = dev - > platform_data ;
2012-01-04 22:18:42 -08:00
struct input_dev * idev = ucb - > ts_idev ;
2008-08-03 21:34:08 +01:00
2012-01-04 22:18:42 -08:00
mutex_lock ( & idev - > mutex ) ;
if ( idev - > users )
ucb1400_ts_stop ( ucb ) ;
mutex_unlock ( & idev - > mutex ) ;
2008-08-03 21:34:08 +01:00
return 0 ;
}
# endif
2012-01-04 22:18:42 -08:00
static SIMPLE_DEV_PM_OPS ( ucb1400_ts_pm_ops ,
ucb1400_ts_suspend , ucb1400_ts_resume ) ;
2012-01-04 22:17:57 -08:00
2008-08-03 21:34:08 +01:00
static struct platform_driver ucb1400_ts_driver = {
. probe = ucb1400_ts_probe ,
2012-01-04 22:18:22 -08:00
. remove = __devexit_p ( ucb1400_ts_remove ) ,
2008-08-03 21:34:08 +01:00
. driver = {
. name = " ucb1400_ts " ,
2012-01-04 22:18:12 -08:00
. owner = THIS_MODULE ,
2012-01-04 22:17:57 -08:00
. pm = & ucb1400_ts_pm_ops ,
2008-08-03 21:34:08 +01:00
} ,
2006-11-17 01:07:26 -05:00
} ;
2011-11-29 11:14:13 -08:00
module_platform_driver ( ucb1400_ts_driver ) ;
2006-11-17 01:07:26 -05:00
2007-04-12 01:35:43 -04:00
module_param ( adcsync , bool , 0444 ) ;
MODULE_PARM_DESC ( adcsync , " Synchronize touch readings with ADCSYNC pin. " ) ;
module_param ( ts_delay , int , 0444 ) ;
2008-08-03 21:34:08 +01:00
MODULE_PARM_DESC ( ts_delay , " Delay between panel setup and "
" position read. Default = 55us. " ) ;
2007-04-12 01:35:43 -04:00
module_param ( ts_delay_pressure , int , 0444 ) ;
MODULE_PARM_DESC ( ts_delay_pressure ,
2008-08-03 21:34:08 +01:00
" delay between panel setup and pressure read. "
" Default = 0us. " ) ;
2006-11-17 01:07:26 -05:00
MODULE_DESCRIPTION ( " Philips UCB1400 touchscreen driver " ) ;
MODULE_LICENSE ( " GPL " ) ;