Fixed MTP to work with TWRP

This commit is contained in:
awab228 2018-06-19 23:16:04 +02:00
commit f6dfaef42e
50820 changed files with 20846062 additions and 0 deletions

View file

@ -0,0 +1,969 @@
#
# Touchscreen driver configuration
#
if INPUT_TOUCHSCREEN
config TOUCHSCREEN_88PM860X
tristate "Marvell 88PM860x touchscreen"
depends on MFD_88PM860X
help
Say Y here if you have a 88PM860x PMIC and want to enable
support for the built-in touchscreen.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called 88pm860x-ts.
config TOUCHSCREEN_ADS7846
tristate "ADS7846/TSC2046/AD7873 and AD(S)7843 based touchscreens"
depends on SPI_MASTER
depends on HWMON = n || HWMON
help
Say Y here if you have a touchscreen interface using the
ADS7846/TSC2046/AD7873 or ADS7843/AD7843 controller,
and your board-specific setup code includes that in its
table of SPI devices.
If HWMON is selected, and the driver is told the reference voltage
on your board, you will also get hwmon interfaces for the voltage
(and on ads7846/tsc2046/ad7873, temperature) sensors of this chip.
If unsure, say N (but it's safe to say "Y").
To compile this driver as a module, choose M here: the
module will be called ads7846.
config TOUCHSCREEN_AD7877
tristate "AD7877 based touchscreens"
depends on SPI_MASTER
help
Say Y here if you have a touchscreen interface using the
AD7877 controller, and your board-specific initialization
code includes that in its table of SPI devices.
If unsure, say N (but it's safe to say "Y").
To compile this driver as a module, choose M here: the
module will be called ad7877.
config TOUCHSCREEN_AD7879
tristate "Analog Devices AD7879-1/AD7889-1 touchscreen interface"
help
Say Y here if you want to support a touchscreen interface using
the AD7879-1/AD7889-1 controller.
You should select a bus connection too.
To compile this driver as a module, choose M here: the
module will be called ad7879.
config TOUCHSCREEN_AD7879_I2C
tristate "support I2C bus connection"
depends on TOUCHSCREEN_AD7879 && I2C
help
Say Y here if you have AD7879-1/AD7889-1 hooked to an I2C bus.
To compile this driver as a module, choose M here: the
module will be called ad7879-i2c.
config TOUCHSCREEN_AD7879_SPI
tristate "support SPI bus connection"
depends on TOUCHSCREEN_AD7879 && SPI_MASTER
help
Say Y here if you have AD7879-1/AD7889-1 hooked to a SPI bus.
If unsure, say N (but it's safe to say "Y").
To compile this driver as a module, choose M here: the
module will be called ad7879-spi.
config TOUCHSCREEN_ATMEL_MXT
tristate "Atmel mXT I2C Touchscreen"
depends on I2C
help
Say Y here if you have Atmel mXT series I2C touchscreen,
such as AT42QT602240/ATMXT224, connected to your system.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called atmel_mxt_ts.
config TOUCHSCREEN_BITSY
tristate "Compaq iPAQ H3600 (Bitsy) touchscreen"
depends on SA1100_BITSY
select SERIO
help
Say Y here if you have the h3600 (Bitsy) touchscreen.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called h3600_ts_input.
config TOUCHSCREEN_BU21013
tristate "BU21013 based touch panel controllers"
depends on I2C
help
Say Y here if you have a bu21013 touchscreen connected to
your system.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called bu21013_ts.
config TOUCHSCREEN_CY8CTMG110
tristate "cy8ctmg110 touchscreen"
depends on I2C
depends on GPIOLIB
help
Say Y here if you have a cy8ctmg110 capacitive touchscreen on
an AAVA device.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called cy8ctmg110_ts.
config TOUCHSCREEN_CYPRESS_CYTTSP5
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 cyttsp5.
config TOUCHSCREEN_CYPRESS_CYTTSP5_DEVICETREE_SUPPORT
bool "Enable Device Tree support"
depends on TOUCHSCREEN_CYPRESS_CYTTSP5 && OF
help
Say Y here to enable support for device tree.
If unsure, say N.
config TOUCHSCREEN_CYPRESS_CYTTSP5_DEBUG
bool "Enable debug output"
depends on TOUCHSCREEN_CYPRESS_CYTTSP5
help
Say Y here to enable debug output for Parade TrueTouch(tm)
Standard Product Generation5 drivers set.
If unsure, say N.
config TOUCHSCREEN_CYPRESS_CYTTSP5_VDEBUG
bool "Enable verbose debug output"
depends on TOUCHSCREEN_CYPRESS_CYTTSP5_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_CYPRESS_CYTTSP5_I2C
tristate "Parade TrueTouch Gen5 I2C"
depends on TOUCHSCREEN_CYPRESS_CYTTSP5
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 cyttsp5_i2c.
config TOUCHSCREEN_CYPRESS_CYTTSP5_SPI
tristate "Parade TrueTouch Gen5 SPI"
depends on TOUCHSCREEN_CYPRESS_CYTTSP5
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 cyttsp5_spi.
choice
bool "Parade TrueTouch Gen5 MultiTouch Protocol"
depends on TOUCHSCREEN_CYPRESS_CYTTSP5
default TOUCHSCREEN_CYPRESS_CYTTSP5_MT_B
help
This option controls which MultiTouch protocol will be used to
report the touch events.
config TOUCHSCREEN_CYPRESS_CYTTSP5_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_CYPRESS_CYTTSP5_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_CYPRESS_CYTTSP5_BUTTON
bool "Parade TrueTouch Gen5 MultiTouch CapSense Button"
depends on TOUCHSCREEN_CYPRESS_CYTTSP5
help
Say Y here to enable CapSense reporting on Parade TrueTouch(tm)
Standard Product Generation5 touchscreen controller.
If unsure, say N.
config TOUCHSCREEN_CYPRESS_CYTTSP5_PROXIMITY
bool "Parade TrueTouch Gen5 Proximity"
depends on TOUCHSCREEN_CYPRESS_CYTTSP5
help
Say Y here to enable proximity reporting on Parade TrueTouch(tm)
Standard Product Generation5 touchscreen controller.
If unsure, say N.
config TOUCHSCREEN_CYPRESS_CYTTSP5_DEVICE_ACCESS
tristate "Parade TrueTouch Gen5 MultiTouch Device Access"
depends on TOUCHSCREEN_CYPRESS_CYTTSP5
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 cyttsp5_device_access.
config TOUCHSCREEN_CYPRESS_CYTTSP5_DEVICE_ACCESS_API
bool "Enable Device Access kernel API"
depends on TOUCHSCREEN_CYPRESS_CYTTSP5_DEVICE_ACCESS
help
Say Y here to enable Device access kernel API which provides
access to Parade TrueTouch(tm) Standard Product Generation5
touchscreen controller for other modules.
If unsure, say N.
config TOUCHSCREEN_CYPRESS_CYTTSP5_TEST_DEVICE_ACCESS_API
tristate "Simple Test module for Device Access kernel API"
depends on TOUCHSCREEN_CYPRESS_CYTTSP5_DEVICE_ACCESS
depends on TOUCHSCREEN_CYPRESS_CYTTSP5_DEVICE_ACCESS_API
help
Say Y here to enable test module for Device access kernel API.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called cyttsp5_test_device_access_api.
config TOUCHSCREEN_CYPRESS_CYTTSP5_LOADER
tristate "Parade TrueTouch Gen5 MultiTouch Loader"
depends on TOUCHSCREEN_CYPRESS_CYTTSP5
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 cyttsp5_loader.
config TOUCHSCREEN_CYPRESS_CYTTSP5_PLATFORM_FW_UPGRADE
bool "FW upgrade from header file"
depends on TOUCHSCREEN_CYPRESS_CYTTSP5_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_CYPRESS_CYTTSP5_BINARY_FW_UPGRADE
bool "FW upgrade from binary file"
depends on TOUCHSCREEN_CYPRESS_CYTTSP5_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_CYPRESS_CYTTSP5_PLATFORM_TTCONFIG_UPGRADE
bool "TT Configuration upgrade from header file"
depends on TOUCHSCREEN_CYPRESS_CYTTSP5_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_CYPRESS_CYTTSP5_MANUAL_TTCONFIG_UPGRADE
bool "TT Configuration upgrade via SysFs"
depends on TOUCHSCREEN_CYPRESS_CYTTSP5_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_CYPRESS_CYTTSP5_DEBUG_MDL
tristate "Parade TrueTouch Gen5 MultiTouch Debug Module"
depends on TOUCHSCREEN_CYPRESS_CYTTSP5
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 cyttsp5_debug.
config TOUCHSCREEN_DA9034
tristate "Touchscreen support for Dialog Semiconductor DA9034"
depends on PMIC_DA903X
default y
help
Say Y here to enable the support for the touchscreen found
on Dialog Semiconductor DA9034 PMIC.
config TOUCHSCREEN_DYNAPRO
tristate "Dynapro serial touchscreen"
select SERIO
help
Say Y here if you have a Dynapro serial touchscreen connected to
your system.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called dynapro.
config TOUCHSCREEN_HAMPSHIRE
tristate "Hampshire serial touchscreen"
select SERIO
help
Say Y here if you have a Hampshire serial touchscreen connected to
your system.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called hampshire.
config TOUCHSCREEN_EETI
tristate "EETI touchscreen panel support"
depends on I2C
help
Say Y here to enable support for I2C connected EETI touch panels.
To compile this driver as a module, choose M here: the
module will be called eeti_ts.
config TOUCHSCREEN_FUJITSU
tristate "Fujitsu serial touchscreen"
select SERIO
help
Say Y here if you have the Fujitsu touchscreen (such as one
installed in Lifebook P series laptop) connected to your
system.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called fujitsu-ts.
config TOUCHSCREEN_S3C2410
tristate "Samsung S3C2410/generic touchscreen input driver"
depends on ARCH_S3C2410 || SAMSUNG_DEV_TS
select S3C_ADC
help
Say Y here if you have the s3c2410 touchscreen.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called s3c2410_ts.
config TOUCHSCREEN_GUNZE
tristate "Gunze AHL-51S touchscreen"
select SERIO
help
Say Y here if you have the Gunze AHL-51 touchscreen connected to
your system.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called gunze.
config TOUCHSCREEN_ELO
tristate "Elo serial touchscreens"
select SERIO
help
Say Y here if you have an Elo serial touchscreen connected to
your system.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called elo.
config TOUCHSCREEN_WACOM_W8001
tristate "Wacom W8001 penabled serial touchscreen"
select SERIO
help
Say Y here if you have an Wacom W8001 penabled serial touchscreen
connected to your system.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called wacom_w8001.
config TOUCHSCREEN_LPC32XX
tristate "LPC32XX touchscreen controller"
depends on ARCH_LPC32XX
help
Say Y here if you have a LPC32XX device and want
to support the built-in touchscreen.
To compile this driver as a module, choose M here: the
module will be called lpc32xx_ts.
config TOUCHSCREEN_MAX11801
tristate "MAX11801 based touchscreens"
depends on I2C
help
Say Y here if you have a MAX11801 based touchscreen
controller.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called max11801_ts.
config TOUCHSCREEN_MCS5000
tristate "MELFAS MCS-5000 touchscreen"
depends on I2C
help
Say Y here if you have the MELFAS MCS-5000 touchscreen controller
chip in your system.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called mcs5000_ts.
config TOUCHSCREEN_MTOUCH
tristate "MicroTouch serial touchscreens"
select SERIO
help
Say Y here if you have a MicroTouch (3M) serial touchscreen connected to
your system.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called mtouch.
config TOUCHSCREEN_INEXIO
tristate "iNexio serial touchscreens"
select SERIO
help
Say Y here if you have an iNexio serial touchscreen connected to
your system.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called inexio.
config TOUCHSCREEN_INTEL_MID
tristate "Intel MID platform resistive touchscreen"
depends on INTEL_SCU_IPC
help
Say Y here if you have a Intel MID based touchscreen in
your system.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called intel_mid_touch.
config TOUCHSCREEN_MK712
tristate "ICS MicroClock MK712 touchscreen"
help
Say Y here if you have the ICS MicroClock MK712 touchscreen
controller chip in your system.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called mk712.
config TOUCHSCREEN_HP600
tristate "HP Jornada 6xx touchscreen"
depends on SH_HP6XX && SH_ADC
help
Say Y here if you have a HP Jornada 620/660/680/690 and want to
support the built-in touchscreen.
To compile this driver as a module, choose M here: the
module will be called hp680_ts_input.
config TOUCHSCREEN_HP7XX
tristate "HP Jornada 7xx touchscreen"
depends on SA1100_JORNADA720_SSP
help
Say Y here if you have a HP Jornada 710/720/728 and want
to support the built-in touchscreen.
To compile this driver as a module, choose M here: the
module will be called jornada720_ts.
config TOUCHSCREEN_HTCPEN
tristate "HTC Shift X9500 touchscreen"
depends on ISA
help
Say Y here if you have an HTC Shift UMPC also known as HTC X9500
Clio / Shangrila and want to support the built-in touchscreen.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called htcpen.
config TOUCHSCREEN_PENMOUNT
tristate "Penmount serial touchscreen"
select SERIO
help
Say Y here if you have a Penmount serial touchscreen connected to
your system.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called penmount.
config TOUCHSCREEN_MIGOR
tristate "Renesas MIGO-R touchscreen"
depends on SH_MIGOR && I2C
help
Say Y here to enable MIGO-R touchscreen support.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called migor_ts.
config TOUCHSCREEN_TNETV107X
tristate "TI TNETV107X touchscreen support"
depends on ARCH_DAVINCI_TNETV107X
help
Say Y here if you want to use the TNETV107X touchscreen.
To compile this driver as a module, choose M here: the
module will be called tnetv107x-ts.
config TOUCHSCREEN_SYNAPTICS_I2C_RMI
tristate "Synaptics i2c touchscreen"
depends on I2C
help
This enables support for Synaptics RMI over I2C based touchscreens.
config TOUCHSCREEN_TOUCHRIGHT
tristate "Touchright serial touchscreen"
select SERIO
help
Say Y here if you have a Touchright serial touchscreen connected to
your system.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called touchright.
config TOUCHSCREEN_TOUCHWIN
tristate "Touchwin serial touchscreen"
select SERIO
help
Say Y here if you have a Touchwin serial touchscreen connected to
your system.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called touchwin.
config TOUCHSCREEN_ATMEL_TSADCC
tristate "Atmel Touchscreen Interface"
depends on ARCH_AT91SAM9RL || ARCH_AT91SAM9G45
help
Say Y here if you have a 4-wire touchscreen connected to the
ADC Controller on your Atmel SoC (such as the AT91SAM9RL).
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called atmel_tsadcc.
config TOUCHSCREEN_UCB1400
tristate "Philips UCB1400 touchscreen"
depends on AC97_BUS
depends on UCB1400_CORE
help
This enables support for the Philips UCB1400 touchscreen interface.
The UCB1400 is an AC97 audio codec. The touchscreen interface
will be initialized only after the ALSA subsystem has been
brought up and the UCB1400 detected. You therefore have to
configure ALSA support as well (either built-in or modular,
independently of whether this driver is itself built-in or
modular) for this driver to work.
To compile this driver as a module, choose M here: the
module will be called ucb1400_ts.
config TOUCHSCREEN_WM831X
tristate "Support for WM831x touchscreen controllers"
depends on MFD_WM831X
help
This enables support for the touchscreen controller on the WM831x
series of PMICs.
To compile this driver as a module, choose M here: the
module will be called wm831x-ts.
config TOUCHSCREEN_WM97XX
tristate "Support for WM97xx AC97 touchscreen controllers"
depends on AC97_BUS
help
Say Y here if you have a Wolfson Microelectronics WM97xx
touchscreen connected to your system. Note that this option
only enables core driver, you will also need to select
support for appropriate chip below.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called wm97xx-ts.
config TOUCHSCREEN_WM9705
bool "WM9705 Touchscreen interface support"
depends on TOUCHSCREEN_WM97XX
default y
help
Say Y here to enable support for the Wolfson Microelectronics
WM9705 touchscreen controller.
config TOUCHSCREEN_WM9712
bool "WM9712 Touchscreen interface support"
depends on TOUCHSCREEN_WM97XX
default y
help
Say Y here to enable support for the Wolfson Microelectronics
WM9712 touchscreen controller.
config TOUCHSCREEN_WM9713
bool "WM9713 Touchscreen interface support"
depends on TOUCHSCREEN_WM97XX
default y
help
Say Y here to enable support for the Wolfson Microelectronics
WM9713 touchscreen controller.
config TOUCHSCREEN_WM97XX_ATMEL
tristate "WM97xx Atmel accelerated touch"
depends on TOUCHSCREEN_WM97XX && (AVR32 || ARCH_AT91)
help
Say Y here for support for streaming mode with WM97xx touchscreens
on Atmel AT91 or AVR32 systems with an AC97C module.
Be aware that this will use channel B in the controller for
streaming data, this must not conflict with other AC97C drivers.
If unsure, say N.
To compile this driver as a module, choose M here: the module will
be called atmel-wm97xx.
config TOUCHSCREEN_WM97XX_MAINSTONE
tristate "WM97xx Mainstone/Palm accelerated touch"
depends on TOUCHSCREEN_WM97XX && ARCH_PXA
help
Say Y here for support for streaming mode with WM97xx touchscreens
on Mainstone, Palm Tungsten T5, TX and LifeDrive systems.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called mainstone-wm97xx.
config TOUCHSCREEN_WM97XX_ZYLONITE
tristate "Zylonite accelerated touch"
depends on TOUCHSCREEN_WM97XX && MACH_ZYLONITE
select TOUCHSCREEN_WM9713
help
Say Y here for support for streaming mode with the touchscreen
on Zylonite systems.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called zylonite-wm97xx.
config TOUCHSCREEN_USB_COMPOSITE
tristate "USB Touchscreen Driver"
depends on USB_ARCH_HAS_HCD
select USB
help
USB Touchscreen driver for:
- eGalax Touchkit USB (also includes eTurboTouch CT-410/510/700)
- PanJit TouchSet USB
- 3M MicroTouch USB (EX II series)
- ITM
- some other eTurboTouch
- Gunze AHL61
- DMC TSC-10/25
- IRTOUCHSYSTEMS/UNITOP
- IdealTEK URTC1000
- GoTop Super_Q2/GogoPen/PenPower tablets
- JASTEC USB Touch Controller/DigiTech DTR-02U
- Zytronic controllers
Have a look at <http://linux.chapter7.ch/touchkit/> for
a usage description and the required user-space stuff.
To compile this driver as a module, choose M here: the
module will be called usbtouchscreen.
config TOUCHSCREEN_MC13783
tristate "Freescale MC13783 touchscreen input driver"
depends on MFD_MC13783
help
Say Y here if you have an Freescale MC13783 PMIC on your
board and want to use its touchscreen
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called mc13783_ts.
config TOUCHSCREEN_USB_EGALAX
default y
bool "eGalax, eTurboTouch CT-410/510/700 device support" if EXPERT
depends on TOUCHSCREEN_USB_COMPOSITE
config TOUCHSCREEN_USB_PANJIT
default y
bool "PanJit device support" if EXPERT
depends on TOUCHSCREEN_USB_COMPOSITE
config TOUCHSCREEN_USB_3M
default y
bool "3M/Microtouch EX II series device support" if EXPERT
depends on TOUCHSCREEN_USB_COMPOSITE
config TOUCHSCREEN_USB_ITM
default y
bool "ITM device support" if EXPERT
depends on TOUCHSCREEN_USB_COMPOSITE
config TOUCHSCREEN_USB_ETURBO
default y
bool "eTurboTouch (non-eGalax compatible) device support" if EXPERT
depends on TOUCHSCREEN_USB_COMPOSITE
config TOUCHSCREEN_USB_GUNZE
default y
bool "Gunze AHL61 device support" if EXPERT
depends on TOUCHSCREEN_USB_COMPOSITE
config TOUCHSCREEN_USB_DMC_TSC10
default y
bool "DMC TSC-10/25 device support" if EXPERT
depends on TOUCHSCREEN_USB_COMPOSITE
config TOUCHSCREEN_USB_IRTOUCH
default y
bool "IRTOUCHSYSTEMS/UNITOP device support" if EXPERT
depends on TOUCHSCREEN_USB_COMPOSITE
config TOUCHSCREEN_USB_IDEALTEK
default y
bool "IdealTEK URTC1000 device support" if EXPERT
depends on TOUCHSCREEN_USB_COMPOSITE
config TOUCHSCREEN_USB_GENERAL_TOUCH
default y
bool "GeneralTouch Touchscreen device support" if EXPERT
depends on TOUCHSCREEN_USB_COMPOSITE
config TOUCHSCREEN_USB_GOTOP
default y
bool "GoTop Super_Q2/GogoPen/PenPower tablet device support" if EXPERT
depends on TOUCHSCREEN_USB_COMPOSITE
config TOUCHSCREEN_USB_JASTEC
default y
bool "JASTEC/DigiTech DTR-02U USB touch controller device support" if EXPERT
depends on TOUCHSCREEN_USB_COMPOSITE
config TOUCHSCREEN_USB_E2I
default y
bool "e2i Touchscreen controller (e.g. from Mimo 740)"
depends on TOUCHSCREEN_USB_COMPOSITE
config TOUCHSCREEN_USB_ZYTRONIC
default y
bool "Zytronic controller" if EXPERT
depends on TOUCHSCREEN_USB_COMPOSITE
config TOUCHSCREEN_USB_ETT_TC45USB
default y
bool "ET&T USB series TC4UM/TC5UH touchscreen controller support" if EXPERT
depends on TOUCHSCREEN_USB_COMPOSITE
config TOUCHSCREEN_USB_NEXIO
default y
bool "NEXIO/iNexio device support" if EXPERT
depends on TOUCHSCREEN_USB_COMPOSITE
config TOUCHSCREEN_TOUCHIT213
tristate "Sahara TouchIT-213 touchscreen"
select SERIO
help
Say Y here if you have a Sahara TouchIT-213 Tablet PC.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called touchit213.
config TOUCHSCREEN_TSC_SERIO
tristate "TSC-10/25/40 serial touchscreen support"
select SERIO
help
Say Y here if you have a TSC-10, 25 or 40 serial touchscreen connected
to your system.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called tsc40.
config TOUCHSCREEN_TSC2005
tristate "TSC2005 based touchscreens"
depends on SPI_MASTER && GENERIC_HARDIRQS
help
Say Y here if you have a TSC2005 based touchscreen.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called tsc2005.
config TOUCHSCREEN_TSC2007
tristate "TSC2007 based touchscreens"
depends on I2C
help
Say Y here if you have a TSC2007 based touchscreen.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called tsc2007.
config TOUCHSCREEN_W90X900
tristate "W90P910 touchscreen driver"
depends on HAVE_CLK
help
Say Y here if you have a W90P910 based touchscreen.
To compile this driver as a module, choose M here: the
module will be called w90p910_ts.
config TOUCHSCREEN_PCAP
tristate "Motorola PCAP touchscreen"
depends on EZX_PCAP
help
Say Y here if you have a Motorola EZX telephone and
want to enable support for the built-in touchscreen.
To compile this driver as a module, choose M here: the
module will be called pcap_ts.
config TOUCHSCREEN_ST1232
tristate "Sitronix ST1232 touchscreen controllers"
depends on I2C
help
Say Y here if you want to support Sitronix ST1232
touchscreen controller.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called st1232_ts.
config TOUCHSCREEN_STMPE
tristate "STMicroelectronics STMPE touchscreens"
depends on MFD_STMPE
help
Say Y here if you want support for STMicroelectronics
STMPE touchscreen controllers.
To compile this driver as a module, choose M here: the
module will be called stmpe-ts.
config TOUCHSCREEN_TPS6507X
tristate "TPS6507x based touchscreens"
depends on I2C
help
Say Y here if you have a TPS6507x based touchscreen
controller.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called tps6507x_ts.
config TOUCHSCREEN_SYNTM12XX
tristate "Synaptic TM12xx touchscreen"
depends on I2C
help
Say Y here to enable support for Synaptic TM12xx
series touchscreen controller.
If unsure, say N.
To compile this driver as module, choose M here: the
module will be called syntm12xx
endif

View file

@ -0,0 +1,113 @@
#
# Makefile for the touchscreen drivers.
#
# Each configuration option enables a list of files.
wm97xx-ts-y := wm97xx-core.o
obj-$(CONFIG_TOUCHSCREEN_88PM860X) += 88pm860x-ts.o
obj-$(CONFIG_TOUCHSCREEN_AD7877) += ad7877.o
obj-$(CONFIG_TOUCHSCREEN_AD7879) += ad7879.o
obj-$(CONFIG_TOUCHSCREEN_AD7879_I2C) += ad7879-i2c.o
obj-$(CONFIG_TOUCHSCREEN_AD7879_SPI) += ad7879-spi.o
obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o
obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT) += atmel_mxt_ts.o
obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o
obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o
obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o
obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110) += cy8ctmg110_ts.o
obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o
obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o
obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += hampshire.o
obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o
obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o
obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o
obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o
obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o
obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o
obj-$(CONFIG_TOUCHSCREEN_LPC32XX) += lpc32xx_ts.o
obj-$(CONFIG_TOUCHSCREEN_MAX11801) += max11801_ts.o
obj-$(CONFIG_TOUCHSCREEN_MC13783) += mc13783_ts.o
obj-$(CONFIG_TOUCHSCREEN_MCS5000) += mcs5000_ts.o
obj-$(CONFIG_TOUCHSCREEN_MIGOR) += migor_ts.o
obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o
obj-$(CONFIG_TOUCHSCREEN_MK712) += mk712.o
obj-$(CONFIG_TOUCHSCREEN_HP600) += hp680_ts_input.o
obj-$(CONFIG_TOUCHSCREEN_HP7XX) += jornada720_ts.o
obj-$(CONFIG_TOUCHSCREEN_HTCPEN) += htcpen.o
obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE) += usbtouchscreen.o
obj-$(CONFIG_TOUCHSCREEN_PCAP) += pcap_ts.o
obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o
obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o
obj-$(CONFIG_TOUCHSCREEN_ST1232) += st1232.o
obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o
obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o
obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI) += synaptics_i2c_rmi.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o
obj-$(CONFIG_TOUCHSCREEN_TSC_SERIO) += tsc40.o
obj-$(CONFIG_TOUCHSCREEN_TSC2005) += tsc2005.o
obj-$(CONFIG_TOUCHSCREEN_TSC2007) += tsc2007.o
obj-$(CONFIG_TOUCHSCREEN_UCB1400) += ucb1400_ts.o
obj-$(CONFIG_TOUCHSCREEN_WACOM_W8001) += wacom_w8001.o
obj-$(CONFIG_TOUCHSCREEN_WM831X) += wm831x-ts.o
obj-$(CONFIG_TOUCHSCREEN_WM97XX) += wm97xx-ts.o
wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705) += wm9705.o
wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712) += wm9712.o
wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9713) += wm9713.o
obj-$(CONFIG_TOUCHSCREEN_WM97XX_ATMEL) += atmel-wm97xx.o
obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o
obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o
obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o
obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o
obj-$(CONFIG_TOUCHSCREEN_SYNTM12XX) += syntm12xx.o
obj-$(CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5) += cyttsp5.o
cyttsp5-y := cyttsp5_core.o cyttsp5_mt_common.o
cyttsp5-$(CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_MT_A) += cyttsp5_mta.o
cyttsp5-$(CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_MT_B) += cyttsp5_mtb.o
cyttsp5-$(CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_BUTTON) += cyttsp5_btn.o
cyttsp5-$(CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_PROXIMITY) += cyttsp5_proximity.o
obj-$(CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_DEVICETREE_SUPPORT) += cyttsp5_devtree.o
ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5
obj-y += cyttsp5_platform.o
endif
obj-$(CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_I2C) += cyttsp5_i2c.o
obj-$(CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_SPI) += cyttsp5_spi.o
obj-$(CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_DEBUG_MDL) += cyttsp5_debug.o
obj-$(CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_LOADER) += cyttsp5_loader.o
obj-$(CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_DEVICE_ACCESS) += cyttsp5_device_access.o
obj-$(CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_TEST_DEVICE_ACCESS_API) += cyttsp5_test_device_access_api.o
ifeq ($(CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_DEBUG),y)
CFLAGS_cyttsp5_core.o += -DDEBUG
CFLAGS_cyttsp5_i2c.o += -DDEBUG
CFLAGS_cyttsp5_spi.o += -DDEBUG
CFLAGS_cyttsp5_mta.o += -DDEBUG
CFLAGS_cyttsp5_mtb.o += -DDEBUG
CFLAGS_cyttsp5_mt_common.o += -DDEBUG
CFLAGS_cyttsp5_btn.o += -DDEBUG
CFLAGS_cyttsp5_proximity.o += -DDEBUG
CFLAGS_cyttsp5_device_access.o += -DDEBUG
CFLAGS_cyttsp5_loader.o += -DDEBUG
CFLAGS_cyttsp5_debug.o += -DDEBUG
CFLAGS_cyttsp5_devtree.o += -DDEBUG
CFLAGS_cyttsp5_platform.o += -DDEBUG
endif
ifeq ($(CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_VDEBUG),y)
CFLAGS_cyttsp5_core.o += -DVERBOSE_DEBUG
CFLAGS_cyttsp5_i2c.o += -DVERBOSE_DEBUG
CFLAGS_cyttsp5_spi.o += -DVERBOSE_DEBUG
CFLAGS_cyttsp5_mta.o += -DVERBOSE_DEBUG
CFLAGS_cyttsp5_mtb.o += -DVERBOSE_DEBUG
CFLAGS_cyttsp5_mt_common.o += -DVERBOSE_DEBUG
CFLAGS_cyttsp5_btn.o += -DVERBOSE_DEBUG
CFLAGS_cyttsp5_proximity.o += -DVERBOSE_DEBUG
CFLAGS_cyttsp5_device_access.o += -DVERBOSE_DEBUG
CFLAGS_cyttsp5_loader.o += -DVERBOSE_DEBUG
CFLAGS_cyttsp5_debug.o += -DVERBOSE_DEBUG
CFLAGS_cyttsp5_devtree.o += -DVERBOSE_DEBUG
CFLAGS_cyttsp5_platform.o += -DVERBOSE_DEBUG
endif

