mirror of https://github.com/torvalds/linux.git
Input updates for v6.17-rc0
- updates to several drivers consuming GPIO APIs to use setters returning error codes - an infrastructure allowing to define "overlays" for touchscreens carving out regions implementing buttons and other elements from a bigger sensors and a corresponding update to st1232 driver - an update to AT/PS2 keyboard driver to map F13-F24 by default - Samsung keypad driver got a facelift - evdev input handler will now bind to all devices using EV_SYN event instead of abusing id->driver_info - 2 new sub-drivers implementing 1A (capacitive buttons) and 21 (forcepad button) functions in Synaptics RMI driver - support for polling mode in Goodix touchscreen driver - support for support for FocalTech FT8716 in edt-ft5x06 driver - support for MT6359 in mtk-pmic-keys driver - removal of pcf50633-input driver since platform it was used on is gone - new definitions for game controller "grip" buttons (BTN_GRIP*) and corresponding changes to xpad and hid-steam controller drivers - a new definition for "performance" key -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQST2eWILY88ieB2DOtAj56VGEWXnAUCaJOUOwAKCRBAj56VGEWX nPJTAQC1hrYgCv1L8hxUukbGH5FFPF2nlk63U78izh/dd7R9fwD+OqrQT7+IEr/5 VBqxiqdy77R1mmYs8RpmjOSTg0MEwwg= =jm8o -----END PGP SIGNATURE----- Merge tag 'input-for-v6.17-rc0' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input Pull input updates from Dmitry Torokhov: - updates to several drivers consuming GPIO APIs to use setters returning error codes - an infrastructure allowing to define "overlays" for touchscreens carving out regions implementing buttons and other elements from a bigger sensors and a corresponding update to st1232 driver - an update to AT/PS2 keyboard driver to map F13-F24 by default - Samsung keypad driver got a facelift - evdev input handler will now bind to all devices using EV_SYN event instead of abusing id->driver_info - two new sub-drivers implementing 1A (capacitive buttons) and 21 (forcepad button) functions in Synaptics RMI driver - support for polling mode in Goodix touchscreen driver - support for support for FocalTech FT8716 in edt-ft5x06 driver - support for MT6359 in mtk-pmic-keys driver - removal of pcf50633-input driver since platform it was used on is gone - new definitions for game controller "grip" buttons (BTN_GRIP*) and corresponding changes to xpad and hid-steam controller drivers - a new definition for "performance" key * tag 'input-for-v6.17-rc0' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (38 commits) HID: hid-steam: Use new BTN_GRIP* buttons Input: add keycode for performance mode key Input: max77693 - convert to atomic pwm operation Input: st1232 - add touch-overlay handling dt-bindings: input: touchscreen: st1232: add touch-overlay example Input: touch-overlay - add touchscreen overlay handling dt-bindings: touchscreen: add touch-overlay property Input: atkbd - correctly map F13 - F24 Input: xpad - use new BTN_GRIP* buttons Input: Add and document BTN_GRIP* Input: xpad - change buttons the D-Pad gets mapped as to BTN_DPAD_* Documentation: Fix capitalization of XBox -> Xbox Input: synaptics-rmi4 - add support for F1A dt-bindings: input: syna,rmi4: Document F1A function Input: synaptics-rmi4 - add support for Forcepads (F21) Input: mtk-pmic-keys - add support for MT6359 PMIC keys Input: remove special handling of id->driver_info when matching Input: evdev - switch matching to EV_SYN Input: samsung-keypad - use BIT() and GENMASK() where appropriate Input: samsung-keypad - use per-chip parameters ...
This commit is contained in:
commit
6e64f45803
|
|
@ -89,6 +89,24 @@ properties:
|
|||
required:
|
||||
- reg
|
||||
|
||||
rmi4-f1a@1a:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
$ref: input.yaml#
|
||||
description:
|
||||
RMI4 Function 1A is for capacitive keys.
|
||||
|
||||
properties:
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
linux,keycodes:
|
||||
minItems: 1
|
||||
maxItems: 4
|
||||
|
||||
required:
|
||||
- reg
|
||||
|
||||
patternProperties:
|
||||
"^rmi4-f1[12]@1[12]$":
|
||||
type: object
|
||||
|
|
@ -201,6 +219,7 @@ allOf:
|
|||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/input/linux-event-codes.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
i2c {
|
||||
|
|
@ -234,6 +253,7 @@ examples:
|
|||
|
||||
rmi4-f1a@1a {
|
||||
reg = <0x1a>;
|
||||
linux,keycodes = <KEY_BACK KEY_HOME KEY_MENU>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ properties:
|
|||
- focaltech,ft5452
|
||||
- focaltech,ft6236
|
||||
- focaltech,ft8201
|
||||
- focaltech,ft8716
|
||||
- focaltech,ft8719
|
||||
|
||||
reg:
|
||||
|
|
|
|||
|
|
@ -1,16 +0,0 @@
|
|||
* NXP LPC32xx SoC Touchscreen Controller (TSC)
|
||||
|
||||
Required properties:
|
||||
- compatible: must be "nxp,lpc3220-tsc"
|
||||
- reg: physical base address of the controller and length of memory mapped
|
||||
region.
|
||||
- interrupts: The TSC/ADC interrupt
|
||||
|
||||
Example:
|
||||
|
||||
tsc@40048000 {
|
||||
compatible = "nxp,lpc3220-tsc";
|
||||
reg = <0x40048000 0x1000>;
|
||||
interrupt-parent = <&mic>;
|
||||
interrupts = <39 0>;
|
||||
};
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/input/touchscreen/nxp,lpc3220-tsc.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: NXP LPC32xx SoC Touchscreen Controller (TSC)
|
||||
|
||||
maintainers:
|
||||
- Frank Li <Frank.Li@nxp.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: nxp,lpc3220-tsc
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- interrupts
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/lpc32xx-clock.h>
|
||||
|
||||
touchscreen@40048000 {
|
||||
compatible = "nxp,lpc3220-tsc";
|
||||
reg = <0x40048000 0x1000>;
|
||||
interrupt-parent = <&mic>;
|
||||
interrupts = <39 0>;
|
||||
clocks = <&clk LPC32XX_CLK_ADC>;
|
||||
};
|
||||
|
|
@ -37,6 +37,7 @@ unevaluatedProperties: false
|
|||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/input/linux-event-codes.h>
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
|
@ -46,5 +47,33 @@ examples:
|
|||
reg = <0x55>;
|
||||
interrupts = <2 0>;
|
||||
gpios = <&gpio1 166 0>;
|
||||
|
||||
touch-overlay {
|
||||
segment-0 {
|
||||
label = "Touchscreen";
|
||||
x-origin = <0>;
|
||||
x-size = <240>;
|
||||
y-origin = <40>;
|
||||
y-size = <280>;
|
||||
};
|
||||
|
||||
segment-1a {
|
||||
label = "Camera light";
|
||||
linux,code = <KEY_LIGHTS_TOGGLE>;
|
||||
x-origin = <40>;
|
||||
x-size = <40>;
|
||||
y-origin = <0>;
|
||||
y-size = <40>;
|
||||
};
|
||||
|
||||
segment-2a {
|
||||
label = "Power";
|
||||
linux,code = <KEY_POWER>;
|
||||
x-origin = <160>;
|
||||
x-size = <40>;
|
||||
y-origin = <0>;
|
||||
y-size = <40>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,75 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/input/touchscreen/ti.tsc2007.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Texas Instruments tsc2007 touchscreen controller
|
||||
|
||||
maintainers:
|
||||
- Frank Li <Frank.Li@nxp.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: ti,tsc2007
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
ti,x-plate-ohms:
|
||||
description: X-plate resistance in ohms.
|
||||
|
||||
gpios: true
|
||||
|
||||
pendown-gpio: true
|
||||
|
||||
ti,max-rt:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: maximum pressure.
|
||||
|
||||
ti,fuzzx:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description:
|
||||
specifies the absolute input fuzz x value.
|
||||
If set, it will permit noise in the data up to +- the value given to the fuzz
|
||||
parameter, that is used to filter noise from the event stream.
|
||||
|
||||
ti,fuzzy:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: specifies the absolute input fuzz y value.
|
||||
|
||||
ti,fuzzz:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: specifies the absolute input fuzz z value.
|
||||
|
||||
ti,poll-period:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description:
|
||||
how much time to wait (in milliseconds) before reading again the
|
||||
values from the tsc2007.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- ti,x-plate-ohms
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
touch@49 {
|
||||
compatible = "ti,tsc2007";
|
||||
reg = <0x49>;
|
||||
interrupt-parent = <&gpio4>;
|
||||
interrupts = <0x0 0x8>;
|
||||
gpios = <&gpio4 0 0>;
|
||||
ti,x-plate-ohms = <180>;
|
||||
};
|
||||
};
|
||||
|
|
@ -87,6 +87,125 @@ properties:
|
|||
touchscreen-y-plate-ohms:
|
||||
description: Resistance of the Y-plate in Ohms
|
||||
|
||||
touch-overlay:
|
||||
description: |
|
||||
List of nodes defining segments (touch areas) on the touchscreen.
|
||||
|
||||
This object can be used to describe a series of segments to restrict
|
||||
the region within touch events are reported or buttons with a specific
|
||||
functionality.
|
||||
|
||||
This is of special interest if the touchscreen is shipped with a physical
|
||||
overlay on top of it with a frame that hides some part of the original
|
||||
touchscreen area. Printed buttons on that overlay are also a typical
|
||||
use case.
|
||||
|
||||
A new touchscreen area is defined as a sub-node without a key code. If a
|
||||
key code is defined in the sub-node, it will be interpreted as a button.
|
||||
|
||||
The x-origin and y-origin properties of a touchscreen area define the
|
||||
offset of a new origin from where the touchscreen events are referenced.
|
||||
This offset is applied to the events accordingly. The x-size and y-size
|
||||
properties define the size of the touchscreen effective area.
|
||||
|
||||
The following example shows a new touchscreen area with the new origin
|
||||
(0',0') for the touch events generated by the device.
|
||||
|
||||
Touchscreen (full area)
|
||||
┌────────────────────────────────────────┐
|
||||
│ ┌───────────────────────────────┐ │
|
||||
│ │ │ │
|
||||
│ ├ y-size │ │
|
||||
│ │ │ │
|
||||
│ │ touchscreen area │ │
|
||||
│ │ (no key code) │ │
|
||||
│ │ │ │
|
||||
│ │ x-size │ │
|
||||
│ ┌└──────────────┴────────────────┘ │
|
||||
│(0',0') │
|
||||
┌└────────────────────────────────────────┘
|
||||
(0,0)
|
||||
|
||||
where (0',0') = (0+x-origin,0+y-origin)
|
||||
|
||||
Sub-nodes with key codes report the touch events on their surface as key
|
||||
events instead.
|
||||
|
||||
The following example shows a touchscreen with a single button on it.
|
||||
|
||||
Touchscreen (full area)
|
||||
┌───────────────────────────────────┐
|
||||
│ │
|
||||
│ │
|
||||
│ ┌─────────┐ │
|
||||
│ │button 0 │ │
|
||||
│ │KEY_POWER│ │
|
||||
│ └─────────┘ │
|
||||
│ │
|
||||
│ │
|
||||
┌└───────────────────────────────────┘
|
||||
(0,0)
|
||||
|
||||
Segments defining buttons and clipped toushcreen areas can be combined
|
||||
as shown in the following example.
|
||||
In that case only the events within the touchscreen area are reported
|
||||
as touch events. Events within the button areas report their associated
|
||||
key code. Any events outside the defined areas are ignored.
|
||||
|
||||
Touchscreen (full area)
|
||||
┌─────────┬──────────────────────────────┐
|
||||
│ │ │
|
||||
│ │ ┌───────────────────────┐ │
|
||||
│ button 0│ │ │ │
|
||||
│KEY_POWER│ │ │ │
|
||||
│ │ │ │ │
|
||||
├─────────┤ │ touchscreen area │ │
|
||||
│ │ │ (no key code) │ │
|
||||
│ │ │ │ │
|
||||
│ button 1│ │ │ │
|
||||
│ KEY_INFO│ ┌└───────────────────────┘ │
|
||||
│ │(0',0') │
|
||||
┌└─────────┴──────────────────────────────┘
|
||||
(0,0)
|
||||
|
||||
type: object
|
||||
|
||||
patternProperties:
|
||||
'^segment-':
|
||||
type: object
|
||||
description:
|
||||
Each segment is represented as a sub-node.
|
||||
properties:
|
||||
x-origin:
|
||||
description: horizontal origin of the node area
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
|
||||
y-origin:
|
||||
description: vertical origin of the node area
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
|
||||
x-size:
|
||||
description: horizontal resolution of the node area
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
|
||||
y-size:
|
||||
description: vertical resolution of the node area
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
|
||||
label:
|
||||
description: descriptive name of the segment
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
|
||||
linux,code: true
|
||||
|
||||
required:
|
||||
- x-origin
|
||||
- y-origin
|
||||
- x-size
|
||||
- y-size
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
dependencies:
|
||||
touchscreen-size-x: [ touchscreen-size-y ]
|
||||
touchscreen-size-y: [ touchscreen-size-x ]
|
||||
|
|
|
|||
|
|
@ -1,39 +0,0 @@
|
|||
* Texas Instruments tsc2007 touchscreen controller
|
||||
|
||||
Required properties:
|
||||
- compatible: must be "ti,tsc2007".
|
||||
- reg: I2C address of the chip.
|
||||
- ti,x-plate-ohms: X-plate resistance in ohms.
|
||||
|
||||
Optional properties:
|
||||
- gpios: the interrupt gpio the chip is connected to (through the penirq pin).
|
||||
The penirq pin goes to low when the panel is touched.
|
||||
(see GPIO binding[1] for more details).
|
||||
- interrupts: (gpio) interrupt to which the chip is connected
|
||||
(see interrupt binding[0]).
|
||||
- ti,max-rt: maximum pressure.
|
||||
- ti,fuzzx: specifies the absolute input fuzz x value.
|
||||
If set, it will permit noise in the data up to +- the value given to the fuzz
|
||||
parameter, that is used to filter noise from the event stream.
|
||||
- ti,fuzzy: specifies the absolute input fuzz y value.
|
||||
- ti,fuzzz: specifies the absolute input fuzz z value.
|
||||
- ti,poll-period: how much time to wait (in milliseconds) before reading again the
|
||||
values from the tsc2007.
|
||||
|
||||
[0]: Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
|
||||
[1]: Documentation/devicetree/bindings/gpio/gpio.txt
|
||||
|
||||
Example:
|
||||
&i2c1 {
|
||||
/* ... */
|
||||
tsc2007@49 {
|
||||
compatible = "ti,tsc2007";
|
||||
reg = <0x49>;
|
||||
interrupt-parent = <&gpio4>;
|
||||
interrupts = <0x0 0x8>;
|
||||
gpios = <&gpio4 0 0>;
|
||||
ti,x-plate-ohms = <180>;
|
||||
};
|
||||
|
||||
/* ... */
|
||||
};
|
||||
|
|
@ -29,8 +29,25 @@ The driver allows configuration of the touch screen via a set of sysfs files:
|
|||
|
||||
|
||||
For debugging purposes the driver provides a few files in the debug
|
||||
filesystem (if available in the kernel). In /sys/kernel/debug/edt_ft5x06
|
||||
you'll find the following files:
|
||||
filesystem (if available in the kernel). They are located in:
|
||||
|
||||
/sys/kernel/debug/i2c/<i2c-bus>/<i2c-device>/
|
||||
|
||||
If you don't know the bus and device numbers, you can look them up with this
|
||||
command:
|
||||
|
||||
$ ls -l /sys/bus/i2c/drivers/edt_ft5x06
|
||||
|
||||
The dereference of the symlink will contain the needed information. You will
|
||||
need the last two elements of its path:
|
||||
|
||||
0-0038 -> ../../../../devices/platform/soc/fcfee800.i2c/i2c-0/0-0038
|
||||
|
||||
So in this case, the location for the debug files is:
|
||||
|
||||
/sys/kernel/debug/i2c/i2c-0/0-0038/
|
||||
|
||||
There, you'll find the following files:
|
||||
|
||||
num_x, num_y:
|
||||
(readonly) contains the number of sensor fields in X- and
|
||||
|
|
|
|||
|
|
@ -190,8 +190,21 @@ Gamepads report the following events:
|
|||
|
||||
Rumble is advertised as FF_RUMBLE.
|
||||
|
||||
- Grip buttons:
|
||||
|
||||
Many pads include buttons on the rear, usually referred to as either grip or
|
||||
rear buttons, or paddles. These are often reprogrammable by the firmware to
|
||||
appear as "normal" buttons, but are sometimes exposed to software too. Some
|
||||
notable examples of this are the Steam Deck, which has R4, R5, L4, and L5 on
|
||||
the back; the Xbox Elite pads, which have P1-P4; and the Switch 2 Pro
|
||||
Controller, which has GL and GR.
|
||||
|
||||
For these controllers, BTN_GRIPR and BTN_GRIPR2 should be used for the top
|
||||
and bottom (if present) right grip button(s), and BTN_GRIPL and BTN_GRIPL2
|
||||
should be used for the top and bottom (if present) left grip button(s).
|
||||
|
||||
- Profile:
|
||||
|
||||
Some pads provide a multi-value profile selection switch. An example is the
|
||||
XBox Adaptive and the XBox Elite 2 controllers. When the active profile is
|
||||
switched, its newly selected value is emitted as an ABS_PROFILE event.
|
||||
Some pads provide a multi-value profile selection switch. Examples include
|
||||
the Xbox Adaptive and the Xbox Elite 2 controllers. When the active profile
|
||||
is switched, its newly selected value is emitted as an ABS_PROFILE event.
|
||||
|
|
|
|||
|
|
@ -449,6 +449,6 @@ the 32 bits.
|
|||
xbox-dvd (RC_PROTO_XBOX_DVD)
|
||||
----------------------------
|
||||
|
||||
This protocol is used by XBox DVD Remote, which was made for the original
|
||||
XBox. There is no in-kernel decoder or encoder for this protocol. The usb
|
||||
This protocol is used by Xbox DVD Remote, which was made for the original
|
||||
Xbox. There is no in-kernel decoder or encoder for this protocol. The usb
|
||||
device decodes the protocol. There is a BPF decoder available in v4l-utils.
|
||||
|
|
|
|||
|
|
@ -25499,6 +25499,13 @@ L: platform-driver-x86@vger.kernel.org
|
|||
S: Maintained
|
||||
F: drivers/platform/x86/toshiba-wmi.c
|
||||
|
||||
TOUCH OVERLAY
|
||||
M: Javier Carrasco <javier.carrasco@wolfvision.net>
|
||||
L: linux-input@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/input/touch-overlay.c
|
||||
F: include/linux/input/touch-overlay.h
|
||||
|
||||
TPM DEVICE DRIVER
|
||||
M: Peter Huewe <peterhuewe@gmx.de>
|
||||
M: Jarkko Sakkinen <jarkko@kernel.org>
|
||||
|
|
|
|||
|
|
@ -3291,6 +3291,8 @@ static const char *keys[KEY_MAX + 1] = {
|
|||
[BTN_TR2] = "BtnTR2", [BTN_SELECT] = "BtnSelect",
|
||||
[BTN_START] = "BtnStart", [BTN_MODE] = "BtnMode",
|
||||
[BTN_THUMBL] = "BtnThumbL", [BTN_THUMBR] = "BtnThumbR",
|
||||
[BTN_GRIPL] = "BtnGripL", [BTN_GRIPR] = "BtnGripR",
|
||||
[BTN_GRIPL2] = "BtnGripL2", [BTN_GRIPR2] = "BtnGripR2",
|
||||
[BTN_TOOL_PEN] = "ToolPen", [BTN_TOOL_RUBBER] = "ToolRubber",
|
||||
[BTN_TOOL_BRUSH] = "ToolBrush", [BTN_TOOL_PENCIL] = "ToolPencil",
|
||||
[BTN_TOOL_AIRBRUSH] = "ToolAirbrush", [BTN_TOOL_FINGER] = "ToolFinger",
|
||||
|
|
|
|||
|
|
@ -755,15 +755,12 @@ static int steam_input_register(struct steam_device *steam)
|
|||
input_set_capability(input, EV_KEY, BTN_THUMBL);
|
||||
input_set_capability(input, EV_KEY, BTN_THUMB);
|
||||
input_set_capability(input, EV_KEY, BTN_THUMB2);
|
||||
input_set_capability(input, EV_KEY, BTN_GRIPL);
|
||||
input_set_capability(input, EV_KEY, BTN_GRIPR);
|
||||
if (steam->quirks & STEAM_QUIRK_DECK) {
|
||||
input_set_capability(input, EV_KEY, BTN_BASE);
|
||||
input_set_capability(input, EV_KEY, BTN_TRIGGER_HAPPY1);
|
||||
input_set_capability(input, EV_KEY, BTN_TRIGGER_HAPPY2);
|
||||
input_set_capability(input, EV_KEY, BTN_TRIGGER_HAPPY3);
|
||||
input_set_capability(input, EV_KEY, BTN_TRIGGER_HAPPY4);
|
||||
} else {
|
||||
input_set_capability(input, EV_KEY, BTN_GEAR_DOWN);
|
||||
input_set_capability(input, EV_KEY, BTN_GEAR_UP);
|
||||
input_set_capability(input, EV_KEY, BTN_GRIPL2);
|
||||
input_set_capability(input, EV_KEY, BTN_GRIPR2);
|
||||
}
|
||||
|
||||
input_set_abs_params(input, ABS_X, -32767, 32767, 0, 0);
|
||||
|
|
@ -1419,8 +1416,8 @@ static inline s16 steam_le16(u8 *data)
|
|||
* 9.4 | BTN_SELECT | menu left
|
||||
* 9.5 | BTN_MODE | steam logo
|
||||
* 9.6 | BTN_START | menu right
|
||||
* 9.7 | BTN_GEAR_DOWN | left back lever
|
||||
* 10.0 | BTN_GEAR_UP | right back lever
|
||||
* 9.7 | BTN_GRIPL | left back lever
|
||||
* 10.0 | BTN_GRIPR | right back lever
|
||||
* 10.1 | -- | left-pad clicked
|
||||
* 10.2 | BTN_THUMBR | right-pad clicked
|
||||
* 10.3 | BTN_THUMB | left-pad touched (but see explanation below)
|
||||
|
|
@ -1485,8 +1482,8 @@ static void steam_do_input_event(struct steam_device *steam,
|
|||
input_event(input, EV_KEY, BTN_SELECT, !!(b9 & BIT(4)));
|
||||
input_event(input, EV_KEY, BTN_MODE, !!(b9 & BIT(5)));
|
||||
input_event(input, EV_KEY, BTN_START, !!(b9 & BIT(6)));
|
||||
input_event(input, EV_KEY, BTN_GEAR_DOWN, !!(b9 & BIT(7)));
|
||||
input_event(input, EV_KEY, BTN_GEAR_UP, !!(b10 & BIT(0)));
|
||||
input_event(input, EV_KEY, BTN_GRIPL, !!(b9 & BIT(7)));
|
||||
input_event(input, EV_KEY, BTN_GRIPR, !!(b10 & BIT(0)));
|
||||
input_event(input, EV_KEY, BTN_THUMBR, !!(b10 & BIT(2)));
|
||||
input_event(input, EV_KEY, BTN_THUMBL, !!(b10 & BIT(6)));
|
||||
input_event(input, EV_KEY, BTN_THUMB, lpad_touched || lpad_and_joy);
|
||||
|
|
@ -1547,8 +1544,8 @@ static void steam_do_input_event(struct steam_device *steam,
|
|||
* 9.4 | BTN_SELECT | menu left
|
||||
* 9.5 | BTN_MODE | steam logo
|
||||
* 9.6 | BTN_START | menu right
|
||||
* 9.7 | BTN_TRIGGER_HAPPY3 | left bottom grip button
|
||||
* 10.0 | BTN_TRIGGER_HAPPY4 | right bottom grip button
|
||||
* 9.7 | BTN_GRIPL2 | left bottom grip button
|
||||
* 10.0 | BTN_GRIPR2 | right bottom grip button
|
||||
* 10.1 | BTN_THUMB | left pad pressed
|
||||
* 10.2 | BTN_THUMB2 | right pad pressed
|
||||
* 10.3 | -- | left pad touched
|
||||
|
|
@ -1573,8 +1570,8 @@ static void steam_do_input_event(struct steam_device *steam,
|
|||
* 12.6 | -- | unknown
|
||||
* 12.7 | -- | unknown
|
||||
* 13.0 | -- | unknown
|
||||
* 13.1 | BTN_TRIGGER_HAPPY1 | left top grip button
|
||||
* 13.2 | BTN_TRIGGER_HAPPY2 | right top grip button
|
||||
* 13.1 | BTN_GRIPL | left top grip button
|
||||
* 13.2 | BTN_GRIPR | right top grip button
|
||||
* 13.3 | -- | unknown
|
||||
* 13.4 | -- | unknown
|
||||
* 13.5 | -- | unknown
|
||||
|
|
@ -1659,8 +1656,8 @@ static void steam_do_deck_input_event(struct steam_device *steam,
|
|||
input_event(input, EV_KEY, BTN_SELECT, !!(b9 & BIT(4)));
|
||||
input_event(input, EV_KEY, BTN_MODE, !!(b9 & BIT(5)));
|
||||
input_event(input, EV_KEY, BTN_START, !!(b9 & BIT(6)));
|
||||
input_event(input, EV_KEY, BTN_TRIGGER_HAPPY3, !!(b9 & BIT(7)));
|
||||
input_event(input, EV_KEY, BTN_TRIGGER_HAPPY4, !!(b10 & BIT(0)));
|
||||
input_event(input, EV_KEY, BTN_GRIPL2, !!(b9 & BIT(7)));
|
||||
input_event(input, EV_KEY, BTN_GRIPR2, !!(b10 & BIT(0)));
|
||||
input_event(input, EV_KEY, BTN_THUMBL, !!(b10 & BIT(6)));
|
||||
input_event(input, EV_KEY, BTN_THUMBR, !!(b11 & BIT(2)));
|
||||
input_event(input, EV_KEY, BTN_DPAD_UP, !!(b9 & BIT(0)));
|
||||
|
|
@ -1669,8 +1666,8 @@ static void steam_do_deck_input_event(struct steam_device *steam,
|
|||
input_event(input, EV_KEY, BTN_DPAD_DOWN, !!(b9 & BIT(3)));
|
||||
input_event(input, EV_KEY, BTN_THUMB, !!(b10 & BIT(1)));
|
||||
input_event(input, EV_KEY, BTN_THUMB2, !!(b10 & BIT(2)));
|
||||
input_event(input, EV_KEY, BTN_TRIGGER_HAPPY1, !!(b13 & BIT(1)));
|
||||
input_event(input, EV_KEY, BTN_TRIGGER_HAPPY2, !!(b13 & BIT(2)));
|
||||
input_event(input, EV_KEY, BTN_GRIPL, !!(b13 & BIT(1)));
|
||||
input_event(input, EV_KEY, BTN_GRIPR, !!(b13 & BIT(2)));
|
||||
input_event(input, EV_KEY, BTN_BASE, !!(b14 & BIT(2)));
|
||||
|
||||
input_sync(input);
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
obj-$(CONFIG_INPUT) += input-core.o
|
||||
input-core-y := input.o input-compat.o input-mt.o input-poller.o ff-core.o
|
||||
input-core-y += touchscreen.o
|
||||
input-core-y += touchscreen.o touch-overlay.o
|
||||
|
||||
obj-$(CONFIG_INPUT_FF_MEMLESS) += ff-memless.o
|
||||
obj-$(CONFIG_INPUT_SPARSEKMAP) += sparse-keymap.o
|
||||
|
|
|
|||
|
|
@ -1408,8 +1408,12 @@ static void evdev_disconnect(struct input_handle *handle)
|
|||
}
|
||||
|
||||
static const struct input_device_id evdev_ids[] = {
|
||||
{ .driver_info = 1 }, /* Matches all devices */
|
||||
{ }, /* Terminating zero entry */
|
||||
{
|
||||
/* Matches all devices */
|
||||
.flags = INPUT_DEVICE_ID_MATCH_EVBIT,
|
||||
.evbit = { BIT_MASK(EV_SYN) },
|
||||
},
|
||||
{ } /* Terminating zero entry */
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(input, evdev_ids);
|
||||
|
|
|
|||
|
|
@ -971,7 +971,7 @@ static const struct input_device_id *input_match_device(struct input_handler *ha
|
|||
{
|
||||
const struct input_device_id *id;
|
||||
|
||||
for (id = handler->id_table; id->flags || id->driver_info; id++) {
|
||||
for (id = handler->id_table; id->flags; id++) {
|
||||
if (input_match_device_id(dev, id) &&
|
||||
(!handler->match || handler->match(handler, dev))) {
|
||||
return id;
|
||||
|
|
|
|||
|
|
@ -442,8 +442,8 @@ static const signed short xpad_btn[] = {
|
|||
|
||||
/* used when dpad is mapped to buttons */
|
||||
static const signed short xpad_btn_pad[] = {
|
||||
BTN_TRIGGER_HAPPY1, BTN_TRIGGER_HAPPY2, /* d-pad left, right */
|
||||
BTN_TRIGGER_HAPPY3, BTN_TRIGGER_HAPPY4, /* d-pad up, down */
|
||||
BTN_DPAD_LEFT, BTN_DPAD_RIGHT, /* d-pad left, right */
|
||||
BTN_DPAD_UP, BTN_DPAD_DOWN, /* d-pad up, down */
|
||||
-1 /* terminating entry */
|
||||
};
|
||||
|
||||
|
|
@ -479,8 +479,8 @@ static const signed short xpad_abs_triggers[] = {
|
|||
|
||||
/* used when the controller has extra paddle buttons */
|
||||
static const signed short xpad_btn_paddles[] = {
|
||||
BTN_TRIGGER_HAPPY5, BTN_TRIGGER_HAPPY6, /* paddle upper right, lower right */
|
||||
BTN_TRIGGER_HAPPY7, BTN_TRIGGER_HAPPY8, /* paddle upper left, lower left */
|
||||
BTN_GRIPR, BTN_GRIPR2, /* paddle upper right, lower right */
|
||||
BTN_GRIPL, BTN_GRIPL2, /* paddle upper left, lower left */
|
||||
-1 /* terminating entry */
|
||||
};
|
||||
|
||||
|
|
@ -840,10 +840,10 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d
|
|||
/* digital pad */
|
||||
if (xpad->mapping & MAP_DPAD_TO_BUTTONS) {
|
||||
/* dpad as buttons (left, right, up, down) */
|
||||
input_report_key(dev, BTN_TRIGGER_HAPPY1, data[2] & BIT(2));
|
||||
input_report_key(dev, BTN_TRIGGER_HAPPY2, data[2] & BIT(3));
|
||||
input_report_key(dev, BTN_TRIGGER_HAPPY3, data[2] & BIT(0));
|
||||
input_report_key(dev, BTN_TRIGGER_HAPPY4, data[2] & BIT(1));
|
||||
input_report_key(dev, BTN_DPAD_LEFT, data[2] & BIT(2));
|
||||
input_report_key(dev, BTN_DPAD_RIGHT, data[2] & BIT(3));
|
||||
input_report_key(dev, BTN_DPAD_UP, data[2] & BIT(0));
|
||||
input_report_key(dev, BTN_DPAD_DOWN, data[2] & BIT(1));
|
||||
} else {
|
||||
input_report_abs(dev, ABS_HAT0X,
|
||||
!!(data[2] & 0x08) - !!(data[2] & 0x04));
|
||||
|
|
@ -891,10 +891,10 @@ static void xpad360_process_packet(struct usb_xpad *xpad, struct input_dev *dev,
|
|||
/* digital pad */
|
||||
if (xpad->mapping & MAP_DPAD_TO_BUTTONS) {
|
||||
/* dpad as buttons (left, right, up, down) */
|
||||
input_report_key(dev, BTN_TRIGGER_HAPPY1, data[2] & BIT(2));
|
||||
input_report_key(dev, BTN_TRIGGER_HAPPY2, data[2] & BIT(3));
|
||||
input_report_key(dev, BTN_TRIGGER_HAPPY3, data[2] & BIT(0));
|
||||
input_report_key(dev, BTN_TRIGGER_HAPPY4, data[2] & BIT(1));
|
||||
input_report_key(dev, BTN_DPAD_LEFT, data[2] & BIT(2));
|
||||
input_report_key(dev, BTN_DPAD_RIGHT, data[2] & BIT(3));
|
||||
input_report_key(dev, BTN_DPAD_UP, data[2] & BIT(0));
|
||||
input_report_key(dev, BTN_DPAD_DOWN, data[2] & BIT(1));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1075,10 +1075,10 @@ static void xpadone_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char
|
|||
data[18] = 0;
|
||||
|
||||
/* Elite Series 2 split packet paddle bits */
|
||||
input_report_key(dev, BTN_TRIGGER_HAPPY5, data[18] & BIT(0));
|
||||
input_report_key(dev, BTN_TRIGGER_HAPPY6, data[18] & BIT(1));
|
||||
input_report_key(dev, BTN_TRIGGER_HAPPY7, data[18] & BIT(2));
|
||||
input_report_key(dev, BTN_TRIGGER_HAPPY8, data[18] & BIT(3));
|
||||
input_report_key(dev, BTN_GRIPR, data[18] & BIT(0));
|
||||
input_report_key(dev, BTN_GRIPR2, data[18] & BIT(1));
|
||||
input_report_key(dev, BTN_GRIPL, data[18] & BIT(2));
|
||||
input_report_key(dev, BTN_GRIPL2, data[18] & BIT(3));
|
||||
|
||||
do_sync = true;
|
||||
}
|
||||
|
|
@ -1113,10 +1113,10 @@ static void xpadone_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char
|
|||
/* digital pad */
|
||||
if (xpad->mapping & MAP_DPAD_TO_BUTTONS) {
|
||||
/* dpad as buttons (left, right, up, down) */
|
||||
input_report_key(dev, BTN_TRIGGER_HAPPY1, data[5] & BIT(2));
|
||||
input_report_key(dev, BTN_TRIGGER_HAPPY2, data[5] & BIT(3));
|
||||
input_report_key(dev, BTN_TRIGGER_HAPPY3, data[5] & BIT(0));
|
||||
input_report_key(dev, BTN_TRIGGER_HAPPY4, data[5] & BIT(1));
|
||||
input_report_key(dev, BTN_DPAD_LEFT, data[5] & BIT(2));
|
||||
input_report_key(dev, BTN_DPAD_RIGHT, data[5] & BIT(3));
|
||||
input_report_key(dev, BTN_DPAD_UP, data[5] & BIT(0));
|
||||
input_report_key(dev, BTN_DPAD_DOWN, data[5] & BIT(1));
|
||||
} else {
|
||||
input_report_abs(dev, ABS_HAT0X,
|
||||
!!(data[5] & 0x08) - !!(data[5] & 0x04));
|
||||
|
|
@ -1175,10 +1175,10 @@ static void xpadone_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char
|
|||
data[32] = 0;
|
||||
|
||||
/* OG Elite Series Controller paddle bits */
|
||||
input_report_key(dev, BTN_TRIGGER_HAPPY5, data[32] & BIT(1));
|
||||
input_report_key(dev, BTN_TRIGGER_HAPPY6, data[32] & BIT(3));
|
||||
input_report_key(dev, BTN_TRIGGER_HAPPY7, data[32] & BIT(0));
|
||||
input_report_key(dev, BTN_TRIGGER_HAPPY8, data[32] & BIT(2));
|
||||
input_report_key(dev, BTN_GRIPR, data[32] & BIT(1));
|
||||
input_report_key(dev, BTN_GRIPR2, data[32] & BIT(3));
|
||||
input_report_key(dev, BTN_GRIPL, data[32] & BIT(0));
|
||||
input_report_key(dev, BTN_GRIPL2, data[32] & BIT(2));
|
||||
} else if (xpad->packet_type == PKT_XBE2_FW_OLD) {
|
||||
/* Mute paddles if controller has a custom mapping applied.
|
||||
* Checked by comparing the current mapping
|
||||
|
|
@ -1188,10 +1188,10 @@ static void xpadone_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char
|
|||
data[18] = 0;
|
||||
|
||||
/* Elite Series 2 4.x firmware paddle bits */
|
||||
input_report_key(dev, BTN_TRIGGER_HAPPY5, data[18] & BIT(0));
|
||||
input_report_key(dev, BTN_TRIGGER_HAPPY6, data[18] & BIT(1));
|
||||
input_report_key(dev, BTN_TRIGGER_HAPPY7, data[18] & BIT(2));
|
||||
input_report_key(dev, BTN_TRIGGER_HAPPY8, data[18] & BIT(3));
|
||||
input_report_key(dev, BTN_GRIPR, data[18] & BIT(0));
|
||||
input_report_key(dev, BTN_GRIPR2, data[18] & BIT(1));
|
||||
input_report_key(dev, BTN_GRIPL, data[18] & BIT(2));
|
||||
input_report_key(dev, BTN_GRIPL2, data[18] & BIT(3));
|
||||
} else if (xpad->packet_type == PKT_XBE2_FW_5_EARLY) {
|
||||
/* Mute paddles if controller has a custom mapping applied.
|
||||
* Checked by comparing the current mapping
|
||||
|
|
@ -1203,10 +1203,10 @@ static void xpadone_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char
|
|||
/* Elite Series 2 5.x firmware paddle bits
|
||||
* (before the packet was split)
|
||||
*/
|
||||
input_report_key(dev, BTN_TRIGGER_HAPPY5, data[22] & BIT(0));
|
||||
input_report_key(dev, BTN_TRIGGER_HAPPY6, data[22] & BIT(1));
|
||||
input_report_key(dev, BTN_TRIGGER_HAPPY7, data[22] & BIT(2));
|
||||
input_report_key(dev, BTN_TRIGGER_HAPPY8, data[22] & BIT(3));
|
||||
input_report_key(dev, BTN_GRIPR, data[22] & BIT(0));
|
||||
input_report_key(dev, BTN_GRIPR2, data[22] & BIT(1));
|
||||
input_report_key(dev, BTN_GRIPL, data[22] & BIT(2));
|
||||
input_report_key(dev, BTN_GRIPL2, data[22] & BIT(3));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -232,8 +232,8 @@ static int adp5588_gpio_get_value(struct gpio_chip *chip, unsigned int off)
|
|||
return !!(val & bit);
|
||||
}
|
||||
|
||||
static void adp5588_gpio_set_value(struct gpio_chip *chip,
|
||||
unsigned int off, int val)
|
||||
static int adp5588_gpio_set_value(struct gpio_chip *chip, unsigned int off,
|
||||
int val)
|
||||
{
|
||||
struct adp5588_kpad *kpad = gpiochip_get_data(chip);
|
||||
unsigned int bank = ADP5588_BANK(kpad->gpiomap[off]);
|
||||
|
|
@ -246,7 +246,8 @@ static void adp5588_gpio_set_value(struct gpio_chip *chip,
|
|||
else
|
||||
kpad->dat_out[bank] &= ~bit;
|
||||
|
||||
adp5588_write(kpad->client, GPIO_DAT_OUT1 + bank, kpad->dat_out[bank]);
|
||||
return adp5588_write(kpad->client, GPIO_DAT_OUT1 + bank,
|
||||
kpad->dat_out[bank]);
|
||||
}
|
||||
|
||||
static int adp5588_gpio_set_config(struct gpio_chip *chip, unsigned int off,
|
||||
|
|
@ -424,7 +425,7 @@ static int adp5588_gpio_add(struct adp5588_kpad *kpad)
|
|||
kpad->gc.direction_input = adp5588_gpio_direction_input;
|
||||
kpad->gc.direction_output = adp5588_gpio_direction_output;
|
||||
kpad->gc.get = adp5588_gpio_get_value;
|
||||
kpad->gc.set = adp5588_gpio_set_value;
|
||||
kpad->gc.set_rv = adp5588_gpio_set_value;
|
||||
kpad->gc.set_config = adp5588_gpio_set_config;
|
||||
kpad->gc.can_sleep = 1;
|
||||
|
||||
|
|
|
|||
|
|
@ -84,12 +84,12 @@ static const unsigned short atkbd_set2_keycode[ATKBD_KEYMAP_SIZE] = {
|
|||
#include "hpps2atkbd.h" /* include the keyboard scancodes */
|
||||
|
||||
#else
|
||||
0, 67, 65, 63, 61, 59, 60, 88, 0, 68, 66, 64, 62, 15, 41,117,
|
||||
0, 56, 42, 93, 29, 16, 2, 0, 0, 0, 44, 31, 30, 17, 3, 0,
|
||||
0, 46, 45, 32, 18, 5, 4, 95, 0, 57, 47, 33, 20, 19, 6,183,
|
||||
0, 49, 48, 35, 34, 21, 7,184, 0, 0, 50, 36, 22, 8, 9,185,
|
||||
0, 51, 37, 23, 24, 11, 10, 0, 0, 52, 53, 38, 39, 25, 12, 0,
|
||||
0, 89, 40, 0, 26, 13, 0,193, 58, 54, 28, 27, 0, 43, 0, 85,
|
||||
0, 67, 65, 63, 61, 59, 60, 88,183, 68, 66, 64, 62, 15, 41,117,
|
||||
184, 56, 42, 93, 29, 16, 2, 0,185, 0, 44, 31, 30, 17, 3, 0,
|
||||
186, 46, 45, 32, 18, 5, 4, 95,187, 57, 47, 33, 20, 19, 6,183,
|
||||
188, 49, 48, 35, 34, 21, 7,184,189, 0, 50, 36, 22, 8, 9,185,
|
||||
190, 51, 37, 23, 24, 11, 10, 0,191, 52, 53, 38, 39, 25, 12, 0,
|
||||
192, 89, 40, 0, 26, 13, 0,193, 58, 54, 28, 27, 0, 43, 0,194,
|
||||
0, 86, 91, 90, 92, 0, 14, 94, 0, 79,124, 75, 71,121, 0, 0,
|
||||
82, 83, 80, 76, 77, 72, 1, 69, 87, 78, 81, 74, 55, 73, 70, 99,
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#include <linux/mfd/mt6331/registers.h>
|
||||
#include <linux/mfd/mt6357/registers.h>
|
||||
#include <linux/mfd/mt6358/registers.h>
|
||||
#include <linux/mfd/mt6359/registers.h>
|
||||
#include <linux/mfd/mt6397/core.h>
|
||||
#include <linux/mfd/mt6397/registers.h>
|
||||
#include <linux/module.h>
|
||||
|
|
@ -117,6 +118,19 @@ static const struct mtk_pmic_regs mt6358_regs = {
|
|||
.rst_lprst_mask = MTK_PMIC_RST_DU_MASK,
|
||||
};
|
||||
|
||||
static const struct mtk_pmic_regs mt6359_regs = {
|
||||
.keys_regs[MTK_PMIC_PWRKEY_INDEX] =
|
||||
MTK_PMIC_KEYS_REGS(MT6359_TOPSTATUS,
|
||||
0x2, MT6359_PSC_TOP_INT_CON0, 0x5,
|
||||
MTK_PMIC_PWRKEY_RST),
|
||||
.keys_regs[MTK_PMIC_HOMEKEY_INDEX] =
|
||||
MTK_PMIC_KEYS_REGS(MT6359_TOPSTATUS,
|
||||
0x8, MT6359_PSC_TOP_INT_CON0, 0xa,
|
||||
MTK_PMIC_HOMEKEY_RST),
|
||||
.pmic_rst_reg = MT6359_TOP_RST_MISC,
|
||||
.rst_lprst_mask = MTK_PMIC_RST_DU_MASK,
|
||||
};
|
||||
|
||||
struct mtk_pmic_keys_info {
|
||||
struct mtk_pmic_keys *keys;
|
||||
const struct mtk_pmic_keys_regs *regs;
|
||||
|
|
@ -296,6 +310,9 @@ static const struct of_device_id of_mtk_pmic_keys_match_tbl[] = {
|
|||
}, {
|
||||
.compatible = "mediatek,mt6358-keys",
|
||||
.data = &mt6358_regs,
|
||||
}, {
|
||||
.compatible = "mediatek,mt6359-keys",
|
||||
.data = &mt6359_regs,
|
||||
}, {
|
||||
/* sentinel */
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
* Author: Donghwa Lee <dh09.lee@samsung.com>
|
||||
*/
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
|
|
@ -29,11 +30,11 @@
|
|||
#define SAMSUNG_KEYIFFC 0x10
|
||||
|
||||
/* SAMSUNG_KEYIFCON */
|
||||
#define SAMSUNG_KEYIFCON_INT_F_EN (1 << 0)
|
||||
#define SAMSUNG_KEYIFCON_INT_R_EN (1 << 1)
|
||||
#define SAMSUNG_KEYIFCON_DF_EN (1 << 2)
|
||||
#define SAMSUNG_KEYIFCON_FC_EN (1 << 3)
|
||||
#define SAMSUNG_KEYIFCON_WAKEUPEN (1 << 4)
|
||||
#define SAMSUNG_KEYIFCON_INT_F_EN BIT(0)
|
||||
#define SAMSUNG_KEYIFCON_INT_R_EN BIT(1)
|
||||
#define SAMSUNG_KEYIFCON_DF_EN BIT(2)
|
||||
#define SAMSUNG_KEYIFCON_FC_EN BIT(3)
|
||||
#define SAMSUNG_KEYIFCON_WAKEUPEN BIT(4)
|
||||
|
||||
/* SAMSUNG_KEYIFSTSCLR */
|
||||
#define SAMSUNG_KEYIFSTSCLR_P_INT_MASK (0xff << 0)
|
||||
|
|
@ -44,8 +45,7 @@
|
|||
#define S5PV210_KEYIFSTSCLR_R_INT_OFFSET 16
|
||||
|
||||
/* SAMSUNG_KEYIFCOL */
|
||||
#define SAMSUNG_KEYIFCOL_MASK (0xff << 0)
|
||||
#define S5PV210_KEYIFCOLEN_MASK (0xff << 8)
|
||||
#define SAMSUNG_KEYIFCOL_MASK 0xff
|
||||
|
||||
/* SAMSUNG_KEYIFROW */
|
||||
#define SAMSUNG_KEYIFROW_MASK (0xff << 0)
|
||||
|
|
@ -54,12 +54,12 @@
|
|||
/* SAMSUNG_KEYIFFC */
|
||||
#define SAMSUNG_KEYIFFC_MASK (0x3ff << 0)
|
||||
|
||||
enum samsung_keypad_type {
|
||||
KEYPAD_TYPE_SAMSUNG,
|
||||
KEYPAD_TYPE_S5PV210,
|
||||
struct samsung_chip_info {
|
||||
unsigned int column_shift;
|
||||
};
|
||||
|
||||
struct samsung_keypad {
|
||||
const struct samsung_chip_info *chip;
|
||||
struct input_dev *input_dev;
|
||||
struct platform_device *pdev;
|
||||
struct clk *clk;
|
||||
|
|
@ -68,7 +68,6 @@ struct samsung_keypad {
|
|||
bool stopped;
|
||||
bool wake_enabled;
|
||||
int irq;
|
||||
enum samsung_keypad_type type;
|
||||
unsigned int row_shift;
|
||||
unsigned int rows;
|
||||
unsigned int cols;
|
||||
|
|
@ -83,19 +82,14 @@ static void samsung_keypad_scan(struct samsung_keypad *keypad,
|
|||
unsigned int val;
|
||||
|
||||
for (col = 0; col < keypad->cols; col++) {
|
||||
if (keypad->type == KEYPAD_TYPE_S5PV210) {
|
||||
val = S5PV210_KEYIFCOLEN_MASK;
|
||||
val &= ~(1 << col) << 8;
|
||||
} else {
|
||||
val = SAMSUNG_KEYIFCOL_MASK;
|
||||
val &= ~(1 << col);
|
||||
}
|
||||
val = SAMSUNG_KEYIFCOL_MASK & ~BIT(col);
|
||||
val <<= keypad->chip->column_shift;
|
||||
|
||||
writel(val, keypad->base + SAMSUNG_KEYIFCOL);
|
||||
mdelay(1);
|
||||
|
||||
val = readl(keypad->base + SAMSUNG_KEYIFROW);
|
||||
row_state[col] = ~val & ((1 << keypad->rows) - 1);
|
||||
row_state[col] = ~val & GENMASK(keypad->rows - 1, 0);
|
||||
}
|
||||
|
||||
/* KEYIFCOL reg clear */
|
||||
|
|
@ -119,10 +113,10 @@ static bool samsung_keypad_report(struct samsung_keypad *keypad,
|
|||
continue;
|
||||
|
||||
for (row = 0; row < keypad->rows; row++) {
|
||||
if (!(changed & (1 << row)))
|
||||
if (!(changed & BIT(row)))
|
||||
continue;
|
||||
|
||||
pressed = row_state[col] & (1 << row);
|
||||
pressed = row_state[col] & BIT(row);
|
||||
|
||||
dev_dbg(&keypad->input_dev->dev,
|
||||
"key %s, row: %d, col: %d\n",
|
||||
|
|
@ -314,11 +308,11 @@ static int samsung_keypad_probe(struct platform_device *pdev)
|
|||
{
|
||||
const struct samsung_keypad_platdata *pdata;
|
||||
const struct matrix_keymap_data *keymap_data;
|
||||
const struct platform_device_id *id;
|
||||
struct samsung_keypad *keypad;
|
||||
struct resource *res;
|
||||
struct input_dev *input_dev;
|
||||
unsigned int row_shift;
|
||||
unsigned int keymap_size;
|
||||
int error;
|
||||
|
||||
pdata = dev_get_platdata(&pdev->dev);
|
||||
|
|
@ -345,12 +339,16 @@ static int samsung_keypad_probe(struct platform_device *pdev)
|
|||
pdata->cfg_gpio(pdata->rows, pdata->cols);
|
||||
|
||||
row_shift = get_count_order(pdata->cols);
|
||||
keymap_size = (pdata->rows << row_shift) * sizeof(keypad->keycodes[0]);
|
||||
|
||||
keypad = devm_kzalloc(&pdev->dev, sizeof(*keypad) + keymap_size,
|
||||
keypad = devm_kzalloc(&pdev->dev,
|
||||
struct_size(keypad, keycodes,
|
||||
pdata->rows << row_shift),
|
||||
GFP_KERNEL);
|
||||
if (!keypad)
|
||||
return -ENOMEM;
|
||||
|
||||
input_dev = devm_input_allocate_device(&pdev->dev);
|
||||
if (!keypad || !input_dev)
|
||||
if (!input_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
|
|
@ -361,18 +359,12 @@ static int samsung_keypad_probe(struct platform_device *pdev)
|
|||
if (!keypad->base)
|
||||
return -EBUSY;
|
||||
|
||||
keypad->clk = devm_clk_get(&pdev->dev, "keypad");
|
||||
keypad->clk = devm_clk_get_prepared(&pdev->dev, "keypad");
|
||||
if (IS_ERR(keypad->clk)) {
|
||||
dev_err(&pdev->dev, "failed to get keypad clk\n");
|
||||
return PTR_ERR(keypad->clk);
|
||||
}
|
||||
|
||||
error = clk_prepare(keypad->clk);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "keypad clock prepare failed\n");
|
||||
return error;
|
||||
}
|
||||
|
||||
keypad->input_dev = input_dev;
|
||||
keypad->pdev = pdev;
|
||||
keypad->row_shift = row_shift;
|
||||
|
|
@ -381,15 +373,20 @@ static int samsung_keypad_probe(struct platform_device *pdev)
|
|||
keypad->stopped = true;
|
||||
init_waitqueue_head(&keypad->wait);
|
||||
|
||||
if (pdev->dev.of_node)
|
||||
keypad->type = of_device_is_compatible(pdev->dev.of_node,
|
||||
"samsung,s5pv210-keypad");
|
||||
else
|
||||
keypad->type = platform_get_device_id(pdev)->driver_data;
|
||||
keypad->chip = device_get_match_data(&pdev->dev);
|
||||
if (!keypad->chip) {
|
||||
id = platform_get_device_id(pdev);
|
||||
if (id)
|
||||
keypad->chip = (const void *)id->driver_data;
|
||||
}
|
||||
|
||||
if (!keypad->chip) {
|
||||
dev_err(&pdev->dev, "Unable to determine chip type");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
input_dev->name = pdev->name;
|
||||
input_dev->id.bustype = BUS_HOST;
|
||||
input_dev->dev.parent = &pdev->dev;
|
||||
|
||||
input_dev->open = samsung_keypad_open;
|
||||
input_dev->close = samsung_keypad_close;
|
||||
|
|
@ -399,7 +396,7 @@ static int samsung_keypad_probe(struct platform_device *pdev)
|
|||
keypad->keycodes, input_dev);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "failed to build keymap\n");
|
||||
goto err_unprepare_clk;
|
||||
return error;
|
||||
}
|
||||
|
||||
input_set_capability(input_dev, EV_MSC, MSC_SCAN);
|
||||
|
|
@ -411,7 +408,7 @@ static int samsung_keypad_probe(struct platform_device *pdev)
|
|||
keypad->irq = platform_get_irq(pdev, 0);
|
||||
if (keypad->irq < 0) {
|
||||
error = keypad->irq;
|
||||
goto err_unprepare_clk;
|
||||
return error;
|
||||
}
|
||||
|
||||
error = devm_request_threaded_irq(&pdev->dev, keypad->irq, NULL,
|
||||
|
|
@ -419,16 +416,19 @@ static int samsung_keypad_probe(struct platform_device *pdev)
|
|||
dev_name(&pdev->dev), keypad);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "failed to register keypad interrupt\n");
|
||||
goto err_unprepare_clk;
|
||||
return error;
|
||||
}
|
||||
|
||||
device_init_wakeup(&pdev->dev, pdata->wakeup);
|
||||
platform_set_drvdata(pdev, keypad);
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
error = devm_pm_runtime_enable(&pdev->dev);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
error = input_register_device(keypad->input_dev);
|
||||
if (error)
|
||||
goto err_disable_runtime_pm;
|
||||
return error;
|
||||
|
||||
if (pdev->dev.of_node) {
|
||||
devm_kfree(&pdev->dev, (void *)pdata->keymap_data->keymap);
|
||||
|
|
@ -436,23 +436,6 @@ static int samsung_keypad_probe(struct platform_device *pdev)
|
|||
devm_kfree(&pdev->dev, (void *)pdata);
|
||||
}
|
||||
return 0;
|
||||
|
||||
err_disable_runtime_pm:
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
err_unprepare_clk:
|
||||
clk_unprepare(keypad->clk);
|
||||
return error;
|
||||
}
|
||||
|
||||
static void samsung_keypad_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct samsung_keypad *keypad = platform_get_drvdata(pdev);
|
||||
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
input_unregister_device(keypad->input_dev);
|
||||
|
||||
clk_unprepare(keypad->clk);
|
||||
}
|
||||
|
||||
static int samsung_keypad_runtime_suspend(struct device *dev)
|
||||
|
|
@ -528,15 +511,13 @@ static int samsung_keypad_suspend(struct device *dev)
|
|||
struct samsung_keypad *keypad = platform_get_drvdata(pdev);
|
||||
struct input_dev *input_dev = keypad->input_dev;
|
||||
|
||||
mutex_lock(&input_dev->mutex);
|
||||
guard(mutex)(&input_dev->mutex);
|
||||
|
||||
if (input_device_enabled(input_dev))
|
||||
samsung_keypad_stop(keypad);
|
||||
|
||||
samsung_keypad_toggle_wakeup(keypad, true);
|
||||
|
||||
mutex_unlock(&input_dev->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -546,15 +527,13 @@ static int samsung_keypad_resume(struct device *dev)
|
|||
struct samsung_keypad *keypad = platform_get_drvdata(pdev);
|
||||
struct input_dev *input_dev = keypad->input_dev;
|
||||
|
||||
mutex_lock(&input_dev->mutex);
|
||||
guard(mutex)(&input_dev->mutex);
|
||||
|
||||
samsung_keypad_toggle_wakeup(keypad, false);
|
||||
|
||||
if (input_device_enabled(input_dev))
|
||||
samsung_keypad_start(keypad);
|
||||
|
||||
mutex_unlock(&input_dev->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -564,11 +543,24 @@ static const struct dev_pm_ops samsung_keypad_pm_ops = {
|
|||
samsung_keypad_runtime_resume, NULL)
|
||||
};
|
||||
|
||||
static const struct samsung_chip_info samsung_s3c6410_chip_info = {
|
||||
.column_shift = 0,
|
||||
};
|
||||
|
||||
static const struct samsung_chip_info samsung_s5pv210_chip_info = {
|
||||
.column_shift = 8,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id samsung_keypad_dt_match[] = {
|
||||
{ .compatible = "samsung,s3c6410-keypad" },
|
||||
{ .compatible = "samsung,s5pv210-keypad" },
|
||||
{},
|
||||
{
|
||||
.compatible = "samsung,s3c6410-keypad",
|
||||
.data = &samsung_s3c6410_chip_info,
|
||||
}, {
|
||||
.compatible = "samsung,s5pv210-keypad",
|
||||
.data = &samsung_s5pv210_chip_info,
|
||||
},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, samsung_keypad_dt_match);
|
||||
#endif
|
||||
|
|
@ -576,18 +568,17 @@ MODULE_DEVICE_TABLE(of, samsung_keypad_dt_match);
|
|||
static const struct platform_device_id samsung_keypad_driver_ids[] = {
|
||||
{
|
||||
.name = "samsung-keypad",
|
||||
.driver_data = KEYPAD_TYPE_SAMSUNG,
|
||||
.driver_data = (kernel_ulong_t)&samsung_s3c6410_chip_info,
|
||||
}, {
|
||||
.name = "s5pv210-keypad",
|
||||
.driver_data = KEYPAD_TYPE_S5PV210,
|
||||
.driver_data = (kernel_ulong_t)&samsung_s5pv210_chip_info,
|
||||
},
|
||||
{ },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, samsung_keypad_driver_ids);
|
||||
|
||||
static struct platform_driver samsung_keypad_driver = {
|
||||
.probe = samsung_keypad_probe,
|
||||
.remove = samsung_keypad_remove,
|
||||
.driver = {
|
||||
.name = "samsung-keypad",
|
||||
.of_match_table = of_match_ptr(samsung_keypad_dt_match),
|
||||
|
|
|
|||
|
|
@ -584,13 +584,6 @@ config INPUT_PALMAS_PWRBUTTON
|
|||
To compile this driver as a module, choose M here. The module will
|
||||
be called palmas_pwrbutton.
|
||||
|
||||
config INPUT_PCF50633_PMU
|
||||
tristate "PCF50633 PMU events"
|
||||
depends on MFD_PCF50633
|
||||
help
|
||||
Say Y to include support for delivering PMU events via input
|
||||
layer on NXP PCF50633.
|
||||
|
||||
config INPUT_PCF8574
|
||||
tristate "PCF8574 Keypad input device"
|
||||
depends on I2C
|
||||
|
|
|
|||
|
|
@ -59,7 +59,6 @@ obj-$(CONFIG_INPUT_MC13783_PWRBUTTON) += mc13783-pwrbutton.o
|
|||
obj-$(CONFIG_INPUT_MMA8450) += mma8450.o
|
||||
obj-$(CONFIG_INPUT_PALMAS_PWRBUTTON) += palmas-pwrbutton.o
|
||||
obj-$(CONFIG_INPUT_PCAP) += pcap_keys.o
|
||||
obj-$(CONFIG_INPUT_PCF50633_PMU) += pcf50633-input.o
|
||||
obj-$(CONFIG_INPUT_PCF8574) += pcf8574_keypad.o
|
||||
obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o
|
||||
obj-$(CONFIG_INPUT_PM8941_PWRKEY) += pm8941-pwrkey.o
|
||||
|
|
|
|||
|
|
@ -482,7 +482,6 @@ static int cs40l50_erase(struct input_dev *dev, int effect_id)
|
|||
|
||||
static void cs40l50_remove_wq(void *data)
|
||||
{
|
||||
flush_workqueue(data);
|
||||
destroy_workqueue(data);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -68,15 +68,16 @@ struct max77693_haptic {
|
|||
|
||||
static int max77693_haptic_set_duty_cycle(struct max77693_haptic *haptic)
|
||||
{
|
||||
struct pwm_args pargs;
|
||||
int delta;
|
||||
struct pwm_state state;
|
||||
int error;
|
||||
|
||||
pwm_get_args(haptic->pwm_dev, &pargs);
|
||||
delta = (pargs.period + haptic->pwm_duty) / 2;
|
||||
error = pwm_config(haptic->pwm_dev, delta, pargs.period);
|
||||
pwm_init_state(haptic->pwm_dev, &state);
|
||||
state.duty_cycle = (state.period + haptic->pwm_duty) / 2;
|
||||
|
||||
error = pwm_apply_might_sleep(haptic->pwm_dev, &state);
|
||||
if (error) {
|
||||
dev_err(haptic->dev, "failed to configure pwm: %d\n", error);
|
||||
dev_err(haptic->dev,
|
||||
"failed to set pwm duty cycle: %d\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
@ -166,12 +167,17 @@ static int max77693_haptic_lowsys(struct max77693_haptic *haptic, bool enable)
|
|||
|
||||
static void max77693_haptic_enable(struct max77693_haptic *haptic)
|
||||
{
|
||||
struct pwm_state state;
|
||||
int error;
|
||||
|
||||
if (haptic->enabled)
|
||||
return;
|
||||
|
||||
error = pwm_enable(haptic->pwm_dev);
|
||||
pwm_init_state(haptic->pwm_dev, &state);
|
||||
state.duty_cycle = (state.period + haptic->pwm_duty) / 2;
|
||||
state.enabled = true;
|
||||
|
||||
error = pwm_apply_might_sleep(haptic->pwm_dev, &state);
|
||||
if (error) {
|
||||
dev_err(haptic->dev,
|
||||
"failed to enable haptic pwm device: %d\n", error);
|
||||
|
|
@ -224,18 +230,13 @@ static void max77693_haptic_play_work(struct work_struct *work)
|
|||
{
|
||||
struct max77693_haptic *haptic =
|
||||
container_of(work, struct max77693_haptic, work);
|
||||
int error;
|
||||
|
||||
error = max77693_haptic_set_duty_cycle(haptic);
|
||||
if (error) {
|
||||
dev_err(haptic->dev, "failed to set duty cycle: %d\n", error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (haptic->magnitude)
|
||||
max77693_haptic_enable(haptic);
|
||||
else
|
||||
if (!haptic->magnitude)
|
||||
max77693_haptic_disable(haptic);
|
||||
else if (haptic->enabled)
|
||||
max77693_haptic_set_duty_cycle(haptic);
|
||||
else
|
||||
max77693_haptic_enable(haptic);
|
||||
}
|
||||
|
||||
static int max77693_haptic_play_effect(struct input_dev *dev, void *data,
|
||||
|
|
@ -340,12 +341,6 @@ static int max77693_haptic_probe(struct platform_device *pdev)
|
|||
return PTR_ERR(haptic->pwm_dev);
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: pwm_apply_args() should be removed when switching to the
|
||||
* atomic PWM API.
|
||||
*/
|
||||
pwm_apply_args(haptic->pwm_dev);
|
||||
|
||||
haptic->motor_reg = devm_regulator_get(&pdev->dev, "haptic");
|
||||
if (IS_ERR(haptic->motor_reg)) {
|
||||
dev_err(&pdev->dev, "failed to get regulator\n");
|
||||
|
|
|
|||
|
|
@ -53,40 +53,30 @@ struct max8997_haptic {
|
|||
unsigned int pattern_signal_period;
|
||||
};
|
||||
|
||||
static int max8997_haptic_set_duty_cycle(struct max8997_haptic *chip)
|
||||
static void max8997_haptic_set_internal_duty_cycle(struct max8997_haptic *chip)
|
||||
{
|
||||
int ret = 0;
|
||||
u8 duty_index = DIV_ROUND_UP(chip->level * 64, 100);
|
||||
|
||||
if (chip->mode == MAX8997_EXTERNAL_MODE) {
|
||||
unsigned int duty = chip->pwm_period * chip->level / 100;
|
||||
ret = pwm_config(chip->pwm, duty, chip->pwm_period);
|
||||
} else {
|
||||
u8 duty_index = 0;
|
||||
|
||||
duty_index = DIV_ROUND_UP(chip->level * 64, 100);
|
||||
|
||||
switch (chip->internal_mode_pattern) {
|
||||
case 0:
|
||||
max8997_write_reg(chip->client,
|
||||
MAX8997_HAPTIC_REG_SIGPWMDC1, duty_index);
|
||||
break;
|
||||
case 1:
|
||||
max8997_write_reg(chip->client,
|
||||
MAX8997_HAPTIC_REG_SIGPWMDC2, duty_index);
|
||||
break;
|
||||
case 2:
|
||||
max8997_write_reg(chip->client,
|
||||
MAX8997_HAPTIC_REG_SIGPWMDC3, duty_index);
|
||||
break;
|
||||
case 3:
|
||||
max8997_write_reg(chip->client,
|
||||
MAX8997_HAPTIC_REG_SIGPWMDC4, duty_index);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch (chip->internal_mode_pattern) {
|
||||
case 0:
|
||||
max8997_write_reg(chip->client,
|
||||
MAX8997_HAPTIC_REG_SIGPWMDC1, duty_index);
|
||||
break;
|
||||
case 1:
|
||||
max8997_write_reg(chip->client,
|
||||
MAX8997_HAPTIC_REG_SIGPWMDC2, duty_index);
|
||||
break;
|
||||
case 2:
|
||||
max8997_write_reg(chip->client,
|
||||
MAX8997_HAPTIC_REG_SIGPWMDC3, duty_index);
|
||||
break;
|
||||
case 3:
|
||||
max8997_write_reg(chip->client,
|
||||
MAX8997_HAPTIC_REG_SIGPWMDC4, duty_index);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void max8997_haptic_configure(struct max8997_haptic *chip)
|
||||
|
|
@ -155,11 +145,8 @@ static void max8997_haptic_enable(struct max8997_haptic *chip)
|
|||
|
||||
guard(mutex)(&chip->mutex);
|
||||
|
||||
error = max8997_haptic_set_duty_cycle(chip);
|
||||
if (error) {
|
||||
dev_err(chip->dev, "set_pwm_cycle failed, error: %d\n", error);
|
||||
return;
|
||||
}
|
||||
if (chip->mode != MAX8997_EXTERNAL_MODE)
|
||||
max8997_haptic_set_internal_duty_cycle(chip);
|
||||
|
||||
if (!chip->enabled) {
|
||||
error = regulator_enable(chip->regulator);
|
||||
|
|
@ -168,16 +155,32 @@ static void max8997_haptic_enable(struct max8997_haptic *chip)
|
|||
return;
|
||||
}
|
||||
max8997_haptic_configure(chip);
|
||||
if (chip->mode == MAX8997_EXTERNAL_MODE) {
|
||||
error = pwm_enable(chip->pwm);
|
||||
if (error) {
|
||||
dev_err(chip->dev, "Failed to enable PWM\n");
|
||||
regulator_disable(chip->regulator);
|
||||
return;
|
||||
}
|
||||
}
|
||||
chip->enabled = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* It would be more straight forward to configure the external PWM
|
||||
* earlier i.e. when the internal duty_cycle is setup in internal mode.
|
||||
* But historically this is done only after the regulator was enabled
|
||||
* and max8997_haptic_configure() set the enable bit in
|
||||
* MAX8997_HAPTIC_REG_CONF2. So better keep it this way.
|
||||
*/
|
||||
if (chip->mode == MAX8997_EXTERNAL_MODE) {
|
||||
struct pwm_state state;
|
||||
|
||||
pwm_init_state(chip->pwm, &state);
|
||||
state.period = chip->pwm_period;
|
||||
state.duty_cycle = chip->pwm_period * chip->level / 100;
|
||||
state.enabled = true;
|
||||
|
||||
error = pwm_apply_might_sleep(chip->pwm, &state);
|
||||
if (error) {
|
||||
dev_err(chip->dev, "Failed to enable PWM\n");
|
||||
regulator_disable(chip->regulator);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
chip->enabled = true;
|
||||
}
|
||||
|
||||
static void max8997_haptic_disable(struct max8997_haptic *chip)
|
||||
|
|
@ -282,11 +285,6 @@ static int max8997_haptic_probe(struct platform_device *pdev)
|
|||
goto err_free_mem;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: pwm_apply_args() should be removed when switching to
|
||||
* the atomic PWM API.
|
||||
*/
|
||||
pwm_apply_args(chip->pwm);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -1,113 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/* NXP PCF50633 Input Driver
|
||||
*
|
||||
* (C) 2006-2008 by Openmoko, Inc.
|
||||
* Author: Balaji Rao <balajirrao@openmoko.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Broken down from monstrous PCF50633 driver mainly by
|
||||
* Harald Welte, Andy Green and Werner Almesberger
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <linux/mfd/pcf50633/core.h>
|
||||
|
||||
#define PCF50633_OOCSTAT_ONKEY 0x01
|
||||
#define PCF50633_REG_OOCSTAT 0x12
|
||||
#define PCF50633_REG_OOCMODE 0x10
|
||||
|
||||
struct pcf50633_input {
|
||||
struct pcf50633 *pcf;
|
||||
struct input_dev *input_dev;
|
||||
};
|
||||
|
||||
static void
|
||||
pcf50633_input_irq(int irq, void *data)
|
||||
{
|
||||
struct pcf50633_input *input;
|
||||
int onkey_released;
|
||||
|
||||
input = data;
|
||||
|
||||
/* We report only one event depending on the key press status */
|
||||
onkey_released = pcf50633_reg_read(input->pcf, PCF50633_REG_OOCSTAT)
|
||||
& PCF50633_OOCSTAT_ONKEY;
|
||||
|
||||
if (irq == PCF50633_IRQ_ONKEYF && !onkey_released)
|
||||
input_report_key(input->input_dev, KEY_POWER, 1);
|
||||
else if (irq == PCF50633_IRQ_ONKEYR && onkey_released)
|
||||
input_report_key(input->input_dev, KEY_POWER, 0);
|
||||
|
||||
input_sync(input->input_dev);
|
||||
}
|
||||
|
||||
static int pcf50633_input_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct pcf50633_input *input;
|
||||
struct input_dev *input_dev;
|
||||
int ret;
|
||||
|
||||
|
||||
input = kzalloc(sizeof(*input), GFP_KERNEL);
|
||||
if (!input)
|
||||
return -ENOMEM;
|
||||
|
||||
input_dev = input_allocate_device();
|
||||
if (!input_dev) {
|
||||
kfree(input);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, input);
|
||||
input->pcf = dev_to_pcf50633(pdev->dev.parent);
|
||||
input->input_dev = input_dev;
|
||||
|
||||
input_dev->name = "PCF50633 PMU events";
|
||||
input_dev->id.bustype = BUS_I2C;
|
||||
input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_PWR);
|
||||
set_bit(KEY_POWER, input_dev->keybit);
|
||||
|
||||
ret = input_register_device(input_dev);
|
||||
if (ret) {
|
||||
input_free_device(input_dev);
|
||||
kfree(input);
|
||||
return ret;
|
||||
}
|
||||
pcf50633_register_irq(input->pcf, PCF50633_IRQ_ONKEYR,
|
||||
pcf50633_input_irq, input);
|
||||
pcf50633_register_irq(input->pcf, PCF50633_IRQ_ONKEYF,
|
||||
pcf50633_input_irq, input);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pcf50633_input_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct pcf50633_input *input = platform_get_drvdata(pdev);
|
||||
|
||||
pcf50633_free_irq(input->pcf, PCF50633_IRQ_ONKEYR);
|
||||
pcf50633_free_irq(input->pcf, PCF50633_IRQ_ONKEYF);
|
||||
|
||||
input_unregister_device(input->input_dev);
|
||||
kfree(input);
|
||||
}
|
||||
|
||||
static struct platform_driver pcf50633_input_driver = {
|
||||
.driver = {
|
||||
.name = "pcf50633-input",
|
||||
},
|
||||
.probe = pcf50633_input_probe,
|
||||
.remove = pcf50633_input_remove,
|
||||
};
|
||||
module_platform_driver(pcf50633_input_driver);
|
||||
|
||||
MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>");
|
||||
MODULE_DESCRIPTION("PCF50633 input driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:pcf50633-input");
|
||||
|
|
@ -82,6 +82,21 @@ config RMI4_F12
|
|||
touchpads. For sensors that support relative pointing, F12 also
|
||||
provides mouse input.
|
||||
|
||||
config RMI4_F1A
|
||||
bool "RMI4 Function 1A (0D pointing)"
|
||||
help
|
||||
Say Y here if you want to add support for RMI4 function 1A.
|
||||
|
||||
Function 1A provides capacitive keys support for RMI4 devices.
|
||||
|
||||
config RMI4_F21
|
||||
bool "RMI4 Function 21 (PRESSURE)"
|
||||
help
|
||||
Say Y here if you want to add support for RMI4 function 21.
|
||||
|
||||
Function 21 provides buttons/pressure handling for RMI4 devices.
|
||||
This includes support for buttons/pressure on PressurePad.
|
||||
|
||||
config RMI4_F30
|
||||
bool "RMI4 Function 30 (GPIO LED)"
|
||||
help
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ rmi_core-$(CONFIG_RMI4_2D_SENSOR) += rmi_2d_sensor.o
|
|||
rmi_core-$(CONFIG_RMI4_F03) += rmi_f03.o
|
||||
rmi_core-$(CONFIG_RMI4_F11) += rmi_f11.o
|
||||
rmi_core-$(CONFIG_RMI4_F12) += rmi_f12.o
|
||||
rmi_core-$(CONFIG_RMI4_F1A) += rmi_f1a.o
|
||||
rmi_core-$(CONFIG_RMI4_F21) += rmi_f21.o
|
||||
rmi_core-$(CONFIG_RMI4_F30) += rmi_f30.o
|
||||
rmi_core-$(CONFIG_RMI4_F34) += rmi_f34.o rmi_f34v7.o
|
||||
rmi_core-$(CONFIG_RMI4_F3A) += rmi_f3a.o
|
||||
|
|
|
|||
|
|
@ -360,6 +360,12 @@ static struct rmi_function_handler *fn_handlers[] = {
|
|||
#ifdef CONFIG_RMI4_F12
|
||||
&rmi_f12_handler,
|
||||
#endif
|
||||
#ifdef CONFIG_RMI4_F1A
|
||||
&rmi_f1a_handler,
|
||||
#endif
|
||||
#ifdef CONFIG_RMI4_F21
|
||||
&rmi_f21_handler,
|
||||
#endif
|
||||
#ifdef CONFIG_RMI4_F30
|
||||
&rmi_f30_handler,
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -133,6 +133,8 @@ extern struct rmi_function_handler rmi_f01_handler;
|
|||
extern struct rmi_function_handler rmi_f03_handler;
|
||||
extern struct rmi_function_handler rmi_f11_handler;
|
||||
extern struct rmi_function_handler rmi_f12_handler;
|
||||
extern struct rmi_function_handler rmi_f1a_handler;
|
||||
extern struct rmi_function_handler rmi_f21_handler;
|
||||
extern struct rmi_function_handler rmi_f30_handler;
|
||||
extern struct rmi_function_handler rmi_f34_handler;
|
||||
extern struct rmi_function_handler rmi_f3a_handler;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,143 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2025 André Apitzsch <git@apitzsch.eu>
|
||||
*/
|
||||
|
||||
#include <linux/input.h>
|
||||
#include <linux/property.h>
|
||||
#include "rmi_driver.h"
|
||||
|
||||
struct f1a_data {
|
||||
struct input_dev *input;
|
||||
|
||||
u32 *keymap;
|
||||
unsigned int num_keys;
|
||||
};
|
||||
|
||||
static int rmi_f1a_parse_device_properties(struct rmi_function *fn, struct f1a_data *f1a)
|
||||
{
|
||||
static const char buttons_property[] = "linux,keycodes";
|
||||
struct device *dev = &fn->dev;
|
||||
u32 *buttonmap;
|
||||
int n_keys;
|
||||
int error;
|
||||
|
||||
if (!device_property_present(dev, buttons_property))
|
||||
return 0;
|
||||
|
||||
n_keys = device_property_count_u32(dev, buttons_property);
|
||||
if (n_keys <= 0) {
|
||||
error = n_keys < 0 ? n_keys : -EINVAL;
|
||||
dev_err(dev, "Invalid/malformed '%s' property: %d\n",
|
||||
buttons_property, error);
|
||||
return error;
|
||||
}
|
||||
|
||||
buttonmap = devm_kmalloc_array(dev, n_keys, sizeof(*buttonmap),
|
||||
GFP_KERNEL);
|
||||
if (!buttonmap)
|
||||
return -ENOMEM;
|
||||
|
||||
error = device_property_read_u32_array(dev, buttons_property,
|
||||
buttonmap, n_keys);
|
||||
if (error) {
|
||||
dev_err(dev, "Failed to parse '%s' property: %d\n",
|
||||
buttons_property, error);
|
||||
return error;
|
||||
}
|
||||
|
||||
f1a->keymap = buttonmap;
|
||||
f1a->num_keys = n_keys;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t rmi_f1a_attention(int irq, void *ctx)
|
||||
{
|
||||
struct rmi_function *fn = ctx;
|
||||
struct f1a_data *f1a = dev_get_drvdata(&fn->dev);
|
||||
char button_bitmask;
|
||||
int key;
|
||||
int error;
|
||||
|
||||
error = rmi_read_block(fn->rmi_dev, fn->fd.data_base_addr,
|
||||
&button_bitmask, sizeof(button_bitmask));
|
||||
if (error) {
|
||||
dev_err(&fn->dev, "Failed to read object data. Code: %d.\n",
|
||||
error);
|
||||
return IRQ_RETVAL(error);
|
||||
}
|
||||
|
||||
for (key = 0; key < f1a->num_keys; key++)
|
||||
input_report_key(f1a->input, f1a->keymap[key],
|
||||
button_bitmask & BIT(key));
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int rmi_f1a_config(struct rmi_function *fn)
|
||||
{
|
||||
struct f1a_data *f1a = dev_get_drvdata(&fn->dev);
|
||||
struct rmi_driver *drv = fn->rmi_dev->driver;
|
||||
|
||||
if (f1a->num_keys)
|
||||
drv->set_irq_bits(fn->rmi_dev, fn->irq_mask);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rmi_f1a_initialize(struct rmi_function *fn, struct f1a_data *f1a)
|
||||
{
|
||||
int error;
|
||||
int i;
|
||||
|
||||
error = rmi_f1a_parse_device_properties(fn, f1a);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
for (i = 0; i < f1a->num_keys; i++)
|
||||
input_set_capability(f1a->input, EV_KEY, f1a->keymap[i]);
|
||||
|
||||
f1a->input->keycode = f1a->keymap;
|
||||
f1a->input->keycodemax = f1a->num_keys;
|
||||
f1a->input->keycodesize = sizeof(f1a->keymap[0]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rmi_f1a_probe(struct rmi_function *fn)
|
||||
{
|
||||
struct rmi_device *rmi_dev = fn->rmi_dev;
|
||||
struct rmi_driver_data *drv_data = dev_get_drvdata(&rmi_dev->dev);
|
||||
struct f1a_data *f1a;
|
||||
int error;
|
||||
|
||||
if (!drv_data->input) {
|
||||
dev_info(&fn->dev, "F1A: no input device found, ignoring\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
f1a = devm_kzalloc(&fn->dev, sizeof(*f1a), GFP_KERNEL);
|
||||
if (!f1a)
|
||||
return -ENOMEM;
|
||||
|
||||
f1a->input = drv_data->input;
|
||||
|
||||
error = rmi_f1a_initialize(fn, f1a);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
dev_set_drvdata(&fn->dev, f1a);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct rmi_function_handler rmi_f1a_handler = {
|
||||
.driver = {
|
||||
.name = "rmi4_f1a",
|
||||
},
|
||||
.func = 0x1a,
|
||||
.probe = rmi_f1a_probe,
|
||||
.config = rmi_f1a_config,
|
||||
.attention = rmi_f1a_attention,
|
||||
};
|
||||
|
|
@ -0,0 +1,179 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2012-2025 Synaptics Incorporated
|
||||
*/
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/dev_printk.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/rmi.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/slab.h>
|
||||
#include "rmi_driver.h"
|
||||
|
||||
#define RMI_F21_SENSOR_COUNT_MASK GENMASK(3, 0)
|
||||
#define RMI_F21_FINGER_COUNT_PRESENT BIT(5)
|
||||
#define RMI_F21_NEW_REPORT_FORMAT BIT(6)
|
||||
|
||||
#define RMI_F21_FINGER_COUNT_MASK GENMASK(3, 0)
|
||||
|
||||
#define RMI_F21_MAX_SENSORS 16
|
||||
#define RMI_F21_MAX_FINGERS 16
|
||||
#define RMI_F21_DATA_REGS_MAX_SIZE (RMI_F21_MAX_SENSORS * 2 + \
|
||||
RMI_F21_MAX_FINGERS * 2 + 1)
|
||||
|
||||
#define RMI_F21_FORCE_CLICK_BIT BIT(0)
|
||||
|
||||
#define RMI_F21_FORCEPAD_BUTTON_COUNT 1
|
||||
|
||||
struct f21_data {
|
||||
struct input_dev *input;
|
||||
u16 key_code;
|
||||
|
||||
unsigned int attn_data_size;
|
||||
unsigned int attn_data_button_offset;
|
||||
|
||||
unsigned int data_reg_size;
|
||||
unsigned int data_reg_button_offset;
|
||||
u8 data_regs[RMI_F21_DATA_REGS_MAX_SIZE];
|
||||
};
|
||||
|
||||
static irqreturn_t rmi_f21_attention(int irq, void *ctx)
|
||||
{
|
||||
struct rmi_function *fn = ctx;
|
||||
struct f21_data *f21 = dev_get_drvdata(&fn->dev);
|
||||
struct rmi_driver_data *drvdata = dev_get_drvdata(&fn->rmi_dev->dev);
|
||||
u8 *pdata;
|
||||
int error;
|
||||
bool pressed;
|
||||
|
||||
if (drvdata->attn_data.data) {
|
||||
if (drvdata->attn_data.size < f21->attn_data_size) {
|
||||
dev_warn(&fn->dev, "f21 interrupt, but data is missing\n");
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
pdata = drvdata->attn_data.data + f21->attn_data_button_offset;
|
||||
|
||||
drvdata->attn_data.data += f21->attn_data_size;
|
||||
drvdata->attn_data.size -= f21->attn_data_size;
|
||||
} else {
|
||||
error = rmi_read_block(fn->rmi_dev, fn->fd.data_base_addr,
|
||||
f21->data_regs, f21->data_reg_size);
|
||||
if (error) {
|
||||
dev_err(&fn->dev, "failed to read f21 data registers: %d\n",
|
||||
error);
|
||||
return IRQ_RETVAL(error);
|
||||
}
|
||||
|
||||
pdata = f21->data_regs + f21->data_reg_button_offset;
|
||||
}
|
||||
|
||||
pressed = *pdata & RMI_F21_FORCE_CLICK_BIT;
|
||||
input_report_key(f21->input, f21->key_code, pressed);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int rmi_f21_config(struct rmi_function *fn)
|
||||
{
|
||||
struct rmi_driver *drv = fn->rmi_dev->driver;
|
||||
|
||||
drv->set_irq_bits(fn->rmi_dev, fn->irq_mask);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rmi_f21_initialize(struct rmi_function *fn, struct f21_data *f21)
|
||||
{
|
||||
struct input_dev *input = f21->input;
|
||||
|
||||
f21->key_code = BTN_LEFT;
|
||||
|
||||
input->keycode = &f21->key_code;
|
||||
input->keycodesize = sizeof(f21->key_code);
|
||||
input->keycodemax = RMI_F21_FORCEPAD_BUTTON_COUNT;
|
||||
|
||||
input_set_capability(input, EV_KEY, f21->key_code);
|
||||
__set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rmi_f21_probe(struct rmi_function *fn)
|
||||
{
|
||||
struct rmi_device *rmi_dev = fn->rmi_dev;
|
||||
struct rmi_driver_data *drv_data = dev_get_drvdata(&rmi_dev->dev);
|
||||
struct f21_data *f21;
|
||||
unsigned int sensor_count;
|
||||
unsigned int max_fingers;
|
||||
unsigned int query15_offset;
|
||||
u8 query15_data;
|
||||
int error;
|
||||
|
||||
if (!drv_data->input) {
|
||||
dev_info(&fn->dev, "f21: no input device found, ignoring\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
f21 = devm_kzalloc(&fn->dev, sizeof(*f21), GFP_KERNEL);
|
||||
if (!f21)
|
||||
return -ENOMEM;
|
||||
|
||||
f21->input = drv_data->input;
|
||||
|
||||
error = rmi_f21_initialize(fn, f21);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
dev_set_drvdata(&fn->dev, f21);
|
||||
|
||||
sensor_count = fn->fd.query_base_addr & RMI_F21_SENSOR_COUNT_MASK;
|
||||
if (fn->fd.query_base_addr & RMI_F21_FINGER_COUNT_PRESENT) {
|
||||
query15_offset = fn->fd.query_base_addr & RMI_F21_NEW_REPORT_FORMAT ? 2 : 1;
|
||||
error = rmi_read_block(fn->rmi_dev,
|
||||
fn->fd.query_base_addr + query15_offset,
|
||||
&query15_data, sizeof(query15_data));
|
||||
if (error)
|
||||
return dev_err_probe(&fn->dev, error,
|
||||
"failed to read 'query15' data");
|
||||
|
||||
max_fingers = query15_data & RMI_F21_FINGER_COUNT_MASK;
|
||||
} else {
|
||||
max_fingers = 5;
|
||||
}
|
||||
|
||||
if (fn->fd.query_base_addr & RMI_F21_NEW_REPORT_FORMAT) {
|
||||
/* Each finger uses one byte, and the button state uses one byte.*/
|
||||
f21->attn_data_size = max_fingers + 1;
|
||||
f21->attn_data_button_offset = f21->attn_data_size - 1;
|
||||
/*
|
||||
* Each sensor uses two bytes, the button state uses one byte,
|
||||
* and each finger uses two bytes.
|
||||
*/
|
||||
f21->data_reg_size = sensor_count * 2 + 1 + max_fingers * 2;
|
||||
f21->data_reg_button_offset = sensor_count * 2;
|
||||
} else {
|
||||
/*
|
||||
* Regardless of the transport each finger uses two bytes,
|
||||
* and the button state uses one byte.
|
||||
*/
|
||||
f21->attn_data_size = sensor_count * 2 + 1;
|
||||
f21->attn_data_button_offset = sensor_count * 2;
|
||||
|
||||
f21->data_reg_size = f21->attn_data_size;
|
||||
f21->data_reg_button_offset = f21->attn_data_button_offset;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct rmi_function_handler rmi_f21_handler = {
|
||||
.driver = {
|
||||
.name = "rmi4_f21",
|
||||
},
|
||||
.func = 0x21,
|
||||
.probe = rmi_f21_probe,
|
||||
.config = rmi_f21_config,
|
||||
.attention = rmi_f21_attention,
|
||||
};
|
||||
|
|
@ -0,0 +1,277 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Helper functions for overlay objects on touchscreens
|
||||
*
|
||||
* Copyright (c) 2023 Javier Carrasco <javier.carrasco@wolfvision.net>
|
||||
*/
|
||||
|
||||
#include <linux/input.h>
|
||||
#include <linux/input/mt.h>
|
||||
#include <linux/input/touch-overlay.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/property.h>
|
||||
|
||||
struct touch_overlay_segment {
|
||||
struct list_head list;
|
||||
u32 x_origin;
|
||||
u32 y_origin;
|
||||
u32 x_size;
|
||||
u32 y_size;
|
||||
u32 key;
|
||||
bool pressed;
|
||||
int slot;
|
||||
};
|
||||
|
||||
static int touch_overlay_get_segment(struct fwnode_handle *segment_node,
|
||||
struct touch_overlay_segment *segment,
|
||||
struct input_dev *input)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = fwnode_property_read_u32(segment_node, "x-origin",
|
||||
&segment->x_origin);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
error = fwnode_property_read_u32(segment_node, "y-origin",
|
||||
&segment->y_origin);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
error = fwnode_property_read_u32(segment_node, "x-size",
|
||||
&segment->x_size);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
error = fwnode_property_read_u32(segment_node, "y-size",
|
||||
&segment->y_size);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
error = fwnode_property_read_u32(segment_node, "linux,code",
|
||||
&segment->key);
|
||||
if (!error)
|
||||
input_set_capability(input, EV_KEY, segment->key);
|
||||
else if (error != -EINVAL)
|
||||
return error;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* touch_overlay_map - map overlay objects from the device tree and set
|
||||
* key capabilities if buttons are defined.
|
||||
* @list: pointer to the list that will hold the segments
|
||||
* @input: pointer to the already allocated input_dev
|
||||
*
|
||||
* Returns 0 on success and error number otherwise.
|
||||
*
|
||||
* If buttons are defined, key capabilities are set accordingly.
|
||||
*/
|
||||
int touch_overlay_map(struct list_head *list, struct input_dev *input)
|
||||
{
|
||||
struct fwnode_handle *fw_segment;
|
||||
struct device *dev = input->dev.parent;
|
||||
struct touch_overlay_segment *segment;
|
||||
int error;
|
||||
|
||||
struct fwnode_handle *overlay __free(fwnode_handle) =
|
||||
device_get_named_child_node(dev, "touch-overlay");
|
||||
if (!overlay)
|
||||
return 0;
|
||||
|
||||
fwnode_for_each_available_child_node(overlay, fw_segment) {
|
||||
segment = devm_kzalloc(dev, sizeof(*segment), GFP_KERNEL);
|
||||
if (!segment) {
|
||||
fwnode_handle_put(fw_segment);
|
||||
return -ENOMEM;
|
||||
}
|
||||
error = touch_overlay_get_segment(fw_segment, segment, input);
|
||||
if (error) {
|
||||
fwnode_handle_put(fw_segment);
|
||||
return error;
|
||||
}
|
||||
list_add_tail(&segment->list, list);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(touch_overlay_map);
|
||||
|
||||
/**
|
||||
* touch_overlay_get_touchscreen_abs - get abs size from the touchscreen area.
|
||||
* @list: pointer to the list that holds the segments
|
||||
* @x: horizontal abs
|
||||
* @y: vertical abs
|
||||
*/
|
||||
void touch_overlay_get_touchscreen_abs(struct list_head *list, u16 *x, u16 *y)
|
||||
{
|
||||
struct touch_overlay_segment *segment;
|
||||
struct list_head *ptr;
|
||||
|
||||
list_for_each(ptr, list) {
|
||||
segment = list_entry(ptr, struct touch_overlay_segment, list);
|
||||
if (!segment->key) {
|
||||
*x = segment->x_size - 1;
|
||||
*y = segment->y_size - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(touch_overlay_get_touchscreen_abs);
|
||||
|
||||
static bool touch_overlay_segment_event(struct touch_overlay_segment *seg,
|
||||
struct input_mt_pos *pos)
|
||||
{
|
||||
if (pos->x >= seg->x_origin && pos->x < (seg->x_origin + seg->x_size) &&
|
||||
pos->y >= seg->y_origin && pos->y < (seg->y_origin + seg->y_size))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* touch_overlay_mapped_touchscreen - check if a touchscreen area is mapped
|
||||
* @list: pointer to the list that holds the segments
|
||||
*
|
||||
* Returns true if a touchscreen area is mapped or false otherwise.
|
||||
*/
|
||||
bool touch_overlay_mapped_touchscreen(struct list_head *list)
|
||||
{
|
||||
struct touch_overlay_segment *segment;
|
||||
struct list_head *ptr;
|
||||
|
||||
list_for_each(ptr, list) {
|
||||
segment = list_entry(ptr, struct touch_overlay_segment, list);
|
||||
if (!segment->key)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
EXPORT_SYMBOL(touch_overlay_mapped_touchscreen);
|
||||
|
||||
static bool touch_overlay_event_on_ts(struct list_head *list,
|
||||
struct input_mt_pos *pos)
|
||||
{
|
||||
struct touch_overlay_segment *segment;
|
||||
struct list_head *ptr;
|
||||
|
||||
list_for_each(ptr, list) {
|
||||
segment = list_entry(ptr, struct touch_overlay_segment, list);
|
||||
if (segment->key)
|
||||
continue;
|
||||
|
||||
if (touch_overlay_segment_event(segment, pos)) {
|
||||
pos->x -= segment->x_origin;
|
||||
pos->y -= segment->y_origin;
|
||||
return true;
|
||||
}
|
||||
/* ignore touch events outside the defined area */
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool touch_overlay_button_event(struct input_dev *input,
|
||||
struct touch_overlay_segment *segment,
|
||||
struct input_mt_pos *pos, int slot)
|
||||
{
|
||||
struct input_mt *mt = input->mt;
|
||||
struct input_mt_slot *s = &mt->slots[slot];
|
||||
bool button_contact = touch_overlay_segment_event(segment, pos);
|
||||
|
||||
if (segment->slot == slot && segment->pressed) {
|
||||
/* sliding out of the button releases it */
|
||||
if (!button_contact) {
|
||||
input_report_key(input, segment->key, false);
|
||||
segment->pressed = false;
|
||||
/* keep available for a possible touch event */
|
||||
return false;
|
||||
}
|
||||
/* ignore sliding on the button while pressed */
|
||||
s->frame = mt->frame;
|
||||
return true;
|
||||
} else if (button_contact) {
|
||||
input_report_key(input, segment->key, true);
|
||||
s->frame = mt->frame;
|
||||
segment->slot = slot;
|
||||
segment->pressed = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* touch_overlay_sync_frame - update the status of the segments and report
|
||||
* buttons whose tracked slot is unused.
|
||||
* @list: pointer to the list that holds the segments
|
||||
* @input: pointer to the input device associated to the contact
|
||||
*/
|
||||
void touch_overlay_sync_frame(struct list_head *list, struct input_dev *input)
|
||||
{
|
||||
struct touch_overlay_segment *segment;
|
||||
struct input_mt *mt = input->mt;
|
||||
struct input_mt_slot *s;
|
||||
struct list_head *ptr;
|
||||
|
||||
list_for_each(ptr, list) {
|
||||
segment = list_entry(ptr, struct touch_overlay_segment, list);
|
||||
if (!segment->key)
|
||||
continue;
|
||||
|
||||
s = &mt->slots[segment->slot];
|
||||
if (!input_mt_is_used(mt, s) && segment->pressed) {
|
||||
input_report_key(input, segment->key, false);
|
||||
segment->pressed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(touch_overlay_sync_frame);
|
||||
|
||||
/**
|
||||
* touch_overlay_process_contact - process contacts according to the overlay
|
||||
* mapping. This function acts as a filter to release the calling driver
|
||||
* from the contacts that are either related to overlay buttons or out of the
|
||||
* overlay touchscreen area, if defined.
|
||||
* @list: pointer to the list that holds the segments
|
||||
* @input: pointer to the input device associated to the contact
|
||||
* @pos: pointer to the contact position
|
||||
* @slot: slot associated to the contact (0 if multitouch is not supported)
|
||||
*
|
||||
* Returns true if the contact was processed (reported for valid key events
|
||||
* and dropped for contacts outside the overlay touchscreen area) or false
|
||||
* if the contact must be processed by the caller. In that case this function
|
||||
* shifts the (x,y) coordinates to the overlay touchscreen axis if required.
|
||||
*/
|
||||
bool touch_overlay_process_contact(struct list_head *list,
|
||||
struct input_dev *input,
|
||||
struct input_mt_pos *pos, int slot)
|
||||
{
|
||||
struct touch_overlay_segment *segment;
|
||||
struct list_head *ptr;
|
||||
|
||||
/*
|
||||
* buttons must be prioritized over overlay touchscreens to account for
|
||||
* overlappings e.g. a button inside the touchscreen area.
|
||||
*/
|
||||
list_for_each(ptr, list) {
|
||||
segment = list_entry(ptr, struct touch_overlay_segment, list);
|
||||
if (segment->key &&
|
||||
touch_overlay_button_event(input, segment, pos, slot))
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* valid contacts on the overlay touchscreen are left for the client
|
||||
* to be processed/reported according to its (possibly) unique features.
|
||||
*/
|
||||
return !touch_overlay_event_on_ts(list, pos);
|
||||
}
|
||||
EXPORT_SYMBOL(touch_overlay_process_contact);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Helper functions for overlay objects on touch devices");
|
||||
|
|
@ -444,10 +444,11 @@ static int ad7879_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
|
|||
return !!(val & AD7879_GPIO_DATA);
|
||||
}
|
||||
|
||||
static void ad7879_gpio_set_value(struct gpio_chip *chip,
|
||||
unsigned gpio, int value)
|
||||
static int ad7879_gpio_set_value(struct gpio_chip *chip, unsigned int gpio,
|
||||
int value)
|
||||
{
|
||||
struct ad7879 *ts = gpiochip_get_data(chip);
|
||||
int ret;
|
||||
|
||||
mutex_lock(&ts->mutex);
|
||||
if (value)
|
||||
|
|
@ -455,8 +456,10 @@ static void ad7879_gpio_set_value(struct gpio_chip *chip,
|
|||
else
|
||||
ts->cmd_crtl2 &= ~AD7879_GPIO_DATA;
|
||||
|
||||
ad7879_write(ts, AD7879_REG_CTRL2, ts->cmd_crtl2);
|
||||
ret = ad7879_write(ts, AD7879_REG_CTRL2, ts->cmd_crtl2);
|
||||
mutex_unlock(&ts->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ad7879_gpio_add(struct ad7879 *ts)
|
||||
|
|
@ -472,7 +475,7 @@ static int ad7879_gpio_add(struct ad7879 *ts)
|
|||
ts->gc.direction_input = ad7879_gpio_direction_input;
|
||||
ts->gc.direction_output = ad7879_gpio_direction_output;
|
||||
ts->gc.get = ad7879_gpio_get_value;
|
||||
ts->gc.set = ad7879_gpio_set_value;
|
||||
ts->gc.set_rv = ad7879_gpio_set_value;
|
||||
ts->gc.can_sleep = 1;
|
||||
ts->gc.base = -1;
|
||||
ts->gc.ngpio = 1;
|
||||
|
|
|
|||
|
|
@ -120,7 +120,6 @@ struct edt_ft5x06_ts_data {
|
|||
struct regmap *regmap;
|
||||
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
struct dentry *debug_dir;
|
||||
u8 *raw_buffer;
|
||||
size_t raw_bufsize;
|
||||
#endif
|
||||
|
|
@ -815,23 +814,21 @@ static const struct file_operations debugfs_raw_data_fops = {
|
|||
.read = edt_ft5x06_debugfs_raw_data_read,
|
||||
};
|
||||
|
||||
static void edt_ft5x06_ts_prepare_debugfs(struct edt_ft5x06_ts_data *tsdata,
|
||||
const char *debugfs_name)
|
||||
static void edt_ft5x06_ts_prepare_debugfs(struct edt_ft5x06_ts_data *tsdata)
|
||||
{
|
||||
tsdata->debug_dir = debugfs_create_dir(debugfs_name, NULL);
|
||||
struct dentry *debug_dir = tsdata->client->debugfs;
|
||||
|
||||
debugfs_create_u16("num_x", S_IRUSR, tsdata->debug_dir, &tsdata->num_x);
|
||||
debugfs_create_u16("num_y", S_IRUSR, tsdata->debug_dir, &tsdata->num_y);
|
||||
debugfs_create_u16("num_x", S_IRUSR, debug_dir, &tsdata->num_x);
|
||||
debugfs_create_u16("num_y", S_IRUSR, debug_dir, &tsdata->num_y);
|
||||
|
||||
debugfs_create_file("mode", S_IRUSR | S_IWUSR,
|
||||
tsdata->debug_dir, tsdata, &debugfs_mode_fops);
|
||||
debug_dir, tsdata, &debugfs_mode_fops);
|
||||
debugfs_create_file("raw_data", S_IRUSR,
|
||||
tsdata->debug_dir, tsdata, &debugfs_raw_data_fops);
|
||||
debug_dir, tsdata, &debugfs_raw_data_fops);
|
||||
}
|
||||
|
||||
static void edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata)
|
||||
{
|
||||
debugfs_remove_recursive(tsdata->debug_dir);
|
||||
kfree(tsdata->raw_buffer);
|
||||
}
|
||||
|
||||
|
|
@ -842,8 +839,7 @@ static int edt_ft5x06_factory_mode(struct edt_ft5x06_ts_data *tsdata)
|
|||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static void edt_ft5x06_ts_prepare_debugfs(struct edt_ft5x06_ts_data *tsdata,
|
||||
const char *debugfs_name)
|
||||
static void edt_ft5x06_ts_prepare_debugfs(struct edt_ft5x06_ts_data *tsdata)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -1349,7 +1345,7 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client)
|
|||
if (error)
|
||||
return error;
|
||||
|
||||
edt_ft5x06_ts_prepare_debugfs(tsdata, dev_driver_string(&client->dev));
|
||||
edt_ft5x06_ts_prepare_debugfs(tsdata);
|
||||
|
||||
dev_dbg(&client->dev,
|
||||
"EDT FT5x06 initialized: IRQ %d, WAKE pin %d, Reset pin %d.\n",
|
||||
|
|
@ -1495,6 +1491,10 @@ static const struct edt_i2c_chip_data edt_ft8201_data = {
|
|||
.max_support_points = 10,
|
||||
};
|
||||
|
||||
static const struct edt_i2c_chip_data edt_ft8716_data = {
|
||||
.max_support_points = 10,
|
||||
};
|
||||
|
||||
static const struct edt_i2c_chip_data edt_ft8719_data = {
|
||||
.max_support_points = 10,
|
||||
};
|
||||
|
|
@ -1507,6 +1507,7 @@ static const struct i2c_device_id edt_ft5x06_ts_id[] = {
|
|||
/* Note no edt- prefix for compatibility with the ft6236.c driver */
|
||||
{ .name = "ft6236", .driver_data = (long)&edt_ft6236_data },
|
||||
{ .name = "ft8201", .driver_data = (long)&edt_ft8201_data },
|
||||
{ .name = "ft8716", .driver_data = (long)&edt_ft8716_data },
|
||||
{ .name = "ft8719", .driver_data = (long)&edt_ft8719_data },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
|
@ -1523,6 +1524,7 @@ static const struct of_device_id edt_ft5x06_of_match[] = {
|
|||
/* Note focaltech vendor prefix for compatibility with ft6236.c */
|
||||
{ .compatible = "focaltech,ft6236", .data = &edt_ft6236_data },
|
||||
{ .compatible = "focaltech,ft8201", .data = &edt_ft8201_data },
|
||||
{ .compatible = "focaltech,ft8716", .data = &edt_ft8716_data },
|
||||
{ .compatible = "focaltech,ft8719", .data = &edt_ft8719_data },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -44,9 +44,11 @@
|
|||
#define GOODIX_HAVE_KEY BIT(4)
|
||||
#define GOODIX_BUFFER_STATUS_TIMEOUT 20
|
||||
|
||||
#define RESOLUTION_LOC 1
|
||||
#define MAX_CONTACTS_LOC 5
|
||||
#define TRIGGER_LOC 6
|
||||
#define RESOLUTION_LOC 1
|
||||
#define MAX_CONTACTS_LOC 5
|
||||
#define TRIGGER_LOC 6
|
||||
|
||||
#define GOODIX_POLL_INTERVAL_MS 17 /* 17ms = 60fps */
|
||||
|
||||
/* Our special handling for GPIO accesses through ACPI is x86 specific */
|
||||
#if defined CONFIG_X86 && defined CONFIG_ACPI
|
||||
|
|
@ -497,6 +499,14 @@ static void goodix_process_events(struct goodix_ts_data *ts)
|
|||
input_sync(ts->input_dev);
|
||||
}
|
||||
|
||||
static void goodix_ts_work_i2c_poll(struct input_dev *input)
|
||||
{
|
||||
struct goodix_ts_data *ts = input_get_drvdata(input);
|
||||
|
||||
goodix_process_events(ts);
|
||||
goodix_i2c_write_u8(ts->client, GOODIX_READ_COOR_ADDR, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* goodix_ts_irq_handler - The IRQ handler
|
||||
*
|
||||
|
|
@ -513,13 +523,29 @@ static irqreturn_t goodix_ts_irq_handler(int irq, void *dev_id)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void goodix_enable_irq(struct goodix_ts_data *ts)
|
||||
{
|
||||
if (ts->client->irq)
|
||||
enable_irq(ts->client->irq);
|
||||
}
|
||||
|
||||
static void goodix_disable_irq(struct goodix_ts_data *ts)
|
||||
{
|
||||
if (ts->client->irq)
|
||||
disable_irq(ts->client->irq);
|
||||
}
|
||||
|
||||
static void goodix_free_irq(struct goodix_ts_data *ts)
|
||||
{
|
||||
devm_free_irq(&ts->client->dev, ts->client->irq, ts);
|
||||
if (ts->client->irq)
|
||||
devm_free_irq(&ts->client->dev, ts->client->irq, ts);
|
||||
}
|
||||
|
||||
static int goodix_request_irq(struct goodix_ts_data *ts)
|
||||
{
|
||||
if (!ts->client->irq)
|
||||
return 0;
|
||||
|
||||
return devm_request_threaded_irq(&ts->client->dev, ts->client->irq,
|
||||
NULL, goodix_ts_irq_handler,
|
||||
ts->irq_flags, ts->client->name, ts);
|
||||
|
|
@ -1219,6 +1245,18 @@ static int goodix_configure_dev(struct goodix_ts_data *ts)
|
|||
return error;
|
||||
}
|
||||
|
||||
input_set_drvdata(ts->input_dev, ts);
|
||||
|
||||
if (!ts->client->irq) {
|
||||
error = input_setup_polling(ts->input_dev, goodix_ts_work_i2c_poll);
|
||||
if (error) {
|
||||
dev_err(&ts->client->dev,
|
||||
"could not set up polling mode, %d\n", error);
|
||||
return error;
|
||||
}
|
||||
input_set_poll_interval(ts->input_dev, GOODIX_POLL_INTERVAL_MS);
|
||||
}
|
||||
|
||||
error = input_register_device(ts->input_dev);
|
||||
if (error) {
|
||||
dev_err(&ts->client->dev,
|
||||
|
|
@ -1422,7 +1460,7 @@ static int goodix_suspend(struct device *dev)
|
|||
|
||||
/* We need gpio pins to suspend/resume */
|
||||
if (ts->irq_pin_access_method == IRQ_PIN_ACCESS_NONE) {
|
||||
disable_irq(client->irq);
|
||||
goodix_disable_irq(ts);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1466,7 +1504,7 @@ static int goodix_resume(struct device *dev)
|
|||
int error;
|
||||
|
||||
if (ts->irq_pin_access_method == IRQ_PIN_ACCESS_NONE) {
|
||||
enable_irq(client->irq);
|
||||
goodix_enable_irq(ts);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
#include <linux/pm_qos.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/input/touch-overlay.h>
|
||||
|
||||
#define ST1232_TS_NAME "st1232-ts"
|
||||
#define ST1633_TS_NAME "st1633-ts"
|
||||
|
|
@ -57,6 +58,7 @@ struct st1232_ts_data {
|
|||
struct dev_pm_qos_request low_latency_req;
|
||||
struct gpio_desc *reset_gpio;
|
||||
const struct st_chip_info *chip_info;
|
||||
struct list_head touch_overlay_list;
|
||||
int read_buf_len;
|
||||
u8 *read_buf;
|
||||
};
|
||||
|
|
@ -156,6 +158,10 @@ static int st1232_ts_parse_and_report(struct st1232_ts_data *ts)
|
|||
|
||||
input_mt_assign_slots(input, slots, pos, n_contacts, 0);
|
||||
for (i = 0; i < n_contacts; i++) {
|
||||
if (touch_overlay_process_contact(&ts->touch_overlay_list,
|
||||
input, &pos[i], slots[i]))
|
||||
continue;
|
||||
|
||||
input_mt_slot(input, slots[i]);
|
||||
input_mt_report_slot_state(input, MT_TOOL_FINGER, true);
|
||||
input_report_abs(input, ABS_MT_POSITION_X, pos[i].x);
|
||||
|
|
@ -164,6 +170,7 @@ static int st1232_ts_parse_and_report(struct st1232_ts_data *ts)
|
|||
input_report_abs(input, ABS_MT_TOUCH_MAJOR, z[i]);
|
||||
}
|
||||
|
||||
touch_overlay_sync_frame(&ts->touch_overlay_list, input);
|
||||
input_mt_sync_frame(input);
|
||||
input_sync(input);
|
||||
|
||||
|
|
@ -292,18 +299,30 @@ static int st1232_ts_probe(struct i2c_client *client)
|
|||
if (error)
|
||||
return error;
|
||||
|
||||
/* Read resolution from the chip */
|
||||
error = st1232_ts_read_resolution(ts, &max_x, &max_y);
|
||||
if (error) {
|
||||
dev_err(&client->dev,
|
||||
"Failed to read resolution: %d\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
if (ts->chip_info->have_z)
|
||||
input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0,
|
||||
ts->chip_info->max_area, 0, 0);
|
||||
|
||||
/* map overlay objects if defined in the device tree */
|
||||
INIT_LIST_HEAD(&ts->touch_overlay_list);
|
||||
error = touch_overlay_map(&ts->touch_overlay_list, input_dev);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (touch_overlay_mapped_touchscreen(&ts->touch_overlay_list)) {
|
||||
/* Read resolution from the overlay touchscreen if defined */
|
||||
touch_overlay_get_touchscreen_abs(&ts->touch_overlay_list,
|
||||
&max_x, &max_y);
|
||||
} else {
|
||||
/* Read resolution from the chip */
|
||||
error = st1232_ts_read_resolution(ts, &max_x, &max_y);
|
||||
if (error) {
|
||||
dev_err(&client->dev,
|
||||
"Failed to read resolution: %d\n", error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
input_set_abs_params(input_dev, ABS_MT_POSITION_X,
|
||||
0, max_x, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2023 Javier Carrasco <javier.carrasco@wolfvision.net>
|
||||
*/
|
||||
|
||||
#ifndef _TOUCH_OVERLAY
|
||||
#define _TOUCH_OVERLAY
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
struct input_dev;
|
||||
|
||||
int touch_overlay_map(struct list_head *list, struct input_dev *input);
|
||||
|
||||
void touch_overlay_get_touchscreen_abs(struct list_head *list, u16 *x, u16 *y);
|
||||
|
||||
bool touch_overlay_mapped_touchscreen(struct list_head *list);
|
||||
|
||||
bool touch_overlay_process_contact(struct list_head *list,
|
||||
struct input_dev *input,
|
||||
struct input_mt_pos *pos, int slot);
|
||||
|
||||
void touch_overlay_sync_frame(struct list_head *list, struct input_dev *input);
|
||||
|
||||
#endif
|
||||
|
|
@ -601,6 +601,11 @@
|
|||
#define BTN_DPAD_LEFT 0x222
|
||||
#define BTN_DPAD_RIGHT 0x223
|
||||
|
||||
#define BTN_GRIPL 0x224
|
||||
#define BTN_GRIPR 0x225
|
||||
#define BTN_GRIPL2 0x226
|
||||
#define BTN_GRIPR2 0x227
|
||||
|
||||
#define KEY_ALS_TOGGLE 0x230 /* Ambient light sensor */
|
||||
#define KEY_ROTATE_LOCK_TOGGLE 0x231 /* Display rotation lock */
|
||||
#define KEY_REFRESH_RATE_TOGGLE 0x232 /* Display refresh rate toggle */
|
||||
|
|
@ -765,6 +770,9 @@
|
|||
#define KEY_KBD_LCD_MENU4 0x2bb
|
||||
#define KEY_KBD_LCD_MENU5 0x2bc
|
||||
|
||||
/* Performance Boost key (Alienware)/G-Mode key (Dell) */
|
||||
#define KEY_PERFORMANCE 0x2bd
|
||||
|
||||
#define BTN_TRIGGER_HAPPY 0x2c0
|
||||
#define BTN_TRIGGER_HAPPY1 0x2c0
|
||||
#define BTN_TRIGGER_HAPPY2 0x2c1
|
||||
|
|
|
|||
Loading…
Reference in New Issue