2019-05-29 07:17:56 -07:00
// SPDX-License-Identifier: GPL-2.0-only
2011-12-30 15:16:21 -08:00
/*
* Driver for Pixcir I2C touchscreen controllers .
*
* Copyright ( C ) 2010 - 2011 Pixcir , Inc .
*/
2019-10-08 10:14:41 -07:00
# include <asm/unaligned.h>
2011-12-30 15:16:21 -08:00
# include <linux/delay.h>
2019-10-08 10:14:41 -07:00
# include <linux/gpio/consumer.h>
2011-12-30 15:16:21 -08:00
# include <linux/i2c.h>
# include <linux/input.h>
2014-07-28 09:58:54 -07:00
# include <linux/input/mt.h>
2015-07-06 14:29:29 -07:00
# include <linux/input/touchscreen.h>
2019-10-08 10:14:41 -07:00
# include <linux/interrupt.h>
# include <linux/module.h>
2023-07-17 09:03:47 -07:00
# include <linux/of.h>
2019-10-08 10:14:41 -07:00
# include <linux/slab.h>
2011-12-30 15:16:21 -08:00
2014-07-28 10:01:07 -07:00
# define PIXCIR_MAX_SLOTS 5 /* Max fingers supported by driver */
2014-07-28 09:58:54 -07:00
2019-10-08 10:13:55 -07:00
/*
* Register map
*/
# define PIXCIR_REG_POWER_MODE 51
# define PIXCIR_REG_INT_MODE 52
/*
* Power modes :
* active : max scan speed
* idle : lower scan speed with automatic transition to active on touch
* halt : datasheet says sleep but this is more like halt as the chip
* clocks are cut and it can only be brought out of this mode
* using the RESET pin .
*/
enum pixcir_power_mode {
PIXCIR_POWER_ACTIVE ,
PIXCIR_POWER_IDLE ,
PIXCIR_POWER_HALT ,
} ;
# define PIXCIR_POWER_MODE_MASK 0x03
# define PIXCIR_POWER_ALLOW_IDLE (1UL << 2)
/*
* Interrupt modes :
* periodical : interrupt is asserted periodicaly
* diff coordinates : interrupt is asserted when coordinates change
* level on touch : interrupt level asserted during touch
* pulse on touch : interrupt pulse asserted during touch
*
*/
enum pixcir_int_mode {
PIXCIR_INT_PERIODICAL ,
PIXCIR_INT_DIFF_COORD ,
PIXCIR_INT_LEVEL_TOUCH ,
PIXCIR_INT_PULSE_TOUCH ,
} ;
# define PIXCIR_INT_MODE_MASK 0x03
# define PIXCIR_INT_ENABLE (1UL << 3)
# define PIXCIR_INT_POL_HIGH (1UL << 2)
/**
2019-10-08 11:38:04 -07:00
* struct pixcir_i2c_chip_data - chip related data
2019-10-08 10:13:55 -07:00
* @ max_fingers : Max number of fingers reported simultaneously by h / w
* @ has_hw_ids : Hardware supports finger tracking IDs
*
*/
struct pixcir_i2c_chip_data {
u8 max_fingers ;
bool has_hw_ids ;
} ;
2011-12-30 15:16:21 -08:00
struct pixcir_i2c_ts_data {
struct i2c_client * client ;
struct input_dev * input ;
2015-07-06 11:56:21 -07:00
struct gpio_desc * gpio_attb ;
2015-07-06 13:27:43 -07:00
struct gpio_desc * gpio_reset ;
2015-12-01 13:25:05 -08:00
struct gpio_desc * gpio_enable ;
struct gpio_desc * gpio_wake ;
2015-07-06 14:29:29 -07:00
const struct pixcir_i2c_chip_data * chip ;
2016-07-15 14:31:31 -07:00
struct touchscreen_properties prop ;
2015-07-06 14:29:29 -07:00
bool running ;
2011-12-30 15:16:21 -08:00
} ;
2014-07-28 09:58:54 -07:00
struct pixcir_report_data {
int num_touches ;
2016-07-15 14:31:31 -07:00
struct input_mt_pos pos [ PIXCIR_MAX_SLOTS ] ;
int ids [ PIXCIR_MAX_SLOTS ] ;
2014-07-28 09:58:54 -07:00
} ;
static void pixcir_ts_parse ( struct pixcir_i2c_ts_data * tsdata ,
struct pixcir_report_data * report )
2011-12-30 15:16:21 -08:00
{
2014-07-28 10:01:07 -07:00
u8 rdbuf [ 2 + PIXCIR_MAX_SLOTS * 5 ] ;
u8 wrbuf [ 1 ] = { 0 } ;
2014-07-28 09:58:54 -07:00
u8 * bufptr ;
2011-12-30 15:16:21 -08:00
u8 touch ;
2014-07-28 09:58:54 -07:00
int ret , i ;
2014-07-28 10:01:07 -07:00
int readsize ;
2015-07-06 14:29:29 -07:00
const struct pixcir_i2c_chip_data * chip = tsdata - > chip ;
2014-07-28 09:58:54 -07:00
memset ( report , 0 , sizeof ( struct pixcir_report_data ) ) ;
2011-12-30 15:16:21 -08:00
2014-07-28 10:01:07 -07:00
i = chip - > has_hw_ids ? 1 : 0 ;
2019-10-08 11:38:04 -07:00
readsize = 2 + tsdata - > chip - > max_fingers * ( 4 + i ) ;
2014-07-28 10:01:07 -07:00
if ( readsize > sizeof ( rdbuf ) )
readsize = sizeof ( rdbuf ) ;
2011-12-30 15:16:21 -08: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 10:01:07 -07:00
ret = i2c_master_recv ( tsdata - > client , rdbuf , readsize ) ;
2015-06-16 15:03:53 -07:00
if ( ret ! = readsize ) {
2011-12-30 15:16:21 -08:00
dev_err ( & tsdata - > client - > dev ,
" %s: i2c_master_recv failed(), ret=%d \n " ,
__func__ , ret ) ;
return ;
}
2014-07-28 09:58:54 -07:00
touch = rdbuf [ 0 ] & 0x7 ;
2019-10-08 11:38:04 -07:00
if ( touch > tsdata - > chip - > max_fingers )
touch = tsdata - > chip - > max_fingers ;
2014-07-28 09:58:54 -07:00
report - > num_touches = touch ;
bufptr = & rdbuf [ 2 ] ;
for ( i = 0 ; i < touch ; i + + ) {
2016-07-15 14:31:31 -07:00
touchscreen_set_mt_pos ( & report - > pos [ i ] , & tsdata - > prop ,
get_unaligned_le16 ( bufptr ) ,
get_unaligned_le16 ( bufptr + 2 ) ) ;
2014-07-28 10:01:07 -07:00
if ( chip - > has_hw_ids ) {
2016-07-15 14:31:31 -07:00
report - > ids [ i ] = bufptr [ 4 ] ;
2014-07-28 10:01:07 -07:00
bufptr = bufptr + 5 ;
} else {
bufptr = bufptr + 4 ;
}
2011-12-30 15:16:21 -08:00
}
2014-07-28 09:58:54 -07:00
}
static void pixcir_ts_report ( struct pixcir_i2c_ts_data * ts ,
struct pixcir_report_data * report )
{
int slots [ PIXCIR_MAX_SLOTS ] ;
int n , i , slot ;
struct device * dev = & ts - > client - > dev ;
2015-07-06 14:29:29 -07:00
const struct pixcir_i2c_chip_data * chip = ts - > chip ;
2014-07-28 09:58:54 -07:00
n = report - > num_touches ;
if ( n > PIXCIR_MAX_SLOTS )
n = PIXCIR_MAX_SLOTS ;
2011-12-30 15:16:21 -08:00
2016-07-15 14:31:31 -07:00
if ( ! ts - > chip - > has_hw_ids )
input_mt_assign_slots ( ts - > input , slots , report - > pos , n , 0 ) ;
2014-07-28 09:58:54 -07:00
for ( i = 0 ; i < n ; i + + ) {
2014-07-28 10:01:07 -07:00
if ( chip - > has_hw_ids ) {
2016-07-15 14:31:31 -07:00
slot = input_mt_get_slot_by_key ( ts - > input ,
report - > ids [ i ] ) ;
2014-07-28 10:01:07 -07:00
if ( slot < 0 ) {
dev_dbg ( dev , " no free slot for id 0x%x \n " ,
2016-07-15 14:31:31 -07:00
report - > ids [ i ] ) ;
2014-07-28 10:01:07 -07:00
continue ;
}
} else {
slot = slots [ i ] ;
}
2014-07-28 09:58:54 -07:00
input_mt_slot ( ts - > input , slot ) ;
2016-07-15 14:31:31 -07:00
input_mt_report_slot_state ( ts - > input , MT_TOOL_FINGER , true ) ;
2014-07-28 09:58:54 -07:00
2016-07-15 14:31:31 -07:00
input_report_abs ( ts - > input , ABS_MT_POSITION_X ,
report - > pos [ i ] . x ) ;
input_report_abs ( ts - > input , ABS_MT_POSITION_Y ,
report - > pos [ i ] . y ) ;
2014-07-28 09:58:54 -07:00
dev_dbg ( dev , " %d: slot %d, x %d, y %d \n " ,
2016-07-15 14:31:31 -07:00
i , slot , report - > pos [ i ] . x , report - > pos [ i ] . y ) ;
2014-07-28 09:58:54 -07:00
}
input_mt_sync_frame ( ts - > input ) ;
input_sync ( ts - > input ) ;
2011-12-30 15:16:21 -08:00
}
static irqreturn_t pixcir_ts_isr ( int irq , void * dev_id )
{
struct pixcir_i2c_ts_data * tsdata = dev_id ;
2014-07-28 09:58:54 -07:00
struct pixcir_report_data report ;
2011-12-30 15:16:21 -08:00
2014-05-18 22:44:35 -07:00
while ( tsdata - > running ) {
2014-07-28 09:58:54 -07:00
/* parse packet */
pixcir_ts_parse ( tsdata , & report ) ;
/* report it */
pixcir_ts_report ( tsdata , & report ) ;
2015-07-06 13:27:00 -07:00
if ( gpiod_get_value_cansleep ( tsdata - > gpio_attb ) ) {
2014-07-28 09:58:54 -07: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-30 15:16:21 -08:00
break ;
2014-07-28 09:58:54 -07:00
}
2011-12-30 15:16:21 -08:00
msleep ( 20 ) ;
}
return IRQ_HANDLED ;
}
2015-07-06 13:27:43 -07: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-18 22:44:35 -07: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 ;
2015-12-01 13:25:05 -08:00
if ( mode = = PIXCIR_POWER_ACTIVE | | mode = = PIXCIR_POWER_IDLE ) {
if ( ts - > gpio_wake )
gpiod_set_value_cansleep ( ts - > gpio_wake , 1 ) ;
}
2014-05-18 22:44:35 -07:00
ret = i2c_smbus_read_byte_data ( ts - > client , PIXCIR_REG_POWER_MODE ) ;
if ( ret < 0 ) {
2019-10-08 10:15:01 -07:00
dev_err ( dev , " %s: can't read reg %d : %d \n " ,
2014-05-18 22:44:35 -07:00
__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 ) {
2019-10-08 10:15:01 -07:00
dev_err ( dev , " %s: can't write reg %d : %d \n " ,
2014-05-18 22:44:35 -07:00
__func__ , PIXCIR_REG_POWER_MODE , ret ) ;
return ret ;
}
2015-12-01 13:25:05 -08:00
if ( mode = = PIXCIR_POWER_HALT ) {
if ( ts - > gpio_wake )
gpiod_set_value_cansleep ( ts - > gpio_wake , 0 ) ;
}
2014-05-18 22:44:35 -07:00
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 ) {
2019-10-08 10:15:01 -07:00
dev_err ( dev , " %s: can't read reg %d : %d \n " ,
2014-05-18 22:44:35 -07:00
__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 ) {
2019-10-08 10:15:01 -07:00
dev_err ( dev , " %s: can't write reg %d : %d \n " ,
2014-05-18 22:44:35 -07:00
__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 ) {
2019-10-08 10:15:01 -07:00
dev_err ( dev , " %s: can't read reg %d : %d \n " ,
2014-05-18 22:44:35 -07:00
__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 ) {
2019-10-08 10:15:01 -07:00
dev_err ( dev , " %s: can't write reg %d : %d \n " ,
2014-05-18 22:44:35 -07:00
__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 ;
2015-12-01 13:25:05 -08:00
if ( ts - > gpio_enable ) {
gpiod_set_value_cansleep ( ts - > gpio_enable , 1 ) ;
msleep ( 100 ) ;
}
2014-05-18 22:44:35 -07:00
/* 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 ) ;
2015-12-01 13:25:05 -08:00
if ( ts - > gpio_enable )
gpiod_set_value_cansleep ( ts - > gpio_enable , 0 ) ;
2014-05-18 22:44:35 -07:00
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 ) ;
}
2023-01-02 18:18:30 +00:00
static int pixcir_i2c_ts_suspend ( struct device * dev )
2011-12-30 15:16:21 -08:00
{
struct i2c_client * client = to_i2c_client ( dev ) ;
2014-05-18 22:49:20 -07: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 ) ) {
2020-10-04 21:16:07 -07:00
if ( ! input_device_enabled ( input ) ) {
2014-05-18 22:49:20 -07:00
ret = pixcir_start ( ts ) ;
if ( ret ) {
dev_err ( dev , " Failed to start \n " ) ;
goto unlock ;
}
}
2020-10-04 21:16:07 -07:00
} else if ( input_device_enabled ( input ) ) {
2014-05-18 22:49:20 -07:00
ret = pixcir_stop ( ts ) ;
}
2011-12-30 15:16:21 -08:00
2014-05-18 22:49:20 -07:00
unlock :
mutex_unlock ( & input - > mutex ) ;
return ret ;
2011-12-30 15:16:21 -08:00
}
2023-01-02 18:18:30 +00:00
static int pixcir_i2c_ts_resume ( struct device * dev )
2011-12-30 15:16:21 -08:00
{
struct i2c_client * client = to_i2c_client ( dev ) ;
2014-05-18 22:49:20 -07: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-30 15:16:21 -08:00
2014-05-18 22:49:20 -07:00
if ( device_may_wakeup ( & client - > dev ) ) {
2020-10-04 21:16:07 -07:00
if ( ! input_device_enabled ( input ) ) {
2014-05-18 22:49:20 -07:00
ret = pixcir_stop ( ts ) ;
if ( ret ) {
dev_err ( dev , " Failed to stop \n " ) ;
goto unlock ;
}
}
2020-10-04 21:16:07 -07:00
} else if ( input_device_enabled ( input ) ) {
2014-05-18 22:49:20 -07:00
ret = pixcir_start ( ts ) ;
}
unlock :
mutex_unlock ( & input - > mutex ) ;
return ret ;
2011-12-30 15:16:21 -08:00
}
2023-01-02 18:18:30 +00:00
static DEFINE_SIMPLE_DEV_PM_OPS ( pixcir_dev_pm_ops ,
pixcir_i2c_ts_suspend , pixcir_i2c_ts_resume ) ;
2011-12-30 15:16:21 -08:00
2022-11-18 23:39:47 +01:00
static int pixcir_i2c_ts_probe ( struct i2c_client * client )
2011-12-30 15:16:21 -08:00
{
2022-11-18 23:39:47 +01:00
const struct i2c_device_id * id = i2c_client_get_device_id ( client ) ;
2014-05-18 22:43:42 -07:00
struct device * dev = & client - > dev ;
2011-12-30 15:16:21 -08:00
struct pixcir_i2c_ts_data * tsdata ;
struct input_dev * input ;
int error ;
2015-07-06 14:29:29 -07:00
tsdata = devm_kzalloc ( dev , sizeof ( * tsdata ) , GFP_KERNEL ) ;
if ( ! tsdata )
return - ENOMEM ;
2014-07-28 10:05:39 -07:00
2019-10-08 11:38:04 -07:00
tsdata - > chip = device_get_match_data ( dev ) ;
if ( ! tsdata - > chip & & id )
tsdata - > chip = ( const void * ) id - > driver_data ;
if ( ! tsdata - > chip ) {
dev_err ( dev , " can't locate chip data \n " ) ;
2014-07-28 10:01:07 -07:00
return - EINVAL ;
}
2014-05-18 22:43:42 -07:00
input = devm_input_allocate_device ( dev ) ;
if ( ! input ) {
dev_err ( dev , " Failed to allocate input device \n " ) ;
return - ENOMEM ;
2011-12-30 15:16:21 -08:00
}
tsdata - > client = client ;
tsdata - > input = input ;
input - > name = client - > name ;
input - > id . bustype = BUS_I2C ;
2014-05-18 22:44:35 -07:00
input - > open = pixcir_input_open ;
input - > close = pixcir_input_close ;
2011-12-30 15:16:21 -08:00
2019-10-08 11:38:04 -07:00
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 , & tsdata - > prop ) ;
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 ;
2014-07-28 10:01:07 -07:00
}
2019-10-08 11:38:04 -07:00
error = input_mt_init_slots ( input , tsdata - > chip - > max_fingers ,
2014-07-28 09:58:54 -07:00
INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED ) ;
if ( error ) {
dev_err ( dev , " Error initializing Multi-Touch slots \n " ) ;
return error ;
}
2011-12-30 15:16:21 -08:00
input_set_drvdata ( input , tsdata ) ;
2015-07-06 11:56:21 -07:00
tsdata - > gpio_attb = devm_gpiod_get ( dev , " attb " , GPIOD_IN ) ;
2023-06-25 18:28:08 +02:00
if ( IS_ERR ( tsdata - > gpio_attb ) )
return dev_err_probe ( dev , PTR_ERR ( tsdata - > gpio_attb ) ,
" Failed to request ATTB gpio \n " ) ;
2014-05-18 22:46:43 -07:00
2015-07-06 13:27:43 -07:00
tsdata - > gpio_reset = devm_gpiod_get_optional ( dev , " reset " ,
GPIOD_OUT_LOW ) ;
2023-06-25 18:28:08 +02:00
if ( IS_ERR ( tsdata - > gpio_reset ) )
return dev_err_probe ( dev , PTR_ERR ( tsdata - > gpio_reset ) ,
" Failed to request RESET gpio \n " ) ;
2015-07-06 13:27:43 -07:00
2015-12-01 13:25:05 -08:00
tsdata - > gpio_wake = devm_gpiod_get_optional ( dev , " wake " ,
GPIOD_OUT_HIGH ) ;
2023-06-25 18:28:08 +02:00
if ( IS_ERR ( tsdata - > gpio_wake ) )
return dev_err_probe ( dev , PTR_ERR ( tsdata - > gpio_wake ) ,
" Failed to get wake gpio \n " ) ;
2015-12-01 13:25:05 -08:00
tsdata - > gpio_enable = devm_gpiod_get_optional ( dev , " enable " ,
GPIOD_OUT_HIGH ) ;
2023-06-25 18:28:08 +02:00
if ( IS_ERR ( tsdata - > gpio_enable ) )
return dev_err_probe ( dev , PTR_ERR ( tsdata - > gpio_enable ) ,
" Failed to get enable gpio \n " ) ;
2015-12-01 13:25:05 -08:00
if ( tsdata - > gpio_enable )
msleep ( 100 ) ;
2014-05-18 22:43:42 -07:00
error = devm_request_threaded_irq ( dev , client - > irq , NULL , pixcir_ts_isr ,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT ,
client - > name , tsdata ) ;
2011-12-30 15:16:21 -08:00
if ( error ) {
2014-05-18 22:43:42 -07:00
dev_err ( dev , " failed to request irq %d \n " , client - > irq ) ;
return error ;
2011-12-30 15:16:21 -08:00
}
2015-07-06 13:27:43 -07:00
pixcir_reset ( tsdata ) ;
2014-05-18 22:44:35 -07: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-30 15:16:21 -08:00
error = input_register_device ( input ) ;
if ( error )
2014-05-18 22:43:42 -07:00
return error ;
2011-12-30 15:16:21 -08:00
2014-05-18 22:49:20 -07:00
i2c_set_clientdata ( client , tsdata ) ;
2011-12-30 15:16:21 -08:00
return 0 ;
}
2014-07-28 10:05:39 -07:00
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 ,
} ;
2019-10-08 11:38:04 -07:00
static const struct i2c_device_id pixcir_i2c_ts_id [ ] = {
{ " pixcir_ts " , ( unsigned long ) & pixcir_ts_data } ,
{ " pixcir_tangoc " , ( unsigned long ) & pixcir_tangoc_data } ,
{ }
} ;
MODULE_DEVICE_TABLE ( i2c , pixcir_i2c_ts_id ) ;
# ifdef CONFIG_OF
2014-07-28 10:05:39 -07:00
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-30 15:16:21 -08:00
static struct i2c_driver pixcir_i2c_ts_driver = {
. driver = {
. name = " pixcir_ts " ,
2023-01-02 18:18:30 +00:00
. pm = pm_sleep_ptr ( & pixcir_dev_pm_ops ) ,
2014-07-28 10:05:39 -07:00
. of_match_table = of_match_ptr ( pixcir_of_match ) ,
2011-12-30 15:16:21 -08:00
} ,
2023-05-17 09:55:42 -07:00
. probe = pixcir_i2c_ts_probe ,
2011-12-30 15:16:21 -08:00
. id_table = pixcir_i2c_ts_id ,
} ;
2012-03-16 23:05:44 -07:00
module_i2c_driver ( pixcir_i2c_ts_driver ) ;
2011-12-30 15:16:21 -08:00
MODULE_AUTHOR ( " Jianchun Bian <jcbian@pixcir.com.cn>, Dequan Meng <dqmeng@pixcir.com.cn> " ) ;
MODULE_DESCRIPTION ( " Pixcir I2C Touchscreen Driver " ) ;
MODULE_LICENSE ( " GPL " ) ;