View file

@ -0,0 +1,367 @@
/*
* cyttsp5_btn.c
* Parade TrueTouch(TM) Standard Product V5 CapSense Reports Module.
* For use with Parade touchscreen controllers.
* Supported parts include:
* CYTMA5XX
* CYTMA448
* CYTMA445A
* CYTT21XXX
* CYTT31XXX
*
* Copyright (C) 2015 Parade Technologies
* Copyright (C) 2012-2015 Cypress Semiconductor
*
* 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 "cyttsp5_regs.h"
#define CYTTSP5_BTN_NAME "cyttsp5_btn"
static inline void cyttsp5_btn_key_action(struct cyttsp5_btn_data *bd,
int btn_no, int btn_state)
{
struct device *dev = bd->dev;
struct cyttsp5_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);
dev_dbg(dev, "%s: btn=%d key_code=%d %s\n", __func__,
btn_no, si->btn[btn_no].key_code,
btn_state == CY_BTN_PRESSED ?
"PRESSED" : "RELEASED");
}
static void cyttsp5_get_btn_touches(struct cyttsp5_btn_data *bd)
{
struct cyttsp5_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 * CY_BITS_PER_BTN))
& CY_NUM_BTN_EVENT_ID;
cyttsp5_btn_key_action(bd, cur_btn, cur_btn_state);
}
}
static void cyttsp5_btn_lift_all(struct cyttsp5_btn_data *bd)
{
struct cyttsp5_sysinfo *si = bd->si;
int i;
if (!si || si->num_btns == 0)
return;
for (i = 0; i < si->num_btns; i++)
cyttsp5_btn_key_action(bd, i, CY_BTN_RELEASED);
}
#ifdef VERBOSE_DEBUG
static void cyttsp5_log_btn_data(struct cyttsp5_btn_data *bd)
{
struct device *dev = bd->dev;
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
u8 *pr_buf = cd->pr_buf;
struct cyttsp5_sysinfo *si = bd->si;
int cur;
int value;
for (cur = 0; cur < si->num_btns; cur++) {
pr_buf[0] = 0;
if (si->xy_data[0] & (1 << cur))
value = 1;
else
value = 0;
snprintf(pr_buf, CY_MAX_PRBUF_SIZE, "btn_rec[%d]=0x", cur);
snprintf(pr_buf, CY_MAX_PRBUF_SIZE, "%s%X (%02X)",
pr_buf, value,
le16_to_cpu(si->xy_data[1 + cur * 2]));
dev_vdbg(dev, "%s: %s\n", __func__, pr_buf);
}
}
#endif
/* read xy_data for all current CapSense button touches */
static int cyttsp5_xy_worker(struct cyttsp5_btn_data *bd)
{
struct cyttsp5_sysinfo *si = bd->si;
/* extract button press/release touch information */
if (si->num_btns > 0) {
cyttsp5_get_btn_touches(bd);
#ifdef VERBOSE_DEBUG
/* log button press/release touch information */
cyttsp5_log_btn_data(bd);
#endif
}
return 0;
}
static int cyttsp5_btn_attention(struct device *dev)
{
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
struct cyttsp5_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 = cyttsp5_xy_worker(bd);
mutex_unlock(&bd->btn_lock);
if (rc < 0)
dev_err(dev, "%s: xy_worker error r=%d\n", __func__, rc);
return rc;
}
static int cyttsp5_startup_attention(struct device *dev)
{
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
struct cyttsp5_btn_data *bd = &cd->bd;
mutex_lock(&bd->btn_lock);
cyttsp5_btn_lift_all(bd);
mutex_unlock(&bd->btn_lock);
return 0;
}
static int cyttsp5_btn_suspend_attention(struct device *dev)
{
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
struct cyttsp5_btn_data *bd = &cd->bd;
mutex_lock(&bd->btn_lock);
cyttsp5_btn_lift_all(bd);
bd->is_suspended = true;
mutex_unlock(&bd->btn_lock);
pm_runtime_put(dev);
return 0;
}
static int cyttsp5_btn_resume_attention(struct device *dev)
{
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
struct cyttsp5_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;
}
static int cyttsp5_btn_open(struct input_dev *input)
{
struct device *dev = input->dev.parent;
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
struct cyttsp5_btn_data *bd = &cd->bd;
pm_runtime_get_sync(dev);
mutex_lock(&bd->btn_lock);
bd->is_suspended = false;
mutex_unlock(&bd->btn_lock);
dev_vdbg(dev, "%s: setup subscriptions\n", __func__);
/* set up touch call back */
_cyttsp5_subscribe_attention(dev, CY_ATTEN_IRQ, CYTTSP5_BTN_NAME,
cyttsp5_btn_attention, CY_MODE_OPERATIONAL);
/* set up startup call back */
_cyttsp5_subscribe_attention(dev, CY_ATTEN_STARTUP, CYTTSP5_BTN_NAME,
cyttsp5_startup_attention, 0);
/* set up suspend call back */
_cyttsp5_subscribe_attention(dev, CY_ATTEN_SUSPEND, CYTTSP5_BTN_NAME,
cyttsp5_btn_suspend_attention, 0);
/* set up resume call back */
_cyttsp5_subscribe_attention(dev, CY_ATTEN_RESUME, CYTTSP5_BTN_NAME,
cyttsp5_btn_resume_attention, 0);
return 0;
}
static void cyttsp5_btn_close(struct input_dev *input)
{
struct device *dev = input->dev.parent;
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
struct cyttsp5_btn_data *bd = &cd->bd;
_cyttsp5_unsubscribe_attention(dev, CY_ATTEN_IRQ, CYTTSP5_BTN_NAME,
cyttsp5_btn_attention, CY_MODE_OPERATIONAL);
_cyttsp5_unsubscribe_attention(dev, CY_ATTEN_STARTUP, CYTTSP5_BTN_NAME,
cyttsp5_startup_attention, 0);
_cyttsp5_unsubscribe_attention(dev, CY_ATTEN_SUSPEND, CYTTSP5_BTN_NAME,
cyttsp5_btn_suspend_attention, 0);
_cyttsp5_unsubscribe_attention(dev, CY_ATTEN_RESUME, CYTTSP5_BTN_NAME,
cyttsp5_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);
}
static int cyttsp5_setup_input_device(struct device *dev)
{
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
struct cyttsp5_btn_data *bd = &cd->bd;
int i;
int rc;
dev_vdbg(dev, "%s: Initialize event signals\n", __func__);
__set_bit(EV_KEY, bd->input->evbit);
dev_vdbg(dev, "%s: Number of buttons %d\n", __func__, bd->si->num_btns);
for (i = 0; i < bd->si->num_btns; i++) {
dev_vdbg(dev, "%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)
dev_err(dev, "%s: Error, failed register input device r=%d\n",
__func__, rc);
else
bd->input_device_registered = true;
return rc;
}
static int cyttsp5_setup_input_attention(struct device *dev)
{
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
struct cyttsp5_btn_data *bd = &cd->bd;
int rc;
bd->si = _cyttsp5_request_sysinfo(dev);
if (!bd->si)
return -1;
rc = cyttsp5_setup_input_device(dev);
_cyttsp5_unsubscribe_attention(dev, CY_ATTEN_STARTUP, CYTTSP5_BTN_NAME,
cyttsp5_setup_input_attention, 0);
return rc;
}
int cyttsp5_btn_probe(struct device *dev)
{
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
struct cyttsp5_btn_data *bd = &cd->bd;
struct cyttsp5_platform_data *pdata = dev_get_platdata(dev);
struct cyttsp5_btn_platform_data *btn_pdata;
int rc = 0;
if (!pdata || !pdata->btn_pdata) {
dev_err(dev, "%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. */
dev_vdbg(dev, "%s: Create the input device and register it\n",
__func__);
bd->input = input_allocate_device();
if (!bd->input) {
dev_err(dev, "%s: Error, failed to allocate input device\n",
__func__);
rc = -ENODEV;
goto error_alloc_failed;
}
if (bd->pdata->inp_dev_name)
bd->input->name = bd->pdata->inp_dev_name;
else
bd->input->name = CYTTSP5_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 = cyttsp5_btn_open;
bd->input->close = cyttsp5_btn_close;
input_set_drvdata(bd->input, bd);
/* get sysinfo */
bd->si = _cyttsp5_request_sysinfo(dev);
if (bd->si) {
rc = cyttsp5_setup_input_device(dev);
if (rc)
goto error_init_input;
} else {
dev_err(dev, "%s: Fail get sysinfo pointer from core p=%p\n",
__func__, bd->si);
_cyttsp5_subscribe_attention(dev, CY_ATTEN_STARTUP,
CYTTSP5_BTN_NAME, cyttsp5_setup_input_attention, 0);
}
return 0;
error_init_input:
input_free_device(bd->input);
error_alloc_failed:
error_no_pdata:
dev_err(dev, "%s failed.\n", __func__);
return rc;
}
int cyttsp5_btn_release(struct device *dev)
{
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
struct cyttsp5_btn_data *bd = &cd->bd;
if (bd->input_device_registered) {
input_unregister_device(bd->input);
} else {
input_free_device(bd->input);
_cyttsp5_unsubscribe_attention(dev, CY_ATTEN_STARTUP,
CYTTSP5_BTN_NAME, cyttsp5_setup_input_attention, 0);
}
return 0;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,393 @@
/*
* cyttsp5_debug.c
* Parade TrueTouch(TM) Standard Product V5 Debug Module.
* For use with Parade touchscreen controllers.
* Supported parts include:
* CYTMA5XX
* CYTMA448
* CYTMA445A
* CYTT21XXX
* CYTT31XXX
*
* Copyright (C) 2015 Parade Technologies
* Copyright (C) 2012-2015 Cypress Semiconductor
*
* 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 "cyttsp5_regs.h"
#define CYTTSP5_DEBUG_NAME "cyttsp5_debug"
struct cyttsp5_debug_data {
struct device *dev;
struct cyttsp5_sysinfo *si;
uint32_t interrupt_count;
uint32_t formated_output;
struct mutex sysfs_lock;
u8 pr_buf[CY_MAX_PRBUF_SIZE];
};
static struct cyttsp5_core_commands *cmd;
static struct cyttsp5_module debug_module;
static inline struct cyttsp5_debug_data *cyttsp5_get_debug_data(
struct device *dev)
{
return cyttsp5_get_module_data(dev, &debug_module);
}
/*
* This function provide output of combined xy_mode and xy_data.
* Required by TTHE.
*/
static void cyttsp5_pr_buf_op_mode(struct cyttsp5_debug_data *dd, u8 *pr_buf,
struct cyttsp5_sysinfo *si, u8 cur_touch)
{
const char fmt[] = "%02X ";
int max = (CY_MAX_PRBUF_SIZE - 1) - sizeof(CY_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, CY_MAX_PRBUF_SIZE, fmt, si->xy_mode[i]);
for (i = 0; i < report_size && i < max; i++, k += 3)
scnprintf(pr_buf + k, CY_MAX_PRBUF_SIZE, fmt, si->xy_data[i]);
pr_info("%s=%s%s\n", "cyttsp5_OpModeData", pr_buf,
total_size <= max ? "" : CY_PR_TRUNCATED);
}
static void cyttsp5_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 = (CY_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, CY_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 ? "" : CY_PR_TRUNCATED);
else
pr_info("%s[]\n", data_name);
}
static void cyttsp5_debug_formated(struct device *dev, u8 *pr_buf,
struct cyttsp5_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 */
cyttsp5_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) {
cyttsp5_debug_print(dev, pr_buf, si->xy_data + i,
max_print_length, " ");
}
if (report_size - i)
cyttsp5_debug_print(dev, pr_buf, si->xy_data + i,
report_size - i, " ");
} else {
cyttsp5_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);
cyttsp5_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)
cyttsp5_debug_print(dev, pr_buf, si->xy_data, report_size,
"button");
}
/* read xy_data for all touches for debug */
static int cyttsp5_xy_worker(struct cyttsp5_debug_data *dd)
{
struct device *dev = dd->dev;
struct cyttsp5_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)
cyttsp5_debug_formated(dev, dd->pr_buf, si, num_cur_tch);
else
/* print data for TTHE */
cyttsp5_pr_buf_op_mode(dd, dd->pr_buf, si, num_cur_tch);
pr_info("\n");
return 0;
}
static int cyttsp5_debug_attention(struct device *dev)
{
struct cyttsp5_debug_data *dd = cyttsp5_get_debug_data(dev);
struct cyttsp5_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 = cyttsp5_xy_worker(dd);
if (rc < 0)
dev_err(dev, "%s: xy_worker error r=%d\n", __func__, rc);
return rc;
}
static ssize_t cyttsp5_interrupt_count_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct cyttsp5_debug_data *dd = cyttsp5_get_debug_data(dev);
int val;
mutex_lock(&dd->sysfs_lock);
val = dd->interrupt_count;
mutex_unlock(&dd->sysfs_lock);
return scnprintf(buf, CY_MAX_PRBUF_SIZE, "Interrupt Count: %d\n", val);
}
static ssize_t cyttsp5_interrupt_count_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct cyttsp5_debug_data *dd = cyttsp5_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, S_IRUSR | S_IWUSR,
cyttsp5_interrupt_count_show, cyttsp5_interrupt_count_store);
static ssize_t cyttsp5_formated_output_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct cyttsp5_debug_data *dd = cyttsp5_get_debug_data(dev);
int val;
mutex_lock(&dd->sysfs_lock);
val = dd->formated_output;
mutex_unlock(&dd->sysfs_lock);
return scnprintf(buf, CY_MAX_PRBUF_SIZE,
"Formated debug output: %x\n", val);
}
static ssize_t cyttsp5_formated_output_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct cyttsp5_debug_data *dd = cyttsp5_get_debug_data(dev);
unsigned long value;
int rc;
rc = kstrtoul(buf, 10, &value);
if (rc < 0) {
dev_err(dev, "%s: Invalid value\n", __func__);
return size;
}
/* Expecting only 0 or 1 */
if (value != 0 && value != 1) {
dev_err(dev, "%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, S_IRUSR | S_IWUSR,
cyttsp5_formated_output_show, cyttsp5_formated_output_store);
static int cyttsp5_debug_probe(struct device *dev, void **data)
{
struct cyttsp5_debug_data *dd;
int rc;
/* get context and debug print buffers */
dd = kzalloc(sizeof(*dd), GFP_KERNEL);
if (!dd) {
rc = -ENOMEM;
goto cyttsp5_debug_probe_alloc_failed;
}
rc = device_create_file(dev, &dev_attr_int_count);
if (rc) {
dev_err(dev, "%s: Error, could not create int_count\n",
__func__);
goto cyttsp5_debug_probe_create_int_count_failed;
}
rc = device_create_file(dev, &dev_attr_formated_output);
if (rc) {
dev_err(dev, "%s: Error, could not create formated_output\n",
__func__);
goto cyttsp5_debug_probe_create_formated_failed;
}
mutex_init(&dd->sysfs_lock);
dd->dev = dev;
*data = dd;
dd->si = cmd->request_sysinfo(dev);
if (!dd->si) {
dev_err(dev, "%s: Fail get sysinfo pointer from core\n",
__func__);
rc = -ENODEV;
goto cyttsp5_debug_probe_sysinfo_failed;
}
rc = cmd->subscribe_attention(dev, CY_ATTEN_IRQ, CYTTSP5_DEBUG_NAME,
cyttsp5_debug_attention, CY_MODE_OPERATIONAL);
if (rc < 0) {
dev_err(dev, "%s: Error, could not subscribe attention cb\n",
__func__);
goto cyttsp5_debug_probe_subscribe_failed;
}
return 0;
cyttsp5_debug_probe_subscribe_failed:
cyttsp5_debug_probe_sysinfo_failed:
device_remove_file(dev, &dev_attr_formated_output);
cyttsp5_debug_probe_create_formated_failed:
device_remove_file(dev, &dev_attr_int_count);
cyttsp5_debug_probe_create_int_count_failed:
kfree(dd);
cyttsp5_debug_probe_alloc_failed:
dev_err(dev, "%s failed.\n", __func__);
return rc;
}
static void cyttsp5_debug_release(struct device *dev, void *data)
{
struct cyttsp5_debug_data *dd = data;
int rc;
rc = cmd->unsubscribe_attention(dev, CY_ATTEN_IRQ, CYTTSP5_DEBUG_NAME,
cyttsp5_debug_attention, CY_MODE_OPERATIONAL);
if (rc < 0) {
dev_err(dev, "%s: Error, could not un-subscribe attention\n",
__func__);
goto cyttsp5_debug_release_exit;
}
cyttsp5_debug_release_exit:
device_remove_file(dev, &dev_attr_formated_output);
device_remove_file(dev, &dev_attr_int_count);
kfree(dd);
}
static struct cyttsp5_module debug_module = {
.name = CYTTSP5_DEBUG_NAME,
.probe = cyttsp5_debug_probe,
.release = cyttsp5_debug_release,
};
static int __init cyttsp5_debug_init(void)
{
int rc;
cmd = cyttsp5_get_commands();
if (!cmd)
return -EINVAL;
rc = cyttsp5_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__, CY_DRIVER_VERSION, rc);
return 0;
}
module_init(cyttsp5_debug_init);
static void __exit cyttsp5_debug_exit(void)
{
cyttsp5_unregister_module(&debug_module);
}
module_exit(cyttsp5_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

View file

@ -0,0 +1,747 @@
/*
* cyttsp5_devtree.c
* Parade TrueTouch(TM) Standard Product V5 Device Tree Support Module.
* For use with Parade touchscreen controllers.
* Supported parts include:
* CYTMA5XX
* CYTMA448
* CYTMA445A
* CYTT21XXX
* CYTT31XXX
*
* Copyright (C) 2015 Parade Technologies
* Copyright (C) 2013-2015 Cypress Semiconductor
*
* 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 <linux/device.h>
#include <linux/err.h>
#include <linux/of_device.h>
#include <linux/slab.h>
/* cyttsp */
#include "cyttsp5_regs.h"
#include <linux/cyttsp5_platform.h>
#define ENABLE_VIRTUAL_KEYS
#define MAX_NAME_LENGTH 64
enum cyttsp5_device_type {
DEVICE_MT,
DEVICE_BTN,
DEVICE_PROXIMITY,
DEVICE_TYPE_MAX,
};
struct cyttsp5_device_pdata_func {
void * (*create_and_get_pdata)(struct device_node *);
void (*free_pdata)(void *);
};
struct cyttsp5_pdata_ptr {
void **pdata;
};
#ifdef ENABLE_VIRTUAL_KEYS
static struct kobject *board_properties_kobj;
struct cyttsp5_virtual_keys {
struct kobj_attribute kobj_attr;
u16 *data;
int size;
};
#endif
struct cyttsp5_extended_mt_platform_data {
struct cyttsp5_mt_platform_data pdata;
#ifdef ENABLE_VIRTUAL_KEYS
struct cyttsp5_virtual_keys vkeys;
#endif
};
static inline int get_inp_dev_name(struct device_node *dev_node,
const char **inp_dev_name)
{
return of_property_read_string(dev_node, "cy,inp_dev_name",
inp_dev_name);
}
static s16 *create_and_get_u16_array(struct device_node *dev_node,
const char *name, int *size)
{
const __be32 *values;
s16 *val_array;
int len;
int sz;
int rc;
int i;
values = of_get_property(dev_node, name, &len);
if (values == NULL)
return NULL;
sz = len / sizeof(u32);
pr_debug("%s: %s size:%d\n", __func__, name, sz);
val_array = kcalloc(sz, sizeof(s16), GFP_KERNEL);
if (!val_array) {
rc = -ENOMEM;
goto fail;
}
for (i = 0; i < sz; i++)
val_array[i] = (s16)be32_to_cpup(values++);
*size = sz;
return val_array;
fail:
return ERR_PTR(rc);
}
static struct touch_framework *create_and_get_touch_framework(
struct device_node *dev_node)
{
struct touch_framework *frmwrk;
s16 *abs;
int size;
int rc;
abs = create_and_get_u16_array(dev_node, "cy,abs", &size);
if (IS_ERR_OR_NULL(abs))
return (void *)abs;
/* Check for valid abs size */
if (size % CY_NUM_ABS_SET) {
rc = -EINVAL;
goto fail_free_abs;
}
frmwrk = kzalloc(sizeof(*frmwrk), GFP_KERNEL);
if (!frmwrk) {
rc = -ENOMEM;
goto fail_free_abs;
}
frmwrk->abs = abs;
frmwrk->size = size;
return frmwrk;
fail_free_abs:
kfree(abs);
return ERR_PTR(rc);
}
static void free_touch_framework(struct touch_framework *frmwrk)
{
kfree(frmwrk->abs);
kfree(frmwrk);
}
#ifdef ENABLE_VIRTUAL_KEYS
#define VIRTUAL_KEY_ELEMENT_SIZE 5
static ssize_t virtual_keys_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
struct cyttsp5_virtual_keys *vkeys = container_of(attr,
struct cyttsp5_virtual_keys, kobj_attr);
u16 *data = vkeys->data;
int size = vkeys->size;
int index;
int i;
index = 0;
for (i = 0; i < size; i += VIRTUAL_KEY_ELEMENT_SIZE)
index += scnprintf(buf + index, CY_MAX_PRBUF_SIZE - index,
"0x01:%d:%d:%d:%d:%d\n",
data[i], data[i+1], data[i+2], data[i+3], data[i+4]);
return index;
}
static int setup_virtual_keys(struct device_node *dev_node,
const char *inp_dev_name, struct cyttsp5_virtual_keys *vkeys)
{
char *name;
u16 *data;
int size;
int rc;
data = create_and_get_u16_array(dev_node, "cy,virtual_keys", &size);
if (data == NULL)
return 0;
else if (IS_ERR(data)) {
rc = PTR_ERR(data);
goto fail;
}
/* Check for valid virtual keys size */
if (size % VIRTUAL_KEY_ELEMENT_SIZE) {
rc = -EINVAL;
goto fail_free_data;
}
name = kzalloc(MAX_NAME_LENGTH, GFP_KERNEL);
if (!name) {
rc = -ENOMEM;
goto fail_free_data;
}
snprintf(name, MAX_NAME_LENGTH, "virtualkeys.%s", inp_dev_name);
vkeys->data = data;
vkeys->size = size;
/* TODO: Instantiate in board file and export it */
if (board_properties_kobj == NULL)
board_properties_kobj =
kobject_create_and_add("board_properties", NULL);
if (board_properties_kobj == NULL) {
pr_err("%s: Cannot get board_properties kobject!\n", __func__);
rc = -EINVAL;
goto fail_free_name;
}
/* Initialize dynamic SysFs attribute */
sysfs_attr_init(&vkeys->kobj_attr.attr);
vkeys->kobj_attr.attr.name = name;
vkeys->kobj_attr.attr.mode = S_IRUGO;
vkeys->kobj_attr.show = virtual_keys_show;
rc = sysfs_create_file(board_properties_kobj, &vkeys->kobj_attr.attr);
if (rc)
goto fail_del_kobj;
return 0;
fail_del_kobj:
kobject_del(board_properties_kobj);
fail_free_name:
kfree(name);
vkeys->kobj_attr.attr.name = NULL;
fail_free_data:
kfree(data);
vkeys->data = NULL;
fail:
return rc;
}
static void free_virtual_keys(struct cyttsp5_virtual_keys *vkeys)
{
if (board_properties_kobj)
sysfs_remove_file(board_properties_kobj,
&vkeys->kobj_attr.attr);
kobject_del(board_properties_kobj);
board_properties_kobj = NULL;
kfree(vkeys->data);
kfree(vkeys->kobj_attr.attr.name);
}
#endif
static void *create_and_get_mt_pdata(struct device_node *dev_node)
{
struct cyttsp5_extended_mt_platform_data *ext_pdata;
struct cyttsp5_mt_platform_data *pdata;
u32 value;
int rc;
ext_pdata = kzalloc(sizeof(*ext_pdata), GFP_KERNEL);
if (!ext_pdata) {
rc = -ENOMEM;
goto fail;
}
pdata = &ext_pdata->pdata;
rc = get_inp_dev_name(dev_node, &pdata->inp_dev_name);
if (rc)
goto fail_free_pdata;
/* Optional fields */
rc = of_property_read_u32(dev_node, "cy,flags", &value);
if (!rc)
pdata->flags = value;
rc = of_property_read_u32(dev_node, "cy,vkeys_x", &value);
if (!rc)
pdata->vkeys_x = value;
rc = of_property_read_u32(dev_node, "cy,vkeys_y", &value);
if (!rc)
pdata->vkeys_y = value;
/* Required fields */
pdata->frmwrk = create_and_get_touch_framework(dev_node);
if (pdata->frmwrk == NULL) {
rc = -EINVAL;
goto fail_free_pdata;
} else if (IS_ERR(pdata->frmwrk)) {
rc = PTR_ERR(pdata->frmwrk);
goto fail_free_pdata;
}
#ifdef ENABLE_VIRTUAL_KEYS
rc = setup_virtual_keys(dev_node, pdata->inp_dev_name,
&ext_pdata->vkeys);
if (rc) {
pr_err("%s: Cannot setup virtual keys!\n", __func__);
goto fail_free_pdata;
}
#endif
return pdata;
fail_free_pdata:
kfree(ext_pdata);
fail:
return ERR_PTR(rc);
}
static void free_mt_pdata(void *pdata)
{
struct cyttsp5_mt_platform_data *mt_pdata =
(struct cyttsp5_mt_platform_data *)pdata;
struct cyttsp5_extended_mt_platform_data *ext_mt_pdata =
container_of(mt_pdata,
struct cyttsp5_extended_mt_platform_data, pdata);
free_touch_framework(mt_pdata->frmwrk);
#ifdef ENABLE_VIRTUAL_KEYS
free_virtual_keys(&ext_mt_pdata->vkeys);
#endif
kfree(ext_mt_pdata);
}
static void *create_and_get_btn_pdata(struct device_node *dev_node)
{
struct cyttsp5_btn_platform_data *pdata;
int rc;
pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
if (!pdata) {
rc = -ENOMEM;
goto fail;
}
rc = get_inp_dev_name(dev_node, &pdata->inp_dev_name);
if (rc)
goto fail_free_pdata;
return pdata;
fail_free_pdata:
kfree(pdata);
fail:
return ERR_PTR(rc);
}
static void free_btn_pdata(void *pdata)
{
struct cyttsp5_btn_platform_data *btn_pdata =
(struct cyttsp5_btn_platform_data *)pdata;
kfree(btn_pdata);
}
static void *create_and_get_proximity_pdata(struct device_node *dev_node)
{
struct cyttsp5_proximity_platform_data *pdata;
int rc;
pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
if (!pdata) {
rc = -ENOMEM;
goto fail;
}
rc = get_inp_dev_name(dev_node, &pdata->inp_dev_name);
if (rc)
goto fail_free_pdata;
pdata->frmwrk = create_and_get_touch_framework(dev_node);
if (pdata->frmwrk == NULL) {
rc = -EINVAL;
goto fail_free_pdata;
} else if (IS_ERR(pdata->frmwrk)) {
rc = PTR_ERR(pdata->frmwrk);
goto fail_free_pdata;
}
return pdata;
fail_free_pdata:
kfree(pdata);
fail:
return ERR_PTR(rc);
}
static void free_proximity_pdata(void *pdata)
{
struct cyttsp5_proximity_platform_data *proximity_pdata =
(struct cyttsp5_proximity_platform_data *)pdata;
free_touch_framework(proximity_pdata->frmwrk);
kfree(proximity_pdata);
}
static struct cyttsp5_device_pdata_func device_pdata_funcs[DEVICE_TYPE_MAX] = {
[DEVICE_MT] = {
.create_and_get_pdata = create_and_get_mt_pdata,
.free_pdata = free_mt_pdata,
},
[DEVICE_BTN] = {
.create_and_get_pdata = create_and_get_btn_pdata,
.free_pdata = free_btn_pdata,
},
[DEVICE_PROXIMITY] = {
.create_and_get_pdata = create_and_get_proximity_pdata,
.free_pdata = free_proximity_pdata,
},
};
static struct cyttsp5_pdata_ptr pdata_ptr[DEVICE_TYPE_MAX];
static const char *device_names[DEVICE_TYPE_MAX] = {
[DEVICE_MT] = "cy,mt",
[DEVICE_BTN] = "cy,btn",
[DEVICE_PROXIMITY] = "cy,proximity",
};
static void set_pdata_ptr(struct cyttsp5_platform_data *pdata)
{
pdata_ptr[DEVICE_MT].pdata = (void **)&pdata->mt_pdata;
pdata_ptr[DEVICE_BTN].pdata = (void **)&pdata->btn_pdata;
pdata_ptr[DEVICE_PROXIMITY].pdata = (void **)&pdata->prox_pdata;
}
static int get_device_type(struct device_node *dev_node,
enum cyttsp5_device_type *type)
{
const char *name;
enum cyttsp5_device_type t;
int rc;
rc = of_property_read_string(dev_node, "name", &name);
if (rc)
return rc;
for (t = 0; t < DEVICE_TYPE_MAX; t++)
if (!strncmp(name, device_names[t], MAX_NAME_LENGTH)) {
*type = t;
return 0;
}
return -EINVAL;
}
static inline void *create_and_get_device_pdata(struct device_node *dev_node,
enum cyttsp5_device_type type)
{
return device_pdata_funcs[type].create_and_get_pdata(dev_node);
}
static inline void free_device_pdata(enum cyttsp5_device_type type)
{
device_pdata_funcs[type].free_pdata(*pdata_ptr[type].pdata);
}
static struct touch_settings *create_and_get_touch_setting(
struct device_node *core_node, const char *name)
{
struct touch_settings *setting;
char *tag_name;
u32 tag_value;
u16 *data;
int size;
int rc;
data = create_and_get_u16_array(core_node, name, &size);
if (IS_ERR_OR_NULL(data))
return (void *)data;
pr_debug("%s: Touch setting:'%s' size:%d\n", __func__, name, size);
setting = kzalloc(sizeof(*setting), GFP_KERNEL);
if (!setting) {
rc = -ENOMEM;
goto fail_free_data;
}
setting->data = (u8 *)data;
setting->size = size;
tag_name = kzalloc(MAX_NAME_LENGTH, GFP_KERNEL);
if (!tag_name) {
rc = -ENOMEM;
goto fail_free_setting;
}
snprintf(tag_name, MAX_NAME_LENGTH, "%s-tag", name);
rc = of_property_read_u32(core_node, tag_name, &tag_value);
if (!rc)
setting->tag = tag_value;
kfree(tag_name);
return setting;
fail_free_setting:
kfree(setting);
fail_free_data:
kfree(data);
return ERR_PTR(rc);
}
static void free_touch_setting(struct touch_settings *setting)
{
if (setting) {
kfree(setting->data);
kfree(setting);
}
}
static char *touch_setting_names[CY_IC_GRPNUM_NUM] = {
NULL, /* CY_IC_GRPNUM_RESERVED */
"cy,cmd_regs", /* CY_IC_GRPNUM_CMD_REGS */
"cy,tch_rep", /* CY_IC_GRPNUM_TCH_REP */
"cy,data_rec", /* CY_IC_GRPNUM_DATA_REC */
"cy,test_rec", /* CY_IC_GRPNUM_TEST_REC */
"cy,pcfg_rec", /* CY_IC_GRPNUM_PCFG_REC */
"cy,tch_parm_val", /* CY_IC_GRPNUM_TCH_PARM_VAL */
"cy,tch_parm_size", /* CY_IC_GRPNUM_TCH_PARM_SIZE */
NULL, /* CY_IC_GRPNUM_RESERVED1 */
NULL, /* CY_IC_GRPNUM_RESERVED2 */
"cy,opcfg_rec", /* CY_IC_GRPNUM_OPCFG_REC */
"cy,ddata_rec", /* CY_IC_GRPNUM_DDATA_REC */
"cy,mdata_rec", /* CY_IC_GRPNUM_MDATA_REC */
"cy,test_regs", /* CY_IC_GRPNUM_TEST_REGS */
"cy,btn_keys", /* CY_IC_GRPNUM_BTN_KEYS */
NULL, /* CY_IC_GRPNUM_TTHE_REGS */
};
static struct cyttsp5_core_platform_data *create_and_get_core_pdata(
struct device_node *core_node)
{
struct cyttsp5_core_platform_data *pdata;
u32 value;
int rc;
int i;
pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
if (!pdata) {
rc = -ENOMEM;
goto fail;
}
/* Required fields */
rc = of_property_read_u32(core_node, "cy,irq_gpio", &value);
if (rc)
goto fail_free;
pdata->irq_gpio = value;
rc = of_property_read_u32(core_node, "cy,hid_desc_register", &value);
if (rc)
goto fail_free;
pdata->hid_desc_register = value;
/* Optional fields */
/* rst_gpio is optional since a platform may use
* power cycling instead of using the XRES pin
*/
rc = of_property_read_u32(core_node, "cy,rst_gpio", &value);
if (!rc)
pdata->rst_gpio = value;
rc = of_property_read_u32(core_node, "cy,level_irq_udelay", &value);
if (!rc)
pdata->level_irq_udelay = value;
rc = of_property_read_u32(core_node, "cy,vendor_id", &value);
if (!rc)
pdata->vendor_id = value;
rc = of_property_read_u32(core_node, "cy,product_id", &value);
if (!rc)
pdata->product_id = value;
rc = of_property_read_u32(core_node, "cy,flags", &value);
if (!rc)
pdata->flags = value;
rc = of_property_read_u32(core_node, "cy,easy_wakeup_gesture", &value);
if (!rc)
pdata->easy_wakeup_gesture = (u8)value;
for (i = 0; (unsigned int)i < ARRAY_SIZE(touch_setting_names); i++) {
if (touch_setting_names[i] == NULL)
continue;
pdata->sett[i] = create_and_get_touch_setting(core_node,
touch_setting_names[i]);
if (IS_ERR(pdata->sett[i])) {
rc = PTR_ERR(pdata->sett[i]);
goto fail_free_sett;
} else if (pdata->sett[i] == NULL)
pr_debug("%s: No data for setting '%s'\n", __func__,
touch_setting_names[i]);
}
pr_debug("%s: irq_gpio:%d rst_gpio:%d\n"
"hid_desc_register:%d level_irq_udelay:%d vendor_id:%d product_id:%d\n"
"flags:%d easy_wakeup_gesture:%d\n", __func__,
pdata->irq_gpio, pdata->rst_gpio,
pdata->hid_desc_register,
pdata->level_irq_udelay, pdata->vendor_id, pdata->product_id,
pdata->flags, pdata->easy_wakeup_gesture);
pdata->xres = cyttsp5_xres;
pdata->init = cyttsp5_init;
pdata->power = cyttsp5_power;
pdata->detect = cyttsp5_detect;
pdata->irq_stat = cyttsp5_irq_stat;
return pdata;
fail_free_sett:
for (i--; i >= 0; i--)
free_touch_setting(pdata->sett[i]);
fail_free:
kfree(pdata);
fail:
return ERR_PTR(rc);
}
static void free_core_pdata(void *pdata)
{
struct cyttsp5_core_platform_data *core_pdata = pdata;
unsigned int i;
for (i = 0; i < ARRAY_SIZE(touch_setting_names); i++)
free_touch_setting(core_pdata->sett[i]);
kfree(core_pdata);
}
int cyttsp5_devtree_create_and_get_pdata(struct device *adap_dev)
{
struct cyttsp5_platform_data *pdata;
struct device_node *core_node, *dev_node, *dev_node_fail;
enum cyttsp5_device_type type;
int count = 0;
int rc = 0;
if (!adap_dev->of_node)
return 0;
pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
adap_dev->platform_data = pdata;
set_pdata_ptr(pdata);
/* There should be only one core node */
for_each_child_of_node(adap_dev->of_node, core_node) {
const char *name;
rc = of_property_read_string(core_node, "name", &name);
if (!rc)
pr_debug("%s: name:%s\n", __func__, name);
pdata->core_pdata = create_and_get_core_pdata(core_node);
if (IS_ERR(pdata->core_pdata)) {
rc = PTR_ERR(pdata->core_pdata);
break;
}
/* Increment reference count */
of_node_get(core_node);
for_each_child_of_node(core_node, dev_node) {
count++;
rc = get_device_type(dev_node, &type);
if (rc)
break;
*pdata_ptr[type].pdata
= create_and_get_device_pdata(dev_node, type);
if (IS_ERR(*pdata_ptr[type].pdata))
rc = PTR_ERR(*pdata_ptr[type].pdata);
if (rc)
break;
/* Increment reference count */
of_node_get(dev_node);
}
if (rc) {
free_core_pdata(pdata->core_pdata);
of_node_put(core_node);
for_each_child_of_node(core_node, dev_node_fail) {
if (dev_node == dev_node_fail)
break;
rc = get_device_type(dev_node, &type);
if (rc)
break;
free_device_pdata(type);
of_node_put(dev_node);
}
break;
}
pdata->loader_pdata = &_cyttsp5_loader_platform_data;
}
pr_debug("%s: %d child node(s) found\n", __func__, count);
return rc;
}
EXPORT_SYMBOL_GPL(cyttsp5_devtree_create_and_get_pdata);
int cyttsp5_devtree_clean_pdata(struct device *adap_dev)
{
struct cyttsp5_platform_data *pdata;
struct device_node *core_node, *dev_node;
enum cyttsp5_device_type type;
int rc = 0;
if (!adap_dev->of_node)
return 0;
pdata = dev_get_platdata(adap_dev);
set_pdata_ptr(pdata);
for_each_child_of_node(adap_dev->of_node, core_node) {
free_core_pdata(pdata->core_pdata);
of_node_put(core_node);
for_each_child_of_node(core_node, dev_node) {
rc = get_device_type(dev_node, &type);
if (rc)
break;
free_device_pdata(type);
of_node_put(dev_node);
}
}
return rc;
}
EXPORT_SYMBOL_GPL(cyttsp5_devtree_clean_pdata);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Parade TrueTouch(R) Standard Product DeviceTree Driver");
MODULE_AUTHOR("Parade Technologies <ttdrivers@paradetech.com>");

