2019-05-29 17:17:56 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2011-12-28 09:21:17 +04:00
/*
* Driver for AUO in - cell touchscreens
*
* Copyright ( c ) 2011 Heiko Stuebner < heiko @ sntech . de >
*
* loosely based on auo_touch . c from Dell Streak vendor - kernel
*
* Copyright ( c ) 2008 QUALCOMM Incorporated .
* Copyright ( c ) 2008 QUALCOMM USA , INC .
*/
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/interrupt.h>
# include <linux/slab.h>
# include <linux/input.h>
# include <linux/jiffies.h>
# include <linux/i2c.h>
# include <linux/mutex.h>
# include <linux/delay.h>
# include <linux/gpio.h>
# include <linux/input/auo-pixcir-ts.h>
2013-02-24 00:08:55 +04:00
# include <linux/of.h>
# include <linux/of_gpio.h>
2011-12-28 09:21:17 +04:00
/*
* Coordinate calculation :
* X1 = X1_LSB + X1_MSB * 256
* Y1 = Y1_LSB + Y1_MSB * 256
* X2 = X2_LSB + X2_MSB * 256
* Y2 = Y2_LSB + Y2_MSB * 256
*/
# define AUO_PIXCIR_REG_X1_LSB 0x00
# define AUO_PIXCIR_REG_X1_MSB 0x01
# define AUO_PIXCIR_REG_Y1_LSB 0x02
# define AUO_PIXCIR_REG_Y1_MSB 0x03
# define AUO_PIXCIR_REG_X2_LSB 0x04
# define AUO_PIXCIR_REG_X2_MSB 0x05
# define AUO_PIXCIR_REG_Y2_LSB 0x06
# define AUO_PIXCIR_REG_Y2_MSB 0x07
# define AUO_PIXCIR_REG_STRENGTH 0x0d
# define AUO_PIXCIR_REG_STRENGTH_X1_LSB 0x0e
# define AUO_PIXCIR_REG_STRENGTH_X1_MSB 0x0f
# define AUO_PIXCIR_REG_RAW_DATA_X 0x2b
# define AUO_PIXCIR_REG_RAW_DATA_Y 0x4f
# define AUO_PIXCIR_REG_X_SENSITIVITY 0x6f
# define AUO_PIXCIR_REG_Y_SENSITIVITY 0x70
# define AUO_PIXCIR_REG_INT_SETTING 0x71
# define AUO_PIXCIR_REG_INT_WIDTH 0x72
# define AUO_PIXCIR_REG_POWER_MODE 0x73
# define AUO_PIXCIR_REG_VERSION 0x77
# define AUO_PIXCIR_REG_CALIBRATE 0x78
# define AUO_PIXCIR_REG_TOUCHAREA_X1 0x1e
# define AUO_PIXCIR_REG_TOUCHAREA_Y1 0x1f
# define AUO_PIXCIR_REG_TOUCHAREA_X2 0x20
# define AUO_PIXCIR_REG_TOUCHAREA_Y2 0x21
# define AUO_PIXCIR_REG_EEPROM_CALIB_X 0x42
# define AUO_PIXCIR_REG_EEPROM_CALIB_Y 0xad
# define AUO_PIXCIR_INT_TPNUM_MASK 0xe0
# define AUO_PIXCIR_INT_TPNUM_SHIFT 5
# define AUO_PIXCIR_INT_RELEASE (1 << 4)
# define AUO_PIXCIR_INT_ENABLE (1 << 3)
# define AUO_PIXCIR_INT_POL_HIGH (1 << 2)
# define AUO_PIXCIR_INT_MODE_MASK 0x03
/*
* Power modes :
* active : scan speed 60 Hz
* sleep : scan speed 10 Hz can be auto - activated , wakeup on 1 st touch
* deep sleep : scan speed 1 Hz can only be entered or left manually .
*/
# define AUO_PIXCIR_POWER_ACTIVE 0x00
# define AUO_PIXCIR_POWER_SLEEP 0x01
# define AUO_PIXCIR_POWER_DEEP_SLEEP 0x02
# define AUO_PIXCIR_POWER_MASK 0x03
# define AUO_PIXCIR_POWER_ALLOW_SLEEP (1 << 2)
# define AUO_PIXCIR_POWER_IDLE_TIME(ms) ((ms & 0xf) << 4)
# define AUO_PIXCIR_CALIBRATE 0x03
# define AUO_PIXCIR_EEPROM_CALIB_X_LEN 62
# define AUO_PIXCIR_EEPROM_CALIB_Y_LEN 36
# define AUO_PIXCIR_RAW_DATA_X_LEN 18
# define AUO_PIXCIR_RAW_DATA_Y_LEN 11
# define AUO_PIXCIR_STRENGTH_ENABLE (1 << 0)
/* Touchscreen absolute values */
# define AUO_PIXCIR_REPORT_POINTS 2
# define AUO_PIXCIR_MAX_AREA 0xff
# define AUO_PIXCIR_PENUP_TIMEOUT_MS 10
struct auo_pixcir_ts {
struct i2c_client * client ;
struct input_dev * input ;
2013-02-24 00:06:48 +04:00
const struct auo_pixcir_ts_platdata * pdata ;
2011-12-28 09:21:17 +04:00
char phys [ 32 ] ;
/* special handling for touch_indicate interupt mode */
bool touch_ind_mode ;
wait_queue_head_t wait ;
bool stopped ;
} ;
struct auo_point_t {
int coord_x ;
int coord_y ;
int area_major ;
int area_minor ;
int orientation ;
} ;
static int auo_pixcir_collect_data ( struct auo_pixcir_ts * ts ,
struct auo_point_t * point )
{
struct i2c_client * client = ts - > client ;
2013-02-24 00:06:48 +04:00
const struct auo_pixcir_ts_platdata * pdata = ts - > pdata ;
2011-12-28 09:21:17 +04:00
uint8_t raw_coord [ 8 ] ;
uint8_t raw_area [ 4 ] ;
int i , ret ;
/* touch coordinates */
ret = i2c_smbus_read_i2c_block_data ( client , AUO_PIXCIR_REG_X1_LSB ,
8 , raw_coord ) ;
if ( ret < 0 ) {
dev_err ( & client - > dev , " failed to read coordinate, %d \n " , ret ) ;
return ret ;
}
/* touch area */
ret = i2c_smbus_read_i2c_block_data ( client , AUO_PIXCIR_REG_TOUCHAREA_X1 ,
4 , raw_area ) ;
if ( ret < 0 ) {
dev_err ( & client - > dev , " could not read touch area, %d \n " , ret ) ;
return ret ;
}
for ( i = 0 ; i < AUO_PIXCIR_REPORT_POINTS ; i + + ) {
point [ i ] . coord_x =
raw_coord [ 4 * i + 1 ] < < 8 | raw_coord [ 4 * i ] ;
point [ i ] . coord_y =
raw_coord [ 4 * i + 3 ] < < 8 | raw_coord [ 4 * i + 2 ] ;
if ( point [ i ] . coord_x > pdata - > x_max | |
point [ i ] . coord_y > pdata - > y_max ) {
dev_warn ( & client - > dev , " coordinates (%d,%d) invalid \n " ,
point [ i ] . coord_x , point [ i ] . coord_y ) ;
point [ i ] . coord_x = point [ i ] . coord_y = 0 ;
}
/* determine touch major, minor and orientation */
point [ i ] . area_major = max ( raw_area [ 2 * i ] , raw_area [ 2 * i + 1 ] ) ;
point [ i ] . area_minor = min ( raw_area [ 2 * i ] , raw_area [ 2 * i + 1 ] ) ;
point [ i ] . orientation = raw_area [ 2 * i ] > raw_area [ 2 * i + 1 ] ;
}
return 0 ;
}
static irqreturn_t auo_pixcir_interrupt ( int irq , void * dev_id )
{
struct auo_pixcir_ts * ts = dev_id ;
2013-02-24 00:06:48 +04:00
const struct auo_pixcir_ts_platdata * pdata = ts - > pdata ;
2011-12-28 09:21:17 +04:00
struct auo_point_t point [ AUO_PIXCIR_REPORT_POINTS ] ;
int i ;
int ret ;
int fingers = 0 ;
int abs = - 1 ;
while ( ! ts - > stopped ) {
/* check for up event in touch touch_ind_mode */
if ( ts - > touch_ind_mode ) {
if ( gpio_get_value ( pdata - > gpio_int ) = = 0 ) {
input_mt_sync ( ts - > input ) ;
input_report_key ( ts - > input , BTN_TOUCH , 0 ) ;
input_sync ( ts - > input ) ;
break ;
}
}
ret = auo_pixcir_collect_data ( ts , point ) ;
if ( ret < 0 ) {
/* we want to loop only in touch_ind_mode */
if ( ! ts - > touch_ind_mode )
break ;
wait_event_timeout ( ts - > wait , ts - > stopped ,
msecs_to_jiffies ( AUO_PIXCIR_PENUP_TIMEOUT_MS ) ) ;
continue ;
}
for ( i = 0 ; i < AUO_PIXCIR_REPORT_POINTS ; i + + ) {
if ( point [ i ] . coord_x > 0 | | point [ i ] . coord_y > 0 ) {
input_report_abs ( ts - > input , ABS_MT_POSITION_X ,
point [ i ] . coord_x ) ;
input_report_abs ( ts - > input , ABS_MT_POSITION_Y ,
point [ i ] . coord_y ) ;
input_report_abs ( ts - > input , ABS_MT_TOUCH_MAJOR ,
point [ i ] . area_major ) ;
input_report_abs ( ts - > input , ABS_MT_TOUCH_MINOR ,
point [ i ] . area_minor ) ;
input_report_abs ( ts - > input , ABS_MT_ORIENTATION ,
point [ i ] . orientation ) ;
input_mt_sync ( ts - > input ) ;
/* use first finger as source for singletouch */
if ( fingers = = 0 )
abs = i ;
/* number of touch points could also be queried
* via i2c but would require an additional call
*/
fingers + + ;
}
}
input_report_key ( ts - > input , BTN_TOUCH , fingers > 0 ) ;
if ( abs > - 1 ) {
input_report_abs ( ts - > input , ABS_X , point [ abs ] . coord_x ) ;
input_report_abs ( ts - > input , ABS_Y , point [ abs ] . coord_y ) ;
}
input_sync ( ts - > input ) ;
/* we want to loop only in touch_ind_mode */
if ( ! ts - > touch_ind_mode )
break ;
wait_event_timeout ( ts - > wait , ts - > stopped ,
msecs_to_jiffies ( AUO_PIXCIR_PENUP_TIMEOUT_MS ) ) ;
}
return IRQ_HANDLED ;
}
/*
* Set the power mode of the device .
* Valid modes are
* - AUO_PIXCIR_POWER_ACTIVE
* - AUO_PIXCIR_POWER_SLEEP - automatically left on first touch
* - AUO_PIXCIR_POWER_DEEP_SLEEP
*/
static int auo_pixcir_power_mode ( struct auo_pixcir_ts * ts , int mode )
{
struct i2c_client * client = ts - > client ;
int ret ;
ret = i2c_smbus_read_byte_data ( client , AUO_PIXCIR_REG_POWER_MODE ) ;
if ( ret < 0 ) {
dev_err ( & client - > dev , " unable to read reg %Xh, %d \n " ,
AUO_PIXCIR_REG_POWER_MODE , ret ) ;
return ret ;
}
ret & = ~ AUO_PIXCIR_POWER_MASK ;
ret | = mode ;
ret = i2c_smbus_write_byte_data ( client , AUO_PIXCIR_REG_POWER_MODE , ret ) ;
if ( ret ) {
dev_err ( & client - > dev , " unable to write reg %Xh, %d \n " ,
AUO_PIXCIR_REG_POWER_MODE , ret ) ;
return ret ;
}
return 0 ;
}
2012-11-24 09:38:25 +04:00
static int auo_pixcir_int_config ( struct auo_pixcir_ts * ts ,
2011-12-28 09:21:17 +04:00
int int_setting )
{
struct i2c_client * client = ts - > client ;
2013-02-24 00:06:48 +04:00
const struct auo_pixcir_ts_platdata * pdata = ts - > pdata ;
2011-12-28 09:21:17 +04:00
int ret ;
ret = i2c_smbus_read_byte_data ( client , AUO_PIXCIR_REG_INT_SETTING ) ;
if ( ret < 0 ) {
dev_err ( & client - > dev , " unable to read reg %Xh, %d \n " ,
AUO_PIXCIR_REG_INT_SETTING , ret ) ;
return ret ;
}
ret & = ~ AUO_PIXCIR_INT_MODE_MASK ;
ret | = int_setting ;
ret | = AUO_PIXCIR_INT_POL_HIGH ; /* always use high for interrupts */
ret = i2c_smbus_write_byte_data ( client , AUO_PIXCIR_REG_INT_SETTING ,
ret ) ;
if ( ret < 0 ) {
dev_err ( & client - > dev , " unable to write reg %Xh, %d \n " ,
AUO_PIXCIR_REG_INT_SETTING , ret ) ;
return ret ;
}
ts - > touch_ind_mode = pdata - > int_setting = = AUO_PIXCIR_INT_TOUCH_IND ;
return 0 ;
}
/* control the generation of interrupts on the device side */
static int auo_pixcir_int_toggle ( struct auo_pixcir_ts * ts , bool enable )
{
struct i2c_client * client = ts - > client ;
int ret ;
ret = i2c_smbus_read_byte_data ( client , AUO_PIXCIR_REG_INT_SETTING ) ;
if ( ret < 0 ) {
dev_err ( & client - > dev , " unable to read reg %Xh, %d \n " ,
AUO_PIXCIR_REG_INT_SETTING , ret ) ;
return ret ;
}
if ( enable )
ret | = AUO_PIXCIR_INT_ENABLE ;
else
ret & = ~ AUO_PIXCIR_INT_ENABLE ;
ret = i2c_smbus_write_byte_data ( client , AUO_PIXCIR_REG_INT_SETTING ,
ret ) ;
if ( ret < 0 ) {
dev_err ( & client - > dev , " unable to write reg %Xh, %d \n " ,
AUO_PIXCIR_REG_INT_SETTING , ret ) ;
return ret ;
}
return 0 ;
}
static int auo_pixcir_start ( struct auo_pixcir_ts * ts )
{
struct i2c_client * client = ts - > client ;
int ret ;
ret = auo_pixcir_power_mode ( ts , AUO_PIXCIR_POWER_ACTIVE ) ;
if ( ret < 0 ) {
dev_err ( & client - > dev , " could not set power mode, %d \n " ,
ret ) ;
return ret ;
}
ts - > stopped = false ;
mb ( ) ;
enable_irq ( client - > irq ) ;
ret = auo_pixcir_int_toggle ( ts , 1 ) ;
if ( ret < 0 ) {
dev_err ( & client - > dev , " could not enable interrupt, %d \n " ,
ret ) ;
disable_irq ( client - > irq ) ;
return ret ;
}
return 0 ;
}
static int auo_pixcir_stop ( struct auo_pixcir_ts * ts )
{
struct i2c_client * client = ts - > client ;
int ret ;
ret = auo_pixcir_int_toggle ( ts , 0 ) ;
if ( ret < 0 ) {
dev_err ( & client - > dev , " could not disable interrupt, %d \n " ,
ret ) ;
return ret ;
}
/* disable receiving of interrupts */
disable_irq ( client - > irq ) ;
ts - > stopped = true ;
mb ( ) ;
wake_up ( & ts - > wait ) ;
return auo_pixcir_power_mode ( ts , AUO_PIXCIR_POWER_DEEP_SLEEP ) ;
}
static int auo_pixcir_input_open ( struct input_dev * dev )
{
struct auo_pixcir_ts * ts = input_get_drvdata ( dev ) ;
2015-10-02 21:18:59 +03:00
return auo_pixcir_start ( ts ) ;
2011-12-28 09:21:17 +04:00
}
static void auo_pixcir_input_close ( struct input_dev * dev )
{
struct auo_pixcir_ts * ts = input_get_drvdata ( dev ) ;
auo_pixcir_stop ( ts ) ;
}
2014-11-02 10:04:14 +03:00
static int __maybe_unused auo_pixcir_suspend ( struct device * dev )
2011-12-28 09:21:17 +04:00
{
struct i2c_client * client = to_i2c_client ( dev ) ;
struct auo_pixcir_ts * ts = i2c_get_clientdata ( client ) ;
struct input_dev * input = ts - > input ;
int ret = 0 ;
mutex_lock ( & input - > mutex ) ;
/* when configured as wakeup source, device should always wake system
* therefore start device if necessary
*/
if ( device_may_wakeup ( & client - > dev ) ) {
/* need to start device if not open, to be wakeup source */
if ( ! input - > users ) {
ret = auo_pixcir_start ( ts ) ;
if ( ret )
goto unlock ;
}
enable_irq_wake ( client - > irq ) ;
ret = auo_pixcir_power_mode ( ts , AUO_PIXCIR_POWER_SLEEP ) ;
} else if ( input - > users ) {
ret = auo_pixcir_stop ( ts ) ;
}
unlock :
mutex_unlock ( & input - > mutex ) ;
return ret ;
}
2014-11-02 10:04:14 +03:00
static int __maybe_unused auo_pixcir_resume ( struct device * dev )
2011-12-28 09:21:17 +04:00
{
struct i2c_client * client = to_i2c_client ( dev ) ;
struct auo_pixcir_ts * ts = i2c_get_clientdata ( client ) ;
struct input_dev * input = ts - > input ;
int ret = 0 ;
mutex_lock ( & input - > mutex ) ;
if ( device_may_wakeup ( & client - > dev ) ) {
disable_irq_wake ( client - > irq ) ;
/* need to stop device if it was not open on suspend */
if ( ! input - > users ) {
ret = auo_pixcir_stop ( ts ) ;
if ( ret )
goto unlock ;
}
/* device wakes automatically from SLEEP */
} else if ( input - > users ) {
ret = auo_pixcir_start ( ts ) ;
}
unlock :
mutex_unlock ( & input - > mutex ) ;
return ret ;
}
2013-02-24 00:08:55 +04:00
static SIMPLE_DEV_PM_OPS ( auo_pixcir_pm_ops ,
auo_pixcir_suspend , auo_pixcir_resume ) ;
# ifdef CONFIG_OF
static struct auo_pixcir_ts_platdata * auo_pixcir_parse_dt ( struct device * dev )
{
struct auo_pixcir_ts_platdata * pdata ;
struct device_node * np = dev - > of_node ;
if ( ! np )
return ERR_PTR ( - ENOENT ) ;
pdata = devm_kzalloc ( dev , sizeof ( * pdata ) , GFP_KERNEL ) ;
2018-01-22 21:54:21 +03:00
if ( ! pdata )
2013-02-24 00:08:55 +04:00
return ERR_PTR ( - ENOMEM ) ;
pdata - > gpio_int = of_get_gpio ( np , 0 ) ;
if ( ! gpio_is_valid ( pdata - > gpio_int ) ) {
dev_err ( dev , " failed to get interrupt gpio \n " ) ;
return ERR_PTR ( - EINVAL ) ;
}
pdata - > gpio_rst = of_get_gpio ( np , 1 ) ;
if ( ! gpio_is_valid ( pdata - > gpio_rst ) ) {
dev_err ( dev , " failed to get reset gpio \n " ) ;
return ERR_PTR ( - EINVAL ) ;
}
if ( of_property_read_u32 ( np , " x-size " , & pdata - > x_max ) ) {
dev_err ( dev , " failed to get x-size property \n " ) ;
return ERR_PTR ( - EINVAL ) ;
}
if ( of_property_read_u32 ( np , " y-size " , & pdata - > y_max ) ) {
dev_err ( dev , " failed to get y-size property \n " ) ;
return ERR_PTR ( - EINVAL ) ;
}
/* default to asserting the interrupt when the screen is touched */
pdata - > int_setting = AUO_PIXCIR_INT_TOUCH_IND ;
return pdata ;
}
# else
static struct auo_pixcir_ts_platdata * auo_pixcir_parse_dt ( struct device * dev )
{
return ERR_PTR ( - EINVAL ) ;
}
# endif
2011-12-28 09:21:17 +04:00
2013-02-24 00:18:14 +04:00
static void auo_pixcir_reset ( void * data )
{
struct auo_pixcir_ts * ts = data ;
gpio_set_value ( ts - > pdata - > gpio_rst , 0 ) ;
}
2012-11-24 09:38:25 +04:00
static int auo_pixcir_probe ( struct i2c_client * client ,
2013-02-24 00:18:14 +04:00
const struct i2c_device_id * id )
2011-12-28 09:21:17 +04:00
{
2013-02-24 00:08:55 +04:00
const struct auo_pixcir_ts_platdata * pdata ;
2011-12-28 09:21:17 +04:00
struct auo_pixcir_ts * ts ;
struct input_dev * input_dev ;
2013-02-24 00:18:14 +04:00
int version ;
int error ;
2011-12-28 09:21:17 +04:00
2013-02-24 00:08:55 +04:00
pdata = dev_get_platdata ( & client - > dev ) ;
if ( ! pdata ) {
pdata = auo_pixcir_parse_dt ( & client - > dev ) ;
if ( IS_ERR ( pdata ) )
return PTR_ERR ( pdata ) ;
}
2011-12-28 09:21:17 +04:00
2013-02-24 00:18:14 +04:00
ts = devm_kzalloc ( & client - > dev ,
sizeof ( struct auo_pixcir_ts ) , GFP_KERNEL ) ;
2011-12-28 09:21:17 +04:00
if ( ! ts )
return - ENOMEM ;
2013-02-24 00:18:14 +04:00
input_dev = devm_input_allocate_device ( & client - > dev ) ;
if ( ! input_dev ) {
dev_err ( & client - > dev , " could not allocate input device \n " ) ;
return - ENOMEM ;
2013-02-24 00:06:44 +04:00
}
2013-02-24 00:06:48 +04:00
ts - > pdata = pdata ;
2011-12-28 09:21:17 +04:00
ts - > client = client ;
2013-02-24 00:18:14 +04:00
ts - > input = input_dev ;
2011-12-28 09:21:17 +04:00
ts - > touch_ind_mode = 0 ;
2013-02-24 00:18:14 +04:00
ts - > stopped = true ;
2011-12-28 09:21:17 +04:00
init_waitqueue_head ( & ts - > wait ) ;
snprintf ( ts - > phys , sizeof ( ts - > phys ) ,
" %s/input0 " , dev_name ( & client - > dev ) ) ;
input_dev - > name = " AUO-Pixcir touchscreen " ;
input_dev - > phys = ts - > phys ;
input_dev - > id . bustype = BUS_I2C ;
input_dev - > open = auo_pixcir_input_open ;
input_dev - > close = auo_pixcir_input_close ;
__set_bit ( EV_ABS , input_dev - > evbit ) ;
__set_bit ( EV_KEY , input_dev - > evbit ) ;
__set_bit ( BTN_TOUCH , input_dev - > keybit ) ;
/* For single touch */
input_set_abs_params ( input_dev , ABS_X , 0 , pdata - > x_max , 0 , 0 ) ;
input_set_abs_params ( input_dev , ABS_Y , 0 , pdata - > y_max , 0 , 0 ) ;
/* For multi touch */
input_set_abs_params ( input_dev , ABS_MT_POSITION_X , 0 ,
pdata - > x_max , 0 , 0 ) ;
input_set_abs_params ( input_dev , ABS_MT_POSITION_Y , 0 ,
pdata - > y_max , 0 , 0 ) ;
input_set_abs_params ( input_dev , ABS_MT_TOUCH_MAJOR , 0 ,
AUO_PIXCIR_MAX_AREA , 0 , 0 ) ;
input_set_abs_params ( input_dev , ABS_MT_TOUCH_MINOR , 0 ,
AUO_PIXCIR_MAX_AREA , 0 , 0 ) ;
input_set_abs_params ( input_dev , ABS_MT_ORIENTATION , 0 , 1 , 0 , 0 ) ;
input_set_drvdata ( ts - > input , ts ) ;
2013-02-24 00:18:14 +04:00
error = devm_gpio_request_one ( & client - > dev , pdata - > gpio_int ,
GPIOF_DIR_IN , " auo_pixcir_ts_int " ) ;
if ( error ) {
dev_err ( & client - > dev , " request of gpio %d failed, %d \n " ,
pdata - > gpio_int , error ) ;
return error ;
2011-12-28 09:21:17 +04:00
}
2013-02-24 00:18:14 +04:00
error = devm_gpio_request_one ( & client - > dev , pdata - > gpio_rst ,
GPIOF_DIR_OUT | GPIOF_INIT_HIGH ,
" auo_pixcir_ts_rst " ) ;
if ( error ) {
dev_err ( & client - > dev , " request of gpio %d failed, %d \n " ,
pdata - > gpio_rst , error ) ;
return error ;
2011-12-28 09:21:17 +04:00
}
2019-07-13 11:05:19 +03:00
error = devm_add_action_or_reset ( & client - > dev , auo_pixcir_reset , ts ) ;
2013-02-24 00:18:14 +04:00
if ( error ) {
dev_err ( & client - > dev , " failed to register reset action, %d \n " ,
error ) ;
return error ;
}
2011-12-28 09:21:17 +04:00
2013-02-24 00:18:14 +04:00
msleep ( 200 ) ;
2011-12-28 09:21:17 +04:00
2013-02-24 00:18:14 +04:00
version = i2c_smbus_read_byte_data ( client , AUO_PIXCIR_REG_VERSION ) ;
if ( version < 0 ) {
error = version ;
return error ;
}
2011-12-28 09:21:17 +04:00
2013-02-24 00:18:14 +04:00
dev_info ( & client - > dev , " firmware version 0x%X \n " , version ) ;
2011-12-28 09:21:17 +04:00
2013-02-24 00:18:14 +04:00
error = auo_pixcir_int_config ( ts , pdata - > int_setting ) ;
if ( error )
return error ;
2011-12-28 09:21:17 +04:00
2013-02-24 00:18:14 +04:00
error = devm_request_threaded_irq ( & client - > dev , client - > irq ,
NULL , auo_pixcir_interrupt ,
IRQF_TRIGGER_RISING | IRQF_ONESHOT ,
input_dev - > name , ts ) ;
if ( error ) {
dev_err ( & client - > dev , " irq %d requested failed, %d \n " ,
client - > irq , error ) ;
return error ;
}
2011-12-28 09:21:17 +04:00
2013-02-24 00:18:14 +04:00
/* stop device and put it into deep sleep until it is opened */
error = auo_pixcir_stop ( ts ) ;
if ( error )
return error ;
error = input_register_device ( input_dev ) ;
if ( error ) {
dev_err ( & client - > dev , " could not register input device, %d \n " ,
error ) ;
return error ;
}
2011-12-28 09:21:17 +04:00
2013-02-24 00:18:14 +04:00
i2c_set_clientdata ( client , ts ) ;
2011-12-28 09:21:17 +04:00
return 0 ;
}
static const struct i2c_device_id auo_pixcir_idtable [ ] = {
{ " auo_pixcir_ts " , 0 } ,
{ }
} ;
MODULE_DEVICE_TABLE ( i2c , auo_pixcir_idtable ) ;
2013-02-24 00:08:55 +04:00
# ifdef CONFIG_OF
2014-05-08 00:05:15 +04:00
static const struct of_device_id auo_pixcir_ts_dt_idtable [ ] = {
2013-02-24 00:08:55 +04:00
{ . compatible = " auo,auo_pixcir_ts " } ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( of , auo_pixcir_ts_dt_idtable ) ;
# endif
2011-12-28 09:21:17 +04:00
static struct i2c_driver auo_pixcir_driver = {
. driver = {
. name = " auo_pixcir_ts " ,
. pm = & auo_pixcir_pm_ops ,
2013-02-24 00:08:55 +04:00
. of_match_table = of_match_ptr ( auo_pixcir_ts_dt_idtable ) ,
2011-12-28 09:21:17 +04:00
} ,
. probe = auo_pixcir_probe ,
. id_table = auo_pixcir_idtable ,
} ;
2012-03-17 10:05:44 +04:00
module_i2c_driver ( auo_pixcir_driver ) ;
2011-12-28 09:21:17 +04:00
MODULE_DESCRIPTION ( " AUO-PIXCIR touchscreen driver " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;
MODULE_AUTHOR ( " Heiko Stuebner <heiko@sntech.de> " ) ;