2016-03-11 02:56:58 +03:00
/*
* Copyright ( c ) 2012 - 2016 Synaptics Incorporated
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation .
*/
# include <linux/kernel.h>
# include <linux/rmi.h>
# include <linux/input.h>
# include <linux/slab.h>
# include "rmi_driver.h"
# define RMI_F30_QUERY_SIZE 2
/* Defs for Query 0 */
# define RMI_F30_EXTENDED_PATTERNS 0x01
2017-02-08 23:02:07 +03:00
# define RMI_F30_HAS_MAPPABLE_BUTTONS BIT(1)
# define RMI_F30_HAS_LED BIT(2)
# define RMI_F30_HAS_GPIO BIT(3)
# define RMI_F30_HAS_HAPTIC BIT(4)
# define RMI_F30_HAS_GPIO_DRV_CTL BIT(5)
# define RMI_F30_HAS_MECH_MOUSE_BTNS BIT(6)
2016-03-11 02:56:58 +03:00
/* Defs for Query 1 */
# define RMI_F30_GPIO_LED_COUNT 0x1F
/* Defs for Control Registers */
# define RMI_F30_CTRL_1_GPIO_DEBOUNCE 0x01
2017-02-08 23:02:07 +03:00
# define RMI_F30_CTRL_1_HALT BIT(4)
# define RMI_F30_CTRL_1_HALTED BIT(5)
2016-03-11 02:56:58 +03:00
# define RMI_F30_CTRL_10_NUM_MECH_MOUSE_BTNS 0x03
# define RMI_F30_CTRL_MAX_REGS 32
2017-02-08 23:02:07 +03:00
# define RMI_F30_CTRL_MAX_BYTES DIV_ROUND_UP(RMI_F30_CTRL_MAX_REGS, 8)
2016-03-11 02:56:58 +03:00
# define RMI_F30_CTRL_MAX_REG_BLOCKS 11
# define RMI_F30_CTRL_REGS_MAX_SIZE (RMI_F30_CTRL_MAX_BYTES \
+ 1 \
+ RMI_F30_CTRL_MAX_BYTES \
+ RMI_F30_CTRL_MAX_BYTES \
+ RMI_F30_CTRL_MAX_BYTES \
+ 6 \
+ RMI_F30_CTRL_MAX_REGS \
+ RMI_F30_CTRL_MAX_REGS \
+ RMI_F30_CTRL_MAX_BYTES \
+ 1 \
+ 1 )
2017-02-08 11:26:45 +03:00
# define TRACKSTICK_RANGE_START 3
# define TRACKSTICK_RANGE_END 6
2017-02-08 23:02:07 +03:00
struct rmi_f30_ctrl_data {
int address ;
int length ;
u8 * regs ;
} ;
2016-03-11 02:56:58 +03:00
struct f30_data {
/* Query Data */
bool has_extended_pattern ;
bool has_mappable_buttons ;
bool has_led ;
bool has_gpio ;
bool has_haptic ;
bool has_gpio_driver_control ;
bool has_mech_mouse_btns ;
u8 gpioled_count ;
u8 register_count ;
/* Control Register Data */
struct rmi_f30_ctrl_data ctrl [ RMI_F30_CTRL_MAX_REG_BLOCKS ] ;
u8 ctrl_regs [ RMI_F30_CTRL_REGS_MAX_SIZE ] ;
u32 ctrl_regs_size ;
u8 data_regs [ RMI_F30_CTRL_MAX_BYTES ] ;
u16 * gpioled_key_map ;
struct input_dev * input ;
2017-02-08 11:26:45 +03:00
struct rmi_function * f03 ;
bool trackstick_buttons ;
2016-03-11 02:56:58 +03:00
} ;
static int rmi_f30_read_control_parameters ( struct rmi_function * fn ,
struct f30_data * f30 )
{
2017-02-08 23:02:07 +03:00
int error ;
2016-03-11 02:56:58 +03:00
2017-02-08 23:02:07 +03:00
error = rmi_read_block ( fn - > rmi_dev , fn - > fd . control_base_addr ,
f30 - > ctrl_regs , f30 - > ctrl_regs_size ) ;
2016-03-11 02:56:58 +03:00
if ( error ) {
2017-02-08 23:02:07 +03:00
dev_err ( & fn - > dev ,
" %s: Could not read control registers at 0x%x: %d \n " ,
2016-03-11 02:56:58 +03:00
__func__ , fn - > fd . control_base_addr , error ) ;
return error ;
}
return 0 ;
}
2017-02-08 23:02:07 +03:00
static void rmi_f30_report_button ( struct rmi_function * fn ,
struct f30_data * f30 , unsigned int button )
{
unsigned int reg_num = button > > 3 ;
unsigned int bit_num = button & 0x07 ;
2017-02-08 11:26:45 +03:00
u16 key_code = f30 - > gpioled_key_map [ button ] ;
2017-02-08 23:02:07 +03:00
bool key_down = ! ( f30 - > data_regs [ reg_num ] & BIT ( bit_num ) ) ;
2017-02-08 11:26:45 +03:00
if ( f30 - > trackstick_buttons & &
button > = TRACKSTICK_RANGE_START & &
button < = TRACKSTICK_RANGE_END ) {
rmi_f03_overwrite_button ( f30 - > f03 , key_code , key_down ) ;
} else {
rmi_dbg ( RMI_DEBUG_FN , & fn - > dev ,
" %s: call input report key (0x%04x) value (0x%02x) " ,
__func__ , key_code , key_down ) ;
2017-02-08 23:02:07 +03:00
2017-02-08 11:26:45 +03:00
input_report_key ( f30 - > input , key_code , key_down ) ;
}
2017-02-08 23:02:07 +03:00
}
2016-03-11 02:56:58 +03:00
static int rmi_f30_attention ( struct rmi_function * fn , unsigned long * irq_bits )
{
struct f30_data * f30 = dev_get_drvdata ( & fn - > dev ) ;
2017-02-08 23:02:07 +03:00
struct rmi_driver_data * drvdata = dev_get_drvdata ( & fn - > rmi_dev - > dev ) ;
int error ;
2016-03-11 02:56:58 +03:00
int i ;
/* Read the gpi led data. */
2016-12-03 04:49:10 +03:00
if ( drvdata - > attn_data . data ) {
if ( drvdata - > attn_data . size < f30 - > register_count ) {
2017-02-08 23:02:07 +03:00
dev_warn ( & fn - > dev ,
" F30 interrupted, but data is missing \n " ) ;
2016-11-09 03:46:20 +03:00
return 0 ;
}
2016-12-03 04:49:10 +03:00
memcpy ( f30 - > data_regs , drvdata - > attn_data . data ,
2016-03-11 02:56:58 +03:00
f30 - > register_count ) ;
2016-12-03 04:49:10 +03:00
drvdata - > attn_data . data + = f30 - > register_count ;
drvdata - > attn_data . size - = f30 - > register_count ;
2016-03-11 02:56:58 +03:00
} else {
2017-02-08 23:02:07 +03:00
error = rmi_read_block ( fn - > rmi_dev , fn - > fd . data_base_addr ,
f30 - > data_regs , f30 - > register_count ) ;
if ( error ) {
dev_err ( & fn - > dev ,
" %s: Failed to read F30 data registers: %d \n " ,
__func__ , error ) ;
return error ;
2016-03-11 02:56:58 +03:00
}
}
2017-02-08 11:26:45 +03:00
if ( f30 - > has_gpio ) {
2017-02-08 23:02:07 +03:00
for ( i = 0 ; i < f30 - > gpioled_count ; i + + )
if ( f30 - > gpioled_key_map [ i ] ! = KEY_RESERVED )
rmi_f30_report_button ( fn , f30 , i ) ;
2017-02-08 11:26:45 +03:00
if ( f30 - > trackstick_buttons )
rmi_f03_commit_buttons ( f30 - > f03 ) ;
}
2016-03-11 02:56:58 +03:00
return 0 ;
}
static int rmi_f30_config ( struct rmi_function * fn )
{
struct f30_data * f30 = dev_get_drvdata ( & fn - > dev ) ;
struct rmi_driver * drv = fn - > rmi_dev - > driver ;
const struct rmi_device_platform_data * pdata =
rmi_get_platform_data ( fn - > rmi_dev ) ;
int error ;
2017-03-10 21:10:54 +03:00
/* can happen if f30_data.disable is set */
if ( ! f30 )
return 0 ;
2017-02-08 11:26:45 +03:00
if ( pdata - > f30_data . trackstick_buttons ) {
/* Try [re-]establish link to F03. */
f30 - > f03 = rmi_find_function ( fn - > rmi_dev , 0x03 ) ;
f30 - > trackstick_buttons = f30 - > f03 ! = NULL ;
}
2016-12-01 04:01:50 +03:00
if ( pdata - > f30_data . disable ) {
2016-03-11 02:56:58 +03:00
drv - > clear_irq_bits ( fn - > rmi_dev , fn - > irq_mask ) ;
} else {
/* Write Control Register values back to device */
error = rmi_write_block ( fn - > rmi_dev , fn - > fd . control_base_addr ,
f30 - > ctrl_regs , f30 - > ctrl_regs_size ) ;
if ( error ) {
2017-02-08 23:02:07 +03:00
dev_err ( & fn - > dev ,
" %s: Could not write control registers at 0x%x: %d \n " ,
2016-03-11 02:56:58 +03:00
__func__ , fn - > fd . control_base_addr , error ) ;
return error ;
}
drv - > set_irq_bits ( fn - > rmi_dev , fn - > irq_mask ) ;
}
2017-02-08 23:02:07 +03:00
2016-03-11 02:56:58 +03:00
return 0 ;
}
2017-02-08 23:02:07 +03:00
static void rmi_f30_set_ctrl_data ( struct rmi_f30_ctrl_data * ctrl ,
int * ctrl_addr , int len , u8 * * reg )
2016-03-11 02:56:58 +03:00
{
ctrl - > address = * ctrl_addr ;
ctrl - > length = len ;
ctrl - > regs = * reg ;
* ctrl_addr + = len ;
* reg + = len ;
}
2017-02-08 23:02:07 +03:00
static bool rmi_f30_is_valid_button ( int button , struct rmi_f30_ctrl_data * ctrl )
2016-03-11 02:56:58 +03:00
{
int byte_position = button > > 3 ;
int bit_position = button & 0x07 ;
/*
* ctrl2 - > dir = = 0 - > input mode
* ctrl3 - > data = = 1 - > actual button
*/
return ! ( ctrl [ 2 ] . regs [ byte_position ] & BIT ( bit_position ) ) & &
( ctrl [ 3 ] . regs [ byte_position ] & BIT ( bit_position ) ) ;
}
2017-02-08 23:02:07 +03:00
static int rmi_f30_map_gpios ( struct rmi_function * fn ,
struct f30_data * f30 )
2016-03-11 02:56:58 +03:00
{
2017-02-08 23:02:07 +03:00
const struct rmi_device_platform_data * pdata =
rmi_get_platform_data ( fn - > rmi_dev ) ;
struct input_dev * input = f30 - > input ;
unsigned int button = BTN_LEFT ;
2017-02-08 11:26:45 +03:00
unsigned int trackstick_button = BTN_LEFT ;
bool button_mapped = false ;
2016-03-11 02:56:58 +03:00
int i ;
2017-02-08 23:02:07 +03:00
f30 - > gpioled_key_map = devm_kcalloc ( & fn - > dev ,
f30 - > gpioled_count ,
sizeof ( f30 - > gpioled_key_map [ 0 ] ) ,
GFP_KERNEL ) ;
if ( ! f30 - > gpioled_key_map ) {
dev_err ( & fn - > dev , " Failed to allocate gpioled map memory. \n " ) ;
2016-03-11 02:56:58 +03:00
return - ENOMEM ;
2017-02-08 23:02:07 +03:00
}
2016-03-11 02:56:58 +03:00
2017-02-08 23:02:07 +03:00
for ( i = 0 ; i < f30 - > gpioled_count ; i + + ) {
2017-02-08 11:26:45 +03:00
if ( ! rmi_f30_is_valid_button ( i , f30 - > ctrl ) )
continue ;
if ( pdata - > f30_data . trackstick_buttons & &
i > = TRACKSTICK_RANGE_START & & i < TRACKSTICK_RANGE_END ) {
f30 - > gpioled_key_map [ i ] = trackstick_button + + ;
} else if ( ! pdata - > f30_data . buttonpad | | ! button_mapped ) {
2017-02-08 23:02:07 +03:00
f30 - > gpioled_key_map [ i ] = button ;
input_set_capability ( input , EV_KEY , button + + ) ;
2017-02-08 11:26:45 +03:00
button_mapped = true ;
2017-02-08 23:02:07 +03:00
}
}
input - > keycode = f30 - > gpioled_key_map ;
input - > keycodesize = sizeof ( f30 - > gpioled_key_map [ 0 ] ) ;
input - > keycodemax = f30 - > gpioled_count ;
2017-02-08 11:26:45 +03:00
/*
* Buttonpad could be also inferred from f30 - > has_mech_mouse_btns ,
2017-03-01 11:57:00 +03:00
* but I am not sure , so use only the pdata info and the number of
* mapped buttons .
2017-02-08 11:26:45 +03:00
*/
2017-03-01 11:57:00 +03:00
if ( pdata - > f30_data . buttonpad | | ( button - BTN_LEFT = = 1 ) )
2017-02-08 11:26:45 +03:00
__set_bit ( INPUT_PROP_BUTTONPAD , input - > propbit ) ;
2017-02-08 23:02:07 +03:00
return 0 ;
}
2016-03-11 02:56:58 +03:00
2017-02-08 23:02:07 +03:00
static int rmi_f30_initialize ( struct rmi_function * fn , struct f30_data * f30 )
{
u8 * ctrl_reg = f30 - > ctrl_regs ;
int control_address = fn - > fd . control_base_addr ;
u8 buf [ RMI_F30_QUERY_SIZE ] ;
int error ;
2016-03-11 02:56:58 +03:00
2017-02-08 23:02:07 +03:00
error = rmi_read_block ( fn - > rmi_dev , fn - > fd . query_base_addr ,
buf , RMI_F30_QUERY_SIZE ) ;
if ( error ) {
dev_err ( & fn - > dev , " Failed to read query register \n " ) ;
return error ;
2016-03-11 02:56:58 +03:00
}
f30 - > has_extended_pattern = buf [ 0 ] & RMI_F30_EXTENDED_PATTERNS ;
f30 - > has_mappable_buttons = buf [ 0 ] & RMI_F30_HAS_MAPPABLE_BUTTONS ;
f30 - > has_led = buf [ 0 ] & RMI_F30_HAS_LED ;
f30 - > has_gpio = buf [ 0 ] & RMI_F30_HAS_GPIO ;
f30 - > has_haptic = buf [ 0 ] & RMI_F30_HAS_HAPTIC ;
f30 - > has_gpio_driver_control = buf [ 0 ] & RMI_F30_HAS_GPIO_DRV_CTL ;
f30 - > has_mech_mouse_btns = buf [ 0 ] & RMI_F30_HAS_MECH_MOUSE_BTNS ;
f30 - > gpioled_count = buf [ 1 ] & RMI_F30_GPIO_LED_COUNT ;
2017-02-08 23:02:07 +03:00
f30 - > register_count = DIV_ROUND_UP ( f30 - > gpioled_count , 8 ) ;
2016-03-11 02:56:58 +03:00
if ( f30 - > has_gpio & & f30 - > has_led )
rmi_f30_set_ctrl_data ( & f30 - > ctrl [ 0 ] , & control_address ,
2017-02-08 23:02:07 +03:00
f30 - > register_count , & ctrl_reg ) ;
2016-03-11 02:56:58 +03:00
2017-02-08 23:02:07 +03:00
rmi_f30_set_ctrl_data ( & f30 - > ctrl [ 1 ] , & control_address ,
sizeof ( u8 ) , & ctrl_reg ) ;
2016-03-11 02:56:58 +03:00
if ( f30 - > has_gpio ) {
rmi_f30_set_ctrl_data ( & f30 - > ctrl [ 2 ] , & control_address ,
2017-02-08 23:02:07 +03:00
f30 - > register_count , & ctrl_reg ) ;
2016-03-11 02:56:58 +03:00
rmi_f30_set_ctrl_data ( & f30 - > ctrl [ 3 ] , & control_address ,
2017-02-08 23:02:07 +03:00
f30 - > register_count , & ctrl_reg ) ;
2016-03-11 02:56:58 +03:00
}
if ( f30 - > has_led ) {
rmi_f30_set_ctrl_data ( & f30 - > ctrl [ 4 ] , & control_address ,
2017-02-08 23:02:07 +03:00
f30 - > register_count , & ctrl_reg ) ;
2016-03-11 02:56:58 +03:00
rmi_f30_set_ctrl_data ( & f30 - > ctrl [ 5 ] , & control_address ,
2017-02-08 23:02:07 +03:00
f30 - > has_extended_pattern ? 6 : 2 ,
& ctrl_reg ) ;
2016-03-11 02:56:58 +03:00
}
if ( f30 - > has_led | | f30 - > has_gpio_driver_control ) {
/* control 6 uses a byte per gpio/led */
rmi_f30_set_ctrl_data ( & f30 - > ctrl [ 6 ] , & control_address ,
2017-02-08 23:02:07 +03:00
f30 - > gpioled_count , & ctrl_reg ) ;
2016-03-11 02:56:58 +03:00
}
if ( f30 - > has_mappable_buttons ) {
/* control 7 uses a byte per gpio/led */
rmi_f30_set_ctrl_data ( & f30 - > ctrl [ 7 ] , & control_address ,
2017-02-08 23:02:07 +03:00
f30 - > gpioled_count , & ctrl_reg ) ;
2016-03-11 02:56:58 +03:00
}
if ( f30 - > has_haptic ) {
rmi_f30_set_ctrl_data ( & f30 - > ctrl [ 8 ] , & control_address ,
2017-02-08 23:02:07 +03:00
f30 - > register_count , & ctrl_reg ) ;
2016-03-11 02:56:58 +03:00
rmi_f30_set_ctrl_data ( & f30 - > ctrl [ 9 ] , & control_address ,
2017-02-08 23:02:07 +03:00
sizeof ( u8 ) , & ctrl_reg ) ;
2016-03-11 02:56:58 +03:00
}
if ( f30 - > has_mech_mouse_btns )
rmi_f30_set_ctrl_data ( & f30 - > ctrl [ 10 ] , & control_address ,
2017-02-08 23:02:07 +03:00
sizeof ( u8 ) , & ctrl_reg ) ;
2016-03-11 02:56:58 +03:00
2017-02-08 23:02:07 +03:00
f30 - > ctrl_regs_size = ctrl_reg -
f30 - > ctrl_regs ? : RMI_F30_CTRL_REGS_MAX_SIZE ;
2016-03-11 02:56:58 +03:00
2017-02-08 23:02:07 +03:00
error = rmi_f30_read_control_parameters ( fn , f30 ) ;
if ( error ) {
2016-03-11 02:56:58 +03:00
dev_err ( & fn - > dev ,
2017-02-08 23:02:07 +03:00
" Failed to initialize F30 control params: %d \n " ,
error ) ;
return error ;
2016-03-11 02:56:58 +03:00
}
2016-12-01 04:01:50 +03:00
if ( f30 - > has_gpio ) {
2017-02-08 23:02:07 +03:00
error = rmi_f30_map_gpios ( fn , f30 ) ;
if ( error )
return error ;
2016-03-11 02:56:58 +03:00
}
return 0 ;
}
static int rmi_f30_probe ( struct rmi_function * fn )
{
2017-02-08 23:02:07 +03:00
struct rmi_device * rmi_dev = fn - > rmi_dev ;
2016-03-11 02:56:58 +03:00
const struct rmi_device_platform_data * pdata =
2017-02-08 23:02:07 +03:00
rmi_get_platform_data ( rmi_dev ) ;
struct rmi_driver_data * drv_data = dev_get_drvdata ( & rmi_dev - > dev ) ;
struct f30_data * f30 ;
int error ;
2016-03-11 02:56:58 +03:00
2016-12-01 04:01:50 +03:00
if ( pdata - > f30_data . disable )
2016-03-11 02:56:58 +03:00
return 0 ;
2017-02-08 23:02:07 +03:00
if ( ! drv_data - > input ) {
dev_info ( & fn - > dev , " F30: no input device found, ignoring \n " ) ;
return - ENXIO ;
}
2016-03-11 02:56:58 +03:00
2017-02-08 23:02:07 +03:00
f30 = devm_kzalloc ( & fn - > dev , sizeof ( * f30 ) , GFP_KERNEL ) ;
if ( ! f30 )
return - ENOMEM ;
2016-03-11 02:56:58 +03:00
2017-02-08 23:02:07 +03:00
f30 - > input = drv_data - > input ;
2016-03-11 02:56:58 +03:00
2017-02-08 23:02:07 +03:00
error = rmi_f30_initialize ( fn , f30 ) ;
if ( error )
return error ;
2016-03-11 02:56:58 +03:00
2017-02-08 23:02:07 +03:00
dev_set_drvdata ( & fn - > dev , f30 ) ;
return 0 ;
2016-03-11 02:56:58 +03:00
}
struct rmi_function_handler rmi_f30_handler = {
. driver = {
. name = " rmi4_f30 " ,
} ,
. func = 0x30 ,
. probe = rmi_f30_probe ,
. config = rmi_f30_config ,
. attention = rmi_f30_attention ,
} ;