View file

@ -0,0 +1,222 @@
/*
* cyttsp5_i2c.c
* Parade TrueTouch(TM) Standard Product V5 I2C Module.
* For use with Parade touchscreen controllers.
* Supported parts include:
* CYTMA5XX
* CYTMA448
* CYTMA445A
* CYTT21XXX
* CYTT31XXX
*
* Copyright (C) 2015 Parade Technologies
* Copyright (C) 2012-2015 Cypress Semiconductor
*
* 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 "cyttsp5_regs.h"
#include <linux/i2c.h>
#include <linux/version.h>
#define CY_I2C_DATA_SIZE (2 * 256)
static int cyttsp5_i2c_read_default(struct device *dev, void *buf, int size)
{
struct i2c_client *client = to_i2c_client(dev);
int rc;
if (!buf || !size || size > CY_I2C_DATA_SIZE)
return -EINVAL;
rc = i2c_master_recv(client, buf, size);
return (rc < 0) ? rc : rc != size ? -EIO : 0;
}
static int cyttsp5_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 >= CY_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;
}
static int cyttsp5_i2c_write_read_specific(struct device *dev, u8 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;
if (!write_buf || !write_len)
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 = cyttsp5_i2c_read_default_nosize(dev, read_buf,
CY_I2C_DATA_SIZE);
return rc;
}
static struct cyttsp5_bus_ops cyttsp5_i2c_bus_ops = {
.bustype = BUS_I2C,
.read_default = cyttsp5_i2c_read_default,
.read_default_nosize = cyttsp5_i2c_read_default_nosize,
.write_read_specific = cyttsp5_i2c_write_read_specific,
};
#ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_DEVICETREE_SUPPORT
static const struct of_device_id cyttsp5_i2c_of_match[] = {
{ .compatible = "cy,cyttsp5_i2c_adapter", },
{ }
};
MODULE_DEVICE_TABLE(of, cyttsp5_i2c_of_match);
#endif
static int cyttsp5_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *i2c_id)
{
struct device *dev = &client->dev;
#ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_DEVICETREE_SUPPORT
const struct of_device_id *match;
#endif
int rc;
pr_err("^^^^^client = %d\n",client->irq);
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
dev_err(dev, "I2C functionality not Supported\n");
return -EIO;
}
#ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_DEVICETREE_SUPPORT
match = of_match_device(of_match_ptr(cyttsp5_i2c_of_match), dev);
if (match) {
rc = cyttsp5_devtree_create_and_get_pdata(dev);
if (rc < 0)
return rc;
}
#endif
rc = cyttsp5_probe(&cyttsp5_i2c_bus_ops, &client->dev, client->irq,
CY_I2C_DATA_SIZE);
#ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_DEVICETREE_SUPPORT
if (rc && match)
cyttsp5_devtree_clean_pdata(dev);
#endif
return rc;
}
static int cyttsp5_i2c_remove(struct i2c_client *client)
{
#ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_DEVICETREE_SUPPORT
struct device *dev = &client->dev;
const struct of_device_id *match;
#endif
struct cyttsp5_core_data *cd = i2c_get_clientdata(client);
cyttsp5_release(cd);
#ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_DEVICETREE_SUPPORT
match = of_match_device(of_match_ptr(cyttsp5_i2c_of_match), dev);
if (match)
cyttsp5_devtree_clean_pdata(dev);
#endif
return 0;
}
static const struct i2c_device_id cyttsp5_i2c_id[] = {
{ CYTTSP5_I2C_NAME, 0, },
{ }
};
MODULE_DEVICE_TABLE(i2c, cyttsp5_i2c_id);
static struct i2c_driver cyttsp5_i2c_driver = {
.driver = {
.name = CYTTSP5_I2C_NAME,
.owner = THIS_MODULE,
.pm = &cyttsp5_pm_ops,
#ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_DEVICETREE_SUPPORT
.of_match_table = cyttsp5_i2c_of_match,
#endif
},
.probe = cyttsp5_i2c_probe,
.remove = cyttsp5_i2c_remove,
.id_table = cyttsp5_i2c_id,
};
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
module_i2c_driver(cyttsp5_i2c_driver);
#else
static int __init cyttsp5_i2c_init(void)
{
int rc = i2c_add_driver(&cyttsp5_i2c_driver);
pr_info("%s: Parade TTSP I2C Driver (Built %s) rc=%d\n",
__func__, CY_DRIVER_VERSION, rc);
return rc;
}
module_init(cyttsp5_i2c_init);
static void __exit cyttsp5_i2c_exit(void)
{
i2c_del_driver(&cyttsp5_i2c_driver);
}
module_exit(cyttsp5_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

View file

@ -0,0 +1,729 @@
/*
* cyttsp5_mt_common.c
* Parade TrueTouch(TM) Standard Product V5 Multi-Touch Reports Module.
* For use with Parade touchscreen controllers.
* Supported parts include:
* CYTMA5XX
* CYTMA448
* CYTMA445A
* CYTT21XXX
* CYTT31XXX
*
* Copyright (C) 2015 Parade Technologies
* Copyright (C) 2012-2015 Cypress Semiconductor
*
* 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 "cyttsp5_regs.h"
#define CYTTSP5_MT_NAME "cyttsp5_mt"
#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)
static void cyttsp5_mt_lift_all(struct cyttsp5_mt_data *md)
{
int max = md->si->tch_abs[CY_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;
}
}
static void cyttsp5_get_touch_axis(struct cyttsp5_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++) {
dev_vdbg(md->dev,
"%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;
dev_vdbg(md->dev,
"%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]);
}
static void cyttsp5_get_touch_hdr(struct cyttsp5_mt_data *md,
struct cyttsp5_touch *touch, u8 *xy_mode)
{
struct device *dev = md->dev;
struct cyttsp5_sysinfo *si = md->si;
enum cyttsp5_tch_hdr hdr;
for (hdr = CY_TCH_TIME; hdr < CY_TCH_NUM_HDR; hdr++) {
if (!si->tch_hdr[hdr].report)
continue;
cyttsp5_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);
dev_vdbg(dev, "%s: get %s=%04X(%d)\n", __func__,
cyttsp5_tch_hdr_string[hdr],
touch->hdr[hdr], touch->hdr[hdr]);
}
dev_dbg(dev,
"%s: time=%X tch_num=%d lo=%d noise=%d counter=%d\n",
__func__,
touch->hdr[CY_TCH_TIME],
touch->hdr[CY_TCH_NUM],
touch->hdr[CY_TCH_LO],
touch->hdr[CY_TCH_NOISE],
touch->hdr[CY_TCH_COUNTER]);
}
static void cyttsp5_get_touch_record(struct cyttsp5_mt_data *md,
struct cyttsp5_touch *touch, u8 *xy_data)
{
struct device *dev = md->dev;
struct cyttsp5_sysinfo *si = md->si;
enum cyttsp5_tch_abs abs;
for (abs = CY_TCH_X; abs < CY_TCH_NUM_ABS; abs++) {
if (!si->tch_abs[abs].report)
continue;
cyttsp5_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);
dev_vdbg(dev, "%s: get %s=%04X(%d)\n", __func__,
cyttsp5_tch_abs_string[abs],
touch->abs[abs], touch->abs[abs]);
}
}
static void cyttsp5_mt_process_touch(struct cyttsp5_mt_data *md,
struct cyttsp5_touch *touch)
{
struct device *dev = md->dev;
struct cyttsp5_sysinfo *si = md->si;
int tmp;
bool flipped;
/* Orientation is signed */
touch->abs[CY_TCH_OR] = (int8_t)touch->abs[CY_TCH_OR];
if (md->pdata->flags & CY_MT_FLAG_FLIP) {
tmp = touch->abs[CY_TCH_X];
touch->abs[CY_TCH_X] = touch->abs[CY_TCH_Y];
touch->abs[CY_TCH_Y] = tmp;
if (touch->abs[CY_TCH_OR] > 0)
touch->abs[CY_TCH_OR] =
md->or_max - touch->abs[CY_TCH_OR];
else
touch->abs[CY_TCH_OR] =
md->or_min - touch->abs[CY_TCH_OR];
flipped = true;
} else
flipped = false;
if (md->pdata->flags & CY_MT_FLAG_INV_X) {
if (flipped)
touch->abs[CY_TCH_X] = si->sensing_conf_data.res_y -
touch->abs[CY_TCH_X];
else
touch->abs[CY_TCH_X] = si->sensing_conf_data.res_x -
touch->abs[CY_TCH_X];
touch->abs[CY_TCH_OR] *= -1;
}
if (md->pdata->flags & CY_MT_FLAG_INV_Y) {
if (flipped)
touch->abs[CY_TCH_Y] = si->sensing_conf_data.res_x -
touch->abs[CY_TCH_Y];
else
touch->abs[CY_TCH_Y] = si->sensing_conf_data.res_y -
touch->abs[CY_TCH_Y];
touch->abs[CY_TCH_OR] *= -1;
}
/* Convert MAJOR/MINOR from mm to resolution */
tmp = touch->abs[CY_TCH_MAJ] * 100 * si->sensing_conf_data.res_x;
touch->abs[CY_TCH_MAJ] = tmp / si->sensing_conf_data.len_x;
tmp = touch->abs[CY_TCH_MIN] * 100 * si->sensing_conf_data.res_x;
touch->abs[CY_TCH_MIN] = tmp / si->sensing_conf_data.len_x;
dev_vdbg(dev, "%s: flip=%s inv-x=%s inv-y=%s x=%04X(%d) y=%04X(%d)\n",
__func__, flipped ? "true" : "false",
md->pdata->flags & CY_MT_FLAG_INV_X ? "true" : "false",
md->pdata->flags & CY_MT_FLAG_INV_Y ? "true" : "false",
touch->abs[CY_TCH_X], touch->abs[CY_TCH_X],
touch->abs[CY_TCH_Y], touch->abs[CY_TCH_Y]);
}
static void cyttsp5_report_event(struct cyttsp5_mt_data *md, int event,
int value)
{
int sig = MT_PARAM_SIGNAL(md, event);
if (sig != CY_IGNORE_VALUE)
input_report_abs(md->input, sig, value);
}
static void cyttsp5_get_mt_touches(struct cyttsp5_mt_data *md,
struct cyttsp5_touch *tch, int num_cur_tch)
{
struct device *dev = md->dev;
struct cyttsp5_sysinfo *si = md->si;
int sig;
int i, j, t = 0;
DECLARE_BITMAP(ids, si->tch_abs[CY_TCH_T].max);
int mt_sync_count = 0;
u8 *tch_addr;
bitmap_zero(ids, si->tch_abs[CY_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);
cyttsp5_get_touch_record(md, tch, tch_addr);
/* Discard proximity event */
if (tch->abs[CY_TCH_O] == CY_OBJ_PROXIMITY) {
dev_vdbg(dev, "%s: Discarding proximity event\n",
__func__);
continue;
}
/* Validate track_id */
t = tch->abs[CY_TCH_T];
if (t < md->t_min || t > md->t_max) {
dev_err(dev, "%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[CY_TCH_E] == CY_EV_LIFTOFF) {
dev_dbg(dev, "%s: t=%d e=%d lift-off\n",
__func__, t, tch->abs[CY_TCH_E]);
goto cyttsp5_get_mt_touches_pr_tch;
}
/* Process touch */
cyttsp5_mt_process_touch(md, tch);
/* use 0 based track id's */
t -= md->t_min;
sig = MT_PARAM_SIGNAL(md, CY_ABS_ID_OST);
if (sig != CY_IGNORE_VALUE) {
if (md->mt_function.input_report)
md->mt_function.input_report(md->input, sig,
t, tch->abs[CY_TCH_O]);
__set_bit(t, ids);
}
/* If touch type is hover, send P as distance, reset P */
if (tch->abs[CY_TCH_O] == CY_OBJ_HOVER) {
/* CY_ABS_D_OST signal must be in touch framework */
cyttsp5_report_event(md, CY_ABS_D_OST,
tch->abs[CY_TCH_P]);
tch->abs[CY_TCH_P] = 0;
} else
cyttsp5_report_event(md, CY_ABS_D_OST, 0);
/* all devices: position and pressure fields */
for (j = 0; j <= CY_ABS_W_OST; j++) {
if (!si->tch_abs[j].report)
continue;
cyttsp5_report_event(md, CY_ABS_X_OST + j,
tch->abs[CY_TCH_X + j]);
}
/* Get the extended touch fields */
for (j = 0; j < CY_NUM_EXT_TCH_FIELDS; j++) {
if (!si->tch_abs[CY_ABS_MAJ_OST + j].report)
continue;
cyttsp5_report_event(md, CY_ABS_MAJ_OST + j,
tch->abs[CY_TCH_MAJ + j]);
}
if (md->mt_function.input_sync)
md->mt_function.input_sync(md->input);
mt_sync_count++;
cyttsp5_get_mt_touches_pr_tch:
dev_dbg(dev,
"%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[CY_TCH_X],
tch->abs[CY_TCH_Y],
tch->abs[CY_TCH_P],
tch->abs[CY_TCH_MAJ],
tch->abs[CY_TCH_MIN],
tch->abs[CY_TCH_OR],
tch->abs[CY_TCH_E],
tch->abs[CY_TCH_O],
tch->abs[CY_TCH_TIP]);
}
if (md->mt_function.final_sync)
md->mt_function.final_sync(md->input,
si->tch_abs[CY_TCH_T].max, mt_sync_count, ids);
md->num_prv_rec = num_cur_tch;
}
/* read xy_data for all current touches */
static int cyttsp5_xy_worker(struct cyttsp5_mt_data *md)
{
struct device *dev = md->dev;
struct cyttsp5_sysinfo *si = md->si;
int max_tch = si->sensing_conf_data.max_tch;
struct cyttsp5_touch tch;
u8 num_cur_tch;
int rc = 0;
cyttsp5_get_touch_hdr(md, &tch, si->xy_mode + 3);
num_cur_tch = tch.hdr[CY_TCH_NUM];
if (num_cur_tch > max_tch) {
dev_err(dev, "%s: Num touch err detected (n=%d)\n",
__func__, num_cur_tch);
num_cur_tch = max_tch;
}
if (tch.hdr[CY_TCH_LO]) {
dev_dbg(dev, "%s: Large area detected\n", __func__);
if (md->pdata->flags & CY_MT_FLAG_NO_TOUCH_ON_LO)
num_cur_tch = 0;
}
if (num_cur_tch == 0 && md->num_prv_rec == 0)
goto cyttsp5_xy_worker_exit;
/* extract xy_data for all currently reported touches */
dev_vdbg(dev, "%s: extract data num_cur_tch=%d\n", __func__,
num_cur_tch);
if (num_cur_tch)
cyttsp5_get_mt_touches(md, &tch, num_cur_tch);
else
cyttsp5_mt_lift_all(md);
rc = 0;
cyttsp5_xy_worker_exit:
return rc;
}
static void cyttsp5_mt_send_dummy_event(struct cyttsp5_core_data *cd,
struct cyttsp5_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, CY_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 EasyWake */
u8 key_value;
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;
}
input_report_key(md->input, key_value, 1);
mdelay(10);
input_report_key(md->input, key_value, 0);
input_sync(md->input);
#endif
}
static int cyttsp5_mt_attention(struct device *dev)
{
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
struct cyttsp5_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 = cyttsp5_xy_worker(md);
mutex_unlock(&md->mt_lock);
if (rc < 0)
dev_err(dev, "%s: xy_worker error r=%d\n", __func__, rc);
return rc;
}
static int cyttsp5_mt_wake_attention(struct device *dev)
{
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
struct cyttsp5_mt_data *md = &cd->md;
mutex_lock(&md->mt_lock);
cyttsp5_mt_send_dummy_event(cd, md);
mutex_unlock(&md->mt_lock);
return 0;
}
static int cyttsp5_startup_attention(struct device *dev)
{
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
struct cyttsp5_mt_data *md = &cd->md;
mutex_lock(&md->mt_lock);
cyttsp5_mt_lift_all(md);
mutex_unlock(&md->mt_lock);
return 0;
}
static int cyttsp5_mt_suspend_attention(struct device *dev)
{
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
struct cyttsp5_mt_data *md = &cd->md;
mutex_lock(&md->mt_lock);
cyttsp5_mt_lift_all(md);
md->is_suspended = true;
mutex_unlock(&md->mt_lock);
pm_runtime_put(dev);
return 0;
}
static int cyttsp5_mt_resume_attention(struct device *dev)
{
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
struct cyttsp5_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;
}
static int cyttsp5_mt_open(struct input_dev *input)
{
struct device *dev = input->dev.parent;
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
struct cyttsp5_mt_data *md = &cd->md;
pm_runtime_get_sync(dev);
mutex_lock(&md->mt_lock);
md->is_suspended = false;
mutex_unlock(&md->mt_lock);
dev_vdbg(dev, "%s: setup subscriptions\n", __func__);
/* set up touch call back */
_cyttsp5_subscribe_attention(dev, CY_ATTEN_IRQ, CYTTSP5_MT_NAME,
cyttsp5_mt_attention, CY_MODE_OPERATIONAL);
/* set up startup call back */
_cyttsp5_subscribe_attention(dev, CY_ATTEN_STARTUP, CYTTSP5_MT_NAME,
cyttsp5_startup_attention, 0);
/* set up wakeup call back */
_cyttsp5_subscribe_attention(dev, CY_ATTEN_WAKE, CYTTSP5_MT_NAME,
cyttsp5_mt_wake_attention, 0);
/* set up suspend call back */
_cyttsp5_subscribe_attention(dev, CY_ATTEN_SUSPEND, CYTTSP5_MT_NAME,
cyttsp5_mt_suspend_attention, 0);
/* set up resume call back */
_cyttsp5_subscribe_attention(dev, CY_ATTEN_RESUME, CYTTSP5_MT_NAME,
cyttsp5_mt_resume_attention, 0);
return 0;
}
static void cyttsp5_mt_close(struct input_dev *input)
{
struct device *dev = input->dev.parent;
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
struct cyttsp5_mt_data *md = &cd->md;
_cyttsp5_unsubscribe_attention(dev, CY_ATTEN_IRQ, CYTTSP5_MT_NAME,
cyttsp5_mt_attention, CY_MODE_OPERATIONAL);
_cyttsp5_unsubscribe_attention(dev, CY_ATTEN_STARTUP, CYTTSP5_MT_NAME,
cyttsp5_startup_attention, 0);
_cyttsp5_unsubscribe_attention(dev, CY_ATTEN_WAKE, CYTTSP5_MT_NAME,
cyttsp5_mt_wake_attention, 0);
_cyttsp5_unsubscribe_attention(dev, CY_ATTEN_SUSPEND, CYTTSP5_MT_NAME,
cyttsp5_mt_suspend_attention, 0);
_cyttsp5_unsubscribe_attention(dev, CY_ATTEN_RESUME, CYTTSP5_MT_NAME,
cyttsp5_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);
}
static int cyttsp5_setup_input_device(struct device *dev)
{
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
struct cyttsp5_mt_data *md = &cd->md;
int signal = CY_IGNORE_VALUE;
int max_x, max_y, max_p, min, max;
int max_x_tmp, max_y_tmp;
int i;
int rc;
dev_vdbg(dev, "%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 & CY_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 & CY_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 != CY_IGNORE_VALUE) {
__set_bit(signal, md->input->absbit);
min = MT_PARAM_MIN(md, i);
max = MT_PARAM_MAX(md, i);
if (i == CY_ABS_ID_OST) {
/* shift track ids down to start at 0 */
max = max - min;
min = min - min;
} else if (i == CY_ABS_X_OST)
max = max_x;
else if (i == CY_ABS_Y_OST)
max = max_y;
else if (i == CY_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));
dev_dbg(dev, "%s: register signal=%02X min=%d max=%d\n",
__func__, signal, min, max);
}
}
md->or_min = MT_PARAM_MIN(md, CY_ABS_OR_OST);
md->or_max = MT_PARAM_MAX(md, CY_ABS_OR_OST);
md->t_min = MT_PARAM_MIN(md, CY_ABS_ID_OST);
md->t_max = MT_PARAM_MAX(md, CY_ABS_ID_OST);
rc = md->mt_function.input_register_device(md->input,
md->si->tch_abs[CY_TCH_T].max);
if (rc < 0)
dev_err(dev, "%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;
}
static int cyttsp5_setup_input_attention(struct device *dev)
{
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
struct cyttsp5_mt_data *md = &cd->md;
int rc;
md->si = _cyttsp5_request_sysinfo(dev);
if (!md->si)
return -EINVAL;
rc = cyttsp5_setup_input_device(dev);
_cyttsp5_unsubscribe_attention(dev, CY_ATTEN_STARTUP, CYTTSP5_MT_NAME,
cyttsp5_setup_input_attention, 0);
return rc;
}
int cyttsp5_mt_probe(struct device *dev)
{
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
struct cyttsp5_mt_data *md = &cd->md;
struct cyttsp5_platform_data *pdata = dev_get_platdata(dev);
struct cyttsp5_mt_platform_data *mt_pdata;
int rc = 0;
if (!pdata || !pdata->mt_pdata) {
dev_err(dev, "%s: Missing platform data\n", __func__);
rc = -ENODEV;
goto error_no_pdata;
}
mt_pdata = pdata->mt_pdata;
cyttsp5_init_function_ptrs(md);
mutex_init(&md->mt_lock);
md->dev = dev;
md->pdata = mt_pdata;
/* Create the input device and register it. */
dev_vdbg(dev, "%s: Create the input device and register it\n",
__func__);
md->input = input_allocate_device();
if (!md->input) {
dev_err(dev, "%s: Error, failed to allocate input device\n",
__func__);
rc = -ENODEV;
goto error_alloc_failed;
}
if (md->pdata->inp_dev_name)
md->input->name = md->pdata->inp_dev_name;
else
md->input->name = CYTTSP5_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 = cyttsp5_mt_open;
md->input->close = cyttsp5_mt_close;
input_set_drvdata(md->input, md);
/* get sysinfo */
md->si = _cyttsp5_request_sysinfo(dev);
if (md->si) {
rc = cyttsp5_setup_input_device(dev);
if (rc)
goto error_init_input;
} else {
dev_err(dev, "%s: Fail get sysinfo pointer from core p=%p\n",
__func__, md->si);
_cyttsp5_subscribe_attention(dev, CY_ATTEN_STARTUP,
CYTTSP5_MT_NAME, cyttsp5_setup_input_attention, 0);
}
return 0;
error_init_input:
input_free_device(md->input);
error_alloc_failed:
error_no_pdata:
dev_err(dev, "%s failed.\n", __func__);
return rc;
}
int cyttsp5_mt_release(struct device *dev)
{
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
struct cyttsp5_mt_data *md = &cd->md;
if (md->input_device_registered) {
input_unregister_device(md->input);
} else {
input_free_device(md->input);
_cyttsp5_unsubscribe_attention(dev, CY_ATTEN_STARTUP,
CYTTSP5_MT_NAME, cyttsp5_setup_input_attention, 0);
}
return 0;
}

