2011-12-31 03:16:21 +04:00
/*
* Driver for Pixcir I2C touchscreen controllers .
*
* Copyright ( C ) 2010 - 2011 Pixcir , Inc .
*
* This software is licensed under the terms of the GNU General Public
* License version 2 , as published by the Free Software Foundation , and
* may be copied , distributed , and modified under those terms .
*
* 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 library ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
# include <linux/delay.h>
# include <linux/module.h>
# include <linux/interrupt.h>
# include <linux/slab.h>
# include <linux/i2c.h>
# include <linux/input.h>
2014-07-28 20:58:54 +04:00
# include <linux/input/mt.h>
2015-07-07 00:29:29 +03:00
# include <linux/input/touchscreen.h>
2014-05-19 09:46:43 +04:00
# include <linux/gpio.h>
2015-07-06 21:56:21 +03:00
# include <linux/gpio/consumer.h>
2015-07-07 00:29:29 +03:00
/*#include <linux/of.h>*/
2014-07-28 21:05:39 +04:00
# include <linux/of_device.h>
2015-07-06 21:48:47 +03:00
# include <linux/platform_data/pixcir_i2c_ts.h>
2011-12-31 03:16:21 +04:00
2014-07-28 21:01:07 +04:00
# define PIXCIR_MAX_SLOTS 5 /* Max fingers supported by driver */
2014-07-28 20:58:54 +04:00
2011-12-31 03:16:21 +04:00
struct pixcir_i2c_ts_data {
struct i2c_client * client ;
struct input_dev * input ;
2015-07-06 21:56:21 +03:00
struct gpio_desc * gpio_attb ;
2015-07-06 23:27:43 +03:00
struct gpio_desc * gpio_reset ;
2015-07-07 00:29:29 +03:00
const struct pixcir_i2c_chip_data * chip ;
2014-07-28 21:01:07 +04:00
int max_fingers ; /* Max fingers supported in this instance */
2015-07-07 00:29:29 +03:00
bool running ;
2011-12-31 03:16:21 +04:00
} ;
2014-07-28 20:58:54 +04:00
struct pixcir_touch {
int x ;
int y ;
2014-07-28 21:01:07 +04:00
int id ;
2014-07-28 20:58:54 +04:00
} ;
struct pixcir_report_data {
int num_touches ;
struct pixcir_touch touches [ PIXCIR_MAX_SLOTS ] ;
} ;
static void pixcir_ts_parse ( struct pixcir_i2c_ts_data * tsdata ,
struct pixcir_report_data * report )
2011-12-31 03:16:21 +04:00
{
2014-07-28 21:01:07 +04:00
u8 rdbuf [ 2 + PIXCIR_MAX_SLOTS * 5 ] ;
u8 wrbuf [ 1 ] = { 0 } ;
2014-07-28 20:58:54 +04:00
u8 * bufptr ;
2011-12-31 03:16:21 +04:00
u8 touch ;
2014-07-28 20:58:54 +04:00
int ret , i ;
2014-07-28 21:01:07 +04:00
int readsize ;
2015-07-07 00:29:29 +03:00
const struct pixcir_i2c_chip_data * chip = tsdata - > chip ;
2014-07-28 20:58:54 +04:00
memset ( report , 0 , sizeof ( struct pixcir_report_data ) ) ;
2011-12-31 03:16:21 +04:00
2014-07-28 21:01:07 +04:00
i = chip - > has_hw_ids ? 1 : 0 ;
readsize = 2 + tsdata - > max_fingers * ( 4 + i ) ;
if ( readsize > sizeof ( rdbuf ) )
readsize = sizeof ( rdbuf ) ;
2011-12-31 03:16:21 +04:00
ret = i2c_master_send ( tsdata - > client , wrbuf , sizeof ( wrbuf ) ) ;
if ( ret ! = sizeof ( wrbuf ) ) {
dev_err ( & tsdata - > client - > dev ,
" %s: i2c_master_send failed(), ret=%d \n " ,
__func__ , ret ) ;
return ;
}
2014-07-28 21:01:07 +04:00
ret = i2c_master_recv ( tsdata - > client , rdbuf , readsize ) ;
2015-06-17 01:03:53 +03:00
if ( ret ! = readsize ) {
2011-12-31 03:16:21 +04:00
dev_err ( & tsdata - > client - > dev ,
" %s: i2c_master_recv failed(), ret=%d \n " ,
__func__ , ret ) ;
return ;
}
2014-07-28 20:58:54 +04:00
touch = rdbuf [ 0 ] & 0x7 ;
2014-07-28 21:01:07 +04:00
if ( touch > tsdata - > max_fingers )
touch = tsdata - > max_fingers ;
2014-07-28 20:58:54 +04:00
report - > num_touches = touch ;
bufptr = & rdbuf [ 2 ] ;
for ( i = 0 ; i < touch ; i + + ) {
report - > touches [ i ] . x = ( bufptr [ 1 ] < < 8 ) | bufptr [ 0 ] ;
report - > touches [ i ] . y = ( bufptr [ 3 ] < < 8 ) | bufptr [ 2 ] ;
2014-07-28 21:01:07 +04:00
if ( chip - > has_hw_ids ) {
report - > touches [ i ] . id = bufptr [ 4 ] ;
bufptr = bufptr + 5 ;
} else {
bufptr = bufptr + 4 ;
}
2011-12-31 03:16:21 +04:00
}
2014-07-28 20:58:54 +04:00
}
static void pixcir_ts_report ( struct pixcir_i2c_ts_data * ts ,
struct pixcir_report_data * report )
{
struct input_mt_pos pos [ PIXCIR_MAX_SLOTS ] ;
int slots [ PIXCIR_MAX_SLOTS ] ;
struct pixcir_touch * touch ;
int n , i , slot ;
struct device * dev = & ts - > client - > dev ;
2015-07-07 00:29:29 +03:00
const struct pixcir_i2c_chip_data * chip = ts - > chip ;
2014-07-28 20:58:54 +04:00
n = report - > num_touches ;
if ( n > PIXCIR_MAX_SLOTS )
n = PIXCIR_MAX_SLOTS ;
2011-12-31 03:16:21 +04:00
2015-07-07 00:29:29 +03:00
if ( ! ts - > chip - > has_hw_ids ) {
2014-07-28 21:01:07 +04:00
for ( i = 0 ; i < n ; i + + ) {
touch = & report - > touches [ i ] ;
pos [ i ] . x = touch - > x ;
pos [ i ] . y = touch - > y ;
}
2014-07-28 20:58:54 +04:00
2015-02-01 22:25:14 +03:00
input_mt_assign_slots ( ts - > input , slots , pos , n , 0 ) ;
2014-07-28 21:01:07 +04:00
}
2014-07-28 20:58:54 +04:00
for ( i = 0 ; i < n ; i + + ) {
touch = & report - > touches [ i ] ;
2014-07-28 21:01:07 +04:00
if ( chip - > has_hw_ids ) {
slot = input_mt_get_slot_by_key ( ts - > input , touch - > id ) ;
if ( slot < 0 ) {
dev_dbg ( dev , " no free slot for id 0x%x \n " ,
touch - > id ) ;
continue ;
}
} else {
slot = slots [ i ] ;
}
2014-07-28 20:58:54 +04:00
input_mt_slot ( ts - > input , slot ) ;
input_mt_report_slot_state ( ts - > input ,
MT_TOOL_FINGER , true ) ;
input_event ( ts - > input , EV_ABS , ABS_MT_POSITION_X , touch - > x ) ;
input_event ( ts - > input , EV_ABS , ABS_MT_POSITION_Y , touch - > y ) ;
dev_dbg ( dev , " %d: slot %d, x %d, y %d \n " ,
i , slot , touch - > x , touch - > y ) ;
}
input_mt_sync_frame ( ts - > input ) ;
input_sync ( ts - > input ) ;
2011-12-31 03:16:21 +04:00
}
static irqreturn_t pixcir_ts_isr ( int irq , void * dev_id )
{
struct pixcir_i2c_ts_data * tsdata = dev_id ;
2014-07-28 20:58:54 +04:00
struct pixcir_report_data report ;
2011-12-31 03:16:21 +04:00
2014-05-19 09:44:35 +04:00
while ( tsdata - > running ) {
2014-07-28 20:58:54 +04:00
/* parse packet */
pixcir_ts_parse ( tsdata , & report ) ;
/* report it */
pixcir_ts_report ( tsdata , & report ) ;
2015-07-06 23:27:00 +03:00
if ( gpiod_get_value_cansleep ( tsdata - > gpio_attb ) ) {
2014-07-28 20:58:54 +04:00
if ( report . num_touches ) {
/*
* Last report with no finger up ?
* Do it now then .
*/
input_mt_sync_frame ( tsdata - > input ) ;
input_sync ( tsdata - > input ) ;
}
2011-12-31 03:16:21 +04:00
break ;
2014-07-28 20:58:54 +04:00
}
2011-12-31 03:16:21 +04:00
msleep ( 20 ) ;
}
return IRQ_HANDLED ;
}
2015-07-06 23:27:43 +03:00
static void pixcir_reset ( struct pixcir_i2c_ts_data * tsdata )
{
if ( ! IS_ERR_OR_NULL ( tsdata - > gpio_reset ) ) {
gpiod_set_value_cansleep ( tsdata - > gpio_reset , 1 ) ;
ndelay ( 100 ) ; /* datasheet section 1.2.3 says 80ns min. */
gpiod_set_value_cansleep ( tsdata - > gpio_reset , 0 ) ;
/* wait for controller ready. 100ms guess. */
msleep ( 100 ) ;
}
}
2014-05-19 09:44:35 +04:00
static int pixcir_set_power_mode ( struct pixcir_i2c_ts_data * ts ,
enum pixcir_power_mode mode )
{
struct device * dev = & ts - > client - > dev ;
int ret ;
ret = i2c_smbus_read_byte_data ( ts - > client , PIXCIR_REG_POWER_MODE ) ;
if ( ret < 0 ) {
dev_err ( dev , " %s: can't read reg 0x%x : %d \n " ,
__func__ , PIXCIR_REG_POWER_MODE , ret ) ;
return ret ;
}
ret & = ~ PIXCIR_POWER_MODE_MASK ;
ret | = mode ;
/* Always AUTO_IDLE */
ret | = PIXCIR_POWER_ALLOW_IDLE ;
ret = i2c_smbus_write_byte_data ( ts - > client , PIXCIR_REG_POWER_MODE , ret ) ;
if ( ret < 0 ) {
dev_err ( dev , " %s: can't write reg 0x%x : %d \n " ,
__func__ , PIXCIR_REG_POWER_MODE , ret ) ;
return ret ;
}
return 0 ;
}
/*
* Set the interrupt mode for the device i . e . ATTB line behaviour
*
* @ polarity : 1 for active high , 0 for active low .
*/
static int pixcir_set_int_mode ( struct pixcir_i2c_ts_data * ts ,
enum pixcir_int_mode mode , bool polarity )
{
struct device * dev = & ts - > client - > dev ;
int ret ;
ret = i2c_smbus_read_byte_data ( ts - > client , PIXCIR_REG_INT_MODE ) ;
if ( ret < 0 ) {
dev_err ( dev , " %s: can't read reg 0x%x : %d \n " ,
__func__ , PIXCIR_REG_INT_MODE , ret ) ;
return ret ;
}
ret & = ~ PIXCIR_INT_MODE_MASK ;
ret | = mode ;
if ( polarity )
ret | = PIXCIR_INT_POL_HIGH ;
else
ret & = ~ PIXCIR_INT_POL_HIGH ;
ret = i2c_smbus_write_byte_data ( ts - > client , PIXCIR_REG_INT_MODE , ret ) ;
if ( ret < 0 ) {
dev_err ( dev , " %s: can't write reg 0x%x : %d \n " ,
__func__ , PIXCIR_REG_INT_MODE , ret ) ;
return ret ;
}
return 0 ;
}
/*
* Enable / disable interrupt generation
*/
static int pixcir_int_enable ( struct pixcir_i2c_ts_data * ts , bool enable )
{
struct device * dev = & ts - > client - > dev ;
int ret ;
ret = i2c_smbus_read_byte_data ( ts - > client , PIXCIR_REG_INT_MODE ) ;
if ( ret < 0 ) {
dev_err ( dev , " %s: can't read reg 0x%x : %d \n " ,
__func__ , PIXCIR_REG_INT_MODE , ret ) ;
return ret ;
}
if ( enable )
ret | = PIXCIR_INT_ENABLE ;
else
ret & = ~ PIXCIR_INT_ENABLE ;
ret = i2c_smbus_write_byte_data ( ts - > client , PIXCIR_REG_INT_MODE , ret ) ;
if ( ret < 0 ) {
dev_err ( dev , " %s: can't write reg 0x%x : %d \n " ,
__func__ , PIXCIR_REG_INT_MODE , ret ) ;
return ret ;
}
return 0 ;
}
static int pixcir_start ( struct pixcir_i2c_ts_data * ts )
{
struct device * dev = & ts - > client - > dev ;
int error ;
/* LEVEL_TOUCH interrupt with active low polarity */
error = pixcir_set_int_mode ( ts , PIXCIR_INT_LEVEL_TOUCH , 0 ) ;
if ( error ) {
dev_err ( dev , " Failed to set interrupt mode: %d \n " , error ) ;
return error ;
}
ts - > running = true ;
mb ( ) ; /* Update status before IRQ can fire */
/* enable interrupt generation */
error = pixcir_int_enable ( ts , true ) ;
if ( error ) {
dev_err ( dev , " Failed to enable interrupt generation: %d \n " ,
error ) ;
return error ;
}
return 0 ;
}
static int pixcir_stop ( struct pixcir_i2c_ts_data * ts )
{
int error ;
/* Disable interrupt generation */
error = pixcir_int_enable ( ts , false ) ;
if ( error ) {
dev_err ( & ts - > client - > dev ,
" Failed to disable interrupt generation: %d \n " ,
error ) ;
return error ;
}
/* Exit ISR if running, no more report parsing */
ts - > running = false ;
mb ( ) ; /* update status before we synchronize irq */
/* Wait till running ISR is complete */
synchronize_irq ( ts - > client - > irq ) ;
return 0 ;
}
static int pixcir_input_open ( struct input_dev * dev )
{
struct pixcir_i2c_ts_data * ts = input_get_drvdata ( dev ) ;
return pixcir_start ( ts ) ;
}
static void pixcir_input_close ( struct input_dev * dev )
{
struct pixcir_i2c_ts_data * ts = input_get_drvdata ( dev ) ;
pixcir_stop ( ts ) ;
}
2014-11-02 10:04:14 +03:00
static int __maybe_unused pixcir_i2c_ts_suspend ( struct device * dev )
2011-12-31 03:16:21 +04:00
{
struct i2c_client * client = to_i2c_client ( dev ) ;
2014-05-19 09:49:20 +04:00
struct pixcir_i2c_ts_data * ts = i2c_get_clientdata ( client ) ;
struct input_dev * input = ts - > input ;
int ret = 0 ;
mutex_lock ( & input - > mutex ) ;
if ( device_may_wakeup ( & client - > dev ) ) {
if ( ! input - > users ) {
ret = pixcir_start ( ts ) ;
if ( ret ) {
dev_err ( dev , " Failed to start \n " ) ;
goto unlock ;
}
}
2011-12-31 03:16:21 +04:00
enable_irq_wake ( client - > irq ) ;
2014-05-19 09:49:20 +04:00
} else if ( input - > users ) {
ret = pixcir_stop ( ts ) ;
}
2011-12-31 03:16:21 +04:00
2014-05-19 09:49:20 +04:00
unlock :
mutex_unlock ( & input - > mutex ) ;
return ret ;
2011-12-31 03:16:21 +04:00
}
2014-11-02 10:04:14 +03:00
static int __maybe_unused pixcir_i2c_ts_resume ( struct device * dev )
2011-12-31 03:16:21 +04:00
{
struct i2c_client * client = to_i2c_client ( dev ) ;
2014-05-19 09:49:20 +04:00
struct pixcir_i2c_ts_data * ts = i2c_get_clientdata ( client ) ;
struct input_dev * input = ts - > input ;
int ret = 0 ;
mutex_lock ( & input - > mutex ) ;
2011-12-31 03:16:21 +04:00
2014-05-19 09:49:20 +04:00
if ( device_may_wakeup ( & client - > dev ) ) {
2011-12-31 03:16:21 +04:00
disable_irq_wake ( client - > irq ) ;
2014-05-19 09:49:20 +04:00
if ( ! input - > users ) {
ret = pixcir_stop ( ts ) ;
if ( ret ) {
dev_err ( dev , " Failed to stop \n " ) ;
goto unlock ;
}
}
} else if ( input - > users ) {
ret = pixcir_start ( ts ) ;
}
unlock :
mutex_unlock ( & input - > mutex ) ;
return ret ;
2011-12-31 03:16:21 +04:00
}
static SIMPLE_DEV_PM_OPS ( pixcir_dev_pm_ops ,
pixcir_i2c_ts_suspend , pixcir_i2c_ts_resume ) ;
2014-07-28 21:05:39 +04:00
# ifdef CONFIG_OF
static const struct of_device_id pixcir_of_match [ ] ;
2015-07-07 00:29:29 +03:00
static int pixcir_parse_dt ( struct device * dev ,
struct pixcir_i2c_ts_data * tsdata )
2014-07-28 21:05:39 +04:00
{
const struct of_device_id * match ;
match = of_match_device ( of_match_ptr ( pixcir_of_match ) , dev ) ;
if ( ! match )
2015-07-07 00:29:29 +03:00
return - EINVAL ;
2014-07-28 21:05:39 +04:00
2015-07-07 00:29:29 +03:00
tsdata - > chip = ( const struct pixcir_i2c_chip_data * ) match - > data ;
if ( ! tsdata - > chip )
return - EINVAL ;
2014-07-28 21:05:39 +04:00
2015-07-07 00:29:29 +03:00
return 0 ;
2014-07-28 21:05:39 +04:00
}
# else
2015-07-07 00:29:29 +03:00
static int pixcir_parse_dt ( struct device * dev ,
struct pixcir_i2c_ts_data * tsdata )
2014-07-28 21:05:39 +04:00
{
2015-07-07 00:29:29 +03:00
return - EINVAL ;
2014-07-28 21:05:39 +04:00
}
# endif
2012-11-24 09:38:25 +04:00
static int pixcir_i2c_ts_probe ( struct i2c_client * client ,
2015-07-07 00:29:29 +03:00
const struct i2c_device_id * id )
2011-12-31 03:16:21 +04:00
{
2013-12-06 07:21:10 +04:00
const struct pixcir_ts_platform_data * pdata =
dev_get_platdata ( & client - > dev ) ;
2014-05-19 09:43:42 +04:00
struct device * dev = & client - > dev ;
2011-12-31 03:16:21 +04:00
struct pixcir_i2c_ts_data * tsdata ;
struct input_dev * input ;
int error ;
2015-07-07 00:29:29 +03:00
tsdata = devm_kzalloc ( dev , sizeof ( * tsdata ) , GFP_KERNEL ) ;
if ( ! tsdata )
return - ENOMEM ;
2014-07-28 21:05:39 +04:00
2015-07-07 00:29:29 +03:00
if ( pdata ) {
tsdata - > chip = & pdata - > chip ;
} else if ( dev - > of_node ) {
error = pixcir_parse_dt ( dev , tsdata ) ;
if ( error )
return error ;
} else {
2011-12-31 03:16:21 +04:00
dev_err ( & client - > dev , " platform data not defined \n " ) ;
return - EINVAL ;
}
2015-07-07 00:29:29 +03:00
if ( ! tsdata - > chip - > max_fingers ) {
dev_err ( dev , " Invalid max_fingers in chip data \n " ) ;
2014-07-28 21:01:07 +04:00
return - EINVAL ;
}
2014-05-19 09:43:42 +04:00
input = devm_input_allocate_device ( dev ) ;
if ( ! input ) {
dev_err ( dev , " Failed to allocate input device \n " ) ;
return - ENOMEM ;
2011-12-31 03:16:21 +04:00
}
tsdata - > client = client ;
tsdata - > input = input ;
input - > name = client - > name ;
input - > id . bustype = BUS_I2C ;
2014-05-19 09:44:35 +04:00
input - > open = pixcir_input_open ;
input - > close = pixcir_input_close ;
2011-12-31 03:16:21 +04:00
input - > dev . parent = & client - > dev ;
2015-07-07 00:29:29 +03:00
if ( pdata ) {
input_set_abs_params ( input , ABS_MT_POSITION_X , 0 , pdata - > x_max , 0 , 0 ) ;
input_set_abs_params ( input , ABS_MT_POSITION_Y , 0 , pdata - > y_max , 0 , 0 ) ;
} else {
input_set_capability ( input , EV_ABS , ABS_MT_POSITION_X ) ;
input_set_capability ( input , EV_ABS , ABS_MT_POSITION_Y ) ;
touchscreen_parse_properties ( input , true ) ;
if ( ! input_abs_get_max ( input , ABS_MT_POSITION_X ) | |
! input_abs_get_max ( input , ABS_MT_POSITION_Y ) ) {
dev_err ( dev , " Touchscreen size is not specified \n " ) ;
return - EINVAL ;
}
}
2011-12-31 03:16:21 +04:00
2015-07-07 00:29:29 +03:00
tsdata - > max_fingers = tsdata - > chip - > max_fingers ;
2014-07-28 21:01:07 +04:00
if ( tsdata - > max_fingers > PIXCIR_MAX_SLOTS ) {
tsdata - > max_fingers = PIXCIR_MAX_SLOTS ;
dev_info ( dev , " Limiting maximum fingers to %d \n " ,
tsdata - > max_fingers ) ;
}
error = input_mt_init_slots ( input , tsdata - > max_fingers ,
2014-07-28 20:58:54 +04:00
INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED ) ;
if ( error ) {
dev_err ( dev , " Error initializing Multi-Touch slots \n " ) ;
return error ;
}
2011-12-31 03:16:21 +04:00
input_set_drvdata ( input , tsdata ) ;
2015-07-06 21:56:21 +03:00
tsdata - > gpio_attb = devm_gpiod_get ( dev , " attb " , GPIOD_IN ) ;
if ( IS_ERR ( tsdata - > gpio_attb ) ) {
error = PTR_ERR ( tsdata - > gpio_attb ) ;
dev_err ( dev , " Failed to request ATTB gpio: %d \n " , error ) ;
2014-05-19 09:46:43 +04:00
return error ;
}
2015-07-06 23:27:43 +03:00
tsdata - > gpio_reset = devm_gpiod_get_optional ( dev , " reset " ,
GPIOD_OUT_LOW ) ;
if ( IS_ERR ( tsdata - > gpio_reset ) ) {
error = PTR_ERR ( tsdata - > gpio_reset ) ;
dev_err ( dev , " Failed to request RESET gpio: %d \n " , error ) ;
return error ;
}
2014-05-19 09:43:42 +04:00
error = devm_request_threaded_irq ( dev , client - > irq , NULL , pixcir_ts_isr ,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT ,
client - > name , tsdata ) ;
2011-12-31 03:16:21 +04:00
if ( error ) {
2014-05-19 09:43:42 +04:00
dev_err ( dev , " failed to request irq %d \n " , client - > irq ) ;
return error ;
2011-12-31 03:16:21 +04:00
}
2015-07-06 23:27:43 +03:00
pixcir_reset ( tsdata ) ;
2014-05-19 09:44:35 +04:00
/* Always be in IDLE mode to save power, device supports auto wake */
error = pixcir_set_power_mode ( tsdata , PIXCIR_POWER_IDLE ) ;
if ( error ) {
dev_err ( dev , " Failed to set IDLE mode \n " ) ;
return error ;
}
/* Stop device till opened */
error = pixcir_stop ( tsdata ) ;
if ( error )
return error ;
2011-12-31 03:16:21 +04:00
error = input_register_device ( input ) ;
if ( error )
2014-05-19 09:43:42 +04:00
return error ;
2011-12-31 03:16:21 +04:00
2014-05-19 09:49:20 +04:00
i2c_set_clientdata ( client , tsdata ) ;
2011-12-31 03:16:21 +04:00
device_init_wakeup ( & client - > dev , 1 ) ;
return 0 ;
}
2012-11-24 09:50:47 +04:00
static int pixcir_i2c_ts_remove ( struct i2c_client * client )
2011-12-31 03:16:21 +04:00
{
device_init_wakeup ( & client - > dev , 0 ) ;
return 0 ;
}
static const struct i2c_device_id pixcir_i2c_ts_id [ ] = {
{ " pixcir_ts " , 0 } ,
2014-07-28 21:05:39 +04:00
{ " pixcir_tangoc " , 0 } ,
2011-12-31 03:16:21 +04:00
{ }
} ;
MODULE_DEVICE_TABLE ( i2c , pixcir_i2c_ts_id ) ;
2014-07-28 21:05:39 +04:00
# ifdef CONFIG_OF
static const struct pixcir_i2c_chip_data pixcir_ts_data = {
. max_fingers = 2 ,
/* no hw id support */
} ;
static const struct pixcir_i2c_chip_data pixcir_tangoc_data = {
. max_fingers = 5 ,
. has_hw_ids = true ,
} ;
static const struct of_device_id pixcir_of_match [ ] = {
{ . compatible = " pixcir,pixcir_ts " , . data = & pixcir_ts_data } ,
{ . compatible = " pixcir,pixcir_tangoc " , . data = & pixcir_tangoc_data } ,
{ }
} ;
MODULE_DEVICE_TABLE ( of , pixcir_of_match ) ;
# endif
2011-12-31 03:16:21 +04:00
static struct i2c_driver pixcir_i2c_ts_driver = {
. driver = {
. name = " pixcir_ts " ,
. pm = & pixcir_dev_pm_ops ,
2014-07-28 21:05:39 +04:00
. of_match_table = of_match_ptr ( pixcir_of_match ) ,
2011-12-31 03:16:21 +04:00
} ,
. probe = pixcir_i2c_ts_probe ,
2012-11-24 09:27:39 +04:00
. remove = pixcir_i2c_ts_remove ,
2011-12-31 03:16:21 +04:00
. id_table = pixcir_i2c_ts_id ,
} ;
2012-03-17 10:05:44 +04:00
module_i2c_driver ( pixcir_i2c_ts_driver ) ;
2011-12-31 03:16:21 +04:00
MODULE_AUTHOR ( " Jianchun Bian <jcbian@pixcir.com.cn>, Dequan Meng <dqmeng@pixcir.com.cn> " ) ;
MODULE_DESCRIPTION ( " Pixcir I2C Touchscreen Driver " ) ;
MODULE_LICENSE ( " GPL " ) ;