2018-11-12 22:30:06 +03:00
// SPDX-License-Identifier: GPL-2.0
2010-12-16 10:39:25 +03:00
/*
* ST1232 Touchscreen Controller Driver
*
* Copyright ( C ) 2010 Renesas Solutions Corp .
* Tony SIM < chinyeow . sim . xt @ renesas . com >
*
* Using code from :
* - android . git . kernel . org : projects / kernel / common . git : synaptics_i2c_rmi . c
* Copyright ( C ) 2007 Google , Inc .
*/
# include <linux/delay.h>
2019-02-09 19:53:13 +03:00
# include <linux/gpio/consumer.h>
2010-12-16 10:39:25 +03:00
# include <linux/i2c.h>
# include <linux/input.h>
# include <linux/interrupt.h>
# include <linux/module.h>
2013-10-06 11:56:40 +04:00
# include <linux/of.h>
2011-12-23 04:24:25 +04:00
# include <linux/pm_qos.h>
2010-12-16 10:39:25 +03:00
# include <linux/slab.h>
# include <linux/types.h>
2019-02-11 11:30:26 +03:00
# include <linux/input/touchscreen.h>
2010-12-16 10:39:25 +03:00
# define ST1232_TS_NAME "st1232-ts"
2019-01-28 21:38:10 +03:00
# define ST1633_TS_NAME "st1633-ts"
2010-12-16 10:39:25 +03:00
struct st1232_ts_finger {
u16 x ;
u16 y ;
u8 t ;
bool is_valid ;
} ;
2019-01-28 21:38:10 +03:00
struct st_chip_info {
bool have_z ;
u16 max_x ;
u16 max_y ;
u16 max_area ;
u16 max_fingers ;
u8 start_reg ;
} ;
2010-12-16 10:39:25 +03:00
struct st1232_ts_data {
struct i2c_client * client ;
struct input_dev * input_dev ;
2019-02-11 11:30:26 +03:00
struct touchscreen_properties prop ;
2011-12-23 04:24:25 +04:00
struct dev_pm_qos_request low_latency_req ;
2019-02-09 19:53:13 +03:00
struct gpio_desc * reset_gpio ;
2019-01-28 21:38:10 +03:00
const struct st_chip_info * chip_info ;
int read_buf_len ;
u8 * read_buf ;
2019-10-22 06:49:19 +03:00
struct st1232_ts_finger fingers [ ] ;
2010-12-16 10:39:25 +03:00
} ;
static int st1232_ts_read_data ( struct st1232_ts_data * ts )
{
2019-10-22 06:49:19 +03:00
struct st1232_ts_finger * finger = ts - > fingers ;
2010-12-16 10:39:25 +03:00
struct i2c_client * client = ts - > client ;
2019-01-28 21:38:10 +03:00
u8 start_reg = ts - > chip_info - > start_reg ;
2019-10-21 20:11:23 +03:00
struct i2c_msg msg [ ] = {
{
. addr = client - > addr ,
. len = sizeof ( start_reg ) ,
. buf = & start_reg ,
} ,
{
. addr = client - > addr ,
. flags = I2C_M_RD ,
. len = ts - > read_buf_len ,
. buf = ts - > read_buf ,
}
} ;
int ret ;
int i ;
u8 * buf ;
2010-12-16 10:39:25 +03:00
2019-10-21 20:11:23 +03:00
ret = i2c_transfer ( client - > adapter , msg , ARRAY_SIZE ( msg ) ) ;
if ( ret ! = ARRAY_SIZE ( msg ) )
return ret < 0 ? ret : - EIO ;
2010-12-16 10:39:25 +03:00
2019-10-21 20:11:23 +03:00
for ( i = 0 ; i < ts - > chip_info - > max_fingers ; i + + ) {
buf = & ts - > read_buf [ i * 4 ] ;
finger [ i ] . is_valid = buf [ 0 ] > > 7 ;
2019-01-28 21:38:10 +03:00
if ( finger [ i ] . is_valid ) {
2019-10-21 20:11:23 +03:00
finger [ i ] . x = ( ( buf [ 0 ] & 0x70 ) < < 4 ) | buf [ 1 ] ;
finger [ i ] . y = ( ( buf [ 0 ] & 0x07 ) < < 8 ) | buf [ 2 ] ;
2010-12-16 10:39:25 +03:00
2019-01-28 21:38:10 +03:00
/* st1232 includes a z-axis / touch strength */
if ( ts - > chip_info - > have_z )
2019-10-21 20:11:23 +03:00
finger [ i ] . t = ts - > read_buf [ i + 6 ] ;
2019-01-28 21:38:10 +03:00
}
2010-12-16 10:39:25 +03:00
}
return 0 ;
}
static irqreturn_t st1232_ts_irq_handler ( int irq , void * dev_id )
{
struct st1232_ts_data * ts = dev_id ;
2019-10-22 06:49:19 +03:00
struct st1232_ts_finger * finger = ts - > fingers ;
2010-12-16 10:39:25 +03:00
struct input_dev * input_dev = ts - > input_dev ;
int count = 0 ;
int i , ret ;
ret = st1232_ts_read_data ( ts ) ;
if ( ret < 0 )
goto end ;
/* multi touch protocol */
2019-01-28 21:38:10 +03:00
for ( i = 0 ; i < ts - > chip_info - > max_fingers ; i + + ) {
2010-12-16 10:39:25 +03:00
if ( ! finger [ i ] . is_valid )
continue ;
2019-01-28 21:38:10 +03:00
if ( ts - > chip_info - > have_z )
input_report_abs ( input_dev , ABS_MT_TOUCH_MAJOR ,
finger [ i ] . t ) ;
2019-02-11 11:30:26 +03:00
touchscreen_report_pos ( input_dev , & ts - > prop ,
finger [ i ] . x , finger [ i ] . y , true ) ;
2010-12-16 10:39:25 +03:00
input_mt_sync ( input_dev ) ;
count + + ;
}
/* SYN_MT_REPORT only if no contact */
2011-12-23 04:24:25 +04:00
if ( ! count ) {
2010-12-16 10:39:25 +03:00
input_mt_sync ( input_dev ) ;
2011-12-23 04:24:25 +04:00
if ( ts - > low_latency_req . dev ) {
dev_pm_qos_remove_request ( & ts - > low_latency_req ) ;
ts - > low_latency_req . dev = NULL ;
}
} else if ( ! ts - > low_latency_req . dev ) {
/* First contact, request 100 us latency. */
dev_pm_qos_add_ancestor_request ( & ts - > client - > dev ,
2014-02-11 03:36:00 +04:00
& ts - > low_latency_req ,
DEV_PM_QOS_RESUME_LATENCY , 100 ) ;
2011-12-23 04:24:25 +04:00
}
2010-12-16 10:39:25 +03:00
/* SYN_REPORT */
input_sync ( input_dev ) ;
end :
return IRQ_HANDLED ;
}
2013-04-15 20:31:00 +04:00
static void st1232_ts_power ( struct st1232_ts_data * ts , bool poweron )
{
2019-02-09 19:53:13 +03:00
if ( ts - > reset_gpio )
gpiod_set_value_cansleep ( ts - > reset_gpio , ! poweron ) ;
2013-04-15 20:31:00 +04:00
}
2019-10-21 21:02:33 +03:00
static void st1232_ts_power_off ( void * data )
{
st1232_ts_power ( data , false ) ;
}
2019-01-28 21:38:10 +03:00
static const struct st_chip_info st1232_chip_info = {
. have_z = true ,
. max_x = 0x31f , /* 800 - 1 */
. max_y = 0x1df , /* 480 -1 */
. max_area = 0xff ,
. max_fingers = 2 ,
. start_reg = 0x12 ,
} ;
static const struct st_chip_info st1633_chip_info = {
. have_z = false ,
. max_x = 0x13f , /* 320 - 1 */
. max_y = 0x1df , /* 480 -1 */
. max_area = 0x00 ,
. max_fingers = 5 ,
. start_reg = 0x12 ,
} ;
2012-11-24 09:38:25 +04:00
static int st1232_ts_probe ( struct i2c_client * client ,
2017-10-31 19:47:28 +03:00
const struct i2c_device_id * id )
2010-12-16 10:39:25 +03:00
{
2019-01-28 21:38:10 +03:00
const struct st_chip_info * match ;
2010-12-16 10:39:25 +03:00
struct st1232_ts_data * ts ;
struct input_dev * input_dev ;
int error ;
2019-01-28 21:38:10 +03:00
match = device_get_match_data ( & client - > dev ) ;
if ( ! match & & id )
match = ( const void * ) id - > driver_data ;
if ( ! match ) {
dev_err ( & client - > dev , " unknown device model \n " ) ;
return - ENODEV ;
}
2010-12-16 10:39:25 +03:00
if ( ! i2c_check_functionality ( client - > adapter , I2C_FUNC_I2C ) ) {
dev_err ( & client - > dev , " need I2C_FUNC_I2C \n " ) ;
return - EIO ;
}
if ( ! client - > irq ) {
dev_err ( & client - > dev , " no IRQ? \n " ) ;
return - EINVAL ;
}
2019-10-22 06:49:19 +03:00
ts = devm_kzalloc ( & client - > dev ,
struct_size ( ts , fingers , match - > max_fingers ) ,
GFP_KERNEL ) ;
2013-04-15 20:23:00 +04:00
if ( ! ts )
return - ENOMEM ;
2010-12-16 10:39:25 +03:00
2019-01-28 21:38:10 +03:00
ts - > chip_info = match ;
/* allocate a buffer according to the number of registers to read */
ts - > read_buf_len = ts - > chip_info - > max_fingers * 4 ;
ts - > read_buf = devm_kzalloc ( & client - > dev , ts - > read_buf_len , GFP_KERNEL ) ;
if ( ! ts - > read_buf )
return - ENOMEM ;
2013-04-15 20:23:00 +04:00
input_dev = devm_input_allocate_device ( & client - > dev ) ;
if ( ! input_dev )
return - ENOMEM ;
2010-12-16 10:39:25 +03:00
ts - > client = client ;
ts - > input_dev = input_dev ;
2019-02-09 19:53:13 +03:00
ts - > reset_gpio = devm_gpiod_get_optional ( & client - > dev , NULL ,
GPIOD_OUT_HIGH ) ;
if ( IS_ERR ( ts - > reset_gpio ) ) {
error = PTR_ERR ( ts - > reset_gpio ) ;
dev_err ( & client - > dev , " Unable to request GPIO pin: %d. \n " ,
error ) ;
return error ;
2013-04-15 20:31:00 +04:00
}
st1232_ts_power ( ts , true ) ;
2019-10-21 21:02:33 +03:00
error = devm_add_action_or_reset ( & client - > dev , st1232_ts_power_off , ts ) ;
if ( error ) {
dev_err ( & client - > dev ,
" Failed to install power off action: %d \n " , error ) ;
return error ;
}
2010-12-16 10:39:25 +03:00
input_dev - > name = " st1232-touchscreen " ;
input_dev - > id . bustype = BUS_I2C ;
2018-10-05 21:44:45 +03:00
__set_bit ( INPUT_PROP_DIRECT , input_dev - > propbit ) ;
2010-12-16 10:39:25 +03:00
__set_bit ( EV_SYN , input_dev - > evbit ) ;
__set_bit ( EV_KEY , input_dev - > evbit ) ;
__set_bit ( EV_ABS , input_dev - > evbit ) ;
2019-01-28 21:38:10 +03:00
if ( ts - > chip_info - > have_z )
input_set_abs_params ( input_dev , ABS_MT_TOUCH_MAJOR , 0 ,
ts - > chip_info - > max_area , 0 , 0 ) ;
input_set_abs_params ( input_dev , ABS_MT_POSITION_X ,
0 , ts - > chip_info - > max_x , 0 , 0 ) ;
input_set_abs_params ( input_dev , ABS_MT_POSITION_Y ,
0 , ts - > chip_info - > max_y , 0 , 0 ) ;
2010-12-16 10:39:25 +03:00
2019-02-11 11:30:26 +03:00
touchscreen_parse_properties ( input_dev , true , & ts - > prop ) ;
2013-04-15 20:23:00 +04:00
error = devm_request_threaded_irq ( & client - > dev , client - > irq ,
NULL , st1232_ts_irq_handler ,
IRQF_ONESHOT ,
client - > name , ts ) ;
2010-12-16 10:39:25 +03:00
if ( error ) {
dev_err ( & client - > dev , " Failed to register interrupt \n " ) ;
2013-04-15 20:23:00 +04:00
return error ;
2010-12-16 10:39:25 +03:00
}
error = input_register_device ( ts - > input_dev ) ;
if ( error ) {
dev_err ( & client - > dev , " Unable to register %s input device \n " ,
input_dev - > name ) ;
2013-04-15 20:23:00 +04:00
return error ;
2010-12-16 10:39:25 +03:00
}
i2c_set_clientdata ( client , ts ) ;
return 0 ;
}
2014-11-02 10:04:14 +03:00
static int __maybe_unused st1232_ts_suspend ( struct device * dev )
2010-12-16 10:39:25 +03:00
{
struct i2c_client * client = to_i2c_client ( dev ) ;
2013-04-15 20:31:00 +04:00
struct st1232_ts_data * ts = i2c_get_clientdata ( client ) ;
2010-12-16 10:39:25 +03:00
2019-10-21 21:00:21 +03:00
disable_irq ( client - > irq ) ;
if ( ! device_may_wakeup ( & client - > dev ) )
2013-04-15 20:31:00 +04:00
st1232_ts_power ( ts , false ) ;
2010-12-16 10:39:25 +03:00
return 0 ;
}
2014-11-02 10:04:14 +03:00
static int __maybe_unused st1232_ts_resume ( struct device * dev )
2010-12-16 10:39:25 +03:00
{
struct i2c_client * client = to_i2c_client ( dev ) ;
2013-04-15 20:31:00 +04:00
struct st1232_ts_data * ts = i2c_get_clientdata ( client ) ;
2010-12-16 10:39:25 +03:00
2019-10-21 21:00:21 +03:00
if ( ! device_may_wakeup ( & client - > dev ) )
2013-04-15 20:31:00 +04:00
st1232_ts_power ( ts , true ) ;
2019-10-21 21:00:21 +03:00
enable_irq ( client - > irq ) ;
2010-12-16 10:39:25 +03:00
return 0 ;
}
2012-04-03 22:30:28 +04:00
static SIMPLE_DEV_PM_OPS ( st1232_ts_pm_ops ,
st1232_ts_suspend , st1232_ts_resume ) ;
2010-12-16 10:39:25 +03:00
static const struct i2c_device_id st1232_ts_id [ ] = {
2019-01-28 21:38:10 +03:00
{ ST1232_TS_NAME , ( unsigned long ) & st1232_chip_info } ,
{ ST1633_TS_NAME , ( unsigned long ) & st1633_chip_info } ,
2010-12-16 10:39:25 +03:00
{ }
} ;
MODULE_DEVICE_TABLE ( i2c , st1232_ts_id ) ;
2012-11-24 09:31:00 +04:00
static const struct of_device_id st1232_ts_dt_ids [ ] = {
2019-01-28 21:38:10 +03:00
{ . compatible = " sitronix,st1232 " , . data = & st1232_chip_info } ,
{ . compatible = " sitronix,st1633 " , . data = & st1633_chip_info } ,
2012-04-03 22:30:28 +04:00
{ }
} ;
MODULE_DEVICE_TABLE ( of , st1232_ts_dt_ids ) ;
2010-12-16 10:39:25 +03:00
static struct i2c_driver st1232_ts_driver = {
. probe = st1232_ts_probe ,
. id_table = st1232_ts_id ,
. driver = {
. name = ST1232_TS_NAME ,
2017-10-31 19:47:28 +03:00
. of_match_table = st1232_ts_dt_ids ,
2010-12-16 10:39:25 +03:00
. pm = & st1232_ts_pm_ops ,
} ,
} ;
2012-03-17 10:05:41 +04:00
module_i2c_driver ( st1232_ts_driver ) ;
2010-12-16 10:39:25 +03:00
MODULE_AUTHOR ( " Tony SIM <chinyeow.sim.xt@renesas.com> " ) ;
2019-01-28 22:04:08 +03:00
MODULE_AUTHOR ( " Martin Kepplinger <martin.kepplinger@ginzinger.com> " ) ;
2010-12-16 10:39:25 +03:00
MODULE_DESCRIPTION ( " SITRONIX ST1232 Touchscreen Controller Driver " ) ;
2018-11-12 22:30:06 +03:00
MODULE_LICENSE ( " GPL v2 " ) ;