View file

@ -0,0 +1,85 @@
/*
* cyttsp5_mta.c
* Parade TrueTouch(TM) Standard Product V5 Multi-Touch Protocol A Module.
* For use with Parade touchscreen controllers.
* Supported parts include:
* CYTMA5XX
* CYTMA448
* CYTMA445A
* CYTT21XXX
* CYTT31XXX
*
* Copyright (C) 2015 Parade Technologies
* Copyright (C) 2012-2015 Cypress Semiconductor
*
* 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 "cyttsp5_regs.h"
static void cyttsp5_final_sync(struct input_dev *input, int max_slots,
int mt_sync_count, unsigned long *ids)
{
if (mt_sync_count)
input_sync(input);
}
static void cyttsp5_input_sync(struct input_dev *input)
{
input_mt_sync(input);
}
static void cyttsp5_input_report(struct input_dev *input, int sig,
int t, int type)
{
if (type == CY_OBJ_STANDARD_FINGER || type == CY_OBJ_GLOVE
|| type == CY_OBJ_HOVER) {
input_report_key(input, BTN_TOOL_FINGER, CY_BTN_PRESSED);
input_report_key(input, BTN_TOOL_PEN, CY_BTN_RELEASED);
} else if (type == CY_OBJ_STYLUS) {
input_report_key(input, BTN_TOOL_PEN, CY_BTN_PRESSED);
input_report_key(input, BTN_TOOL_FINGER, CY_BTN_RELEASED);
}
if (type != CY_OBJ_HOVER)
input_report_key(input, BTN_TOUCH, CY_BTN_PRESSED);
input_report_abs(input, sig, t);
}
static void cyttsp5_report_slot_liftoff(struct cyttsp5_mt_data *md,
int max_slots)
{
input_report_key(md->input, BTN_TOUCH, CY_BTN_RELEASED);
input_report_key(md->input, BTN_TOOL_FINGER, CY_BTN_RELEASED);
input_report_key(md->input, BTN_TOOL_PEN, CY_BTN_RELEASED);
}
static int cyttsp5_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);
}
void cyttsp5_init_function_ptrs(struct cyttsp5_mt_data *md)
{
md->mt_function.report_slot_liftoff = cyttsp5_report_slot_liftoff;
md->mt_function.final_sync = cyttsp5_final_sync;
md->mt_function.input_sync = cyttsp5_input_sync;
md->mt_function.input_report = cyttsp5_input_report;
md->mt_function.input_register_device = cyttsp5_input_register_device;
}

View file

@ -0,0 +1,93 @@
/*
* cyttsp5_mtb.c
* Parade TrueTouch(TM) Standard Product V5 Multi-Touch Protocol B Module.
* For use with Parade touchscreen controllers.
* Supported parts include:
* CYTMA5XX
* CYTMA448
* CYTMA445A
* CYTT21XXX
* CYTT31XXX
*
* Copyright (C) 2015 Parade Technologies
* Copyright (C) 2012-2015 Cypress Semiconductor
*
* 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 "cyttsp5_regs.h"
#include <linux/input/mt.h>
#include <linux/version.h>
static void cyttsp5_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);
}
static void cyttsp5_input_report(struct input_dev *input, int sig,
int t, int type)
{
input_mt_slot(input, t);
if (type == CY_OBJ_STANDARD_FINGER || type == CY_OBJ_GLOVE
|| type == CY_OBJ_HOVER)
input_mt_report_slot_state(input, MT_TOOL_FINGER, true);
else if (type == CY_OBJ_STYLUS)
input_mt_report_slot_state(input, MT_TOOL_PEN, true);
}
static void cyttsp5_report_slot_liftoff(struct cyttsp5_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);
}
}
static int cyttsp5_input_register_device(struct input_dev *input, int max_slots)
{
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0))
input_mt_init_slots(input, max_slots, 0);
#else
input_mt_init_slots(input, max_slots);
#endif
return input_register_device(input);
}
void cyttsp5_init_function_ptrs(struct cyttsp5_mt_data *md)
{
md->mt_function.report_slot_liftoff = cyttsp5_report_slot_liftoff;
md->mt_function.final_sync = cyttsp5_final_sync;
md->mt_function.input_sync = NULL;
md->mt_function.input_report = cyttsp5_input_report;
md->mt_function.input_register_device = cyttsp5_input_register_device;
}

View file

@ -0,0 +1,288 @@
/*
* cyttsp5_platform.c
* Parade TrueTouch(TM) Standard Product V5 Platform Module.
* For use with Parade touchscreen controllers.
* Supported parts include:
* CYTMA5XX
* CYTMA448
* CYTMA445A
* CYTT21XXX
* CYTT31XXX
*
* Copyright (C) 2015 Parade Technologies
* Copyright (C) 2013-2015 Cypress Semiconductor
*
* 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 "cyttsp5_regs.h"
#include <linux/cyttsp5_platform.h>
#ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_PLATFORM_FW_UPGRADE
/* FW for Panel ID = 0x00 */
#include "cyttsp5_fw_pid00.h"
static struct cyttsp5_touch_firmware cyttsp5_firmware_pid00 = {
.img = cyttsp4_img_pid00,
.size = ARRAY_SIZE(cyttsp4_img_pid00),
.ver = cyttsp4_ver_pid00,
.vsize = ARRAY_SIZE(cyttsp4_ver_pid00),
.panel_id = 0x00,
};
/* FW for Panel ID = 0x01 */
#include "cyttsp5_fw_pid01.h"
static struct cyttsp5_touch_firmware cyttsp5_firmware_pid01 = {
.img = cyttsp4_img_pid01,
.size = ARRAY_SIZE(cyttsp4_img_pid01),
.ver = cyttsp4_ver_pid01,
.vsize = ARRAY_SIZE(cyttsp4_ver_pid01),
.panel_id = 0x01,
};
/* FW for Panel ID not enabled (legacy) */
#include "cyttsp5_fw.h"
static struct cyttsp5_touch_firmware cyttsp5_firmware = {
.img = cyttsp4_img,
.size = ARRAY_SIZE(cyttsp4_img),
.ver = cyttsp4_ver,
.vsize = ARRAY_SIZE(cyttsp4_ver),
};
#else
/* FW for Panel ID not enabled (legacy) */
static struct cyttsp5_touch_firmware cyttsp5_firmware = {
.img = NULL,
.size = 0,
.ver = NULL,
.vsize = 0,
};
#endif
#ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_PLATFORM_TTCONFIG_UPGRADE
/* TT Config for Panel ID = 0x00 */
#include "cyttsp5_params_pid00.h"
static struct touch_settings cyttsp5_sett_param_regs_pid00 = {
.data = (uint8_t *)&cyttsp4_param_regs_pid00[0],
.size = ARRAY_SIZE(cyttsp4_param_regs_pid00),
.tag = 0,
};
static struct touch_settings cyttsp5_sett_param_size_pid00 = {
.data = (uint8_t *)&cyttsp4_param_size_pid00[0],
.size = ARRAY_SIZE(cyttsp4_param_size_pid00),
.tag = 0,
};
static struct cyttsp5_touch_config cyttsp5_ttconfig_pid00 = {
.param_regs = &cyttsp5_sett_param_regs_pid00,
.param_size = &cyttsp5_sett_param_size_pid00,
.fw_ver = ttconfig_fw_ver_pid00,
.fw_vsize = ARRAY_SIZE(ttconfig_fw_ver_pid00),
.panel_id = 0x00,
};
/* TT Config for Panel ID = 0x01 */
#include "cyttsp5_params_pid01.h"
static struct touch_settings cyttsp5_sett_param_regs_pid01 = {
.data = (uint8_t *)&cyttsp4_param_regs_pid01[0],
.size = ARRAY_SIZE(cyttsp4_param_regs_pid01),
.tag = 0,
};
static struct touch_settings cyttsp5_sett_param_size_pid01 = {
.data = (uint8_t *)&cyttsp4_param_size_pid01[0],
.size = ARRAY_SIZE(cyttsp4_param_size_pid01),
.tag = 0,
};
static struct cyttsp5_touch_config cyttsp5_ttconfig_pid01 = {
.param_regs = &cyttsp5_sett_param_regs_pid01,
.param_size = &cyttsp5_sett_param_size_pid01,
.fw_ver = ttconfig_fw_ver_pid01,
.fw_vsize = ARRAY_SIZE(ttconfig_fw_ver_pid01),
.panel_id = 0x01,
};
/* TT Config for Panel ID not enabled (legacy)*/
#include "cyttsp5_params.h"
static struct touch_settings cyttsp5_sett_param_regs = {
.data = (uint8_t *)&cyttsp4_param_regs[0],
.size = ARRAY_SIZE(cyttsp4_param_regs),
.tag = 0,
};
static struct touch_settings cyttsp5_sett_param_size = {
.data = (uint8_t *)&cyttsp4_param_size[0],
.size = ARRAY_SIZE(cyttsp4_param_size),
.tag = 0,
};
static struct cyttsp5_touch_config cyttsp5_ttconfig = {
.param_regs = &cyttsp5_sett_param_regs,
.param_size = &cyttsp5_sett_param_size,
.fw_ver = ttconfig_fw_ver,
.fw_vsize = ARRAY_SIZE(ttconfig_fw_ver),
};
#else
/* TT Config for Panel ID not enabled (legacy)*/
static struct cyttsp5_touch_config cyttsp5_ttconfig = {
.param_regs = NULL,
.param_size = NULL,
.fw_ver = NULL,
.fw_vsize = 0,
};
#endif
static struct cyttsp5_touch_firmware *cyttsp5_firmwares[] = {
#ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_PLATFORM_FW_UPGRADE
&cyttsp5_firmware_pid00,
&cyttsp5_firmware_pid01,
#endif
NULL, /* Last item should always be NULL */
};
static struct cyttsp5_touch_config *cyttsp5_ttconfigs[] = {
#ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_PLATFORM_TTCONFIG_UPGRADE
&cyttsp5_ttconfig_pid00,
&cyttsp5_ttconfig_pid01,
#endif
NULL, /* Last item should always be NULL */
};
struct cyttsp5_loader_platform_data _cyttsp5_loader_platform_data = {
.fw = &cyttsp5_firmware,
.ttconfig = &cyttsp5_ttconfig,
.fws = cyttsp5_firmwares,
.ttconfigs = cyttsp5_ttconfigs,
.flags = CY_LOADER_FLAG_NONE,
};
int cyttsp5_xres(struct cyttsp5_core_platform_data *pdata,
struct device *dev)
{
int rst_gpio = pdata->rst_gpio;
int rc = 0;
gpio_set_value(rst_gpio, 1);
msleep(20);
gpio_set_value(rst_gpio, 0);
msleep(40);
gpio_set_value(rst_gpio, 1);
msleep(20);
dev_info(dev,
"%s: RESET CYTTSP gpio=%d r=%d\n", __func__,
pdata->rst_gpio, rc);
return rc;
}
int cyttsp5_init(struct cyttsp5_core_platform_data *pdata,
int on, struct device *dev)
{
int rst_gpio = pdata->rst_gpio;
int irq_gpio = pdata->irq_gpio;
int rc = 0;
if (on) {
rc = gpio_request(rst_gpio, NULL);
if (rc < 0) {
gpio_free(rst_gpio);
rc = gpio_request(rst_gpio, NULL);
}
if (rc < 0) {
dev_err(dev,
"%s: Fail request gpio=%d\n", __func__,
rst_gpio);
} else {
rc = gpio_direction_output(rst_gpio, 1);
if (rc < 0) {
pr_err("%s: Fail set output gpio=%d\n",
__func__, rst_gpio);
gpio_free(rst_gpio);
} else {
rc = gpio_request(irq_gpio, NULL);
if (rc < 0) {
gpio_free(irq_gpio);
rc = gpio_request(irq_gpio,
NULL);
}
if (rc < 0) {
dev_err(dev,
"%s: Fail request gpio=%d\n",
__func__, irq_gpio);
gpio_free(rst_gpio);
} else {
gpio_direction_input(irq_gpio);
}
}
}
} else {
gpio_free(rst_gpio);
gpio_free(irq_gpio);
}
dev_info(dev, "%s: INIT CYTTSP RST gpio=%d and IRQ gpio=%d r=%d\n",
__func__, rst_gpio, irq_gpio, rc);
return rc;
}
static int cyttsp5_wakeup(struct cyttsp5_core_platform_data *pdata,
struct device *dev, atomic_t *ignore_irq)
{
return 0;
}
static int cyttsp5_sleep(struct cyttsp5_core_platform_data *pdata,
struct device *dev, atomic_t *ignore_irq)
{
return 0;
}
int cyttsp5_power(struct cyttsp5_core_platform_data *pdata,
int on, struct device *dev, atomic_t *ignore_irq)
{
if (on)
return cyttsp5_wakeup(pdata, dev, ignore_irq);
return cyttsp5_sleep(pdata, dev, ignore_irq);
}
int cyttsp5_irq_stat(struct cyttsp5_core_platform_data *pdata,
struct device *dev)
{
return gpio_get_value(pdata->irq_gpio);
}
#ifdef CYTTSP5_DETECT_HW
int cyttsp5_detect(struct cyttsp5_core_platform_data *pdata,
struct device *dev, cyttsp5_platform_read read)
{
int retry = 3;
int rc;
char buf[1];
while (retry--) {
/* Perform reset, wait for 100 ms and perform read */
dev_vdbg(dev, "%s: Performing a reset\n", __func__);
pdata->xres(pdata, dev);
msleep(100);
rc = read(dev, buf, 1);
if (!rc)
return 0;
dev_vdbg(dev, "%s: Read unsuccessful, try=%d\n",
__func__, 3 - retry);
}
return rc;
}
#endif

