2011-03-17 08:07:36 +03:00
/*
* TSC2005 touchscreen driver
*
* Copyright ( C ) 2006 - 2010 Nokia Corporation
*
* Author : Lauri Leukkunen < lauri . leukkunen @ nokia . com >
* based on TSC2301 driver by Klaus K . Pedersen < klaus . k . pedersen @ nokia . com >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*
*/
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/input.h>
2014-05-29 10:57:29 +04:00
# include <linux/input/touchscreen.h>
2011-03-17 08:07:36 +03:00
# include <linux/interrupt.h>
# include <linux/delay.h>
2011-03-17 08:08:26 +03:00
# include <linux/pm.h>
2014-05-29 10:57:29 +04:00
# include <linux/of.h>
2011-03-17 08:07:36 +03:00
# include <linux/spi/spi.h>
# include <linux/spi/tsc2005.h>
2014-05-29 10:57:29 +04:00
# include <linux/regulator/consumer.h>
2015-07-28 03:27:25 +03:00
# include <linux/regmap.h>
2015-07-28 03:28:58 +03:00
# include <linux/gpio/consumer.h>
2011-03-17 08:07:36 +03:00
/*
* The touchscreen interface operates as follows :
*
* 1 ) Pen is pressed against the touchscreen .
* 2 ) TSC2005 performs AD conversion .
* 3 ) After the conversion is done TSC2005 drives DAV line down .
* 4 ) GPIO IRQ is received and tsc2005_irq_thread ( ) is scheduled .
* 5 ) tsc2005_irq_thread ( ) queues up an spi transfer to fetch the x , y , z1 , z2
* values .
* 6 ) tsc2005_irq_thread ( ) reports coordinates to input layer and sets up
* tsc2005_penup_timer ( ) to be called after TSC2005_PENUP_TIME_MS ( 40 ms ) .
* 7 ) When the penup timer expires , there have not been touch or DAV interrupts
* during the last 40 ms which means the pen has been lifted .
*
* ESD recovery via a hardware reset is done if the TSC2005 doesn ' t respond
* after a configurable period ( in ms ) of activity . If esd_timeout is 0 , the
* watchdog is disabled .
*/
/* control byte 1 */
# define TSC2005_CMD 0x80
# define TSC2005_CMD_NORMAL 0x00
# define TSC2005_CMD_STOP 0x01
# define TSC2005_CMD_12BIT 0x04
/* control byte 0 */
2015-07-28 03:26:38 +03:00
# define TSC2005_REG_READ 0x01 /* R/W access */
# define TSC2005_REG_PND0 0x02 /* Power Not Down Control */
# define TSC2005_REG_X (0x0 << 3)
# define TSC2005_REG_Y (0x1 << 3)
# define TSC2005_REG_Z1 (0x2 << 3)
# define TSC2005_REG_Z2 (0x3 << 3)
# define TSC2005_REG_AUX (0x4 << 3)
# define TSC2005_REG_TEMP1 (0x5 << 3)
# define TSC2005_REG_TEMP2 (0x6 << 3)
# define TSC2005_REG_STATUS (0x7 << 3)
# define TSC2005_REG_AUX_HIGH (0x8 << 3)
# define TSC2005_REG_AUX_LOW (0x9 << 3)
# define TSC2005_REG_TEMP_HIGH (0xA << 3)
# define TSC2005_REG_TEMP_LOW (0xB << 3)
# define TSC2005_REG_CFR0 (0xC << 3)
# define TSC2005_REG_CFR1 (0xD << 3)
# define TSC2005_REG_CFR2 (0xE << 3)
# define TSC2005_REG_CONV_FUNC (0xF << 3)
2011-03-17 08:07:36 +03:00
/* configuration register 0 */
# define TSC2005_CFR0_PRECHARGE_276US 0x0040
# define TSC2005_CFR0_STABTIME_1MS 0x0300
# define TSC2005_CFR0_CLOCK_1MHZ 0x1000
# define TSC2005_CFR0_RESOLUTION12 0x2000
# define TSC2005_CFR0_PENMODE 0x8000
# define TSC2005_CFR0_INITVALUE (TSC2005_CFR0_STABTIME_1MS | \
TSC2005_CFR0_CLOCK_1MHZ | \
TSC2005_CFR0_RESOLUTION12 | \
TSC2005_CFR0_PRECHARGE_276US | \
TSC2005_CFR0_PENMODE )
/* bits common to both read and write of configuration register 0 */
# define TSC2005_CFR0_RW_MASK 0x3fff
/* configuration register 1 */
# define TSC2005_CFR1_BATCHDELAY_4MS 0x0003
# define TSC2005_CFR1_INITVALUE TSC2005_CFR1_BATCHDELAY_4MS
/* configuration register 2 */
# define TSC2005_CFR2_MAVE_Z 0x0004
# define TSC2005_CFR2_MAVE_Y 0x0008
# define TSC2005_CFR2_MAVE_X 0x0010
# define TSC2005_CFR2_AVG_7 0x0800
# define TSC2005_CFR2_MEDIUM_15 0x3000
# define TSC2005_CFR2_INITVALUE (TSC2005_CFR2_MAVE_X | \
TSC2005_CFR2_MAVE_Y | \
TSC2005_CFR2_MAVE_Z | \
TSC2005_CFR2_MEDIUM_15 | \
TSC2005_CFR2_AVG_7 )
# define MAX_12BIT 0xfff
2014-05-29 10:57:29 +04:00
# define TSC2005_DEF_X_FUZZ 4
# define TSC2005_DEF_Y_FUZZ 8
# define TSC2005_DEF_P_FUZZ 2
# define TSC2005_DEF_RESISTOR 280
2011-03-17 08:07:36 +03:00
# define TSC2005_SPI_MAX_SPEED_HZ 10000000
# define TSC2005_PENUP_TIME_MS 40
2015-07-28 03:27:25 +03:00
static const struct regmap_range tsc2005_writable_ranges [ ] = {
regmap_reg_range ( TSC2005_REG_AUX_HIGH , TSC2005_REG_CFR2 ) ,
2011-03-17 08:07:36 +03:00
} ;
2015-07-28 03:27:25 +03:00
static const struct regmap_access_table tsc2005_writable_table = {
. yes_ranges = tsc2005_writable_ranges ,
. n_yes_ranges = ARRAY_SIZE ( tsc2005_writable_ranges ) ,
} ;
static struct regmap_config tsc2005_regmap_config = {
. reg_bits = 8 ,
. val_bits = 16 ,
. reg_stride = 0x08 ,
. max_register = 0x78 ,
. read_flag_mask = TSC2005_REG_READ ,
. write_flag_mask = TSC2005_REG_PND0 ,
. wr_table = & tsc2005_writable_table ,
. use_single_rw = true ,
} ;
struct tsc2005_data {
u16 x ;
u16 y ;
u16 z1 ;
u16 z2 ;
} __packed ;
# define TSC2005_DATA_REGS 4
2011-03-17 08:07:36 +03:00
struct tsc2005 {
struct spi_device * spi ;
2015-07-28 03:27:25 +03:00
struct regmap * regmap ;
2011-03-17 08:07:36 +03:00
struct input_dev * idev ;
char phys [ 32 ] ;
struct mutex mutex ;
/* raw copy of previous x,y,z */
int in_x ;
int in_y ;
int in_z1 ;
int in_z2 ;
2011-03-17 08:11:08 +03:00
spinlock_t lock ;
2011-03-17 08:07:36 +03:00
struct timer_list penup_timer ;
unsigned int esd_timeout ;
2011-03-17 08:11:34 +03:00
struct delayed_work esd_work ;
unsigned long last_valid_interrupt ;
2011-03-17 08:07:36 +03:00
unsigned int x_plate_ohm ;
2011-03-17 08:11:34 +03:00
bool opened ;
bool suspended ;
2011-03-17 08:10:46 +03:00
bool pen_down ;
2011-03-17 08:07:36 +03:00
2014-05-29 10:57:29 +04:00
struct regulator * vio ;
2015-07-28 03:28:58 +03:00
struct gpio_desc * reset_gpio ;
2011-03-17 08:07:36 +03:00
void ( * set_reset ) ( bool enable ) ;
} ;
2011-03-17 08:11:25 +03:00
static int tsc2005_cmd ( struct tsc2005 * ts , u8 cmd )
2011-03-17 08:07:36 +03:00
{
2011-03-17 08:10:52 +03:00
u8 tx = TSC2005_CMD | TSC2005_CMD_12BIT | cmd ;
struct spi_transfer xfer = {
. tx_buf = & tx ,
. len = 1 ,
. bits_per_word = 8 ,
} ;
2011-03-17 08:07:36 +03:00
struct spi_message msg ;
2011-03-17 08:11:25 +03:00
int error ;
2011-03-17 08:07:36 +03:00
spi_message_init ( & msg ) ;
spi_message_add_tail ( & xfer , & msg ) ;
2011-03-17 08:11:25 +03:00
error = spi_sync ( ts - > spi , & msg ) ;
if ( error ) {
dev_err ( & ts - > spi - > dev , " %s: failed, command: %x, error: %d \n " ,
__func__ , cmd , error ) ;
return error ;
}
return 0 ;
2011-03-17 08:07:36 +03:00
}
static void tsc2005_update_pen_state ( struct tsc2005 * ts ,
int x , int y , int pressure )
{
if ( pressure ) {
input_report_abs ( ts - > idev , ABS_X , x ) ;
input_report_abs ( ts - > idev , ABS_Y , y ) ;
input_report_abs ( ts - > idev , ABS_PRESSURE , pressure ) ;
if ( ! ts - > pen_down ) {
input_report_key ( ts - > idev , BTN_TOUCH , ! ! pressure ) ;
2011-03-17 08:10:46 +03:00
ts - > pen_down = true ;
2011-03-17 08:07:36 +03:00
}
} else {
input_report_abs ( ts - > idev , ABS_PRESSURE , 0 ) ;
if ( ts - > pen_down ) {
input_report_key ( ts - > idev , BTN_TOUCH , 0 ) ;
2011-03-17 08:10:46 +03:00
ts - > pen_down = false ;
2011-03-17 08:07:36 +03:00
}
}
input_sync ( ts - > idev ) ;
dev_dbg ( & ts - > spi - > dev , " point(%4d,%4d), pressure (%4d) \n " , x , y ,
pressure ) ;
}
static irqreturn_t tsc2005_irq_thread ( int irq , void * _ts )
{
struct tsc2005 * ts = _ts ;
2011-03-17 08:11:08 +03:00
unsigned long flags ;
2011-03-17 08:07:36 +03:00
unsigned int pressure ;
2015-07-28 03:27:25 +03:00
struct tsc2005_data tsdata ;
2011-03-17 08:11:25 +03:00
int error ;
2011-03-17 08:07:36 +03:00
/* read the coordinates */
2015-07-28 03:27:25 +03:00
error = regmap_bulk_read ( ts - > regmap , TSC2005_REG_X , & tsdata ,
TSC2005_DATA_REGS ) ;
2011-03-17 08:11:25 +03:00
if ( unlikely ( error ) )
goto out ;
2011-03-17 08:07:36 +03:00
/* validate position */
2015-07-28 03:27:25 +03:00
if ( unlikely ( tsdata . x > MAX_12BIT | | tsdata . y > MAX_12BIT ) )
2011-03-17 08:07:36 +03:00
goto out ;
2011-03-17 08:11:08 +03:00
/* Skip reading if the pressure components are out of range */
2015-07-28 03:27:25 +03:00
if ( unlikely ( tsdata . z1 = = 0 | | tsdata . z2 > MAX_12BIT ) )
goto out ;
if ( unlikely ( tsdata . z1 > = tsdata . z2 ) )
2011-03-17 08:07:36 +03:00
goto out ;
2011-03-17 08:11:08 +03:00
/*
* Skip point if this is a pen down with the exact same values as
2011-03-17 08:07:36 +03:00
* the value before pen - up - that implies SPI fed us stale data
*/
if ( ! ts - > pen_down & &
2015-07-28 03:27:25 +03:00
ts - > in_x = = tsdata . x & & ts - > in_y = = tsdata . y & &
ts - > in_z1 = = tsdata . z1 & & ts - > in_z2 = = tsdata . z2 ) {
2011-03-17 08:07:36 +03:00
goto out ;
2011-03-17 08:11:08 +03:00
}
2011-03-17 08:07:36 +03:00
2011-03-17 08:11:08 +03:00
/*
* At this point we are happy we have a valid and useful reading .
* Remember it for later comparisons . We may now begin downsampling .
*/
2015-07-28 03:27:25 +03:00
ts - > in_x = tsdata . x ;
ts - > in_y = tsdata . y ;
ts - > in_z1 = tsdata . z1 ;
ts - > in_z2 = tsdata . z2 ;
2011-03-17 08:07:36 +03:00
2011-03-17 08:11:08 +03:00
/* Compute touch pressure resistance using equation #1 */
2015-07-28 03:27:25 +03:00
pressure = tsdata . x * ( tsdata . z2 - tsdata . z1 ) / tsdata . z1 ;
2011-03-17 08:07:36 +03:00
pressure = pressure * ts - > x_plate_ohm / 4096 ;
if ( unlikely ( pressure > MAX_12BIT ) )
goto out ;
2011-03-17 08:11:08 +03:00
spin_lock_irqsave ( & ts - > lock , flags ) ;
2015-07-28 03:27:25 +03:00
tsc2005_update_pen_state ( ts , tsdata . x , tsdata . y , pressure ) ;
2011-03-17 08:07:36 +03:00
mod_timer ( & ts - > penup_timer ,
jiffies + msecs_to_jiffies ( TSC2005_PENUP_TIME_MS ) ) ;
2011-03-17 08:11:08 +03:00
spin_unlock_irqrestore ( & ts - > lock , flags ) ;
2011-03-17 08:07:36 +03:00
2011-03-17 08:11:34 +03:00
ts - > last_valid_interrupt = jiffies ;
2011-03-17 08:07:36 +03:00
out :
return IRQ_HANDLED ;
}
static void tsc2005_penup_timer ( unsigned long data )
{
struct tsc2005 * ts = ( struct tsc2005 * ) data ;
2011-03-17 08:11:08 +03:00
unsigned long flags ;
2011-03-17 08:07:36 +03:00
2011-03-17 08:11:08 +03:00
spin_lock_irqsave ( & ts - > lock , flags ) ;
2011-03-17 08:07:36 +03:00
tsc2005_update_pen_state ( ts , 0 , 0 , 0 ) ;
2011-03-17 08:11:08 +03:00
spin_unlock_irqrestore ( & ts - > lock , flags ) ;
2011-03-17 08:07:36 +03:00
}
static void tsc2005_start_scan ( struct tsc2005 * ts )
{
2015-07-28 03:27:25 +03:00
regmap_write ( ts - > regmap , TSC2005_REG_CFR0 , TSC2005_CFR0_INITVALUE ) ;
regmap_write ( ts - > regmap , TSC2005_REG_CFR1 , TSC2005_CFR1_INITVALUE ) ;
regmap_write ( ts - > regmap , TSC2005_REG_CFR2 , TSC2005_CFR2_INITVALUE ) ;
2011-03-17 08:07:36 +03:00
tsc2005_cmd ( ts , TSC2005_CMD_NORMAL ) ;
}
static void tsc2005_stop_scan ( struct tsc2005 * ts )
{
tsc2005_cmd ( ts , TSC2005_CMD_STOP ) ;
}
2014-05-29 10:57:29 +04:00
static void tsc2005_set_reset ( struct tsc2005 * ts , bool enable )
{
2015-07-28 03:28:58 +03:00
if ( ts - > reset_gpio )
gpiod_set_value_cansleep ( ts - > reset_gpio , enable ) ;
2014-05-29 10:57:29 +04:00
else if ( ts - > set_reset )
ts - > set_reset ( enable ) ;
}
2011-03-17 08:11:34 +03:00
/* must be called with ts->mutex held */
static void __tsc2005_disable ( struct tsc2005 * ts )
2011-03-17 08:07:36 +03:00
{
2011-03-17 08:11:34 +03:00
tsc2005_stop_scan ( ts ) ;
2011-03-17 08:07:36 +03:00
disable_irq ( ts - > spi - > irq ) ;
del_timer_sync ( & ts - > penup_timer ) ;
2011-03-17 08:11:34 +03:00
cancel_delayed_work_sync ( & ts - > esd_work ) ;
enable_irq ( ts - > spi - > irq ) ;
2011-03-17 08:07:36 +03:00
}
2011-03-17 08:11:34 +03:00
/* must be called with ts->mutex held */
static void __tsc2005_enable ( struct tsc2005 * ts )
2011-03-17 08:07:36 +03:00
{
tsc2005_start_scan ( ts ) ;
2011-03-17 08:11:34 +03:00
2014-05-29 10:57:29 +04:00
if ( ts - > esd_timeout & & ( ts - > set_reset | | ts - > reset_gpio ) ) {
2011-03-17 08:11:34 +03:00
ts - > last_valid_interrupt = jiffies ;
schedule_delayed_work ( & ts - > esd_work ,
2011-03-24 09:45:11 +03:00
round_jiffies_relative (
2011-03-17 08:11:34 +03:00
msecs_to_jiffies ( ts - > esd_timeout ) ) ) ;
}
2011-03-17 08:07:36 +03:00
}
static ssize_t tsc2005_selftest_show ( struct device * dev ,
struct device_attribute * attr ,
char * buf )
{
2015-07-28 03:28:37 +03:00
struct tsc2005 * ts = dev_get_drvdata ( dev ) ;
2015-07-28 03:27:25 +03:00
unsigned int temp_high ;
unsigned int temp_high_orig ;
unsigned int temp_high_test ;
2011-03-17 08:11:25 +03:00
bool success = true ;
int error ;
2011-03-17 08:07:36 +03:00
mutex_lock ( & ts - > mutex ) ;
/*
* Test TSC2005 communications via temp high register .
*/
2011-03-17 08:11:34 +03:00
__tsc2005_disable ( ts ) ;
2011-03-17 08:11:25 +03:00
2015-07-28 03:27:25 +03:00
error = regmap_read ( ts - > regmap , TSC2005_REG_TEMP_HIGH , & temp_high_orig ) ;
2011-03-17 08:11:25 +03:00
if ( error ) {
dev_warn ( dev , " selftest failed: read error %d \n " , error ) ;
success = false ;
goto out ;
}
2011-03-17 08:07:36 +03:00
temp_high_test = ( temp_high_orig - 1 ) & MAX_12BIT ;
2011-03-17 08:11:25 +03:00
2015-07-28 03:27:25 +03:00
error = regmap_write ( ts - > regmap , TSC2005_REG_TEMP_HIGH , temp_high_test ) ;
2011-03-17 08:11:25 +03:00
if ( error ) {
dev_warn ( dev , " selftest failed: write error %d \n " , error ) ;
success = false ;
goto out ;
}
2015-07-28 03:27:25 +03:00
error = regmap_read ( ts - > regmap , TSC2005_REG_TEMP_HIGH , & temp_high ) ;
2011-03-17 08:11:25 +03:00
if ( error ) {
dev_warn ( dev , " selftest failed: read error %d after write \n " ,
error ) ;
success = false ;
goto out ;
}
2011-03-17 08:07:36 +03:00
if ( temp_high ! = temp_high_test ) {
dev_warn ( dev , " selftest failed: %d != %d \n " ,
temp_high , temp_high_test ) ;
2011-03-17 08:11:25 +03:00
success = false ;
2011-03-17 08:07:36 +03:00
}
/* hardware reset */
2014-05-29 10:57:29 +04:00
tsc2005_set_reset ( ts , false ) ;
2011-03-17 08:07:36 +03:00
usleep_range ( 100 , 500 ) ; /* only 10us required */
2014-05-29 10:57:29 +04:00
tsc2005_set_reset ( ts , true ) ;
2011-03-17 08:11:25 +03:00
if ( ! success )
goto out ;
2011-03-17 08:07:36 +03:00
/* test that the reset really happened */
2015-07-28 03:27:25 +03:00
error = regmap_read ( ts - > regmap , TSC2005_REG_TEMP_HIGH , & temp_high ) ;
2011-03-17 08:11:25 +03:00
if ( error ) {
dev_warn ( dev , " selftest failed: read error %d after reset \n " ,
error ) ;
success = false ;
goto out ;
}
2011-03-17 08:07:36 +03:00
if ( temp_high ! = temp_high_orig ) {
dev_warn ( dev , " selftest failed after reset: %d != %d \n " ,
temp_high , temp_high_orig ) ;
2011-03-17 08:11:25 +03:00
success = false ;
2011-03-17 08:07:36 +03:00
}
2011-03-17 08:11:25 +03:00
out :
2011-03-17 08:11:34 +03:00
__tsc2005_enable ( ts ) ;
2011-03-17 08:07:36 +03:00
mutex_unlock ( & ts - > mutex ) ;
2011-03-17 08:11:25 +03:00
return sprintf ( buf , " %d \n " , success ) ;
2011-03-17 08:07:36 +03:00
}
2011-03-17 08:10:37 +03:00
2011-03-17 08:07:36 +03:00
static DEVICE_ATTR ( selftest , S_IRUGO , tsc2005_selftest_show , NULL ) ;
2011-03-17 08:10:37 +03:00
static struct attribute * tsc2005_attrs [ ] = {
& dev_attr_selftest . attr ,
NULL
} ;
2011-07-24 07:11:19 +04:00
static umode_t tsc2005_attr_is_visible ( struct kobject * kobj ,
2011-03-17 08:10:37 +03:00
struct attribute * attr , int n )
{
struct device * dev = container_of ( kobj , struct device , kobj ) ;
2015-07-28 03:28:37 +03:00
struct tsc2005 * ts = dev_get_drvdata ( dev ) ;
2011-07-24 07:11:19 +04:00
umode_t mode = attr - > mode ;
2011-03-17 08:10:37 +03:00
if ( attr = = & dev_attr_selftest . attr ) {
2014-05-29 10:57:29 +04:00
if ( ! ts - > set_reset & & ! ts - > reset_gpio )
2011-03-17 08:10:37 +03:00
mode = 0 ;
}
return mode ;
}
static const struct attribute_group tsc2005_attr_group = {
. is_visible = tsc2005_attr_is_visible ,
. attrs = tsc2005_attrs ,
} ;
2011-03-17 08:07:36 +03:00
static void tsc2005_esd_work ( struct work_struct * work )
{
2011-03-17 08:11:34 +03:00
struct tsc2005 * ts = container_of ( work , struct tsc2005 , esd_work . work ) ;
2011-03-17 08:11:25 +03:00
int error ;
2015-07-28 03:27:25 +03:00
unsigned int r ;
2011-03-17 08:07:36 +03:00
2011-03-24 09:48:19 +03:00
if ( ! mutex_trylock ( & ts - > mutex ) ) {
/*
* If the mutex is taken , it means that disable or enable is in
* progress . In that case just reschedule the work . If the work
* is not needed , it will be canceled by disable .
*/
goto reschedule ;
}
2011-03-17 08:07:36 +03:00
2011-03-17 08:11:34 +03:00
if ( time_is_after_jiffies ( ts - > last_valid_interrupt +
msecs_to_jiffies ( ts - > esd_timeout ) ) )
2011-03-17 08:07:36 +03:00
goto out ;
2011-03-17 08:11:34 +03:00
/* We should be able to read register without disabling interrupts. */
2015-07-28 03:27:25 +03:00
error = regmap_read ( ts - > regmap , TSC2005_REG_CFR0 , & r ) ;
2011-03-17 08:11:34 +03:00
if ( ! error & &
! ( ( r ^ TSC2005_CFR0_INITVALUE ) & TSC2005_CFR0_RW_MASK ) ) {
goto out ;
2011-03-17 08:07:36 +03:00
}
2011-03-17 08:11:34 +03:00
/*
* If we could not read our known value from configuration register 0
* then we should reset the controller as if from power - up and start
* scanning again .
*/
dev_info ( & ts - > spi - > dev , " TSC2005 not responding - resetting \n " ) ;
disable_irq ( ts - > spi - > irq ) ;
del_timer_sync ( & ts - > penup_timer ) ;
tsc2005_update_pen_state ( ts , 0 , 0 , 0 ) ;
2014-05-29 10:57:29 +04:00
tsc2005_set_reset ( ts , false ) ;
2011-03-17 08:11:34 +03:00
usleep_range ( 100 , 500 ) ; /* only 10us required */
2014-05-29 10:57:29 +04:00
tsc2005_set_reset ( ts , true ) ;
2011-03-17 08:11:34 +03:00
enable_irq ( ts - > spi - > irq ) ;
tsc2005_start_scan ( ts ) ;
2011-03-17 08:07:36 +03:00
out :
2011-03-24 09:48:19 +03:00
mutex_unlock ( & ts - > mutex ) ;
reschedule :
2011-03-17 08:11:34 +03:00
/* re-arm the watchdog */
schedule_delayed_work ( & ts - > esd_work ,
2011-03-24 09:45:11 +03:00
round_jiffies_relative (
2011-03-17 08:11:34 +03:00
msecs_to_jiffies ( ts - > esd_timeout ) ) ) ;
}
static int tsc2005_open ( struct input_dev * input )
{
struct tsc2005 * ts = input_get_drvdata ( input ) ;
mutex_lock ( & ts - > mutex ) ;
2011-03-17 08:11:41 +03:00
if ( ! ts - > suspended )
2011-03-17 08:11:34 +03:00
__tsc2005_enable ( ts ) ;
ts - > opened = true ;
mutex_unlock ( & ts - > mutex ) ;
return 0 ;
}
static void tsc2005_close ( struct input_dev * input )
{
struct tsc2005 * ts = input_get_drvdata ( input ) ;
mutex_lock ( & ts - > mutex ) ;
2011-03-17 08:11:41 +03:00
if ( ! ts - > suspended )
2011-03-17 08:11:34 +03:00
__tsc2005_disable ( ts ) ;
ts - > opened = false ;
2011-03-17 08:07:36 +03:00
mutex_unlock ( & ts - > mutex ) ;
}
2012-11-24 09:38:25 +04:00
static int tsc2005_probe ( struct spi_device * spi )
2011-03-17 08:07:36 +03:00
{
2013-12-06 07:21:10 +04:00
const struct tsc2005_platform_data * pdata = dev_get_platdata ( & spi - > dev ) ;
2014-05-29 10:57:29 +04:00
struct device_node * np = spi - > dev . of_node ;
2011-03-17 08:09:38 +03:00
struct tsc2005 * ts ;
struct input_dev * input_dev ;
2014-05-29 10:57:29 +04:00
unsigned int max_x = MAX_12BIT ;
unsigned int max_y = MAX_12BIT ;
unsigned int max_p = MAX_12BIT ;
unsigned int fudge_x = TSC2005_DEF_X_FUZZ ;
unsigned int fudge_y = TSC2005_DEF_Y_FUZZ ;
unsigned int fudge_p = TSC2005_DEF_P_FUZZ ;
unsigned int x_plate_ohm = TSC2005_DEF_RESISTOR ;
unsigned int esd_timeout ;
2011-03-17 08:09:38 +03:00
int error ;
2011-03-17 08:07:36 +03:00
2014-05-29 10:57:29 +04:00
if ( ! np & & ! pdata ) {
2014-04-26 08:50:13 +04:00
dev_err ( & spi - > dev , " no platform data \n " ) ;
2011-03-17 08:09:38 +03:00
return - ENODEV ;
}
2011-03-17 08:07:36 +03:00
2011-03-17 08:09:38 +03:00
if ( spi - > irq < = 0 ) {
2014-04-26 08:50:13 +04:00
dev_err ( & spi - > dev , " no irq \n " ) ;
2011-03-17 08:09:38 +03:00
return - ENODEV ;
}
2011-03-17 08:07:36 +03:00
2014-05-29 10:57:29 +04:00
if ( pdata ) {
fudge_x = pdata - > ts_x_fudge ;
fudge_y = pdata - > ts_y_fudge ;
fudge_p = pdata - > ts_pressure_fudge ;
max_x = pdata - > ts_x_max ;
max_y = pdata - > ts_y_max ;
max_p = pdata - > ts_pressure_max ;
x_plate_ohm = pdata - > ts_x_plate_ohm ;
esd_timeout = pdata - > esd_timeout_ms ;
} else {
x_plate_ohm = TSC2005_DEF_RESISTOR ;
of_property_read_u32 ( np , " ti,x-plate-ohms " , & x_plate_ohm ) ;
esd_timeout = 0 ;
of_property_read_u32 ( np , " ti,esd-recovery-timeout-ms " ,
& esd_timeout ) ;
}
2011-03-17 08:09:38 +03:00
spi - > mode = SPI_MODE_0 ;
spi - > bits_per_word = 8 ;
if ( ! spi - > max_speed_hz )
spi - > max_speed_hz = TSC2005_SPI_MAX_SPEED_HZ ;
2011-03-17 08:07:36 +03:00
2011-03-17 08:09:38 +03:00
error = spi_setup ( spi ) ;
if ( error )
return error ;
2011-03-17 08:07:36 +03:00
2014-04-26 08:50:21 +04:00
ts = devm_kzalloc ( & spi - > dev , sizeof ( * ts ) , GFP_KERNEL ) ;
if ( ! ts )
return - ENOMEM ;
input_dev = devm_input_allocate_device ( & spi - > dev ) ;
if ( ! input_dev )
return - ENOMEM ;
2011-03-17 08:07:36 +03:00
2011-03-17 08:09:38 +03:00
ts - > spi = spi ;
ts - > idev = input_dev ;
2015-07-28 03:27:25 +03:00
ts - > regmap = devm_regmap_init_spi ( spi , & tsc2005_regmap_config ) ;
if ( IS_ERR ( ts - > regmap ) )
return PTR_ERR ( ts - > regmap ) ;
2014-05-29 10:57:29 +04:00
ts - > x_plate_ohm = x_plate_ohm ;
ts - > esd_timeout = esd_timeout ;
2015-07-28 03:28:58 +03:00
ts - > reset_gpio = devm_gpiod_get_optional ( & spi - > dev , " reset " ,
GPIOD_OUT_HIGH ) ;
if ( IS_ERR ( ts - > reset_gpio ) ) {
error = PTR_ERR ( ts - > reset_gpio ) ;
dev_err ( & spi - > dev , " error acquiring reset gpio: %d \n " , error ) ;
return error ;
}
2014-05-29 10:57:29 +04:00
2015-07-28 03:28:58 +03:00
ts - > vio = devm_regulator_get_optional ( & spi - > dev , " vio " ) ;
if ( IS_ERR ( ts - > vio ) ) {
error = PTR_ERR ( ts - > vio ) ;
dev_err ( & spi - > dev , " vio regulator missing (%d) " , error ) ;
return error ;
}
2014-05-29 10:57:29 +04:00
2015-07-28 03:28:58 +03:00
if ( ! ts - > reset_gpio & & pdata )
2014-05-29 10:57:29 +04:00
ts - > set_reset = pdata - > set_reset ;
2011-03-17 08:07:36 +03:00
2011-03-17 08:09:38 +03:00
mutex_init ( & ts - > mutex ) ;
2011-03-17 08:07:36 +03:00
2011-03-17 08:11:08 +03:00
spin_lock_init ( & ts - > lock ) ;
2011-03-17 08:09:38 +03:00
setup_timer ( & ts - > penup_timer , tsc2005_penup_timer , ( unsigned long ) ts ) ;
2011-03-17 08:07:36 +03:00
2011-03-17 08:11:34 +03:00
INIT_DELAYED_WORK ( & ts - > esd_work , tsc2005_esd_work ) ;
2011-03-17 08:07:36 +03:00
2011-03-17 08:09:38 +03:00
snprintf ( ts - > phys , sizeof ( ts - > phys ) ,
" %s/input-ts " , dev_name ( & spi - > dev ) ) ;
input_dev - > name = " TSC2005 touchscreen " ;
input_dev - > phys = ts - > phys ;
input_dev - > id . bustype = BUS_SPI ;
input_dev - > dev . parent = & spi - > dev ;
input_dev - > evbit [ 0 ] = BIT ( EV_ABS ) | BIT ( EV_KEY ) ;
input_dev - > keybit [ BIT_WORD ( BTN_TOUCH ) ] = BIT_MASK ( BTN_TOUCH ) ;
input_set_abs_params ( input_dev , ABS_X , 0 , max_x , fudge_x , 0 ) ;
input_set_abs_params ( input_dev , ABS_Y , 0 , max_y , fudge_y , 0 ) ;
input_set_abs_params ( input_dev , ABS_PRESSURE , 0 , max_p , fudge_p , 0 ) ;
2014-05-29 10:57:29 +04:00
if ( np )
2015-07-07 01:18:24 +03:00
touchscreen_parse_properties ( input_dev , false ) ;
2014-05-29 10:57:29 +04:00
2011-03-17 08:11:34 +03:00
input_dev - > open = tsc2005_open ;
input_dev - > close = tsc2005_close ;
input_set_drvdata ( input_dev , ts ) ;
/* Ensure the touchscreen is off */
tsc2005_stop_scan ( ts ) ;
2014-04-26 08:50:21 +04:00
error = devm_request_threaded_irq ( & spi - > dev , spi - > irq , NULL ,
tsc2005_irq_thread ,
IRQF_TRIGGER_RISING | IRQF_ONESHOT ,
" tsc2005 " , ts ) ;
2011-03-17 08:09:38 +03:00
if ( error ) {
dev_err ( & spi - > dev , " Failed to request irq, err: %d \n " , error ) ;
2014-04-26 08:50:21 +04:00
return error ;
2011-03-17 08:07:36 +03:00
}
2014-05-29 10:57:29 +04:00
/* enable regulator for DT */
if ( ts - > vio ) {
error = regulator_enable ( ts - > vio ) ;
if ( error )
return error ;
}
2015-07-28 03:28:37 +03:00
dev_set_drvdata ( & spi - > dev , ts ) ;
2011-03-17 08:09:38 +03:00
error = sysfs_create_group ( & spi - > dev . kobj , & tsc2005_attr_group ) ;
if ( error ) {
dev_err ( & spi - > dev ,
" Failed to create sysfs attributes, err: %d \n " , error ) ;
2014-05-29 10:57:29 +04:00
goto disable_regulator ;
2011-03-17 08:07:36 +03:00
}
2011-03-17 08:09:38 +03:00
error = input_register_device ( ts - > idev ) ;
if ( error ) {
dev_err ( & spi - > dev ,
" Failed to register input device, err: %d \n " , error ) ;
goto err_remove_sysfs ;
}
2011-03-17 08:07:36 +03:00
2011-03-21 12:37:07 +03:00
irq_set_irq_wake ( spi - > irq , 1 ) ;
2011-03-17 08:09:38 +03:00
return 0 ;
err_remove_sysfs :
sysfs_remove_group ( & spi - > dev . kobj , & tsc2005_attr_group ) ;
2014-05-29 10:57:29 +04:00
disable_regulator :
if ( ts - > vio )
regulator_disable ( ts - > vio ) ;
2011-03-17 08:09:38 +03:00
return error ;
2011-03-17 08:07:36 +03:00
}
2012-11-24 09:50:47 +04:00
static int tsc2005_remove ( struct spi_device * spi )
2011-03-17 08:07:36 +03:00
{
2015-07-28 03:28:37 +03:00
struct tsc2005 * ts = dev_get_drvdata ( & spi - > dev ) ;
2014-05-29 10:57:29 +04:00
2014-04-26 08:50:21 +04:00
sysfs_remove_group ( & spi - > dev . kobj , & tsc2005_attr_group ) ;
2011-03-17 08:07:36 +03:00
2014-05-29 10:57:29 +04:00
if ( ts - > vio )
regulator_disable ( ts - > vio ) ;
2011-03-17 08:07:36 +03:00
return 0 ;
}
2014-11-02 10:04:14 +03:00
static int __maybe_unused tsc2005_suspend ( struct device * dev )
2011-03-17 08:07:36 +03:00
{
2015-07-28 03:28:37 +03:00
struct tsc2005 * ts = dev_get_drvdata ( dev ) ;
2011-03-17 08:07:36 +03:00
mutex_lock ( & ts - > mutex ) ;
2011-03-17 08:11:34 +03:00
2011-03-17 08:11:41 +03:00
if ( ! ts - > suspended & & ts - > opened )
2011-03-17 08:11:34 +03:00
__tsc2005_disable ( ts ) ;
ts - > suspended = true ;
2011-03-17 08:07:36 +03:00
mutex_unlock ( & ts - > mutex ) ;
return 0 ;
}
2014-11-02 10:04:14 +03:00
static int __maybe_unused tsc2005_resume ( struct device * dev )
2011-03-17 08:07:36 +03:00
{
2015-07-28 03:28:37 +03:00
struct tsc2005 * ts = dev_get_drvdata ( dev ) ;
2011-03-17 08:07:36 +03:00
mutex_lock ( & ts - > mutex ) ;
2011-03-17 08:11:34 +03:00
2011-03-17 08:11:41 +03:00
if ( ts - > suspended & & ts - > opened )
2011-03-17 08:11:34 +03:00
__tsc2005_enable ( ts ) ;
ts - > suspended = false ;
2011-03-17 08:07:36 +03:00
mutex_unlock ( & ts - > mutex ) ;
return 0 ;
}
2011-03-17 08:08:26 +03:00
static SIMPLE_DEV_PM_OPS ( tsc2005_pm_ops , tsc2005_suspend , tsc2005_resume ) ;
2011-03-17 08:07:36 +03:00
static struct spi_driver tsc2005_driver = {
2011-03-17 08:08:26 +03:00
. driver = {
. name = " tsc2005 " ,
. owner = THIS_MODULE ,
. pm = & tsc2005_pm_ops ,
2011-03-17 08:07:36 +03:00
} ,
2011-03-17 08:08:26 +03:00
. probe = tsc2005_probe ,
2012-11-24 09:27:39 +04:00
. remove = tsc2005_remove ,
2011-03-17 08:07:36 +03:00
} ;
2012-03-17 10:05:26 +04:00
module_spi_driver ( tsc2005_driver ) ;
2011-03-17 08:07:36 +03:00
MODULE_AUTHOR ( " Lauri Leukkunen <lauri.leukkunen@nokia.com> " ) ;
2011-03-17 08:09:03 +03:00
MODULE_DESCRIPTION ( " TSC2005 Touchscreen Driver " ) ;
2011-03-17 08:07:36 +03:00
MODULE_LICENSE ( " GPL " ) ;
2013-02-17 10:01:44 +04:00
MODULE_ALIAS ( " spi:tsc2005 " ) ;