touch: imported pt (Parade TrueTouch Gen5 Touchscreen Driver)
parent
521acadc4d
commit
2ac5ccb2db
|
@ -0,0 +1,135 @@
|
|||
pt_i2c_adaptor bindings
|
||||
|
||||
Required properties:
|
||||
- compatible: "parade,pt_i2c_adaptor"
|
||||
- reg: i2c address of the chip
|
||||
- interrupt-parent: a phandle for the interrupt controller
|
||||
- interrupts: Interrupt GPIO
|
||||
- parade,adapter_id: adaptor name
|
||||
- core,name: name of core
|
||||
- core,irq_gpio: IRQ GPIO
|
||||
- core,hid_desc_register: Default HID register
|
||||
- core,flags: Special flags
|
||||
- core,mt,name: name of multi-touch module
|
||||
- core,mt,inp_dev_name: input device name
|
||||
- core,mt,flags: MT flags
|
||||
- core,mt,abs: ABS_MT_* event names
|
||||
|
||||
Optional properties:
|
||||
- core,rst_gpio: Reset GPIO
|
||||
- core,easy_wakeup_gesture: Default wakeup gesture
|
||||
- core,panel_id_support: panel ID support
|
||||
- core,btn_keys: Virtual button key codes
|
||||
- core,btn_keys-tag: Button Tag
|
||||
- core,mt,vkeys-x: X coordinate for virtual button area
|
||||
- core,mt,vkeys-y: Y coordinate for virtual button area
|
||||
- core,mt,virtual_keys: Keycode CenterX CenterY Width Height
|
||||
|
||||
[1]: Documentation/devicetree/bindings/input/parade-touchscreen.txt
|
||||
|
||||
Example:
|
||||
i2c@0 {
|
||||
status = "ok";
|
||||
tsc@24 {
|
||||
compatible = "parade,pt_i2c_adapter";
|
||||
reg = <0x24>;
|
||||
interrupt-parent = <&msmgpio>;
|
||||
interrupts = <59 0x2>;
|
||||
parade,adapter_id = "pt_i2c_adapter";
|
||||
pinctrl-names = "pmx_ts_active","pmx_ts_suspend","pmx_ts_release";
|
||||
pinctrl-0 = <&ts_int_active>, <&ts_reset_active>;
|
||||
pinctrl-1 = <&ts_int_suspend>, <&ts_reset_suspend>;
|
||||
pinctrl-2 = <&ts_release>;
|
||||
|
||||
parade,core {
|
||||
parade,name = "pt_core";
|
||||
|
||||
parade,irq_gpio = <59>;
|
||||
parade,rst_gpio = <13>;
|
||||
parade,runfw_gpio = <64>;
|
||||
parade,hid_desc_register = <1>;
|
||||
/*
|
||||
* PT_CORE_FLAG_NONE = 0x00
|
||||
* PT_CORE_FLAG_POWEROFF_ON_SLEEP = 0x02
|
||||
* PT_CORE_FLAG_RESTORE_PARAMETERS = 0x04
|
||||
* PT_CORE_FLAG_DEEP_STANDBY = 0x08
|
||||
* PT_CORE_FLAG_SKIP_SYS_SLEEP = 0x10
|
||||
* PT_CORE_FLAG_SKIP_RUNTIME = 0x20
|
||||
* PT_CORE_FLAG_SKIP_RESUME = 0x40
|
||||
*/
|
||||
parade,flags = <4>;
|
||||
/* PT_CORE_EWG_NONE */
|
||||
parade,easy_wakeup_gesture = <0>;
|
||||
/* 0:AUTO 1:PIP1_ONLY 2:PIP2_CAPABLE*/
|
||||
parade,config_dut_generation = <2>;
|
||||
/* 0:False 1:True*/
|
||||
parade,watchdog_force_stop = <0>;
|
||||
/*
|
||||
* PT_PANEL_ID_DISABLE = 0x00
|
||||
* PT_PANEL_ID_BY_BL = 0x01
|
||||
* PT_PANEL_ID_BY_SYS_INFO = 0x02
|
||||
* PT_PANEL_ID_BY_MFG_DATA = 0x04
|
||||
*/
|
||||
parade,panel_id_support = <0>;
|
||||
parade,btn_keys = <172 /* KEY_HOMEPAGE */
|
||||
/* previously was KEY_HOME, new Android versions use KEY_HOMEPAGE */
|
||||
139 /* KEY_MENU */
|
||||
158 /* KEY_BACK */
|
||||
217 /* KEY_SEARCH */
|
||||
114 /* KEY_VOLUMEDOWN */
|
||||
115 /* KEY_VOLUMEUP */
|
||||
212 /* KEY_CAMERA */
|
||||
116>; /* KEY_POWER */
|
||||
parade,btn_keys-tag = <0>;
|
||||
|
||||
parade,mt {
|
||||
parade,name = "pt_mt";
|
||||
|
||||
parade,inp_dev_name = "pt_mt";
|
||||
/*
|
||||
* PT_MT_FLAG_NONE = 0x00
|
||||
* PT_MT_FLAG_FLIP = 0x08
|
||||
* PT_MT_FLAG_INV_X = 0x10
|
||||
* PT_MT_FLAG_INV_Y = 0x20
|
||||
* PT_MT_FLAG_VKEYS = 0x40
|
||||
*/
|
||||
parade,flags = <0x00>;
|
||||
parade,abs =
|
||||
/* ABS_MT_POSITION_X, PT_ABS_MIN_X, PT_ABS_MAX_X, 0, 0 */
|
||||
<0x35 0 880 0 0
|
||||
/* ABS_MT_POSITION_Y, PT_ABS_MIN_Y, PT_ABS_MAX_Y, 0, 0 */
|
||||
0x36 0 1280 0 0
|
||||
/* ABS_MT_PRESSURE, PT_ABS_MIN_P, PT_ABS_MAX_P, 0, 0 */
|
||||
0x3a 0 255 0 0
|
||||
/* PT_IGNORE_VALUE, PT_ABS_MIN_W, PT_ABS_MAX_W, 0, 0 */
|
||||
0xffff 0 255 0 0
|
||||
/* ABS_MT_TRACKING_ID, PT_ABS_MIN_T, PT_ABS_MAX_T, 0, 0 */
|
||||
0x39 0 15 0 0
|
||||
/* ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0 */
|
||||
0x30 0 255 0 0
|
||||
/* ABS_MT_TOUCH_MINOR, 0, 255, 0, 0 */
|
||||
0x31 0 255 0 0
|
||||
/* ABS_MT_ORIENTATION, -127, 127, 0, 0 */
|
||||
0x34 0xffffff81 127 0 0
|
||||
/* ABS_MT_TOOL_TYPE, 0, MT_TOOL_MAX, 0, 0 */
|
||||
0x37 0 1 0 0
|
||||
/* ABS_DISTANCE, 0, 255, 0, 0 */
|
||||
0x19 0 255 0 0>;
|
||||
|
||||
parade,vkeys_x = <720>;
|
||||
parade,vkeys_y = <1280>;
|
||||
|
||||
parade,virtual_keys = /* KeyCode CenterX CenterY Width Height */
|
||||
/* KEY_BACK */
|
||||
<158 90 1360 160 180
|
||||
/* KEY_MENU */
|
||||
139 270 1360 160 180
|
||||
/* KEY_HOMEPAGE */
|
||||
172 450 1360 160 180
|
||||
/* KEY SEARCH */
|
||||
217 630 1360 160 180>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -252,7 +252,7 @@ config TOUCHSCREEN_CYTTSP4_SPI
|
|||
module will be called cyttsp4_spi.
|
||||
|
||||
config TOUCHSCREEN_CYPRESS_CYTTSP5
|
||||
tristate "Parade TrueTouch Gen5 Touchscreen Driver"
|
||||
tristate "Parade TrueTouch Gen5 Touchscreen Driver (cyttsp5)"
|
||||
help
|
||||
Core driver for Parade TrueTouch(tm) Standard Product
|
||||
Geneartion5 touchscreen controllers.
|
||||
|
@ -470,6 +470,202 @@ config TOUCHSCREEN_CYPRESS_CYTTSP5_DEBUG_MDL
|
|||
module will be called cyttsp5_debug.
|
||||
|
||||
|
||||
config TOUCHSCREEN_PARADE
|
||||
tristate "Parade TrueTouch Gen5 Touchscreen Driver"
|
||||
help
|
||||
Core driver for Parade TrueTouch(tm) Standard Product
|
||||
Geneartion5 touchscreen controllers.
|
||||
|
||||
Say Y here if you have a Parade Gen5 touchscreen.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called pt.
|
||||
|
||||
config TOUCHSCREEN_PARADE_DEVICETREE_SUPPORT
|
||||
bool "Enable Device Tree support"
|
||||
depends on TOUCHSCREEN_PARADE && OF
|
||||
help
|
||||
Say Y here to enable support for device tree.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config TOUCHSCREEN_PARADE_DEBUG
|
||||
bool "Enable debug output"
|
||||
depends on TOUCHSCREEN_PARADE
|
||||
help
|
||||
Say Y here to enable debug output for Parade TrueTouch(tm)
|
||||
Standard Product Generation5 drivers set.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config TOUCHSCREEN_PARADE_VDEBUG
|
||||
bool "Enable verbose debug output"
|
||||
depends on TOUCHSCREEN_PARADE_DEBUG
|
||||
help
|
||||
Say Y here to enable verbose debug output for Parade TrueTouch(tm)
|
||||
Standard Product Generation5 drivers set.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config TOUCHSCREEN_PARADE_I2C
|
||||
tristate "Parade TrueTouch Gen5 I2C"
|
||||
depends on TOUCHSCREEN_PARADE
|
||||
select I2C
|
||||
help
|
||||
Say Y here to enable I2C bus interface to Parade TrueTouch(tm)
|
||||
Standard Product Generation5 touchscreen controller.
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called pt_i2c.
|
||||
|
||||
config TOUCHSCREEN_PARADE_SPI
|
||||
tristate "Parade TrueTouch Gen5 SPI"
|
||||
depends on TOUCHSCREEN_PARADE
|
||||
select SPI
|
||||
help
|
||||
Say Y here to enable SPI bus interface to Parade TrueTouch(tm)
|
||||
Standard Product Generation5 touchscreen controller.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called pt_spi.
|
||||
|
||||
choice
|
||||
bool "Parade TrueTouch Gen5 MultiTouch Protocol"
|
||||
depends on TOUCHSCREEN_PARADE
|
||||
default TOUCHSCREEN_PARADE_MT_B
|
||||
help
|
||||
This option controls which MultiTouch protocol will be used to
|
||||
report the touch events.
|
||||
|
||||
config TOUCHSCREEN_PARADE_MT_A
|
||||
bool "Protocol A"
|
||||
help
|
||||
Select to enable MultiTouch touch reporting using protocol A
|
||||
on Parade TrueTouch(tm) Standard Product Generation4 touchscreen
|
||||
controller.
|
||||
|
||||
config TOUCHSCREEN_PARADE_MT_B
|
||||
bool "Protocol B"
|
||||
help
|
||||
Select to enable MultiTouch touch reporting using protocol B
|
||||
on Parade TrueTouch(tm) Standard Product Generation4 touchscreen
|
||||
controller.
|
||||
|
||||
endchoice
|
||||
|
||||
config TOUCHSCREEN_PARADE_BUTTON
|
||||
bool "Parade TrueTouch Gen5 MultiTouch CapSense Button"
|
||||
depends on TOUCHSCREEN_PARADE
|
||||
help
|
||||
Say Y here to enable CapSense reporting on Parade TrueTouch(tm)
|
||||
Standard Product Generation5 touchscreen controller.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config TOUCHSCREEN_PARADE_PROXIMITY
|
||||
bool "Parade TrueTouch Gen5 Proximity"
|
||||
depends on TOUCHSCREEN_PARADE
|
||||
help
|
||||
Say Y here to enable proximity reporting on Parade TrueTouch(tm)
|
||||
Standard Product Generation5 touchscreen controller.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config TOUCHSCREEN_PARADE_DEVICE_ACCESS
|
||||
tristate "Parade TrueTouch Gen5 MultiTouch Device Access"
|
||||
depends on TOUCHSCREEN_PARADE
|
||||
help
|
||||
Say Y here to enable Parade TrueTouch(tm) Standard Product
|
||||
Generation5 touchscreen controller device access module.
|
||||
|
||||
This modules adds an interface to access touchscreen
|
||||
controller using driver sysfs nodes.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called pt_device_access.
|
||||
|
||||
config TOUCHSCREEN_PARADE_LOADER
|
||||
tristate "Parade TrueTouch Gen5 MultiTouch Loader"
|
||||
depends on TOUCHSCREEN_PARADE
|
||||
help
|
||||
Say Y here to enable Parade TrueTouch(tm) Standard Product
|
||||
Generation5 touchscreen controller FW Loader module.
|
||||
|
||||
This module enables support for Firmware upgrade.
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called pt_loader.
|
||||
|
||||
config TOUCHSCREEN_PARADE_PLATFORM_FW_UPGRADE
|
||||
bool "FW upgrade from header file"
|
||||
depends on TOUCHSCREEN_PARADE_LOADER
|
||||
help
|
||||
Say Y here to include Parade TrueTouch(tm) Standard Product
|
||||
Generation5 device Firmware into driver.
|
||||
|
||||
Need proper header file for this.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config TOUCHSCREEN_PARADE_BINARY_FW_UPGRADE
|
||||
bool "FW upgrade from binary file"
|
||||
depends on TOUCHSCREEN_PARADE_LOADER
|
||||
help
|
||||
Say Y here to include Parade TrueTouch(tm) Standard Product
|
||||
Generation5 device Firmware into kernel as binary blob.
|
||||
|
||||
This should be enabled for manual FW upgrade support.
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
config TOUCHSCREEN_PARADE_PLATFORM_TTCONFIG_UPGRADE
|
||||
bool "TT Configuration upgrade from header file"
|
||||
depends on TOUCHSCREEN_PARADE_LOADER
|
||||
help
|
||||
Say Y here to include Parade TrueTouch(tm) Standard Product
|
||||
Generation5 device TrueTouch Configuration into kernel itself.
|
||||
|
||||
Need proper header file for this.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config TOUCHSCREEN_PARADE_MANUAL_TTCONFIG_UPGRADE
|
||||
bool "TT Configuration upgrade via SysFs"
|
||||
depends on TOUCHSCREEN_PARADE_LOADER
|
||||
help
|
||||
Say Y here to provide a SysFs interface to upgrade TrueTouch
|
||||
Configuration with a binary configuration file.
|
||||
|
||||
Need proper binary version of config file for this
|
||||
feature.
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
config TOUCHSCREEN_PARADE_DEBUG_MDL
|
||||
tristate "Parade TrueTouch Gen5 MultiTouch Debug Module"
|
||||
depends on TOUCHSCREEN_PARADE
|
||||
help
|
||||
Say Y here to enable Parade TrueTouch(tm) Standard Product
|
||||
Generation5 Debug module.
|
||||
|
||||
This module adds support for verbose printing touch
|
||||
information.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called pt_debug.
|
||||
|
||||
config TOUCHSCREEN_DA9034
|
||||
tristate "Touchscreen support for Dialog Semiconductor DA9034"
|
||||
depends on PMIC_DA903X
|
||||
|
|
|
@ -157,3 +157,53 @@ CFLAGS_cyttsp5_devtree.o += -DVERBOSE_DEBUG
|
|||
CFLAGS_cyttsp5_platform.o += -DVERBOSE_DEBUG
|
||||
endif
|
||||
|
||||
GCOV_PROFILE := y
|
||||
|
||||
obj-$(CONFIG_TOUCHSCREEN_PARADE) += pt.o
|
||||
pt-y := pt_core.o pt_mt_common.o
|
||||
pt-$(CONFIG_TOUCHSCREEN_PARADE_MT_A) += pt_mta.o
|
||||
pt-$(CONFIG_TOUCHSCREEN_PARADE_MT_B) += pt_mtb.o
|
||||
pt-$(CONFIG_TOUCHSCREEN_PARADE_BUTTON) += pt_btn.o
|
||||
pt-$(CONFIG_TOUCHSCREEN_PARADE_PROXIMITY) += pt_proximity.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_PARADE_DEVICETREE_SUPPORT) += pt_devtree.o
|
||||
ifdef CONFIG_TOUCHSCREEN_PARADE
|
||||
obj-y += pt_platform.o
|
||||
endif
|
||||
obj-$(CONFIG_TOUCHSCREEN_PARADE_I2C) += pt_i2c.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_PARADE_SPI) += pt_spi.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_PARADE_DEBUG_MDL) += pt_debug.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_PARADE_LOADER) += pt_loader.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_PARADE_DEVICE_ACCESS) += pt_device_access.o
|
||||
|
||||
ifeq ($(CONFIG_TOUCHSCREEN_PARADE_DEBUG),y)
|
||||
CFLAGS_pt_core.o += -DDEBUG
|
||||
CFLAGS_pt_i2c.o += -DDEBUG
|
||||
CFLAGS_pt_spi.o += -DDEBUG
|
||||
CFLAGS_pt_mta.o += -DDEBUG
|
||||
CFLAGS_pt_mtb.o += -DDEBUG
|
||||
CFLAGS_pt_mt_common.o += -DDEBUG
|
||||
CFLAGS_pt_btn.o += -DDEBUG
|
||||
CFLAGS_pt_proximity.o += -DDEBUG
|
||||
CFLAGS_pt_device_access.o += -DDEBUG
|
||||
CFLAGS_pt_loader.o += -DDEBUG
|
||||
CFLAGS_pt_debug.o += -DDEBUG
|
||||
CFLAGS_pt_devtree.o += -DDEBUG
|
||||
CFLAGS_pt_platform.o += -DDEBUG
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_TOUCHSCREEN_PARADE_VDEBUG),y)
|
||||
CFLAGS_pt_core.o += -DVERBOSE_DEBUG
|
||||
CFLAGS_pt_i2c.o += -DVERBOSE_DEBUG
|
||||
CFLAGS_pt_spi.o += -DVERBOSE_DEBUG
|
||||
CFLAGS_pt_mta.o += -DVERBOSE_DEBUG
|
||||
CFLAGS_pt_mtb.o += -DVERBOSE_DEBUG
|
||||
CFLAGS_pt_mt_common.o += -DVERBOSE_DEBUG
|
||||
CFLAGS_pt_btn.o += -DVERBOSE_DEBUG
|
||||
CFLAGS_pt_proximity.o += -DVERBOSE_DEBUG
|
||||
CFLAGS_pt_device_access.o += -DVERBOSE_DEBUG
|
||||
CFLAGS_pt_loader.o += -DVERBOSE_DEBUG
|
||||
CFLAGS_pt_debug.o += -DVERBOSE_DEBUG
|
||||
CFLAGS_pt_devtree.o += -DVERBOSE_DEBUG
|
||||
CFLAGS_pt_platform.o += -DVERBOSE_DEBUG
|
||||
endif
|
||||
|
||||
|
|
|
@ -0,0 +1,522 @@
|
|||
/*
|
||||
* pt_btn.c
|
||||
* Parade TrueTouch(TM) Standard Product CapSense Reports Module.
|
||||
* For use with Parade touchscreen controllers.
|
||||
* Supported parts include:
|
||||
* TMA5XX
|
||||
* TMA448
|
||||
* TMA445A
|
||||
* TT21XXX
|
||||
* TT31XXX
|
||||
* TT4XXXX
|
||||
* TT7XXX
|
||||
* TC3XXX
|
||||
*
|
||||
* Copyright (C) 2015-2020 Parade Technologies
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2, and only version 2, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contact Parade Technologies at www.paradetech.com <ttdrivers@paradetech.com>
|
||||
*/
|
||||
|
||||
#include "pt_regs.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_btn_key_action
|
||||
*
|
||||
* SUMMARY: Reports key event
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *bd - pointer to button data structure
|
||||
* btn_no - number of button
|
||||
* btn_state - state of button
|
||||
******************************************************************************/
|
||||
static inline void pt_btn_key_action(struct pt_btn_data *bd,
|
||||
int btn_no, int btn_state)
|
||||
{
|
||||
struct device *dev = bd->dev;
|
||||
struct pt_sysinfo *si = bd->si;
|
||||
|
||||
if (!si->btn[btn_no].enabled ||
|
||||
si->btn[btn_no].state == btn_state)
|
||||
return;
|
||||
|
||||
si->btn[btn_no].state = btn_state;
|
||||
input_report_key(bd->input, si->btn[btn_no].key_code, btn_state);
|
||||
input_sync(bd->input);
|
||||
|
||||
pt_debug(dev, DL_INFO, "%s: btn=%d key_code=%d %s\n",
|
||||
__func__, btn_no, si->btn[btn_no].key_code,
|
||||
btn_state == PT_BTN_PRESSED ?
|
||||
"PRESSED" : "RELEASED");
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_get_btn_touches
|
||||
*
|
||||
* SUMMARY: Parse and report key event
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *bd - pointer to button data structure
|
||||
******************************************************************************/
|
||||
static void pt_get_btn_touches(struct pt_btn_data *bd)
|
||||
{
|
||||
struct pt_sysinfo *si = bd->si;
|
||||
int num_btns = si->num_btns;
|
||||
int cur_btn;
|
||||
int cur_btn_state;
|
||||
|
||||
for (cur_btn = 0; cur_btn < num_btns; cur_btn++) {
|
||||
/* Get current button state */
|
||||
cur_btn_state = (si->xy_data[0] >> (cur_btn * PT_BITS_PER_BTN))
|
||||
& PT_NUM_BTN_EVENT_ID;
|
||||
|
||||
pt_btn_key_action(bd, cur_btn, cur_btn_state);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_btn_lift_all
|
||||
*
|
||||
* SUMMARY: Reports button liftoff action
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *bd - pointer to button data structure
|
||||
******************************************************************************/
|
||||
static void pt_btn_lift_all(struct pt_btn_data *bd)
|
||||
{
|
||||
struct pt_sysinfo *si = bd->si;
|
||||
int i;
|
||||
|
||||
if (!si || si->num_btns == 0)
|
||||
return;
|
||||
|
||||
for (i = 0; i < si->num_btns; i++)
|
||||
pt_btn_key_action(bd, i, PT_BTN_RELEASED);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_xy_worker
|
||||
*
|
||||
* SUMMARY: Read xy_data for all current CapSense button touches
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *bd - pointer to button data structure
|
||||
******************************************************************************/
|
||||
static int pt_xy_worker(struct pt_btn_data *bd)
|
||||
{
|
||||
struct pt_sysinfo *si = bd->si;
|
||||
|
||||
/* extract button press/release touch information */
|
||||
if (si->num_btns > 0)
|
||||
pt_get_btn_touches(bd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_btn_attention
|
||||
*
|
||||
* SUMMARY: Wrapper function for pt_xy_worker() that register to TTDL attention
|
||||
* list.
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
* !0 = failure
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dev - pointer to device structure
|
||||
******************************************************************************/
|
||||
static int pt_btn_attention(struct device *dev)
|
||||
{
|
||||
struct pt_core_data *cd = dev_get_drvdata(dev);
|
||||
struct pt_btn_data *bd = &cd->bd;
|
||||
int rc;
|
||||
|
||||
if (bd->si->xy_mode[2] != bd->si->desc.btn_report_id)
|
||||
return 0;
|
||||
|
||||
/* core handles handshake */
|
||||
mutex_lock(&bd->btn_lock);
|
||||
rc = pt_xy_worker(bd);
|
||||
mutex_unlock(&bd->btn_lock);
|
||||
if (rc < 0)
|
||||
pt_debug(dev, DL_ERROR,
|
||||
"%s: xy_worker error r=%d\n", __func__, rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_startup_attention
|
||||
*
|
||||
* SUMMARY: Wrapper function for pt_btn_lift_all() that register to TTDL
|
||||
* attention list.
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dev - pointer to device structure
|
||||
******************************************************************************/
|
||||
static int pt_startup_attention(struct device *dev)
|
||||
{
|
||||
struct pt_core_data *cd = dev_get_drvdata(dev);
|
||||
struct pt_btn_data *bd = &cd->bd;
|
||||
|
||||
mutex_lock(&bd->btn_lock);
|
||||
pt_btn_lift_all(bd);
|
||||
mutex_unlock(&bd->btn_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_btn_suspend_attention
|
||||
*
|
||||
* SUMMARY: Function for button to enter suspend state that as following steps:
|
||||
* 1) Lift all button
|
||||
* 2) Set flag with suspend state
|
||||
* 3) Decrese pm system count
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dev - pointer to device structure
|
||||
******************************************************************************/
|
||||
static int pt_btn_suspend_attention(struct device *dev)
|
||||
{
|
||||
struct pt_core_data *cd = dev_get_drvdata(dev);
|
||||
struct pt_btn_data *bd = &cd->bd;
|
||||
|
||||
mutex_lock(&bd->btn_lock);
|
||||
pt_btn_lift_all(bd);
|
||||
bd->is_suspended = true;
|
||||
mutex_unlock(&bd->btn_lock);
|
||||
|
||||
pm_runtime_put(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_btn_resume_attention
|
||||
*
|
||||
* SUMMARY: Function for button to leave suspend state that as following steps:
|
||||
* 1) Increse pm system count
|
||||
* 2) Clear suspend state flag
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dev - pointer to device structure
|
||||
******************************************************************************/
|
||||
static int pt_btn_resume_attention(struct device *dev)
|
||||
{
|
||||
struct pt_core_data *cd = dev_get_drvdata(dev);
|
||||
struct pt_btn_data *bd = &cd->bd;
|
||||
|
||||
pm_runtime_get(dev);
|
||||
|
||||
mutex_lock(&bd->btn_lock);
|
||||
bd->is_suspended = false;
|
||||
mutex_unlock(&bd->btn_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_btn_open
|
||||
*
|
||||
* SUMMARY: Open method for input device(button) that sets up call back
|
||||
* functions to TTDL attention list
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *input - pointer to input_dev structure
|
||||
******************************************************************************/
|
||||
static int pt_btn_open(struct input_dev *input)
|
||||
{
|
||||
struct device *dev = input->dev.parent;
|
||||
struct pt_core_data *cd = dev_get_drvdata(dev);
|
||||
struct pt_btn_data *bd = &cd->bd;
|
||||
|
||||
pm_runtime_get_sync(dev);
|
||||
|
||||
mutex_lock(&bd->btn_lock);
|
||||
bd->is_suspended = false;
|
||||
mutex_unlock(&bd->btn_lock);
|
||||
|
||||
pt_debug(dev, DL_INFO, "%s: setup subscriptions\n", __func__);
|
||||
|
||||
/* set up touch call back */
|
||||
_pt_subscribe_attention(dev, PT_ATTEN_IRQ, PT_BTN_NAME,
|
||||
pt_btn_attention, PT_MODE_OPERATIONAL);
|
||||
|
||||
/* set up startup call back */
|
||||
_pt_subscribe_attention(dev, PT_ATTEN_STARTUP, PT_BTN_NAME,
|
||||
pt_startup_attention, 0);
|
||||
|
||||
/* set up suspend call back */
|
||||
_pt_subscribe_attention(dev, PT_ATTEN_SUSPEND, PT_BTN_NAME,
|
||||
pt_btn_suspend_attention, 0);
|
||||
|
||||
/* set up resume call back */
|
||||
_pt_subscribe_attention(dev, PT_ATTEN_RESUME, PT_BTN_NAME,
|
||||
pt_btn_resume_attention, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_btn_close
|
||||
*
|
||||
* SUMMARY: Close method for input device(button) that clears call back
|
||||
* functions from TTDL attention list.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *input - pointer to input_dev structure
|
||||
******************************************************************************/
|
||||
static void pt_btn_close(struct input_dev *input)
|
||||
{
|
||||
struct device *dev = input->dev.parent;
|
||||
struct pt_core_data *cd = dev_get_drvdata(dev);
|
||||
struct pt_btn_data *bd = &cd->bd;
|
||||
|
||||
_pt_unsubscribe_attention(dev, PT_ATTEN_IRQ, PT_BTN_NAME,
|
||||
pt_btn_attention, PT_MODE_OPERATIONAL);
|
||||
|
||||
_pt_unsubscribe_attention(dev, PT_ATTEN_STARTUP, PT_BTN_NAME,
|
||||
pt_startup_attention, 0);
|
||||
|
||||
_pt_unsubscribe_attention(dev, PT_ATTEN_SUSPEND, PT_BTN_NAME,
|
||||
pt_btn_suspend_attention, 0);
|
||||
|
||||
_pt_unsubscribe_attention(dev, PT_ATTEN_RESUME, PT_BTN_NAME,
|
||||
pt_btn_resume_attention, 0);
|
||||
|
||||
mutex_lock(&bd->btn_lock);
|
||||
if (!bd->is_suspended) {
|
||||
pm_runtime_put(dev);
|
||||
bd->is_suspended = true;
|
||||
}
|
||||
mutex_unlock(&bd->btn_lock);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_setup_input_device
|
||||
*
|
||||
* SUMMARY: Set up resolution, event signal capabilities and register input
|
||||
* device for button.
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
* !0 = failure
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dev - pointer to device structure
|
||||
******************************************************************************/
|
||||
static int pt_setup_input_device(struct device *dev)
|
||||
{
|
||||
struct pt_core_data *cd = dev_get_drvdata(dev);
|
||||
struct pt_btn_data *bd = &cd->bd;
|
||||
int i;
|
||||
int rc;
|
||||
|
||||
pt_debug(dev, DL_INFO, "%s: Initialize event signals\n",
|
||||
__func__);
|
||||
__set_bit(EV_KEY, bd->input->evbit);
|
||||
pt_debug(dev, DL_INFO, "%s: Number of buttons %d\n",
|
||||
__func__, bd->si->num_btns);
|
||||
for (i = 0; i < bd->si->num_btns; i++) {
|
||||
pt_debug(dev, DL_INFO, "%s: btn:%d keycode:%d\n",
|
||||
__func__, i, bd->si->btn[i].key_code);
|
||||
__set_bit(bd->si->btn[i].key_code, bd->input->keybit);
|
||||
}
|
||||
|
||||
rc = input_register_device(bd->input);
|
||||
if (rc < 0)
|
||||
pt_debug(dev, DL_ERROR,
|
||||
"%s: Error, failed register input device r=%d\n",
|
||||
__func__, rc);
|
||||
else
|
||||
bd->input_device_registered = true;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_setup_input_attention
|
||||
*
|
||||
* SUMMARY: Wrapper function for pt_setup_input_device() register to TTDL
|
||||
* attention list.
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
* !0 = failure
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dev - pointer to device structure
|
||||
******************************************************************************/
|
||||
static int pt_setup_input_attention(struct device *dev)
|
||||
{
|
||||
struct pt_core_data *cd = dev_get_drvdata(dev);
|
||||
struct pt_btn_data *bd = &cd->bd;
|
||||
int rc;
|
||||
|
||||
bd->si = _pt_request_sysinfo(dev);
|
||||
if (!bd->si)
|
||||
return -1;
|
||||
|
||||
rc = pt_setup_input_device(dev);
|
||||
|
||||
_pt_unsubscribe_attention(dev, PT_ATTEN_STARTUP, PT_BTN_NAME,
|
||||
pt_setup_input_attention, 0);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_btn_probe
|
||||
*
|
||||
* SUMMARY: The probe function for button input device
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
* !0 = failure
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dev - pointer to device structure
|
||||
******************************************************************************/
|
||||
int pt_btn_probe(struct device *dev)
|
||||
{
|
||||
struct pt_core_data *cd = dev_get_drvdata(dev);
|
||||
struct pt_btn_data *bd = &cd->bd;
|
||||
struct pt_platform_data *pdata = dev_get_platdata(dev);
|
||||
struct pt_btn_platform_data *btn_pdata;
|
||||
int rc = 0;
|
||||
|
||||
if (!pdata || !pdata->btn_pdata) {
|
||||
pt_debug(dev, DL_ERROR,
|
||||
"%s: Missing platform data\n", __func__);
|
||||
rc = -ENODEV;
|
||||
goto error_no_pdata;
|
||||
}
|
||||
btn_pdata = pdata->btn_pdata;
|
||||
|
||||
mutex_init(&bd->btn_lock);
|
||||
bd->dev = dev;
|
||||
bd->pdata = btn_pdata;
|
||||
|
||||
/* Create the input device and register it. */
|
||||
pt_debug(dev, DL_INFO,
|
||||
"%s: Create the input device and register it\n", __func__);
|
||||
bd->input = input_allocate_device();
|
||||
if (!bd->input) {
|
||||
pt_debug(dev, DL_ERROR,
|
||||
"%s: Error, failed to allocate input device\n",
|
||||
__func__);
|
||||
rc = -ENODEV;
|
||||
goto error_alloc_failed;
|
||||
} else
|
||||
bd->input_device_allocated = true;
|
||||
|
||||
if (bd->pdata->inp_dev_name)
|
||||
bd->input->name = bd->pdata->inp_dev_name;
|
||||
else
|
||||
bd->input->name = PT_BTN_NAME;
|
||||
scnprintf(bd->phys, sizeof(bd->phys), "%s/input%d", dev_name(dev),
|
||||
cd->phys_num++);
|
||||
bd->input->phys = bd->phys;
|
||||
bd->input->dev.parent = bd->dev;
|
||||
bd->input->open = pt_btn_open;
|
||||
bd->input->close = pt_btn_close;
|
||||
input_set_drvdata(bd->input, bd);
|
||||
|
||||
/* get sysinfo */
|
||||
bd->si = _pt_request_sysinfo(dev);
|
||||
|
||||
if (bd->si) {
|
||||
rc = pt_setup_input_device(dev);
|
||||
if (rc)
|
||||
goto error_init_input;
|
||||
} else {
|
||||
pt_debug(dev, DL_ERROR,
|
||||
"%s: Fail get sysinfo pointer from core p=%p\n",
|
||||
__func__, bd->si);
|
||||
_pt_subscribe_attention(dev, PT_ATTEN_STARTUP,
|
||||
PT_BTN_NAME, pt_setup_input_attention, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error_init_input:
|
||||
input_free_device(bd->input);
|
||||
bd->input_device_allocated = false;
|
||||
error_alloc_failed:
|
||||
error_no_pdata:
|
||||
pt_debug(dev, DL_ERROR, "%s failed.\n", __func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_btn_release
|
||||
*
|
||||
* SUMMARY: The release function for button input device
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dev - pointer to device structure
|
||||
******************************************************************************/
|
||||
int pt_btn_release(struct device *dev)
|
||||
{
|
||||
struct pt_core_data *cd;
|
||||
struct pt_btn_data *bd;
|
||||
|
||||
/* Ensure valid pointers before de-referencing them */
|
||||
if (dev) {
|
||||
cd = dev_get_drvdata(dev);
|
||||
if (cd)
|
||||
bd = &cd->bd;
|
||||
else
|
||||
return 0;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Second call this function may cause kernel panic if probe fail.
|
||||
* Use input_device_registered & input_device_allocated variable to
|
||||
* avoid unregister or free unavailable devive.
|
||||
*/
|
||||
if (bd && bd->input_device_registered) {
|
||||
bd->input_device_registered = false;
|
||||
input_unregister_device(bd->input);
|
||||
/* Unregistering device will free the device too */
|
||||
bd->input_device_allocated = false;
|
||||
} else if (bd && bd->input_device_allocated) {
|
||||
bd->input_device_allocated = false;
|
||||
input_free_device(bd->input);
|
||||
_pt_unsubscribe_attention(dev, PT_ATTEN_STARTUP,
|
||||
PT_BTN_NAME, pt_setup_input_attention, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,556 @@
|
|||
/*
|
||||
* pt_debug.c
|
||||
* Parade TrueTouch(TM) Standard Product Debug Module.
|
||||
* For use with Parade touchscreen controllers.
|
||||
* Supported parts include:
|
||||
* TMA5XX
|
||||
* TMA448
|
||||
* TMA445A
|
||||
* TT21XXX
|
||||
* TT31XXX
|
||||
* TT4XXXX
|
||||
* TT7XXX
|
||||
* TC3XXX
|
||||
*
|
||||
* Copyright (C) 2015-2020 Parade Technologies
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2, and only version 2, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contact Parade Technologies at www.paradetech.com <ttdrivers@paradetech.com>
|
||||
*/
|
||||
|
||||
#include "pt_regs.h"
|
||||
|
||||
#define PT_DEBUG_NAME "pt_debug"
|
||||
|
||||
struct pt_debug_data {
|
||||
struct device *dev;
|
||||
struct pt_sysinfo *si;
|
||||
uint32_t interrupt_count;
|
||||
uint32_t formated_output;
|
||||
struct mutex sysfs_lock;
|
||||
u8 pr_buf[PT_MAX_PRBUF_SIZE];
|
||||
};
|
||||
|
||||
static struct pt_core_commands *cmd;
|
||||
|
||||
static struct pt_module debug_module;
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_get_debug_data
|
||||
*
|
||||
* SUMMARY: Inline function to get pt_debug_data pointer from debug module.
|
||||
*
|
||||
* RETURN:
|
||||
* pointer to pt_debug_data structure
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dev - pointer to device structure
|
||||
******************************************************************************/
|
||||
static inline struct pt_debug_data *pt_get_debug_data(
|
||||
struct device *dev)
|
||||
{
|
||||
return pt_get_module_data(dev, &debug_module);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_pr_buf_op_mode
|
||||
*
|
||||
* SUMMARY: Formats touch/button report to pr_buf that combined xy_mode and
|
||||
* xy_data. The feature is required by TTHE.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dd - pointer to pt_debug_data structure
|
||||
* *pr_buf - pointer to print buffer
|
||||
* *si - pointer to sysinfo structure
|
||||
* cur_touch - number of current touch
|
||||
******************************************************************************/
|
||||
static void pt_pr_buf_op_mode(struct pt_debug_data *dd, u8 *pr_buf,
|
||||
struct pt_sysinfo *si, u8 cur_touch)
|
||||
{
|
||||
const char fmt[] = "%02X ";
|
||||
int max = (PT_MAX_PRBUF_SIZE - 1) - sizeof(PT_PR_TRUNCATED);
|
||||
u8 report_id = si->xy_mode[2];
|
||||
int header_size = 0;
|
||||
int report_size = 0;
|
||||
int total_size = 0;
|
||||
int i, k;
|
||||
|
||||
if (report_id == si->desc.tch_report_id) {
|
||||
header_size = si->desc.tch_header_size;
|
||||
report_size = cur_touch * si->desc.tch_record_size;
|
||||
} else if (report_id == si->desc.btn_report_id) {
|
||||
header_size = BTN_INPUT_HEADER_SIZE;
|
||||
report_size = BTN_REPORT_SIZE;
|
||||
}
|
||||
total_size = header_size + report_size;
|
||||
|
||||
pr_buf[0] = 0;
|
||||
for (i = k = 0; i < header_size && i < max; i++, k += 3)
|
||||
scnprintf(pr_buf + k, PT_MAX_PRBUF_SIZE, fmt, si->xy_mode[i]);
|
||||
|
||||
for (i = 0; i < report_size && i < max; i++, k += 3)
|
||||
scnprintf(pr_buf + k, PT_MAX_PRBUF_SIZE, fmt, si->xy_data[i]);
|
||||
|
||||
pr_info("%s=%s%s\n", "pt_OpModeData", pr_buf,
|
||||
total_size <= max ? "" : PT_PR_TRUNCATED);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_debug_print
|
||||
*
|
||||
* SUMMARY: This function prints header to show data size and data_name and
|
||||
* content of "pr_buf" with hex base.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dev - pointer to device structure
|
||||
* *pr_buf - pointer to input buffer which stores the formated data
|
||||
* *sptr - pointer to the buffer to print
|
||||
* size - size of data elements
|
||||
* *data_name - data name to print
|
||||
******************************************************************************/
|
||||
static void pt_debug_print(struct device *dev, u8 *pr_buf, u8 *sptr,
|
||||
int size, const char *data_name)
|
||||
{
|
||||
int i, j;
|
||||
int elem_size = sizeof("XX ") - 1;
|
||||
int max = (PT_MAX_PRBUF_SIZE - 1) / elem_size;
|
||||
int limit = size < max ? size : max;
|
||||
|
||||
if (limit < 0)
|
||||
limit = 0;
|
||||
|
||||
pr_buf[0] = 0;
|
||||
for (i = j = 0; i < limit; i++, j += elem_size)
|
||||
scnprintf(pr_buf + j, PT_MAX_PRBUF_SIZE - j, "%02X ", sptr[i]);
|
||||
|
||||
if (size)
|
||||
pr_info("%s[0..%d]=%s%s\n", data_name, size - 1, pr_buf,
|
||||
size <= max ? "" : PT_PR_TRUNCATED);
|
||||
else
|
||||
pr_info("%s[]\n", data_name);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_debug_formated
|
||||
*
|
||||
* SUMMARY: Formats and prints touch & button report.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dev - pointer to device structure
|
||||
* *pr_buf - pointer to print buffer
|
||||
* *si - pointer to sysinfo structure
|
||||
* cur_touch - number of current touch
|
||||
******************************************************************************/
|
||||
static void pt_debug_formated(struct device *dev, u8 *pr_buf,
|
||||
struct pt_sysinfo *si, u8 num_cur_tch)
|
||||
{
|
||||
u8 report_id = si->xy_mode[2];
|
||||
int header_size = 0;
|
||||
int report_size = 0;
|
||||
u8 data_name[] = "touch[99]";
|
||||
int max_print_length = 20;
|
||||
int i;
|
||||
|
||||
if (report_id == si->desc.tch_report_id) {
|
||||
header_size = si->desc.tch_header_size;
|
||||
report_size = num_cur_tch * si->desc.tch_record_size;
|
||||
} else if (report_id == si->desc.btn_report_id) {
|
||||
header_size = BTN_INPUT_HEADER_SIZE;
|
||||
report_size = BTN_REPORT_SIZE;
|
||||
}
|
||||
|
||||
/* xy_mode */
|
||||
pt_debug_print(dev, pr_buf, si->xy_mode, header_size, "xy_mode");
|
||||
|
||||
/* xy_data */
|
||||
if (report_size > max_print_length) {
|
||||
pr_info("xy_data[0..%d]:\n", report_size);
|
||||
for (i = 0; i < report_size - max_print_length;
|
||||
i += max_print_length) {
|
||||
pt_debug_print(dev, pr_buf, si->xy_data + i,
|
||||
max_print_length, " ");
|
||||
}
|
||||
if (report_size - i)
|
||||
pt_debug_print(dev, pr_buf, si->xy_data + i,
|
||||
report_size - i, " ");
|
||||
} else {
|
||||
pt_debug_print(dev, pr_buf, si->xy_data, report_size,
|
||||
"xy_data");
|
||||
}
|
||||
|
||||
/* touches */
|
||||
if (report_id == si->desc.tch_report_id) {
|
||||
for (i = 0; i < num_cur_tch; i++) {
|
||||
scnprintf(data_name, sizeof(data_name) - 1,
|
||||
"touch[%u]", i);
|
||||
pt_debug_print(dev, pr_buf,
|
||||
si->xy_data + (i * si->desc.tch_record_size),
|
||||
si->desc.tch_record_size, data_name);
|
||||
}
|
||||
}
|
||||
|
||||
/* buttons */
|
||||
if (report_id == si->desc.btn_report_id)
|
||||
pt_debug_print(dev, pr_buf, si->xy_data, report_size,
|
||||
"button");
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_xy_worker
|
||||
*
|
||||
* SUMMARY: Read xy_data for all touches for debug.
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dd - pointer to pt_debug_data structure
|
||||
******************************************************************************/
|
||||
static int pt_xy_worker(struct pt_debug_data *dd)
|
||||
{
|
||||
struct device *dev = dd->dev;
|
||||
struct pt_sysinfo *si = dd->si;
|
||||
u8 report_reg = si->xy_mode[TOUCH_COUNT_BYTE_OFFSET];
|
||||
u8 num_cur_tch = GET_NUM_TOUCHES(report_reg);
|
||||
uint32_t formated_output;
|
||||
|
||||
mutex_lock(&dd->sysfs_lock);
|
||||
dd->interrupt_count++;
|
||||
formated_output = dd->formated_output;
|
||||
mutex_unlock(&dd->sysfs_lock);
|
||||
|
||||
/* Interrupt */
|
||||
pr_info("Interrupt(%u)\n", dd->interrupt_count);
|
||||
|
||||
if (formated_output)
|
||||
pt_debug_formated(dev, dd->pr_buf, si, num_cur_tch);
|
||||
else
|
||||
/* print data for TTHE */
|
||||
pt_pr_buf_op_mode(dd, dd->pr_buf, si, num_cur_tch);
|
||||
|
||||
pr_info("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_debug_attention
|
||||
*
|
||||
* SUMMARY: Wrapper funtion for pt_xy_worker() to subcribe into TTDL attention
|
||||
* list.
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
* !0 = failure
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dev - pointer to device structure
|
||||
******************************************************************************/
|
||||
static int pt_debug_attention(struct device *dev)
|
||||
{
|
||||
struct pt_debug_data *dd = pt_get_debug_data(dev);
|
||||
struct pt_sysinfo *si = dd->si;
|
||||
u8 report_id = si->xy_mode[2];
|
||||
int rc = 0;
|
||||
|
||||
if (report_id != si->desc.tch_report_id
|
||||
&& report_id != si->desc.btn_report_id)
|
||||
return 0;
|
||||
|
||||
/* core handles handshake */
|
||||
rc = pt_xy_worker(dd);
|
||||
if (rc < 0)
|
||||
pt_debug(dev, DL_ERROR, "%s: xy_worker error r=%d\n",
|
||||
__func__, rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_status_show
|
||||
*
|
||||
* SUMMARY: The show method for the int_count sysfs node. This node displays
|
||||
* the count of interrupt.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dev - pointer to Device structure
|
||||
* *attr - pointer to the device attribute structure
|
||||
* *buf - pointer to buffer to print
|
||||
******************************************************************************/
|
||||
static ssize_t pt_interrupt_count_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct pt_debug_data *dd = pt_get_debug_data(dev);
|
||||
int val;
|
||||
|
||||
mutex_lock(&dd->sysfs_lock);
|
||||
val = dd->interrupt_count;
|
||||
mutex_unlock(&dd->sysfs_lock);
|
||||
|
||||
return scnprintf(buf, PT_MAX_PRBUF_SIZE, "Interrupt Count: %d\n", val);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_interrupt_count_store
|
||||
*
|
||||
* SUMMARY: The store method for the int_count sysfs node that allows the count
|
||||
* of interrput to be cleared.
|
||||
*
|
||||
* RETURN: Size of passed in buffer
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dev - pointer to device structure
|
||||
* *attr - pointer to device attributes
|
||||
* *buf - pointer to buffer that hold the command parameters
|
||||
* size - size of buf
|
||||
******************************************************************************/
|
||||
static ssize_t pt_interrupt_count_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
struct pt_debug_data *dd = pt_get_debug_data(dev);
|
||||
|
||||
mutex_lock(&dd->sysfs_lock);
|
||||
dd->interrupt_count = 0;
|
||||
mutex_unlock(&dd->sysfs_lock);
|
||||
return size;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(int_count, 0600,
|
||||
pt_interrupt_count_show, pt_interrupt_count_store);
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_formated_output_show
|
||||
*
|
||||
* SUMMARY: Show method for the formated_output sysfs node that will show
|
||||
* whether to format data to buffer or print directly.
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
* !0 = failure
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dev - pointer to device structure
|
||||
* *attr - pointer to device attributes
|
||||
* *buf - pointer to output buffer
|
||||
******************************************************************************/
|
||||
static ssize_t pt_formated_output_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct pt_debug_data *dd = pt_get_debug_data(dev);
|
||||
int val;
|
||||
|
||||
mutex_lock(&dd->sysfs_lock);
|
||||
val = dd->formated_output;
|
||||
mutex_unlock(&dd->sysfs_lock);
|
||||
|
||||
return scnprintf(buf, PT_MAX_PRBUF_SIZE,
|
||||
"Formated debug output: %x\n", val);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_formated_output_store
|
||||
*
|
||||
* SUMMARY: The store method for the formated_output sysfs node. Allows the
|
||||
* setting to format data to buffer or print directly.
|
||||
*
|
||||
* RETURN: Size of passed in buffer
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dev - pointer to device structure
|
||||
* *attr - pointer to device attributes
|
||||
* *buf - pointer to buffer that hold the command parameters
|
||||
* size - size of buf
|
||||
******************************************************************************/
|
||||
static ssize_t pt_formated_output_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
struct pt_debug_data *dd = pt_get_debug_data(dev);
|
||||
unsigned long value;
|
||||
int rc;
|
||||
|
||||
rc = kstrtoul(buf, 10, &value);
|
||||
if (rc < 0) {
|
||||
pt_debug(dev, DL_ERROR, "%s: Invalid value\n", __func__);
|
||||
return size;
|
||||
}
|
||||
|
||||
/* Expecting only 0 or 1 */
|
||||
if (value != 0 && value != 1) {
|
||||
pt_debug(dev, DL_ERROR, "%s: Invalid value %lu\n",
|
||||
__func__, value);
|
||||
return size;
|
||||
}
|
||||
|
||||
mutex_lock(&dd->sysfs_lock);
|
||||
dd->formated_output = value;
|
||||
mutex_unlock(&dd->sysfs_lock);
|
||||
return size;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(formated_output, 0600,
|
||||
pt_formated_output_show, pt_formated_output_store);
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_mt_probe
|
||||
*
|
||||
* SUMMARY: The probe function for debug module to create sysfs nodes and
|
||||
* subscribe attention list.
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dev - pointer to device structure
|
||||
* **data - double pointer tothe pt_debug_data structure to be created here
|
||||
******************************************************************************/
|
||||
static int pt_debug_probe(struct device *dev, void **data)
|
||||
{
|
||||
struct pt_debug_data *dd;
|
||||
int rc;
|
||||
|
||||
/* get context and debug print buffers */
|
||||
dd = kzalloc(sizeof(*dd), GFP_KERNEL);
|
||||
if (!dd) {
|
||||
rc = -ENOMEM;
|
||||
goto pt_debug_probe_alloc_failed;
|
||||
}
|
||||
|
||||
rc = device_create_file(dev, &dev_attr_int_count);
|
||||
if (rc) {
|
||||
pt_debug(dev, DL_ERROR, "%s: Error, could not create int_count\n",
|
||||
__func__);
|
||||
goto pt_debug_probe_create_int_count_failed;
|
||||
}
|
||||
|
||||
rc = device_create_file(dev, &dev_attr_formated_output);
|
||||
if (rc) {
|
||||
pt_debug(dev, DL_ERROR, "%s: Error, could not create formated_output\n",
|
||||
__func__);
|
||||
goto pt_debug_probe_create_formated_failed;
|
||||
}
|
||||
|
||||
mutex_init(&dd->sysfs_lock);
|
||||
dd->dev = dev;
|
||||
*data = dd;
|
||||
|
||||
dd->si = cmd->request_sysinfo(dev);
|
||||
if (!dd->si) {
|
||||
pt_debug(dev, DL_ERROR, "%s: Fail get sysinfo pointer from core\n",
|
||||
__func__);
|
||||
rc = -ENODEV;
|
||||
goto pt_debug_probe_sysinfo_failed;
|
||||
}
|
||||
|
||||
rc = cmd->subscribe_attention(dev, PT_ATTEN_IRQ, PT_DEBUG_NAME,
|
||||
pt_debug_attention, PT_MODE_OPERATIONAL);
|
||||
if (rc < 0) {
|
||||
pt_debug(dev, DL_ERROR, "%s: Error, could not subscribe attention cb\n",
|
||||
__func__);
|
||||
goto pt_debug_probe_subscribe_failed;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
pt_debug_probe_subscribe_failed:
|
||||
pt_debug_probe_sysinfo_failed:
|
||||
device_remove_file(dev, &dev_attr_formated_output);
|
||||
pt_debug_probe_create_formated_failed:
|
||||
device_remove_file(dev, &dev_attr_int_count);
|
||||
pt_debug_probe_create_int_count_failed:
|
||||
kfree(dd);
|
||||
pt_debug_probe_alloc_failed:
|
||||
pt_debug(dev, DL_ERROR, "%s failed.\n", __func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_debug_release
|
||||
*
|
||||
* SUMMARY: Remove function for debug module that does following cleanup:
|
||||
* - Unsubscibe all registered attention tasks
|
||||
* - Removes all created sysfs nodes
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dev - pointer to device structure
|
||||
* *data - pointer to the pt_debug_data structure
|
||||
******************************************************************************/
|
||||
static void pt_debug_release(struct device *dev, void *data)
|
||||
{
|
||||
struct pt_debug_data *dd = data;
|
||||
int rc;
|
||||
|
||||
rc = cmd->unsubscribe_attention(dev, PT_ATTEN_IRQ, PT_DEBUG_NAME,
|
||||
pt_debug_attention, PT_MODE_OPERATIONAL);
|
||||
if (rc < 0) {
|
||||
pt_debug(dev, DL_ERROR, "%s: Error, could not un-subscribe attention\n",
|
||||
__func__);
|
||||
goto pt_debug_release_exit;
|
||||
}
|
||||
|
||||
pt_debug_release_exit:
|
||||
device_remove_file(dev, &dev_attr_formated_output);
|
||||
device_remove_file(dev, &dev_attr_int_count);
|
||||
kfree(dd);
|
||||
}
|
||||
|
||||
static struct pt_module debug_module = {
|
||||
.name = PT_DEBUG_NAME,
|
||||
.probe = pt_debug_probe,
|
||||
.release = pt_debug_release,
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_debug_init
|
||||
*
|
||||
* SUMMARY: Initialize function for debug module which to register
|
||||
* debug_module into TTDL module list.
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
******************************************************************************/
|
||||
static int __init pt_debug_init(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
cmd = pt_get_commands();
|
||||
if (!cmd)
|
||||
return -EINVAL;
|
||||
|
||||
rc = pt_register_module(&debug_module);
|
||||
if (rc < 0) {
|
||||
pr_err("%s: Error, failed registering module\n",
|
||||
__func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
pr_info("%s: Parade TTSP Debug Driver (Built %s) rc=%d\n",
|
||||
__func__, PT_DRIVER_VERSION, rc);
|
||||
return 0;
|
||||
}
|
||||
module_init(pt_debug_init);
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_debug_exit
|
||||
*
|
||||
* SUMMARY: Exit function for debug module which to unregister debug_module
|
||||
* from TTDL module list.
|
||||
*
|
||||
******************************************************************************/
|
||||
static void __exit pt_debug_exit(void)
|
||||
{
|
||||
pt_unregister_module(&debug_module);
|
||||
}
|
||||
module_exit(pt_debug_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Parade TrueTouch(R) Standard Product Debug Driver");
|
||||
MODULE_AUTHOR("Parade Technologies <ttdrivers@paradetech.com>");
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,306 @@
|
|||
/*
|
||||
* pt_i2c.c
|
||||
* Parade TrueTouch(TM) Standard Product I2C Module.
|
||||
* For use with Parade touchscreen controllers.
|
||||
* Supported parts include:
|
||||
* TMA5XX
|
||||
* TMA448
|
||||
* TMA445A
|
||||
* TT21XXX
|
||||
* TT31XXX
|
||||
* TT4XXXX
|
||||
* TT7XXX
|
||||
* TC3XXX
|
||||
*
|
||||
* Copyright (C) 2015-2020 Parade Technologies
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2, and only version 2, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contact Parade Technologies at www.paradetech.com <ttdrivers@paradetech.com>
|
||||
*/
|
||||
|
||||
#include "pt_regs.h"
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
#define PT_I2C_DATA_SIZE (2 * 256)
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_i2c_read_default
|
||||
*
|
||||
* SUMMARY: Read a certain number of bytes from the I2C bus
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dev - pointer to Device structure
|
||||
* *buf - pointer to buffer where the data read will be stored
|
||||
* size - size to be read
|
||||
******************************************************************************/
|
||||
static int pt_i2c_read_default(struct device *dev, void *buf, int size)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
int rc;
|
||||
int read_size = size;
|
||||
|
||||
if (!buf || !size || size > PT_I2C_DATA_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
rc = i2c_master_recv(client, buf, read_size);
|
||||
|
||||
return (rc < 0) ? rc : rc != read_size ? -EIO : 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_i2c_read_default_nosize
|
||||
*
|
||||
* SUMMARY: Read from the I2C bus in two transactions first reading the HID
|
||||
* packet size (2 bytes) followed by reading the rest of the packet based
|
||||
* on the size initially read.
|
||||
* NOTE: The empty buffer 'size' was redefined in PIP version 1.7.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dev - pointer to Device structure
|
||||
* *buf - pointer to buffer where the data read will be stored
|
||||
* max - max size that can be read
|
||||
******************************************************************************/
|
||||
static int pt_i2c_read_default_nosize(struct device *dev, u8 *buf, u32 max)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct i2c_msg msgs[2];
|
||||
u8 msg_count = 1;
|
||||
int rc;
|
||||
u32 size;
|
||||
|
||||
if (!buf)
|
||||
return -EINVAL;
|
||||
|
||||
msgs[0].addr = client->addr;
|
||||
msgs[0].flags = (client->flags & I2C_M_TEN) | I2C_M_RD;
|
||||
msgs[0].len = 2;
|
||||
msgs[0].buf = buf;
|
||||
rc = i2c_transfer(client->adapter, msgs, msg_count);
|
||||
if (rc < 0 || rc != msg_count)
|
||||
return (rc < 0) ? rc : -EIO;
|
||||
|
||||
size = get_unaligned_le16(&buf[0]);
|
||||
if (!size || size == 2 || size >= PT_PIP_1P7_EMPTY_BUF)
|
||||
/*
|
||||
* Before PIP 1.7, empty buffer is 0x0002;
|
||||
* From PIP 1.7, empty buffer is 0xFFXX
|
||||
*/
|
||||
return 0;
|
||||
|
||||
if (size > max)
|
||||
return -EINVAL;
|
||||
|
||||
rc = i2c_master_recv(client, buf, size);
|
||||
return (rc < 0) ? rc : rc != (int)size ? -EIO : 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_i2c_write_read_specific
|
||||
*
|
||||
* SUMMARY: Write the contents of write_buf to the I2C device and then read
|
||||
* the response using pt_i2c_read_default_nosize()
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dev - pointer to Device structure
|
||||
* write_len - length of data buffer write_buf
|
||||
* *write_buf - pointer to buffer to write
|
||||
* *read_buf - pointer to buffer to read response into
|
||||
******************************************************************************/
|
||||
static int pt_i2c_write_read_specific(struct device *dev, u16 write_len,
|
||||
u8 *write_buf, u8 *read_buf)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct i2c_msg msgs[2];
|
||||
u8 msg_count = 1;
|
||||
int rc;
|
||||
|
||||
/* Ensure no packet larger than what the PIP spec allows */
|
||||
if (write_len > PT_MAX_PIP2_MSG_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
if (!write_buf || !write_len) {
|
||||
if (!write_buf)
|
||||
pt_debug(dev, DL_ERROR,
|
||||
"%s write_buf is NULL", __func__);
|
||||
if (!write_len)
|
||||
pt_debug(dev, DL_ERROR,
|
||||
"%s write_len is NULL", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
msgs[0].addr = client->addr;
|
||||
msgs[0].flags = client->flags & I2C_M_TEN;
|
||||
msgs[0].len = write_len;
|
||||
msgs[0].buf = write_buf;
|
||||
rc = i2c_transfer(client->adapter, msgs, msg_count);
|
||||
|
||||
if (rc < 0 || rc != msg_count)
|
||||
return (rc < 0) ? rc : -EIO;
|
||||
|
||||
rc = 0;
|
||||
|
||||
if (read_buf) {
|
||||
rc = pt_i2c_read_default_nosize(dev, read_buf,
|
||||
PT_I2C_DATA_SIZE);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static struct pt_bus_ops pt_i2c_bus_ops = {
|
||||
.bustype = BUS_I2C,
|
||||
.read_default = pt_i2c_read_default,
|
||||
.read_default_nosize = pt_i2c_read_default_nosize,
|
||||
.write_read_specific = pt_i2c_write_read_specific,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_TOUCHSCREEN_PARADE_DEVICETREE_SUPPORT
|
||||
static const struct of_device_id pt_i2c_of_match[] = {
|
||||
{ .compatible = "parade,pt_i2c_adapter", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, pt_i2c_of_match);
|
||||
#endif
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_i2c_probe
|
||||
*
|
||||
* SUMMARY: Probe functon for the I2C module
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *client - pointer to i2c client structure
|
||||
* *i2c_id - pointer to i2c device structure
|
||||
******************************************************************************/
|
||||
static int pt_i2c_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *i2c_id)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
#ifdef CONFIG_TOUCHSCREEN_PARADE_DEVICETREE_SUPPORT
|
||||
const struct of_device_id *match;
|
||||
#endif
|
||||
int rc;
|
||||
|
||||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
|
||||
pt_debug(dev, DL_ERROR, "I2C functionality not Supported\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TOUCHSCREEN_PARADE_DEVICETREE_SUPPORT
|
||||
match = of_match_device(of_match_ptr(pt_i2c_of_match), dev);
|
||||
if (match) {
|
||||
rc = pt_devtree_create_and_get_pdata(dev);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
rc = pt_probe(&pt_i2c_bus_ops, &client->dev, client->irq,
|
||||
PT_I2C_DATA_SIZE);
|
||||
|
||||
#ifdef CONFIG_TOUCHSCREEN_PARADE_DEVICETREE_SUPPORT
|
||||
if (rc && match)
|
||||
pt_devtree_clean_pdata(dev);
|
||||
#endif
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_i2c_remove
|
||||
*
|
||||
* SUMMARY: Remove functon for the I2C module
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *client - pointer to i2c client structure
|
||||
******************************************************************************/
|
||||
static int pt_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
#ifdef CONFIG_TOUCHSCREEN_PARADE_DEVICETREE_SUPPORT
|
||||
const struct of_device_id *match;
|
||||
#endif
|
||||
struct device *dev = &client->dev;
|
||||
struct pt_core_data *cd = i2c_get_clientdata(client);
|
||||
|
||||
pt_release(cd);
|
||||
|
||||
#ifdef CONFIG_TOUCHSCREEN_PARADE_DEVICETREE_SUPPORT
|
||||
match = of_match_device(of_match_ptr(pt_i2c_of_match), dev);
|
||||
if (match)
|
||||
pt_devtree_clean_pdata(dev);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id pt_i2c_id[] = {
|
||||
{ PT_I2C_NAME, 0, },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, pt_i2c_id);
|
||||
|
||||
static struct i2c_driver pt_i2c_driver = {
|
||||
.driver = {
|
||||
.name = PT_I2C_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &pt_pm_ops,
|
||||
#ifdef CONFIG_TOUCHSCREEN_PARADE_DEVICETREE_SUPPORT
|
||||
.of_match_table = pt_i2c_of_match,
|
||||
#endif
|
||||
},
|
||||
.probe = pt_i2c_probe,
|
||||
.remove = pt_i2c_remove,
|
||||
.id_table = pt_i2c_id,
|
||||
};
|
||||
|
||||
#if (KERNEL_VERSION(3, 3, 0) <= LINUX_VERSION_CODE)
|
||||
module_i2c_driver(pt_i2c_driver);
|
||||
#else
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_i2c_init
|
||||
*
|
||||
* SUMMARY: Initialize function to register i2c module to kernel.
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
* !0 = failure
|
||||
******************************************************************************/
|
||||
static int __init pt_i2c_init(void)
|
||||
{
|
||||
int rc = i2c_add_driver(&pt_i2c_driver);
|
||||
|
||||
pr_info("%s: Parade TTDL I2C Driver (Build %s) rc=%d\n",
|
||||
__func__, PT_DRIVER_VERSION, rc);
|
||||
return rc;
|
||||
}
|
||||
module_init(pt_i2c_init);
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_i2c_exit
|
||||
*
|
||||
* SUMMARY: Exit function to unregister i2c module from kernel.
|
||||
*
|
||||
******************************************************************************/
|
||||
static void __exit pt_i2c_exit(void)
|
||||
{
|
||||
i2c_del_driver(&pt_i2c_driver);
|
||||
}
|
||||
module_exit(pt_i2c_exit);
|
||||
#endif
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Parade TrueTouch(R) Standard Product I2C driver");
|
||||
MODULE_AUTHOR("Parade Technologies <ttdrivers@paradetech.com>");
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,998 @@
|
|||
/*
|
||||
* pt_mt_common.c
|
||||
* Parade TrueTouch(TM) Standard Product Multi-Touch Reports Module.
|
||||
* For use with Parade touchscreen controllers.
|
||||
* Supported parts include:
|
||||
* TMA5XX
|
||||
* TMA448
|
||||
* TMA445A
|
||||
* TT21XXX
|
||||
* TT31XXX
|
||||
* TT4XXXX
|
||||
* TT7XXX
|
||||
* TC3XXX
|
||||
*
|
||||
* Copyright (C) 2015-2020 Parade Technologies
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2, and only version 2, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contact Parade Technologies at www.paradetech.com <ttdrivers@paradetech.com>
|
||||
*/
|
||||
|
||||
#include "pt_regs.h"
|
||||
|
||||
#define MT_PARAM_SIGNAL(md, sig_ost) PARAM_SIGNAL(md->pdata->frmwrk, sig_ost)
|
||||
#define MT_PARAM_MIN(md, sig_ost) PARAM_MIN(md->pdata->frmwrk, sig_ost)
|
||||
#define MT_PARAM_MAX(md, sig_ost) PARAM_MAX(md->pdata->frmwrk, sig_ost)
|
||||
#define MT_PARAM_FUZZ(md, sig_ost) PARAM_FUZZ(md->pdata->frmwrk, sig_ost)
|
||||
#define MT_PARAM_FLAT(md, sig_ost) PARAM_FLAT(md->pdata->frmwrk, sig_ost)
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_mt_lift_all
|
||||
*
|
||||
* SUMMARY: Reports touch liftoff action
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *md - pointer to touch data structure
|
||||
******************************************************************************/
|
||||
static void pt_mt_lift_all(struct pt_mt_data *md)
|
||||
{
|
||||
int max = md->si->tch_abs[PT_TCH_T].max;
|
||||
|
||||
if (md->num_prv_rec != 0) {
|
||||
if (md->mt_function.report_slot_liftoff)
|
||||
md->mt_function.report_slot_liftoff(md, max);
|
||||
input_sync(md->input);
|
||||
md->num_prv_rec = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_get_touch_axis
|
||||
*
|
||||
* SUMMARY: Calculates touch axis
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *md - pointer to touch data structure
|
||||
* *axis - pointer to axis calculation result
|
||||
* size - size in byte
|
||||
* max - max value of result
|
||||
* *xy_data - pointer to input data to be parsed
|
||||
* bofs - bit offset
|
||||
******************************************************************************/
|
||||
static void pt_get_touch_axis(struct pt_mt_data *md,
|
||||
int *axis, int size, int max, u8 *xy_data, int bofs)
|
||||
{
|
||||
int nbyte;
|
||||
int next;
|
||||
|
||||
for (nbyte = 0, *axis = 0, next = 0; nbyte < size; nbyte++) {
|
||||
pt_debug(md->dev, DL_DEBUG,
|
||||
"%s: *axis=%02X(%d) size=%d max=%08X xy_data=%p xy_data[%d]=%02X(%d) bofs=%d\n",
|
||||
__func__, *axis, *axis, size, max, xy_data, next,
|
||||
xy_data[next], xy_data[next], bofs);
|
||||
*axis = *axis + ((xy_data[next] >> bofs) << (nbyte * 8));
|
||||
next++;
|
||||
}
|
||||
|
||||
*axis &= max - 1;
|
||||
|
||||
pt_debug(md->dev, DL_DEBUG,
|
||||
"%s: *axis=%02X(%d) size=%d max=%08X xy_data=%p xy_data[%d]=%02X(%d)\n",
|
||||
__func__, *axis, *axis, size, max, xy_data, next,
|
||||
xy_data[next], xy_data[next]);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_get_touch_hdr
|
||||
*
|
||||
* SUMMARY: Get the header of touch report
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *md - pointer to touch data structure
|
||||
* *touch - pointer to pt_touch structure
|
||||
* *xy_mode - pointer to touch mode data
|
||||
******************************************************************************/
|
||||
static void pt_get_touch_hdr(struct pt_mt_data *md,
|
||||
struct pt_touch *touch, u8 *xy_mode)
|
||||
{
|
||||
struct device *dev = md->dev;
|
||||
struct pt_sysinfo *si = md->si;
|
||||
enum pt_tch_hdr hdr;
|
||||
|
||||
for (hdr = PT_TCH_TIME; hdr < PT_TCH_NUM_HDR; hdr++) {
|
||||
if (!si->tch_hdr[hdr].report)
|
||||
continue;
|
||||
pt_get_touch_axis(md, &touch->hdr[hdr],
|
||||
si->tch_hdr[hdr].size,
|
||||
si->tch_hdr[hdr].max,
|
||||
xy_mode + si->tch_hdr[hdr].ofs,
|
||||
si->tch_hdr[hdr].bofs);
|
||||
pt_debug(dev, DL_DEBUG, "%s: get %s=%04X(%d)\n",
|
||||
__func__, pt_tch_hdr_string[hdr],
|
||||
touch->hdr[hdr], touch->hdr[hdr]);
|
||||
}
|
||||
|
||||
pt_debug(dev, DL_INFO,
|
||||
"%s: time=%X tch_num=%d lo=%d noise=%d counter=%d\n",
|
||||
__func__,
|
||||
touch->hdr[PT_TCH_TIME],
|
||||
touch->hdr[PT_TCH_NUM],
|
||||
touch->hdr[PT_TCH_LO],
|
||||
touch->hdr[PT_TCH_NOISE],
|
||||
touch->hdr[PT_TCH_COUNTER]);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_get_touch_record
|
||||
*
|
||||
* SUMMARY: Gets axis of touch report
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *md - pointer to touch data structure
|
||||
* *touch - pointer to pt_touch structure
|
||||
* *xy_data - pointer to touch data
|
||||
******************************************************************************/
|
||||
static void pt_get_touch_record(struct pt_mt_data *md,
|
||||
struct pt_touch *touch, u8 *xy_data)
|
||||
{
|
||||
struct device *dev = md->dev;
|
||||
struct pt_sysinfo *si = md->si;
|
||||
enum pt_tch_abs abs;
|
||||
|
||||
for (abs = PT_TCH_X; abs < PT_TCH_NUM_ABS; abs++) {
|
||||
if (!si->tch_abs[abs].report)
|
||||
continue;
|
||||
pt_get_touch_axis(md, &touch->abs[abs],
|
||||
si->tch_abs[abs].size,
|
||||
si->tch_abs[abs].max,
|
||||
xy_data + si->tch_abs[abs].ofs,
|
||||
si->tch_abs[abs].bofs);
|
||||
pt_debug(dev, DL_DEBUG, "%s: get %s=%04X(%d)\n",
|
||||
__func__, pt_tch_abs_string[abs],
|
||||
touch->abs[abs], touch->abs[abs]);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_mt_process_touch
|
||||
*
|
||||
* SUMMARY: Process touch includes oritation,axis invert and
|
||||
* convert MAJOR/MINOR from mm to resolution
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *md - pointer to touch data structure
|
||||
* *touch - pointer to pt_touch structure
|
||||
******************************************************************************/
|
||||
static void pt_mt_process_touch(struct pt_mt_data *md,
|
||||
struct pt_touch *touch)
|
||||
{
|
||||
struct device *dev = md->dev;
|
||||
struct pt_sysinfo *si = md->si;
|
||||
int tmp;
|
||||
bool flipped;
|
||||
|
||||
|
||||
/* Orientation is signed */
|
||||
touch->abs[PT_TCH_OR] = (int8_t)touch->abs[PT_TCH_OR];
|
||||
|
||||
if (md->pdata->flags & PT_MT_FLAG_FLIP) {
|
||||
tmp = touch->abs[PT_TCH_X];
|
||||
touch->abs[PT_TCH_X] = touch->abs[PT_TCH_Y];
|
||||
touch->abs[PT_TCH_Y] = tmp;
|
||||
if (touch->abs[PT_TCH_OR] > 0)
|
||||
touch->abs[PT_TCH_OR] =
|
||||
md->or_max - touch->abs[PT_TCH_OR];
|
||||
else
|
||||
touch->abs[PT_TCH_OR] =
|
||||
md->or_min - touch->abs[PT_TCH_OR];
|
||||
flipped = true;
|
||||
} else
|
||||
flipped = false;
|
||||
|
||||
/*
|
||||
* 1 is subtracted from each touch location to make the location
|
||||
* 0 based. e.g. If the resolution of touch panel is 1200x1600,
|
||||
* the FW touch report must be (0~1199,0~1599). The driver
|
||||
* should register the (min,max) value to Linux input system as
|
||||
* (0~1199,0~1599). When the host needs to invert the
|
||||
* coordinates, the driver would incorrectly use the resolution
|
||||
* to subtract the reported point directly, such as
|
||||
* 1200-(0~1199). The input system will lose the 0 point report
|
||||
* and the 1200 point will be ignored.
|
||||
*/
|
||||
if (md->pdata->flags & PT_MT_FLAG_INV_X) {
|
||||
if (flipped)
|
||||
touch->abs[PT_TCH_X] = si->sensing_conf_data.res_y -
|
||||
touch->abs[PT_TCH_X] - 1;
|
||||
else
|
||||
touch->abs[PT_TCH_X] = si->sensing_conf_data.res_x -
|
||||
touch->abs[PT_TCH_X] - 1;
|
||||
touch->abs[PT_TCH_OR] *= -1;
|
||||
}
|
||||
if (md->pdata->flags & PT_MT_FLAG_INV_Y) {
|
||||
if (flipped)
|
||||
touch->abs[PT_TCH_Y] = si->sensing_conf_data.res_x -
|
||||
touch->abs[PT_TCH_Y] - 1;
|
||||
else
|
||||
touch->abs[PT_TCH_Y] = si->sensing_conf_data.res_y -
|
||||
touch->abs[PT_TCH_Y] - 1;
|
||||
touch->abs[PT_TCH_OR] *= -1;
|
||||
}
|
||||
|
||||
/* Convert MAJOR/MINOR from mm to resolution */
|
||||
tmp = touch->abs[PT_TCH_MAJ] * 100 * si->sensing_conf_data.res_x;
|
||||
touch->abs[PT_TCH_MAJ] = tmp / si->sensing_conf_data.len_x;
|
||||
tmp = touch->abs[PT_TCH_MIN] * 100 * si->sensing_conf_data.res_x;
|
||||
touch->abs[PT_TCH_MIN] = tmp / si->sensing_conf_data.len_x;
|
||||
|
||||
pt_debug(dev, DL_INFO,
|
||||
"%s: flip=%s inv-x=%s inv-y=%s x=%04X(%d) y=%04X(%d)\n",
|
||||
__func__, flipped ? "true" : "false",
|
||||
md->pdata->flags & PT_MT_FLAG_INV_X ? "true" : "false",
|
||||
md->pdata->flags & PT_MT_FLAG_INV_Y ? "true" : "false",
|
||||
touch->abs[PT_TCH_X], touch->abs[PT_TCH_X],
|
||||
touch->abs[PT_TCH_Y], touch->abs[PT_TCH_Y]);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_report_event
|
||||
*
|
||||
* SUMMARY: Reports touch event
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *md - pointer to touch data structure
|
||||
* event - type of touch event
|
||||
* value - value of report event
|
||||
******************************************************************************/
|
||||
static void pt_report_event(struct pt_mt_data *md, int event,
|
||||
int value)
|
||||
{
|
||||
int sig = MT_PARAM_SIGNAL(md, event);
|
||||
|
||||
if (sig != PT_IGNORE_VALUE)
|
||||
input_report_abs(md->input, sig, value);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_get_mt_touches
|
||||
*
|
||||
* SUMMARY: Parse and report touch event
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *md - pointer to touch data structure
|
||||
* *tch - pointer to touch structure
|
||||
* num_cur_tch - number of current touch
|
||||
******************************************************************************/
|
||||
static void pt_get_mt_touches(struct pt_mt_data *md,
|
||||
struct pt_touch *tch, int num_cur_tch)
|
||||
{
|
||||
struct device *dev = md->dev;
|
||||
struct pt_sysinfo *si = md->si;
|
||||
int sig;
|
||||
int i, j, t = 0;
|
||||
DECLARE_BITMAP(ids, si->tch_abs[PT_TCH_T].max);
|
||||
int mt_sync_count = 0;
|
||||
u8 *tch_addr;
|
||||
|
||||
bitmap_zero(ids, si->tch_abs[PT_TCH_T].max);
|
||||
memset(tch->abs, 0, sizeof(tch->abs));
|
||||
|
||||
for (i = 0; i < num_cur_tch; i++) {
|
||||
tch_addr = si->xy_data + (i * si->desc.tch_record_size);
|
||||
pt_get_touch_record(md, tch, tch_addr);
|
||||
|
||||
/* Discard proximity event */
|
||||
if (tch->abs[PT_TCH_O] == PT_OBJ_PROXIMITY) {
|
||||
pt_debug(dev, DL_INFO,
|
||||
"%s: Discarding proximity event\n",
|
||||
__func__);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Validate track_id */
|
||||
t = tch->abs[PT_TCH_T];
|
||||
if (t < md->t_min || t > md->t_max) {
|
||||
pt_debug(dev, DL_INFO,
|
||||
"%s: tch=%d -> bad trk_id=%d max_id=%d\n",
|
||||
__func__, i, t, md->t_max);
|
||||
if (md->mt_function.input_sync)
|
||||
md->mt_function.input_sync(md->input);
|
||||
mt_sync_count++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Lift-off */
|
||||
if (tch->abs[PT_TCH_E] == PT_EV_LIFTOFF) {
|
||||
pt_debug(dev, DL_INFO, "%s: t=%d e=%d lift-off\n",
|
||||
__func__, t, tch->abs[PT_TCH_E]);
|
||||
goto pt_get_mt_touches_pr_tch;
|
||||
}
|
||||
|
||||
/* Process touch */
|
||||
pt_mt_process_touch(md, tch);
|
||||
|
||||
/* use 0 based track id's */
|
||||
t -= md->t_min;
|
||||
|
||||
sig = MT_PARAM_SIGNAL(md, PT_ABS_ID_OST);
|
||||
if (sig != PT_IGNORE_VALUE) {
|
||||
if (md->mt_function.input_report)
|
||||
md->mt_function.input_report(md->input, sig,
|
||||
t, tch->abs[PT_TCH_O]);
|
||||
__set_bit(t, ids);
|
||||
}
|
||||
|
||||
pt_report_event(md, PT_ABS_D_OST, 0);
|
||||
|
||||
/* all devices: position and pressure fields */
|
||||
for (j = 0; j <= PT_ABS_W_OST; j++) {
|
||||
if (!si->tch_abs[j].report)
|
||||
continue;
|
||||
pt_report_event(md, PT_ABS_X_OST + j,
|
||||
tch->abs[PT_TCH_X + j]);
|
||||
}
|
||||
|
||||
/* Get the extended touch fields */
|
||||
for (j = 0; j < PT_NUM_EXT_TCH_FIELDS; j++) {
|
||||
if (!si->tch_abs[PT_ABS_MAJ_OST + j].report)
|
||||
continue;
|
||||
pt_report_event(md, PT_ABS_MAJ_OST + j,
|
||||
tch->abs[PT_TCH_MAJ + j]);
|
||||
}
|
||||
if (md->mt_function.input_sync)
|
||||
md->mt_function.input_sync(md->input);
|
||||
mt_sync_count++;
|
||||
|
||||
pt_get_mt_touches_pr_tch:
|
||||
pt_debug(dev, DL_INFO,
|
||||
"%s: t=%d x=%d y=%d z=%d M=%d m=%d o=%d e=%d obj=%d tip=%d\n",
|
||||
__func__, t,
|
||||
tch->abs[PT_TCH_X],
|
||||
tch->abs[PT_TCH_Y],
|
||||
tch->abs[PT_TCH_P],
|
||||
tch->abs[PT_TCH_MAJ],
|
||||
tch->abs[PT_TCH_MIN],
|
||||
tch->abs[PT_TCH_OR],
|
||||
tch->abs[PT_TCH_E],
|
||||
tch->abs[PT_TCH_O],
|
||||
tch->abs[PT_TCH_TIP]);
|
||||
}
|
||||
|
||||
if (md->mt_function.final_sync)
|
||||
md->mt_function.final_sync(md->input,
|
||||
si->tch_abs[PT_TCH_T].max, mt_sync_count, ids);
|
||||
|
||||
md->num_prv_rec = num_cur_tch;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_xy_worker
|
||||
*
|
||||
* SUMMARY: Read xy_data for all current touches
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
* !0 = failure
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *md - pointer to touch data structure
|
||||
******************************************************************************/
|
||||
static int pt_xy_worker(struct pt_mt_data *md)
|
||||
{
|
||||
struct device *dev = md->dev;
|
||||
struct pt_sysinfo *si = md->si;
|
||||
int max_tch = si->sensing_conf_data.max_tch;
|
||||
struct pt_touch tch;
|
||||
u8 num_cur_tch;
|
||||
int rc = 0;
|
||||
|
||||
pt_get_touch_hdr(md, &tch, si->xy_mode + 3);
|
||||
|
||||
num_cur_tch = tch.hdr[PT_TCH_NUM];
|
||||
if (num_cur_tch > max_tch) {
|
||||
pt_debug(dev, DL_ERROR, "%s: Num touch err detected (n=%d)\n",
|
||||
__func__, num_cur_tch);
|
||||
num_cur_tch = max_tch;
|
||||
}
|
||||
|
||||
if (tch.hdr[PT_TCH_LO]) {
|
||||
pt_debug(dev, DL_INFO, "%s: Large area detected\n",
|
||||
__func__);
|
||||
if (md->pdata->flags & PT_MT_FLAG_NO_TOUCH_ON_LO)
|
||||
num_cur_tch = 0;
|
||||
}
|
||||
|
||||
if (num_cur_tch == 0 && md->num_prv_rec == 0)
|
||||
goto pt_xy_worker_exit;
|
||||
|
||||
/* extract xy_data for all currently reported touches */
|
||||
pt_debug(dev, DL_DEBUG, "%s: extract data num_cur_tch=%d\n",
|
||||
__func__, num_cur_tch);
|
||||
if (num_cur_tch)
|
||||
pt_get_mt_touches(md, &tch, num_cur_tch);
|
||||
else
|
||||
pt_mt_lift_all(md);
|
||||
|
||||
rc = 0;
|
||||
|
||||
pt_xy_worker_exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_mt_send_dummy_event
|
||||
*
|
||||
* SUMMARY: Send dummy/key event to wakeup upper layer of system
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *cd - pointer to core data structure
|
||||
* *md - pointer to touch data structure
|
||||
******************************************************************************/
|
||||
static void pt_mt_send_dummy_event(struct pt_core_data *cd,
|
||||
struct pt_mt_data *md)
|
||||
{
|
||||
#ifndef EASYWAKE_TSG6
|
||||
/* TSG5 EasyWake */
|
||||
unsigned long ids = 0;
|
||||
|
||||
/* for easy wakeup */
|
||||
if (md->mt_function.input_report)
|
||||
md->mt_function.input_report(md->input, ABS_MT_TRACKING_ID,
|
||||
0, PT_OBJ_STANDARD_FINGER);
|
||||
if (md->mt_function.input_sync)
|
||||
md->mt_function.input_sync(md->input);
|
||||
if (md->mt_function.final_sync)
|
||||
md->mt_function.final_sync(md->input, 0, 1, &ids);
|
||||
if (md->mt_function.report_slot_liftoff)
|
||||
md->mt_function.report_slot_liftoff(md, 1);
|
||||
if (md->mt_function.final_sync)
|
||||
md->mt_function.final_sync(md->input, 1, 1, &ids);
|
||||
#else
|
||||
/* TSG6 FW1.3 and above only. TSG6 FW1.0 - 1.2 does not */
|
||||
/* support EasyWake, and this function will not be called */
|
||||
u8 key_value = 0;
|
||||
|
||||
switch (cd->gesture_id) {
|
||||
case GESTURE_DOUBLE_TAP:
|
||||
key_value = KEY_F1;
|
||||
break;
|
||||
case GESTURE_TWO_FINGERS_SLIDE:
|
||||
key_value = KEY_F2;
|
||||
break;
|
||||
case GESTURE_TOUCH_DETECTED:
|
||||
key_value = KEY_F3;
|
||||
break;
|
||||
case GESTURE_PUSH_BUTTON:
|
||||
key_value = KEY_F4;
|
||||
break;
|
||||
case GESTURE_SINGLE_SLIDE_DE_TX:
|
||||
key_value = KEY_F5;
|
||||
break;
|
||||
case GESTURE_SINGLE_SLIDE_IN_TX:
|
||||
key_value = KEY_F6;
|
||||
break;
|
||||
case GESTURE_SINGLE_SLIDE_DE_RX:
|
||||
key_value = KEY_F7;
|
||||
break;
|
||||
case GESTURE_SINGLE_SLIDE_IN_RX:
|
||||
key_value = KEY_F8;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (key_value > 0) {
|
||||
input_report_key(md->input, key_value, 1);
|
||||
mdelay(10);
|
||||
input_report_key(md->input, key_value, 0);
|
||||
input_sync(md->input);
|
||||
}
|
||||
|
||||
/*
|
||||
* Caution - this debug print is needed by the TTDL automated
|
||||
* regression test suite
|
||||
*/
|
||||
pt_debug(md->dev, DL_INFO, "%s: report key: %d\n",
|
||||
__func__, key_value);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_mt_attention
|
||||
*
|
||||
* SUMMARY: Wrapper function for pt_xy_worker() that subscribe into the TTDL
|
||||
* attention list.
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
* !0 = failure
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dev - pointer to device structure
|
||||
******************************************************************************/
|
||||
static int pt_mt_attention(struct device *dev)
|
||||
{
|
||||
struct pt_core_data *cd = dev_get_drvdata(dev);
|
||||
struct pt_mt_data *md = &cd->md;
|
||||
int rc;
|
||||
|
||||
if (md->si->xy_mode[2] != md->si->desc.tch_report_id)
|
||||
return 0;
|
||||
|
||||
/* core handles handshake */
|
||||
mutex_lock(&md->mt_lock);
|
||||
rc = pt_xy_worker(md);
|
||||
mutex_unlock(&md->mt_lock);
|
||||
if (rc < 0)
|
||||
pt_debug(dev, DL_ERROR,
|
||||
"%s: xy_worker error r=%d\n", __func__, rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_mt_wake_attention
|
||||
*
|
||||
* SUMMARY: Wrapper function for pt_mt_send_dummy_event() that register to
|
||||
* attention list.
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dev - pointer to device structure
|
||||
******************************************************************************/
|
||||
static int pt_mt_wake_attention(struct device *dev)
|
||||
{
|
||||
struct pt_core_data *cd = dev_get_drvdata(dev);
|
||||
struct pt_mt_data *md = &cd->md;
|
||||
|
||||
mutex_lock(&md->mt_lock);
|
||||
pt_mt_send_dummy_event(cd, md);
|
||||
mutex_unlock(&md->mt_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_startup_attention
|
||||
*
|
||||
* SUMMARY: Wrapper function for pt_mt_lift_all() that subcribe into the TTDL
|
||||
* attention list.
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dev - pointer to device structure
|
||||
******************************************************************************/
|
||||
static int pt_startup_attention(struct device *dev)
|
||||
{
|
||||
struct pt_core_data *cd = dev_get_drvdata(dev);
|
||||
struct pt_mt_data *md = &cd->md;
|
||||
|
||||
mutex_lock(&md->mt_lock);
|
||||
pt_mt_lift_all(md);
|
||||
mutex_unlock(&md->mt_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_mt_suspend_attention
|
||||
*
|
||||
* SUMMARY: Function for touch to enter suspend state that as following steps:
|
||||
* 1) Lift all touch
|
||||
* 2) Set flag with suspend state
|
||||
* 3) Decrese pm system count
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dev - pointer to device structure
|
||||
******************************************************************************/
|
||||
static int pt_mt_suspend_attention(struct device *dev)
|
||||
{
|
||||
struct pt_core_data *cd = dev_get_drvdata(dev);
|
||||
struct pt_mt_data *md = &cd->md;
|
||||
|
||||
mutex_lock(&md->mt_lock);
|
||||
pt_mt_lift_all(md);
|
||||
md->is_suspended = true;
|
||||
mutex_unlock(&md->mt_lock);
|
||||
|
||||
pm_runtime_put(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_mt_resume_attention
|
||||
*
|
||||
* SUMMARY: Function for touch to leave suspend state that as following steps:
|
||||
* 1) Increse pm system count
|
||||
* 2) Clear suspend state flag
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dev - pointer to device structure
|
||||
******************************************************************************/
|
||||
static int pt_mt_resume_attention(struct device *dev)
|
||||
{
|
||||
struct pt_core_data *cd = dev_get_drvdata(dev);
|
||||
struct pt_mt_data *md = &cd->md;
|
||||
|
||||
pm_runtime_get(dev);
|
||||
|
||||
mutex_lock(&md->mt_lock);
|
||||
md->is_suspended = false;
|
||||
mutex_unlock(&md->mt_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_mt_open
|
||||
*
|
||||
* SUMMARY: Open method for input device(touch) that sets up call back
|
||||
* functions to TTDL attention list
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *input - pointer to input_dev structure
|
||||
******************************************************************************/
|
||||
static int pt_mt_open(struct input_dev *input)
|
||||
{
|
||||
struct device *dev = input->dev.parent;
|
||||
struct pt_core_data *cd = dev_get_drvdata(dev);
|
||||
struct pt_mt_data *md = &cd->md;
|
||||
|
||||
pm_runtime_get_sync(dev);
|
||||
|
||||
mutex_lock(&md->mt_lock);
|
||||
md->is_suspended = false;
|
||||
mutex_unlock(&md->mt_lock);
|
||||
|
||||
pt_debug(dev, DL_INFO, "%s: setup subscriptions\n", __func__);
|
||||
|
||||
/* set up touch call back */
|
||||
_pt_subscribe_attention(dev, PT_ATTEN_IRQ, PT_MT_NAME,
|
||||
pt_mt_attention, PT_MODE_OPERATIONAL);
|
||||
|
||||
/* set up startup call back */
|
||||
_pt_subscribe_attention(dev, PT_ATTEN_STARTUP, PT_MT_NAME,
|
||||
pt_startup_attention, 0);
|
||||
|
||||
/* set up wakeup call back */
|
||||
_pt_subscribe_attention(dev, PT_ATTEN_WAKE, PT_MT_NAME,
|
||||
pt_mt_wake_attention, 0);
|
||||
|
||||
/* set up suspend call back */
|
||||
_pt_subscribe_attention(dev, PT_ATTEN_SUSPEND, PT_MT_NAME,
|
||||
pt_mt_suspend_attention, 0);
|
||||
|
||||
/* set up resume call back */
|
||||
_pt_subscribe_attention(dev, PT_ATTEN_RESUME, PT_MT_NAME,
|
||||
pt_mt_resume_attention, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_mt_close
|
||||
*
|
||||
* SUMMARY: Close method for input device(touch) that clears call back
|
||||
* functions from TTDL attention list.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *input - pointer to input_dev structure
|
||||
******************************************************************************/
|
||||
static void pt_mt_close(struct input_dev *input)
|
||||
{
|
||||
struct device *dev = input->dev.parent;
|
||||
struct pt_core_data *cd = dev_get_drvdata(dev);
|
||||
struct pt_mt_data *md = &cd->md;
|
||||
|
||||
_pt_unsubscribe_attention(dev, PT_ATTEN_IRQ, PT_MT_NAME,
|
||||
pt_mt_attention, PT_MODE_OPERATIONAL);
|
||||
|
||||
_pt_unsubscribe_attention(dev, PT_ATTEN_STARTUP, PT_MT_NAME,
|
||||
pt_startup_attention, 0);
|
||||
|
||||
_pt_unsubscribe_attention(dev, PT_ATTEN_WAKE, PT_MT_NAME,
|
||||
pt_mt_wake_attention, 0);
|
||||
|
||||
_pt_unsubscribe_attention(dev, PT_ATTEN_SUSPEND, PT_MT_NAME,
|
||||
pt_mt_suspend_attention, 0);
|
||||
|
||||
_pt_unsubscribe_attention(dev, PT_ATTEN_RESUME, PT_MT_NAME,
|
||||
pt_mt_resume_attention, 0);
|
||||
|
||||
mutex_lock(&md->mt_lock);
|
||||
if (!md->is_suspended) {
|
||||
pm_runtime_put(dev);
|
||||
md->is_suspended = true;
|
||||
}
|
||||
mutex_unlock(&md->mt_lock);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_setup_input_device
|
||||
*
|
||||
* SUMMARY: Set up resolution, event signal capabilities and
|
||||
* register input device for touch.
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
* !0 = failure
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dev - pointer to device structure
|
||||
******************************************************************************/
|
||||
static int pt_setup_input_device(struct device *dev)
|
||||
{
|
||||
struct pt_core_data *cd = dev_get_drvdata(dev);
|
||||
struct pt_mt_data *md = &cd->md;
|
||||
int signal = PT_IGNORE_VALUE;
|
||||
int max_x, max_y, max_p, min, max;
|
||||
int max_x_tmp, max_y_tmp;
|
||||
int i;
|
||||
int rc;
|
||||
|
||||
pt_debug(dev, DL_INFO, "%s: Initialize event signals\n",
|
||||
__func__);
|
||||
__set_bit(EV_ABS, md->input->evbit);
|
||||
__set_bit(EV_REL, md->input->evbit);
|
||||
__set_bit(EV_KEY, md->input->evbit);
|
||||
#ifdef INPUT_PROP_DIRECT
|
||||
__set_bit(INPUT_PROP_DIRECT, md->input->propbit);
|
||||
#endif
|
||||
|
||||
/* If virtualkeys enabled, don't use all screen */
|
||||
if (md->pdata->flags & PT_MT_FLAG_VKEYS) {
|
||||
max_x_tmp = md->pdata->vkeys_x;
|
||||
max_y_tmp = md->pdata->vkeys_y;
|
||||
} else {
|
||||
max_x_tmp = md->si->sensing_conf_data.res_x;
|
||||
max_y_tmp = md->si->sensing_conf_data.res_y;
|
||||
}
|
||||
|
||||
/* get maximum values from the sysinfo data */
|
||||
if (md->pdata->flags & PT_MT_FLAG_FLIP) {
|
||||
max_x = max_y_tmp - 1;
|
||||
max_y = max_x_tmp - 1;
|
||||
} else {
|
||||
max_x = max_x_tmp - 1;
|
||||
max_y = max_y_tmp - 1;
|
||||
}
|
||||
max_p = md->si->sensing_conf_data.max_z;
|
||||
|
||||
/* set event signal capabilities */
|
||||
for (i = 0; i < NUM_SIGNALS(md->pdata->frmwrk); i++) {
|
||||
signal = MT_PARAM_SIGNAL(md, i);
|
||||
if (signal != PT_IGNORE_VALUE) {
|
||||
__set_bit(signal, md->input->absbit);
|
||||
|
||||
min = MT_PARAM_MIN(md, i);
|
||||
max = MT_PARAM_MAX(md, i);
|
||||
if (i == PT_ABS_ID_OST) {
|
||||
/* shift track ids down to start at 0 */
|
||||
max = max - min;
|
||||
min = min - min;
|
||||
} else if (i == PT_ABS_X_OST)
|
||||
max = max_x;
|
||||
else if (i == PT_ABS_Y_OST)
|
||||
max = max_y;
|
||||
else if (i == PT_ABS_P_OST)
|
||||
max = max_p;
|
||||
|
||||
input_set_abs_params(md->input, signal, min, max,
|
||||
MT_PARAM_FUZZ(md, i), MT_PARAM_FLAT(md, i));
|
||||
pt_debug(dev, DL_INFO,
|
||||
"%s: register signal=%02X min=%d max=%d\n",
|
||||
__func__, signal, min, max);
|
||||
}
|
||||
}
|
||||
|
||||
md->or_min = MT_PARAM_MIN(md, PT_ABS_OR_OST);
|
||||
md->or_max = MT_PARAM_MAX(md, PT_ABS_OR_OST);
|
||||
|
||||
md->t_min = MT_PARAM_MIN(md, PT_ABS_ID_OST);
|
||||
md->t_max = MT_PARAM_MAX(md, PT_ABS_ID_OST);
|
||||
|
||||
rc = md->mt_function.input_register_device(md->input,
|
||||
md->si->tch_abs[PT_TCH_T].max);
|
||||
if (rc < 0)
|
||||
pt_debug(dev, DL_ERROR, "%s: Error, failed register input device r=%d\n",
|
||||
__func__, rc);
|
||||
else
|
||||
md->input_device_registered = true;
|
||||
|
||||
#ifdef EASYWAKE_TSG6
|
||||
input_set_capability(md->input, EV_KEY, KEY_F1);
|
||||
input_set_capability(md->input, EV_KEY, KEY_F2);
|
||||
input_set_capability(md->input, EV_KEY, KEY_F3);
|
||||
input_set_capability(md->input, EV_KEY, KEY_F4);
|
||||
input_set_capability(md->input, EV_KEY, KEY_F5);
|
||||
input_set_capability(md->input, EV_KEY, KEY_F6);
|
||||
input_set_capability(md->input, EV_KEY, KEY_F7);
|
||||
input_set_capability(md->input, EV_KEY, KEY_F8);
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_setup_input_attention
|
||||
*
|
||||
* SUMMARY: Wrapper function for pt_setup_input_device() register to TTDL
|
||||
* attention list.
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
* !0 = failure
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dev - pointer to device structure
|
||||
******************************************************************************/
|
||||
static int pt_setup_input_attention(struct device *dev)
|
||||
{
|
||||
struct pt_core_data *cd = dev_get_drvdata(dev);
|
||||
struct pt_mt_data *md = &cd->md;
|
||||
int rc;
|
||||
|
||||
md->si = _pt_request_sysinfo(dev);
|
||||
if (!md->si)
|
||||
return -EINVAL;
|
||||
|
||||
rc = pt_setup_input_device(dev);
|
||||
|
||||
_pt_unsubscribe_attention(dev, PT_ATTEN_STARTUP, PT_MT_NAME,
|
||||
pt_setup_input_attention, 0);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_mt_probe
|
||||
*
|
||||
* SUMMARY: The probe function for touch input device
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
* !0 = failure
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dev - pointer to device structure
|
||||
******************************************************************************/
|
||||
int pt_mt_probe(struct device *dev)
|
||||
{
|
||||
struct pt_core_data *cd = dev_get_drvdata(dev);
|
||||
struct pt_mt_data *md = &cd->md;
|
||||
struct pt_platform_data *pdata = dev_get_platdata(dev);
|
||||
struct pt_mt_platform_data *mt_pdata;
|
||||
int rc = 0;
|
||||
|
||||
pt_debug(dev, DL_INFO,
|
||||
"%s: >>>>>> Register MT <<<<<<\n", __func__);
|
||||
if (!pdata || !pdata->mt_pdata) {
|
||||
pt_debug(dev, DL_ERROR,
|
||||
"%s: Missing platform data\n", __func__);
|
||||
rc = -ENODEV;
|
||||
goto error_no_pdata;
|
||||
}
|
||||
mt_pdata = pdata->mt_pdata;
|
||||
|
||||
pt_init_function_ptrs(md);
|
||||
|
||||
mutex_init(&md->mt_lock);
|
||||
md->dev = dev;
|
||||
md->pdata = mt_pdata;
|
||||
|
||||
/* Create the input device and register it. */
|
||||
pt_debug(dev, DL_INFO,
|
||||
"%s: Create the input device and register it\n", __func__);
|
||||
md->input = input_allocate_device();
|
||||
if (!md->input) {
|
||||
pt_debug(dev, DL_ERROR, "%s: Error, failed to allocate input device\n",
|
||||
__func__);
|
||||
rc = -ENODEV;
|
||||
goto error_alloc_failed;
|
||||
} else
|
||||
md->input_device_allocated = true;
|
||||
|
||||
if (md->pdata->inp_dev_name)
|
||||
md->input->name = md->pdata->inp_dev_name;
|
||||
else
|
||||
md->input->name = PT_MT_NAME;
|
||||
scnprintf(md->phys, sizeof(md->phys), "%s/input%d", dev_name(dev),
|
||||
cd->phys_num++);
|
||||
md->input->phys = md->phys;
|
||||
md->input->dev.parent = md->dev;
|
||||
md->input->open = pt_mt_open;
|
||||
md->input->close = pt_mt_close;
|
||||
input_set_drvdata(md->input, md);
|
||||
|
||||
/* get sysinfo */
|
||||
md->si = _pt_request_sysinfo(dev);
|
||||
|
||||
if (md->si) {
|
||||
rc = pt_setup_input_device(dev);
|
||||
if (rc)
|
||||
goto error_init_input;
|
||||
} else {
|
||||
pt_debug(dev, DL_ERROR, "%s: Fail get sysinfo pointer from core p=%p\n",
|
||||
__func__, md->si);
|
||||
_pt_subscribe_attention(dev, PT_ATTEN_STARTUP,
|
||||
PT_MT_NAME, pt_setup_input_attention, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error_init_input:
|
||||
input_free_device(md->input);
|
||||
md->input_device_allocated = false;
|
||||
error_alloc_failed:
|
||||
error_no_pdata:
|
||||
pt_debug(dev, DL_ERROR, "%s failed.\n", __func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_mt_release
|
||||
*
|
||||
* SUMMARY: The release function for touch input device
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dev - pointer to device structure
|
||||
******************************************************************************/
|
||||
int pt_mt_release(struct device *dev)
|
||||
{
|
||||
struct pt_core_data *cd;
|
||||
struct pt_mt_data *md;
|
||||
|
||||
/* Ensure valid pointers before de-referencing them */
|
||||
if (dev) {
|
||||
cd = dev_get_drvdata(dev);
|
||||
if (cd)
|
||||
md = &cd->md;
|
||||
else
|
||||
return 0;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Second call this function may cause kernel panic if probe fail.
|
||||
* Use input_device_registered & input_device_allocated variable to
|
||||
* avoid unregister or free unavailable devive.
|
||||
*/
|
||||
if (md && md->input_device_registered) {
|
||||
md->input_device_registered = false;
|
||||
input_unregister_device(md->input);
|
||||
/* Unregistering device will free the device too */
|
||||
md->input_device_allocated = false;
|
||||
} else if (md && md->input_device_allocated) {
|
||||
md->input_device_allocated = false;
|
||||
input_free_device(md->input);
|
||||
_pt_unsubscribe_attention(dev, PT_ATTEN_STARTUP,
|
||||
PT_MT_NAME, pt_setup_input_attention, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* pt_mta.c
|
||||
* Parade TrueTouch(TM) Standard Product Multi-Touch Protocol A Module.
|
||||
* For use with Parade touchscreen controllers.
|
||||
* Supported parts include:
|
||||
* TMA5XX
|
||||
* TMA448
|
||||
* TMA445A
|
||||
* TT21XXX
|
||||
* TT31XXX
|
||||
* TT4XXXX
|
||||
* TT7XXX
|
||||
* TC3XXX
|
||||
*
|
||||
* Copyright (C) 2015-2020 Parade Technologies
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2, and only version 2, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contact Parade Technologies at www.paradetech.com <ttdrivers@paradetech.com>
|
||||
*/
|
||||
|
||||
#include "pt_regs.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_final_sync
|
||||
*
|
||||
* SUMMARY: Function to create SYN_REPORT
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *input - pointer to input device structure
|
||||
* max_slots - max support touch number
|
||||
* mt_sync_count - current valid touch number
|
||||
* ids - bit map value
|
||||
******************************************************************************/
|
||||
static void pt_final_sync(struct input_dev *input, int max_slots,
|
||||
int mt_sync_count, unsigned long *ids)
|
||||
{
|
||||
if (mt_sync_count)
|
||||
input_sync(input);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_input_sync
|
||||
*
|
||||
* SUMMARY: Function to create SYN_MT_REPORT
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *input - pointer to input device structure
|
||||
******************************************************************************/
|
||||
static void pt_input_sync(struct input_dev *input)
|
||||
{
|
||||
input_mt_sync(input);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_input_report
|
||||
*
|
||||
* SUMMARY: Function to report coordinate information of touch point
|
||||
* protocol
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *input - pointer to input device structure
|
||||
* sig - track id to allow tracking of a touch
|
||||
* t - event id to indicate an event associated with touch instance
|
||||
* type - indicate the touch object
|
||||
******************************************************************************/
|
||||
static void pt_input_report(struct input_dev *input, int sig,
|
||||
int t, int type)
|
||||
{
|
||||
if (type == PT_OBJ_STANDARD_FINGER || type == PT_OBJ_GLOVE) {
|
||||
input_report_key(input, BTN_TOOL_FINGER, PT_BTN_PRESSED);
|
||||
input_report_key(input, BTN_TOOL_PEN, PT_BTN_RELEASED);
|
||||
} else if (type == PT_OBJ_STYLUS) {
|
||||
input_report_key(input, BTN_TOOL_PEN, PT_BTN_PRESSED);
|
||||
input_report_key(input, BTN_TOOL_FINGER, PT_BTN_RELEASED);
|
||||
}
|
||||
|
||||
input_report_key(input, BTN_TOUCH, PT_BTN_PRESSED);
|
||||
|
||||
input_report_abs(input, sig, t);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_report_slot_liftoff
|
||||
*
|
||||
* SUMMARY: Function to report all touches are lifted
|
||||
* protocol
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *md - pointer to input device structure
|
||||
* max_slots - indicate max number of touch id
|
||||
******************************************************************************/
|
||||
static void pt_report_slot_liftoff(struct pt_mt_data *md,
|
||||
int max_slots)
|
||||
{
|
||||
input_report_key(md->input, BTN_TOUCH, PT_BTN_RELEASED);
|
||||
input_report_key(md->input, BTN_TOOL_FINGER, PT_BTN_RELEASED);
|
||||
input_report_key(md->input, BTN_TOOL_PEN, PT_BTN_RELEASED);
|
||||
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_input_register_device
|
||||
*
|
||||
* SUMMARY: Function to register input device
|
||||
* protocol
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *input - pointer to input device structure
|
||||
* max_slots - indicate max number of touch id
|
||||
******************************************************************************/
|
||||
static int pt_input_register_device(struct input_dev *input, int max_slots)
|
||||
{
|
||||
__set_bit(BTN_TOUCH, input->keybit);
|
||||
__set_bit(BTN_TOOL_FINGER, input->keybit);
|
||||
__set_bit(BTN_TOOL_PEN, input->keybit);
|
||||
return input_register_device(input);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_init_function_ptrs
|
||||
*
|
||||
* SUMMARY: Function to init function pointer
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *md - pointer to touch data structure
|
||||
******************************************************************************/
|
||||
void pt_init_function_ptrs(struct pt_mt_data *md)
|
||||
{
|
||||
md->mt_function.report_slot_liftoff = pt_report_slot_liftoff;
|
||||
md->mt_function.final_sync = pt_final_sync;
|
||||
md->mt_function.input_sync = pt_input_sync;
|
||||
md->mt_function.input_report = pt_input_report;
|
||||
md->mt_function.input_register_device = pt_input_register_device;
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* pt_mtb.c
|
||||
* Parade TrueTouch(TM) Standard Product Multi-Touch Protocol B Module.
|
||||
* For use with Parade touchscreen controllers.
|
||||
* Supported parts include:
|
||||
* TMA5XX
|
||||
* TMA448
|
||||
* TMA445A
|
||||
* TT21XXX
|
||||
* TT31XXX
|
||||
* TT4XXXX
|
||||
* TT7XXX
|
||||
* TC3XXX
|
||||
*
|
||||
* Copyright (C) 2015-2020 Parade Technologies
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2, and only version 2, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contact Parade Technologies at www.paradetech.com <ttdrivers@paradetech.com>
|
||||
*/
|
||||
|
||||
#include "pt_regs.h"
|
||||
#include <linux/input/mt.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_final_sync
|
||||
*
|
||||
* SUMMARY: Function to create SYN_REPORT
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *input - pointer to input device structure
|
||||
* max_slots - max support touch number
|
||||
* mt_sync_count - current valid touch number
|
||||
* ids - bit map value
|
||||
******************************************************************************/
|
||||
static void pt_final_sync(struct input_dev *input, int max_slots,
|
||||
int mt_sync_count, unsigned long *ids)
|
||||
{
|
||||
int t;
|
||||
|
||||
for (t = 0; t < max_slots; t++) {
|
||||
if (test_bit(t, ids))
|
||||
continue;
|
||||
input_mt_slot(input, t);
|
||||
input_mt_report_slot_state(input, MT_TOOL_FINGER, false);
|
||||
}
|
||||
|
||||
input_sync(input);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_input_report
|
||||
*
|
||||
* SUMMARY: Function to report coordinate information of touch point
|
||||
* protocol
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *input - pointer to input device structure
|
||||
* sig - track id to allow tracking of a touch
|
||||
* t - event id to indicate an event associated with touch instance
|
||||
* type - indicate the touch object
|
||||
******************************************************************************/
|
||||
static void pt_input_report(struct input_dev *input, int sig,
|
||||
int t, int type)
|
||||
{
|
||||
input_mt_slot(input, t);
|
||||
|
||||
if (type == PT_OBJ_STANDARD_FINGER || type == PT_OBJ_GLOVE)
|
||||
input_mt_report_slot_state(input, MT_TOOL_FINGER, true);
|
||||
else if (type == PT_OBJ_STYLUS)
|
||||
input_mt_report_slot_state(input, MT_TOOL_PEN, true);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_report_slot_liftoff
|
||||
*
|
||||
* SUMMARY: Function to report all touches are lifted
|
||||
* protocol
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *md - pointer to input device structure
|
||||
* max_slots - indicate max number of touch id
|
||||
******************************************************************************/
|
||||
static void pt_report_slot_liftoff(struct pt_mt_data *md,
|
||||
int max_slots)
|
||||
{
|
||||
int t;
|
||||
|
||||
if (md->num_prv_rec == 0)
|
||||
return;
|
||||
|
||||
for (t = 0; t < max_slots; t++) {
|
||||
input_mt_slot(md->input, t);
|
||||
input_mt_report_slot_state(md->input,
|
||||
MT_TOOL_FINGER, false);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_input_register_device
|
||||
*
|
||||
* SUMMARY: Function to register input device
|
||||
* protocol
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *input - pointer to input device structure
|
||||
* max_slots - indicate max number of touch id
|
||||
******************************************************************************/
|
||||
static int pt_input_register_device(struct input_dev *input, int max_slots)
|
||||
{
|
||||
#if (KERNEL_VERSION(3, 7, 0) <= LINUX_VERSION_CODE)
|
||||
input_mt_init_slots(input, max_slots, 0);
|
||||
#else
|
||||
input_mt_init_slots(input, max_slots);
|
||||
#endif
|
||||
return input_register_device(input);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_init_function_ptrs
|
||||
*
|
||||
* SUMMARY: Function to init function pointer
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *md - pointer to touch data structure
|
||||
******************************************************************************/
|
||||
void pt_init_function_ptrs(struct pt_mt_data *md)
|
||||
{
|
||||
md->mt_function.report_slot_liftoff = pt_report_slot_liftoff;
|
||||
md->mt_function.final_sync = pt_final_sync;
|
||||
md->mt_function.input_sync = NULL;
|
||||
md->mt_function.input_report = pt_input_report;
|
||||
md->mt_function.input_register_device = pt_input_register_device;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,815 @@
|
|||
/*
|
||||
* pt_proximity.c
|
||||
* Parade TrueTouch(TM) Standard Product Proximity Module.
|
||||
* For use with Parade touchscreen controllers.
|
||||
* Supported parts include:
|
||||
* TMA5XX
|
||||
* TMA448
|
||||
* TMA445A
|
||||
* TT21XXX
|
||||
* TT31XXX
|
||||
* TT4XXXX
|
||||
* TT7XXX
|
||||
* TC3XXX
|
||||
*
|
||||
* Copyright (C) 2015-2020 Parade Technologies
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2, and only version 2, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contact Parade Technologies at www.paradetech.com <ttdrivers@paradetech.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "pt_regs.h"
|
||||
|
||||
#define PT_PROXIMITY_NAME "pt_proximity"
|
||||
|
||||
/* Timeout value in ms. */
|
||||
#define PT_PROXIMITY_REQUEST_EXCLUSIVE_TIMEOUT 1000
|
||||
|
||||
#define PT_PROXIMITY_ON 0
|
||||
#define PT_PROXIMITY_OFF 1
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: get_prox_data
|
||||
*
|
||||
* SUMMARY: Gets pointer of proximity data from core data structure
|
||||
*
|
||||
* RETURN:
|
||||
* pointer of pt_proximity_data structure in core data structure
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dev - pointer to device structure
|
||||
******************************************************************************/
|
||||
static inline struct pt_proximity_data *get_prox_data(struct device *dev)
|
||||
{
|
||||
struct pt_core_data *cd = dev_get_drvdata(dev);
|
||||
|
||||
return &cd->pd;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_report_proximity
|
||||
*
|
||||
* SUMMARY: Reports proximity event
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *pd - pointer to proximity data structure
|
||||
* on - state of proximity(true:on; false:off)
|
||||
******************************************************************************/
|
||||
static void pt_report_proximity(struct pt_proximity_data *pd,
|
||||
bool on)
|
||||
{
|
||||
int val = on ? PT_PROXIMITY_ON : PT_PROXIMITY_OFF;
|
||||
|
||||
input_report_abs(pd->input, ABS_DISTANCE, val);
|
||||
input_sync(pd->input);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_get_touch_axis
|
||||
*
|
||||
* SUMMARY: Calculates touch axis
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *pd - pointer to proximity data structure
|
||||
* *axis - pointer to axis calculation result
|
||||
* size - size in bytes
|
||||
* max - max value of result
|
||||
* *xy_data - pointer to input data to be parsed
|
||||
* bofs - bit offset
|
||||
******************************************************************************/
|
||||
static void pt_get_touch_axis(struct pt_proximity_data *pd,
|
||||
int *axis, int size, int max, u8 *xy_data, int bofs)
|
||||
{
|
||||
int nbyte;
|
||||
int next;
|
||||
|
||||
for (nbyte = 0, *axis = 0, next = 0; nbyte < size; nbyte++) {
|
||||
pt_debug(pd->dev, DL_INFO,
|
||||
"%s: *axis=%02X(%d) size=%d max=%08X xy_data=%p xy_data[%d]=%02X(%d) bofs=%d\n",
|
||||
__func__, *axis, *axis, size, max, xy_data, next,
|
||||
xy_data[next], xy_data[next], bofs);
|
||||
*axis = *axis + ((xy_data[next] >> bofs) << (nbyte * 8));
|
||||
next++;
|
||||
}
|
||||
|
||||
*axis &= max - 1;
|
||||
|
||||
pt_debug(pd->dev, DL_INFO,
|
||||
"%s: *axis=%02X(%d) size=%d max=%08X xy_data=%p xy_data[%d]=%02X(%d)\n",
|
||||
__func__, *axis, *axis, size, max, xy_data, next,
|
||||
xy_data[next], xy_data[next]);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_get_touch_hdr
|
||||
*
|
||||
* SUMMARY: Gets header of touch report
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *pd - pointer to proximity data structure
|
||||
* *touch - pointer to pt_touch structure
|
||||
* *xy_mode - pointer to input mode data
|
||||
******************************************************************************/
|
||||
static void pt_get_touch_hdr(struct pt_proximity_data *pd,
|
||||
struct pt_touch *touch, u8 *xy_mode)
|
||||
{
|
||||
struct device *dev = pd->dev;
|
||||
struct pt_sysinfo *si = pd->si;
|
||||
enum pt_tch_hdr hdr;
|
||||
|
||||
for (hdr = PT_TCH_TIME; hdr < PT_TCH_NUM_HDR; hdr++) {
|
||||
if (!si->tch_hdr[hdr].report)
|
||||
continue;
|
||||
pt_get_touch_axis(pd, &touch->hdr[hdr],
|
||||
si->tch_hdr[hdr].size,
|
||||
si->tch_hdr[hdr].max,
|
||||
xy_mode + si->tch_hdr[hdr].ofs,
|
||||
si->tch_hdr[hdr].bofs);
|
||||
pt_debug(dev, DL_INFO, "%s: get %s=%04X(%d)\n",
|
||||
__func__, pt_tch_hdr_string[hdr],
|
||||
touch->hdr[hdr], touch->hdr[hdr]);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_get_touch
|
||||
*
|
||||
* SUMMARY: Parse proximity touch event
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *pd - pointer to proximity data structure
|
||||
* *touch - pointer to touch structure
|
||||
* xy_data - pointer to touch data
|
||||
******************************************************************************/
|
||||
static void pt_get_touch(struct pt_proximity_data *pd,
|
||||
struct pt_touch *touch, u8 *xy_data)
|
||||
{
|
||||
struct device *dev = pd->dev;
|
||||
struct pt_sysinfo *si = pd->si;
|
||||
enum pt_tch_abs abs;
|
||||
|
||||
for (abs = PT_TCH_X; abs < PT_TCH_NUM_ABS; abs++) {
|
||||
if (!si->tch_abs[abs].report)
|
||||
continue;
|
||||
pt_get_touch_axis(pd, &touch->abs[abs],
|
||||
si->tch_abs[abs].size,
|
||||
si->tch_abs[abs].max,
|
||||
xy_data + si->tch_abs[abs].ofs,
|
||||
si->tch_abs[abs].bofs);
|
||||
pt_debug(dev, DL_INFO, "%s: get %s=%04X(%d)\n",
|
||||
__func__, pt_tch_abs_string[abs],
|
||||
touch->abs[abs], touch->abs[abs]);
|
||||
}
|
||||
|
||||
pt_debug(dev, DL_INFO, "%s: x=%04X(%d) y=%04X(%d)\n",
|
||||
__func__, touch->abs[PT_TCH_X], touch->abs[PT_TCH_X],
|
||||
touch->abs[PT_TCH_Y], touch->abs[PT_TCH_Y]);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_get_proximity_touch
|
||||
*
|
||||
* SUMMARY: Parse and report proximity touch event
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *pd - pointer to proximity data structure
|
||||
* *touch - pointer to pt_touch structure
|
||||
******************************************************************************/
|
||||
static void pt_get_proximity_touch(struct pt_proximity_data *pd,
|
||||
struct pt_touch *tch, int num_cur_tch)
|
||||
{
|
||||
struct pt_sysinfo *si = pd->si;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_cur_tch; i++) {
|
||||
pt_get_touch(pd, tch, si->xy_data +
|
||||
(i * si->desc.tch_record_size));
|
||||
|
||||
/* Check for proximity event */
|
||||
if (tch->abs[PT_TCH_O] == PT_OBJ_PROXIMITY) {
|
||||
if (tch->abs[PT_TCH_E] == PT_EV_TOUCHDOWN)
|
||||
pt_report_proximity(pd, true);
|
||||
else if (tch->abs[PT_TCH_E] == PT_EV_LIFTOFF)
|
||||
pt_report_proximity(pd, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_xy_worker
|
||||
*
|
||||
* SUMMARY: Read xy_data for all current touches
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
* !0 = failure
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *pd - pointer to proximity data structure
|
||||
******************************************************************************/
|
||||
static int pt_xy_worker(struct pt_proximity_data *pd)
|
||||
{
|
||||
struct device *dev = pd->dev;
|
||||
struct pt_sysinfo *si = pd->si;
|
||||
struct pt_touch tch;
|
||||
u8 num_cur_tch;
|
||||
|
||||
pt_get_touch_hdr(pd, &tch, si->xy_mode + 3);
|
||||
|
||||
num_cur_tch = tch.hdr[PT_TCH_NUM];
|
||||
if (num_cur_tch > si->sensing_conf_data.max_tch) {
|
||||
pt_debug(dev, DL_ERROR, "%s: Num touch err detected (n=%d)\n",
|
||||
__func__, num_cur_tch);
|
||||
num_cur_tch = si->sensing_conf_data.max_tch;
|
||||
}
|
||||
|
||||
if (tch.hdr[PT_TCH_LO])
|
||||
pt_debug(dev, DL_WARN, "%s: Large area detected\n",
|
||||
__func__);
|
||||
|
||||
/* extract xy_data for all currently reported touches */
|
||||
pt_debug(dev, DL_INFO, "%s: extract data num_cur_rec=%d\n",
|
||||
__func__, num_cur_tch);
|
||||
if (num_cur_tch)
|
||||
pt_get_proximity_touch(pd, &tch, num_cur_tch);
|
||||
else
|
||||
pt_report_proximity(pd, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_mt_attention
|
||||
*
|
||||
* SUMMARY: Wrapper function for pt_xy_worker() that subscribe into the TTDL
|
||||
* attention list.
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
* !0 = failure
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dev - pointer to device structure
|
||||
******************************************************************************/
|
||||
static int pt_proximity_attention(struct device *dev)
|
||||
{
|
||||
struct pt_proximity_data *pd = get_prox_data(dev);
|
||||
int rc = 0;
|
||||
|
||||
if (pd->si->xy_mode[2] != pd->si->desc.tch_report_id)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&pd->prox_lock);
|
||||
rc = pt_xy_worker(pd);
|
||||
mutex_unlock(&pd->prox_lock);
|
||||
if (rc < 0)
|
||||
pt_debug(dev, DL_ERROR, "%s: xy_worker error r=%d\n",
|
||||
__func__, rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_startup_attention
|
||||
*
|
||||
* SUMMARY: Wrapper function for pt_report_proximity() that subcribe into the
|
||||
* TTDL attention list.
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dev - pointer to device structure
|
||||
******************************************************************************/
|
||||
static int pt_startup_attention(struct device *dev)
|
||||
{
|
||||
struct pt_proximity_data *pd = get_prox_data(dev);
|
||||
|
||||
mutex_lock(&pd->prox_lock);
|
||||
pt_report_proximity(pd, false);
|
||||
mutex_unlock(&pd->prox_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: _pt_set_proximity_via_touchmode_enabled
|
||||
*
|
||||
* SUMMARY: Enable/Disable proximity via touchmode parameter
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
* !0 = failure
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *pd - pointer to proximity data structure
|
||||
* enable - enable or disable proximity(true:enable; false:disable)
|
||||
******************************************************************************/
|
||||
static int _pt_set_proximity_via_touchmode_enabled(
|
||||
struct pt_proximity_data *pd, bool enable)
|
||||
{
|
||||
struct device *dev = pd->dev;
|
||||
u32 touchmode_enabled;
|
||||
int rc;
|
||||
|
||||
rc = _pt_request_pip_get_param(dev, 0,
|
||||
PT_RAM_ID_TOUCHMODE_ENABLED, &touchmode_enabled);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (enable)
|
||||
touchmode_enabled |= 0x80;
|
||||
else
|
||||
touchmode_enabled &= 0x7F;
|
||||
|
||||
rc = _pt_request_pip_set_param(dev, 0,
|
||||
PT_RAM_ID_TOUCHMODE_ENABLED, touchmode_enabled,
|
||||
PT_RAM_ID_TOUCHMODE_ENABLED_SIZE);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: _pt_set_proximity_via_proximity_enable
|
||||
*
|
||||
* SUMMARY: Enable/Disable proximity via proximity parameter
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
* !0 = failure
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *pd - pointer to proximity data structure
|
||||
* enable - enable or disable proximity(true:enable; false:disable)
|
||||
******************************************************************************/
|
||||
static int _pt_set_proximity_via_proximity_enable(
|
||||
struct pt_proximity_data *pd, bool enable)
|
||||
{
|
||||
struct device *dev = pd->dev;
|
||||
u32 proximity_enable;
|
||||
int rc;
|
||||
|
||||
rc = _pt_request_pip_get_param(dev, 0,
|
||||
PT_RAM_ID_PROXIMITY_ENABLE, &proximity_enable);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (enable)
|
||||
proximity_enable |= 0x01;
|
||||
else
|
||||
proximity_enable &= 0xFE;
|
||||
|
||||
rc = _pt_request_pip_set_param(dev, 0,
|
||||
PT_RAM_ID_PROXIMITY_ENABLE, proximity_enable,
|
||||
PT_RAM_ID_PROXIMITY_ENABLE_SIZE);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: _pt_set_proximity
|
||||
*
|
||||
* SUMMARY: Set proximity mode via touchmode parameter or proximity parameter.
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
* !0 = failure
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *pd - pointer to proximity data structure
|
||||
* enable - enable or disable proximity(true:enable; false:disable)
|
||||
******************************************************************************/
|
||||
static int _pt_set_proximity(struct pt_proximity_data *pd,
|
||||
bool enable)
|
||||
{
|
||||
if (!IS_PIP_VER_GE(pd->si, 1, 4))
|
||||
return _pt_set_proximity_via_touchmode_enabled(pd,
|
||||
enable);
|
||||
|
||||
return _pt_set_proximity_via_proximity_enable(pd, enable);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: _pt_set_proximity
|
||||
*
|
||||
* SUMMARY: Enable proximity mode and subscribe into IRQ and STARTUP TTDL
|
||||
* attention list.
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
* !0 = failure
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *pd - pointer to proximity data structure
|
||||
******************************************************************************/
|
||||
static int _pt_proximity_enable(struct pt_proximity_data *pd)
|
||||
{
|
||||
struct device *dev = pd->dev;
|
||||
int rc = 0;
|
||||
|
||||
pm_runtime_get_sync(dev);
|
||||
|
||||
rc = pt_request_exclusive(dev,
|
||||
PT_PROXIMITY_REQUEST_EXCLUSIVE_TIMEOUT);
|
||||
if (rc < 0) {
|
||||
pt_debug(dev, DL_ERROR, "%s: Error on request exclusive r=%d\n",
|
||||
__func__, rc);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
rc = _pt_set_proximity(pd, true);
|
||||
if (rc < 0) {
|
||||
pt_debug(dev, DL_ERROR, "%s: Error on request enable proximity scantype r=%d\n",
|
||||
__func__, rc);
|
||||
goto exit_release;
|
||||
}
|
||||
|
||||
pt_debug(dev, DL_INFO, "%s: setup subscriptions\n", __func__);
|
||||
|
||||
/* set up touch call back */
|
||||
_pt_subscribe_attention(dev, PT_ATTEN_IRQ, PT_PROXIMITY_NAME,
|
||||
pt_proximity_attention, PT_MODE_OPERATIONAL);
|
||||
|
||||
/* set up startup call back */
|
||||
_pt_subscribe_attention(dev, PT_ATTEN_STARTUP,
|
||||
PT_PROXIMITY_NAME, pt_startup_attention, 0);
|
||||
|
||||
exit_release:
|
||||
pt_release_exclusive(dev);
|
||||
exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: _pt_proximity_disable
|
||||
*
|
||||
* SUMMARY: Disable proximity mode and unsubscribe from IRQ and STARTUP TTDL
|
||||
* attention list.
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
* !0 = failure
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *pd - pointer to proximity data structure
|
||||
******************************************************************************/
|
||||
static int _pt_proximity_disable(struct pt_proximity_data *pd,
|
||||
bool force)
|
||||
{
|
||||
struct device *dev = pd->dev;
|
||||
int rc = 0;
|
||||
|
||||
rc = pt_request_exclusive(dev,
|
||||
PT_PROXIMITY_REQUEST_EXCLUSIVE_TIMEOUT);
|
||||
if (rc < 0) {
|
||||
pt_debug(dev, DL_ERROR, "%s: Error on request exclusive r=%d\n",
|
||||
__func__, rc);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
rc = _pt_set_proximity(pd, false);
|
||||
if (rc < 0) {
|
||||
pt_debug(dev, DL_ERROR, "%s: Error on request disable proximity scan r=%d\n",
|
||||
__func__, rc);
|
||||
goto exit_release;
|
||||
}
|
||||
|
||||
exit_release:
|
||||
pt_release_exclusive(dev);
|
||||
|
||||
exit:
|
||||
if (!rc || force) {
|
||||
_pt_unsubscribe_attention(dev, PT_ATTEN_IRQ,
|
||||
PT_PROXIMITY_NAME, pt_proximity_attention,
|
||||
PT_MODE_OPERATIONAL);
|
||||
|
||||
_pt_unsubscribe_attention(dev, PT_ATTEN_STARTUP,
|
||||
PT_PROXIMITY_NAME, pt_startup_attention, 0);
|
||||
}
|
||||
|
||||
pm_runtime_put(dev);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_proximity_enable_show
|
||||
*
|
||||
* SUMMARY: Show method for the prox_enable sysfs node that will show the
|
||||
* enable_count of proximity
|
||||
*
|
||||
* RETURN: Size of printed buffer
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dev - pointer to device structure
|
||||
* *attr - pointer to device attributes
|
||||
* *buf - pointer to output buffer
|
||||
******************************************************************************/
|
||||
static ssize_t pt_proximity_enable_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct pt_proximity_data *pd = get_prox_data(dev);
|
||||
int val = 0;
|
||||
|
||||
mutex_lock(&pd->sysfs_lock);
|
||||
val = pd->enable_count;
|
||||
mutex_unlock(&pd->sysfs_lock);
|
||||
|
||||
return scnprintf(buf, PT_MAX_PRBUF_SIZE, "%d\n", val);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_proximity_enable_store
|
||||
*
|
||||
* SUMMARY: The store method for the prox_enable sysfs node that allows to
|
||||
* enable or disable proxmity mode.
|
||||
*
|
||||
* RETURN: Size of passed in buffer
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dev - pointer to device structure
|
||||
* *attr - pointer to device attributes
|
||||
* *buf - pointer to buffer that hold the command parameters
|
||||
* size - size of buf
|
||||
******************************************************************************/
|
||||
static ssize_t pt_proximity_enable_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
struct pt_proximity_data *pd = get_prox_data(dev);
|
||||
unsigned long value;
|
||||
int rc;
|
||||
|
||||
rc = kstrtoul(buf, 10, &value);
|
||||
if (rc < 0 || (value != 0 && value != 1)) {
|
||||
pt_debug(dev, DL_ERROR, "%s: Invalid value\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&pd->sysfs_lock);
|
||||
if (value) {
|
||||
if (pd->enable_count++) {
|
||||
pt_debug(dev, DL_WARN, "%s: '%s' already enabled\n",
|
||||
__func__, pd->input->name);
|
||||
} else {
|
||||
rc = _pt_proximity_enable(pd);
|
||||
if (rc)
|
||||
pd->enable_count--;
|
||||
}
|
||||
} else {
|
||||
if (--pd->enable_count) {
|
||||
if (pd->enable_count < 0) {
|
||||
pt_debug(dev, DL_ERROR, "%s: '%s' unbalanced disable\n",
|
||||
__func__, pd->input->name);
|
||||
pd->enable_count = 0;
|
||||
}
|
||||
} else {
|
||||
rc = _pt_proximity_disable(pd, false);
|
||||
if (rc)
|
||||
pd->enable_count++;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&pd->sysfs_lock);
|
||||
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(prox_enable, 0600,
|
||||
pt_proximity_enable_show,
|
||||
pt_proximity_enable_store);
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_setup_input_device_and_sysfs
|
||||
*
|
||||
* SUMMARY: Create sysnode, set event signal capabilities and register input
|
||||
* device for proximity.
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
* !0 = failure
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dev - pointer to device structure
|
||||
******************************************************************************/
|
||||
static int pt_setup_input_device_and_sysfs(struct device *dev)
|
||||
{
|
||||
struct pt_proximity_data *pd = get_prox_data(dev);
|
||||
int signal = PT_IGNORE_VALUE;
|
||||
int i;
|
||||
int rc;
|
||||
|
||||
rc = device_create_file(dev, &dev_attr_prox_enable);
|
||||
if (rc) {
|
||||
pt_debug(dev, DL_ERROR, "%s: Error, could not create enable\n",
|
||||
__func__);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
pt_debug(dev, DL_INFO, "%s: Initialize event signals\n",
|
||||
__func__);
|
||||
|
||||
__set_bit(EV_ABS, pd->input->evbit);
|
||||
|
||||
/* set event signal capabilities */
|
||||
for (i = 0; i < NUM_SIGNALS(pd->pdata->frmwrk); i++) {
|
||||
signal = PARAM_SIGNAL(pd->pdata->frmwrk, i);
|
||||
if (signal != PT_IGNORE_VALUE) {
|
||||
input_set_abs_params(pd->input, signal,
|
||||
PARAM_MIN(pd->pdata->frmwrk, i),
|
||||
PARAM_MAX(pd->pdata->frmwrk, i),
|
||||
PARAM_FUZZ(pd->pdata->frmwrk, i),
|
||||
PARAM_FLAT(pd->pdata->frmwrk, i));
|
||||
}
|
||||
}
|
||||
|
||||
rc = input_register_device(pd->input);
|
||||
if (rc) {
|
||||
pt_debug(dev, DL_ERROR, "%s: Error, failed register input device r=%d\n",
|
||||
__func__, rc);
|
||||
goto unregister_enable;
|
||||
}
|
||||
|
||||
pd->input_device_registered = true;
|
||||
return rc;
|
||||
|
||||
unregister_enable:
|
||||
device_remove_file(dev, &dev_attr_prox_enable);
|
||||
exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_setup_input_attention
|
||||
*
|
||||
* SUMMARY: Wrapper function for pt_setup_input_device_and_sysfs() that
|
||||
* subscribe into TTDL attention list.
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
* !0 = failure
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dev - pointer to device structure
|
||||
******************************************************************************/
|
||||
static int pt_setup_input_attention(struct device *dev)
|
||||
{
|
||||
struct pt_proximity_data *pd = get_prox_data(dev);
|
||||
int rc;
|
||||
|
||||
pd->si = _pt_request_sysinfo(dev);
|
||||
if (!pd->si)
|
||||
return -EINVAL;
|
||||
|
||||
rc = pt_setup_input_device_and_sysfs(dev);
|
||||
if (!rc)
|
||||
rc = _pt_set_proximity(pd, false);
|
||||
|
||||
_pt_unsubscribe_attention(dev, PT_ATTEN_STARTUP,
|
||||
PT_PROXIMITY_NAME, pt_setup_input_attention, 0);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_proximity_probe
|
||||
*
|
||||
* SUMMARY: The probe function for proximity input device
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
* !0 = failure
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dev - pointer to device structure
|
||||
******************************************************************************/
|
||||
int pt_proximity_probe(struct device *dev)
|
||||
{
|
||||
struct pt_core_data *cd = dev_get_drvdata(dev);
|
||||
struct pt_proximity_data *pd = &cd->pd;
|
||||
struct pt_platform_data *pdata = dev_get_platdata(dev);
|
||||
struct pt_proximity_platform_data *prox_pdata;
|
||||
int rc = 0;
|
||||
|
||||
if (!pdata || !pdata->prox_pdata) {
|
||||
pt_debug(dev, DL_ERROR,
|
||||
"%s: Missing platform data\n", __func__);
|
||||
rc = -ENODEV;
|
||||
goto error_no_pdata;
|
||||
}
|
||||
prox_pdata = pdata->prox_pdata;
|
||||
|
||||
mutex_init(&pd->prox_lock);
|
||||
mutex_init(&pd->sysfs_lock);
|
||||
pd->dev = dev;
|
||||
pd->pdata = prox_pdata;
|
||||
|
||||
/* Create the input device and register it. */
|
||||
pt_debug(dev, DL_INFO,
|
||||
"%s: Create the input device and register it\n", __func__);
|
||||
pd->input = input_allocate_device();
|
||||
if (!pd->input) {
|
||||
pt_debug(dev, DL_ERROR, "%s: Error, failed to allocate input device\n",
|
||||
__func__);
|
||||
rc = -ENODEV;
|
||||
goto error_alloc_failed;
|
||||
} else
|
||||
pd->input_device_allocated = true;
|
||||
|
||||
if (pd->pdata->inp_dev_name)
|
||||
pd->input->name = pd->pdata->inp_dev_name;
|
||||
else
|
||||
pd->input->name = PT_PROXIMITY_NAME;
|
||||
scnprintf(pd->phys, sizeof(pd->phys), "%s/input%d", dev_name(dev),
|
||||
cd->phys_num++);
|
||||
pd->input->phys = pd->phys;
|
||||
pd->input->dev.parent = pd->dev;
|
||||
input_set_drvdata(pd->input, pd);
|
||||
|
||||
/* get sysinfo */
|
||||
pd->si = _pt_request_sysinfo(dev);
|
||||
|
||||
if (pd->si) {
|
||||
rc = pt_setup_input_device_and_sysfs(dev);
|
||||
if (rc)
|
||||
goto error_init_input;
|
||||
|
||||
rc = _pt_set_proximity(pd, false);
|
||||
} else {
|
||||
pt_debug(dev, DL_ERROR, "%s: Fail get sysinfo pointer from core p=%p\n",
|
||||
__func__, pd->si);
|
||||
_pt_subscribe_attention(dev, PT_ATTEN_STARTUP,
|
||||
PT_PROXIMITY_NAME, pt_setup_input_attention,
|
||||
0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error_init_input:
|
||||
input_free_device(pd->input);
|
||||
pd->input_device_allocated = false;
|
||||
error_alloc_failed:
|
||||
error_no_pdata:
|
||||
pt_debug(dev, DL_ERROR, "%s failed.\n", __func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_proximity_release
|
||||
*
|
||||
* SUMMARY: The release function for proximity input device
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dev - pointer to device structure
|
||||
******************************************************************************/
|
||||
int pt_proximity_release(struct device *dev)
|
||||
{
|
||||
struct pt_proximity_data *pd;
|
||||
|
||||
/* Ensure valid pointers before de-referencing them */
|
||||
if (dev)
|
||||
pd = get_prox_data(dev);
|
||||
else
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Second call this function may cause kernel panic if probe fail.
|
||||
* Use input_device_registered & input_device_allocated variable to
|
||||
* avoid unregister or free unavailable devive.
|
||||
*/
|
||||
if (pd && pd->input_device_registered) {
|
||||
/* Disable proximity sensing */
|
||||
pd->input_device_registered = false;
|
||||
mutex_lock(&pd->sysfs_lock);
|
||||
if (pd->enable_count)
|
||||
_pt_proximity_disable(pd, true);
|
||||
mutex_unlock(&pd->sysfs_lock);
|
||||
device_remove_file(dev, &dev_attr_prox_enable);
|
||||
input_unregister_device(pd->input);
|
||||
/* Unregistering device will free the device too */
|
||||
pd->input_device_allocated = false;
|
||||
} else if (pd && pd->input_device_allocated) {
|
||||
pd->input_device_allocated = false;
|
||||
input_free_device(pd->input);
|
||||
_pt_unsubscribe_attention(dev, PT_ATTEN_STARTUP,
|
||||
PT_PROXIMITY_NAME, pt_setup_input_attention,
|
||||
0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,429 @@
|
|||
/*
|
||||
* pt_spi.c
|
||||
* Parade TrueTouch(TM) Standard Product SPI Module.
|
||||
* For use with Parade touchscreen controllers.
|
||||
* Supported parts include:
|
||||
* TMA5XX
|
||||
* TMA448
|
||||
* TMA445A
|
||||
* TT21XXX
|
||||
* TT31XXX
|
||||
* TT4XXXX
|
||||
* TT7XXX
|
||||
* TC3XXX
|
||||
*
|
||||
* Copyright (C) 2015-2020 Parade Technologies
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2, and only version 2, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contact Parade Technologies at www.paradetech.com <ttdrivers@paradetech.com>
|
||||
*/
|
||||
|
||||
#include "pt_regs.h"
|
||||
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
/* TC3315 - DUT Address (0x24 & 0x07) << 1 = 0x08 for write and 0x09 for read */
|
||||
#define PT_SPI_WR_OP 0x08 /* r/~w */
|
||||
#define PT_SPI_RD_OP 0x09
|
||||
#define PT_SPI_BITS_PER_WORD 8
|
||||
#define PT_SPI_SYNC_ACK 0x62
|
||||
|
||||
#define PT_SPI_CMD_BYTES 0
|
||||
#define PT_SPI_DATA_SIZE (2 * 256)
|
||||
#define PT_SPI_DATA_BUF_SIZE (PT_SPI_CMD_BYTES + PT_SPI_DATA_SIZE)
|
||||
|
||||
#define PT_SPI_OP_SIZE (1)
|
||||
#define PT_SPI_DUMMY_READ (1)
|
||||
#define PT_SPI_BUFFER_SIZE \
|
||||
(PT_MAX_PIP2_MSG_SIZE + PT_SPI_OP_SIZE + PT_SPI_DUMMY_READ)
|
||||
|
||||
static u8 *tmp_rbuf;
|
||||
static u8 *tmp_wbuf;
|
||||
DEFINE_MUTEX(pt_spi_bus_lock);
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_spi_xfer
|
||||
*
|
||||
* SUMMARY: Read or write date for SPI device.
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
* !0 = failure
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dev - pointer to device structure
|
||||
* op - flag to write or read data
|
||||
* *buf - pointer to data buffer
|
||||
* length - data length
|
||||
******************************************************************************/
|
||||
static int pt_spi_xfer(struct device *dev, u8 op, u8 *buf, int length)
|
||||
{
|
||||
struct spi_device *spi = to_spi_device(dev);
|
||||
struct spi_message msg;
|
||||
struct spi_transfer xfer;
|
||||
int rc;
|
||||
|
||||
memset(&xfer, 0, sizeof(xfer));
|
||||
spi_message_init(&msg);
|
||||
|
||||
switch (op) {
|
||||
case PT_SPI_RD_OP:
|
||||
/* Clear tmp_wbuf with additional OP Code and dummy byte */
|
||||
memset(tmp_wbuf, 0, length + 2);
|
||||
tmp_wbuf[0] = op;
|
||||
/* Total read/write = Read length + Op code + dummy byte */
|
||||
xfer.tx_buf = tmp_wbuf;
|
||||
xfer.rx_buf = tmp_rbuf;
|
||||
xfer.len = length + 2;
|
||||
break;
|
||||
case PT_SPI_WR_OP:
|
||||
memcpy(&tmp_wbuf[1], buf, length);
|
||||
tmp_wbuf[0] = op;
|
||||
/* Write length + size of Op code */
|
||||
xfer.tx_buf = tmp_wbuf;
|
||||
xfer.len = length + 1;
|
||||
break;
|
||||
default:
|
||||
rc = -EIO;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
spi_message_add_tail(&xfer, &msg);
|
||||
rc = spi_sync(spi, &msg);
|
||||
|
||||
/* On reads copy only the data content back into the passed in buf */
|
||||
if (op == PT_SPI_RD_OP)
|
||||
memcpy(buf, &tmp_rbuf[2], length);
|
||||
exit:
|
||||
if (rc < 0)
|
||||
pt_debug(dev, DL_ERROR, "%s: spi_sync() error %d\n",
|
||||
__func__, rc);
|
||||
|
||||
#if 0 /* TODO TC3315 - need to verify the ACK byte */
|
||||
if (tmp_rbuf[0] != PT_SPI_SYNC_ACK) {
|
||||
pt_debug(dev, DL_ERROR, "%s: r_header = 0x%02X\n", __func__,
|
||||
r_header[0]);
|
||||
return -EIO;
|
||||
}
|
||||
#endif
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_spi_read_default
|
||||
*
|
||||
* SUMMARY: Read a certain number of bytes from the SPI bus
|
||||
* NOTE: For TC3315 every response includes a "dummy" prefix byte that
|
||||
* needs to be stipped off before returning buf.
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
* !0 = failure
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dev - pointer to Device structure
|
||||
* *buf - pointer to buffer where the data read will be stored
|
||||
* size - size to be read
|
||||
******************************************************************************/
|
||||
static int pt_spi_read_default(struct device *dev, void *buf, int size)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!buf || !size || size > PT_MAX_PIP2_MSG_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&pt_spi_bus_lock);
|
||||
rc = pt_spi_xfer(dev, PT_SPI_RD_OP, buf, size);
|
||||
mutex_unlock(&pt_spi_bus_lock);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_spi_read_default_nosize
|
||||
*
|
||||
* SUMMARY: Read from the SPI bus in two transactions first reading the HID
|
||||
* packet size (2 bytes) followed by reading the rest of the packet based
|
||||
* on the size initially read.
|
||||
* NOTE: The empty buffer 'size' was redefined in PIP version 1.7.
|
||||
* NOTE: For TC3315 every response includes a "dummy" prefix byte that
|
||||
* needs to be stipped off before returning buf.
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
* !0 = failure
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dev - pointer to Device structure
|
||||
* *buf - pointer to buffer where the data read will be stored
|
||||
* max - max size that can be read
|
||||
******************************************************************************/
|
||||
static int pt_spi_read_default_nosize(struct device *dev, u8 *buf, u32 max)
|
||||
{
|
||||
u32 size;
|
||||
int rc = 0;
|
||||
|
||||
if (!buf)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&pt_spi_bus_lock);
|
||||
|
||||
/* Separate transaction to retrieve only the length to read */
|
||||
rc = pt_spi_xfer(dev, PT_SPI_RD_OP, buf, 2);
|
||||
if (rc < 0) {
|
||||
pt_debug(dev, DL_ERROR, "%s: SPI transfer error rc = %d\n",
|
||||
__func__, rc);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
size = get_unaligned_le16(&buf[0]);
|
||||
if (!size || size == 2 || size >= PT_PIP_1P7_EMPTY_BUF)
|
||||
goto exit;
|
||||
|
||||
if (size > max || size > PT_MAX_PIP2_MSG_SIZE) {
|
||||
pt_debug(dev, DL_ERROR, "%s: Invalid size %d !\n", __func__,
|
||||
size);
|
||||
rc = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
rc = pt_spi_xfer(dev, PT_SPI_RD_OP, buf, size);
|
||||
if (rc)
|
||||
pt_debug(dev, DL_ERROR, "%s: SPI transfer error rc = %d\n",
|
||||
__func__, rc);
|
||||
|
||||
exit:
|
||||
mutex_unlock(&pt_spi_bus_lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_spi_write_read_specific
|
||||
*
|
||||
* SUMMARY: Write the contents of write_buf to the SPI device and then read
|
||||
* the response using pt_spi_read_default_nosize()
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
* !0 = failure
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *dev - pointer to Device structure
|
||||
* write_len - length of data buffer write_buf
|
||||
* *write_buf - pointer to buffer to write
|
||||
* *read_buf - pointer to buffer to read response into
|
||||
******************************************************************************/
|
||||
static int pt_spi_write_read_specific(struct device *dev, u16 write_len,
|
||||
u8 *write_buf, u8 *read_buf)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
/* Ensure no packet larger than what the PIP spec allows */
|
||||
if (write_len > PT_MAX_PIP2_MSG_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
if (!write_buf || !write_len) {
|
||||
if (!write_buf)
|
||||
pt_debug(dev, DL_ERROR,
|
||||
"%s write_buf is NULL", __func__);
|
||||
if (!write_len)
|
||||
pt_debug(dev, DL_ERROR,
|
||||
"%s write_len is NULL", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&pt_spi_bus_lock);
|
||||
rc = pt_spi_xfer(dev, PT_SPI_WR_OP, write_buf, write_len);
|
||||
if (rc < 0)
|
||||
goto error;
|
||||
mutex_unlock(&pt_spi_bus_lock);
|
||||
|
||||
if (read_buf)
|
||||
rc = pt_spi_read_default_nosize(dev, read_buf,
|
||||
PT_SPI_DATA_SIZE);
|
||||
return rc;
|
||||
|
||||
error:
|
||||
mutex_unlock(&pt_spi_bus_lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static struct pt_bus_ops pt_spi_bus_ops = {
|
||||
.bustype = BUS_SPI,
|
||||
.read_default = pt_spi_read_default,
|
||||
.read_default_nosize = pt_spi_read_default_nosize,
|
||||
.write_read_specific = pt_spi_write_read_specific,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_TOUCHSCREEN_PARADE_DEVICETREE_SUPPORT
|
||||
static const struct of_device_id pt_spi_of_match[] = {
|
||||
{ .compatible = "parade,pt_spi_adapter", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, pt_spi_of_match);
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_spi_probe
|
||||
*
|
||||
* SUMMARY: Probe functon for the SPI module
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
* !0 = failure
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *spi - pointer to spi device structure
|
||||
******************************************************************************/
|
||||
static int pt_spi_probe(struct spi_device *spi)
|
||||
{
|
||||
struct device *dev = &spi->dev;
|
||||
#ifdef CONFIG_TOUCHSCREEN_PARADE_DEVICETREE_SUPPORT
|
||||
const struct of_device_id *match;
|
||||
#endif
|
||||
int rc;
|
||||
|
||||
/* Set up SPI*/
|
||||
spi->bits_per_word = PT_SPI_BITS_PER_WORD;
|
||||
spi->mode = SPI_MODE_0;
|
||||
rc = spi_setup(spi);
|
||||
if (rc < 0) {
|
||||
pt_debug(dev, DL_ERROR, "%s: SPI setup error %d\n",
|
||||
__func__, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TOUCHSCREEN_PARADE_DEVICETREE_SUPPORT
|
||||
match = of_match_device(of_match_ptr(pt_spi_of_match), dev);
|
||||
if (match) {
|
||||
rc = pt_devtree_create_and_get_pdata(dev);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Add 2 to the length for the 'OP Code' & 'Dummy' prefix bytes */
|
||||
tmp_wbuf = kzalloc(PT_SPI_BUFFER_SIZE, GFP_KERNEL);
|
||||
tmp_rbuf = kzalloc(PT_SPI_BUFFER_SIZE, GFP_KERNEL);
|
||||
if (!tmp_wbuf || !tmp_rbuf)
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
rc = pt_probe(&pt_spi_bus_ops, &spi->dev, spi->irq,
|
||||
PT_SPI_DATA_BUF_SIZE);
|
||||
|
||||
#ifdef CONFIG_TOUCHSCREEN_PARADE_DEVICETREE_SUPPORT
|
||||
if (rc && match)
|
||||
pt_devtree_clean_pdata(dev);
|
||||
#endif
|
||||
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_spi_remove
|
||||
*
|
||||
* SUMMARY: Remove functon for the SPI module
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
* !0 = failure
|
||||
*
|
||||
* PARAMETERS:
|
||||
* *spi - pointer to spi device structure
|
||||
******************************************************************************/
|
||||
static int pt_spi_remove(struct spi_device *spi)
|
||||
{
|
||||
#ifdef CONFIG_TOUCHSCREEN_PARADE_DEVICETREE_SUPPORT
|
||||
const struct of_device_id *match;
|
||||
#endif
|
||||
struct device *dev = &spi->dev;
|
||||
struct pt_core_data *cd = dev_get_drvdata(dev);
|
||||
|
||||
kfree(tmp_rbuf);
|
||||
kfree(tmp_wbuf);
|
||||
|
||||
|
||||
pt_release(cd);
|
||||
|
||||
#ifdef CONFIG_TOUCHSCREEN_PARADE_DEVICETREE_SUPPORT
|
||||
match = of_match_device(of_match_ptr(pt_spi_of_match), dev);
|
||||
if (match)
|
||||
pt_devtree_clean_pdata(dev);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct spi_device_id pt_spi_id[] = {
|
||||
{ PT_SPI_NAME, 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, pt_spi_id);
|
||||
|
||||
static struct spi_driver pt_spi_driver = {
|
||||
.driver = {
|
||||
.name = PT_SPI_NAME,
|
||||
.bus = &spi_bus_type,
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &pt_pm_ops,
|
||||
#ifdef CONFIG_TOUCHSCREEN_PARADE_DEVICETREE_SUPPORT
|
||||
.of_match_table = pt_spi_of_match,
|
||||
#endif
|
||||
},
|
||||
.probe = pt_spi_probe,
|
||||
.remove = (pt_spi_remove),
|
||||
.id_table = pt_spi_id,
|
||||
};
|
||||
|
||||
#if (KERNEL_VERSION(3, 3, 0) <= LINUX_VERSION_CODE)
|
||||
module_spi_driver(pt_spi_driver);
|
||||
#else
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_spi_init
|
||||
*
|
||||
* SUMMARY: Initialize function to register spi module to kernel.
|
||||
*
|
||||
* RETURN:
|
||||
* 0 = success
|
||||
* !0 = failure
|
||||
******************************************************************************/
|
||||
static int __init pt_spi_init(void)
|
||||
{
|
||||
int err = spi_register_driver(&pt_spi_driver);
|
||||
|
||||
pr_info("%s: Parade TTDL SPI Driver (Build %s) rc=%d\n",
|
||||
__func__, PT_DRIVER_VERSION, err);
|
||||
return err;
|
||||
}
|
||||
module_init(pt_spi_init);
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTION: pt_spi_exit
|
||||
*
|
||||
* SUMMARY: Exit function to unregister spi module from kernel.
|
||||
*
|
||||
******************************************************************************/
|
||||
static void __exit pt_spi_exit(void)
|
||||
{
|
||||
spi_unregister_driver(&pt_spi_driver);
|
||||
}
|
||||
module_exit(pt_spi_exit);
|
||||
#endif
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Parade TrueTouch(R) Standard Product SPI Driver");
|
||||
MODULE_AUTHOR("Parade Technologies <ttdrivers@paradetech.com>");
|
|
@ -0,0 +1,219 @@
|
|||
/*
|
||||
* pt_core.h
|
||||
* Parade TrueTouch(TM) Standard Product Core Module.
|
||||
* For use with Parade touchscreen controllers.
|
||||
* Supported parts include:
|
||||
* TMA5XX
|
||||
* TMA448
|
||||
* TMA445A
|
||||
* TT21XXX
|
||||
* TT31XXX
|
||||
* TT4XXXX
|
||||
* TT7XXX
|
||||
* TC3XXX
|
||||
*
|
||||
* Copyright (C) 2015-2020 Parade Technologies
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2, and only version 2, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contact Parade Technologies at www.parade.com <ttdrivers@paradetech.com>
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_PT_CORE_H
|
||||
#define _LINUX_PT_CORE_H
|
||||
|
||||
#include <linux/stringify.h>
|
||||
|
||||
#define PT_I2C_NAME "pt_i2c_adapter"
|
||||
#define PT_SPI_NAME "pt_spi_adapter"
|
||||
|
||||
#define PT_CORE_NAME "pt_core"
|
||||
#define PT_MT_NAME "pt_mt"
|
||||
#define PT_BTN_NAME "pt_btn"
|
||||
#define PT_PROXIMITY_NAME "pt_proximity"
|
||||
|
||||
#define PT_DRIVER_NAME TTDL
|
||||
#define PT_DRIVER_MAJOR 04
|
||||
#define PT_DRIVER_MINOR 11
|
||||
|
||||
#define PT_DRIVER_REVCTRL 977092
|
||||
|
||||
#define PT_DRIVER_VERSION \
|
||||
__stringify(PT_DRIVER_NAME) \
|
||||
"." __stringify(PT_DRIVER_MAJOR) \
|
||||
"." __stringify(PT_DRIVER_MINOR) \
|
||||
"." __stringify(PT_DRIVER_REVCTRL)
|
||||
|
||||
#define PT_DRIVER_DATE "20201210"
|
||||
|
||||
/* abs settings */
|
||||
#define PT_IGNORE_VALUE -1
|
||||
|
||||
enum pt_core_platform_flags {
|
||||
PT_CORE_FLAG_NONE,
|
||||
PT_CORE_FLAG_POWEROFF_ON_SLEEP = 0x02,
|
||||
PT_CORE_FLAG_RESTORE_PARAMETERS = 0x04,
|
||||
PT_CORE_FLAG_DEEP_STANDBY = 0x08,
|
||||
PT_CORE_FLAG_SKIP_SYS_SLEEP = 0x10,
|
||||
PT_CORE_FLAG_SKIP_RUNTIME = 0x20,
|
||||
PT_CORE_FLAG_SKIP_RESUME = 0x40,
|
||||
};
|
||||
|
||||
enum pt_core_platform_easy_wakeup_gesture {
|
||||
PT_CORE_EWG_NONE,
|
||||
PT_CORE_EWG_TAP_TAP,
|
||||
PT_CORE_EWG_TWO_FINGER_SLIDE,
|
||||
PT_CORE_EWG_RESERVED,
|
||||
PT_CORE_EWG_WAKE_ON_INT_FROM_HOST = 0xFF,
|
||||
};
|
||||
|
||||
enum pt_loader_platform_flags {
|
||||
PT_LOADER_FLAG_NONE,
|
||||
PT_LOADER_FLAG_CALIBRATE_AFTER_FW_UPGRADE,
|
||||
/* Use CONFIG_VER field in TT_CFG to decide TT_CFG update */
|
||||
PT_LOADER_FLAG_CHECK_TTCONFIG_VERSION,
|
||||
PT_LOADER_FLAG_CALIBRATE_AFTER_TTCONFIG_UPGRADE,
|
||||
};
|
||||
|
||||
enum CONFIG_DUT_GENERATION {
|
||||
CONFIG_DUT_AUTO_DETECT = 0x00,
|
||||
CONFIG_DUT_PIP1_ONLY = 0x01,
|
||||
CONFIG_DUT_PIP2_CAPABLE = 0x02,
|
||||
};
|
||||
|
||||
enum pt_core_platform_panel_id_flags {
|
||||
PT_PANEL_ID_DISABLE = 0x00,
|
||||
PT_PANEL_ID_BY_BL = 0x01,
|
||||
PT_PANEL_ID_BY_SYS_INFO = 0x02,
|
||||
PT_PANEL_ID_BY_MFG_DATA = 0x04,
|
||||
};
|
||||
|
||||
struct touch_settings {
|
||||
const uint8_t *data;
|
||||
uint32_t size;
|
||||
uint8_t tag;
|
||||
};
|
||||
|
||||
struct pt_touch_firmware {
|
||||
const uint8_t *img;
|
||||
uint32_t size;
|
||||
const uint8_t *ver;
|
||||
uint8_t vsize;
|
||||
uint8_t panel_id;
|
||||
};
|
||||
|
||||
struct pt_touch_config {
|
||||
struct touch_settings *param_regs;
|
||||
struct touch_settings *param_size;
|
||||
const uint8_t *fw_ver;
|
||||
uint8_t fw_vsize;
|
||||
uint8_t panel_id;
|
||||
};
|
||||
|
||||
struct pt_loader_platform_data {
|
||||
struct pt_touch_firmware *fw;
|
||||
struct pt_touch_config *ttconfig;
|
||||
struct pt_touch_firmware **fws;
|
||||
struct pt_touch_config **ttconfigs;
|
||||
u32 flags;
|
||||
};
|
||||
|
||||
typedef int (*pt_platform_read) (struct device *dev, void *buf, int size);
|
||||
|
||||
#define PT_TOUCH_SETTINGS_MAX 32
|
||||
|
||||
struct pt_core_platform_data {
|
||||
int irq_gpio;
|
||||
int rst_gpio;
|
||||
int ddi_rst_gpio;
|
||||
int vddi_gpio;
|
||||
int vcc_gpio;
|
||||
int avdd_gpio;
|
||||
int avee_gpio;
|
||||
int level_irq_udelay;
|
||||
u16 hid_desc_register;
|
||||
u16 vendor_id;
|
||||
u16 product_id;
|
||||
|
||||
int (*xres)(struct pt_core_platform_data *pdata,
|
||||
struct device *dev);
|
||||
int (*init)(struct pt_core_platform_data *pdata,
|
||||
int on, struct device *dev);
|
||||
int (*power)(struct pt_core_platform_data *pdata,
|
||||
int on, struct device *dev, atomic_t *ignore_irq);
|
||||
int (*detect)(struct pt_core_platform_data *pdata,
|
||||
struct device *dev, pt_platform_read read);
|
||||
int (*irq_stat)(struct pt_core_platform_data *pdata,
|
||||
struct device *dev);
|
||||
int (*setup_power)(struct pt_core_platform_data *pdata,
|
||||
int on, struct device *dev);
|
||||
int (*setup_irq)(struct pt_core_platform_data *pdata,
|
||||
int on, struct device *dev);
|
||||
struct touch_settings *sett[PT_TOUCH_SETTINGS_MAX];
|
||||
u32 flags;
|
||||
u8 easy_wakeup_gesture;
|
||||
u8 config_dut_generation;
|
||||
u8 watchdog_force_stop;
|
||||
u8 panel_id_support;
|
||||
};
|
||||
|
||||
struct touch_framework {
|
||||
const int16_t *abs;
|
||||
uint8_t size;
|
||||
uint8_t enable_vkeys;
|
||||
} __packed;
|
||||
|
||||
enum pt_mt_platform_power_state {
|
||||
PT_MT_POWER_OFF = 0x00,
|
||||
PT_MT_POWER_ON = 0x01
|
||||
};
|
||||
|
||||
enum pt_mt_platform_irq_state {
|
||||
PT_MT_IRQ_FREE = 0x00,
|
||||
PT_MT_IRQ_REG = 0x01
|
||||
};
|
||||
|
||||
enum pt_mt_platform_flags {
|
||||
PT_MT_FLAG_NONE,
|
||||
PT_MT_FLAG_HOVER = 0x04,
|
||||
PT_MT_FLAG_FLIP = 0x08,
|
||||
PT_MT_FLAG_INV_X = 0x10,
|
||||
PT_MT_FLAG_INV_Y = 0x20,
|
||||
PT_MT_FLAG_VKEYS = 0x40,
|
||||
PT_MT_FLAG_NO_TOUCH_ON_LO = 0x80,
|
||||
};
|
||||
|
||||
struct pt_mt_platform_data {
|
||||
struct touch_framework *frmwrk;
|
||||
unsigned short flags;
|
||||
char const *inp_dev_name;
|
||||
int vkeys_x;
|
||||
int vkeys_y;
|
||||
};
|
||||
|
||||
struct pt_btn_platform_data {
|
||||
char const *inp_dev_name;
|
||||
};
|
||||
|
||||
struct pt_proximity_platform_data {
|
||||
struct touch_framework *frmwrk;
|
||||
char const *inp_dev_name;
|
||||
};
|
||||
|
||||
struct pt_platform_data {
|
||||
struct pt_core_platform_data *core_pdata;
|
||||
struct pt_mt_platform_data *mt_pdata;
|
||||
struct pt_btn_platform_data *btn_pdata;
|
||||
struct pt_proximity_platform_data *prox_pdata;
|
||||
struct pt_loader_platform_data *loader_pdata;
|
||||
};
|
||||
|
||||
#endif /* _LINUX_PT_CORE_H */
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* pt_platform.h
|
||||
* Parade TrueTouch(TM) Standard Product Platform Module.
|
||||
* For use with Parade touchscreen controllers.
|
||||
* Supported parts include:
|
||||
* TMA5XX
|
||||
* TMA448
|
||||
* TMA445A
|
||||
* TT21XXX
|
||||
* TT31XXX
|
||||
* TT4XXXX
|
||||
* TT7XXX
|
||||
* TC3XXX
|
||||
*
|
||||
* Copyright (C) 2015-2020 Parade Technologies
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2, and only version 2, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contact Parade Technologies at www.parade.com <ttdrivers@paradetech.com>
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_PT_PLATFORM_H
|
||||
#define _LINUX_PT_PLATFORM_H
|
||||
|
||||
#include <linux/pt_core.h>
|
||||
|
||||
#if defined(CONFIG_TOUCHSCREEN_PARADE) \
|
||||
|| defined(CONFIG_TOUCHSCREEN_PARADE_MODULE)
|
||||
extern struct pt_loader_platform_data _pt_loader_platform_data;
|
||||
extern irqreturn_t pt_irq(int irq, void *handle);
|
||||
|
||||
int pt_xres(struct pt_core_platform_data *pdata, struct device *dev);
|
||||
int pt_init(struct pt_core_platform_data *pdata, int on,
|
||||
struct device *dev);
|
||||
int pt_power(struct pt_core_platform_data *pdata, int on,
|
||||
struct device *dev, atomic_t *ignore_irq);
|
||||
#ifdef PT_DETECT_HW
|
||||
int pt_detect(struct pt_core_platform_data *pdata,
|
||||
struct device *dev, pt_platform_read read);
|
||||
#else
|
||||
#define pt_detect NULL
|
||||
#endif
|
||||
int pt_irq_stat(struct pt_core_platform_data *pdata,
|
||||
struct device *dev);
|
||||
int pt_setup_power(struct pt_core_platform_data *pdata, int on,
|
||||
struct device *dev);
|
||||
int pt_setup_irq(struct pt_core_platform_data *pdata, int on,
|
||||
struct device *dev);
|
||||
#else /* !CONFIG_TOUCHSCREEN_PARADE */
|
||||
static struct pt_loader_platform_data _pt_loader_platform_data;
|
||||
#define pt_xres NULL
|
||||
#define pt_init NULL
|
||||
#define pt_power NULL
|
||||
#define pt_irq_stat NULL
|
||||
#define pt_detect NULL
|
||||
#define pt_setup_power NULL
|
||||
#define pt_setup_irq NULL
|
||||
#endif /* CONFIG_TOUCHSCREEN_PARADE */
|
||||
|
||||
#endif /* _LINUX_PT_PLATFORM_H */
|
Loading…
Reference in New Issue