View file

@ -0,0 +1,553 @@
/*
* cyttsp5_proximity.c
* Parade TrueTouch(TM) Standard Product V5 Proximity Module.
* For use with Parade touchscreen controllers.
* Supported parts include:
* CYTMA5XX
* CYTMA448
* CYTMA445A
* CYTT21XXX
* CYTT31XXX
*
* Copyright (C) 2015 Parade Technologies
* Copyright (C) 2013-2015 Cypress Semiconductor
*
* 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 "cyttsp5_regs.h"
#define CYTTSP5_PROXIMITY_NAME "cyttsp5_proximity"
/* Timeout value in ms. */
#define CYTTSP5_PROXIMITY_REQUEST_EXCLUSIVE_TIMEOUT 1000
#define CYTTSP5_PROXIMITY_ON 0
#define CYTTSP5_PROXIMITY_OFF 1
static inline struct cyttsp5_proximity_data *get_prox_data(struct device *dev)
{
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
return &cd->pd;
}
static void cyttsp5_report_proximity(struct cyttsp5_proximity_data *pd,
bool on)
{
int val = on ? CYTTSP5_PROXIMITY_ON : CYTTSP5_PROXIMITY_OFF;
input_report_abs(pd->input, ABS_DISTANCE, val);
input_sync(pd->input);
}
static void cyttsp5_get_touch_axis(struct cyttsp5_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++) {
dev_vdbg(pd->dev,
"%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;
dev_vdbg(pd->dev,
"%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]);
}
static void cyttsp5_get_touch_hdr(struct cyttsp5_proximity_data *pd,
struct cyttsp5_touch *touch, u8 *xy_mode)
{
struct device *dev = pd->dev;
struct cyttsp5_sysinfo *si = pd->si;
enum cyttsp5_tch_hdr hdr;
for (hdr = CY_TCH_TIME; hdr < CY_TCH_NUM_HDR; hdr++) {
if (!si->tch_hdr[hdr].report)
continue;
cyttsp5_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);
dev_vdbg(dev, "%s: get %s=%04X(%d)\n", __func__,
cyttsp5_tch_hdr_string[hdr],
touch->hdr[hdr], touch->hdr[hdr]);
}
}
static void cyttsp5_get_touch(struct cyttsp5_proximity_data *pd,
struct cyttsp5_touch *touch, u8 *xy_data)
{
struct device *dev = pd->dev;
struct cyttsp5_sysinfo *si = pd->si;
enum cyttsp5_tch_abs abs;
for (abs = CY_TCH_X; abs < CY_TCH_NUM_ABS; abs++) {
if (!si->tch_abs[abs].report)
continue;
cyttsp5_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);
dev_vdbg(dev, "%s: get %s=%04X(%d)\n", __func__,
cyttsp5_tch_abs_string[abs],
touch->abs[abs], touch->abs[abs]);
}
dev_vdbg(dev, "%s: x=%04X(%d) y=%04X(%d)\n", __func__,
touch->abs[CY_TCH_X], touch->abs[CY_TCH_X],
touch->abs[CY_TCH_Y], touch->abs[CY_TCH_Y]);
}
static void cyttsp5_get_proximity_touch(struct cyttsp5_proximity_data *pd,
struct cyttsp5_touch *tch, int num_cur_tch)
{
struct cyttsp5_sysinfo *si = pd->si;
int i;
for (i = 0; i < num_cur_tch; i++) {
cyttsp5_get_touch(pd, tch, si->xy_data +
(i * si->desc.tch_record_size));
/* Check for proximity event */
if (tch->abs[CY_TCH_O] == CY_OBJ_PROXIMITY) {
if (tch->abs[CY_TCH_E] == CY_EV_TOUCHDOWN)
cyttsp5_report_proximity(pd, true);
else if (tch->abs[CY_TCH_E] == CY_EV_LIFTOFF)
cyttsp5_report_proximity(pd, false);
break;
}
}
}
/* read xy_data for all current touches */
static int cyttsp5_xy_worker(struct cyttsp5_proximity_data *pd)
{
struct device *dev = pd->dev;
struct cyttsp5_sysinfo *si = pd->si;
struct cyttsp5_touch tch;
u8 num_cur_tch;
cyttsp5_get_touch_hdr(pd, &tch, si->xy_mode + 3);
num_cur_tch = tch.hdr[CY_TCH_NUM];
if (num_cur_tch > si->sensing_conf_data.max_tch) {
dev_err(dev, "%s: Num touch err detected (n=%d)\n",
__func__, num_cur_tch);
num_cur_tch = si->sensing_conf_data.max_tch;
}
if (tch.hdr[CY_TCH_LO])
dev_dbg(dev, "%s: Large area detected\n", __func__);
/* extract xy_data for all currently reported touches */
dev_vdbg(dev, "%s: extract data num_cur_rec=%d\n", __func__,
num_cur_tch);
if (num_cur_tch)
cyttsp5_get_proximity_touch(pd, &tch, num_cur_tch);
else
cyttsp5_report_proximity(pd, false);
return 0;
}
static int cyttsp5_proximity_attention(struct device *dev)
{
struct cyttsp5_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 = cyttsp5_xy_worker(pd);
mutex_unlock(&pd->prox_lock);
if (rc < 0)
dev_err(dev, "%s: xy_worker error r=%d\n", __func__, rc);
return rc;
}
static int cyttsp5_startup_attention(struct device *dev)
{
struct cyttsp5_proximity_data *pd = get_prox_data(dev);
mutex_lock(&pd->prox_lock);
cyttsp5_report_proximity(pd, false);
mutex_unlock(&pd->prox_lock);
return 0;
}
static int _cyttsp5_set_proximity_via_touchmode_enabled(
struct cyttsp5_proximity_data *pd, bool enable)
{
struct device *dev = pd->dev;
u32 touchmode_enabled;
int rc;
rc = cyttsp5_request_nonhid_get_param(dev, 0,
CY_RAM_ID_TOUCHMODE_ENABLED, &touchmode_enabled);
if (rc)
return rc;
if (enable)
touchmode_enabled |= 0x80;
else
touchmode_enabled &= 0x7F;
rc = cyttsp5_request_nonhid_set_param(dev, 0,
CY_RAM_ID_TOUCHMODE_ENABLED, touchmode_enabled,
CY_RAM_ID_TOUCHMODE_ENABLED_SIZE);
return rc;
}
static int _cyttsp5_set_proximity_via_proximity_enable(
struct cyttsp5_proximity_data *pd, bool enable)
{
struct device *dev = pd->dev;
u32 proximity_enable;
int rc;
rc = cyttsp5_request_nonhid_get_param(dev, 0,
CY_RAM_ID_PROXIMITY_ENABLE, &proximity_enable);
if (rc)
return rc;
if (enable)
proximity_enable |= 0x01;
else
proximity_enable &= 0xFE;
rc = cyttsp5_request_nonhid_set_param(dev, 0,
CY_RAM_ID_PROXIMITY_ENABLE, proximity_enable,
CY_RAM_ID_PROXIMITY_ENABLE_SIZE);
return rc;
}
static int _cyttsp5_set_proximity(struct cyttsp5_proximity_data *pd,
bool enable)
{
if (!IS_PIP_VER_GE(pd->si, 1, 4))
return _cyttsp5_set_proximity_via_touchmode_enabled(pd,
enable);
return _cyttsp5_set_proximity_via_proximity_enable(pd, enable);
}
static int _cyttsp5_proximity_enable(struct cyttsp5_proximity_data *pd)
{
struct device *dev = pd->dev;
int rc = 0;
pm_runtime_get_sync(dev);
rc = cyttsp5_request_exclusive(dev,
CYTTSP5_PROXIMITY_REQUEST_EXCLUSIVE_TIMEOUT);
if (rc < 0) {
dev_err(dev, "%s: Error on request exclusive r=%d\n",
__func__, rc);
goto exit;
}
rc = _cyttsp5_set_proximity(pd, true);
if (rc < 0) {
dev_err(dev, "%s: Error on request enable proximity scantype r=%d\n",
__func__, rc);
goto exit_release;
}
dev_vdbg(dev, "%s: setup subscriptions\n", __func__);
/* set up touch call back */
_cyttsp5_subscribe_attention(dev, CY_ATTEN_IRQ, CYTTSP5_PROXIMITY_NAME,
cyttsp5_proximity_attention, CY_MODE_OPERATIONAL);
/* set up startup call back */
_cyttsp5_subscribe_attention(dev, CY_ATTEN_STARTUP,
CYTTSP5_PROXIMITY_NAME, cyttsp5_startup_attention, 0);
exit_release:
cyttsp5_release_exclusive(dev);
exit:
return rc;
}
static int _cyttsp5_proximity_disable(struct cyttsp5_proximity_data *pd,
bool force)
{
struct device *dev = pd->dev;
int rc = 0;
rc = cyttsp5_request_exclusive(dev,
CYTTSP5_PROXIMITY_REQUEST_EXCLUSIVE_TIMEOUT);
if (rc < 0) {
dev_err(dev, "%s: Error on request exclusive r=%d\n",
__func__, rc);
goto exit;
}
rc = _cyttsp5_set_proximity(pd, false);
if (rc < 0) {
dev_err(dev, "%s: Error on request disable proximity scan r=%d\n",
__func__, rc);
goto exit_release;
}
exit_release:
cyttsp5_release_exclusive(dev);
exit:
if (!rc || force) {
_cyttsp5_unsubscribe_attention(dev, CY_ATTEN_IRQ,
CYTTSP5_PROXIMITY_NAME, cyttsp5_proximity_attention,
CY_MODE_OPERATIONAL);
_cyttsp5_unsubscribe_attention(dev, CY_ATTEN_STARTUP,
CYTTSP5_PROXIMITY_NAME, cyttsp5_startup_attention, 0);
}
pm_runtime_put(dev);
return rc;
}
static ssize_t cyttsp5_proximity_enable_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct cyttsp5_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, CY_MAX_PRBUF_SIZE, "%d\n", val);
}
static ssize_t cyttsp5_proximity_enable_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct cyttsp5_proximity_data *pd = get_prox_data(dev);
unsigned long value;
int rc;
rc = kstrtoul(buf, 10, &value);
if (rc < 0 || (value != 0 && value != 1)) {
dev_err(dev, "%s: Invalid value\n", __func__);
return -EINVAL;
}
mutex_lock(&pd->sysfs_lock);
if (value) {
if (pd->enable_count++) {
dev_vdbg(dev, "%s: '%s' already enabled\n", __func__,
pd->input->name);
} else {
rc = _cyttsp5_proximity_enable(pd);
if (rc)
pd->enable_count--;
}
} else {
if (--pd->enable_count) {
if (pd->enable_count < 0) {
dev_err(dev, "%s: '%s' unbalanced disable\n",
__func__, pd->input->name);
pd->enable_count = 0;
}
} else {
rc = _cyttsp5_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, S_IRUSR | S_IWUSR,
cyttsp5_proximity_enable_show,
cyttsp5_proximity_enable_store);
static int cyttsp5_setup_input_device_and_sysfs(struct device *dev)
{
struct cyttsp5_proximity_data *pd = get_prox_data(dev);
int signal = CY_IGNORE_VALUE;
int i;
int rc;
rc = device_create_file(dev, &dev_attr_prox_enable);
if (rc) {
dev_err(dev, "%s: Error, could not create enable\n",
__func__);
goto exit;
}
dev_vdbg(dev, "%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 != CY_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) {
dev_err(dev, "%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;
}
static int cyttsp5_setup_input_attention(struct device *dev)
{
struct cyttsp5_proximity_data *pd = get_prox_data(dev);
int rc;
pd->si = _cyttsp5_request_sysinfo(dev);
if (!pd->si)
return -EINVAL;
rc = cyttsp5_setup_input_device_and_sysfs(dev);
if (!rc)
rc = _cyttsp5_set_proximity(pd, false);
_cyttsp5_unsubscribe_attention(dev, CY_ATTEN_STARTUP,
CYTTSP5_PROXIMITY_NAME, cyttsp5_setup_input_attention, 0);
return rc;
}
int cyttsp5_proximity_probe(struct device *dev)
{
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
struct cyttsp5_proximity_data *pd = &cd->pd;
struct cyttsp5_platform_data *pdata = dev_get_platdata(dev);
struct cyttsp5_proximity_platform_data *prox_pdata;
int rc = 0;
if (!pdata || !pdata->prox_pdata) {
dev_err(dev, "%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. */
dev_vdbg(dev, "%s: Create the input device and register it\n",
__func__);
pd->input = input_allocate_device();
if (!pd->input) {
dev_err(dev, "%s: Error, failed to allocate input device\n",
__func__);
rc = -ENODEV;
goto error_alloc_failed;
}
if (pd->pdata->inp_dev_name)
pd->input->name = pd->pdata->inp_dev_name;
else
pd->input->name = CYTTSP5_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 = _cyttsp5_request_sysinfo(dev);
if (pd->si) {
rc = cyttsp5_setup_input_device_and_sysfs(dev);
if (rc)
goto error_init_input;
rc = _cyttsp5_set_proximity(pd, false);
} else {
dev_err(dev, "%s: Fail get sysinfo pointer from core p=%p\n",
__func__, pd->si);
_cyttsp5_subscribe_attention(dev, CY_ATTEN_STARTUP,
CYTTSP5_PROXIMITY_NAME, cyttsp5_setup_input_attention,
0);
}
return 0;
error_init_input:
input_free_device(pd->input);
error_alloc_failed:
error_no_pdata:
dev_err(dev, "%s failed.\n", __func__);
return rc;
}
int cyttsp5_proximity_release(struct device *dev)
{
struct cyttsp5_proximity_data *pd = get_prox_data(dev);
if (pd->input_device_registered) {
/* Disable proximity sensing */
mutex_lock(&pd->sysfs_lock);
if (pd->enable_count)
_cyttsp5_proximity_disable(pd, true);
mutex_unlock(&pd->sysfs_lock);
device_remove_file(dev, &dev_attr_prox_enable);
input_unregister_device(pd->input);
} else {
input_free_device(pd->input);
_cyttsp5_unsubscribe_attention(dev, CY_ATTEN_STARTUP,
CYTTSP5_PROXIMITY_NAME, cyttsp5_setup_input_attention,
0);
}
return 0;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,254 @@
/*
* cyttsp5_spi.c
* Parade TrueTouch(TM) Standard Product V5 SPI Module.
* For use with Parade touchscreen controllers.
* Supported parts include:
* CYTMA5XX
* CYTMA448
* CYTMA445A
* CYTT21XXX
* CYTT31XXX
*
* Copyright (C) 2015 Parade Technologies
* Copyright (C) 2012-2015 Cypress Semiconductor
*
* 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 "cyttsp5_regs.h"
#include <linux/spi/spi.h>
#include <linux/version.h>
#define CY_SPI_WR_OP 0x00 /* r/~w */
#define CY_SPI_RD_OP 0x01
#define CY_SPI_BITS_PER_WORD 8
#define CY_SPI_SYNC_ACK 0x62
#define CY_SPI_CMD_BYTES 0
#define CY_SPI_DATA_SIZE (2 * 256)
#define CY_SPI_DATA_BUF_SIZE (CY_SPI_CMD_BYTES + CY_SPI_DATA_SIZE)
static void cyttsp5_spi_add_rw_msg(struct spi_message *msg,
struct spi_transfer *xfer, u8 *w_header, u8 *r_header, u8 op)
{
xfer->tx_buf = w_header;
xfer->rx_buf = r_header;
w_header[0] = op;
xfer->len = 1;
spi_message_add_tail(xfer, msg);
}
static int cyttsp5_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[2];
u8 w_header[2];
u8 r_header[2];
int rc;
memset(xfer, 0, sizeof(xfer));
spi_message_init(&msg);
cyttsp5_spi_add_rw_msg(&msg, &xfer[0], w_header, r_header, op);
switch (op) {
case CY_SPI_RD_OP:
xfer[1].rx_buf = buf;
xfer[1].len = length;
spi_message_add_tail(&xfer[1], &msg);
break;
case CY_SPI_WR_OP:
xfer[1].tx_buf = buf;
xfer[1].len = length;
spi_message_add_tail(&xfer[1], &msg);
break;
default:
rc = -EIO;
goto exit;
}
rc = spi_sync(spi, &msg);
exit:
if (rc < 0)
dev_vdbg(dev, "%s: spi_sync() error %d\n", __func__, rc);
if (r_header[0] != CY_SPI_SYNC_ACK)
return -EIO;
return rc;
}
static int cyttsp5_spi_read_default(struct device *dev, void *buf, int size)
{
if (!buf || !size)
return 0;
return cyttsp5_spi_xfer(dev, CY_SPI_RD_OP, buf, size);
}
static int cyttsp5_spi_read_default_nosize(struct device *dev, u8 *buf, u32 max)
{
u32 size;
int rc;
if (!buf)
return 0;
rc = cyttsp5_spi_xfer(dev, CY_SPI_RD_OP, buf, 2);
if (rc < 0)
return rc;
size = get_unaligned_le16(&buf[0]);
if (!size)
return rc;
if (size > max)
return -EINVAL;
return cyttsp5_spi_read_default(dev, buf, size);
}
static int cyttsp5_spi_write_read_specific(struct device *dev, u8 write_len,
u8 *write_buf, u8 *read_buf)
{
int rc;
rc = cyttsp5_spi_xfer(dev, CY_SPI_WR_OP, write_buf, write_len);
if (rc < 0)
return rc;
if (read_buf)
rc = cyttsp5_spi_read_default_nosize(dev, read_buf,
CY_SPI_DATA_SIZE);
return rc;
}
static struct cyttsp5_bus_ops cyttsp5_spi_bus_ops = {
.bustype = BUS_SPI,
.read_default = cyttsp5_spi_read_default,
.read_default_nosize = cyttsp5_spi_read_default_nosize,
.write_read_specific = cyttsp5_spi_write_read_specific,
};
#ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_DEVICETREE_SUPPORT
static const struct of_device_id cyttsp5_spi_of_match[] = {
{ .compatible = "cy,cyttsp5_spi_adapter", },
{ }
};
MODULE_DEVICE_TABLE(of, cyttsp5_spi_of_match);
#endif
static int cyttsp5_spi_probe(struct spi_device *spi)
{
struct device *dev = &spi->dev;
#ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_DEVICETREE_SUPPORT
const struct of_device_id *match;
#endif
int rc;
/* Set up SPI*/
spi->bits_per_word = CY_SPI_BITS_PER_WORD;
spi->mode = SPI_MODE_0;
rc = spi_setup(spi);
if (rc < 0) {
dev_err(dev, "%s: SPI setup error %d\n", __func__, rc);
return rc;
}
#ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_DEVICETREE_SUPPORT
match = of_match_device(of_match_ptr(cyttsp5_spi_of_match), dev);
if (match) {
rc = cyttsp5_devtree_create_and_get_pdata(dev);
if (rc < 0)
return rc;
}
#endif
rc = cyttsp5_probe(&cyttsp5_spi_bus_ops, &spi->dev, spi->irq,
CY_SPI_DATA_BUF_SIZE);
#ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_DEVICETREE_SUPPORT
if (rc && match)
cyttsp5_devtree_clean_pdata(dev);
#endif
return rc;
}
static int cyttsp5_spi_remove(struct spi_device *spi)
{
#ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_DEVICETREE_SUPPORT
struct device *dev = &spi->dev;
const struct of_device_id *match;
#endif
struct cyttsp5_core_data *cd = dev_get_drvdata(&spi->dev);
cyttsp5_release(cd);
#ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_DEVICETREE_SUPPORT
match = of_match_device(of_match_ptr(cyttsp5_spi_of_match), dev);
if (match)
cyttsp5_devtree_clean_pdata(dev);
#endif
return 0;
}
static const struct spi_device_id cyttsp5_spi_id[] = {
{ CYTTSP5_SPI_NAME, 0 },
{ }
};
MODULE_DEVICE_TABLE(spi, cyttsp5_spi_id);
static struct spi_driver cyttsp5_spi_driver = {
.driver = {
.name = CYTTSP5_SPI_NAME,
.bus = &spi_bus_type,
.owner = THIS_MODULE,
.pm = &cyttsp5_pm_ops,
#ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_DEVICETREE_SUPPORT
.of_match_table = cyttsp5_spi_of_match,
#endif
},
.probe = cyttsp5_spi_probe,
.remove = (cyttsp5_spi_remove),
.id_table = cyttsp5_spi_id,
};
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
module_spi_driver(cyttsp5_spi_driver);
#else
static int __init cyttsp5_spi_init(void)
{
int err = spi_register_driver(&cyttsp5_spi_driver);
pr_info("%s: Parade TTSP SPI Driver (Built %s) rc=%d\n",
__func__, CY_DRIVER_VERSION, err);
return err;
}
module_init(cyttsp5_spi_init);
static void __exit cyttsp5_spi_exit(void)
{
spi_unregister_driver(&cyttsp5_spi_driver);
}
module_exit(cyttsp5_spi_exit);
#endif
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Parade TrueTouch(R) Standard Product SPI Driver");
MODULE_AUTHOR("Parade Technologies <ttdrivers@paradetech.com>");

View file

@ -0,0 +1,442 @@
/*
* cyttsp5_test_device_access_api.c
* Parade TrueTouch(TM) Standard Product V5 Device Access API test module.
* For use with Parade touchscreen controllers.
* Supported parts include:
* CYTMA5XX
* CYTMA448
* CYTMA445A
* CYTT21XXX
* CYTT31XXX
*
* Copyright (C) 2015 Parade Technologies
* Copyright (C) 2012-2015 Cypress Semiconductor
*
* 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 <linux/module.h>
#include <linux/cyttsp5_device_access-api.h>
#include <asm/unaligned.h>
#define BUFFER_SIZE 256
#define COMMAND_GET_SYSTEM_INFO 2
#define COMMAND_SUSPEND_SCANNING 3
#define COMMAND_RESUME_SCANNING 4
#define COMMAND_GET_PARAMETER 5
#define COMMAND_SET_PARAMETER 6
#define PARAMETER_ACTIVE_DISTANCE_2 0x0B
struct tt_output_report {
__le16 reg_address;
__le16 length;
u8 report_id;
u8 reserved;
u8 command;
u8 parameters[0];
} __packed;
struct tt_input_report {
__le16 length;
u8 report_id;
u8 reserved;
u8 command;
u8 return_data[0];
} __packed;
static int prepare_tt_output_report(struct tt_output_report *out,
u16 length, u8 command)
{
put_unaligned_le16(0x04, &out->reg_address);
put_unaligned_le16(5 + length, &out->length);
out->report_id = 0x2f;
out->reserved = 0x00;
out->command = command;
return 7 + length;
}
static int check_and_parse_tt_input_report(struct tt_input_report *in,
u16 *length, u8 *command)
{
if (in->report_id != 0x1f)
return -EINVAL;
*length = get_unaligned_le16(&in->length);
*command = in->command & 0x7f;
return 0;
}
static int prepare_get_system_info_report(u8 *buf)
{
struct tt_output_report *out = (struct tt_output_report *)buf;
return prepare_tt_output_report(out, 0, COMMAND_GET_SYSTEM_INFO);
}
static int check_get_system_info_response(u8 *buf, u16 read_length)
{
struct tt_input_report *in = (struct tt_input_report *)buf;
u16 length = 0;
u8 command = 0;
if (read_length != 51)
return -EINVAL;
if (check_and_parse_tt_input_report(in, &length, &command)
|| command != COMMAND_GET_SYSTEM_INFO
|| length != 51)
return -EINVAL;
pr_info("PIP Major Version: %d\n", in->return_data[0]);
pr_info("PIP Minor Version: %d\n", in->return_data[1]);
pr_info("Touch Firmware Product Id: %d\n",
get_unaligned_le16(&in->return_data[2]));
pr_info("Touch Firmware Major Version: %d\n", in->return_data[4]);
pr_info("Touch Firmware Minor Version: %d\n", in->return_data[5]);
pr_info("Touch Firmware Internal Revision Control Number: %d\n",
get_unaligned_le32(&in->return_data[6]));
pr_info("Customer Specified Firmware/Configuration Version: %d\n",
get_unaligned_le16(&in->return_data[10]));
pr_info("Bootloader Major Version: %d\n", in->return_data[12]);
pr_info("Bootloader Minor Version: %d\n", in->return_data[13]);
pr_info("Family ID: 0x%02x\n", in->return_data[14]);
pr_info("Revision ID: 0x%02x\n", in->return_data[15]);
pr_info("Silicon ID: 0x%02x\n",
get_unaligned_le16(&in->return_data[16]));
pr_info("Parade Manufacturing ID[0]: 0x%02x\n", in->return_data[18]);
pr_info("Parade Manufacturing ID[1]: 0x%02x\n", in->return_data[19]);
pr_info("Parade Manufacturing ID[2]: 0x%02x\n", in->return_data[20]);
pr_info("Parade Manufacturing ID[3]: 0x%02x\n", in->return_data[21]);
pr_info("Parade Manufacturing ID[4]: 0x%02x\n", in->return_data[22]);
pr_info("Parade Manufacturing ID[5]: 0x%02x\n", in->return_data[23]);
pr_info("Parade Manufacturing ID[6]: 0x%02x\n", in->return_data[24]);
pr_info("Parade Manufacturing ID[7]: 0x%02x\n", in->return_data[25]);
pr_info("POST Result Code: 0x%02x\n",
get_unaligned_le16(&in->return_data[26]));
pr_info("Number of X Electrodes: %d\n", in->return_data[28]);
pr_info("Number of Y Electrodes: %d\n", in->return_data[29]);
pr_info("Panel X Axis Length: %d\n",
get_unaligned_le16(&in->return_data[30]));
pr_info("Panel Y Axis Length: %d\n",
get_unaligned_le16(&in->return_data[32]));
pr_info("Panel X Axis Resolution: %d\n",
get_unaligned_le16(&in->return_data[34]));
pr_info("Panel Y Axis Resolution: %d\n",
get_unaligned_le16(&in->return_data[36]));
pr_info("Panel Pressure Resolution: %d\n",
get_unaligned_le16(&in->return_data[38]));
pr_info("X_ORG: %d\n", in->return_data[40]);
pr_info("Y_ORG: %d\n", in->return_data[41]);
pr_info("Panel ID: %d\n", in->return_data[42]);
pr_info("Buttons: 0x%02x\n", in->return_data[43]);
pr_info("BAL SELF MC: 0x%02x\n", in->return_data[44]);
pr_info("Max Number of Touch Records per Refresh Cycle: %d\n",
in->return_data[45]);
return 0;
}
static int prepare_get_parameter_report(u8 *buf, u8 parameter_id)
{
struct tt_output_report *out = (struct tt_output_report *)buf;
out->parameters[0] = parameter_id;
return prepare_tt_output_report(out, 1, COMMAND_GET_PARAMETER);
}
static int check_get_parameter_response(u8 *buf, u16 read_length,
u32 *parameter_value)
{
struct tt_input_report *in = (struct tt_input_report *)buf;
u16 length = 0;
u8 command = 0;
u32 param_value = 0;
u8 param_id;
u8 param_size = 0;
if (read_length != 8 && read_length != 9 && read_length != 11)
return -EINVAL;
if (check_and_parse_tt_input_report(in, &length, &command)
|| command != COMMAND_GET_PARAMETER
|| (length != 8 && length != 9 && length != 11))
return -EINVAL;
param_id = in->return_data[0];
param_size = in->return_data[1];
if (param_size == 1)
param_value = in->return_data[2];
else if (param_size == 2)
param_value = get_unaligned_le16(&in->return_data[2]);
else if (param_size == 4)
param_value = get_unaligned_le32(&in->return_data[2]);
else
return -EINVAL;
pr_info("%s: Parameter ID: 0x%02x Value: 0x%02x\n",
__func__, param_id, param_value);
if (parameter_value)
*parameter_value = param_value;
return 0;
}
static int prepare_set_parameter_report(u8 *buf, u8 parameter_id,
u8 parameter_size, u32 parameter_value)
{
struct tt_output_report *out = (struct tt_output_report *)buf;
out->parameters[0] = parameter_id;
out->parameters[1] = parameter_size;
if (parameter_size == 1)
out->parameters[2] = (u8)parameter_value;
else if (parameter_size == 2)
put_unaligned_le16(parameter_value, &out->parameters[2]);
else if (parameter_size == 4)
put_unaligned_le32(parameter_value, &out->parameters[2]);
else
return -EINVAL;
return prepare_tt_output_report(out, 2 + parameter_size,
COMMAND_SET_PARAMETER);
}
static int check_set_parameter_response(u8 *buf, u16 read_length)
{
struct tt_input_report *in = (struct tt_input_report *)buf;
u16 length = 0;
u8 command = 0;
u8 param_id;
u8 param_size = 0;
if (read_length != 7)
return -EINVAL;
if (check_and_parse_tt_input_report(in, &length, &command)
|| command != COMMAND_SET_PARAMETER
|| length != 7)
return -EINVAL;
param_id = in->return_data[0];
param_size = in->return_data[1];
pr_info("%s: Parameter ID: 0x%02x Size: 0x%02x\n",
__func__, param_id, param_size);
return 0;
}
static int prepare_suspend_scanning_report(u8 *buf)
{
struct tt_output_report *out = (struct tt_output_report *)buf;
return prepare_tt_output_report(out, 0, COMMAND_SUSPEND_SCANNING);
}
static int check_suspend_scanning_response(u8 *buf, u16 read_length)
{
struct tt_input_report *in = (struct tt_input_report *)buf;
u16 length = 0;
u8 command = 0;
if (read_length != 5)
return -EINVAL;
if (check_and_parse_tt_input_report(in, &length, &command)
|| command != COMMAND_SUSPEND_SCANNING
|| length != 5)
return -EINVAL;
return 0;
}
static int prepare_resume_scanning_report(u8 *buf)
{
struct tt_output_report *out = (struct tt_output_report *)buf;
return prepare_tt_output_report(out, 0, COMMAND_RESUME_SCANNING);
}
static int check_resume_scanning_response(u8 *buf, u16 read_length)
{
struct tt_input_report *in = (struct tt_input_report *)buf;
u16 length = 0;
u8 command = 0;
if (read_length != 5)
return -EINVAL;
if (check_and_parse_tt_input_report(in, &length, &command)
|| command != COMMAND_RESUME_SCANNING
|| length != 5)
return -EINVAL;
return 0;
}
void cyttsp5_user_command_async_cont(const char *core_name,
u16 read_len, u8 *read_buf, u16 write_len, u8 *write_buf,
u16 actual_read_length, int rc)
{
if (rc) {
pr_err("%s: suspend scan fails\n", __func__);
goto exit;
}
rc = check_suspend_scanning_response(read_buf, actual_read_length);
if (rc) {
pr_err("%s: check suspend scanning response fails\n", __func__);
goto exit;
}
pr_info("%s: suspend scanning succeeds\n", __func__);
exit:
return;
}
/* Read and write buffers */
static u8 write_buf[BUFFER_SIZE];
static u8 read_buf[BUFFER_SIZE];
static uint active_distance;
module_param(active_distance, uint, 0);
static int __init cyttsp5_test_device_access_api_init(void)
{
u32 initial_active_distance;
u16 actual_read_len;
int write_len;
int rc;
pr_info("%s: Enter\n", __func__);
/* CASE 1: Run get system information */
write_len = prepare_get_system_info_report(write_buf);
rc = cyttsp5_device_access_user_command(NULL, sizeof(read_buf),
read_buf, write_len, write_buf,
&actual_read_len);
if (rc)
goto exit;
rc = check_get_system_info_response(read_buf, actual_read_len);
if (rc)
goto exit;
/* CASE 2: Run get parameter (Active distance) */
write_len = prepare_get_parameter_report(write_buf,
PARAMETER_ACTIVE_DISTANCE_2);
rc = cyttsp5_device_access_user_command(NULL, sizeof(read_buf),
read_buf, write_len, write_buf,
&actual_read_len);
if (rc)
goto exit;
rc = check_get_parameter_response(read_buf, actual_read_len,
&initial_active_distance);
if (rc)
goto exit;
pr_info("%s: Initial Active Distance: %d\n",
__func__, initial_active_distance);
/* CASE 3: Run set parameter (Active distance) */
write_len = prepare_set_parameter_report(write_buf,
PARAMETER_ACTIVE_DISTANCE_2, 1,
active_distance);
rc = cyttsp5_device_access_user_command(NULL, sizeof(read_buf),
read_buf, write_len, write_buf,
&actual_read_len);
if (rc)
goto exit;
rc = check_set_parameter_response(read_buf, actual_read_len);
if (rc)
goto exit;
pr_info("%s: Active Distance set to %d\n", __func__, active_distance);
/* CASE 4: Run get parameter (Active distance) */
write_len = prepare_get_parameter_report(write_buf,
PARAMETER_ACTIVE_DISTANCE_2);
rc = cyttsp5_device_access_user_command(NULL, sizeof(read_buf),
read_buf, write_len, write_buf,
&actual_read_len);
if (rc)
goto exit;
rc = check_get_parameter_response(read_buf, actual_read_len,
&active_distance);
if (rc)
goto exit;
pr_info("%s: New Active Distance: %d\n", __func__, active_distance);
/* CASE 5: Run suspend scanning asynchronously */
write_len = prepare_suspend_scanning_report(write_buf);
preempt_disable();
rc = cyttsp5_device_access_user_command_async(NULL,
sizeof(read_buf), read_buf, write_len, write_buf,
cyttsp5_user_command_async_cont);
preempt_enable();
if (rc)
goto exit;
exit:
return rc;
}
module_init(cyttsp5_test_device_access_api_init);
static void __exit cyttsp5_test_device_access_api_exit(void)
{
u16 actual_read_len;
int write_len;
int rc;
/* CASE 6: Run resume scanning */
write_len = prepare_resume_scanning_report(write_buf);
rc = cyttsp5_device_access_user_command(NULL, sizeof(read_buf),
read_buf, write_len, write_buf,
&actual_read_len);
if (rc)
goto exit;
rc = check_resume_scanning_response(read_buf, actual_read_len);
if (rc)
goto exit;
pr_info("%s: resume scanning succeeds\n", __func__);
exit:
return;
}
module_exit(cyttsp5_test_device_access_api_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Parade TrueTouch(R) Standard Product Device Access Driver API Tester");
MODULE_AUTHOR("Parade Technologies <ttdrivers@paradetech.com>");