Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull input updates from Dmitry Torokhov: - a new driver for SparkFun Qwiic Joystick - pm8941-pwrkey driver now supports PMK8350 - a bunch of assorted driver fixes * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (44 commits) Input: joydev - prevent use of not validated data in JSIOCSBTNMAP ioctl Input: hideep - fix the uninitialized use in hideep_nvm_unlock() Input: trackpoint - use kobj_to_dev() Input: atkbd - use kobj_to_dev() Input: tsc200x-core - use kobj_to_dev() Input: ims-pcu - use kobj_to_dev() Input: cros_ec_keyb - use kobj_to_dev() API dt-bindings: input: touchscreen: st1232: Convert to json-schema Input: i8042 - fix typos in comments Input: add SparkFun Qwiic Joystick driver dt-bindings: Add vendor prefix and bindings for Qwiic Joystick Input: cy8ctmg110_ts - switch to using gpiod API Input: cy8ctmg110_ts - switch to using managed resources Input: cy8ctmg110_ts - use endian helpers when converting data on wire Input: cy8ctmg110_ts - let I2C core configure wake interrupt Input: cy8ctmg110_ts - do not hardcode as wakeup source Input: cy8ctmg110_ts - do not hard code interrupt trigger Input: cy8ctmg110_ts - rely on platform code to supply interrupt Input: resistive-adc-touch - fix uninitialized variable 'press' Input: pm8941-pwrkey - add support for PMK8350 PON_HLOS PMIC peripheral ...
This commit is contained in:
commit
1f89a590b2
@ -1,12 +0,0 @@
|
||||
* Freescale MMA8450 3-Axis Accelerometer
|
||||
|
||||
Required properties:
|
||||
- compatible : "fsl,mma8450".
|
||||
- reg: the I2C address of MMA8450
|
||||
|
||||
Example:
|
||||
|
||||
accelerometer: mma8450@1c {
|
||||
compatible = "fsl,mma8450";
|
||||
reg = <0x1c>;
|
||||
};
|
@ -8,6 +8,8 @@ PROPERTIES
|
||||
Definition: must be one of:
|
||||
"qcom,pm8941-pwrkey"
|
||||
"qcom,pm8941-resin"
|
||||
"qcom,pmk8350-pwrkey"
|
||||
"qcom,pmk8350-resin"
|
||||
|
||||
- reg:
|
||||
Usage: required
|
||||
|
@ -0,0 +1,148 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/input/touchscreen/cypress,cy8ctma340.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Cypress CY8CTMA340 series touchscreen controller bindings
|
||||
|
||||
description: The Cypress CY8CTMA340 series (also known as "CYTTSP" after
|
||||
the marketing name Cypress TrueTouch Standard Product) touchscreens can
|
||||
be connected to either I2C or SPI buses.
|
||||
|
||||
maintainers:
|
||||
- Javier Martinez Canillas <javier@dowhile0.org>
|
||||
- Linus Walleij <linus.walleij@linaro.org>
|
||||
|
||||
allOf:
|
||||
- $ref: touchscreen.yaml#
|
||||
|
||||
properties:
|
||||
$nodename:
|
||||
pattern: "^touchscreen(@.*)?$"
|
||||
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: cypress,cy8ctma340
|
||||
- const: cypress,cy8ctst341
|
||||
- const: cypress,cyttsp-spi
|
||||
description: Legacy compatible for SPI connected CY8CTMA340
|
||||
deprecated: true
|
||||
- const: cypress,cyttsp-i2c
|
||||
description: Legacy compatible for I2C connected CY8CTMA340
|
||||
deprecated: true
|
||||
|
||||
reg:
|
||||
description: I2C address when used on the I2C bus, or the SPI chip
|
||||
select index when used on the SPI bus
|
||||
|
||||
clock-frequency:
|
||||
description: I2C client clock frequency, defined for host when using
|
||||
the device on the I2C bus
|
||||
minimum: 0
|
||||
maximum: 400000
|
||||
|
||||
spi-max-frequency:
|
||||
description: SPI clock frequency, defined for host, defined when using
|
||||
the device on the SPI bus. The throughput is maximum 2 Mbps so the
|
||||
typical value is 2000000, if higher rates are used the total throughput
|
||||
needs to be restricted to 2 Mbps.
|
||||
minimum: 0
|
||||
maximum: 6000000
|
||||
|
||||
interrupts:
|
||||
description: Interrupt to host
|
||||
maxItems: 1
|
||||
|
||||
vcpin-supply:
|
||||
description: Analog power supply regulator on VCPIN pin
|
||||
|
||||
vdd-supply:
|
||||
description: Digital power supply regulator on VDD pin
|
||||
|
||||
reset-gpios:
|
||||
description: Reset line for the touchscreen, should be tagged
|
||||
as GPIO_ACTIVE_LOW
|
||||
|
||||
bootloader-key:
|
||||
description: the 8-byte bootloader key that is required to switch
|
||||
the chip from bootloader mode (default mode) to application mode
|
||||
$ref: /schemas/types.yaml#/definitions/uint8-array
|
||||
minItems: 8
|
||||
maxItems: 8
|
||||
|
||||
touchscreen-size-x: true
|
||||
touchscreen-size-y: true
|
||||
touchscreen-fuzz-x: true
|
||||
touchscreen-fuzz-y: true
|
||||
|
||||
active-distance:
|
||||
description: the distance in pixels beyond which a touch must move
|
||||
before movement is detected and reported by the device
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
minimum: 0
|
||||
maximum: 15
|
||||
|
||||
active-interval-ms:
|
||||
description: the minimum period in ms between consecutive
|
||||
scanning/processing cycles when the chip is in active mode
|
||||
minimum: 0
|
||||
maximum: 255
|
||||
|
||||
lowpower-interval-ms:
|
||||
description: the minimum period in ms between consecutive
|
||||
scanning/processing cycles when the chip is in low-power mode
|
||||
minimum: 0
|
||||
maximum: 2550
|
||||
|
||||
touch-timeout-ms:
|
||||
description: minimum time in ms spent in the active power state while no
|
||||
touches are detected before entering low-power mode
|
||||
minimum: 0
|
||||
maximum: 2550
|
||||
|
||||
use-handshake:
|
||||
description: enable register-based handshake (boolean). This should only
|
||||
be used if the chip is configured to use 'blocking communication with
|
||||
timeout' (in this case the device generates an interrupt at the end of
|
||||
every scanning/processing cycle)
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- bootloader-key
|
||||
- touchscreen-size-x
|
||||
- touchscreen-size-y
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
num-cs = <1>;
|
||||
cs-gpios = <&gpio 2 GPIO_ACTIVE_HIGH>;
|
||||
|
||||
touchscreen@0 {
|
||||
compatible = "cypress,cy8ctma340";
|
||||
reg = <0>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <20 IRQ_TYPE_EDGE_FALLING>;
|
||||
reset-gpios = <&gpio 21 GPIO_ACTIVE_LOW>;
|
||||
vdd-supply = <&ldo_aux1_reg>;
|
||||
vcpin-supply = <&ldo_aux2_reg>;
|
||||
bootloader-key = /bits/ 8 <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07>;
|
||||
touchscreen-size-x = <480>;
|
||||
touchscreen-size-y = <800>;
|
||||
active-interval-ms = <0>;
|
||||
touch-timeout-ms = <255>;
|
||||
lowpower-interval-ms = <10>;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
@ -1,93 +0,0 @@
|
||||
* Cypress cyttsp touchscreen controller
|
||||
|
||||
Required properties:
|
||||
- compatible : must be "cypress,cyttsp-i2c" or "cypress,cyttsp-spi"
|
||||
- reg : Device I2C address or SPI chip select number
|
||||
- spi-max-frequency : Maximum SPI clocking speed of the device (for cyttsp-spi)
|
||||
- interrupts : (gpio) interrupt to which the chip is connected
|
||||
(see interrupt binding[0]).
|
||||
- bootloader-key : the 8-byte bootloader key that is required to switch
|
||||
the chip from bootloader mode (default mode) to
|
||||
application mode.
|
||||
This property has to be specified as an array of 8
|
||||
'/bits/ 8' values.
|
||||
|
||||
Optional properties:
|
||||
- reset-gpios : the reset gpio the chip is connected to
|
||||
(see GPIO binding[1] for more details).
|
||||
- touchscreen-size-x : horizontal resolution of touchscreen (in pixels)
|
||||
- touchscreen-size-y : vertical resolution of touchscreen (in pixels)
|
||||
- touchscreen-fuzz-x : horizontal noise value of the absolute input device
|
||||
(in pixels)
|
||||
- touchscreen-fuzz-y : vertical noise value of the absolute input device
|
||||
(in pixels)
|
||||
- active-distance : the distance in pixels beyond which a touch must move
|
||||
before movement is detected and reported by the device.
|
||||
Valid values: 0-15.
|
||||
- active-interval-ms : the minimum period in ms between consecutive
|
||||
scanning/processing cycles when the chip is in active mode.
|
||||
Valid values: 0-255.
|
||||
- lowpower-interval-ms : the minimum period in ms between consecutive
|
||||
scanning/processing cycles when the chip is in low-power mode.
|
||||
Valid values: 0-2550
|
||||
- touch-timeout-ms : minimum time in ms spent in the active power state while no
|
||||
touches are detected before entering low-power mode.
|
||||
Valid values: 0-2550
|
||||
- use-handshake : enable register-based handshake (boolean). This should
|
||||
only be used if the chip is configured to use 'blocking
|
||||
communication with timeout' (in this case the device
|
||||
generates an interrupt at the end of every
|
||||
scanning/processing cycle).
|
||||
|
||||
[0]: Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
|
||||
[1]: Documentation/devicetree/bindings/gpio/gpio.txt
|
||||
|
||||
Example:
|
||||
&i2c1 {
|
||||
/* ... */
|
||||
cyttsp@a {
|
||||
compatible = "cypress,cyttsp-i2c";
|
||||
reg = <0xa>;
|
||||
interrupt-parent = <&gpio0>;
|
||||
interrupts = <28 0>;
|
||||
reset-gpios = <&gpio3 4 GPIO_ACTIVE_LOW>;
|
||||
|
||||
touchscreen-size-x = <800>;
|
||||
touchscreen-size-y = <480>;
|
||||
touchscreen-fuzz-x = <4>;
|
||||
touchscreen-fuzz-y = <7>;
|
||||
|
||||
bootloader-key = /bits/ 8 <0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08>;
|
||||
active-distance = <8>;
|
||||
active-interval-ms = <0>;
|
||||
lowpower-interval-ms = <200>;
|
||||
touch-timeout-ms = <100>;
|
||||
};
|
||||
|
||||
/* ... */
|
||||
};
|
||||
|
||||
&mcspi1 {
|
||||
/* ... */
|
||||
cyttsp@0 {
|
||||
compatible = "cypress,cyttsp-spi";
|
||||
spi-max-frequency = <6000000>;
|
||||
reg = <0>;
|
||||
interrupt-parent = <&gpio0>;
|
||||
interrupts = <28 0>;
|
||||
reset-gpios = <&gpio3 4 GPIO_ACTIVE_LOW>;
|
||||
|
||||
touchscreen-size-x = <800>;
|
||||
touchscreen-size-y = <480>;
|
||||
touchscreen-fuzz-x = <4>;
|
||||
touchscreen-fuzz-y = <7>;
|
||||
|
||||
bootloader-key = /bits/ 8 <0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08>;
|
||||
active-distance = <8>;
|
||||
active-interval-ms = <0>;
|
||||
lowpower-interval-ms = <200>;
|
||||
touch-timeout-ms = <100>;
|
||||
};
|
||||
|
||||
/* ... */
|
||||
};
|
@ -56,6 +56,7 @@ properties:
|
||||
wakeup-source: true
|
||||
|
||||
vcc-supply: true
|
||||
iovcc-supply: true
|
||||
|
||||
gain:
|
||||
description: Allows setting the sensitivity in the range from 0 to 31.
|
||||
|
@ -1,33 +0,0 @@
|
||||
Generic resistive touchscreen ADC
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: must be "resistive-adc-touch"
|
||||
The device must be connected to an ADC device that provides channels for
|
||||
position measurement and optional pressure.
|
||||
Refer to
|
||||
https://github.com/devicetree-org/dt-schema/blob/master/schemas/iio/iio-consumer.yaml
|
||||
for details
|
||||
|
||||
- iio-channels: must have at least two channels connected to an ADC device.
|
||||
These should correspond to the channels exposed by the ADC device and should
|
||||
have the right index as the ADC device registers them. These channels
|
||||
represent the relative position on the "x" and "y" axes.
|
||||
- iio-channel-names: must have all the channels' names. Mandatory channels
|
||||
are "x" and "y".
|
||||
|
||||
Optional properties:
|
||||
- iio-channels: The third channel named "pressure" is optional and can be
|
||||
used if the ADC device also measures pressure besides position.
|
||||
If this channel is missing, pressure will be ignored and the touchscreen
|
||||
will only report position.
|
||||
- iio-channel-names: optional channel named "pressure".
|
||||
|
||||
Example:
|
||||
|
||||
resistive_touch: resistive_touch {
|
||||
compatible = "resistive-adc-touch";
|
||||
touchscreen-min-pressure = <50000>;
|
||||
io-channels = <&adc 24>, <&adc 25>, <&adc 26>;
|
||||
io-channel-names = "x", "y", "pressure";
|
||||
};
|
@ -0,0 +1,86 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/input/touchscreen/resistive-adc-touch.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Generic resistive touchscreen ADC
|
||||
|
||||
maintainers:
|
||||
- Oleksij Rempel <o.rempel@pengutronix.de>
|
||||
|
||||
description: |
|
||||
Generic ADC based resistive touchscreen controller
|
||||
The device must be connected to an ADC device that provides channels for
|
||||
position measurement and optional pressure.
|
||||
|
||||
allOf:
|
||||
- $ref: touchscreen.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: resistive-adc-touch
|
||||
|
||||
io-channels:
|
||||
minItems: 2
|
||||
items:
|
||||
- description: x
|
||||
- description: y
|
||||
- description: pressure (optional)
|
||||
- description: z1 (optional)
|
||||
- description: z2 (optional)
|
||||
|
||||
io-channel-names:
|
||||
oneOf:
|
||||
- items:
|
||||
- enum: [x, y]
|
||||
- enum: [x, y]
|
||||
- items:
|
||||
- enum: [x, y, pressure]
|
||||
- enum: [x, y, pressure]
|
||||
- enum: [x, y, pressure]
|
||||
- items:
|
||||
- enum: [x, y, z1, z2]
|
||||
- enum: [x, y, z1, z2]
|
||||
- enum: [x, y, z1, z2]
|
||||
- enum: [x, y, z1, z2]
|
||||
|
||||
touchscreen-size-x: true
|
||||
touchscreen-size-y: true
|
||||
touchscreen-fuzz-x: true
|
||||
touchscreen-fuzz-y: true
|
||||
touchscreen-inverted-x: true
|
||||
touchscreen-inverted-y: true
|
||||
touchscreen-swapped-x-y: true
|
||||
touchscreen-min-pressure: true
|
||||
touchscreen-x-plate-ohms: true
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- io-channels
|
||||
- io-channel-names
|
||||
|
||||
examples:
|
||||
- |
|
||||
touchscreen {
|
||||
compatible = "resistive-adc-touch";
|
||||
io-channels = <&adc 24>, <&adc 25>;
|
||||
io-channel-names = "y", "x";
|
||||
};
|
||||
- |
|
||||
touchscreen {
|
||||
compatible = "resistive-adc-touch";
|
||||
touchscreen-min-pressure = <50000>;
|
||||
io-channels = <&adc 24>, <&adc 25>, <&adc 26>;
|
||||
io-channel-names = "y", "pressure", "x";
|
||||
};
|
||||
- |
|
||||
touchscreen {
|
||||
compatible = "resistive-adc-touch";
|
||||
touchscreen-min-pressure = <50000>;
|
||||
io-channels = <&adc 1>, <&adc 2>, <&adc 3>, <&adc 4>;
|
||||
io-channel-names = "x", "z1", "z2", "y";
|
||||
touchscreen-x-plate-ohms = <800>;
|
||||
};
|
@ -0,0 +1,50 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/input/touchscreen/sitronix,st1232.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Sitronix st1232 or st1633 touchscreen controller
|
||||
|
||||
maintainers:
|
||||
- Bastian Hecht <hechtb@gmail.com>
|
||||
|
||||
allOf:
|
||||
- $ref: touchscreen.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- sitronix,st1232
|
||||
- sitronix,st1633
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
gpios:
|
||||
description: A phandle to the reset GPIO
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
touchscreen@55 {
|
||||
compatible = "sitronix,st1232";
|
||||
reg = <0x55>;
|
||||
interrupts = <2 0>;
|
||||
gpios = <&gpio1 166 0>;
|
||||
};
|
||||
};
|
@ -1,28 +0,0 @@
|
||||
* Sitronix st1232 or st1633 touchscreen controller
|
||||
|
||||
Required properties:
|
||||
- compatible: must contain one of
|
||||
* "sitronix,st1232"
|
||||
* "sitronix,st1633"
|
||||
- reg: I2C address of the chip
|
||||
- interrupts: interrupt to which the chip is connected
|
||||
|
||||
Optional properties:
|
||||
- gpios: a phandle to the reset GPIO
|
||||
|
||||
For additional optional properties see: touchscreen.txt
|
||||
|
||||
Example:
|
||||
|
||||
i2c@00000000 {
|
||||
/* ... */
|
||||
|
||||
touchscreen@55 {
|
||||
compatible = "sitronix,st1232";
|
||||
reg = <0x55>;
|
||||
interrupts = <2 0>;
|
||||
gpios = <&gpio1 166 0>;
|
||||
};
|
||||
|
||||
/* ... */
|
||||
};
|
@ -74,6 +74,12 @@ properties:
|
||||
touchscreen-y-mm:
|
||||
description: vertical length in mm of the touchscreen
|
||||
|
||||
touchscreen-x-plate-ohms:
|
||||
description: Resistance of the X-plate in Ohms
|
||||
|
||||
touchscreen-y-plate-ohms:
|
||||
description: Resistance of the Y-plate in Ohms
|
||||
|
||||
dependencies:
|
||||
touchscreen-size-x: [ touchscreen-size-y ]
|
||||
touchscreen-size-y: [ touchscreen-size-x ]
|
||||
|
@ -272,6 +272,8 @@ properties:
|
||||
# Socionext SynQuacer TPM MMIO module
|
||||
- socionext,synquacer-tpm-mmio
|
||||
# i2c serial eeprom (24cxx)
|
||||
- sparkfun,qwiic-joystick
|
||||
# SparkFun Qwiic Joystick (COM-15168) with i2c interface
|
||||
- st,24c256
|
||||
# Ambient Light Sensor with SMBUS/Two Wire Serial Interface
|
||||
- taos,tsl2550
|
||||
|
@ -1080,6 +1080,8 @@ patternProperties:
|
||||
description: Sony Corporation
|
||||
"^spansion,.*":
|
||||
description: Spansion Inc.
|
||||
"^sparkfun,.*":
|
||||
description: SparkFun Electronics
|
||||
"^sprd,.*":
|
||||
description: Spreadtrum Communications Inc.
|
||||
"^sst,.*":
|
||||
|
@ -5051,11 +5051,10 @@ S: Maintained
|
||||
F: drivers/input/touchscreen/cy8ctma140.c
|
||||
|
||||
CYTTSP TOUCHSCREEN DRIVER
|
||||
M: Ferruh Yigit <fery@cypress.com>
|
||||
M: Linus Walleij <linus.walleij@linaro.org>
|
||||
L: linux-input@vger.kernel.org
|
||||
S: Supported
|
||||
S: Maintained
|
||||
F: drivers/input/touchscreen/cyttsp*
|
||||
F: include/linux/input/cyttsp.h
|
||||
|
||||
D-LINK DIR-685 TOUCHKEYS DRIVER
|
||||
M: Linus Walleij <linus.walleij@linaro.org>
|
||||
|
@ -7,9 +7,6 @@
|
||||
* Input driver event debug module - dumps all events into syslog
|
||||
*/
|
||||
|
||||
/*
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/slab.h>
|
||||
|
@ -499,7 +499,7 @@ static int joydev_handle_JSIOCSBTNMAP(struct joydev *joydev,
|
||||
memcpy(joydev->keypam, keypam, len);
|
||||
|
||||
for (i = 0; i < joydev->nkey; i++)
|
||||
joydev->keymap[keypam[i] - BTN_MISC] = i;
|
||||
joydev->keymap[joydev->keypam[i] - BTN_MISC] = i;
|
||||
|
||||
out:
|
||||
kfree(keypam);
|
||||
|
@ -372,6 +372,15 @@ config JOYSTICK_PXRC
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called pxrc.
|
||||
|
||||
config JOYSTICK_QWIIC
|
||||
tristate "SparkFun Qwiic Joystick"
|
||||
depends on I2C
|
||||
help
|
||||
Say Y here if you want to use the SparkFun Qwiic Joystick.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called qwiic-joystick.
|
||||
|
||||
config JOYSTICK_FSIA6B
|
||||
tristate "FlySky FS-iA6B RC Receiver"
|
||||
select SERIO
|
||||
|
@ -27,6 +27,7 @@ obj-$(CONFIG_JOYSTICK_MAPLE) += maplecontrol.o
|
||||
obj-$(CONFIG_JOYSTICK_N64) += n64joy.o
|
||||
obj-$(CONFIG_JOYSTICK_PSXPAD_SPI) += psxpad-spi.o
|
||||
obj-$(CONFIG_JOYSTICK_PXRC) += pxrc.o
|
||||
obj-$(CONFIG_JOYSTICK_QWIIC) += qwiic-joystick.o
|
||||
obj-$(CONFIG_JOYSTICK_SIDEWINDER) += sidewinder.o
|
||||
obj-$(CONFIG_JOYSTICK_SPACEBALL) += spaceball.o
|
||||
obj-$(CONFIG_JOYSTICK_SPACEORB) += spaceorb.o
|
||||
|
146
drivers/input/joystick/qwiic-joystick.c
Normal file
146
drivers/input/joystick/qwiic-joystick.c
Normal file
@ -0,0 +1,146 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2021 Oleh Kravchenko <oleg@kaa.org.ua>
|
||||
*
|
||||
* SparkFun Qwiic Joystick
|
||||
* Product page:https://www.sparkfun.com/products/15168
|
||||
* Firmware and hardware sources:https://github.com/sparkfun/Qwiic_Joystick
|
||||
*/
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#define DRV_NAME "qwiic-joystick"
|
||||
|
||||
#define QWIIC_JSK_REG_VERS 1
|
||||
#define QWIIC_JSK_REG_DATA 3
|
||||
|
||||
#define QWIIC_JSK_MAX_AXIS GENMASK(9, 0)
|
||||
#define QWIIC_JSK_FUZZ 2
|
||||
#define QWIIC_JSK_FLAT 2
|
||||
#define QWIIC_JSK_POLL_INTERVAL 16
|
||||
#define QWIIC_JSK_POLL_MIN 8
|
||||
#define QWIIC_JSK_POLL_MAX 32
|
||||
|
||||
struct qwiic_jsk {
|
||||
char phys[32];
|
||||
struct input_dev *dev;
|
||||
struct i2c_client *client;
|
||||
};
|
||||
|
||||
struct qwiic_ver {
|
||||
u8 major;
|
||||
u8 minor;
|
||||
};
|
||||
|
||||
struct qwiic_data {
|
||||
__be16 x;
|
||||
__be16 y;
|
||||
u8 thumb;
|
||||
};
|
||||
|
||||
static void qwiic_poll(struct input_dev *input)
|
||||
{
|
||||
struct qwiic_jsk *priv = input_get_drvdata(input);
|
||||
struct qwiic_data data;
|
||||
int err;
|
||||
|
||||
err = i2c_smbus_read_i2c_block_data(priv->client, QWIIC_JSK_REG_DATA,
|
||||
sizeof(data), (u8 *)&data);
|
||||
if (err != sizeof(data))
|
||||
return;
|
||||
|
||||
input_report_abs(input, ABS_X, be16_to_cpu(data.x) >> 6);
|
||||
input_report_abs(input, ABS_Y, be16_to_cpu(data.y) >> 6);
|
||||
input_report_key(input, BTN_THUMBL, !data.thumb);
|
||||
input_sync(input);
|
||||
}
|
||||
|
||||
static int qwiic_probe(struct i2c_client *client)
|
||||
{
|
||||
struct qwiic_jsk *priv;
|
||||
struct qwiic_ver vers;
|
||||
int err;
|
||||
|
||||
err = i2c_smbus_read_i2c_block_data(client, QWIIC_JSK_REG_VERS,
|
||||
sizeof(vers), (u8 *)&vers);
|
||||
if (err < 0)
|
||||
return err;
|
||||
if (err != sizeof(vers))
|
||||
return -EIO;
|
||||
|
||||
dev_dbg(&client->dev, "SparkFun Qwiic Joystick, FW: %u.%u\n",
|
||||
vers.major, vers.minor);
|
||||
|
||||
priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->client = client;
|
||||
snprintf(priv->phys, sizeof(priv->phys),
|
||||
"i2c/%s", dev_name(&client->dev));
|
||||
i2c_set_clientdata(client, priv);
|
||||
|
||||
priv->dev = devm_input_allocate_device(&client->dev);
|
||||
if (!priv->dev)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->dev->id.bustype = BUS_I2C;
|
||||
priv->dev->name = "SparkFun Qwiic Joystick";
|
||||
priv->dev->phys = priv->phys;
|
||||
input_set_drvdata(priv->dev, priv);
|
||||
|
||||
input_set_abs_params(priv->dev, ABS_X, 0, QWIIC_JSK_MAX_AXIS,
|
||||
QWIIC_JSK_FUZZ, QWIIC_JSK_FLAT);
|
||||
input_set_abs_params(priv->dev, ABS_Y, 0, QWIIC_JSK_MAX_AXIS,
|
||||
QWIIC_JSK_FUZZ, QWIIC_JSK_FLAT);
|
||||
input_set_capability(priv->dev, EV_KEY, BTN_THUMBL);
|
||||
|
||||
err = input_setup_polling(priv->dev, qwiic_poll);
|
||||
if (err) {
|
||||
dev_err(&client->dev, "failed to set up polling: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
input_set_poll_interval(priv->dev, QWIIC_JSK_POLL_INTERVAL);
|
||||
input_set_min_poll_interval(priv->dev, QWIIC_JSK_POLL_MIN);
|
||||
input_set_max_poll_interval(priv->dev, QWIIC_JSK_POLL_MAX);
|
||||
|
||||
err = input_register_device(priv->dev);
|
||||
if (err) {
|
||||
dev_err(&client->dev, "failed to register joystick: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id of_qwiic_match[] = {
|
||||
{ .compatible = "sparkfun,qwiic-joystick", },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, of_qwiic_match);
|
||||
#endif /* CONFIG_OF */
|
||||
|
||||
static const struct i2c_device_id qwiic_id_table[] = {
|
||||
{ KBUILD_MODNAME, 0 },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, qwiic_id_table);
|
||||
|
||||
static struct i2c_driver qwiic_driver = {
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.of_match_table = of_match_ptr(of_qwiic_match),
|
||||
},
|
||||
.id_table = qwiic_id_table,
|
||||
.probe_new = qwiic_probe,
|
||||
};
|
||||
module_i2c_driver(qwiic_driver);
|
||||
|
||||
MODULE_AUTHOR("Oleh Kravchenko <oleg@kaa.org.ua>");
|
||||
MODULE_DESCRIPTION("SparkFun Qwiic Joystick driver");
|
||||
MODULE_LICENSE("GPL v2");
|
@ -79,6 +79,7 @@
|
||||
#define MAP_DPAD_TO_BUTTONS (1 << 0)
|
||||
#define MAP_TRIGGERS_TO_BUTTONS (1 << 1)
|
||||
#define MAP_STICKS_TO_NULL (1 << 2)
|
||||
#define MAP_SELECT_BUTTON (1 << 3)
|
||||
#define DANCEPAD_MAP_CONFIG (MAP_DPAD_TO_BUTTONS | \
|
||||
MAP_TRIGGERS_TO_BUTTONS | MAP_STICKS_TO_NULL)
|
||||
|
||||
@ -130,6 +131,7 @@ static const struct xpad_device {
|
||||
{ 0x045e, 0x02e3, "Microsoft X-Box One Elite pad", 0, XTYPE_XBOXONE },
|
||||
{ 0x045e, 0x02ea, "Microsoft X-Box One S pad", 0, XTYPE_XBOXONE },
|
||||
{ 0x045e, 0x0719, "Xbox 360 Wireless Receiver", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W },
|
||||
{ 0x045e, 0x0b12, "Microsoft Xbox One X pad", MAP_SELECT_BUTTON, XTYPE_XBOXONE },
|
||||
{ 0x046d, 0xc21d, "Logitech Gamepad F310", 0, XTYPE_XBOX360 },
|
||||
{ 0x046d, 0xc21e, "Logitech Gamepad F510", 0, XTYPE_XBOX360 },
|
||||
{ 0x046d, 0xc21f, "Logitech Gamepad F710", 0, XTYPE_XBOX360 },
|
||||
@ -864,6 +866,8 @@ static void xpadone_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char
|
||||
/* menu/view buttons */
|
||||
input_report_key(dev, BTN_START, data[4] & 0x04);
|
||||
input_report_key(dev, BTN_SELECT, data[4] & 0x08);
|
||||
if (xpad->mapping & MAP_SELECT_BUTTON)
|
||||
input_report_key(dev, KEY_RECORD, data[22] & 0x01);
|
||||
|
||||
/* buttons A,B,X,Y */
|
||||
input_report_key(dev, BTN_A, data[4] & 0x10);
|
||||
@ -1674,6 +1678,8 @@ static int xpad_init_input(struct usb_xpad *xpad)
|
||||
xpad->xtype == XTYPE_XBOXONE) {
|
||||
for (i = 0; xpad360_btn[i] >= 0; i++)
|
||||
input_set_capability(input_dev, EV_KEY, xpad360_btn[i]);
|
||||
if (xpad->mapping & MAP_SELECT_BUTTON)
|
||||
input_set_capability(input_dev, EV_KEY, KEY_RECORD);
|
||||
} else {
|
||||
for (i = 0; xpad_btn[i] >= 0; i++)
|
||||
input_set_capability(input_dev, EV_KEY, xpad_btn[i]);
|
||||
|
@ -324,7 +324,7 @@ static ssize_t atkbd_show_function_row_physmap(struct atkbd *atkbd, char *buf)
|
||||
static umode_t atkbd_attr_is_visible(struct kobject *kobj,
|
||||
struct attribute *attr, int i)
|
||||
{
|
||||
struct device *dev = container_of(kobj, struct device, kobj);
|
||||
struct device *dev = kobj_to_dev(kobj);
|
||||
struct serio *serio = to_serio_port(dev);
|
||||
struct atkbd *atkbd = serio_get_drvdata(serio);
|
||||
|
||||
|
@ -644,7 +644,7 @@ static umode_t cros_ec_keyb_attr_is_visible(struct kobject *kobj,
|
||||
struct attribute *attr,
|
||||
int n)
|
||||
{
|
||||
struct device *dev = container_of(kobj, struct device, kobj);
|
||||
struct device *dev = kobj_to_dev(kobj);
|
||||
struct cros_ec_keyb *ckdev = dev_get_drvdata(dev);
|
||||
|
||||
if (attr == &dev_attr_function_row_physmap.attr &&
|
||||
|
@ -512,6 +512,7 @@ static int hil_dev_connect(struct serio *serio, struct serio_driver *drv)
|
||||
HIL_IDD_NUM_AXES_PER_SET(*idd)) {
|
||||
printk(KERN_INFO PREFIX
|
||||
"combo devices are not supported.\n");
|
||||
error = -EINVAL;
|
||||
goto bail1;
|
||||
}
|
||||
|
||||
|
@ -647,8 +647,8 @@ static int __ims_pcu_execute_command(struct ims_pcu *pcu,
|
||||
#define IMS_PCU_BL_DATA_OFFSET 3
|
||||
|
||||
static int __ims_pcu_execute_bl_command(struct ims_pcu *pcu,
|
||||
u8 command, const void *data, size_t len,
|
||||
u8 expected_response, int response_time)
|
||||
u8 command, const void *data, size_t len,
|
||||
u8 expected_response, int response_time)
|
||||
{
|
||||
int error;
|
||||
|
||||
@ -1228,7 +1228,7 @@ static struct attribute *ims_pcu_attrs[] = {
|
||||
static umode_t ims_pcu_is_attr_visible(struct kobject *kobj,
|
||||
struct attribute *attr, int n)
|
||||
{
|
||||
struct device *dev = container_of(kobj, struct device, kobj);
|
||||
struct device *dev = kobj_to_dev(kobj);
|
||||
struct usb_interface *intf = to_usb_interface(dev);
|
||||
struct ims_pcu *pcu = usb_get_intfdata(intf);
|
||||
umode_t mode = attr->mode;
|
||||
|
@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
|
||||
* Copyright (c) 2010-2011, 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2014, Sony Mobile Communications Inc.
|
||||
*/
|
||||
|
||||
@ -22,6 +22,8 @@
|
||||
#define PON_RT_STS 0x10
|
||||
#define PON_KPDPWR_N_SET BIT(0)
|
||||
#define PON_RESIN_N_SET BIT(1)
|
||||
#define PON_GEN3_RESIN_N_SET BIT(6)
|
||||
#define PON_GEN3_KPDPWR_N_SET BIT(7)
|
||||
|
||||
#define PON_PS_HOLD_RST_CTL 0x5a
|
||||
#define PON_PS_HOLD_RST_CTL2 0x5b
|
||||
@ -38,8 +40,12 @@
|
||||
#define PON_DBC_DELAY_MASK 0x7
|
||||
|
||||
struct pm8941_data {
|
||||
unsigned int pull_up_bit;
|
||||
unsigned int status_bit;
|
||||
unsigned int pull_up_bit;
|
||||
unsigned int status_bit;
|
||||
bool supports_ps_hold_poff_config;
|
||||
bool supports_debounce_config;
|
||||
const char *name;
|
||||
const char *phys;
|
||||
};
|
||||
|
||||
struct pm8941_pwrkey {
|
||||
@ -231,34 +237,40 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev)
|
||||
|
||||
input_set_capability(pwrkey->input, EV_KEY, pwrkey->code);
|
||||
|
||||
pwrkey->input->name = "pm8941_pwrkey";
|
||||
pwrkey->input->phys = "pm8941_pwrkey/input0";
|
||||
pwrkey->input->name = pwrkey->data->name;
|
||||
pwrkey->input->phys = pwrkey->data->phys;
|
||||
|
||||
req_delay = (req_delay << 6) / USEC_PER_SEC;
|
||||
req_delay = ilog2(req_delay);
|
||||
if (pwrkey->data->supports_debounce_config) {
|
||||
req_delay = (req_delay << 6) / USEC_PER_SEC;
|
||||
req_delay = ilog2(req_delay);
|
||||
|
||||
error = regmap_update_bits(pwrkey->regmap,
|
||||
pwrkey->baseaddr + PON_DBC_CTL,
|
||||
PON_DBC_DELAY_MASK,
|
||||
req_delay);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "failed to set debounce: %d\n", error);
|
||||
return error;
|
||||
error = regmap_update_bits(pwrkey->regmap,
|
||||
pwrkey->baseaddr + PON_DBC_CTL,
|
||||
PON_DBC_DELAY_MASK,
|
||||
req_delay);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "failed to set debounce: %d\n",
|
||||
error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
error = regmap_update_bits(pwrkey->regmap,
|
||||
pwrkey->baseaddr + PON_PULL_CTL,
|
||||
pwrkey->data->pull_up_bit,
|
||||
pull_up ? pwrkey->data->pull_up_bit : 0);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "failed to set pull: %d\n", error);
|
||||
return error;
|
||||
if (pwrkey->data->pull_up_bit) {
|
||||
error = regmap_update_bits(pwrkey->regmap,
|
||||
pwrkey->baseaddr + PON_PULL_CTL,
|
||||
pwrkey->data->pull_up_bit,
|
||||
pull_up ? pwrkey->data->pull_up_bit :
|
||||
0);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "failed to set pull: %d\n", error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
error = devm_request_threaded_irq(&pdev->dev, pwrkey->irq,
|
||||
NULL, pm8941_pwrkey_irq,
|
||||
IRQF_ONESHOT,
|
||||
"pm8941_pwrkey", pwrkey);
|
||||
pwrkey->data->name, pwrkey);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "failed requesting IRQ: %d\n", error);
|
||||
return error;
|
||||
@ -271,12 +283,14 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev)
|
||||
return error;
|
||||
}
|
||||
|
||||
pwrkey->reboot_notifier.notifier_call = pm8941_reboot_notify,
|
||||
error = register_reboot_notifier(&pwrkey->reboot_notifier);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "failed to register reboot notifier: %d\n",
|
||||
error);
|
||||
return error;
|
||||
if (pwrkey->data->supports_ps_hold_poff_config) {
|
||||
pwrkey->reboot_notifier.notifier_call = pm8941_reboot_notify,
|
||||
error = register_reboot_notifier(&pwrkey->reboot_notifier);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "failed to register reboot notifier: %d\n",
|
||||
error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, pwrkey);
|
||||
@ -289,7 +303,8 @@ static int pm8941_pwrkey_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct pm8941_pwrkey *pwrkey = platform_get_drvdata(pdev);
|
||||
|
||||
unregister_reboot_notifier(&pwrkey->reboot_notifier);
|
||||
if (pwrkey->data->supports_ps_hold_poff_config)
|
||||
unregister_reboot_notifier(&pwrkey->reboot_notifier);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -297,16 +312,42 @@ static int pm8941_pwrkey_remove(struct platform_device *pdev)
|
||||
static const struct pm8941_data pwrkey_data = {
|
||||
.pull_up_bit = PON_KPDPWR_PULL_UP,
|
||||
.status_bit = PON_KPDPWR_N_SET,
|
||||
.name = "pm8941_pwrkey",
|
||||
.phys = "pm8941_pwrkey/input0",
|
||||
.supports_ps_hold_poff_config = true,
|
||||
.supports_debounce_config = true,
|
||||
};
|
||||
|
||||
static const struct pm8941_data resin_data = {
|
||||
.pull_up_bit = PON_RESIN_PULL_UP,
|
||||
.status_bit = PON_RESIN_N_SET,
|
||||
.name = "pm8941_resin",
|
||||
.phys = "pm8941_resin/input0",
|
||||
.supports_ps_hold_poff_config = true,
|
||||
.supports_debounce_config = true,
|
||||
};
|
||||
|
||||
static const struct pm8941_data pon_gen3_pwrkey_data = {
|
||||
.status_bit = PON_GEN3_KPDPWR_N_SET,
|
||||
.name = "pmic_pwrkey",
|
||||
.phys = "pmic_pwrkey/input0",
|
||||
.supports_ps_hold_poff_config = false,
|
||||
.supports_debounce_config = false,
|
||||
};
|
||||
|
||||
static const struct pm8941_data pon_gen3_resin_data = {
|
||||
.status_bit = PON_GEN3_RESIN_N_SET,
|
||||
.name = "pmic_resin",
|
||||
.phys = "pmic_resin/input0",
|
||||
.supports_ps_hold_poff_config = false,
|
||||
.supports_debounce_config = false,
|
||||
};
|
||||
|
||||
static const struct of_device_id pm8941_pwr_key_id_table[] = {
|
||||
{ .compatible = "qcom,pm8941-pwrkey", .data = &pwrkey_data },
|
||||
{ .compatible = "qcom,pm8941-resin", .data = &resin_data },
|
||||
{ .compatible = "qcom,pmk8350-pwrkey", .data = &pon_gen3_pwrkey_data },
|
||||
{ .compatible = "qcom,pmk8350-resin", .data = &pon_gen3_resin_data },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, pm8941_pwr_key_id_table);
|
||||
|
@ -214,7 +214,7 @@ static bool trackpoint_is_attr_available(struct psmouse *psmouse,
|
||||
static umode_t trackpoint_is_attr_visible(struct kobject *kobj,
|
||||
struct attribute *attr, int n)
|
||||
{
|
||||
struct device *dev = container_of(kobj, struct device, kobj);
|
||||
struct device *dev = kobj_to_dev(kobj);
|
||||
struct serio *serio = to_serio_port(dev);
|
||||
struct psmouse *psmouse = serio_get_drvdata(serio);
|
||||
|
||||
|
@ -139,7 +139,7 @@ static DEFINE_SPINLOCK(i8042_lock);
|
||||
/*
|
||||
* Writers to AUX and KBD ports as well as users issuing i8042_command
|
||||
* directly should acquire i8042_mutex (by means of calling
|
||||
* i8042_lock_chip() and i8042_unlock_ship() helpers) to ensure that
|
||||
* i8042_lock_chip() and i8042_unlock_chip() helpers) to ensure that
|
||||
* they do not disturb each other (unfortunately in many i8042
|
||||
* implementations write to one of the ports will immediately abort
|
||||
* command that is being processed by another port).
|
||||
@ -979,7 +979,7 @@ static int i8042_controller_selftest(void)
|
||||
}
|
||||
|
||||
/*
|
||||
* i8042_controller init initializes the i8042 controller, and,
|
||||
* i8042_controller_init initializes the i8042 controller, and,
|
||||
* most importantly, sets it into non-xlated mode if that's
|
||||
* desired.
|
||||
*/
|
||||
|
@ -7,15 +7,14 @@
|
||||
* Some cleanups by Alan Cox <alan@linux.intel.com>
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/input/cy8ctmg110_pdata.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
#define CY8CTMG110_DRIVER_NAME "cy8ctmg110"
|
||||
|
||||
@ -45,18 +44,18 @@ struct cy8ctmg110 {
|
||||
struct input_dev *input;
|
||||
char phys[32];
|
||||
struct i2c_client *client;
|
||||
int reset_pin;
|
||||
int irq_pin;
|
||||
struct gpio_desc *reset_gpio;
|
||||
};
|
||||
|
||||
/*
|
||||
* cy8ctmg110_power is the routine that is called when touch hardware
|
||||
* will powered off or on.
|
||||
* is being powered off or on. When powering on this routine de-asserts
|
||||
* the RESET line, when powering off reset line is asserted.
|
||||
*/
|
||||
static void cy8ctmg110_power(struct cy8ctmg110 *ts, bool poweron)
|
||||
{
|
||||
if (ts->reset_pin)
|
||||
gpio_direction_output(ts->reset_pin, 1 - poweron);
|
||||
if (ts->reset_gpio)
|
||||
gpiod_set_value_cansleep(ts->reset_gpio, !poweron);
|
||||
}
|
||||
|
||||
static int cy8ctmg110_write_regs(struct cy8ctmg110 *tsc, unsigned char reg,
|
||||
@ -112,7 +111,6 @@ static int cy8ctmg110_touch_pos(struct cy8ctmg110 *tsc)
|
||||
{
|
||||
struct input_dev *input = tsc->input;
|
||||
unsigned char reg_p[CY8CTMG110_REG_MAX];
|
||||
int x, y;
|
||||
|
||||
memset(reg_p, 0, CY8CTMG110_REG_MAX);
|
||||
|
||||
@ -120,16 +118,15 @@ static int cy8ctmg110_touch_pos(struct cy8ctmg110 *tsc)
|
||||
if (cy8ctmg110_read_regs(tsc, reg_p, 9, CY8CTMG110_TOUCH_X1) != 0)
|
||||
return -EIO;
|
||||
|
||||
y = reg_p[2] << 8 | reg_p[3];
|
||||
x = reg_p[0] << 8 | reg_p[1];
|
||||
|
||||
/* Number of touch */
|
||||
if (reg_p[8] == 0) {
|
||||
input_report_key(input, BTN_TOUCH, 0);
|
||||
} else {
|
||||
input_report_key(input, BTN_TOUCH, 1);
|
||||
input_report_abs(input, ABS_X, x);
|
||||
input_report_abs(input, ABS_Y, y);
|
||||
input_report_abs(input, ABS_X,
|
||||
be16_to_cpup((__be16 *)(reg_p + 0)));
|
||||
input_report_abs(input, ABS_Y,
|
||||
be16_to_cpup((__be16 *)(reg_p + 2)));
|
||||
}
|
||||
|
||||
input_sync(input);
|
||||
@ -163,35 +160,35 @@ static irqreturn_t cy8ctmg110_irq_thread(int irq, void *dev_id)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void cy8ctmg110_shut_off(void *_ts)
|
||||
{
|
||||
struct cy8ctmg110 *ts = _ts;
|
||||
|
||||
cy8ctmg110_set_sleepmode(ts, true);
|
||||
cy8ctmg110_power(ts, false);
|
||||
}
|
||||
|
||||
static int cy8ctmg110_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
const struct cy8ctmg110_pdata *pdata = dev_get_platdata(&client->dev);
|
||||
struct cy8ctmg110 *ts;
|
||||
struct input_dev *input_dev;
|
||||
int err;
|
||||
|
||||
/* No pdata no way forward */
|
||||
if (pdata == NULL) {
|
||||
dev_err(&client->dev, "no pdata\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!i2c_check_functionality(client->adapter,
|
||||
I2C_FUNC_SMBUS_READ_WORD_DATA))
|
||||
return -EIO;
|
||||
|
||||
ts = kzalloc(sizeof(struct cy8ctmg110), GFP_KERNEL);
|
||||
input_dev = input_allocate_device();
|
||||
if (!ts || !input_dev) {
|
||||
err = -ENOMEM;
|
||||
goto err_free_mem;
|
||||
}
|
||||
ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL);
|
||||
if (!ts)
|
||||
return -ENOMEM;
|
||||
|
||||
input_dev = devm_input_allocate_device(&client->dev);
|
||||
if (!input_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
ts->client = client;
|
||||
ts->input = input_dev;
|
||||
ts->reset_pin = pdata->reset_pin;
|
||||
ts->irq_pin = pdata->irq_pin;
|
||||
|
||||
snprintf(ts->phys, sizeof(ts->phys),
|
||||
"%s/input0", dev_name(&client->dev));
|
||||
@ -199,84 +196,46 @@ static int cy8ctmg110_probe(struct i2c_client *client,
|
||||
input_dev->name = CY8CTMG110_DRIVER_NAME " Touchscreen";
|
||||
input_dev->phys = ts->phys;
|
||||
input_dev->id.bustype = BUS_I2C;
|
||||
input_dev->dev.parent = &client->dev;
|
||||
|
||||
input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
|
||||
input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
|
||||
|
||||
input_set_capability(input_dev, EV_KEY, BTN_TOUCH);
|
||||
input_set_abs_params(input_dev, ABS_X,
|
||||
CY8CTMG110_X_MIN, CY8CTMG110_X_MAX, 4, 0);
|
||||
input_set_abs_params(input_dev, ABS_Y,
|
||||
CY8CTMG110_Y_MIN, CY8CTMG110_Y_MAX, 4, 0);
|
||||
|
||||
if (ts->reset_pin) {
|
||||
err = gpio_request(ts->reset_pin, NULL);
|
||||
if (err) {
|
||||
dev_err(&client->dev,
|
||||
"Unable to request GPIO pin %d.\n",
|
||||
ts->reset_pin);
|
||||
goto err_free_mem;
|
||||
}
|
||||
/* Request and assert reset line */
|
||||
ts->reset_gpio = devm_gpiod_get_optional(&client->dev, NULL,
|
||||
GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(ts->reset_gpio)) {
|
||||
err = PTR_ERR(ts->reset_gpio);
|
||||
dev_err(&client->dev,
|
||||
"Unable to request reset GPIO: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
cy8ctmg110_power(ts, true);
|
||||
cy8ctmg110_set_sleepmode(ts, false);
|
||||
|
||||
err = gpio_request(ts->irq_pin, "touch_irq_key");
|
||||
if (err < 0) {
|
||||
dev_err(&client->dev,
|
||||
"Failed to request GPIO %d, error %d\n",
|
||||
ts->irq_pin, err);
|
||||
goto err_shutoff_device;
|
||||
}
|
||||
err = devm_add_action_or_reset(&client->dev, cy8ctmg110_shut_off, ts);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = gpio_direction_input(ts->irq_pin);
|
||||
if (err < 0) {
|
||||
dev_err(&client->dev,
|
||||
"Failed to configure input direction for GPIO %d, error %d\n",
|
||||
ts->irq_pin, err);
|
||||
goto err_free_irq_gpio;
|
||||
}
|
||||
|
||||
client->irq = gpio_to_irq(ts->irq_pin);
|
||||
if (client->irq < 0) {
|
||||
err = client->irq;
|
||||
dev_err(&client->dev,
|
||||
"Unable to get irq number for GPIO %d, error %d\n",
|
||||
ts->irq_pin, err);
|
||||
goto err_free_irq_gpio;
|
||||
}
|
||||
|
||||
err = request_threaded_irq(client->irq, NULL, cy8ctmg110_irq_thread,
|
||||
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
|
||||
"touch_reset_key", ts);
|
||||
if (err < 0) {
|
||||
err = devm_request_threaded_irq(&client->dev, client->irq,
|
||||
NULL, cy8ctmg110_irq_thread,
|
||||
IRQF_ONESHOT, "touch_reset_key", ts);
|
||||
if (err) {
|
||||
dev_err(&client->dev,
|
||||
"irq %d busy? error %d\n", client->irq, err);
|
||||
goto err_free_irq_gpio;
|
||||
return err;
|
||||
}
|
||||
|
||||
err = input_register_device(input_dev);
|
||||
if (err)
|
||||
goto err_free_irq;
|
||||
return err;
|
||||
|
||||
i2c_set_clientdata(client, ts);
|
||||
device_init_wakeup(&client->dev, 1);
|
||||
return 0;
|
||||
|
||||
err_free_irq:
|
||||
free_irq(client->irq, ts);
|
||||
err_free_irq_gpio:
|
||||
gpio_free(ts->irq_pin);
|
||||
err_shutoff_device:
|
||||
cy8ctmg110_set_sleepmode(ts, true);
|
||||
cy8ctmg110_power(ts, false);
|
||||
if (ts->reset_pin)
|
||||
gpio_free(ts->reset_pin);
|
||||
err_free_mem:
|
||||
input_free_device(input_dev);
|
||||
kfree(ts);
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused cy8ctmg110_suspend(struct device *dev)
|
||||
@ -284,12 +243,11 @@ static int __maybe_unused cy8ctmg110_suspend(struct device *dev)
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct cy8ctmg110 *ts = i2c_get_clientdata(client);
|
||||
|
||||
if (device_may_wakeup(&client->dev))
|
||||
enable_irq_wake(client->irq);
|
||||
else {
|
||||
if (!device_may_wakeup(&client->dev)) {
|
||||
cy8ctmg110_set_sleepmode(ts, true);
|
||||
cy8ctmg110_power(ts, false);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -298,34 +256,16 @@ static int __maybe_unused cy8ctmg110_resume(struct device *dev)
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct cy8ctmg110 *ts = i2c_get_clientdata(client);
|
||||
|
||||
if (device_may_wakeup(&client->dev))
|
||||
disable_irq_wake(client->irq);
|
||||
else {
|
||||
if (!device_may_wakeup(&client->dev)) {
|
||||
cy8ctmg110_power(ts, true);
|
||||
cy8ctmg110_set_sleepmode(ts, false);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(cy8ctmg110_pm, cy8ctmg110_suspend, cy8ctmg110_resume);
|
||||
|
||||
static int cy8ctmg110_remove(struct i2c_client *client)
|
||||
{
|
||||
struct cy8ctmg110 *ts = i2c_get_clientdata(client);
|
||||
|
||||
cy8ctmg110_set_sleepmode(ts, true);
|
||||
cy8ctmg110_power(ts, false);
|
||||
|
||||
free_irq(client->irq, ts);
|
||||
input_unregister_device(ts->input);
|
||||
gpio_free(ts->irq_pin);
|
||||
if (ts->reset_pin)
|
||||
gpio_free(ts->reset_pin);
|
||||
kfree(ts);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id cy8ctmg110_idtable[] = {
|
||||
{ CY8CTMG110_DRIVER_NAME, 1 },
|
||||
{ }
|
||||
@ -340,7 +280,6 @@ static struct i2c_driver cy8ctmg110_driver = {
|
||||
},
|
||||
.id_table = cy8ctmg110_idtable,
|
||||
.probe = cy8ctmg110_probe,
|
||||
.remove = cy8ctmg110_remove,
|
||||
};
|
||||
|
||||
module_i2c_driver(cy8ctmg110_driver);
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include "cyttsp_core.h"
|
||||
|
||||
@ -45,8 +46,15 @@
|
||||
#define CY_MAXZ 255
|
||||
#define CY_DELAY_DFLT 20 /* ms */
|
||||
#define CY_DELAY_MAX 500
|
||||
#define CY_ACT_DIST_DFLT 0xF8
|
||||
/* Active distance in pixels for a gesture to be reported */
|
||||
#define CY_ACT_DIST_DFLT 0xF8 /* pixels */
|
||||
#define CY_ACT_DIST_MASK 0x0F
|
||||
/* Active Power state scanning/processing refresh interval */
|
||||
#define CY_ACT_INTRVL_DFLT 0x00 /* ms */
|
||||
/* Low Power state scanning/processing refresh interval */
|
||||
#define CY_LP_INTRVL_DFLT 0x0A /* ms */
|
||||
/* touch timeout for the Active power */
|
||||
#define CY_TCH_TMOUT_DFLT 0xFF /* ms */
|
||||
#define CY_HNDSHK_BIT 0x80
|
||||
/* device mode bits */
|
||||
#define CY_OPERATE_MODE 0x00
|
||||
@ -608,6 +616,14 @@ static int cyttsp_parse_properties(struct cyttsp *ts)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cyttsp_disable_regulators(void *_ts)
|
||||
{
|
||||
struct cyttsp *ts = _ts;
|
||||
|
||||
regulator_bulk_disable(ARRAY_SIZE(ts->regulators),
|
||||
ts->regulators);
|
||||
}
|
||||
|
||||
struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops,
|
||||
struct device *dev, int irq, size_t xfer_buf_size)
|
||||
{
|
||||
@ -628,6 +644,32 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops,
|
||||
ts->bus_ops = bus_ops;
|
||||
ts->irq = irq;
|
||||
|
||||
/*
|
||||
* VCPIN is the analog voltage supply
|
||||
* VDD is the digital voltage supply
|
||||
*/
|
||||
ts->regulators[0].supply = "vcpin";
|
||||
ts->regulators[1].supply = "vdd";
|
||||
error = devm_regulator_bulk_get(dev, ARRAY_SIZE(ts->regulators),
|
||||
ts->regulators);
|
||||
if (error) {
|
||||
dev_err(dev, "Failed to get regulators: %d\n", error);
|
||||
return ERR_PTR(error);
|
||||
}
|
||||
|
||||
error = regulator_bulk_enable(ARRAY_SIZE(ts->regulators),
|
||||
ts->regulators);
|
||||
if (error) {
|
||||
dev_err(dev, "Cannot enable regulators: %d\n", error);
|
||||
return ERR_PTR(error);
|
||||
}
|
||||
|
||||
error = devm_add_action_or_reset(dev, cyttsp_disable_regulators, ts);
|
||||
if (error) {
|
||||
dev_err(dev, "failed to install chip disable handler\n");
|
||||
return ERR_PTR(error);
|
||||
}
|
||||
|
||||
ts->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(ts->reset_gpio)) {
|
||||
error = PTR_ERR(ts->reset_gpio);
|
||||
@ -664,8 +706,7 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops,
|
||||
}
|
||||
|
||||
error = devm_request_threaded_irq(dev, ts->irq, NULL, cyttsp_irq,
|
||||
IRQF_TRIGGER_FALLING | IRQF_ONESHOT |
|
||||
IRQF_NO_AUTOEN,
|
||||
IRQF_ONESHOT | IRQF_NO_AUTOEN,
|
||||
"cyttsp", ts);
|
||||
if (error) {
|
||||
dev_err(ts->dev, "failed to request IRQ %d, err: %d\n",
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/input/cyttsp.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#define CY_NUM_RETRY 16 /* max number of retries for read ops */
|
||||
|
||||
@ -122,6 +122,7 @@ struct cyttsp {
|
||||
enum cyttsp_state state;
|
||||
bool suspended;
|
||||
|
||||
struct regulator_bulk_data regulators[2];
|
||||
struct gpio_desc *reset_gpio;
|
||||
bool use_hndshk;
|
||||
u8 act_dist;
|
||||
|
@ -18,6 +18,8 @@
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/input.h>
|
||||
|
||||
#define CY_I2C_NAME "cyttsp-i2c"
|
||||
|
||||
#define CY_I2C_DATA_SIZE 128
|
||||
|
||||
static const struct cyttsp_bus_ops cyttsp_i2c_bus_ops = {
|
||||
@ -52,10 +54,18 @@ static const struct i2c_device_id cyttsp_i2c_id[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, cyttsp_i2c_id);
|
||||
|
||||
static const struct of_device_id cyttsp_of_i2c_match[] = {
|
||||
{ .compatible = "cypress,cy8ctma340", },
|
||||
{ .compatible = "cypress,cy8ctst341", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, cyttsp_of_i2c_match);
|
||||
|
||||
static struct i2c_driver cyttsp_i2c_driver = {
|
||||
.driver = {
|
||||
.name = CY_I2C_NAME,
|
||||
.pm = &cyttsp_pm_ops,
|
||||
.of_match_table = cyttsp_of_i2c_match,
|
||||
},
|
||||
.probe = cyttsp_i2c_probe,
|
||||
.id_table = cyttsp_i2c_id,
|
||||
|
@ -20,6 +20,8 @@
|
||||
#include <linux/input.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
||||
#define CY_SPI_NAME "cyttsp-spi"
|
||||
|
||||
#define CY_SPI_WR_OP 0x00 /* r/~w */
|
||||
#define CY_SPI_RD_OP 0x01
|
||||
#define CY_SPI_CMD_BYTES 4
|
||||
@ -160,10 +162,18 @@ static int cyttsp_spi_probe(struct spi_device *spi)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id cyttsp_of_spi_match[] = {
|
||||
{ .compatible = "cypress,cy8ctma340", },
|
||||
{ .compatible = "cypress,cy8ctst341", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, cyttsp_of_spi_match);
|
||||
|
||||
static struct spi_driver cyttsp_spi_driver = {
|
||||
.driver = {
|
||||
.name = CY_SPI_NAME,
|
||||
.pm = &cyttsp_pm_ops,
|
||||
.of_match_table = cyttsp_of_spi_match,
|
||||
},
|
||||
.probe = cyttsp_spi_probe,
|
||||
};
|
||||
|
@ -104,6 +104,7 @@ struct edt_ft5x06_ts_data {
|
||||
u16 num_x;
|
||||
u16 num_y;
|
||||
struct regulator *vcc;
|
||||
struct regulator *iovcc;
|
||||
|
||||
struct gpio_desc *reset_gpio;
|
||||
struct gpio_desc *wake_gpio;
|
||||
@ -1062,11 +1063,12 @@ static void edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata)
|
||||
}
|
||||
}
|
||||
|
||||
static void edt_ft5x06_disable_regulator(void *arg)
|
||||
static void edt_ft5x06_disable_regulators(void *arg)
|
||||
{
|
||||
struct edt_ft5x06_ts_data *data = arg;
|
||||
|
||||
regulator_disable(data->vcc);
|
||||
regulator_disable(data->iovcc);
|
||||
}
|
||||
|
||||
static int edt_ft5x06_ts_probe(struct i2c_client *client,
|
||||
@ -1107,14 +1109,33 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client,
|
||||
return error;
|
||||
}
|
||||
|
||||
tsdata->iovcc = devm_regulator_get(&client->dev, "iovcc");
|
||||
if (IS_ERR(tsdata->iovcc)) {
|
||||
error = PTR_ERR(tsdata->iovcc);
|
||||
if (error != -EPROBE_DEFER)
|
||||
dev_err(&client->dev,
|
||||
"failed to request iovcc regulator: %d\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
error = regulator_enable(tsdata->iovcc);
|
||||
if (error < 0) {
|
||||
dev_err(&client->dev, "failed to enable iovcc: %d\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Delay enabling VCC for > 10us (T_ivd) after IOVCC */
|
||||
usleep_range(10, 100);
|
||||
|
||||
error = regulator_enable(tsdata->vcc);
|
||||
if (error < 0) {
|
||||
dev_err(&client->dev, "failed to enable vcc: %d\n", error);
|
||||
regulator_disable(tsdata->iovcc);
|
||||
return error;
|
||||
}
|
||||
|
||||
error = devm_add_action_or_reset(&client->dev,
|
||||
edt_ft5x06_disable_regulator,
|
||||
edt_ft5x06_disable_regulators,
|
||||
tsdata);
|
||||
if (error)
|
||||
return error;
|
||||
@ -1289,6 +1310,9 @@ static int __maybe_unused edt_ft5x06_ts_suspend(struct device *dev)
|
||||
ret = regulator_disable(tsdata->vcc);
|
||||
if (ret)
|
||||
dev_warn(dev, "Failed to disable vcc\n");
|
||||
ret = regulator_disable(tsdata->iovcc);
|
||||
if (ret)
|
||||
dev_warn(dev, "Failed to disable iovcc\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1319,9 +1343,19 @@ static int __maybe_unused edt_ft5x06_ts_resume(struct device *dev)
|
||||
gpiod_set_value_cansleep(reset_gpio, 1);
|
||||
usleep_range(5000, 6000);
|
||||
|
||||
ret = regulator_enable(tsdata->iovcc);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to enable iovcc\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Delay enabling VCC for > 10us (T_ivd) after IOVCC */
|
||||
usleep_range(10, 100);
|
||||
|
||||
ret = regulator_enable(tsdata->vcc);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to enable vcc\n");
|
||||
regulator_disable(tsdata->iovcc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1369,8 +1369,7 @@ static bool elants_acpi_is_hid_device(struct device *dev)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int elants_i2c_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int elants_i2c_probe(struct i2c_client *client)
|
||||
{
|
||||
union i2c_smbus_data dummy;
|
||||
struct elants_data *ts;
|
||||
@ -1396,7 +1395,7 @@ static int elants_i2c_probe(struct i2c_client *client,
|
||||
init_completion(&ts->cmd_done);
|
||||
|
||||
ts->client = client;
|
||||
ts->chip_id = (enum elants_chip_id)id->driver_data;
|
||||
ts->chip_id = (enum elants_chip_id)(uintptr_t)device_get_match_data(&client->dev);
|
||||
i2c_set_clientdata(client, ts);
|
||||
|
||||
ts->vcc33 = devm_regulator_get(&client->dev, "vcc33");
|
||||
@ -1636,15 +1635,15 @@ MODULE_DEVICE_TABLE(acpi, elants_acpi_id);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id elants_of_match[] = {
|
||||
{ .compatible = "elan,ekth3500" },
|
||||
{ .compatible = "elan,ektf3624" },
|
||||
{ .compatible = "elan,ekth3500", .data = (void *)EKTH3500 },
|
||||
{ .compatible = "elan,ektf3624", .data = (void *)EKTF3624 },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, elants_of_match);
|
||||
#endif
|
||||
|
||||
static struct i2c_driver elants_i2c_driver = {
|
||||
.probe = elants_i2c_probe,
|
||||
.probe_new = elants_i2c_probe,
|
||||
.id_table = elants_i2c_id,
|
||||
.driver = {
|
||||
.name = DEVICE_NAME,
|
||||
|
@ -361,13 +361,16 @@ static int hideep_enter_pgm(struct hideep_ts *ts)
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static void hideep_nvm_unlock(struct hideep_ts *ts)
|
||||
static int hideep_nvm_unlock(struct hideep_ts *ts)
|
||||
{
|
||||
u32 unmask_code;
|
||||
int error;
|
||||
|
||||
hideep_pgm_w_reg(ts, HIDEEP_FLASH_CFG, HIDEEP_NVM_SFR_RPAGE);
|
||||
hideep_pgm_r_reg(ts, 0x0000000C, &unmask_code);
|
||||
error = hideep_pgm_r_reg(ts, 0x0000000C, &unmask_code);
|
||||
hideep_pgm_w_reg(ts, HIDEEP_FLASH_CFG, HIDEEP_NVM_DEFAULT_PAGE);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/* make it unprotected code */
|
||||
unmask_code &= ~HIDEEP_PROT_MODE;
|
||||
@ -384,6 +387,8 @@ static void hideep_nvm_unlock(struct hideep_ts *ts)
|
||||
NVM_W_SFR(HIDEEP_NVM_MASK_OFS, ts->nvm_mask);
|
||||
SET_FLASH_HWCONTROL();
|
||||
hideep_pgm_w_reg(ts, HIDEEP_FLASH_CFG, HIDEEP_NVM_DEFAULT_PAGE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hideep_check_status(struct hideep_ts *ts)
|
||||
@ -462,7 +467,9 @@ static int hideep_program_nvm(struct hideep_ts *ts,
|
||||
u32 addr = 0;
|
||||
int error;
|
||||
|
||||
hideep_nvm_unlock(ts);
|
||||
error = hideep_nvm_unlock(ts);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
while (ucode_len > 0) {
|
||||
xfer_len = min_t(size_t, ucode_len, HIDEEP_NVM_PAGE_SIZE);
|
||||
|
@ -13,44 +13,78 @@
|
||||
#include <linux/input/touchscreen.h>
|
||||
#include <linux/iio/consumer.h>
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/property.h>
|
||||
|
||||
#define DRIVER_NAME "resistive-adc-touch"
|
||||
#define GRTS_DEFAULT_PRESSURE_MIN 50000
|
||||
#define GRTS_DEFAULT_PRESSURE_MAX 65535
|
||||
#define GRTS_MAX_POS_MASK GENMASK(11, 0)
|
||||
#define GRTS_MAX_CHANNELS 4
|
||||
|
||||
enum grts_ch_type {
|
||||
GRTS_CH_X,
|
||||
GRTS_CH_Y,
|
||||
GRTS_CH_PRESSURE,
|
||||
GRTS_CH_Z1,
|
||||
GRTS_CH_Z2,
|
||||
GRTS_CH_MAX = GRTS_CH_Z2 + 1
|
||||
};
|
||||
|
||||
/**
|
||||
* struct grts_state - generic resistive touch screen information struct
|
||||
* @x_plate_ohms: resistance of the X plate
|
||||
* @pressure_min: number representing the minimum for the pressure
|
||||
* @pressure: are we getting pressure info or not
|
||||
* @iio_chans: list of channels acquired
|
||||
* @iio_cb: iio_callback buffer for the data
|
||||
* @input: the input device structure that we register
|
||||
* @prop: touchscreen properties struct
|
||||
* @ch_map: map of channels that are defined for the touchscreen
|
||||
*/
|
||||
struct grts_state {
|
||||
u32 x_plate_ohms;
|
||||
u32 pressure_min;
|
||||
bool pressure;
|
||||
struct iio_channel *iio_chans;
|
||||
struct iio_cb_buffer *iio_cb;
|
||||
struct input_dev *input;
|
||||
struct touchscreen_properties prop;
|
||||
u8 ch_map[GRTS_CH_MAX];
|
||||
};
|
||||
|
||||
static int grts_cb(const void *data, void *private)
|
||||
{
|
||||
const u16 *touch_info = data;
|
||||
struct grts_state *st = private;
|
||||
unsigned int x, y, press = 0x0;
|
||||
unsigned int x, y, press = 0;
|
||||
|
||||
/* channel data coming in buffer in the order below */
|
||||
x = touch_info[0];
|
||||
y = touch_info[1];
|
||||
if (st->pressure)
|
||||
press = touch_info[2];
|
||||
x = touch_info[st->ch_map[GRTS_CH_X]];
|
||||
y = touch_info[st->ch_map[GRTS_CH_Y]];
|
||||
|
||||
if (st->ch_map[GRTS_CH_PRESSURE] < GRTS_MAX_CHANNELS) {
|
||||
press = touch_info[st->ch_map[GRTS_CH_PRESSURE]];
|
||||
} else if (st->ch_map[GRTS_CH_Z1] < GRTS_MAX_CHANNELS) {
|
||||
unsigned int z1 = touch_info[st->ch_map[GRTS_CH_Z1]];
|
||||
unsigned int z2 = touch_info[st->ch_map[GRTS_CH_Z2]];
|
||||
unsigned int Rt;
|
||||
|
||||
Rt = z2;
|
||||
Rt -= z1;
|
||||
Rt *= st->x_plate_ohms;
|
||||
Rt = DIV_ROUND_CLOSEST(Rt, 16);
|
||||
Rt *= x;
|
||||
Rt /= z1;
|
||||
Rt = DIV_ROUND_CLOSEST(Rt, 256);
|
||||
/*
|
||||
* On increased pressure the resistance (Rt) is decreasing
|
||||
* so, convert values to make it looks as real pressure.
|
||||
*/
|
||||
if (Rt < GRTS_DEFAULT_PRESSURE_MAX)
|
||||
press = GRTS_DEFAULT_PRESSURE_MAX - Rt;
|
||||
}
|
||||
|
||||
if ((!x && !y) || (st->pressure && (press < st->pressure_min))) {
|
||||
/* report end of touch */
|
||||
@ -94,12 +128,77 @@ static void grts_disable(void *data)
|
||||
iio_channel_release_all_cb(data);
|
||||
}
|
||||
|
||||
static int grts_map_channel(struct grts_state *st, struct device *dev,
|
||||
enum grts_ch_type type, const char *name,
|
||||
bool optional)
|
||||
{
|
||||
int idx;
|
||||
|
||||
idx = device_property_match_string(dev, "io-channel-names", name);
|
||||
if (idx < 0) {
|
||||
if (!optional)
|
||||
return idx;
|
||||
idx = GRTS_MAX_CHANNELS;
|
||||
} else if (idx >= GRTS_MAX_CHANNELS) {
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
|
||||
st->ch_map[type] = idx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int grts_get_properties(struct grts_state *st, struct device *dev)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = grts_map_channel(st, dev, GRTS_CH_X, "x", false);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
error = grts_map_channel(st, dev, GRTS_CH_Y, "y", false);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/* pressure is optional */
|
||||
error = grts_map_channel(st, dev, GRTS_CH_PRESSURE, "pressure", true);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (st->ch_map[GRTS_CH_PRESSURE] < GRTS_MAX_CHANNELS) {
|
||||
st->pressure = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if no pressure is defined, try optional z1 + z2 */
|
||||
error = grts_map_channel(st, dev, GRTS_CH_Z1, "z1", true);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (st->ch_map[GRTS_CH_Z1] >= GRTS_MAX_CHANNELS)
|
||||
return 0;
|
||||
|
||||
/* if z1 is provided z2 is not optional */
|
||||
error = grts_map_channel(st, dev, GRTS_CH_Z2, "z2", true);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
error = device_property_read_u32(dev,
|
||||
"touchscreen-x-plate-ohms",
|
||||
&st->x_plate_ohms);
|
||||
if (error) {
|
||||
dev_err(dev, "can't get touchscreen-x-plate-ohms property\n");
|
||||
return error;
|
||||
}
|
||||
|
||||
st->pressure = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int grts_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct grts_state *st;
|
||||
struct input_dev *input;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct iio_channel *chan;
|
||||
int error;
|
||||
|
||||
st = devm_kzalloc(dev, sizeof(struct grts_state), GFP_KERNEL);
|
||||
@ -115,12 +214,13 @@ static int grts_probe(struct platform_device *pdev)
|
||||
return error;
|
||||
}
|
||||
|
||||
chan = &st->iio_chans[0];
|
||||
st->pressure = false;
|
||||
while (chan && chan->indio_dev) {
|
||||
if (!strcmp(chan->channel->datasheet_name, "pressure"))
|
||||
st->pressure = true;
|
||||
chan++;
|
||||
if (!device_property_present(dev, "io-channel-names"))
|
||||
return -ENODEV;
|
||||
|
||||
error = grts_get_properties(st, dev);
|
||||
if (error) {
|
||||
dev_err(dev, "Failed to parse properties\n");
|
||||
return error;
|
||||
}
|
||||
|
||||
if (st->pressure) {
|
||||
@ -148,7 +248,7 @@ static int grts_probe(struct platform_device *pdev)
|
||||
input_set_abs_params(input, ABS_Y, 0, GRTS_MAX_POS_MASK - 1, 0, 0);
|
||||
if (st->pressure)
|
||||
input_set_abs_params(input, ABS_PRESSURE, st->pressure_min,
|
||||
0xffff, 0, 0);
|
||||
GRTS_DEFAULT_PRESSURE_MAX, 0, 0);
|
||||
|
||||
input_set_capability(input, EV_KEY, BTN_TOUCH);
|
||||
|
||||
@ -193,7 +293,7 @@ static struct platform_driver grts_driver = {
|
||||
.probe = grts_probe,
|
||||
.driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.of_match_table = of_match_ptr(grts_of_match),
|
||||
.of_match_table = grts_of_match,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -338,7 +338,7 @@ static struct attribute *tsc200x_attrs[] = {
|
||||
static umode_t tsc200x_attr_is_visible(struct kobject *kobj,
|
||||
struct attribute *attr, int n)
|
||||
{
|
||||
struct device *dev = container_of(kobj, struct device, kobj);
|
||||
struct device *dev = kobj_to_dev(kobj);
|
||||
struct tsc200x *ts = dev_get_drvdata(dev);
|
||||
umode_t mode = attr->mode;
|
||||
|
||||
|
@ -251,7 +251,7 @@ static int e2i_init(struct usbtouch_usb *usbtouch)
|
||||
int ret;
|
||||
struct usb_device *udev = interface_to_usbdev(usbtouch->interface);
|
||||
|
||||
ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
|
||||
ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
|
||||
0x01, 0x02, 0x0000, 0x0081,
|
||||
NULL, 0, USB_CTRL_SET_TIMEOUT);
|
||||
|
||||
@ -531,7 +531,7 @@ static int mtouch_init(struct usbtouch_usb *usbtouch)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
|
||||
ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
|
||||
MTOUCHUSB_RESET,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
||||
1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
|
||||
@ -543,7 +543,7 @@ static int mtouch_init(struct usbtouch_usb *usbtouch)
|
||||
msleep(150);
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
|
||||
ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
|
||||
MTOUCHUSB_ASYNC_REPORT,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
||||
1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT);
|
||||
@ -722,7 +722,7 @@ static int dmc_tsc10_init(struct usbtouch_usb *usbtouch)
|
||||
}
|
||||
|
||||
/* start sending data */
|
||||
ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0),
|
||||
ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
|
||||
TSC10_CMD_DATA1,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
||||
0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
|
||||
|
@ -5,7 +5,6 @@
|
||||
struct cy8ctmg110_pdata
|
||||
{
|
||||
int reset_pin; /* Reset pin is wired to this GPIO (optional) */
|
||||
int irq_pin; /* IRQ pin is wired to this GPIO */
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1,29 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Header file for:
|
||||
* Cypress TrueTouch(TM) Standard Product (TTSP) touchscreen drivers.
|
||||
* For use with Cypress Txx3xx parts.
|
||||
* Supported parts include:
|
||||
* CY8CTST341
|
||||
* CY8CTMA340
|
||||
*
|
||||
* Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc.
|
||||
* Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org>
|
||||
*
|
||||
* Contact Cypress Semiconductor at www.cypress.com (kev@cypress.com)
|
||||
*/
|
||||
#ifndef _CYTTSP_H_
|
||||
#define _CYTTSP_H_
|
||||
|
||||
#define CY_SPI_NAME "cyttsp-spi"
|
||||
#define CY_I2C_NAME "cyttsp-i2c"
|
||||
/* Active Power state scanning/processing refresh interval */
|
||||
#define CY_ACT_INTRVL_DFLT 0x00 /* ms */
|
||||
/* touch timeout for the Active power */
|
||||
#define CY_TCH_TMOUT_DFLT 0xFF /* ms */
|
||||
/* Low Power state scanning/processing refresh interval */
|
||||
#define CY_LP_INTRVL_DFLT 0x0A /* ms */
|
||||
/* Active distance in pixels for a gesture to be reported */
|
||||
#define CY_ACT_DIST_DFLT 0xF8 /* pixels */
|
||||
|
||||
#endif /* _CYTTSP_H_ */
|
Loading…
Reference in New Issue
Block a user