2015-11-03 04:45:51 +03:00
/*
* TSC2004 / TSC2005 touchscreen driver core
*
* Copyright ( C ) 2006 - 2010 Nokia Corporation
* Copyright ( C ) 2015 QWERTY Embedded Design
* Copyright ( C ) 2015 EMAC Inc .
*
* 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 .
*/
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/input.h>
# include <linux/input/touchscreen.h>
# include <linux/interrupt.h>
# include <linux/delay.h>
# include <linux/pm.h>
# include <linux/of.h>
# include <linux/regulator/consumer.h>
# include <linux/regmap.h>
# include <linux/gpio/consumer.h>
# include "tsc200x-core.h"
/*
* The touchscreen interface operates as follows :
*
* 1 ) Pen is pressed against the touchscreen .
2015-11-03 04:51:49 +03:00
* 2 ) TSC200X performs AD conversion .
* 3 ) After the conversion is done TSC200X drives DAV line down .
* 4 ) GPIO IRQ is received and tsc200x_irq_thread ( ) is scheduled .
* 5 ) tsc200x_irq_thread ( ) queues up a transfer to fetch the x , y , z1 , z2
2015-11-03 04:45:51 +03:00
* values .
2015-11-03 04:51:49 +03:00
* 6 ) tsc200x_irq_thread ( ) reports coordinates to input layer and sets up
* tsc200x_penup_timer ( ) to be called after TSC200X_PENUP_TIME_MS ( 40 ms ) .
2015-11-03 04:45:51 +03:00
* 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 .
*
2015-11-03 04:51:49 +03:00
* ESD recovery via a hardware reset is done if the TSC200X doesn ' t respond
2015-11-03 04:45:51 +03:00
* after a configurable period ( in ms ) of activity . If esd_timeout is 0 , the
* watchdog is disabled .
*/
2015-11-03 04:51:49 +03:00
static const struct regmap_range tsc200x_writable_ranges [ ] = {
regmap_reg_range ( TSC200X_REG_AUX_HIGH , TSC200X_REG_CFR2 ) ,
2015-11-03 04:45:51 +03:00
} ;
2015-11-03 04:51:49 +03:00
static const struct regmap_access_table tsc200x_writable_table = {
. yes_ranges = tsc200x_writable_ranges ,
. n_yes_ranges = ARRAY_SIZE ( tsc200x_writable_ranges ) ,
2015-11-03 04:45:51 +03:00
} ;
const struct regmap_config tsc200x_regmap_config = {
. reg_bits = 8 ,
. val_bits = 16 ,
. reg_stride = 0x08 ,
. max_register = 0x78 ,
2015-11-03 04:51:49 +03:00
. read_flag_mask = TSC200X_REG_READ ,
. write_flag_mask = TSC200X_REG_PND0 ,
. wr_table = & tsc200x_writable_table ,
2018-09-01 19:50:41 +03:00
. use_single_read = true ,
. use_single_write = true ,
2015-11-03 04:45:51 +03:00
} ;
EXPORT_SYMBOL_GPL ( tsc200x_regmap_config ) ;
2015-11-03 04:51:49 +03:00
struct tsc200x_data {
2015-11-03 04:45:51 +03:00
u16 x ;
u16 y ;
u16 z1 ;
u16 z2 ;
} __packed ;
2015-11-03 04:51:49 +03:00
# define TSC200X_DATA_REGS 4
2015-11-03 04:45:51 +03:00
2015-11-03 04:51:49 +03:00
struct tsc200x {
2015-11-03 04:45:51 +03:00
struct device * dev ;
struct regmap * regmap ;
__u16 bustype ;
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 ;
spinlock_t lock ;
struct timer_list penup_timer ;
unsigned int esd_timeout ;
struct delayed_work esd_work ;
unsigned long last_valid_interrupt ;
unsigned int x_plate_ohm ;
bool opened ;
bool suspended ;
bool pen_down ;
struct regulator * vio ;
struct gpio_desc * reset_gpio ;
int ( * tsc200x_cmd ) ( struct device * dev , u8 cmd ) ;
int irq ;
} ;
2015-11-03 04:51:49 +03:00
static void tsc200x_update_pen_state ( struct tsc200x * ts ,
2015-11-03 04:45:51 +03:00
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 ) ;
ts - > pen_down = true ;
}
} else {
input_report_abs ( ts - > idev , ABS_PRESSURE , 0 ) ;
if ( ts - > pen_down ) {
input_report_key ( ts - > idev , BTN_TOUCH , 0 ) ;
ts - > pen_down = false ;
}
}
input_sync ( ts - > idev ) ;
dev_dbg ( ts - > dev , " point(%4d,%4d), pressure (%4d) \n " , x , y ,
pressure ) ;
}
2015-11-03 04:51:49 +03:00
static irqreturn_t tsc200x_irq_thread ( int irq , void * _ts )
2015-11-03 04:45:51 +03:00
{
2015-11-03 04:51:49 +03:00
struct tsc200x * ts = _ts ;
2015-11-03 04:45:51 +03:00
unsigned long flags ;
unsigned int pressure ;
2015-11-03 04:51:49 +03:00
struct tsc200x_data tsdata ;
2015-11-03 04:45:51 +03:00
int error ;
/* read the coordinates */
2015-11-03 04:51:49 +03:00
error = regmap_bulk_read ( ts - > regmap , TSC200X_REG_X , & tsdata ,
TSC200X_DATA_REGS ) ;
2015-11-03 04:45:51 +03:00
if ( unlikely ( error ) )
goto out ;
/* validate position */
if ( unlikely ( tsdata . x > MAX_12BIT | | tsdata . y > MAX_12BIT ) )
goto out ;
/* Skip reading if the pressure components are out of range */
if ( unlikely ( tsdata . z1 = = 0 | | tsdata . z2 > MAX_12BIT ) )
goto out ;
if ( unlikely ( tsdata . z1 > = tsdata . z2 ) )
goto out ;
/*
* Skip point if this is a pen down with the exact same values as
* the value before pen - up - that implies SPI fed us stale data
*/
if ( ! ts - > pen_down & &
ts - > in_x = = tsdata . x & & ts - > in_y = = tsdata . y & &
ts - > in_z1 = = tsdata . z1 & & ts - > in_z2 = = tsdata . z2 ) {
goto out ;
}
/*
* At this point we are happy we have a valid and useful reading .
* Remember it for later comparisons . We may now begin downsampling .
*/
ts - > in_x = tsdata . x ;
ts - > in_y = tsdata . y ;
ts - > in_z1 = tsdata . z1 ;
ts - > in_z2 = tsdata . z2 ;
/* Compute touch pressure resistance using equation #1 */
pressure = tsdata . x * ( tsdata . z2 - tsdata . z1 ) / tsdata . z1 ;
pressure = pressure * ts - > x_plate_ohm / 4096 ;
if ( unlikely ( pressure > MAX_12BIT ) )
goto out ;
spin_lock_irqsave ( & ts - > lock , flags ) ;
2015-11-03 04:51:49 +03:00
tsc200x_update_pen_state ( ts , tsdata . x , tsdata . y , pressure ) ;
2015-11-03 04:45:51 +03:00
mod_timer ( & ts - > penup_timer ,
2015-11-03 04:51:49 +03:00
jiffies + msecs_to_jiffies ( TSC200X_PENUP_TIME_MS ) ) ;
2015-11-03 04:45:51 +03:00
spin_unlock_irqrestore ( & ts - > lock , flags ) ;
ts - > last_valid_interrupt = jiffies ;
out :
return IRQ_HANDLED ;
}
2017-10-24 19:44:48 +03:00
static void tsc200x_penup_timer ( struct timer_list * t )
2015-11-03 04:45:51 +03:00
{
2017-10-24 19:44:48 +03:00
struct tsc200x * ts = from_timer ( ts , t , penup_timer ) ;
2015-11-03 04:45:51 +03:00
unsigned long flags ;
spin_lock_irqsave ( & ts - > lock , flags ) ;
2015-11-03 04:51:49 +03:00
tsc200x_update_pen_state ( ts , 0 , 0 , 0 ) ;
2015-11-03 04:45:51 +03:00
spin_unlock_irqrestore ( & ts - > lock , flags ) ;
}
2015-11-03 04:51:49 +03:00
static void tsc200x_start_scan ( struct tsc200x * ts )
2015-11-03 04:45:51 +03:00
{
2015-11-03 04:51:49 +03:00
regmap_write ( ts - > regmap , TSC200X_REG_CFR0 , TSC200X_CFR0_INITVALUE ) ;
regmap_write ( ts - > regmap , TSC200X_REG_CFR1 , TSC200X_CFR1_INITVALUE ) ;
regmap_write ( ts - > regmap , TSC200X_REG_CFR2 , TSC200X_CFR2_INITVALUE ) ;
ts - > tsc200x_cmd ( ts - > dev , TSC200X_CMD_NORMAL ) ;
2015-11-03 04:45:51 +03:00
}
2015-11-03 04:51:49 +03:00
static void tsc200x_stop_scan ( struct tsc200x * ts )
2015-11-03 04:45:51 +03:00
{
2015-11-03 04:51:49 +03:00
ts - > tsc200x_cmd ( ts - > dev , TSC200X_CMD_STOP ) ;
2015-11-03 04:45:51 +03:00
}
2017-02-11 02:18:07 +03:00
static void tsc200x_reset ( struct tsc200x * ts )
2015-11-03 04:45:51 +03:00
{
2017-02-11 02:18:07 +03:00
if ( ts - > reset_gpio ) {
gpiod_set_value_cansleep ( ts - > reset_gpio , 1 ) ;
usleep_range ( 100 , 500 ) ; /* only 10us required */
gpiod_set_value_cansleep ( ts - > reset_gpio , 0 ) ;
}
2015-11-03 04:45:51 +03:00
}
/* must be called with ts->mutex held */
2015-11-03 04:51:49 +03:00
static void __tsc200x_disable ( struct tsc200x * ts )
2015-11-03 04:45:51 +03:00
{
2015-11-03 04:51:49 +03:00
tsc200x_stop_scan ( ts ) ;
2015-11-03 04:45:51 +03:00
disable_irq ( ts - > irq ) ;
del_timer_sync ( & ts - > penup_timer ) ;
cancel_delayed_work_sync ( & ts - > esd_work ) ;
enable_irq ( ts - > irq ) ;
}
/* must be called with ts->mutex held */
2015-11-03 04:51:49 +03:00
static void __tsc200x_enable ( struct tsc200x * ts )
2015-11-03 04:45:51 +03:00
{
2015-11-03 04:51:49 +03:00
tsc200x_start_scan ( ts ) ;
2015-11-03 04:45:51 +03:00
2017-02-11 02:18:07 +03:00
if ( ts - > esd_timeout & & ts - > reset_gpio ) {
2015-11-03 04:45:51 +03:00
ts - > last_valid_interrupt = jiffies ;
schedule_delayed_work ( & ts - > esd_work ,
round_jiffies_relative (
msecs_to_jiffies ( ts - > esd_timeout ) ) ) ;
}
}
2015-11-03 04:51:49 +03:00
static ssize_t tsc200x_selftest_show ( struct device * dev ,
2015-11-03 04:45:51 +03:00
struct device_attribute * attr ,
char * buf )
{
2015-11-03 04:51:49 +03:00
struct tsc200x * ts = dev_get_drvdata ( dev ) ;
2015-11-03 04:45:51 +03:00
unsigned int temp_high ;
unsigned int temp_high_orig ;
unsigned int temp_high_test ;
bool success = true ;
int error ;
mutex_lock ( & ts - > mutex ) ;
/*
2015-11-03 04:51:49 +03:00
* Test TSC200X communications via temp high register .
2015-11-03 04:45:51 +03:00
*/
2015-11-03 04:51:49 +03:00
__tsc200x_disable ( ts ) ;
2015-11-03 04:45:51 +03:00
2015-11-03 04:51:49 +03:00
error = regmap_read ( ts - > regmap , TSC200X_REG_TEMP_HIGH , & temp_high_orig ) ;
2015-11-03 04:45:51 +03:00
if ( error ) {
dev_warn ( dev , " selftest failed: read error %d \n " , error ) ;
success = false ;
goto out ;
}
temp_high_test = ( temp_high_orig - 1 ) & MAX_12BIT ;
2015-11-03 04:51:49 +03:00
error = regmap_write ( ts - > regmap , TSC200X_REG_TEMP_HIGH , temp_high_test ) ;
2015-11-03 04:45:51 +03:00
if ( error ) {
dev_warn ( dev , " selftest failed: write error %d \n " , error ) ;
success = false ;
goto out ;
}
2015-11-03 04:51:49 +03:00
error = regmap_read ( ts - > regmap , TSC200X_REG_TEMP_HIGH , & temp_high ) ;
2015-11-03 04:45:51 +03:00
if ( error ) {
dev_warn ( dev , " selftest failed: read error %d after write \n " ,
error ) ;
success = false ;
goto out ;
}
if ( temp_high ! = temp_high_test ) {
dev_warn ( dev , " selftest failed: %d != %d \n " ,
temp_high , temp_high_test ) ;
success = false ;
}
/* hardware reset */
2017-02-11 02:18:07 +03:00
tsc200x_reset ( ts ) ;
2015-11-03 04:45:51 +03:00
if ( ! success )
goto out ;
/* test that the reset really happened */
2015-11-03 04:51:49 +03:00
error = regmap_read ( ts - > regmap , TSC200X_REG_TEMP_HIGH , & temp_high ) ;
2015-11-03 04:45:51 +03:00
if ( error ) {
dev_warn ( dev , " selftest failed: read error %d after reset \n " ,
error ) ;
success = false ;
goto out ;
}
if ( temp_high ! = temp_high_orig ) {
dev_warn ( dev , " selftest failed after reset: %d != %d \n " ,
temp_high , temp_high_orig ) ;
success = false ;
}
out :
2015-11-03 04:51:49 +03:00
__tsc200x_enable ( ts ) ;
2015-11-03 04:45:51 +03:00
mutex_unlock ( & ts - > mutex ) ;
return sprintf ( buf , " %d \n " , success ) ;
}
2015-11-03 04:51:49 +03:00
static DEVICE_ATTR ( selftest , S_IRUGO , tsc200x_selftest_show , NULL ) ;
2015-11-03 04:45:51 +03:00
2015-11-03 04:51:49 +03:00
static struct attribute * tsc200x_attrs [ ] = {
2015-11-03 04:45:51 +03:00
& dev_attr_selftest . attr ,
NULL
} ;
2015-11-03 04:51:49 +03:00
static umode_t tsc200x_attr_is_visible ( struct kobject * kobj ,
2015-11-03 04:45:51 +03:00
struct attribute * attr , int n )
{
struct device * dev = container_of ( kobj , struct device , kobj ) ;
2015-11-03 04:51:49 +03:00
struct tsc200x * ts = dev_get_drvdata ( dev ) ;
2015-11-03 04:45:51 +03:00
umode_t mode = attr - > mode ;
if ( attr = = & dev_attr_selftest . attr ) {
2017-02-11 02:18:07 +03:00
if ( ! ts - > reset_gpio )
2015-11-03 04:45:51 +03:00
mode = 0 ;
}
return mode ;
}
2015-11-03 04:51:49 +03:00
static const struct attribute_group tsc200x_attr_group = {
. is_visible = tsc200x_attr_is_visible ,
. attrs = tsc200x_attrs ,
2015-11-03 04:45:51 +03:00
} ;
2015-11-03 04:51:49 +03:00
static void tsc200x_esd_work ( struct work_struct * work )
2015-11-03 04:45:51 +03:00
{
2015-11-03 04:51:49 +03:00
struct tsc200x * ts = container_of ( work , struct tsc200x , esd_work . work ) ;
2015-11-03 04:45:51 +03:00
int error ;
unsigned int r ;
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 ;
}
if ( time_is_after_jiffies ( ts - > last_valid_interrupt +
msecs_to_jiffies ( ts - > esd_timeout ) ) )
goto out ;
/* We should be able to read register without disabling interrupts. */
2015-11-03 04:51:49 +03:00
error = regmap_read ( ts - > regmap , TSC200X_REG_CFR0 , & r ) ;
2015-11-03 04:45:51 +03:00
if ( ! error & &
2015-11-03 04:51:49 +03:00
! ( ( r ^ TSC200X_CFR0_INITVALUE ) & TSC200X_CFR0_RW_MASK ) ) {
2015-11-03 04:45:51 +03:00
goto out ;
}
/*
* 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 .
*/
2015-11-03 04:51:49 +03:00
dev_info ( ts - > dev , " TSC200X not responding - resetting \n " ) ;
2015-11-03 04:45:51 +03:00
disable_irq ( ts - > irq ) ;
del_timer_sync ( & ts - > penup_timer ) ;
2015-11-03 04:51:49 +03:00
tsc200x_update_pen_state ( ts , 0 , 0 , 0 ) ;
2015-11-03 04:45:51 +03:00
2017-02-11 02:18:07 +03:00
tsc200x_reset ( ts ) ;
2015-11-03 04:45:51 +03:00
enable_irq ( ts - > irq ) ;
2015-11-03 04:51:49 +03:00
tsc200x_start_scan ( ts ) ;
2015-11-03 04:45:51 +03:00
out :
mutex_unlock ( & ts - > mutex ) ;
reschedule :
/* re-arm the watchdog */
schedule_delayed_work ( & ts - > esd_work ,
round_jiffies_relative (
msecs_to_jiffies ( ts - > esd_timeout ) ) ) ;
}
2015-11-03 04:51:49 +03:00
static int tsc200x_open ( struct input_dev * input )
2015-11-03 04:45:51 +03:00
{
2015-11-03 04:51:49 +03:00
struct tsc200x * ts = input_get_drvdata ( input ) ;
2015-11-03 04:45:51 +03:00
mutex_lock ( & ts - > mutex ) ;
if ( ! ts - > suspended )
2015-11-03 04:51:49 +03:00
__tsc200x_enable ( ts ) ;
2015-11-03 04:45:51 +03:00
ts - > opened = true ;
mutex_unlock ( & ts - > mutex ) ;
return 0 ;
}
2015-11-03 04:51:49 +03:00
static void tsc200x_close ( struct input_dev * input )
2015-11-03 04:45:51 +03:00
{
2015-11-03 04:51:49 +03:00
struct tsc200x * ts = input_get_drvdata ( input ) ;
2015-11-03 04:45:51 +03:00
mutex_lock ( & ts - > mutex ) ;
if ( ! ts - > suspended )
2015-11-03 04:51:49 +03:00
__tsc200x_disable ( ts ) ;
2015-11-03 04:45:51 +03:00
ts - > opened = false ;
mutex_unlock ( & ts - > mutex ) ;
}
2016-07-20 20:02:07 +03:00
int tsc200x_probe ( struct device * dev , int irq , const struct input_id * tsc_id ,
2015-11-03 04:45:51 +03:00
struct regmap * regmap ,
int ( * tsc200x_cmd ) ( struct device * dev , u8 cmd ) )
{
2015-11-03 04:51:49 +03:00
struct tsc200x * ts ;
2015-11-03 04:45:51 +03:00
struct input_dev * input_dev ;
2017-02-11 02:18:07 +03:00
u32 x_plate_ohm ;
u32 esd_timeout ;
2015-11-03 04:45:51 +03:00
int error ;
if ( irq < = 0 ) {
dev_err ( dev , " no irq \n " ) ;
return - ENODEV ;
}
if ( IS_ERR ( regmap ) )
return PTR_ERR ( regmap ) ;
if ( ! tsc200x_cmd ) {
dev_err ( dev , " no cmd function \n " ) ;
return - ENODEV ;
}
ts = devm_kzalloc ( dev , sizeof ( * ts ) , GFP_KERNEL ) ;
if ( ! ts )
return - ENOMEM ;
input_dev = devm_input_allocate_device ( dev ) ;
if ( ! input_dev )
return - ENOMEM ;
ts - > irq = irq ;
ts - > dev = dev ;
ts - > idev = input_dev ;
ts - > regmap = regmap ;
ts - > tsc200x_cmd = tsc200x_cmd ;
2017-02-11 02:18:07 +03:00
error = device_property_read_u32 ( dev , " ti,x-plate-ohms " , & x_plate_ohm ) ;
ts - > x_plate_ohm = error ? TSC200X_DEF_RESISTOR : x_plate_ohm ;
error = device_property_read_u32 ( dev , " ti,esd-recovery-timeout-ms " ,
& esd_timeout ) ;
ts - > esd_timeout = error ? 0 : esd_timeout ;
2015-11-03 04:45:51 +03:00
ts - > reset_gpio = devm_gpiod_get_optional ( dev , " reset " , GPIOD_OUT_HIGH ) ;
if ( IS_ERR ( ts - > reset_gpio ) ) {
error = PTR_ERR ( ts - > reset_gpio ) ;
dev_err ( dev , " error acquiring reset gpio: %d \n " , error ) ;
return error ;
}
2017-02-11 02:30:29 +03:00
ts - > vio = devm_regulator_get ( dev , " vio " ) ;
2015-11-03 04:45:51 +03:00
if ( IS_ERR ( ts - > vio ) ) {
error = PTR_ERR ( ts - > vio ) ;
2017-02-11 02:30:29 +03:00
dev_err ( dev , " error acquiring vio regulator: %d " , error ) ;
2015-11-03 04:45:51 +03:00
return error ;
}
mutex_init ( & ts - > mutex ) ;
spin_lock_init ( & ts - > lock ) ;
2017-10-24 19:44:48 +03:00
timer_setup ( & ts - > penup_timer , tsc200x_penup_timer , 0 ) ;
2015-11-03 04:45:51 +03:00
2015-11-03 04:51:49 +03:00
INIT_DELAYED_WORK ( & ts - > esd_work , tsc200x_esd_work ) ;
2015-11-03 04:45:51 +03:00
snprintf ( ts - > phys , sizeof ( ts - > phys ) ,
" %s/input-ts " , dev_name ( dev ) ) ;
2016-07-20 20:02:07 +03:00
if ( tsc_id - > product = = 2004 ) {
input_dev - > name = " TSC200X touchscreen " ;
} else {
input_dev - > name = devm_kasprintf ( dev , GFP_KERNEL ,
" TSC%04d touchscreen " ,
tsc_id - > product ) ;
if ( ! input_dev - > name )
return - ENOMEM ;
}
2015-11-03 04:45:51 +03:00
input_dev - > phys = ts - > phys ;
2016-07-20 20:02:07 +03:00
input_dev - > id = * tsc_id ;
2015-11-03 04:45:51 +03:00
2015-11-03 04:51:49 +03:00
input_dev - > open = tsc200x_open ;
input_dev - > close = tsc200x_close ;
2015-11-03 04:45:51 +03:00
input_set_drvdata ( input_dev , ts ) ;
2017-11-08 03:20:49 +03:00
__set_bit ( INPUT_PROP_DIRECT , input_dev - > propbit ) ;
2017-02-11 02:18:07 +03:00
input_set_capability ( input_dev , EV_KEY , BTN_TOUCH ) ;
input_set_abs_params ( input_dev , ABS_X ,
0 , MAX_12BIT , TSC200X_DEF_X_FUZZ , 0 ) ;
input_set_abs_params ( input_dev , ABS_Y ,
0 , MAX_12BIT , TSC200X_DEF_Y_FUZZ , 0 ) ;
input_set_abs_params ( input_dev , ABS_PRESSURE ,
0 , MAX_12BIT , TSC200X_DEF_P_FUZZ , 0 ) ;
touchscreen_parse_properties ( input_dev , false , NULL ) ;
2015-11-03 04:45:51 +03:00
/* Ensure the touchscreen is off */
2015-11-03 04:51:49 +03:00
tsc200x_stop_scan ( ts ) ;
2015-11-03 04:45:51 +03:00
error = devm_request_threaded_irq ( dev , irq , NULL ,
2015-11-03 04:51:49 +03:00
tsc200x_irq_thread ,
2015-11-03 04:45:51 +03:00
IRQF_TRIGGER_RISING | IRQF_ONESHOT ,
2015-11-03 04:51:49 +03:00
" tsc200x " , ts ) ;
2015-11-03 04:45:51 +03:00
if ( error ) {
dev_err ( dev , " Failed to request irq, err: %d \n " , error ) ;
return error ;
}
2017-02-11 02:30:29 +03:00
error = regulator_enable ( ts - > vio ) ;
if ( error )
return error ;
2015-11-03 04:45:51 +03:00
dev_set_drvdata ( dev , ts ) ;
2015-11-03 04:51:49 +03:00
error = sysfs_create_group ( & dev - > kobj , & tsc200x_attr_group ) ;
2015-11-03 04:45:51 +03:00
if ( error ) {
dev_err ( dev ,
" Failed to create sysfs attributes, err: %d \n " , error ) ;
goto disable_regulator ;
}
error = input_register_device ( ts - > idev ) ;
if ( error ) {
dev_err ( dev ,
" Failed to register input device, err: %d \n " , error ) ;
goto err_remove_sysfs ;
}
irq_set_irq_wake ( irq , 1 ) ;
return 0 ;
err_remove_sysfs :
2015-11-03 04:51:49 +03:00
sysfs_remove_group ( & dev - > kobj , & tsc200x_attr_group ) ;
2015-11-03 04:45:51 +03:00
disable_regulator :
2017-02-11 02:30:29 +03:00
regulator_disable ( ts - > vio ) ;
2015-11-03 04:45:51 +03:00
return error ;
}
EXPORT_SYMBOL_GPL ( tsc200x_probe ) ;
int tsc200x_remove ( struct device * dev )
{
2015-11-03 04:51:49 +03:00
struct tsc200x * ts = dev_get_drvdata ( dev ) ;
2015-11-03 04:45:51 +03:00
2015-11-03 04:51:49 +03:00
sysfs_remove_group ( & dev - > kobj , & tsc200x_attr_group ) ;
2015-11-03 04:45:51 +03:00
2017-02-11 02:30:29 +03:00
regulator_disable ( ts - > vio ) ;
2015-11-03 04:45:51 +03:00
return 0 ;
}
EXPORT_SYMBOL_GPL ( tsc200x_remove ) ;
2015-11-03 04:51:49 +03:00
static int __maybe_unused tsc200x_suspend ( struct device * dev )
2015-11-03 04:45:51 +03:00
{
2015-11-03 04:51:49 +03:00
struct tsc200x * ts = dev_get_drvdata ( dev ) ;
2015-11-03 04:45:51 +03:00
mutex_lock ( & ts - > mutex ) ;
if ( ! ts - > suspended & & ts - > opened )
2015-11-03 04:51:49 +03:00
__tsc200x_disable ( ts ) ;
2015-11-03 04:45:51 +03:00
ts - > suspended = true ;
mutex_unlock ( & ts - > mutex ) ;
return 0 ;
}
2015-11-03 04:51:49 +03:00
static int __maybe_unused tsc200x_resume ( struct device * dev )
2015-11-03 04:45:51 +03:00
{
2015-11-03 04:51:49 +03:00
struct tsc200x * ts = dev_get_drvdata ( dev ) ;
2015-11-03 04:45:51 +03:00
mutex_lock ( & ts - > mutex ) ;
if ( ts - > suspended & & ts - > opened )
2015-11-03 04:51:49 +03:00
__tsc200x_enable ( ts ) ;
2015-11-03 04:45:51 +03:00
ts - > suspended = false ;
mutex_unlock ( & ts - > mutex ) ;
return 0 ;
}
2015-11-03 04:51:49 +03:00
SIMPLE_DEV_PM_OPS ( tsc200x_pm_ops , tsc200x_suspend , tsc200x_resume ) ;
2015-11-03 04:45:51 +03:00
EXPORT_SYMBOL_GPL ( tsc200x_pm_ops ) ;
MODULE_AUTHOR ( " Lauri Leukkunen <lauri.leukkunen@nokia.com> " ) ;
2015-11-03 04:51:49 +03:00
MODULE_DESCRIPTION ( " TSC200x Touchscreen Driver Core " ) ;
2015-11-03 04:45:51 +03:00
MODULE_LICENSE ( " GPL " ) ;