Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull input updates from Dmitry Torokhov: - support for inhibiting input devices at request from userspace. If a device implements open/close methods, it can also put device into low power state. This is needed, for example, to disable keyboard and touchpad on convertibles when they are transitioned into tablet mode - now that ordinary input devices can be configured for polling mode, dedicated input polling device implementation has been removed - GTCO tablet driver has been removed, as it used problematic custom HID parser, devices are EOL, and there is no interest from the manufacturer - a new driver for Dialog DA7280 haptic chips has been introduced - a new driver for power button on Dell Wyse 3020 - support for eKTF2132 in ektf2127 driver - support for SC2721 and SC2730 in sc27xx-vibra driver - enhancements for Atmel touchscreens, AD7846 touchscreens, Elan touchpads, ADP5589, ST1232 touchscreen, TM2 touchkey drivers - fixes and cleanups to allow clean builds with W=1 * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (86 commits) Input: da7280 - fix spelling mistake "sequemce" -> "sequence" Input: cyapa_gen6 - fix out-of-bounds stack access Input: sc27xx - add support for sc2730 and sc2721 dt-bindings: input: Add compatible string for SC2721 and SC2730 dt-bindings: input: Convert sc27xx-vibra.txt to json-schema Input: stmpe - add axis inversion and swapping capability Input: adp5589-keys - do not explicitly control IRQ for wakeup Input: adp5589-keys - do not unconditionally configure as wakeup source Input: ipx4xx-beeper - convert comma to semicolon Input: parkbd - convert comma to semicolon Input: new da7280 haptic driver dt-bindings: input: Add document bindings for DA7280 MAINTAINERS: da7280 updates to the Dialog Semiconductor search terms Input: elantech - fix protocol errors for some trackpoints in SMBus mode Input: elan_i2c - add new trackpoint report type 0x5F Input: elants - document some registers and values Input: atmel_mxt_ts - simplify the return expression of mxt_send_bootloader_cmd() Input: imx_keypad - add COMPILE_TEST support Input: applespi - use new structure for SPI transfer delays Input: synaptics-rmi4 - use new structure for SPI transfer delays ...
This commit is contained in:
Коммит
ee249d30fa
|
@ -0,0 +1,57 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/input/ariel-pwrbutton.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Dell Wyse 3020 a.k.a. "Ariel" Power Button
|
||||
|
||||
maintainers:
|
||||
- Lubomir Rintel <lkundrak@v3.sk>
|
||||
|
||||
description: |
|
||||
The ENE Embedded Controller on the Ariel board has an interface to the
|
||||
SPI bus that is capable of sending keyboard and mouse data. A single
|
||||
power button is attached to it. This binding describes this
|
||||
configuration.
|
||||
|
||||
allOf:
|
||||
- $ref: input.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- const: dell,wyse-ariel-ec-input
|
||||
- const: ene,kb3930-input
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
spi-max-frequency: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
power-button@0 {
|
||||
compatible = "dell,wyse-ariel-ec-input", "ene,kb3930-input";
|
||||
reg = <0>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <60 IRQ_TYPE_EDGE_RISING>;
|
||||
spi-max-frequency = <33000000>;
|
||||
};
|
||||
};
|
|
@ -1,41 +0,0 @@
|
|||
Atmel maXTouch touchscreen/touchpad
|
||||
|
||||
Required properties:
|
||||
- compatible:
|
||||
atmel,maxtouch
|
||||
|
||||
The following compatibles have been used in various products but are
|
||||
deprecated:
|
||||
atmel,qt602240_ts
|
||||
atmel,atmel_mxt_ts
|
||||
atmel,atmel_mxt_tp
|
||||
atmel,mXT224
|
||||
|
||||
- reg: The I2C address of the device
|
||||
|
||||
- interrupts: The sink for the touchpad's IRQ output
|
||||
See ../interrupt-controller/interrupts.txt
|
||||
|
||||
Optional properties for main touchpad device:
|
||||
|
||||
- linux,gpio-keymap: When enabled, the SPT_GPIOPWN_T19 object sends messages
|
||||
on GPIO bit changes. An array of up to 8 entries can be provided
|
||||
indicating the Linux keycode mapped to each bit of the status byte,
|
||||
starting at the LSB. Linux keycodes are defined in
|
||||
<dt-bindings/input/input.h>.
|
||||
|
||||
Note: the numbering of the GPIOs and the bit they start at varies between
|
||||
maXTouch devices. You must either refer to the documentation, or
|
||||
experiment to determine which bit corresponds to which input. Use
|
||||
KEY_RESERVED for unused padding values.
|
||||
|
||||
- reset-gpios: GPIO specifier for the touchscreen's reset pin (active low)
|
||||
|
||||
Example:
|
||||
|
||||
touch@4b {
|
||||
compatible = "atmel,maxtouch";
|
||||
reg = <0x4b>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <TEGRA_GPIO(W, 3) IRQ_TYPE_LEVEL_LOW>;
|
||||
};
|
|
@ -0,0 +1,81 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/input/atmel,maxtouch.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Atmel maXTouch touchscreen/touchpad
|
||||
|
||||
maintainers:
|
||||
- Nick Dyer <nick@shmanahar.org>
|
||||
- Linus Walleij <linus.walleij@linaro.org>
|
||||
|
||||
description: |
|
||||
Atmel maXTouch touchscreen or touchpads such as the mXT244
|
||||
and similar devices.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: atmel,maxtouch
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
vdda-supply:
|
||||
description:
|
||||
Optional regulator for the AVDD analog voltage.
|
||||
|
||||
vdd-supply:
|
||||
description:
|
||||
Optional regulator for the VDD digital voltage.
|
||||
|
||||
reset-gpios:
|
||||
maxItems: 1
|
||||
description:
|
||||
Optional GPIO specifier for the touchscreen's reset pin
|
||||
(active low). The line must be flagged with
|
||||
GPIO_ACTIVE_LOW.
|
||||
|
||||
linux,gpio-keymap:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
description: |
|
||||
When enabled, the SPT_GPIOPWN_T19 object sends messages
|
||||
on GPIO bit changes. An array of up to 8 entries can be provided
|
||||
indicating the Linux keycode mapped to each bit of the status byte,
|
||||
starting at the LSB. Linux keycodes are defined in
|
||||
<dt-bindings/input/input.h>.
|
||||
|
||||
Note: the numbering of the GPIOs and the bit they start at varies
|
||||
between maXTouch devices. You must either refer to the documentation,
|
||||
or experiment to determine which bit corresponds to which input. Use
|
||||
KEY_RESERVED for unused padding values.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
touchscreen@4a {
|
||||
compatible = "atmel,maxtouch";
|
||||
reg = <0x4a>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <26 IRQ_TYPE_EDGE_FALLING>;
|
||||
reset-gpios = <&gpio 27 GPIO_ACTIVE_LOW>;
|
||||
vdda-supply = <&ab8500_ldo_aux2_reg>;
|
||||
vdd-supply = <&ab8500_ldo_aux5_reg>;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
|
@ -1,33 +0,0 @@
|
|||
Samsung tm2-touchkey
|
||||
|
||||
Required properties:
|
||||
- compatible:
|
||||
* "cypress,tm2-touchkey" - for the touchkey found on the tm2 board
|
||||
* "cypress,midas-touchkey" - for the touchkey found on midas boards
|
||||
* "cypress,aries-touchkey" - for the touchkey found on aries boards
|
||||
* "coreriver,tc360-touchkey" - for the Coreriver TouchCore 360 touchkey
|
||||
- reg: I2C address of the chip.
|
||||
- interrupts: interrupt to which the chip is connected (see interrupt
|
||||
binding[0]).
|
||||
- vcc-supply : internal regulator output. 1.8V
|
||||
- vdd-supply : power supply for IC 3.3V
|
||||
|
||||
Optional properties:
|
||||
- linux,keycodes: array of keycodes (max 4), default KEY_PHONE and KEY_BACK
|
||||
|
||||
[0]: Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
|
||||
|
||||
Example:
|
||||
&i2c0 {
|
||||
/* ... */
|
||||
|
||||
touchkey@20 {
|
||||
compatible = "cypress,tm2-touchkey";
|
||||
reg = <0x20>;
|
||||
interrupt-parent = <&gpa3>;
|
||||
interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
|
||||
vcc-supply=<&ldo32_reg>;
|
||||
vdd-supply=<&ldo33_reg>;
|
||||
linux,keycodes = <KEY_PHONE KEY_BACK>;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,73 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/input/cypress,tm2-touchkey.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Samsung TM2 touch key controller
|
||||
|
||||
maintainers:
|
||||
- Stephan Gerhold <stephan@gerhold.net>
|
||||
|
||||
description: |
|
||||
Touch key controllers similar to the TM2 can be found in a wide range of
|
||||
Samsung devices. They are implemented using many different MCUs, but use
|
||||
a similar I2C protocol.
|
||||
|
||||
allOf:
|
||||
- $ref: input.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- cypress,tm2-touchkey
|
||||
- cypress,midas-touchkey
|
||||
- cypress,aries-touchkey
|
||||
- coreriver,tc360-touchkey
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
vdd-supply:
|
||||
description: Optional regulator for LED voltage, 3.3V.
|
||||
|
||||
vcc-supply:
|
||||
description: Optional regulator for MCU, 1.8V-3.3V (depending on MCU).
|
||||
|
||||
vddio-supply:
|
||||
description: |
|
||||
Optional regulator that provides digital I/O voltage,
|
||||
e.g. for pulling up the interrupt line or the I2C pins.
|
||||
|
||||
linux,keycodes:
|
||||
minItems: 1
|
||||
maxItems: 4
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/input/input.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
touchkey@20 {
|
||||
compatible = "cypress,tm2-touchkey";
|
||||
reg = <0x20>;
|
||||
interrupt-parent = <&gpa3>;
|
||||
interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
|
||||
vcc-supply = <&ldo32_reg>;
|
||||
vdd-supply = <&ldo33_reg>;
|
||||
linux,keycodes = <KEY_MENU KEY_BACK>;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,108 @@
|
|||
Dialog Semiconductor DA7280 Haptics bindings
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "dlg,da7280".
|
||||
- reg: Specifies the I2C slave address.
|
||||
|
||||
- interrupt-parent : Specifies the phandle of the interrupt controller to
|
||||
which the IRQs from DA7280 are delivered to.
|
||||
|
||||
- dlg,actuator-type: Set Actuator type. it should be one of:
|
||||
"LRA" - Linear Resonance Actuator type.
|
||||
"ERM-bar" - Bar type Eccentric Rotating Mass.
|
||||
"ERM-coin" - Coin type Eccentric Rotating Mass.
|
||||
|
||||
- dlg,const-op-mode: Haptic operation mode for FF_CONSTANT.
|
||||
Possible values:
|
||||
1 - Direct register override(DRO) mode triggered by i2c(default),
|
||||
2 - PWM data source mode controlled by PWM duty,
|
||||
- dlg,periodic-op-mode: Haptic operation mode for FF_PERIODIC.
|
||||
Possible values:
|
||||
1 - Register triggered waveform memory(RTWM) mode, the pattern
|
||||
assigned to the PS_SEQ_ID played as much times as PS_SEQ_LOOP,
|
||||
2 - Edge triggered waveform memory(ETWM) mode, external GPI(N)
|
||||
control are required to enable/disable and it needs to keep
|
||||
device enabled by sending magnitude (X > 0),
|
||||
the pattern is assigned to the GPI(N)_SEQUENCE_ID below.
|
||||
The default value is 1 for both of the operation modes.
|
||||
For more details, please see the datasheet.
|
||||
|
||||
- dlg,nom-microvolt: Nominal actuator voltage rating.
|
||||
Valid values: 0 - 6000000.
|
||||
- dlg,abs-max-microvolt: Absolute actuator maximum voltage rating.
|
||||
Valid values: 0 - 6000000.
|
||||
- dlg,imax-microamp: Actuator max current rating.
|
||||
Valid values: 0 - 252000.
|
||||
Default: 130000.
|
||||
- dlg,impd-micro-ohms: the impedance of the actuator in micro ohms.
|
||||
Valid values: 0 - 1500000000.
|
||||
|
||||
Optional properties:
|
||||
- pwms : phandle to the physical PWM(Pulse Width Modulation) device.
|
||||
PWM properties should be named "pwms". And number of cell is different
|
||||
for each pwm device.
|
||||
(See Documentation/devicetree/bindings/pwm/pwm.txt
|
||||
for further information relating to pwm properties)
|
||||
|
||||
- dlg,ps-seq-id: the PS_SEQ_ID(pattern ID in waveform memory inside chip)
|
||||
to play back when RTWM-MODE is enabled.
|
||||
Valid range: 0 - 15.
|
||||
- dlg,ps-seq-loop: the PS_SEQ_LOOP, Number of times the pre-stored sequence
|
||||
pointed to by PS_SEQ_ID or GPI(N)_SEQUENCE_ID is repeated.
|
||||
Valid range: 0 - 15.
|
||||
- dlg,gpiN-seq-id: the GPI(N)_SEQUENCE_ID, pattern to play
|
||||
when gpi0 is triggered, 'N' must be 0 - 2.
|
||||
Valid range: 0 - 15.
|
||||
- dlg,gpiN-mode: the pattern mode which can select either
|
||||
"Single-pattern" or "Multi-pattern", 'N' must be 0 - 2.
|
||||
- dlg,gpiN-polarity: gpiN polarity which can be chosen among
|
||||
"Rising-edge", "Falling-edge" and "Both-edge",
|
||||
'N' must be 0 - 2
|
||||
Haptic will work by this edge option in case of ETWM mode.
|
||||
|
||||
- dlg,resonant-freq-hz: use in case of LRA.
|
||||
the frequency range: 50 - 300.
|
||||
Default: 205.
|
||||
|
||||
- dlg,bemf-sens-enable: Enable for internal loop computations.
|
||||
- dlg,freq-track-enable: Enable for resonant frequency tracking.
|
||||
- dlg,acc-enable: Enable for active acceleration.
|
||||
- dlg,rapid-stop-enable: Enable for rapid stop.
|
||||
- dlg,amp-pid-enable: Enable for the amplitude PID.
|
||||
- dlg,mem-array: Customized waveform memory(patterns) data downloaded to
|
||||
the device during initialization. This is an array of 100 values(u8).
|
||||
|
||||
For further information, see device datasheet.
|
||||
|
||||
======
|
||||
|
||||
Example:
|
||||
|
||||
haptics: da7280-haptics@4a {
|
||||
compatible = "dlg,da7280";
|
||||
reg = <0x4a>;
|
||||
interrupt-parent = <&gpio6>;
|
||||
interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
|
||||
dlg,actuator-type = "LRA";
|
||||
dlg,dlg,const-op-mode = <1>;
|
||||
dlg,dlg,periodic-op-mode = <1>;
|
||||
dlg,nom-microvolt = <2000000>;
|
||||
dlg,abs-max-microvolt = <2000000>;
|
||||
dlg,imax-microamp = <170000>;
|
||||
dlg,resonant-freq-hz = <180>;
|
||||
dlg,impd-micro-ohms = <10500000>;
|
||||
dlg,freq-track-enable;
|
||||
dlg,rapid-stop-enable;
|
||||
dlg,mem-array = <
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
>;
|
||||
};
|
|
@ -1,23 +0,0 @@
|
|||
Spreadtrum SC27xx PMIC Vibrator
|
||||
|
||||
Required properties:
|
||||
- compatible: should be "sprd,sc2731-vibrator".
|
||||
- reg: address of vibrator control register.
|
||||
|
||||
Example :
|
||||
|
||||
sc2731_pmic: pmic@0 {
|
||||
compatible = "sprd,sc2731";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <26000000>;
|
||||
interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
vibrator@eb4 {
|
||||
compatible = "sprd,sc2731-vibrator";
|
||||
reg = <0xeb4>;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,48 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
# Copyright 2020 Unisoc Inc.
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/input/sprd,sc27xx-vibrator.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Spreadtrum SC27xx PMIC Vibrator Device Tree Bindings
|
||||
|
||||
maintainers:
|
||||
- Orson Zhai <orsonzhai@gmail.com>
|
||||
- Baolin Wang <baolin.wang7@gmail.com>
|
||||
- Chunyan Zhang <zhang.lyra@gmail.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- sprd,sc2721-vibrator
|
||||
- sprd,sc2730-vibrator
|
||||
- sprd,sc2731-vibrator
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
sc2731_pmic: pmic@0 {
|
||||
compatible = "sprd,sc2731";
|
||||
reg = <0 0>;
|
||||
spi-max-frequency = <26000000>;
|
||||
interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
vibrator@eb4 {
|
||||
compatible = "sprd,sc2731-vibrator";
|
||||
reg = <0xeb4>;
|
||||
};
|
||||
};
|
|
@ -1,7 +1,7 @@
|
|||
* Elan eKTF2127 I2C touchscreen controller
|
||||
|
||||
Required properties:
|
||||
- compatible : "elan,ektf2127"
|
||||
- compatible : "elan,ektf2127" or "elan,ektf2132"
|
||||
- reg : I2C slave address of the chip (0x40)
|
||||
- interrupts : interrupt specification for the ektf2127 interrupt
|
||||
- power-gpios : GPIO specification for the pin connected to the
|
||||
|
|
|
@ -25,15 +25,6 @@ Multitouch Library
|
|||
.. kernel-doc:: drivers/input/input-mt.c
|
||||
:export:
|
||||
|
||||
Polled input devices
|
||||
--------------------
|
||||
|
||||
.. kernel-doc:: include/linux/input-polldev.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/input/input-polldev.c
|
||||
:export:
|
||||
|
||||
Matrix keyboards/keypads
|
||||
------------------------
|
||||
|
||||
|
|
|
@ -164,6 +164,52 @@ disconnects. Calls to both callbacks are serialized.
|
|||
The open() callback should return a 0 in case of success or any nonzero value
|
||||
in case of failure. The close() callback (which is void) must always succeed.
|
||||
|
||||
Inhibiting input devices
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Inhibiting a device means ignoring input events from it. As such it is about
|
||||
maintaining relationships with input handlers - either already existing
|
||||
relationships, or relationships to be established while the device is in
|
||||
inhibited state.
|
||||
|
||||
If a device is inhibited, no input handler will receive events from it.
|
||||
|
||||
The fact that nobody wants events from the device is exploited further, by
|
||||
calling device's close() (if there are users) and open() (if there are users) on
|
||||
inhibit and uninhibit operations, respectively. Indeed, the meaning of close()
|
||||
is to stop providing events to the input core and that of open() is to start
|
||||
providing events to the input core.
|
||||
|
||||
Calling the device's close() method on inhibit (if there are users) allows the
|
||||
driver to save power. Either by directly powering down the device or by
|
||||
releasing the runtime-pm reference it got in open() when the driver is using
|
||||
runtime-pm.
|
||||
|
||||
Inhibiting and uninhibiting are orthogonal to opening and closing the device by
|
||||
input handlers. Userspace might want to inhibit a device in anticipation before
|
||||
any handler is positively matched against it.
|
||||
|
||||
Inhibiting and uninhibiting are orthogonal to device's being a wakeup source,
|
||||
too. Being a wakeup source plays a role when the system is sleeping, not when
|
||||
the system is operating. How drivers should program their interaction between
|
||||
inhibiting, sleeping and being a wakeup source is driver-specific.
|
||||
|
||||
Taking the analogy with the network devices - bringing a network interface down
|
||||
doesn't mean that it should be impossible be wake the system up on LAN through
|
||||
this interface. So, there may be input drivers which should be considered wakeup
|
||||
sources even when inhibited. Actually, in many I2C input devices their interrupt
|
||||
is declared a wakeup interrupt and its handling happens in driver's core, which
|
||||
is not aware of input-specific inhibit (nor should it be). Composite devices
|
||||
containing several interfaces can be inhibited on a per-interface basis and e.g.
|
||||
inhibiting one interface shouldn't affect the device's capability of being a
|
||||
wakeup source.
|
||||
|
||||
If a device is to be considered a wakeup source while inhibited, special care
|
||||
must be taken when programming its suspend(), as it might need to call device's
|
||||
open(). Depending on what close() means for the device in question, not
|
||||
opening() it before going to sleep might make it impossible to provide any
|
||||
wakeup events. The device is going to sleep anyway.
|
||||
|
||||
Basic event types
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
@ -2966,7 +2966,7 @@ ATMEL MAXTOUCH DRIVER
|
|||
M: Nick Dyer <nick@shmanahar.org>
|
||||
S: Maintained
|
||||
T: git git://github.com/ndyer/linux.git
|
||||
F: Documentation/devicetree/bindings/input/atmel,maxtouch.txt
|
||||
F: Documentation/devicetree/bindings/input/atmel,maxtouch.yaml
|
||||
F: drivers/input/touchscreen/atmel_mxt_ts.c
|
||||
|
||||
ATMEL WIRELESS DRIVER
|
||||
|
@ -5159,6 +5159,7 @@ M: Support Opensource <support.opensource@diasemi.com>
|
|||
S: Supported
|
||||
W: http://www.dialog-semiconductor.com/products
|
||||
F: Documentation/devicetree/bindings/input/da90??-onkey.txt
|
||||
F: Documentation/devicetree/bindings/input/dlg,da72??.txt
|
||||
F: Documentation/devicetree/bindings/mfd/da90*.txt
|
||||
F: Documentation/devicetree/bindings/regulator/dlg,da9*.yaml
|
||||
F: Documentation/devicetree/bindings/regulator/da92*.txt
|
||||
|
@ -5170,6 +5171,7 @@ F: Documentation/hwmon/da90??.rst
|
|||
F: drivers/gpio/gpio-da90??.c
|
||||
F: drivers/hwmon/da90??-hwmon.c
|
||||
F: drivers/iio/adc/da91??-*.c
|
||||
F: drivers/input/misc/da72??.[ch]
|
||||
F: drivers/input/misc/da90??_onkey.c
|
||||
F: drivers/input/touchscreen/da9052_tsi.c
|
||||
F: drivers/leds/leds-da90??.c
|
||||
|
|
|
@ -589,7 +589,7 @@
|
|||
|
||||
touchscreen@4b {
|
||||
compatible = "atmel,maxtouch";
|
||||
reset-gpio = <&gpio5 19 GPIO_ACTIVE_HIGH>;
|
||||
reset-gpio = <&gpio5 19 GPIO_ACTIVE_LOW>;
|
||||
reg = <0x4b>;
|
||||
interrupt-parent = <&gpio5>;
|
||||
interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
|
||||
|
|
|
@ -143,7 +143,7 @@
|
|||
reg = <0x4a>;
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <9 IRQ_TYPE_EDGE_FALLING>; /* SODIMM 28 */
|
||||
reset-gpios = <&gpio2 10 GPIO_ACTIVE_HIGH>; /* SODIMM 30 */
|
||||
reset-gpios = <&gpio2 10 GPIO_ACTIVE_LOW>; /* SODIMM 30 */
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
|
|
@ -140,7 +140,7 @@
|
|||
reg = <0x4a>;
|
||||
interrupt-parent = <&gpio6>;
|
||||
interrupts = <10 IRQ_TYPE_EDGE_FALLING>;
|
||||
reset-gpios = <&gpio6 9 GPIO_ACTIVE_HIGH>; /* SODIMM 13 */
|
||||
reset-gpios = <&gpio6 9 GPIO_ACTIVE_LOW>; /* SODIMM 13 */
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
|
|
@ -145,7 +145,7 @@
|
|||
reg = <0x4a>;
|
||||
interrupt-parent = <&gpio6>;
|
||||
interrupts = <10 IRQ_TYPE_EDGE_FALLING>;
|
||||
reset-gpios = <&gpio6 9 GPIO_ACTIVE_HIGH>; /* SODIMM 13 */
|
||||
reset-gpios = <&gpio6 9 GPIO_ACTIVE_LOW>; /* SODIMM 13 */
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
|
|
@ -144,7 +144,7 @@
|
|||
reg = <0x4a>;
|
||||
interrupt-parent = <&gpio6>;
|
||||
interrupts = <10 IRQ_TYPE_EDGE_FALLING>;
|
||||
reset-gpios = <&gpio6 9 GPIO_ACTIVE_HIGH>; /* SODIMM 13 */
|
||||
reset-gpios = <&gpio6 9 GPIO_ACTIVE_LOW>; /* SODIMM 13 */
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
|
|
@ -99,7 +99,7 @@
|
|||
reg = <0x4a>;
|
||||
interrupt-parent = <&gpio2>;
|
||||
interrupts = <15 IRQ_TYPE_EDGE_FALLING>; /* SODIMM 107 */
|
||||
reset-gpios = <&gpio2 28 GPIO_ACTIVE_HIGH>; /* SODIMM 106 */
|
||||
reset-gpios = <&gpio2 28 GPIO_ACTIVE_LOW>; /* SODIMM 106 */
|
||||
};
|
||||
|
||||
/* M41T0M6 real time clock on carrier board */
|
||||
|
|
|
@ -124,7 +124,7 @@
|
|||
reg = <0x4a>;
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <9 IRQ_TYPE_EDGE_FALLING>; /* SODIMM 28 */
|
||||
reset-gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>; /* SODIMM 30 */
|
||||
reset-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>; /* SODIMM 30 */
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
|
|
@ -430,7 +430,7 @@
|
|||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&touchscreen_pins>;
|
||||
|
||||
reset-gpios = <&gpio6 13 GPIO_ACTIVE_HIGH>; /* gpio173 */
|
||||
reset-gpios = <&gpio6 13 GPIO_ACTIVE_LOW>; /* gpio173 */
|
||||
|
||||
/* gpio_183 with sys_nirq2 pad as wakeup */
|
||||
interrupts-extended = <&gpio6 23 IRQ_TYPE_LEVEL_LOW>,
|
||||
|
|
|
@ -632,7 +632,7 @@
|
|||
interrupts = <5 IRQ_TYPE_EDGE_FALLING>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&ts_irq>;
|
||||
reset-gpios = <&gpj1 3 GPIO_ACTIVE_HIGH>;
|
||||
reset-gpios = <&gpj1 3 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -446,7 +446,7 @@
|
|||
interrupt-parent = <&gpio>;
|
||||
interrupts = <TEGRA_GPIO(V, 6) IRQ_TYPE_LEVEL_LOW>;
|
||||
|
||||
reset-gpios = <&gpio TEGRA_GPIO(Q, 7) GPIO_ACTIVE_HIGH>;
|
||||
reset-gpios = <&gpio TEGRA_GPIO(Q, 7) GPIO_ACTIVE_LOW>;
|
||||
|
||||
avdd-supply = <&vdd_3v3_sys>;
|
||||
vdd-supply = <&vdd_3v3_sys>;
|
||||
|
|
|
@ -579,7 +579,6 @@ CONFIG_JOYSTICK_XPAD_LEDS=y
|
|||
CONFIG_INPUT_TABLET=y
|
||||
CONFIG_TABLET_USB_ACECAD=m
|
||||
CONFIG_TABLET_USB_AIPTEK=m
|
||||
CONFIG_TABLET_USB_GTCO=m
|
||||
CONFIG_TABLET_USB_KBTAB=m
|
||||
CONFIG_INPUT_MISC=y
|
||||
CONFIG_INPUT_PCSPKR=m
|
||||
|
|
|
@ -52,19 +52,6 @@ config INPUT_FF_MEMLESS
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called ff-memless.
|
||||
|
||||
config INPUT_POLLDEV
|
||||
tristate "Polled input device skeleton"
|
||||
help
|
||||
Say Y here if you are using a driver for an input
|
||||
device that periodically polls hardware state. This
|
||||
option is only useful for out-of-tree drivers since
|
||||
in-tree drivers select it automatically.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called input-polldev.
|
||||
|
||||
config INPUT_SPARSEKMAP
|
||||
tristate "Sparse keymap support library"
|
||||
help
|
||||
|
|
|
@ -9,7 +9,6 @@ obj-$(CONFIG_INPUT) += input-core.o
|
|||
input-core-y := input.o input-compat.o input-mt.o input-poller.o ff-core.o
|
||||
|
||||
obj-$(CONFIG_INPUT_FF_MEMLESS) += ff-memless.o
|
||||
obj-$(CONFIG_INPUT_POLLDEV) += input-polldev.o
|
||||
obj-$(CONFIG_INPUT_SPARSEKMAP) += sparse-keymap.o
|
||||
obj-$(CONFIG_INPUT_MATRIXKMAP) += matrix-keymap.o
|
||||
|
||||
|
|
|
@ -1,362 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Generic implementation of a polled input device
|
||||
|
||||
* Copyright (c) 2007 Dmitry Torokhov
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/input-polldev.h>
|
||||
|
||||
MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>");
|
||||
MODULE_DESCRIPTION("Generic implementation of a polled input device");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
||||
static void input_polldev_queue_work(struct input_polled_dev *dev)
|
||||
{
|
||||
unsigned long delay;
|
||||
|
||||
delay = msecs_to_jiffies(dev->poll_interval);
|
||||
if (delay >= HZ)
|
||||
delay = round_jiffies_relative(delay);
|
||||
|
||||
queue_delayed_work(system_freezable_wq, &dev->work, delay);
|
||||
}
|
||||
|
||||
static void input_polled_device_work(struct work_struct *work)
|
||||
{
|
||||
struct input_polled_dev *dev =
|
||||
container_of(work, struct input_polled_dev, work.work);
|
||||
|
||||
dev->poll(dev);
|
||||
input_polldev_queue_work(dev);
|
||||
}
|
||||
|
||||
static int input_open_polled_device(struct input_dev *input)
|
||||
{
|
||||
struct input_polled_dev *dev = input_get_drvdata(input);
|
||||
|
||||
if (dev->open)
|
||||
dev->open(dev);
|
||||
|
||||
/* Only start polling if polling is enabled */
|
||||
if (dev->poll_interval > 0) {
|
||||
dev->poll(dev);
|
||||
input_polldev_queue_work(dev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void input_close_polled_device(struct input_dev *input)
|
||||
{
|
||||
struct input_polled_dev *dev = input_get_drvdata(input);
|
||||
|
||||
cancel_delayed_work_sync(&dev->work);
|
||||
|
||||
if (dev->close)
|
||||
dev->close(dev);
|
||||
}
|
||||
|
||||
/* SYSFS interface */
|
||||
|
||||
static ssize_t input_polldev_get_poll(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct input_polled_dev *polldev = dev_get_drvdata(dev);
|
||||
|
||||
return sprintf(buf, "%d\n", polldev->poll_interval);
|
||||
}
|
||||
|
||||
static ssize_t input_polldev_set_poll(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
struct input_polled_dev *polldev = dev_get_drvdata(dev);
|
||||
struct input_dev *input = polldev->input;
|
||||
unsigned int interval;
|
||||
int err;
|
||||
|
||||
err = kstrtouint(buf, 0, &interval);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (interval < polldev->poll_interval_min)
|
||||
return -EINVAL;
|
||||
|
||||
if (interval > polldev->poll_interval_max)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&input->mutex);
|
||||
|
||||
polldev->poll_interval = interval;
|
||||
|
||||
if (input->users) {
|
||||
cancel_delayed_work_sync(&polldev->work);
|
||||
if (polldev->poll_interval > 0)
|
||||
input_polldev_queue_work(polldev);
|
||||
}
|
||||
|
||||
mutex_unlock(&input->mutex);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(poll, S_IRUGO | S_IWUSR, input_polldev_get_poll,
|
||||
input_polldev_set_poll);
|
||||
|
||||
|
||||
static ssize_t input_polldev_get_max(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct input_polled_dev *polldev = dev_get_drvdata(dev);
|
||||
|
||||
return sprintf(buf, "%d\n", polldev->poll_interval_max);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(max, S_IRUGO, input_polldev_get_max, NULL);
|
||||
|
||||
static ssize_t input_polldev_get_min(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct input_polled_dev *polldev = dev_get_drvdata(dev);
|
||||
|
||||
return sprintf(buf, "%d\n", polldev->poll_interval_min);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(min, S_IRUGO, input_polldev_get_min, NULL);
|
||||
|
||||
static struct attribute *sysfs_attrs[] = {
|
||||
&dev_attr_poll.attr,
|
||||
&dev_attr_max.attr,
|
||||
&dev_attr_min.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group input_polldev_attribute_group = {
|
||||
.attrs = sysfs_attrs
|
||||
};
|
||||
|
||||
static const struct attribute_group *input_polldev_attribute_groups[] = {
|
||||
&input_polldev_attribute_group,
|
||||
NULL
|
||||
};
|
||||
|
||||
/**
|
||||
* input_allocate_polled_device - allocate memory for polled device
|
||||
*
|
||||
* The function allocates memory for a polled device and also
|
||||
* for an input device associated with this polled device.
|
||||
*/
|
||||
struct input_polled_dev *input_allocate_polled_device(void)
|
||||
{
|
||||
struct input_polled_dev *dev;
|
||||
|
||||
dev = kzalloc(sizeof(struct input_polled_dev), GFP_KERNEL);
|
||||
if (!dev)
|
||||
return NULL;
|
||||
|
||||
dev->input = input_allocate_device();
|
||||
if (!dev->input) {
|
||||
kfree(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return dev;
|
||||
}
|
||||
EXPORT_SYMBOL(input_allocate_polled_device);
|
||||
|
||||
struct input_polled_devres {
|
||||
struct input_polled_dev *polldev;
|
||||
};
|
||||
|
||||
static int devm_input_polldev_match(struct device *dev, void *res, void *data)
|
||||
{
|
||||
struct input_polled_devres *devres = res;
|
||||
|
||||
return devres->polldev == data;
|
||||
}
|
||||
|
||||
static void devm_input_polldev_release(struct device *dev, void *res)
|
||||
{
|
||||
struct input_polled_devres *devres = res;
|
||||
struct input_polled_dev *polldev = devres->polldev;
|
||||
|
||||
dev_dbg(dev, "%s: dropping reference/freeing %s\n",
|
||||
__func__, dev_name(&polldev->input->dev));
|
||||
|
||||
input_put_device(polldev->input);
|
||||
kfree(polldev);
|
||||
}
|
||||
|
||||
static void devm_input_polldev_unregister(struct device *dev, void *res)
|
||||
{
|
||||
struct input_polled_devres *devres = res;
|
||||
struct input_polled_dev *polldev = devres->polldev;
|
||||
|
||||
dev_dbg(dev, "%s: unregistering device %s\n",
|
||||
__func__, dev_name(&polldev->input->dev));
|
||||
input_unregister_device(polldev->input);
|
||||
|
||||
/*
|
||||
* Note that we are still holding extra reference to the input
|
||||
* device so it will stick around until devm_input_polldev_release()
|
||||
* is called.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_input_allocate_polled_device - allocate managed polled device
|
||||
* @dev: device owning the polled device being created
|
||||
*
|
||||
* Returns prepared &struct input_polled_dev or %NULL.
|
||||
*
|
||||
* Managed polled input devices do not need to be explicitly unregistered
|
||||
* or freed as it will be done automatically when owner device unbinds
|
||||
* from * its driver (or binding fails). Once such managed polled device
|
||||
* is allocated, it is ready to be set up and registered in the same
|
||||
* fashion as regular polled input devices (using
|
||||
* input_register_polled_device() function).
|
||||
*
|
||||
* If you want to manually unregister and free such managed polled devices,
|
||||
* it can be still done by calling input_unregister_polled_device() and
|
||||
* input_free_polled_device(), although it is rarely needed.
|
||||
*
|
||||
* NOTE: the owner device is set up as parent of input device and users
|
||||
* should not override it.
|
||||
*/
|
||||
struct input_polled_dev *devm_input_allocate_polled_device(struct device *dev)
|
||||
{
|
||||
struct input_polled_dev *polldev;
|
||||
struct input_polled_devres *devres;
|
||||
|
||||
devres = devres_alloc(devm_input_polldev_release, sizeof(*devres),
|
||||
GFP_KERNEL);
|
||||
if (!devres)
|
||||
return NULL;
|
||||
|
||||
polldev = input_allocate_polled_device();
|
||||
if (!polldev) {
|
||||
devres_free(devres);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
polldev->input->dev.parent = dev;
|
||||
polldev->devres_managed = true;
|
||||
|
||||
devres->polldev = polldev;
|
||||
devres_add(dev, devres);
|
||||
|
||||
return polldev;
|
||||
}
|
||||
EXPORT_SYMBOL(devm_input_allocate_polled_device);
|
||||
|
||||
/**
|
||||
* input_free_polled_device - free memory allocated for polled device
|
||||
* @dev: device to free
|
||||
*
|
||||
* The function frees memory allocated for polling device and drops
|
||||
* reference to the associated input device.
|
||||
*/
|
||||
void input_free_polled_device(struct input_polled_dev *dev)
|
||||
{
|
||||
if (dev) {
|
||||
if (dev->devres_managed)
|
||||
WARN_ON(devres_destroy(dev->input->dev.parent,
|
||||
devm_input_polldev_release,
|
||||
devm_input_polldev_match,
|
||||
dev));
|
||||
input_put_device(dev->input);
|
||||
kfree(dev);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(input_free_polled_device);
|
||||
|
||||
/**
|
||||
* input_register_polled_device - register polled device
|
||||
* @dev: device to register
|
||||
*
|
||||
* The function registers previously initialized polled input device
|
||||
* with input layer. The device should be allocated with call to
|
||||
* input_allocate_polled_device(). Callers should also set up poll()
|
||||
* method and set up capabilities (id, name, phys, bits) of the
|
||||
* corresponding input_dev structure.
|
||||
*/
|
||||
int input_register_polled_device(struct input_polled_dev *dev)
|
||||
{
|
||||
struct input_polled_devres *devres = NULL;
|
||||
struct input_dev *input = dev->input;
|
||||
int error;
|
||||
|
||||
if (dev->devres_managed) {
|
||||
devres = devres_alloc(devm_input_polldev_unregister,
|
||||
sizeof(*devres), GFP_KERNEL);
|
||||
if (!devres)
|
||||
return -ENOMEM;
|
||||
|
||||
devres->polldev = dev;
|
||||
}
|
||||
|
||||
input_set_drvdata(input, dev);
|
||||
INIT_DELAYED_WORK(&dev->work, input_polled_device_work);
|
||||
|
||||
if (!dev->poll_interval)
|
||||
dev->poll_interval = 500;
|
||||
if (!dev->poll_interval_max)
|
||||
dev->poll_interval_max = dev->poll_interval;
|
||||
|
||||
input->open = input_open_polled_device;
|
||||
input->close = input_close_polled_device;
|
||||
|
||||
input->dev.groups = input_polldev_attribute_groups;
|
||||
|
||||
error = input_register_device(input);
|
||||
if (error) {
|
||||
devres_free(devres);
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Take extra reference to the underlying input device so
|
||||
* that it survives call to input_unregister_polled_device()
|
||||
* and is deleted only after input_free_polled_device()
|
||||
* has been invoked. This is needed to ease task of freeing
|
||||
* sparse keymaps.
|
||||
*/
|
||||
input_get_device(input);
|
||||
|
||||
if (dev->devres_managed) {
|
||||
dev_dbg(input->dev.parent, "%s: registering %s with devres.\n",
|
||||
__func__, dev_name(&input->dev));
|
||||
devres_add(input->dev.parent, devres);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(input_register_polled_device);
|
||||
|
||||
/**
|
||||
* input_unregister_polled_device - unregister polled device
|
||||
* @dev: device to unregister
|
||||
*
|
||||
* The function unregisters previously registered polled input
|
||||
* device from input layer. Polling is stopped and device is
|
||||
* ready to be freed with call to input_free_polled_device().
|
||||
*/
|
||||
void input_unregister_polled_device(struct input_polled_dev *dev)
|
||||
{
|
||||
if (dev->devres_managed)
|
||||
WARN_ON(devres_destroy(dev->input->dev.parent,
|
||||
devm_input_polldev_unregister,
|
||||
devm_input_polldev_match,
|
||||
dev));
|
||||
|
||||
input_unregister_device(dev->input);
|
||||
}
|
||||
EXPORT_SYMBOL(input_unregister_polled_device);
|
|
@ -166,7 +166,7 @@ static ssize_t input_dev_set_poll_interval(struct device *dev,
|
|||
|
||||
poller->poll_interval = interval;
|
||||
|
||||
if (input->users) {
|
||||
if (input_device_enabled(input)) {
|
||||
cancel_delayed_work_sync(&poller->work);
|
||||
if (poller->poll_interval > 0)
|
||||
input_dev_poller_queue_work(poller);
|
||||
|
|
|
@ -367,8 +367,13 @@ static int input_get_disposition(struct input_dev *dev,
|
|||
static void input_handle_event(struct input_dev *dev,
|
||||
unsigned int type, unsigned int code, int value)
|
||||
{
|
||||
int disposition = input_get_disposition(dev, type, code, &value);
|
||||
int disposition;
|
||||
|
||||
/* filter-out events from inhibited devices */
|
||||
if (dev->inhibited)
|
||||
return;
|
||||
|
||||
disposition = input_get_disposition(dev, type, code, &value);
|
||||
if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN)
|
||||
add_input_randomness(type, code, value);
|
||||
|
||||
|
@ -612,10 +617,10 @@ int input_open_device(struct input_handle *handle)
|
|||
|
||||
handle->open++;
|
||||
|
||||
if (dev->users++) {
|
||||
if (dev->users++ || dev->inhibited) {
|
||||
/*
|
||||
* Device is already opened, so we can exit immediately and
|
||||
* report success.
|
||||
* Device is already opened and/or inhibited,
|
||||
* so we can exit immediately and report success.
|
||||
*/
|
||||
goto out;
|
||||
}
|
||||
|
@ -675,10 +680,9 @@ void input_close_device(struct input_handle *handle)
|
|||
|
||||
__input_release_device(handle);
|
||||
|
||||
if (!--dev->users) {
|
||||
if (!dev->inhibited && !--dev->users) {
|
||||
if (dev->poller)
|
||||
input_dev_poller_stop(dev->poller);
|
||||
|
||||
if (dev->close)
|
||||
dev->close(dev);
|
||||
}
|
||||
|
@ -1416,12 +1420,49 @@ static ssize_t input_dev_show_properties(struct device *dev,
|
|||
}
|
||||
static DEVICE_ATTR(properties, S_IRUGO, input_dev_show_properties, NULL);
|
||||
|
||||
static int input_inhibit_device(struct input_dev *dev);
|
||||
static int input_uninhibit_device(struct input_dev *dev);
|
||||
|
||||
static ssize_t inhibited_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct input_dev *input_dev = to_input_dev(dev);
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", input_dev->inhibited);
|
||||
}
|
||||
|
||||
static ssize_t inhibited_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf,
|
||||
size_t len)
|
||||
{
|
||||
struct input_dev *input_dev = to_input_dev(dev);
|
||||
ssize_t rv;
|
||||
bool inhibited;
|
||||
|
||||
if (strtobool(buf, &inhibited))
|
||||
return -EINVAL;
|
||||
|
||||
if (inhibited)
|
||||
rv = input_inhibit_device(input_dev);
|
||||
else
|
||||
rv = input_uninhibit_device(input_dev);
|
||||
|
||||
if (rv != 0)
|
||||
return rv;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RW(inhibited);
|
||||
|
||||
static struct attribute *input_dev_attrs[] = {
|
||||
&dev_attr_name.attr,
|
||||
&dev_attr_phys.attr,
|
||||
&dev_attr_uniq.attr,
|
||||
&dev_attr_modalias.attr,
|
||||
&dev_attr_properties.attr,
|
||||
&dev_attr_inhibited.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -1703,6 +1744,63 @@ void input_reset_device(struct input_dev *dev)
|
|||
}
|
||||
EXPORT_SYMBOL(input_reset_device);
|
||||
|
||||
static int input_inhibit_device(struct input_dev *dev)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&dev->mutex);
|
||||
|
||||
if (dev->inhibited)
|
||||
goto out;
|
||||
|
||||
if (dev->users) {
|
||||
if (dev->close)
|
||||
dev->close(dev);
|
||||
if (dev->poller)
|
||||
input_dev_poller_stop(dev->poller);
|
||||
}
|
||||
|
||||
spin_lock_irq(&dev->event_lock);
|
||||
input_dev_release_keys(dev);
|
||||
input_dev_toggle(dev, false);
|
||||
spin_unlock_irq(&dev->event_lock);
|
||||
|
||||
dev->inhibited = true;
|
||||
|
||||
out:
|
||||
mutex_unlock(&dev->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int input_uninhibit_device(struct input_dev *dev)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&dev->mutex);
|
||||
|
||||
if (!dev->inhibited)
|
||||
goto out;
|
||||
|
||||
if (dev->users) {
|
||||
if (dev->open) {
|
||||
ret = dev->open(dev);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
if (dev->poller)
|
||||
input_dev_poller_start(dev->poller);
|
||||
}
|
||||
|
||||
dev->inhibited = false;
|
||||
spin_lock_irq(&dev->event_lock);
|
||||
input_dev_toggle(dev, true);
|
||||
spin_unlock_irq(&dev->event_lock);
|
||||
|
||||
out:
|
||||
mutex_unlock(&dev->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int input_dev_suspend(struct device *dev)
|
||||
{
|
||||
|
@ -2127,6 +2225,14 @@ void input_enable_softrepeat(struct input_dev *dev, int delay, int period)
|
|||
}
|
||||
EXPORT_SYMBOL(input_enable_softrepeat);
|
||||
|
||||
bool input_device_enabled(struct input_dev *dev)
|
||||
{
|
||||
lockdep_assert_held(&dev->mutex);
|
||||
|
||||
return !dev->inhibited && dev->users > 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(input_device_enabled);
|
||||
|
||||
/**
|
||||
* input_register_device - register device with input core
|
||||
* @dev: device to be registered
|
||||
|
|
|
@ -665,7 +665,7 @@ static int analog_connect(struct gameport *gameport, struct gameport_driver *drv
|
|||
int err;
|
||||
|
||||
if (!(port = kzalloc(sizeof(struct analog_port), GFP_KERNEL)))
|
||||
return - ENOMEM;
|
||||
return -ENOMEM;
|
||||
|
||||
err = analog_init_port(gameport, drv, port);
|
||||
if (err)
|
||||
|
|
|
@ -1339,7 +1339,7 @@ struct xpad_led {
|
|||
struct usb_xpad *xpad;
|
||||
};
|
||||
|
||||
/**
|
||||
/*
|
||||
* set the LEDs on Xbox360 / Wireless Controllers
|
||||
* @param command
|
||||
* 0: off
|
||||
|
@ -1904,7 +1904,7 @@ static int xpad_suspend(struct usb_interface *intf, pm_message_t message)
|
|||
xpad360w_poweroff_controller(xpad);
|
||||
} else {
|
||||
mutex_lock(&input->mutex);
|
||||
if (input->users)
|
||||
if (input_device_enabled(input))
|
||||
xpad_stop_input(xpad);
|
||||
mutex_unlock(&input->mutex);
|
||||
}
|
||||
|
@ -1924,7 +1924,7 @@ static int xpad_resume(struct usb_interface *intf)
|
|||
retval = xpad360w_start_input(xpad);
|
||||
} else {
|
||||
mutex_lock(&input->mutex);
|
||||
if (input->users) {
|
||||
if (input_device_enabled(input)) {
|
||||
retval = xpad_start_input(xpad);
|
||||
} else if (xpad->xtype == XTYPE_XBOXONE) {
|
||||
/*
|
||||
|
|
|
@ -457,7 +457,7 @@ config KEYBOARD_SNVS_PWRKEY
|
|||
|
||||
config KEYBOARD_IMX
|
||||
tristate "IMX keypad support"
|
||||
depends on ARCH_MXC
|
||||
depends on ARCH_MXC || COMPILE_TEST
|
||||
select INPUT_MATRIXKMAP
|
||||
help
|
||||
Enable support for IMX keypad port.
|
||||
|
|
|
@ -7,12 +7,14 @@
|
|||
* Copyright (C) 2010-2011 Analog Devices Inc.
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/pm_wakeirq.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/i2c.h>
|
||||
|
@ -153,48 +155,48 @@
|
|||
#define ADP5589_5_MAN_ID 0x02
|
||||
|
||||
/* GENERAL_CFG Register */
|
||||
#define OSC_EN (1 << 7)
|
||||
#define OSC_EN BIT(7)
|
||||
#define CORE_CLK(x) (((x) & 0x3) << 5)
|
||||
#define LCK_TRK_LOGIC (1 << 4) /* ADP5589 only */
|
||||
#define LCK_TRK_GPI (1 << 3) /* ADP5589 only */
|
||||
#define INT_CFG (1 << 1)
|
||||
#define RST_CFG (1 << 0)
|
||||
#define LCK_TRK_LOGIC BIT(4) /* ADP5589 only */
|
||||
#define LCK_TRK_GPI BIT(3) /* ADP5589 only */
|
||||
#define INT_CFG BIT(1)
|
||||
#define RST_CFG BIT(0)
|
||||
|
||||
/* INT_EN Register */
|
||||
#define LOGIC2_IEN (1 << 5) /* ADP5589 only */
|
||||
#define LOGIC1_IEN (1 << 4)
|
||||
#define LOCK_IEN (1 << 3) /* ADP5589 only */
|
||||
#define OVRFLOW_IEN (1 << 2)
|
||||
#define GPI_IEN (1 << 1)
|
||||
#define EVENT_IEN (1 << 0)
|
||||
#define LOGIC2_IEN BIT(5) /* ADP5589 only */
|
||||
#define LOGIC1_IEN BIT(4)
|
||||
#define LOCK_IEN BIT(3) /* ADP5589 only */
|
||||
#define OVRFLOW_IEN BIT(2)
|
||||
#define GPI_IEN BIT(1)
|
||||
#define EVENT_IEN BIT(0)
|
||||
|
||||
/* Interrupt Status Register */
|
||||
#define LOGIC2_INT (1 << 5) /* ADP5589 only */
|
||||
#define LOGIC1_INT (1 << 4)
|
||||
#define LOCK_INT (1 << 3) /* ADP5589 only */
|
||||
#define OVRFLOW_INT (1 << 2)
|
||||
#define GPI_INT (1 << 1)
|
||||
#define EVENT_INT (1 << 0)
|
||||
#define LOGIC2_INT BIT(5) /* ADP5589 only */
|
||||
#define LOGIC1_INT BIT(4)
|
||||
#define LOCK_INT BIT(3) /* ADP5589 only */
|
||||
#define OVRFLOW_INT BIT(2)
|
||||
#define GPI_INT BIT(1)
|
||||
#define EVENT_INT BIT(0)
|
||||
|
||||
/* STATUS Register */
|
||||
#define LOGIC2_STAT (1 << 7) /* ADP5589 only */
|
||||
#define LOGIC1_STAT (1 << 6)
|
||||
#define LOCK_STAT (1 << 5) /* ADP5589 only */
|
||||
#define LOGIC2_STAT BIT(7) /* ADP5589 only */
|
||||
#define LOGIC1_STAT BIT(6)
|
||||
#define LOCK_STAT BIT(5) /* ADP5589 only */
|
||||
#define KEC 0x1F
|
||||
|
||||
/* PIN_CONFIG_D Register */
|
||||
#define C4_EXTEND_CFG (1 << 6) /* RESET2 */
|
||||
#define R4_EXTEND_CFG (1 << 5) /* RESET1 */
|
||||
#define C4_EXTEND_CFG BIT(6) /* RESET2 */
|
||||
#define R4_EXTEND_CFG BIT(5) /* RESET1 */
|
||||
|
||||
/* LOCK_CFG */
|
||||
#define LOCK_EN (1 << 0)
|
||||
#define LOCK_EN BIT(0)
|
||||
|
||||
#define PTIME_MASK 0x3
|
||||
#define LTIME_MASK 0x3 /* ADP5589 only */
|
||||
|
||||
/* Key Event Register xy */
|
||||
#define KEY_EV_PRESSED (1 << 7)
|
||||
#define KEY_EV_MASK (0x7F)
|
||||
#define KEY_EV_PRESSED BIT(7)
|
||||
#define KEY_EV_MASK 0x7F
|
||||
|
||||
#define KEYP_MAX_EVENT 16
|
||||
#define ADP5589_MAXGPIO 19
|
||||
|
@ -238,7 +240,6 @@ struct adp5589_kpad {
|
|||
bool support_row5;
|
||||
#ifdef CONFIG_GPIOLIB
|
||||
unsigned char gpiomap[ADP5589_MAXGPIO];
|
||||
bool export_gpio;
|
||||
struct gpio_chip gc;
|
||||
struct mutex gpio_lock; /* Protect cached dir, dat_out */
|
||||
u8 dat_out[3];
|
||||
|
@ -473,7 +474,7 @@ static int adp5589_build_gpiomap(struct adp5589_kpad *kpad,
|
|||
memset(pin_used, false, sizeof(pin_used));
|
||||
|
||||
for (i = 0; i < kpad->var->maxgpio; i++)
|
||||
if (pdata->keypad_en_mask & (1 << i))
|
||||
if (pdata->keypad_en_mask & BIT(i))
|
||||
pin_used[i] = true;
|
||||
|
||||
for (i = 0; i < kpad->gpimapsize; i++)
|
||||
|
@ -512,8 +513,6 @@ static int adp5589_gpio_add(struct adp5589_kpad *kpad)
|
|||
return 0;
|
||||
}
|
||||
|
||||
kpad->export_gpio = true;
|
||||
|
||||
kpad->gc.direction_input = adp5589_gpio_direction_input;
|
||||
kpad->gc.direction_output = adp5589_gpio_direction_output;
|
||||
kpad->gc.get = adp5589_gpio_get_value;
|
||||
|
@ -526,11 +525,9 @@ static int adp5589_gpio_add(struct adp5589_kpad *kpad)
|
|||
|
||||
mutex_init(&kpad->gpio_lock);
|
||||
|
||||
error = gpiochip_add_data(&kpad->gc, kpad);
|
||||
if (error) {
|
||||
dev_err(dev, "gpiochip_add_data() failed, err: %d\n", error);
|
||||
error = devm_gpiochip_add_data(dev, &kpad->gc, kpad);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
|
||||
for (i = 0; i <= kpad->var->bank(kpad->var->maxgpio); i++) {
|
||||
kpad->dat_out[i] = adp5589_read(kpad->client, kpad->var->reg(
|
||||
|
@ -539,46 +536,13 @@ static int adp5589_gpio_add(struct adp5589_kpad *kpad)
|
|||
ADP5589_GPIO_DIRECTION_A) + i);
|
||||
}
|
||||
|
||||
if (gpio_data->setup) {
|
||||
error = gpio_data->setup(kpad->client,
|
||||
kpad->gc.base, kpad->gc.ngpio,
|
||||
gpio_data->context);
|
||||
if (error)
|
||||
dev_warn(dev, "setup failed, %d\n", error);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void adp5589_gpio_remove(struct adp5589_kpad *kpad)
|
||||
{
|
||||
struct device *dev = &kpad->client->dev;
|
||||
const struct adp5589_kpad_platform_data *pdata = dev_get_platdata(dev);
|
||||
const struct adp5589_gpio_platform_data *gpio_data = pdata->gpio_data;
|
||||
int error;
|
||||
|
||||
if (!kpad->export_gpio)
|
||||
return;
|
||||
|
||||
if (gpio_data->teardown) {
|
||||
error = gpio_data->teardown(kpad->client,
|
||||
kpad->gc.base, kpad->gc.ngpio,
|
||||
gpio_data->context);
|
||||
if (error)
|
||||
dev_warn(dev, "teardown failed %d\n", error);
|
||||
}
|
||||
|
||||
gpiochip_remove(&kpad->gc);
|
||||
}
|
||||
#else
|
||||
static inline int adp5589_gpio_add(struct adp5589_kpad *kpad)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void adp5589_gpio_remove(struct adp5589_kpad *kpad)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
static void adp5589_report_switches(struct adp5589_kpad *kpad,
|
||||
|
@ -689,13 +653,13 @@ static int adp5589_setup(struct adp5589_kpad *kpad)
|
|||
unsigned short pin = pdata->gpimap[i].pin;
|
||||
|
||||
if (pin <= kpad->var->gpi_pin_row_end) {
|
||||
evt_mode1 |= (1 << (pin - kpad->var->gpi_pin_row_base));
|
||||
evt_mode1 |= BIT(pin - kpad->var->gpi_pin_row_base);
|
||||
} else {
|
||||
evt_mode2 |=
|
||||
((1 << (pin - kpad->var->gpi_pin_col_base)) & 0xFF);
|
||||
BIT(pin - kpad->var->gpi_pin_col_base) & 0xFF;
|
||||
if (!kpad->is_adp5585)
|
||||
evt_mode3 |= ((1 << (pin -
|
||||
kpad->var->gpi_pin_col_base)) >> 8);
|
||||
evt_mode3 |=
|
||||
BIT(pin - kpad->var->gpi_pin_col_base) >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -715,7 +679,7 @@ static int adp5589_setup(struct adp5589_kpad *kpad)
|
|||
dev_warn(&client->dev, "Conflicting pull resistor config\n");
|
||||
|
||||
for (i = 0; i <= kpad->var->max_row_num; i++) {
|
||||
unsigned val = 0, bit = (1 << i);
|
||||
unsigned int val = 0, bit = BIT(i);
|
||||
if (pdata->pullup_en_300k & bit)
|
||||
val = 0;
|
||||
else if (pdata->pulldown_en_300k & bit)
|
||||
|
@ -735,7 +699,7 @@ static int adp5589_setup(struct adp5589_kpad *kpad)
|
|||
}
|
||||
|
||||
for (i = 0; i <= kpad->var->max_col_num; i++) {
|
||||
unsigned val = 0, bit = 1 << (i + kpad->var->col_shift);
|
||||
unsigned int val = 0, bit = BIT(i + kpad->var->col_shift);
|
||||
if (pdata->pullup_en_300k & bit)
|
||||
val = 0;
|
||||
else if (pdata->pulldown_en_300k & bit)
|
||||
|
@ -851,7 +815,7 @@ static void adp5589_report_switch_state(struct adp5589_kpad *kpad)
|
|||
|
||||
input_report_switch(kpad->input,
|
||||
kpad->gpimap[i].sw_evt,
|
||||
!(gpi_stat_tmp & (1 << pin_loc)));
|
||||
!(gpi_stat_tmp & BIT(pin_loc)));
|
||||
}
|
||||
|
||||
input_sync(kpad->input);
|
||||
|
@ -897,7 +861,7 @@ static int adp5589_keypad_add(struct adp5589_kpad *kpad, unsigned int revid)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((1 << (pin - kpad->var->gpi_pin_row_base)) &
|
||||
if (BIT(pin - kpad->var->gpi_pin_row_base) &
|
||||
pdata->keypad_en_mask) {
|
||||
dev_err(&client->dev, "invalid gpi row/col data\n");
|
||||
return -EINVAL;
|
||||
|
@ -909,7 +873,7 @@ static int adp5589_keypad_add(struct adp5589_kpad *kpad, unsigned int revid)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
input = input_allocate_device();
|
||||
input = devm_input_allocate_device(&client->dev);
|
||||
if (!input)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -955,36 +919,27 @@ static int adp5589_keypad_add(struct adp5589_kpad *kpad, unsigned int revid)
|
|||
error = input_register_device(input);
|
||||
if (error) {
|
||||
dev_err(&client->dev, "unable to register input device\n");
|
||||
goto err_free_input;
|
||||
return error;
|
||||
}
|
||||
|
||||
error = request_threaded_irq(client->irq, NULL, adp5589_irq,
|
||||
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
|
||||
client->dev.driver->name, kpad);
|
||||
error = devm_request_threaded_irq(&client->dev, client->irq,
|
||||
NULL, adp5589_irq,
|
||||
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
|
||||
client->dev.driver->name, kpad);
|
||||
if (error) {
|
||||
dev_err(&client->dev, "irq %d busy?\n", client->irq);
|
||||
goto err_unreg_dev;
|
||||
dev_err(&client->dev, "unable to request irq %d\n", client->irq);
|
||||
return error;
|
||||
}
|
||||
|
||||
device_init_wakeup(&client->dev, 1);
|
||||
|
||||
return 0;
|
||||
|
||||
err_unreg_dev:
|
||||
input_unregister_device(input);
|
||||
input = NULL;
|
||||
err_free_input:
|
||||
input_free_device(input);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static void adp5589_keypad_remove(struct adp5589_kpad *kpad)
|
||||
static void adp5589_clear_config(void *data)
|
||||
{
|
||||
if (kpad->input) {
|
||||
free_irq(kpad->client->irq, kpad);
|
||||
input_unregister_device(kpad->input);
|
||||
}
|
||||
struct i2c_client *client = data;
|
||||
struct adp5589_kpad *kpad = i2c_get_clientdata(client);
|
||||
|
||||
adp5589_write(client, kpad->var->reg(ADP5589_GENERAL_CFG), 0);
|
||||
}
|
||||
|
||||
static int adp5589_probe(struct i2c_client *client,
|
||||
|
@ -1007,7 +962,7 @@ static int adp5589_probe(struct i2c_client *client,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
kpad = kzalloc(sizeof(*kpad), GFP_KERNEL);
|
||||
kpad = devm_kzalloc(&client->dev, sizeof(*kpad), GFP_KERNEL);
|
||||
if (!kpad)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -1027,90 +982,62 @@ static int adp5589_probe(struct i2c_client *client,
|
|||
break;
|
||||
}
|
||||
|
||||
error = devm_add_action_or_reset(&client->dev, adp5589_clear_config,
|
||||
client);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
ret = adp5589_read(client, ADP5589_5_ID);
|
||||
if (ret < 0) {
|
||||
error = ret;
|
||||
goto err_free_mem;
|
||||
}
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
revid = (u8) ret & ADP5589_5_DEVICE_ID_MASK;
|
||||
|
||||
if (pdata->keymapsize) {
|
||||
error = adp5589_keypad_add(kpad, revid);
|
||||
if (error)
|
||||
goto err_free_mem;
|
||||
return error;
|
||||
}
|
||||
|
||||
error = adp5589_setup(kpad);
|
||||
if (error)
|
||||
goto err_keypad_remove;
|
||||
return error;
|
||||
|
||||
if (kpad->gpimapsize)
|
||||
adp5589_report_switch_state(kpad);
|
||||
|
||||
error = adp5589_gpio_add(kpad);
|
||||
if (error)
|
||||
goto err_keypad_remove;
|
||||
return error;
|
||||
|
||||
i2c_set_clientdata(client, kpad);
|
||||
|
||||
dev_info(&client->dev, "Rev.%d keypad, irq %d\n", revid, client->irq);
|
||||
return 0;
|
||||
|
||||
err_keypad_remove:
|
||||
adp5589_keypad_remove(kpad);
|
||||
err_free_mem:
|
||||
kfree(kpad);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int adp5589_remove(struct i2c_client *client)
|
||||
static int __maybe_unused adp5589_suspend(struct device *dev)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct adp5589_kpad *kpad = i2c_get_clientdata(client);
|
||||
|
||||
adp5589_write(client, kpad->var->reg(ADP5589_GENERAL_CFG), 0);
|
||||
adp5589_keypad_remove(kpad);
|
||||
adp5589_gpio_remove(kpad);
|
||||
kfree(kpad);
|
||||
if (kpad->input)
|
||||
disable_irq(client->irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int adp5589_suspend(struct device *dev)
|
||||
static int __maybe_unused adp5589_resume(struct device *dev)
|
||||
{
|
||||
struct adp5589_kpad *kpad = dev_get_drvdata(dev);
|
||||
struct i2c_client *client = kpad->client;
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct adp5589_kpad *kpad = i2c_get_clientdata(client);
|
||||
|
||||
if (!kpad->input)
|
||||
return 0;
|
||||
|
||||
disable_irq(client->irq);
|
||||
|
||||
if (device_may_wakeup(&client->dev))
|
||||
enable_irq_wake(client->irq);
|
||||
if (kpad->input)
|
||||
enable_irq(client->irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int adp5589_resume(struct device *dev)
|
||||
{
|
||||
struct adp5589_kpad *kpad = dev_get_drvdata(dev);
|
||||
struct i2c_client *client = kpad->client;
|
||||
|
||||
if (!kpad->input)
|
||||
return 0;
|
||||
|
||||
if (device_may_wakeup(&client->dev))
|
||||
disable_irq_wake(client->irq);
|
||||
|
||||
enable_irq(client->irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(adp5589_dev_pm_ops, adp5589_suspend, adp5589_resume);
|
||||
|
||||
static const struct i2c_device_id adp5589_id[] = {
|
||||
|
@ -1128,7 +1055,6 @@ static struct i2c_driver adp5589_driver = {
|
|||
.pm = &adp5589_dev_pm_ops,
|
||||
},
|
||||
.probe = adp5589_probe,
|
||||
.remove = adp5589_remove,
|
||||
.id_table = adp5589_id,
|
||||
};
|
||||
|
||||
|
|
|
@ -286,6 +286,15 @@ struct command_protocol_bl {
|
|||
* structure (after re-assembly in case of being split over
|
||||
* multiple spi-packets), minus the trailing crc. The total size
|
||||
* of the message struct is therefore @length + 10.
|
||||
*
|
||||
* @keyboard: Keyboard message
|
||||
* @touchpad: Touchpad message
|
||||
* @tp_info: Touchpad info (response)
|
||||
* @tp_info_command: Touchpad info (CRC)
|
||||
* @init_mt_command: Initialise Multitouch
|
||||
* @capsl_command: Toggle caps-lock LED
|
||||
* @bl_command: Keyboard brightness
|
||||
* @data: Buffer data
|
||||
*/
|
||||
struct message {
|
||||
__le16 type;
|
||||
|
@ -545,7 +554,8 @@ static void applespi_setup_read_txfrs(struct applespi_data *applespi)
|
|||
memset(dl_t, 0, sizeof(*dl_t));
|
||||
memset(rd_t, 0, sizeof(*rd_t));
|
||||
|
||||
dl_t->delay_usecs = applespi->spi_settings.spi_cs_delay;
|
||||
dl_t->delay.value = applespi->spi_settings.spi_cs_delay;
|
||||
dl_t->delay.unit = SPI_DELAY_UNIT_USECS;
|
||||
|
||||
rd_t->rx_buf = applespi->rx_buffer;
|
||||
rd_t->len = APPLESPI_PACKET_SIZE;
|
||||
|
@ -574,14 +584,17 @@ static void applespi_setup_write_txfrs(struct applespi_data *applespi)
|
|||
* end up with an extra unnecessary (but harmless) cs assertion and
|
||||
* deassertion.
|
||||
*/
|
||||
wt_t->delay_usecs = SPI_RW_CHG_DELAY_US;
|
||||
wt_t->delay.value = SPI_RW_CHG_DELAY_US;
|
||||
wt_t->delay.unit = SPI_DELAY_UNIT_USECS;
|
||||
wt_t->cs_change = 1;
|
||||
|
||||
dl_t->delay_usecs = applespi->spi_settings.spi_cs_delay;
|
||||
dl_t->delay.value = applespi->spi_settings.spi_cs_delay;
|
||||
dl_t->delay.unit = SPI_DELAY_UNIT_USECS;
|
||||
|
||||
wr_t->tx_buf = applespi->tx_buffer;
|
||||
wr_t->len = APPLESPI_PACKET_SIZE;
|
||||
wr_t->delay_usecs = SPI_RW_CHG_DELAY_US;
|
||||
wr_t->delay.value = SPI_RW_CHG_DELAY_US;
|
||||
wr_t->delay.unit = SPI_DELAY_UNIT_USECS;
|
||||
|
||||
st_t->rx_buf = applespi->tx_status;
|
||||
st_t->len = APPLESPI_STATUS_SIZE;
|
||||
|
|
|
@ -27,7 +27,9 @@
|
|||
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
/*
|
||||
/**
|
||||
* struct cros_ec_keyb - Structure representing EC keyboard device
|
||||
*
|
||||
* @rows: Number of rows in the keypad
|
||||
* @cols: Number of columns in the keypad
|
||||
* @row_shift: log2 or number of rows, rounded up
|
||||
|
@ -58,10 +60,9 @@ struct cros_ec_keyb {
|
|||
struct notifier_block notifier;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* cros_ec_bs_map - Struct mapping Linux keycodes to EC button/switch bitmap
|
||||
* #defines
|
||||
* struct cros_ec_bs_map - Mapping between Linux keycodes and EC button/switch
|
||||
* bitmap #defines
|
||||
*
|
||||
* @ev_type: The type of the input event to generate (e.g., EV_KEY).
|
||||
* @code: A linux keycode
|
||||
|
|
|
@ -208,7 +208,7 @@ static int ep93xx_keypad_resume(struct device *dev)
|
|||
|
||||
mutex_lock(&input_dev->mutex);
|
||||
|
||||
if (input_dev->users) {
|
||||
if (input_device_enabled(input_dev)) {
|
||||
if (!keypad->enabled) {
|
||||
ep93xx_keypad_config(keypad);
|
||||
clk_enable(keypad->clk);
|
||||
|
|
|
@ -108,7 +108,7 @@ static int get_n_events_by_type(int type)
|
|||
|
||||
/**
|
||||
* get_bm_events_by_type() - returns bitmap of supported events per @type
|
||||
* @input: input device from which bitmap is retrieved
|
||||
* @dev: input device from which bitmap is retrieved
|
||||
* @type: type of button (%EV_KEY, %EV_SW)
|
||||
*
|
||||
* Return value of this function can be used to allocate bitmap
|
||||
|
@ -965,7 +965,7 @@ static int __maybe_unused gpio_keys_suspend(struct device *dev)
|
|||
return error;
|
||||
} else {
|
||||
mutex_lock(&input->mutex);
|
||||
if (input->users)
|
||||
if (input_device_enabled(input))
|
||||
gpio_keys_close(input);
|
||||
mutex_unlock(&input->mutex);
|
||||
}
|
||||
|
@ -983,7 +983,7 @@ static int __maybe_unused gpio_keys_resume(struct device *dev)
|
|||
gpio_keys_disable_wakeup(ddata);
|
||||
} else {
|
||||
mutex_lock(&input->mutex);
|
||||
if (input->users)
|
||||
if (input_device_enabled(input))
|
||||
error = gpio_keys_open(input);
|
||||
mutex_unlock(&input->mutex);
|
||||
}
|
||||
|
|
|
@ -532,7 +532,7 @@ static int __maybe_unused imx_kbd_noirq_suspend(struct device *dev)
|
|||
/* imx kbd can wake up system even clock is disabled */
|
||||
mutex_lock(&input_dev->mutex);
|
||||
|
||||
if (input_dev->users)
|
||||
if (input_device_enabled(input_dev))
|
||||
clk_disable_unprepare(kbd->clk);
|
||||
|
||||
mutex_unlock(&input_dev->mutex);
|
||||
|
@ -562,7 +562,7 @@ static int __maybe_unused imx_kbd_noirq_resume(struct device *dev)
|
|||
|
||||
mutex_lock(&input_dev->mutex);
|
||||
|
||||
if (input_dev->users) {
|
||||
if (input_device_enabled(input_dev)) {
|
||||
ret = clk_prepare_enable(kbd->clk);
|
||||
if (ret)
|
||||
goto err_clk;
|
||||
|
|
|
@ -140,7 +140,7 @@ static int __maybe_unused micro_key_resume(struct device *dev)
|
|||
|
||||
mutex_lock(&input->mutex);
|
||||
|
||||
if (input->users)
|
||||
if (input_device_enabled(input))
|
||||
micro_key_start(keys);
|
||||
|
||||
mutex_unlock(&input->mutex);
|
||||
|
|
|
@ -273,7 +273,7 @@ static int lpc32xx_kscan_suspend(struct device *dev)
|
|||
|
||||
mutex_lock(&input->mutex);
|
||||
|
||||
if (input->users) {
|
||||
if (input_device_enabled(input)) {
|
||||
/* Clear IRQ and disable clock */
|
||||
writel(1, LPC32XX_KS_IRQ(kscandat->kscan_base));
|
||||
clk_disable_unprepare(kscandat->clk);
|
||||
|
@ -292,7 +292,7 @@ static int lpc32xx_kscan_resume(struct device *dev)
|
|||
|
||||
mutex_lock(&input->mutex);
|
||||
|
||||
if (input->users) {
|
||||
if (input_device_enabled(input)) {
|
||||
/* Enable clock and clear IRQ */
|
||||
retval = clk_prepare_enable(kscandat->clk);
|
||||
if (retval == 0)
|
||||
|
|
|
@ -58,6 +58,8 @@
|
|||
* @board: keypad platform device
|
||||
* @keymap: matrix scan code table for keycodes
|
||||
* @clk: clock structure pointer
|
||||
* @pclk: clock structure pointer
|
||||
* @ske_keypad_lock: spinlock protecting the keypad read/writes
|
||||
*/
|
||||
struct ske_keypad {
|
||||
int irq;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <linux/input/matrix_keypad.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/pm_wakeirq.h>
|
||||
|
||||
/* OMAP4 registers */
|
||||
#define OMAP4_KBD_REVISION 0x00
|
||||
|
@ -69,7 +70,6 @@ struct omap4_keypad {
|
|||
struct input_dev *input;
|
||||
|
||||
void __iomem *base;
|
||||
bool irq_wake_enabled;
|
||||
unsigned int irq;
|
||||
|
||||
unsigned int rows;
|
||||
|
@ -186,12 +186,8 @@ static int omap4_keypad_open(struct input_dev *input)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void omap4_keypad_close(struct input_dev *input)
|
||||
static void omap4_keypad_stop(struct omap4_keypad *keypad_data)
|
||||
{
|
||||
struct omap4_keypad *keypad_data = input_get_drvdata(input);
|
||||
|
||||
disable_irq(keypad_data->irq);
|
||||
|
||||
/* Disable interrupts and wake-up events */
|
||||
kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
|
||||
OMAP4_VAL_IRQDISABLE);
|
||||
|
@ -200,7 +196,15 @@ static void omap4_keypad_close(struct input_dev *input)
|
|||
/* clear pending interrupts */
|
||||
kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
|
||||
kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
|
||||
}
|
||||
|
||||
static void omap4_keypad_close(struct input_dev *input)
|
||||
{
|
||||
struct omap4_keypad *keypad_data;
|
||||
|
||||
keypad_data = input_get_drvdata(input);
|
||||
disable_irq(keypad_data->irq);
|
||||
omap4_keypad_stop(keypad_data);
|
||||
enable_irq(keypad_data->irq);
|
||||
|
||||
pm_runtime_put_sync(input->dev.parent);
|
||||
|
@ -223,13 +227,37 @@ static int omap4_keypad_parse_dt(struct device *dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int omap4_keypad_check_revision(struct device *dev,
|
||||
struct omap4_keypad *keypad_data)
|
||||
{
|
||||
unsigned int rev;
|
||||
|
||||
rev = __raw_readl(keypad_data->base + OMAP4_KBD_REVISION);
|
||||
rev &= 0x03 << 30;
|
||||
rev >>= 30;
|
||||
switch (rev) {
|
||||
case KBD_REVISION_OMAP4:
|
||||
keypad_data->reg_offset = 0x00;
|
||||
keypad_data->irqreg_offset = 0x00;
|
||||
break;
|
||||
case KBD_REVISION_OMAP5:
|
||||
keypad_data->reg_offset = 0x10;
|
||||
keypad_data->irqreg_offset = 0x0c;
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "Keypad reports unsupported revision %d", rev);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int omap4_keypad_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct omap4_keypad *keypad_data;
|
||||
struct input_dev *input_dev;
|
||||
struct resource *res;
|
||||
unsigned int max_keys;
|
||||
int rev;
|
||||
int irq;
|
||||
int error;
|
||||
|
||||
|
@ -269,41 +297,33 @@ static int omap4_keypad_probe(struct platform_device *pdev)
|
|||
goto err_release_mem;
|
||||
}
|
||||
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
/*
|
||||
* Enable clocks for the keypad module so that we can read
|
||||
* revision register.
|
||||
*/
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
error = pm_runtime_get_sync(&pdev->dev);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n");
|
||||
goto err_unmap;
|
||||
}
|
||||
rev = __raw_readl(keypad_data->base + OMAP4_KBD_REVISION);
|
||||
rev &= 0x03 << 30;
|
||||
rev >>= 30;
|
||||
switch (rev) {
|
||||
case KBD_REVISION_OMAP4:
|
||||
keypad_data->reg_offset = 0x00;
|
||||
keypad_data->irqreg_offset = 0x00;
|
||||
break;
|
||||
case KBD_REVISION_OMAP5:
|
||||
keypad_data->reg_offset = 0x10;
|
||||
keypad_data->irqreg_offset = 0x0c;
|
||||
break;
|
||||
default:
|
||||
dev_err(&pdev->dev,
|
||||
"Keypad reports unsupported revision %d", rev);
|
||||
error = -EINVAL;
|
||||
goto err_pm_put_sync;
|
||||
pm_runtime_put_noidle(&pdev->dev);
|
||||
} else {
|
||||
error = omap4_keypad_check_revision(&pdev->dev,
|
||||
keypad_data);
|
||||
if (!error) {
|
||||
/* Ensure device does not raise interrupts */
|
||||
omap4_keypad_stop(keypad_data);
|
||||
}
|
||||
pm_runtime_put_sync(&pdev->dev);
|
||||
}
|
||||
if (error)
|
||||
goto err_pm_disable;
|
||||
|
||||
/* input device allocation */
|
||||
keypad_data->input = input_dev = input_allocate_device();
|
||||
if (!input_dev) {
|
||||
error = -ENOMEM;
|
||||
goto err_pm_put_sync;
|
||||
goto err_pm_disable;
|
||||
}
|
||||
|
||||
input_dev->name = pdev->name;
|
||||
|
@ -349,28 +369,30 @@ static int omap4_keypad_probe(struct platform_device *pdev)
|
|||
goto err_free_keymap;
|
||||
}
|
||||
|
||||
device_init_wakeup(&pdev->dev, true);
|
||||
pm_runtime_put_sync(&pdev->dev);
|
||||
|
||||
error = input_register_device(keypad_data->input);
|
||||
if (error < 0) {
|
||||
dev_err(&pdev->dev, "failed to register input device\n");
|
||||
goto err_pm_disable;
|
||||
goto err_free_irq;
|
||||
}
|
||||
|
||||
device_init_wakeup(&pdev->dev, true);
|
||||
error = dev_pm_set_wake_irq(&pdev->dev, keypad_data->irq);
|
||||
if (error)
|
||||
dev_warn(&pdev->dev,
|
||||
"failed to set up wakeup irq: %d\n", error);
|
||||
|
||||
platform_set_drvdata(pdev, keypad_data);
|
||||
|
||||
return 0;
|
||||
|
||||
err_pm_disable:
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
err_free_irq:
|
||||
free_irq(keypad_data->irq, keypad_data);
|
||||
err_free_keymap:
|
||||
kfree(keypad_data->keymap);
|
||||
err_free_input:
|
||||
input_free_device(input_dev);
|
||||
err_pm_put_sync:
|
||||
pm_runtime_put_sync(&pdev->dev);
|
||||
err_unmap:
|
||||
err_pm_disable:
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
iounmap(keypad_data->base);
|
||||
err_release_mem:
|
||||
release_mem_region(res->start, resource_size(res));
|
||||
|
@ -384,6 +406,8 @@ static int omap4_keypad_remove(struct platform_device *pdev)
|
|||
struct omap4_keypad *keypad_data = platform_get_drvdata(pdev);
|
||||
struct resource *res;
|
||||
|
||||
dev_pm_clear_wake_irq(&pdev->dev);
|
||||
|
||||
free_irq(keypad_data->irq, keypad_data);
|
||||
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
@ -407,45 +431,11 @@ static const struct of_device_id omap_keypad_dt_match[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(of, omap_keypad_dt_match);
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int omap4_keypad_suspend(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct omap4_keypad *keypad_data = platform_get_drvdata(pdev);
|
||||
int error;
|
||||
|
||||
if (device_may_wakeup(&pdev->dev)) {
|
||||
error = enable_irq_wake(keypad_data->irq);
|
||||
if (!error)
|
||||
keypad_data->irq_wake_enabled = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int omap4_keypad_resume(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct omap4_keypad *keypad_data = platform_get_drvdata(pdev);
|
||||
|
||||
if (device_may_wakeup(&pdev->dev) && keypad_data->irq_wake_enabled) {
|
||||
disable_irq_wake(keypad_data->irq);
|
||||
keypad_data->irq_wake_enabled = false;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(omap4_keypad_pm_ops,
|
||||
omap4_keypad_suspend, omap4_keypad_resume);
|
||||
|
||||
static struct platform_driver omap4_keypad_driver = {
|
||||
.probe = omap4_keypad_probe,
|
||||
.remove = omap4_keypad_remove,
|
||||
.driver = {
|
||||
.name = "omap4-keypad",
|
||||
.pm = &omap4_keypad_pm_ops,
|
||||
.of_match_table = omap_keypad_dt_match,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -76,17 +76,17 @@
|
|||
|
||||
/**
|
||||
* struct pmic8xxx_kp - internal keypad data structure
|
||||
* @num_cols - number of columns of keypad
|
||||
* @num_rows - number of row of keypad
|
||||
* @input - input device pointer for keypad
|
||||
* @regmap - regmap handle
|
||||
* @key_sense_irq - key press/release irq number
|
||||
* @key_stuck_irq - key stuck notification irq number
|
||||
* @keycodes - array to hold the key codes
|
||||
* @dev - parent device pointer
|
||||
* @keystate - present key press/release state
|
||||
* @stuckstate - present state when key stuck irq
|
||||
* @ctrl_reg - control register value
|
||||
* @num_cols: number of columns of keypad
|
||||
* @num_rows: number of row of keypad
|
||||
* @input: input device pointer for keypad
|
||||
* @regmap: regmap handle
|
||||
* @key_sense_irq: key press/release irq number
|
||||
* @key_stuck_irq: key stuck notification irq number
|
||||
* @keycodes: array to hold the key codes
|
||||
* @dev: parent device pointer
|
||||
* @keystate: present key press/release state
|
||||
* @stuckstate: present state when key stuck irq
|
||||
* @ctrl_reg: control register value
|
||||
*/
|
||||
struct pmic8xxx_kp {
|
||||
unsigned int num_rows;
|
||||
|
@ -633,7 +633,7 @@ static int pmic8xxx_kp_suspend(struct device *dev)
|
|||
} else {
|
||||
mutex_lock(&input_dev->mutex);
|
||||
|
||||
if (input_dev->users)
|
||||
if (input_device_enabled(input_dev))
|
||||
pmic8xxx_kp_disable(kp);
|
||||
|
||||
mutex_unlock(&input_dev->mutex);
|
||||
|
@ -653,7 +653,7 @@ static int pmic8xxx_kp_resume(struct device *dev)
|
|||
} else {
|
||||
mutex_lock(&input_dev->mutex);
|
||||
|
||||
if (input_dev->users)
|
||||
if (input_device_enabled(input_dev))
|
||||
pmic8xxx_kp_enable(kp);
|
||||
|
||||
mutex_unlock(&input_dev->mutex);
|
||||
|
|
|
@ -694,7 +694,7 @@ static int pxa27x_keypad_resume(struct device *dev)
|
|||
} else {
|
||||
mutex_lock(&input_dev->mutex);
|
||||
|
||||
if (input_dev->users) {
|
||||
if (input_device_enabled(input_dev)) {
|
||||
/* Enable unit clock */
|
||||
ret = clk_prepare_enable(keypad->clk);
|
||||
if (!ret)
|
||||
|
|
|
@ -146,13 +146,12 @@ static irqreturn_t samsung_keypad_irq(int irq, void *dev_id)
|
|||
{
|
||||
struct samsung_keypad *keypad = dev_id;
|
||||
unsigned int row_state[SAMSUNG_MAX_COLS];
|
||||
unsigned int val;
|
||||
bool key_down;
|
||||
|
||||
pm_runtime_get_sync(&keypad->pdev->dev);
|
||||
|
||||
do {
|
||||
val = readl(keypad->base + SAMSUNG_KEYIFSTSCLR);
|
||||
readl(keypad->base + SAMSUNG_KEYIFSTSCLR);
|
||||
/* Clear interrupt. */
|
||||
writel(~0x0, keypad->base + SAMSUNG_KEYIFSTSCLR);
|
||||
|
||||
|
@ -537,7 +536,7 @@ static int samsung_keypad_suspend(struct device *dev)
|
|||
|
||||
mutex_lock(&input_dev->mutex);
|
||||
|
||||
if (input_dev->users)
|
||||
if (input_device_enabled(input_dev))
|
||||
samsung_keypad_stop(keypad);
|
||||
|
||||
samsung_keypad_toggle_wakeup(keypad, true);
|
||||
|
@ -557,7 +556,7 @@ static int samsung_keypad_resume(struct device *dev)
|
|||
|
||||
samsung_keypad_toggle_wakeup(keypad, false);
|
||||
|
||||
if (input_dev->users)
|
||||
if (input_device_enabled(input_dev))
|
||||
samsung_keypad_start(keypad);
|
||||
|
||||
mutex_unlock(&input_dev->mutex);
|
||||
|
|
|
@ -318,7 +318,7 @@ static int __maybe_unused spear_kbd_suspend(struct device *dev)
|
|||
writel_relaxed(val, kbd->io_base + MODE_CTL_REG);
|
||||
|
||||
} else {
|
||||
if (input_dev->users) {
|
||||
if (input_device_enabled(input_dev)) {
|
||||
writel_relaxed(mode_ctl_reg & ~MODE_CTL_START_SCAN,
|
||||
kbd->io_base + MODE_CTL_REG);
|
||||
clk_disable(kbd->clk);
|
||||
|
@ -326,7 +326,7 @@ static int __maybe_unused spear_kbd_suspend(struct device *dev)
|
|||
}
|
||||
|
||||
/* store current configuration */
|
||||
if (input_dev->users)
|
||||
if (input_device_enabled(input_dev))
|
||||
kbd->mode_ctl_reg = mode_ctl_reg;
|
||||
|
||||
/* restore previous clk state */
|
||||
|
@ -351,12 +351,12 @@ static int __maybe_unused spear_kbd_resume(struct device *dev)
|
|||
disable_irq_wake(kbd->irq);
|
||||
}
|
||||
} else {
|
||||
if (input_dev->users)
|
||||
if (input_device_enabled(input_dev))
|
||||
clk_enable(kbd->clk);
|
||||
}
|
||||
|
||||
/* restore current configuration */
|
||||
if (input_dev->users)
|
||||
if (input_device_enabled(input_dev))
|
||||
writel_relaxed(kbd->mode_ctl_reg, kbd->io_base + MODE_CTL_REG);
|
||||
|
||||
mutex_unlock(&input_dev->mutex);
|
||||
|
|
|
@ -221,7 +221,7 @@ static int keyscan_suspend(struct device *dev)
|
|||
|
||||
if (device_may_wakeup(dev))
|
||||
enable_irq_wake(keypad->irq);
|
||||
else if (input->users)
|
||||
else if (input_device_enabled(input))
|
||||
keyscan_stop(keypad);
|
||||
|
||||
mutex_unlock(&input->mutex);
|
||||
|
@ -239,7 +239,7 @@ static int keyscan_resume(struct device *dev)
|
|||
|
||||
if (device_may_wakeup(dev))
|
||||
disable_irq_wake(keypad->irq);
|
||||
else if (input->users)
|
||||
else if (input_device_enabled(input))
|
||||
retval = keyscan_start(keypad);
|
||||
|
||||
mutex_unlock(&input->mutex);
|
||||
|
|
|
@ -756,7 +756,7 @@ static int tegra_kbc_suspend(struct device *dev)
|
|||
enable_irq(kbc->irq);
|
||||
enable_irq_wake(kbc->irq);
|
||||
} else {
|
||||
if (kbc->idev->users)
|
||||
if (input_device_enabled(kbc->idev))
|
||||
tegra_kbc_stop(kbc);
|
||||
}
|
||||
mutex_unlock(&kbc->idev->mutex);
|
||||
|
@ -796,7 +796,7 @@ static int tegra_kbc_resume(struct device *dev)
|
|||
input_sync(kbc->idev);
|
||||
}
|
||||
} else {
|
||||
if (kbc->idev->users)
|
||||
if (input_device_enabled(kbc->idev))
|
||||
err = tegra_kbc_start(kbc);
|
||||
}
|
||||
mutex_unlock(&kbc->idev->mutex);
|
||||
|
|
|
@ -48,7 +48,7 @@ struct tm2_touchkey_data {
|
|||
struct input_dev *input_dev;
|
||||
struct led_classdev led_dev;
|
||||
struct regulator *vdd;
|
||||
struct regulator_bulk_data regulators[2];
|
||||
struct regulator_bulk_data regulators[3];
|
||||
const struct touchkey_variant *variant;
|
||||
u32 keycodes[4];
|
||||
int num_keycodes;
|
||||
|
@ -204,6 +204,7 @@ static int tm2_touchkey_probe(struct i2c_client *client,
|
|||
|
||||
touchkey->regulators[0].supply = "vcc";
|
||||
touchkey->regulators[1].supply = "vdd";
|
||||
touchkey->regulators[2].supply = "vddio";
|
||||
error = devm_regulator_bulk_get(&client->dev,
|
||||
ARRAY_SIZE(touchkey->regulators),
|
||||
touchkey->regulators);
|
||||
|
|
|
@ -73,6 +73,17 @@ config INPUT_AD714X_SPI
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called ad714x-spi.
|
||||
|
||||
config INPUT_ARIEL_PWRBUTTON
|
||||
tristate "Dell Wyse 3020 Power Button Driver"
|
||||
depends on SPI
|
||||
depends on MACH_MMP3_DT || COMPILE_TEST
|
||||
help
|
||||
Say Y to enable support for reporting power button status on
|
||||
on Dell Wyse 3020 ("Ariel") thin client.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called ariel-pwrbutton.
|
||||
|
||||
config INPUT_ARIZONA_HAPTICS
|
||||
tristate "Arizona haptics support"
|
||||
depends on MFD_ARIZONA && SND_SOC
|
||||
|
@ -609,6 +620,18 @@ config INPUT_RB532_BUTTON
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called rb532_button.
|
||||
|
||||
config INPUT_DA7280_HAPTICS
|
||||
tristate "Dialog Semiconductor DA7280 haptics support"
|
||||
depends on INPUT && I2C
|
||||
select REGMAP_I2C
|
||||
help
|
||||
Say Y to enable support for the Dialog DA7280 haptics driver.
|
||||
The haptics can be controlled by PWM or GPIO
|
||||
with I2C communication.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called da7280.
|
||||
|
||||
config INPUT_DA9052_ONKEY
|
||||
tristate "Dialog DA9052/DA9053 Onkey"
|
||||
depends on PMIC_DA9052
|
||||
|
|
|
@ -15,6 +15,7 @@ obj-$(CONFIG_INPUT_ADXL34X) += adxl34x.o
|
|||
obj-$(CONFIG_INPUT_ADXL34X_I2C) += adxl34x-i2c.o
|
||||
obj-$(CONFIG_INPUT_ADXL34X_SPI) += adxl34x-spi.o
|
||||
obj-$(CONFIG_INPUT_APANEL) += apanel.o
|
||||
obj-$(CONFIG_INPUT_ARIEL_PWRBUTTON) += ariel-pwrbutton.o
|
||||
obj-$(CONFIG_INPUT_ARIZONA_HAPTICS) += arizona-haptics.o
|
||||
obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o
|
||||
obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o
|
||||
|
@ -25,6 +26,7 @@ obj-$(CONFIG_INPUT_CMA3000) += cma3000_d0x.o
|
|||
obj-$(CONFIG_INPUT_CMA3000_I2C) += cma3000_d0x_i2c.o
|
||||
obj-$(CONFIG_INPUT_COBALT_BTNS) += cobalt_btns.o
|
||||
obj-$(CONFIG_INPUT_CPCAP_PWRBUTTON) += cpcap-pwrbutton.o
|
||||
obj-$(CONFIG_INPUT_DA7280_HAPTICS) += da7280.o
|
||||
obj-$(CONFIG_INPUT_DA9052_ONKEY) += da9052_onkey.o
|
||||
obj-$(CONFIG_INPUT_DA9055_ONKEY) += da9055_onkey.o
|
||||
obj-$(CONFIG_INPUT_DA9063_ONKEY) += da9063_onkey.o
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
/**
|
||||
* struct ab8500_ponkey - ab8500 ponkey information
|
||||
* @input_dev: pointer to input device
|
||||
* @idev: pointer to input device
|
||||
* @ab8500: ab8500 parent
|
||||
* @irq_dbf: irq number for falling transition
|
||||
* @irq_dbr: irq number for rising transition
|
||||
|
|
|
@ -0,0 +1,169 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0-or-later
|
||||
/*
|
||||
* Dell Wyse 3020 a.k.a. "Ariel" Power Button Driver
|
||||
*
|
||||
* Copyright (C) 2020 Lubomir Rintel
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
||||
#define RESP_COUNTER(response) (response.header & 0x3)
|
||||
#define RESP_SIZE(response) ((response.header >> 2) & 0x3)
|
||||
#define RESP_TYPE(response) ((response.header >> 4) & 0xf)
|
||||
|
||||
struct ec_input_response {
|
||||
u8 reserved;
|
||||
u8 header;
|
||||
u8 data[3];
|
||||
} __packed;
|
||||
|
||||
struct ariel_pwrbutton {
|
||||
struct spi_device *client;
|
||||
struct input_dev *input;
|
||||
u8 msg_counter;
|
||||
};
|
||||
|
||||
static int ec_input_read(struct ariel_pwrbutton *priv,
|
||||
struct ec_input_response *response)
|
||||
{
|
||||
u8 read_request[] = { 0x00, 0x5a, 0xa5, 0x00, 0x00 };
|
||||
struct spi_device *spi = priv->client;
|
||||
struct spi_transfer t = {
|
||||
.tx_buf = read_request,
|
||||
.rx_buf = response,
|
||||
.len = sizeof(read_request),
|
||||
};
|
||||
|
||||
compiletime_assert(sizeof(read_request) == sizeof(*response),
|
||||
"SPI xfer request/response size mismatch");
|
||||
|
||||
return spi_sync_transfer(spi, &t, 1);
|
||||
}
|
||||
|
||||
static irqreturn_t ec_input_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct ariel_pwrbutton *priv = dev_id;
|
||||
struct spi_device *spi = priv->client;
|
||||
struct ec_input_response response;
|
||||
int error;
|
||||
int i;
|
||||
|
||||
error = ec_input_read(priv, &response);
|
||||
if (error < 0) {
|
||||
dev_err(&spi->dev, "EC read failed: %d\n", error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (priv->msg_counter == RESP_COUNTER(response)) {
|
||||
dev_warn(&spi->dev, "No new data to read?\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
priv->msg_counter = RESP_COUNTER(response);
|
||||
|
||||
if (RESP_TYPE(response) != 0x3 && RESP_TYPE(response) != 0xc) {
|
||||
dev_dbg(&spi->dev, "Ignoring message that's not kbd data\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < RESP_SIZE(response); i++) {
|
||||
switch (response.data[i]) {
|
||||
case 0x74:
|
||||
input_report_key(priv->input, KEY_POWER, 1);
|
||||
input_sync(priv->input);
|
||||
break;
|
||||
case 0xf4:
|
||||
input_report_key(priv->input, KEY_POWER, 0);
|
||||
input_sync(priv->input);
|
||||
break;
|
||||
default:
|
||||
dev_dbg(&spi->dev, "Unknown scan code: %02x\n",
|
||||
response.data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int ariel_pwrbutton_probe(struct spi_device *spi)
|
||||
{
|
||||
struct ec_input_response response;
|
||||
struct ariel_pwrbutton *priv;
|
||||
int error;
|
||||
|
||||
if (!spi->irq) {
|
||||
dev_err(&spi->dev, "Missing IRQ.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
priv = devm_kzalloc(&spi->dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->client = spi;
|
||||
spi_set_drvdata(spi, priv);
|
||||
|
||||
priv->input = devm_input_allocate_device(&spi->dev);
|
||||
if (!priv->input)
|
||||
return -ENOMEM;
|
||||
priv->input->name = "Power Button";
|
||||
priv->input->dev.parent = &spi->dev;
|
||||
input_set_capability(priv->input, EV_KEY, KEY_POWER);
|
||||
error = input_register_device(priv->input);
|
||||
if (error) {
|
||||
dev_err(&spi->dev, "error registering input device: %d\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
error = ec_input_read(priv, &response);
|
||||
if (error < 0) {
|
||||
dev_err(&spi->dev, "EC read failed: %d\n", error);
|
||||
return error;
|
||||
}
|
||||
priv->msg_counter = RESP_COUNTER(response);
|
||||
|
||||
error = devm_request_threaded_irq(&spi->dev, spi->irq, NULL,
|
||||
ec_input_interrupt,
|
||||
IRQF_ONESHOT,
|
||||
"Ariel EC Input", priv);
|
||||
|
||||
if (error) {
|
||||
dev_err(&spi->dev, "Failed to request IRQ %d: %d\n",
|
||||
spi->irq, error);
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id ariel_pwrbutton_of_match[] = {
|
||||
{ .compatible = "dell,wyse-ariel-ec-input" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ariel_pwrbutton_of_match);
|
||||
|
||||
static const struct spi_device_id ariel_pwrbutton_id_table[] = {
|
||||
{ "wyse-ariel-ec-input", 0 },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, ariel_pwrbutton_id_table);
|
||||
|
||||
static struct spi_driver ariel_pwrbutton_driver = {
|
||||
.driver = {
|
||||
.name = "dell-wyse-ariel-ec-input",
|
||||
.of_match_table = ariel_pwrbutton_of_match,
|
||||
},
|
||||
.probe = ariel_pwrbutton_probe,
|
||||
};
|
||||
module_spi_driver(ariel_pwrbutton_driver);
|
||||
|
||||
MODULE_AUTHOR("Lubomir Rintel <lkundrak@v3.sk>");
|
||||
MODULE_DESCRIPTION("Dell Wyse 3020 Power Button Input Driver");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -167,17 +167,17 @@
|
|||
|
||||
/**
|
||||
* struct drv260x_data -
|
||||
* @input_dev - Pointer to the input device
|
||||
* @client - Pointer to the I2C client
|
||||
* @regmap - Register map of the device
|
||||
* @work - Work item used to off load the enable/disable of the vibration
|
||||
* @enable_gpio - Pointer to the gpio used for enable/disabling
|
||||
* @regulator - Pointer to the regulator for the IC
|
||||
* @magnitude - Magnitude of the vibration event
|
||||
* @mode - The operating mode of the IC (LRA_NO_CAL, ERM or LRA)
|
||||
* @library - The vibration library to be used
|
||||
* @rated_voltage - The rated_voltage of the actuator
|
||||
* @overdriver_voltage - The over drive voltage of the actuator
|
||||
* @input_dev: Pointer to the input device
|
||||
* @client: Pointer to the I2C client
|
||||
* @regmap: Register map of the device
|
||||
* @work: Work item used to off load the enable/disable of the vibration
|
||||
* @enable_gpio: Pointer to the gpio used for enable/disabling
|
||||
* @regulator: Pointer to the regulator for the IC
|
||||
* @magnitude: Magnitude of the vibration event
|
||||
* @mode: The operating mode of the IC (LRA_NO_CAL, ERM or LRA)
|
||||
* @library: The vibration library to be used
|
||||
* @rated_voltage: The rated_voltage of the actuator
|
||||
* @overdrive_voltage: The over drive voltage of the actuator
|
||||
**/
|
||||
struct drv260x_data {
|
||||
struct input_dev *input_dev;
|
||||
|
@ -234,12 +234,12 @@ static const struct reg_default drv260x_reg_defs[] = {
|
|||
#define DRV260X_DEF_RATED_VOLT 0x90
|
||||
#define DRV260X_DEF_OD_CLAMP_VOLT 0x90
|
||||
|
||||
/**
|
||||
/*
|
||||
* Rated and Overdriver Voltages:
|
||||
* Calculated using the formula r = v * 255 / 5.6
|
||||
* where r is what will be written to the register
|
||||
* and v is the rated or overdriver voltage of the actuator
|
||||
**/
|
||||
*/
|
||||
static int drv260x_calculate_voltage(unsigned int voltage)
|
||||
{
|
||||
return (voltage * 255 / 5600);
|
||||
|
@ -580,7 +580,7 @@ static int __maybe_unused drv260x_suspend(struct device *dev)
|
|||
|
||||
mutex_lock(&haptics->input_dev->mutex);
|
||||
|
||||
if (haptics->input_dev->users) {
|
||||
if (input_device_enabled(haptics->input_dev)) {
|
||||
ret = regmap_update_bits(haptics->regmap,
|
||||
DRV260X_MODE,
|
||||
DRV260X_STANDBY_MASK,
|
||||
|
@ -612,7 +612,7 @@ static int __maybe_unused drv260x_resume(struct device *dev)
|
|||
|
||||
mutex_lock(&haptics->input_dev->mutex);
|
||||
|
||||
if (haptics->input_dev->users) {
|
||||
if (input_device_enabled(haptics->input_dev)) {
|
||||
ret = regulator_enable(haptics->regulator);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to enable regulator\n");
|
||||
|
|
|
@ -44,11 +44,11 @@
|
|||
|
||||
/**
|
||||
* struct drv2665_data -
|
||||
* @input_dev - Pointer to the input device
|
||||
* @client - Pointer to the I2C client
|
||||
* @regmap - Register map of the device
|
||||
* @work - Work item used to off load the enable/disable of the vibration
|
||||
* @regulator - Pointer to the regulator for the IC
|
||||
* @input_dev: Pointer to the input device
|
||||
* @client: Pointer to the I2C client
|
||||
* @regmap: Register map of the device
|
||||
* @work: Work item used to off load the enable/disable of the vibration
|
||||
* @regulator: Pointer to the regulator for the IC
|
||||
*/
|
||||
struct drv2665_data {
|
||||
struct input_dev *input_dev;
|
||||
|
@ -230,7 +230,7 @@ static int __maybe_unused drv2665_suspend(struct device *dev)
|
|||
|
||||
mutex_lock(&haptics->input_dev->mutex);
|
||||
|
||||
if (haptics->input_dev->users) {
|
||||
if (input_device_enabled(haptics->input_dev)) {
|
||||
ret = regmap_update_bits(haptics->regmap, DRV2665_CTRL_2,
|
||||
DRV2665_STANDBY, DRV2665_STANDBY);
|
||||
if (ret) {
|
||||
|
@ -259,7 +259,7 @@ static int __maybe_unused drv2665_resume(struct device *dev)
|
|||
|
||||
mutex_lock(&haptics->input_dev->mutex);
|
||||
|
||||
if (haptics->input_dev->users) {
|
||||
if (input_device_enabled(haptics->input_dev)) {
|
||||
ret = regulator_enable(haptics->regulator);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to enable regulator\n");
|
||||
|
|
|
@ -90,12 +90,14 @@
|
|||
|
||||
/**
|
||||
* struct drv2667_data -
|
||||
* @input_dev - Pointer to the input device
|
||||
* @client - Pointer to the I2C client
|
||||
* @regmap - Register map of the device
|
||||
* @work - Work item used to off load the enable/disable of the vibration
|
||||
* @regulator - Pointer to the regulator for the IC
|
||||
* @magnitude - Magnitude of the vibration event
|
||||
* @input_dev: Pointer to the input device
|
||||
* @client: Pointer to the I2C client
|
||||
* @regmap: Register map of the device
|
||||
* @work: Work item used to off load the enable/disable of the vibration
|
||||
* @regulator: Pointer to the regulator for the IC
|
||||
* @page: Page number
|
||||
* @magnitude: Magnitude of the vibration event
|
||||
* @frequency: Frequency of the vibration event
|
||||
**/
|
||||
struct drv2667_data {
|
||||
struct input_dev *input_dev;
|
||||
|
@ -405,7 +407,7 @@ static int __maybe_unused drv2667_suspend(struct device *dev)
|
|||
|
||||
mutex_lock(&haptics->input_dev->mutex);
|
||||
|
||||
if (haptics->input_dev->users) {
|
||||
if (input_device_enabled(haptics->input_dev)) {
|
||||
ret = regmap_update_bits(haptics->regmap, DRV2667_CTRL_2,
|
||||
DRV2667_STANDBY, DRV2667_STANDBY);
|
||||
if (ret) {
|
||||
|
@ -434,7 +436,7 @@ static int __maybe_unused drv2667_resume(struct device *dev)
|
|||
|
||||
mutex_lock(&haptics->input_dev->mutex);
|
||||
|
||||
if (haptics->input_dev->users) {
|
||||
if (input_device_enabled(haptics->input_dev)) {
|
||||
ret = regulator_enable(haptics->regulator);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to enable regulator\n");
|
||||
|
|
|
@ -97,7 +97,7 @@ static int ixp4xx_spkr_probe(struct platform_device *dev)
|
|||
|
||||
input_set_drvdata(input_dev, (void *) dev->id);
|
||||
|
||||
input_dev->name = "ixp4xx beeper",
|
||||
input_dev->name = "ixp4xx beeper";
|
||||
input_dev->phys = "ixp4xx/gpio";
|
||||
input_dev->id.bustype = BUS_HOST;
|
||||
input_dev->id.vendor = 0x001f;
|
||||
|
|
|
@ -503,7 +503,7 @@ static int __maybe_unused kxtj9_suspend(struct device *dev)
|
|||
|
||||
mutex_lock(&input_dev->mutex);
|
||||
|
||||
if (input_dev->users)
|
||||
if (input_device_enabled(input_dev))
|
||||
kxtj9_disable(tj9);
|
||||
|
||||
mutex_unlock(&input_dev->mutex);
|
||||
|
@ -518,7 +518,7 @@ static int __maybe_unused kxtj9_resume(struct device *dev)
|
|||
|
||||
mutex_lock(&input_dev->mutex);
|
||||
|
||||
if (input_dev->users)
|
||||
if (input_device_enabled(input_dev))
|
||||
kxtj9_enable(tj9);
|
||||
|
||||
mutex_unlock(&input_dev->mutex);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/**
|
||||
/*
|
||||
* Copyright (C) 2011 Philippe Rétornaz
|
||||
*
|
||||
* Based on twl4030-pwrbutton driver by:
|
||||
|
|
|
@ -33,6 +33,7 @@ static int pcspkr_event(struct input_dev *dev, unsigned int type,
|
|||
case SND_BELL:
|
||||
if (value)
|
||||
value = 1000;
|
||||
break;
|
||||
case SND_TONE:
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -3,45 +3,82 @@
|
|||
* Copyright (C) 2018 Spreadtrum Communications Inc.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#define CUR_DRV_CAL_SEL GENMASK(13, 12)
|
||||
#define SLP_LDOVIBR_PD_EN BIT(9)
|
||||
#define LDO_VIBR_PD BIT(8)
|
||||
#define CUR_DRV_CAL_SEL GENMASK(13, 12)
|
||||
#define SLP_LDOVIBR_PD_EN BIT(9)
|
||||
#define LDO_VIBR_PD BIT(8)
|
||||
#define SC2730_CUR_DRV_CAL_SEL 0
|
||||
#define SC2730_SLP_LDOVIBR_PD_EN BIT(14)
|
||||
#define SC2730_LDO_VIBR_PD BIT(13)
|
||||
|
||||
struct sc27xx_vibra_data {
|
||||
u32 cur_drv_cal_sel;
|
||||
u32 slp_pd_en;
|
||||
u32 ldo_pd;
|
||||
};
|
||||
|
||||
struct vibra_info {
|
||||
struct input_dev *input_dev;
|
||||
struct work_struct play_work;
|
||||
struct regmap *regmap;
|
||||
const struct sc27xx_vibra_data *data;
|
||||
u32 base;
|
||||
u32 strength;
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
static const struct sc27xx_vibra_data sc2731_data = {
|
||||
.cur_drv_cal_sel = CUR_DRV_CAL_SEL,
|
||||
.slp_pd_en = SLP_LDOVIBR_PD_EN,
|
||||
.ldo_pd = LDO_VIBR_PD,
|
||||
};
|
||||
|
||||
static const struct sc27xx_vibra_data sc2730_data = {
|
||||
.cur_drv_cal_sel = SC2730_CUR_DRV_CAL_SEL,
|
||||
.slp_pd_en = SC2730_SLP_LDOVIBR_PD_EN,
|
||||
.ldo_pd = SC2730_LDO_VIBR_PD,
|
||||
};
|
||||
|
||||
static const struct sc27xx_vibra_data sc2721_data = {
|
||||
.cur_drv_cal_sel = CUR_DRV_CAL_SEL,
|
||||
.slp_pd_en = SLP_LDOVIBR_PD_EN,
|
||||
.ldo_pd = LDO_VIBR_PD,
|
||||
};
|
||||
|
||||
static void sc27xx_vibra_set(struct vibra_info *info, bool on)
|
||||
{
|
||||
const struct sc27xx_vibra_data *data = info->data;
|
||||
if (on) {
|
||||
regmap_update_bits(info->regmap, info->base, LDO_VIBR_PD, 0);
|
||||
regmap_update_bits(info->regmap, info->base, data->ldo_pd, 0);
|
||||
regmap_update_bits(info->regmap, info->base,
|
||||
SLP_LDOVIBR_PD_EN, 0);
|
||||
data->slp_pd_en, 0);
|
||||
info->enabled = true;
|
||||
} else {
|
||||
regmap_update_bits(info->regmap, info->base, LDO_VIBR_PD,
|
||||
LDO_VIBR_PD);
|
||||
regmap_update_bits(info->regmap, info->base, data->ldo_pd,
|
||||
data->ldo_pd);
|
||||
regmap_update_bits(info->regmap, info->base,
|
||||
SLP_LDOVIBR_PD_EN, SLP_LDOVIBR_PD_EN);
|
||||
data->slp_pd_en, data->slp_pd_en);
|
||||
info->enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
static int sc27xx_vibra_hw_init(struct vibra_info *info)
|
||||
{
|
||||
return regmap_update_bits(info->regmap, info->base, CUR_DRV_CAL_SEL, 0);
|
||||
const struct sc27xx_vibra_data *data = info->data;
|
||||
|
||||
if (!data->cur_drv_cal_sel)
|
||||
return 0;
|
||||
|
||||
return regmap_update_bits(info->regmap, info->base,
|
||||
data->cur_drv_cal_sel, 0);
|
||||
}
|
||||
|
||||
static void sc27xx_vibra_play_work(struct work_struct *work)
|
||||
|
@ -78,8 +115,15 @@ static void sc27xx_vibra_close(struct input_dev *input)
|
|||
static int sc27xx_vibra_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct vibra_info *info;
|
||||
const struct sc27xx_vibra_data *data;
|
||||
int error;
|
||||
|
||||
data = device_get_match_data(&pdev->dev);
|
||||
if (!data) {
|
||||
dev_err(&pdev->dev, "no matching driver data found\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
|
||||
if (!info)
|
||||
return -ENOMEM;
|
||||
|
@ -105,6 +149,7 @@ static int sc27xx_vibra_probe(struct platform_device *pdev)
|
|||
info->input_dev->name = "sc27xx:vibrator";
|
||||
info->input_dev->id.version = 0;
|
||||
info->input_dev->close = sc27xx_vibra_close;
|
||||
info->data = data;
|
||||
|
||||
input_set_drvdata(info->input_dev, info);
|
||||
input_set_capability(info->input_dev, EV_FF, FF_RUMBLE);
|
||||
|
@ -134,7 +179,9 @@ static int sc27xx_vibra_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
static const struct of_device_id sc27xx_vibra_of_match[] = {
|
||||
{ .compatible = "sprd,sc2731-vibrator", },
|
||||
{ .compatible = "sprd,sc2721-vibrator", .data = &sc2721_data },
|
||||
{ .compatible = "sprd,sc2730-vibrator", .data = &sc2730_data },
|
||||
{ .compatible = "sprd,sc2731-vibrator", .data = &sc2731_data },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, sc27xx_vibra_of_match);
|
||||
|
|
|
@ -181,7 +181,7 @@ static int __maybe_unused sirfsoc_pwrc_resume(struct device *dev)
|
|||
* if users touch X_ONKEY_B, see arch/arm/mach-prima2/pm.c
|
||||
*/
|
||||
mutex_lock(&input->mutex);
|
||||
if (input->users)
|
||||
if (input_device_enabled(input))
|
||||
sirfsoc_pwrc_toggle_interrupts(pwrcdrv, true);
|
||||
mutex_unlock(&input->mutex);
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/**
|
||||
/*
|
||||
* wm831x-on.c - WM831X ON pin driver
|
||||
*
|
||||
* Copyright (C) 2009 Wolfson Microelectronics plc
|
||||
|
|
|
@ -372,7 +372,7 @@ config MOUSE_VSXXXAA
|
|||
select SERIO
|
||||
help
|
||||
Say Y (or M) if you want to use a DEC VSXXX-AA (hockey
|
||||
puck) or a VSXXX-GA (rectangular) mouse. Theses mice are
|
||||
puck) or a VSXXX-GA (rectangular) mouse. These mice are
|
||||
typically used on DECstations or VAXstations, but can also
|
||||
be used on any box capable of RS232 (with some adaptor
|
||||
described in the source file). This driver also works with the
|
||||
|
|
|
@ -119,7 +119,7 @@ static ssize_t cyapa_i2c_read(struct cyapa *cyapa, u8 reg, size_t len,
|
|||
/**
|
||||
* cyapa_i2c_write - Execute i2c block data write operation
|
||||
* @cyapa: Handle to this driver
|
||||
* @ret: Offset of the data to written in the register map
|
||||
* @reg: Offset of the data to written in the register map
|
||||
* @len: number of bytes to write
|
||||
* @values: Data to be written
|
||||
*
|
||||
|
@ -526,7 +526,7 @@ static void cyapa_enable_irq_for_cmd(struct cyapa *cyapa)
|
|||
{
|
||||
struct input_dev *input = cyapa->input;
|
||||
|
||||
if (!input || !input->users) {
|
||||
if (!input || !input_device_enabled(input)) {
|
||||
/*
|
||||
* When input is NULL, TP must be in deep sleep mode.
|
||||
* In this mode, later non-power I2C command will always failed
|
||||
|
@ -546,7 +546,7 @@ static void cyapa_disable_irq_for_cmd(struct cyapa *cyapa)
|
|||
{
|
||||
struct input_dev *input = cyapa->input;
|
||||
|
||||
if (!input || !input->users) {
|
||||
if (!input || !input_device_enabled(input)) {
|
||||
if (cyapa->gen >= CYAPA_GEN5)
|
||||
disable_irq(cyapa->client->irq);
|
||||
if (!input || cyapa->operational)
|
||||
|
@ -652,7 +652,7 @@ static int cyapa_reinitialize(struct cyapa *cyapa)
|
|||
}
|
||||
|
||||
out:
|
||||
if (!input || !input->users) {
|
||||
if (!input || !input_device_enabled(input)) {
|
||||
/* Reset to power OFF state to save power when no user open. */
|
||||
if (cyapa->operational)
|
||||
cyapa->ops->set_power_mode(cyapa,
|
||||
|
@ -840,10 +840,9 @@ static int cyapa_prepare_wakeup_controls(struct cyapa *cyapa)
|
|||
return error;
|
||||
}
|
||||
|
||||
error = devm_add_action(dev,
|
||||
error = devm_add_action_or_reset(dev,
|
||||
cyapa_remove_power_wakeup_group, cyapa);
|
||||
if (error) {
|
||||
cyapa_remove_power_wakeup_group(cyapa);
|
||||
dev_err(dev, "failed to add power cleanup action: %d\n",
|
||||
error);
|
||||
return error;
|
||||
|
@ -957,9 +956,9 @@ static int cyapa_start_runtime(struct cyapa *cyapa)
|
|||
return error;
|
||||
}
|
||||
|
||||
error = devm_add_action(dev, cyapa_remove_power_runtime_group, cyapa);
|
||||
error = devm_add_action_or_reset(dev, cyapa_remove_power_runtime_group,
|
||||
cyapa);
|
||||
if (error) {
|
||||
cyapa_remove_power_runtime_group(cyapa);
|
||||
dev_err(dev,
|
||||
"failed to add power runtime cleanup action: %d\n",
|
||||
error);
|
||||
|
@ -1291,9 +1290,8 @@ static int cyapa_probe(struct i2c_client *client,
|
|||
return error;
|
||||
}
|
||||
|
||||
error = devm_add_action(dev, cyapa_disable_regulator, cyapa);
|
||||
error = devm_add_action_or_reset(dev, cyapa_disable_regulator, cyapa);
|
||||
if (error) {
|
||||
cyapa_disable_regulator(cyapa);
|
||||
dev_err(dev, "failed to add disable regulator action: %d\n",
|
||||
error);
|
||||
return error;
|
||||
|
|
|
@ -952,7 +952,8 @@ static int cyapa_gen3_set_power_mode(struct cyapa *cyapa, u8 power_mode,
|
|||
* doing so before issuing the next command may result in errors
|
||||
* depending on the command's content.
|
||||
*/
|
||||
if (cyapa->operational && input && input->users &&
|
||||
if (cyapa->operational &&
|
||||
input && input_device_enabled(input) &&
|
||||
(pm_stage == CYAPA_PM_RUNTIME_SUSPEND ||
|
||||
pm_stage == CYAPA_PM_RUNTIME_RESUME)) {
|
||||
/* Try to polling in 120Hz, read may fail, just ignore it. */
|
||||
|
|
|
@ -385,7 +385,7 @@ ssize_t cyapa_i2c_pip_read(struct cyapa *cyapa, u8 *buf, size_t size)
|
|||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* Return a negative errno code else zero on success.
|
||||
*/
|
||||
ssize_t cyapa_i2c_pip_write(struct cyapa *cyapa, u8 *buf, size_t size)
|
||||
|
@ -435,7 +435,7 @@ static enum cyapa_pm_stage cyapa_get_pip_pm_state(struct cyapa *cyapa)
|
|||
return pm_stage;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* This function is aimed to dump all not read data in Gen5 trackpad
|
||||
* before send any command, otherwise, the interrupt line will be blocked.
|
||||
*/
|
||||
|
@ -518,7 +518,8 @@ int cyapa_empty_pip_output_data(struct cyapa *cyapa,
|
|||
*len = length;
|
||||
/* Response found, success. */
|
||||
return 0;
|
||||
} else if (cyapa->operational && input && input->users &&
|
||||
} else if (cyapa->operational &&
|
||||
input && input_device_enabled(input) &&
|
||||
(pm_stage == CYAPA_PM_RUNTIME_RESUME ||
|
||||
pm_stage == CYAPA_PM_RUNTIME_SUSPEND)) {
|
||||
/* Parse the data and report it if it's valid. */
|
||||
|
|
|
@ -573,7 +573,7 @@ static int cyapa_pip_retrieve_data_structure(struct cyapa *cyapa,
|
|||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR, &cmd.head.addr);
|
||||
put_unaligned_le16(sizeof(cmd), &cmd.head.length - 2);
|
||||
put_unaligned_le16(sizeof(cmd) - 2, &cmd.head.length);
|
||||
cmd.head.report_id = PIP_APP_CMD_REPORT_ID;
|
||||
cmd.head.cmd_code = PIP_RETRIEVE_DATA_STRUCTURE;
|
||||
put_unaligned_le16(read_offset, &cmd.read_offset);
|
||||
|
|
|
@ -28,6 +28,22 @@
|
|||
|
||||
#define ETP_FEATURE_REPORT_MK BIT(0)
|
||||
|
||||
#define ETP_REPORT_ID 0x5D
|
||||
#define ETP_TP_REPORT_ID 0x5E
|
||||
#define ETP_TP_REPORT_ID2 0x5F
|
||||
#define ETP_REPORT_ID2 0x60 /* High precision report */
|
||||
|
||||
#define ETP_REPORT_ID_OFFSET 2
|
||||
#define ETP_TOUCH_INFO_OFFSET 3
|
||||
#define ETP_FINGER_DATA_OFFSET 4
|
||||
#define ETP_HOVER_INFO_OFFSET 30
|
||||
#define ETP_MK_DATA_OFFSET 33 /* For high precision reports */
|
||||
|
||||
#define ETP_MAX_REPORT_LEN 39
|
||||
|
||||
#define ETP_MAX_FINGERS 5
|
||||
#define ETP_FINGER_DATA_LEN 5
|
||||
|
||||
/* IAP Firmware handling */
|
||||
#define ETP_PRODUCT_ID_FORMAT_STRING "%d.0"
|
||||
#define ETP_FW_NAME "elan_i2c_" ETP_PRODUCT_ID_FORMAT_STRING ".bin"
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
#include <linux/completion.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/input/elan-i2c-ids.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
|
@ -47,18 +46,6 @@
|
|||
#define ETP_FINGER_WIDTH 15
|
||||
#define ETP_RETRY_COUNT 3
|
||||
|
||||
#define ETP_MAX_FINGERS 5
|
||||
#define ETP_FINGER_DATA_LEN 5
|
||||
#define ETP_REPORT_ID 0x5D
|
||||
#define ETP_REPORT_ID2 0x60 /* High precision report */
|
||||
#define ETP_TP_REPORT_ID 0x5E
|
||||
#define ETP_REPORT_ID_OFFSET 2
|
||||
#define ETP_TOUCH_INFO_OFFSET 3
|
||||
#define ETP_FINGER_DATA_OFFSET 4
|
||||
#define ETP_HOVER_INFO_OFFSET 30
|
||||
#define ETP_MK_DATA_OFFSET 33 /* For high precision reports */
|
||||
#define ETP_MAX_REPORT_LEN 39
|
||||
|
||||
/* The main device structure */
|
||||
struct elan_tp_data {
|
||||
struct i2c_client *client;
|
||||
|
@ -1076,6 +1063,7 @@ static irqreturn_t elan_isr(int irq, void *dev_id)
|
|||
elan_report_absolute(data, report, true);
|
||||
break;
|
||||
case ETP_TP_REPORT_ID:
|
||||
case ETP_TP_REPORT_ID2:
|
||||
elan_report_trackpoint(data, report);
|
||||
break;
|
||||
default:
|
||||
|
@ -1414,6 +1402,7 @@ static const struct i2c_device_id elan_id[] = {
|
|||
MODULE_DEVICE_TABLE(i2c, elan_id);
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
#include <linux/input/elan-i2c-ids.h>
|
||||
MODULE_DEVICE_TABLE(acpi, elan_acpi_id);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#define ETP_SMBUS_CALIBRATE_QUERY 0xC5
|
||||
|
||||
#define ETP_SMBUS_REPORT_LEN 32
|
||||
#define ETP_SMBUS_REPORT_LEN2 7
|
||||
#define ETP_SMBUS_REPORT_OFFSET 2
|
||||
#define ETP_SMBUS_HELLOPACKET_LEN 5
|
||||
#define ETP_SMBUS_IAP_PASSWORD 0x1234
|
||||
|
@ -497,10 +498,13 @@ static int elan_smbus_get_report(struct i2c_client *client,
|
|||
return len;
|
||||
}
|
||||
|
||||
if (len != ETP_SMBUS_REPORT_LEN) {
|
||||
if (report[ETP_REPORT_ID_OFFSET] == ETP_TP_REPORT_ID2)
|
||||
report_len = ETP_SMBUS_REPORT_LEN2;
|
||||
|
||||
if (len != report_len) {
|
||||
dev_err(&client->dev,
|
||||
"wrong report length (%d vs %d expected)\n",
|
||||
len, ETP_SMBUS_REPORT_LEN);
|
||||
len, report_len);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
|
|
@ -89,6 +89,47 @@ static int elantech_ps2_command(struct psmouse *psmouse,
|
|||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send an Elantech style special command to read 3 bytes from a register
|
||||
*/
|
||||
static int elantech_read_reg_params(struct psmouse *psmouse, u8 reg, u8 *param)
|
||||
{
|
||||
if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
|
||||
elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) ||
|
||||
elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
|
||||
elantech_ps2_command(psmouse, NULL, reg) ||
|
||||
elantech_ps2_command(psmouse, param, PSMOUSE_CMD_GETINFO)) {
|
||||
psmouse_err(psmouse,
|
||||
"failed to read register %#02x\n", reg);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send an Elantech style special command to write a register with a parameter
|
||||
*/
|
||||
static int elantech_write_reg_params(struct psmouse *psmouse, u8 reg, u8 *param)
|
||||
{
|
||||
if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
|
||||
elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) ||
|
||||
elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
|
||||
elantech_ps2_command(psmouse, NULL, reg) ||
|
||||
elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
|
||||
elantech_ps2_command(psmouse, NULL, param[0]) ||
|
||||
elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
|
||||
elantech_ps2_command(psmouse, NULL, param[1]) ||
|
||||
elantech_ps2_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) {
|
||||
psmouse_err(psmouse,
|
||||
"failed to write register %#02x with value %#02x%#02x\n",
|
||||
reg, param[0], param[1]);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send an Elantech style special command to read a value from a register
|
||||
*/
|
||||
|
@ -1529,19 +1570,35 @@ static const struct dmi_system_id no_hw_res_dmi_table[] = {
|
|||
{ }
|
||||
};
|
||||
|
||||
/*
|
||||
* Change Report id 0x5E to 0x5F.
|
||||
*/
|
||||
static int elantech_change_report_id(struct psmouse *psmouse)
|
||||
{
|
||||
unsigned char param[2] = { 0x10, 0x03 };
|
||||
|
||||
if (elantech_write_reg_params(psmouse, 0x7, param) ||
|
||||
elantech_read_reg_params(psmouse, 0x7, param) ||
|
||||
param[0] != 0x10 || param[1] != 0x03) {
|
||||
psmouse_err(psmouse, "Unable to change report ID to 0x5f.\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* determine hardware version and set some properties according to it.
|
||||
*/
|
||||
static int elantech_set_properties(struct elantech_device_info *info)
|
||||
{
|
||||
/* This represents the version of IC body. */
|
||||
int ver = (info->fw_version & 0x0f0000) >> 16;
|
||||
info->ic_version = (info->fw_version & 0x0f0000) >> 16;
|
||||
|
||||
/* Early version of Elan touchpads doesn't obey the rule. */
|
||||
if (info->fw_version < 0x020030 || info->fw_version == 0x020600)
|
||||
info->hw_version = 1;
|
||||
else {
|
||||
switch (ver) {
|
||||
switch (info->ic_version) {
|
||||
case 2:
|
||||
case 4:
|
||||
info->hw_version = 2;
|
||||
|
@ -1557,6 +1614,11 @@ static int elantech_set_properties(struct elantech_device_info *info)
|
|||
}
|
||||
}
|
||||
|
||||
/* Get information pattern for hw_version 4 */
|
||||
info->pattern = 0x00;
|
||||
if (info->ic_version == 0x0f && (info->fw_version & 0xff) <= 0x02)
|
||||
info->pattern = info->fw_version & 0xff;
|
||||
|
||||
/* decide which send_cmd we're gonna use early */
|
||||
info->send_cmd = info->hw_version >= 3 ? elantech_send_cmd :
|
||||
synaptics_send_cmd;
|
||||
|
@ -1598,6 +1660,7 @@ static int elantech_query_info(struct psmouse *psmouse,
|
|||
{
|
||||
unsigned char param[3];
|
||||
unsigned char traces;
|
||||
unsigned char ic_body[3];
|
||||
|
||||
memset(info, 0, sizeof(*info));
|
||||
|
||||
|
@ -1640,6 +1703,21 @@ static int elantech_query_info(struct psmouse *psmouse,
|
|||
info->samples[2]);
|
||||
}
|
||||
|
||||
if (info->pattern > 0x00 && info->ic_version == 0xf) {
|
||||
if (info->send_cmd(psmouse, ETP_ICBODY_QUERY, ic_body)) {
|
||||
psmouse_err(psmouse, "failed to query ic body\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
info->ic_version = be16_to_cpup((__be16 *)ic_body);
|
||||
psmouse_info(psmouse,
|
||||
"Elan ic body: %#04x, current fw version: %#02x\n",
|
||||
info->ic_version, ic_body[2]);
|
||||
}
|
||||
|
||||
info->product_id = be16_to_cpup((__be16 *)info->samples);
|
||||
if (info->pattern == 0x00)
|
||||
info->product_id &= 0xff;
|
||||
|
||||
if (info->samples[1] == 0x74 && info->hw_version == 0x03) {
|
||||
/*
|
||||
* This module has a bug which makes absolute mode
|
||||
|
@ -1654,6 +1732,23 @@ static int elantech_query_info(struct psmouse *psmouse,
|
|||
/* The MSB indicates the presence of the trackpoint */
|
||||
info->has_trackpoint = (info->capabilities[0] & 0x80) == 0x80;
|
||||
|
||||
if (info->has_trackpoint && info->ic_version == 0x0011 &&
|
||||
(info->product_id == 0x08 || info->product_id == 0x09 ||
|
||||
info->product_id == 0x0d || info->product_id == 0x0e)) {
|
||||
/*
|
||||
* This module has a bug which makes trackpoint in SMBus
|
||||
* mode return invalid data unless trackpoint is switched
|
||||
* from using 0x5e reports to 0x5f. If we are not able to
|
||||
* make the switch, let's abort initialization so we'll be
|
||||
* using standard PS/2 protocol.
|
||||
*/
|
||||
if (elantech_change_report_id(psmouse)) {
|
||||
psmouse_info(psmouse,
|
||||
"Trackpoint report is broken, forcing standard PS/2 protocol\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
info->x_res = 31;
|
||||
info->y_res = 31;
|
||||
if (info->hw_version == 4) {
|
||||
|
@ -1827,7 +1922,7 @@ static int elantech_create_smbus(struct psmouse *psmouse,
|
|||
leave_breadcrumbs);
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* elantech_setup_smbus - called once the PS/2 devices are enumerated
|
||||
* and decides to instantiate a SMBus InterTouch device.
|
||||
*/
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#define ETP_CAPABILITIES_QUERY 0x02
|
||||
#define ETP_SAMPLE_QUERY 0x03
|
||||
#define ETP_RESOLUTION_QUERY 0x04
|
||||
#define ETP_ICBODY_QUERY 0x05
|
||||
|
||||
/*
|
||||
* Command values for register reading or writing
|
||||
|
@ -140,7 +141,10 @@ struct elantech_device_info {
|
|||
unsigned char samples[3];
|
||||
unsigned char debug;
|
||||
unsigned char hw_version;
|
||||
unsigned char pattern;
|
||||
unsigned int fw_version;
|
||||
unsigned int ic_version;
|
||||
unsigned int product_id;
|
||||
unsigned int x_min;
|
||||
unsigned int y_min;
|
||||
unsigned int x_max;
|
||||
|
|
|
@ -322,7 +322,7 @@ static int __maybe_unused navpoint_suspend(struct device *dev)
|
|||
struct input_dev *input = navpoint->input;
|
||||
|
||||
mutex_lock(&input->mutex);
|
||||
if (input->users)
|
||||
if (input_device_enabled(input))
|
||||
navpoint_down(navpoint);
|
||||
mutex_unlock(&input->mutex);
|
||||
|
||||
|
@ -336,7 +336,7 @@ static int __maybe_unused navpoint_resume(struct device *dev)
|
|||
struct input_dev *input = navpoint->input;
|
||||
|
||||
mutex_lock(&input->mutex);
|
||||
if (input->users)
|
||||
if (input_device_enabled(input))
|
||||
navpoint_up(navpoint);
|
||||
mutex_unlock(&input->mutex);
|
||||
|
||||
|
|
|
@ -1770,7 +1770,7 @@ static int synaptics_create_intertouch(struct psmouse *psmouse,
|
|||
leave_breadcrumbs);
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* synaptics_setup_intertouch - called once the PS/2 devices are enumerated
|
||||
* and decides to instantiate a SMBus InterTouch device.
|
||||
*/
|
||||
|
|
|
@ -76,7 +76,7 @@ struct vmmouse_data {
|
|||
char dev_name[128];
|
||||
};
|
||||
|
||||
/**
|
||||
/*
|
||||
* Hypervisor-specific bi-directional communication channel
|
||||
* implementing the vmmouse protocol. Should never execute on
|
||||
* bare metal hardware.
|
||||
|
|
|
@ -286,7 +286,7 @@ void rmi_unregister_function(struct rmi_function *fn)
|
|||
/**
|
||||
* rmi_register_function_handler - register a handler for an RMI function
|
||||
* @handler: RMI handler that should be registered.
|
||||
* @module: pointer to module that implements the handler
|
||||
* @owner: pointer to module that implements the handler
|
||||
* @mod_name: name of the module implementing the handler
|
||||
*
|
||||
* This function performs additional setup of RMI function handler and
|
||||
|
|
|
@ -103,13 +103,15 @@ struct f01_basic_properties {
|
|||
#define RMI_F01_CTRL0_CONFIGURED_BIT BIT(7)
|
||||
|
||||
/**
|
||||
* @ctrl0 - see the bit definitions above.
|
||||
* @doze_interval - controls the interval between checks for finger presence
|
||||
* when the touch sensor is in doze mode, in units of 10ms.
|
||||
* @wakeup_threshold - controls the capacitance threshold at which the touch
|
||||
* sensor will decide to wake up from that low power state.
|
||||
* @doze_holdoff - controls how long the touch sensor waits after the last
|
||||
* finger lifts before entering the doze state, in units of 100ms.
|
||||
* struct f01_device_control - controls basic sensor functions
|
||||
*
|
||||
* @ctrl0: see the bit definitions above.
|
||||
* @doze_interval: controls the interval between checks for finger presence
|
||||
* when the touch sensor is in doze mode, in units of 10ms.
|
||||
* @wakeup_threshold: controls the capacitance threshold at which the touch
|
||||
* sensor will decide to wake up from that low power state.
|
||||
* @doze_holdoff: controls how long the touch sensor waits after the last
|
||||
* finger lifts before entering the doze state, in units of 100ms.
|
||||
*/
|
||||
struct f01_device_control {
|
||||
u8 ctrl0;
|
||||
|
|
|
@ -30,12 +30,12 @@
|
|||
#define DEFAULT_MIN_ABS_MT_TRACKING_ID 1
|
||||
#define DEFAULT_MAX_ABS_MT_TRACKING_ID 10
|
||||
|
||||
/** A note about RMI4 F11 register structure.
|
||||
/*
|
||||
* A note about RMI4 F11 register structure.
|
||||
*
|
||||
* The properties for
|
||||
* a given sensor are described by its query registers. The number of query
|
||||
* registers and the layout of their contents are described by the F11 device
|
||||
* queries as well as the sensor query information.
|
||||
* The properties for a given sensor are described by its query registers. The
|
||||
* number of query registers and the layout of their contents are described by
|
||||
* the F11 device queries as well as the sensor query information.
|
||||
*
|
||||
* Similarly, each sensor has control registers that govern its behavior. The
|
||||
* size and layout of the control registers for a given sensor can be determined
|
||||
|
@ -62,8 +62,8 @@
|
|||
/* maximum ABS_MT_POSITION displacement (in mm) */
|
||||
#define DMAX 10
|
||||
|
||||
/**
|
||||
* @rezero - writing this to the F11 command register will cause the sensor to
|
||||
/*
|
||||
* Writing this to the F11 command register will cause the sensor to
|
||||
* calibrate to the current capacitive state.
|
||||
*/
|
||||
#define RMI_F11_REZERO 0x01
|
||||
|
@ -178,135 +178,157 @@
|
|||
#define F11_UNIFORM_CLICKPAD 0x02
|
||||
|
||||
/**
|
||||
* struct f11_2d_sensor_queries - describes sensor capabilities
|
||||
*
|
||||
* Query registers 1 through 4 are always present.
|
||||
*
|
||||
* @nr_fingers - describes the maximum number of fingers the 2-D sensor
|
||||
* supports.
|
||||
* @has_rel - the sensor supports relative motion reporting.
|
||||
* @has_abs - the sensor supports absolute poition reporting.
|
||||
* @has_gestures - the sensor supports gesture reporting.
|
||||
* @has_sensitivity_adjust - the sensor supports a global sensitivity
|
||||
* adjustment.
|
||||
* @configurable - the sensor supports various configuration options.
|
||||
* @num_of_x_electrodes - the maximum number of electrodes the 2-D sensor
|
||||
* supports on the X axis.
|
||||
* @num_of_y_electrodes - the maximum number of electrodes the 2-D sensor
|
||||
* supports on the Y axis.
|
||||
* @max_electrodes - the total number of X and Y electrodes that may be
|
||||
* configured.
|
||||
* @nr_fingers: describes the maximum number of fingers the 2-D sensor
|
||||
* supports.
|
||||
* @has_rel: the sensor supports relative motion reporting.
|
||||
* @has_abs: the sensor supports absolute poition reporting.
|
||||
* @has_gestures: the sensor supports gesture reporting.
|
||||
* @has_sensitivity_adjust: the sensor supports a global sensitivity
|
||||
* adjustment.
|
||||
* @configurable: the sensor supports various configuration options.
|
||||
* @nr_x_electrodes: the maximum number of electrodes the 2-D sensor
|
||||
* supports on the X axis.
|
||||
* @nr_y_electrodes: the maximum number of electrodes the 2-D sensor
|
||||
* supports on the Y axis.
|
||||
* @max_electrodes: the total number of X and Y electrodes that may be
|
||||
* configured.
|
||||
*
|
||||
* Query 5 is present if the has_abs bit is set.
|
||||
*
|
||||
* @abs_data_size - describes the format of data reported by the absolute
|
||||
* data source. Only one format (the kind used here) is supported at this
|
||||
* time.
|
||||
* @has_anchored_finger - then the sensor supports the high-precision second
|
||||
* finger tracking provided by the manual tracking and motion sensitivity
|
||||
* options.
|
||||
* @has_adjust_hyst - the difference between the finger release threshold and
|
||||
* the touch threshold.
|
||||
* @has_dribble - the sensor supports the generation of dribble interrupts,
|
||||
* which may be enabled or disabled with the dribble control bit.
|
||||
* @has_bending_correction - Bending related data registers 28 and 36, and
|
||||
* control register 52..57 are present.
|
||||
* @has_large_object_suppression - control register 58 and data register 28
|
||||
* exist.
|
||||
* @has_jitter_filter - query 13 and control 73..76 exist.
|
||||
* @abs_data_size: describes the format of data reported by the absolute
|
||||
* data source. Only one format (the kind used here) is supported at this
|
||||
* time.
|
||||
* @has_anchored_finger: then the sensor supports the high-precision second
|
||||
* finger tracking provided by the manual tracking and motion sensitivity
|
||||
* options.
|
||||
* @has_adj_hyst: the difference between the finger release threshold and
|
||||
* the touch threshold.
|
||||
* @has_dribble: the sensor supports the generation of dribble interrupts,
|
||||
* which may be enabled or disabled with the dribble control bit.
|
||||
* @has_bending_correction: Bending related data registers 28 and 36, and
|
||||
* control register 52..57 are present.
|
||||
* @has_large_object_suppression: control register 58 and data register 28
|
||||
* exist.
|
||||
* @has_jitter_filter: query 13 and control 73..76 exist.
|
||||
*
|
||||
* Query 6 is present if the has_rel it is set.
|
||||
*
|
||||
* @f11_2d_query6: this register is reserved.
|
||||
*
|
||||
* Gesture information queries 7 and 8 are present if has_gestures bit is set.
|
||||
*
|
||||
* @has_single_tap - a basic single-tap gesture is supported.
|
||||
* @has_tap_n_hold - tap-and-hold gesture is supported.
|
||||
* @has_double_tap - double-tap gesture is supported.
|
||||
* @has_early_tap - early tap is supported and reported as soon as the finger
|
||||
* lifts for any tap event that could be interpreted as either a single tap
|
||||
* or as the first tap of a double-tap or tap-and-hold gesture.
|
||||
* @has_flick - flick detection is supported.
|
||||
* @has_press - press gesture reporting is supported.
|
||||
* @has_pinch - pinch gesture detection is supported.
|
||||
* @has_palm_det - the 2-D sensor notifies the host whenever a large conductive
|
||||
* object such as a palm or a cheek touches the 2-D sensor.
|
||||
* @has_rotate - rotation gesture detection is supported.
|
||||
* @has_touch_shapes - TouchShapes are supported. A TouchShape is a fixed
|
||||
* rectangular area on the sensor that behaves like a capacitive button.
|
||||
* @has_scroll_zones - scrolling areas near the sensor edges are supported.
|
||||
* @has_individual_scroll_zones - if 1, then 4 scroll zones are supported;
|
||||
* if 0, then only two are supported.
|
||||
* @has_mf_scroll - the multifinger_scrolling bit will be set when
|
||||
* more than one finger is involved in a scrolling action.
|
||||
* @has_single_tap: a basic single-tap gesture is supported.
|
||||
* @has_tap_n_hold: tap-and-hold gesture is supported.
|
||||
* @has_double_tap: double-tap gesture is supported.
|
||||
* @has_early_tap: early tap is supported and reported as soon as the finger
|
||||
* lifts for any tap event that could be interpreted as either a single
|
||||
* tap or as the first tap of a double-tap or tap-and-hold gesture.
|
||||
* @has_flick: flick detection is supported.
|
||||
* @has_press: press gesture reporting is supported.
|
||||
* @has_pinch: pinch gesture detection is supported.
|
||||
* @has_chiral: chiral (circular) scrolling gesture detection is supported.
|
||||
* @has_palm_det: the 2-D sensor notifies the host whenever a large conductive
|
||||
* object such as a palm or a cheek touches the 2-D sensor.
|
||||
* @has_rotate: rotation gesture detection is supported.
|
||||
* @has_touch_shapes: TouchShapes are supported. A TouchShape is a fixed
|
||||
* rectangular area on the sensor that behaves like a capacitive button.
|
||||
* @has_scroll_zones: scrolling areas near the sensor edges are supported.
|
||||
* @has_individual_scroll_zones: if 1, then 4 scroll zones are supported;
|
||||
* if 0, then only two are supported.
|
||||
* @has_mf_scroll: the multifinger_scrolling bit will be set when
|
||||
* more than one finger is involved in a scrolling action.
|
||||
* @has_mf_edge_motion: indicates whether multi-finger edge motion gesture
|
||||
* is supported.
|
||||
* @has_mf_scroll_inertia: indicates whether multi-finger scroll inertia
|
||||
* feature is supported.
|
||||
*
|
||||
* Convenience for checking bytes in the gesture info registers. This is done
|
||||
* often enough that we put it here to declutter the conditionals
|
||||
*
|
||||
* @query7_nonzero - true if none of the query 7 bits are set
|
||||
* @query8_nonzero - true if none of the query 8 bits are set
|
||||
* @query7_nonzero: true if none of the query 7 bits are set
|
||||
* @query8_nonzero: true if none of the query 8 bits are set
|
||||
*
|
||||
* Query 9 is present if the has_query9 is set.
|
||||
*
|
||||
* @has_pen - detection of a stylus is supported and registers F11_2D_Ctrl20
|
||||
* and F11_2D_Ctrl21 exist.
|
||||
* @has_proximity - detection of fingers near the sensor is supported and
|
||||
* registers F11_2D_Ctrl22 through F11_2D_Ctrl26 exist.
|
||||
* @has_palm_det_sensitivity - the sensor supports the palm detect sensitivity
|
||||
* feature and register F11_2D_Ctrl27 exists.
|
||||
* @has_two_pen_thresholds - is has_pen is also set, then F11_2D_Ctrl35 exists.
|
||||
* @has_contact_geometry - the sensor supports the use of contact geometry to
|
||||
* map absolute X and Y target positions and registers F11_2D_Data18
|
||||
* through F11_2D_Data27 exist.
|
||||
* @has_pen: detection of a stylus is supported and registers F11_2D_Ctrl20
|
||||
* and F11_2D_Ctrl21 exist.
|
||||
* @has_proximity: detection of fingers near the sensor is supported and
|
||||
* registers F11_2D_Ctrl22 through F11_2D_Ctrl26 exist.
|
||||
* @has_palm_det_sensitivity: the sensor supports the palm detect sensitivity
|
||||
* feature and register F11_2D_Ctrl27 exists.
|
||||
* @has_suppress_on_palm_detect: the device supports the large object detect
|
||||
* suppression feature and register F11_2D_Ctrl27 exists.
|
||||
* @has_two_pen_thresholds: if has_pen is also set, then F11_2D_Ctrl35 exists.
|
||||
* @has_contact_geometry: the sensor supports the use of contact geometry to
|
||||
* map absolute X and Y target positions and registers F11_2D_Data18
|
||||
* through F11_2D_Data27 exist.
|
||||
* @has_pen_hover_discrimination: if has_pen is also set, then registers
|
||||
* F11_2D_Data29 through F11_2D_Data31, F11_2D_Ctrl68.*, F11_2D_Ctrl69
|
||||
* and F11_2D_Ctrl72 exist.
|
||||
* @has_pen_filters: if has_pen is also set, then registers F11_2D_Ctrl70 and
|
||||
* F11_2D_Ctrl71 exist.
|
||||
*
|
||||
* Touch shape info (query 10) is present if has_touch_shapes is set.
|
||||
*
|
||||
* @nr_touch_shapes - the total number of touch shapes supported.
|
||||
* @nr_touch_shapes: the total number of touch shapes supported.
|
||||
*
|
||||
* Query 11 is present if the has_query11 bit is set in query 0.
|
||||
*
|
||||
* @has_z_tuning - if set, the sensor supports Z tuning and registers
|
||||
* F11_2D_Ctrl29 through F11_2D_Ctrl33 exist.
|
||||
* @has_algorithm_selection - controls choice of noise suppression algorithm
|
||||
* @has_w_tuning - the sensor supports Wx and Wy scaling and registers
|
||||
* F11_2D_Ctrl36 through F11_2D_Ctrl39 exist.
|
||||
* @has_pitch_info - the X and Y pitches of the sensor electrodes can be
|
||||
* configured and registers F11_2D_Ctrl40 and F11_2D_Ctrl41 exist.
|
||||
* @has_finger_size - the default finger width settings for the
|
||||
* sensor can be configured and registers F11_2D_Ctrl42 through F11_2D_Ctrl44
|
||||
* exist.
|
||||
* @has_segmentation_aggressiveness - the sensor’s ability to distinguish
|
||||
* multiple objects close together can be configured and register F11_2D_Ctrl45
|
||||
* exists.
|
||||
* @has_XY_clip - the inactive outside borders of the sensor can be
|
||||
* configured and registers F11_2D_Ctrl46 through F11_2D_Ctrl49 exist.
|
||||
* @has_drumming_filter - the sensor can be configured to distinguish
|
||||
* between a fast flick and a quick drumming movement and registers
|
||||
* F11_2D_Ctrl50 and F11_2D_Ctrl51 exist.
|
||||
* @has_z_tuning: if set, the sensor supports Z tuning and registers
|
||||
* F11_2D_Ctrl29 through F11_2D_Ctrl33 exist.
|
||||
* @has_algorithm_selection: controls choice of noise suppression algorithm
|
||||
* @has_w_tuning: the sensor supports Wx and Wy scaling and registers
|
||||
* F11_2D_Ctrl36 through F11_2D_Ctrl39 exist.
|
||||
* @has_pitch_info: the X and Y pitches of the sensor electrodes can be
|
||||
* configured and registers F11_2D_Ctrl40 and F11_2D_Ctrl41 exist.
|
||||
* @has_finger_size: the default finger width settings for the sensor
|
||||
* can be configured and registers F11_2D_Ctrl42 through F11_2D_Ctrl44
|
||||
* exist.
|
||||
* @has_segmentation_aggressiveness: the sensor’s ability to distinguish
|
||||
* multiple objects close together can be configured and register
|
||||
* F11_2D_Ctrl45 exists.
|
||||
* @has_XY_clip: the inactive outside borders of the sensor can be
|
||||
* configured and registers F11_2D_Ctrl46 through F11_2D_Ctrl49 exist.
|
||||
* @has_drumming_filter: the sensor can be configured to distinguish
|
||||
* between a fast flick and a quick drumming movement and registers
|
||||
* F11_2D_Ctrl50 and F11_2D_Ctrl51 exist.
|
||||
*
|
||||
* Query 12 is present if hasQuery12 bit is set.
|
||||
*
|
||||
* @has_gapless_finger - control registers relating to gapless finger are
|
||||
* present.
|
||||
* @has_gapless_finger_tuning - additional control and data registers relating
|
||||
* to gapless finger are present.
|
||||
* @has_8bit_w - larger W value reporting is supported.
|
||||
* @has_adjustable_mapping - TBD
|
||||
* @has_info2 - the general info query14 is present
|
||||
* @has_physical_props - additional queries describing the physical properties
|
||||
* of the sensor are present.
|
||||
* @has_finger_limit - indicates that F11 Ctrl 80 exists.
|
||||
* @has_linear_coeff - indicates that F11 Ctrl 81 exists.
|
||||
* @has_gapless_finger: control registers relating to gapless finger are
|
||||
* present.
|
||||
* @has_gapless_finger_tuning: additional control and data registers relating
|
||||
* to gapless finger are present.
|
||||
* @has_8bit_w: larger W value reporting is supported.
|
||||
* @has_adjustable_mapping: TBD
|
||||
* @has_info2: the general info query14 is present
|
||||
* @has_physical_props: additional queries describing the physical properties
|
||||
* of the sensor are present.
|
||||
* @has_finger_limit: indicates that F11 Ctrl 80 exists.
|
||||
* @has_linear_coeff_2: indicates that F11 Ctrl 81 exists.
|
||||
*
|
||||
* Query 13 is present if Query 5's has_jitter_filter bit is set.
|
||||
* @jitter_window_size - used by Design Studio 4.
|
||||
* @jitter_filter_type - used by Design Studio 4.
|
||||
*
|
||||
* @jitter_window_size: used by Design Studio 4.
|
||||
* @jitter_filter_type: used by Design Studio 4.
|
||||
*
|
||||
* Query 14 is present if query 12's has_general_info2 flag is set.
|
||||
*
|
||||
* @light_control - Indicates what light/led control features are present, if
|
||||
* any.
|
||||
* @is_clear - if set, this is a clear sensor (indicating direct pointing
|
||||
* application), otherwise it's opaque (indicating indirect pointing).
|
||||
* @clickpad_props - specifies if this is a clickpad, and if so what sort of
|
||||
* mechanism it uses
|
||||
* @mouse_buttons - specifies the number of mouse buttons present (if any).
|
||||
* @has_advanced_gestures - advanced driver gestures are supported.
|
||||
* @light_control: Indicates what light/led control features are present,
|
||||
* if any.
|
||||
* @is_clear: if set, this is a clear sensor (indicating direct pointing
|
||||
* application), otherwise it's opaque (indicating indirect pointing).
|
||||
* @clickpad_props: specifies if this is a clickpad, and if so what sort of
|
||||
* mechanism it uses
|
||||
* @mouse_buttons: specifies the number of mouse buttons present (if any).
|
||||
* @has_advanced_gestures: advanced driver gestures are supported.
|
||||
*
|
||||
* @x_sensor_size_mm: size of the sensor in millimeters on the X axis.
|
||||
* @y_sensor_size_mm: size of the sensor in millimeters on the Y axis.
|
||||
*/
|
||||
struct f11_2d_sensor_queries {
|
||||
/* query1 */
|
||||
|
|
|
@ -42,6 +42,8 @@
|
|||
/**
|
||||
* enum rmi_f54_report_type - RMI4 F54 report types
|
||||
*
|
||||
* @F54_REPORT_NONE: No Image Report.
|
||||
*
|
||||
* @F54_8BIT_IMAGE: Normalized 8-Bit Image Report. The capacitance variance
|
||||
* from baseline for each pixel.
|
||||
*
|
||||
|
@ -64,6 +66,10 @@
|
|||
* Report. Set Low reference to its minimum value and high
|
||||
* references to its maximum value, then report the raw
|
||||
* capacitance for each pixel.
|
||||
*
|
||||
* @F54_MAX_REPORT_TYPE:
|
||||
* Maximum number of Report Types. Used for sanity
|
||||
* checking.
|
||||
*/
|
||||
enum rmi_f54_report_type {
|
||||
F54_REPORT_NONE = 0,
|
||||
|
|
|
@ -17,12 +17,16 @@
|
|||
* struct rmi_i2c_xport - stores information for i2c communication
|
||||
*
|
||||
* @xport: The transport interface structure
|
||||
* @client: The I2C client device structure
|
||||
*
|
||||
* @page_mutex: Locks current page to avoid changing pages in unexpected ways.
|
||||
* @page: Keeps track of the current virtual page
|
||||
*
|
||||
* @tx_buf: Buffer used for transmitting data to the sensor over i2c.
|
||||
* @tx_buf_size: Size of the buffer
|
||||
*
|
||||
* @supplies: Array of voltage regulators
|
||||
* @startup_delay: Milliseconds to pause after powering up the regulators
|
||||
*/
|
||||
struct rmi_i2c_xport {
|
||||
struct rmi_transport_dev xport;
|
||||
|
|
|
@ -188,7 +188,8 @@ static int rmi_spi_xfer(struct rmi_spi_xport *rmi_spi,
|
|||
memset(xfer, 0, sizeof(struct spi_transfer));
|
||||
xfer->tx_buf = &rmi_spi->tx_buf[i];
|
||||
xfer->len = 1;
|
||||
xfer->delay_usecs = spi_data->write_delay_us;
|
||||
xfer->delay.value = spi_data->write_delay_us;
|
||||
xfer->delay.unit = SPI_DELAY_UNIT_USECS;
|
||||
spi_message_add_tail(xfer, &msg);
|
||||
}
|
||||
} else {
|
||||
|
@ -210,7 +211,8 @@ static int rmi_spi_xfer(struct rmi_spi_xport *rmi_spi,
|
|||
memset(xfer, 0, sizeof(struct spi_transfer));
|
||||
xfer->rx_buf = &rmi_spi->rx_buf[i];
|
||||
xfer->len = 1;
|
||||
xfer->delay_usecs = spi_data->read_delay_us;
|
||||
xfer->delay.value = spi_data->read_delay_us;
|
||||
xfer->delay.unit = SPI_DELAY_UNIT_USECS;
|
||||
spi_message_add_tail(xfer, &msg);
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -405,7 +405,7 @@ bool ps2_handle_ack(struct ps2dev *ps2dev, u8 data)
|
|||
ps2dev->nak = PS2_RET_ERR;
|
||||
break;
|
||||
}
|
||||
/* Fall through */
|
||||
fallthrough;
|
||||
|
||||
/*
|
||||
* Workaround for mice which don't ACK the Get ID command.
|
||||
|
|
|
@ -168,7 +168,7 @@ static struct serio *parkbd_allocate_serio(void)
|
|||
serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
|
||||
if (serio) {
|
||||
serio->id.type = parkbd_mode;
|
||||
serio->write = parkbd_write,
|
||||
serio->write = parkbd_write;
|
||||
strlcpy(serio->name, "PARKBD AT/XT keyboard adapter", sizeof(serio->name));
|
||||
snprintf(serio->phys, sizeof(serio->phys), "%s/serio0", parkbd_dev->port->name);
|
||||
}
|
||||
|
|
|
@ -38,18 +38,6 @@ config TABLET_USB_AIPTEK
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called aiptek.
|
||||
|
||||
config TABLET_USB_GTCO
|
||||
tristate "GTCO CalComp/InterWrite USB Support"
|
||||
depends on USB && INPUT
|
||||
help
|
||||
Say Y here if you want to use the USB version of the GTCO
|
||||
CalComp/InterWrite Tablet. Make sure to say Y to "Mouse support"
|
||||
(CONFIG_INPUT_MOUSEDEV) and/or "Event interface support"
|
||||
(CONFIG_INPUT_EVDEV) as well.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called gtco.
|
||||
|
||||
config TABLET_USB_HANWANG
|
||||
tristate "Hanwang Art Master III tablet support (USB)"
|
||||
depends on USB_ARCH_HAS_HCD
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
obj-$(CONFIG_TABLET_USB_ACECAD) += acecad.o
|
||||
obj-$(CONFIG_TABLET_USB_AIPTEK) += aiptek.o
|
||||
obj-$(CONFIG_TABLET_USB_GTCO) += gtco.o
|
||||
obj-$(CONFIG_TABLET_USB_HANWANG) += hanwang.o
|
||||
obj-$(CONFIG_TABLET_USB_KBTAB) += kbtab.o
|
||||
obj-$(CONFIG_TABLET_USB_PEGASUS) += pegasus_notetaker.o
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -281,12 +281,14 @@ static int ad7877_read_adc(struct spi_device *spi, unsigned command)
|
|||
|
||||
req->xfer[1].tx_buf = &req->ref_on;
|
||||
req->xfer[1].len = 2;
|
||||
req->xfer[1].delay_usecs = ts->vref_delay_usecs;
|
||||
req->xfer[1].delay.value = ts->vref_delay_usecs;
|
||||
req->xfer[1].delay.unit = SPI_DELAY_UNIT_USECS;
|
||||
req->xfer[1].cs_change = 1;
|
||||
|
||||
req->xfer[2].tx_buf = &req->command;
|
||||
req->xfer[2].len = 2;
|
||||
req->xfer[2].delay_usecs = ts->vref_delay_usecs;
|
||||
req->xfer[2].delay.value = ts->vref_delay_usecs;
|
||||
req->xfer[2].delay.unit = SPI_DELAY_UNIT_USECS;
|
||||
req->xfer[2].cs_change = 1;
|
||||
|
||||
req->xfer[3].rx_buf = &req->sample;
|
||||
|
|
|
@ -306,7 +306,7 @@ static int __maybe_unused ad7879_suspend(struct device *dev)
|
|||
|
||||
mutex_lock(&ts->input->mutex);
|
||||
|
||||
if (!ts->suspended && !ts->disabled && ts->input->users)
|
||||
if (!ts->suspended && !ts->disabled && input_device_enabled(ts->input))
|
||||
__ad7879_disable(ts);
|
||||
|
||||
ts->suspended = true;
|
||||
|
@ -322,7 +322,7 @@ static int __maybe_unused ad7879_resume(struct device *dev)
|
|||
|
||||
mutex_lock(&ts->input->mutex);
|
||||
|
||||
if (ts->suspended && !ts->disabled && ts->input->users)
|
||||
if (ts->suspended && !ts->disabled && input_device_enabled(ts->input))
|
||||
__ad7879_enable(ts);
|
||||
|
||||
ts->suspended = false;
|
||||
|
@ -339,7 +339,7 @@ static void ad7879_toggle(struct ad7879 *ts, bool disable)
|
|||
{
|
||||
mutex_lock(&ts->input->mutex);
|
||||
|
||||
if (!ts->suspended && ts->input->users != 0) {
|
||||
if (!ts->suspended && input_device_enabled(ts->input)) {
|
||||
|
||||
if (disable) {
|
||||
if (ts->disabled)
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#include <linux/spi/ads7846.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/module.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
/*
|
||||
* This code has been heavily tested on a Nokia 770, and lightly
|
||||
|
@ -62,19 +62,26 @@
|
|||
/* this driver doesn't aim at the peak continuous sample rate */
|
||||
#define SAMPLE_BITS (8 /*cmd*/ + 16 /*sample*/ + 2 /* before, after */)
|
||||
|
||||
struct ts_event {
|
||||
struct ads7846_buf {
|
||||
u8 cmd;
|
||||
/*
|
||||
* For portability, we can't read 12 bit values using SPI (which
|
||||
* would make the controller deliver them as native byte order u16
|
||||
* with msbs zeroed). Instead, we read them as two 8-bit values,
|
||||
* *** WHICH NEED BYTESWAPPING *** and range adjustment.
|
||||
* This union is a temporary hack. The driver does an in-place
|
||||
* endianness conversion. This will be cleaned up in the next
|
||||
* patch.
|
||||
*/
|
||||
u16 x;
|
||||
u16 y;
|
||||
u16 z1, z2;
|
||||
bool ignore;
|
||||
u8 x_buf[3];
|
||||
u8 y_buf[3];
|
||||
union {
|
||||
__be16 data_be16;
|
||||
u16 data;
|
||||
};
|
||||
} __packed;
|
||||
|
||||
|
||||
struct ts_event {
|
||||
bool ignore;
|
||||
struct ads7846_buf x;
|
||||
struct ads7846_buf y;
|
||||
struct ads7846_buf z1;
|
||||
struct ads7846_buf z2;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -83,11 +90,12 @@ struct ts_event {
|
|||
* systems where main memory is not DMA-coherent (most non-x86 boards).
|
||||
*/
|
||||
struct ads7846_packet {
|
||||
u8 read_x, read_y, read_z1, read_z2, pwrdown;
|
||||
u16 dummy; /* for the pwrdown read */
|
||||
struct ts_event tc;
|
||||
/* for ads7845 with mpc5121 psc spi we use 3-byte buffers */
|
||||
u8 read_x_cmd[3], read_y_cmd[3], pwrdown_cmd[3];
|
||||
struct ts_event tc;
|
||||
struct ads7846_buf read_x_cmd;
|
||||
struct ads7846_buf read_y_cmd;
|
||||
struct ads7846_buf read_z1_cmd;
|
||||
struct ads7846_buf read_z2_cmd;
|
||||
struct ads7846_buf pwrdown_cmd;
|
||||
};
|
||||
|
||||
struct ads7846 {
|
||||
|
@ -199,6 +207,26 @@ struct ads7846 {
|
|||
#define REF_ON (READ_12BIT_DFR(x, 1, 1))
|
||||
#define REF_OFF (READ_12BIT_DFR(y, 0, 0))
|
||||
|
||||
static int get_pendown_state(struct ads7846 *ts)
|
||||
{
|
||||
if (ts->get_pendown_state)
|
||||
return ts->get_pendown_state();
|
||||
|
||||
return !gpio_get_value(ts->gpio_pendown);
|
||||
}
|
||||
|
||||
static void ads7846_report_pen_up(struct ads7846 *ts)
|
||||
{
|
||||
struct input_dev *input = ts->input;
|
||||
|
||||
input_report_key(input, BTN_TOUCH, 0);
|
||||
input_report_abs(input, ABS_PRESSURE, 0);
|
||||
input_sync(input);
|
||||
|
||||
ts->pendown = false;
|
||||
dev_vdbg(&ts->spi->dev, "UP\n");
|
||||
}
|
||||
|
||||
/* Must be called with ts->lock held */
|
||||
static void ads7846_stop(struct ads7846 *ts)
|
||||
{
|
||||
|
@ -215,6 +243,10 @@ static void ads7846_stop(struct ads7846 *ts)
|
|||
static void ads7846_restart(struct ads7846 *ts)
|
||||
{
|
||||
if (!ts->disabled && !ts->suspended) {
|
||||
/* Check if pen was released since last stop */
|
||||
if (ts->pendown && !get_pendown_state(ts))
|
||||
ads7846_report_pen_up(ts);
|
||||
|
||||
/* Tell IRQ thread that it may poll the device. */
|
||||
ts->stopped = false;
|
||||
mb();
|
||||
|
@ -411,7 +443,7 @@ static int ads7845_read12_ser(struct device *dev, unsigned command)
|
|||
|
||||
if (status == 0) {
|
||||
/* BE12 value, then padding */
|
||||
status = be16_to_cpu(*((u16 *)&req->sample[1]));
|
||||
status = get_unaligned_be16(&req->sample[1]);
|
||||
status = status >> 3;
|
||||
status &= 0x0fff;
|
||||
}
|
||||
|
@ -481,7 +513,7 @@ SHOW(in1_input, vbatt, vbatt_adjust)
|
|||
static umode_t ads7846_is_visible(struct kobject *kobj, struct attribute *attr,
|
||||
int index)
|
||||
{
|
||||
struct device *dev = container_of(kobj, struct device, kobj);
|
||||
struct device *dev = kobj_to_dev(kobj);
|
||||
struct ads7846 *ts = dev_get_drvdata(dev);
|
||||
|
||||
if (ts->model == 7843 && index < 2) /* in0, in1 */
|
||||
|
@ -606,14 +638,6 @@ static const struct attribute_group ads784x_attr_group = {
|
|||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
static int get_pendown_state(struct ads7846 *ts)
|
||||
{
|
||||
if (ts->get_pendown_state)
|
||||
return ts->get_pendown_state();
|
||||
|
||||
return !gpio_get_value(ts->gpio_pendown);
|
||||
}
|
||||
|
||||
static void null_wait_for_sync(void)
|
||||
{
|
||||
}
|
||||
|
@ -670,16 +694,9 @@ static int ads7846_get_value(struct ads7846 *ts, struct spi_message *m)
|
|||
int value;
|
||||
struct spi_transfer *t =
|
||||
list_entry(m->transfers.prev, struct spi_transfer, transfer_list);
|
||||
struct ads7846_buf *buf = t->rx_buf;
|
||||
|
||||
if (ts->model == 7845) {
|
||||
value = be16_to_cpup((__be16 *)&(((char *)t->rx_buf)[1]));
|
||||
} else {
|
||||
/*
|
||||
* adjust: on-wire is a must-ignore bit, a BE12 value, then
|
||||
* padding; built from two 8 bit values written msb-first.
|
||||
*/
|
||||
value = be16_to_cpup((__be16 *)t->rx_buf);
|
||||
}
|
||||
value = be16_to_cpup(&buf->data_be16);
|
||||
|
||||
/* enforce ADC output is 12 bits width */
|
||||
return (value >> 3) & 0xfff;
|
||||
|
@ -689,8 +706,9 @@ static void ads7846_update_value(struct spi_message *m, int val)
|
|||
{
|
||||
struct spi_transfer *t =
|
||||
list_entry(m->transfers.prev, struct spi_transfer, transfer_list);
|
||||
struct ads7846_buf *buf = t->rx_buf;
|
||||
|
||||
*(u16 *)t->rx_buf = val;
|
||||
buf->data = val;
|
||||
}
|
||||
|
||||
static void ads7846_read_state(struct ads7846 *ts)
|
||||
|
@ -758,16 +776,14 @@ static void ads7846_report_state(struct ads7846 *ts)
|
|||
* from on-the-wire format as part of debouncing to get stable
|
||||
* readings.
|
||||
*/
|
||||
x = packet->tc.x.data;
|
||||
y = packet->tc.y.data;
|
||||
if (ts->model == 7845) {
|
||||
x = *(u16 *)packet->tc.x_buf;
|
||||
y = *(u16 *)packet->tc.y_buf;
|
||||
z1 = 0;
|
||||
z2 = 0;
|
||||
} else {
|
||||
x = packet->tc.x;
|
||||
y = packet->tc.y;
|
||||
z1 = packet->tc.z1;
|
||||
z2 = packet->tc.z2;
|
||||
z1 = packet->tc.z1.data;
|
||||
z2 = packet->tc.z2.data;
|
||||
}
|
||||
|
||||
/* range filtering */
|
||||
|
@ -786,10 +802,11 @@ static void ads7846_report_state(struct ads7846 *ts)
|
|||
/* compute touch pressure resistance using equation #2 */
|
||||
Rt = z2;
|
||||
Rt -= z1;
|
||||
Rt *= x;
|
||||
Rt *= ts->x_plate_ohms;
|
||||
Rt = DIV_ROUND_CLOSEST(Rt, 16);
|
||||
Rt *= x;
|
||||
Rt /= z1;
|
||||
Rt = (Rt + 2047) >> 12;
|
||||
Rt = DIV_ROUND_CLOSEST(Rt, 256);
|
||||
} else {
|
||||
Rt = 0;
|
||||
}
|
||||
|
@ -868,16 +885,8 @@ static irqreturn_t ads7846_irq(int irq, void *handle)
|
|||
msecs_to_jiffies(TS_POLL_PERIOD));
|
||||
}
|
||||
|
||||
if (ts->pendown && !ts->stopped) {
|
||||
struct input_dev *input = ts->input;
|
||||
|
||||
input_report_key(input, BTN_TOUCH, 0);
|
||||
input_report_abs(input, ABS_PRESSURE, 0);
|
||||
input_sync(input);
|
||||
|
||||
ts->pendown = false;
|
||||
dev_vdbg(&ts->spi->dev, "UP\n");
|
||||
}
|
||||
if (ts->pendown && !ts->stopped)
|
||||
ads7846_report_pen_up(ts);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
@ -992,26 +1001,11 @@ static void ads7846_setup_spi_msg(struct ads7846 *ts,
|
|||
spi_message_init(m);
|
||||
m->context = ts;
|
||||
|
||||
if (ts->model == 7845) {
|
||||
packet->read_y_cmd[0] = READ_Y(vref);
|
||||
packet->read_y_cmd[1] = 0;
|
||||
packet->read_y_cmd[2] = 0;
|
||||
x->tx_buf = &packet->read_y_cmd[0];
|
||||
x->rx_buf = &packet->tc.y_buf[0];
|
||||
x->len = 3;
|
||||
spi_message_add_tail(x, m);
|
||||
} else {
|
||||
/* y- still on; turn on only y+ (and ADC) */
|
||||
packet->read_y = READ_Y(vref);
|
||||
x->tx_buf = &packet->read_y;
|
||||
x->len = 1;
|
||||
spi_message_add_tail(x, m);
|
||||
|
||||
x++;
|
||||
x->rx_buf = &packet->tc.y;
|
||||
x->len = 2;
|
||||
spi_message_add_tail(x, m);
|
||||
}
|
||||
packet->read_y_cmd.cmd = READ_Y(vref);
|
||||
x->tx_buf = &packet->read_y_cmd;
|
||||
x->rx_buf = &packet->tc.y;
|
||||
x->len = 3;
|
||||
spi_message_add_tail(x, m);
|
||||
|
||||
/*
|
||||
* The first sample after switching drivers can be low quality;
|
||||
|
@ -1021,15 +1015,11 @@ static void ads7846_setup_spi_msg(struct ads7846 *ts,
|
|||
if (pdata->settle_delay_usecs) {
|
||||
x->delay.value = pdata->settle_delay_usecs;
|
||||
x->delay.unit = SPI_DELAY_UNIT_USECS;
|
||||
|
||||
x++;
|
||||
x->tx_buf = &packet->read_y;
|
||||
x->len = 1;
|
||||
spi_message_add_tail(x, m);
|
||||
|
||||
x++;
|
||||
x->tx_buf = &packet->read_y_cmd;
|
||||
x->rx_buf = &packet->tc.y;
|
||||
x->len = 2;
|
||||
x->len = 3;
|
||||
spi_message_add_tail(x, m);
|
||||
}
|
||||
|
||||
|
@ -1038,28 +1028,13 @@ static void ads7846_setup_spi_msg(struct ads7846 *ts,
|
|||
spi_message_init(m);
|
||||
m->context = ts;
|
||||
|
||||
if (ts->model == 7845) {
|
||||
x++;
|
||||
packet->read_x_cmd[0] = READ_X(vref);
|
||||
packet->read_x_cmd[1] = 0;
|
||||
packet->read_x_cmd[2] = 0;
|
||||
x->tx_buf = &packet->read_x_cmd[0];
|
||||
x->rx_buf = &packet->tc.x_buf[0];
|
||||
x->len = 3;
|
||||
spi_message_add_tail(x, m);
|
||||
} else {
|
||||
/* turn y- off, x+ on, then leave in lowpower */
|
||||
x++;
|
||||
packet->read_x = READ_X(vref);
|
||||
x->tx_buf = &packet->read_x;
|
||||
x->len = 1;
|
||||
spi_message_add_tail(x, m);
|
||||
|
||||
x++;
|
||||
x->rx_buf = &packet->tc.x;
|
||||
x->len = 2;
|
||||
spi_message_add_tail(x, m);
|
||||
}
|
||||
/* turn y- off, x+ on, then leave in lowpower */
|
||||
x++;
|
||||
packet->read_x_cmd.cmd = READ_X(vref);
|
||||
x->tx_buf = &packet->read_x_cmd;
|
||||
x->rx_buf = &packet->tc.x;
|
||||
x->len = 3;
|
||||
spi_message_add_tail(x, m);
|
||||
|
||||
/* ... maybe discard first sample ... */
|
||||
if (pdata->settle_delay_usecs) {
|
||||
|
@ -1067,13 +1042,9 @@ static void ads7846_setup_spi_msg(struct ads7846 *ts,
|
|||
x->delay.unit = SPI_DELAY_UNIT_USECS;
|
||||
|
||||
x++;
|
||||
x->tx_buf = &packet->read_x;
|
||||
x->len = 1;
|
||||
spi_message_add_tail(x, m);
|
||||
|
||||
x++;
|
||||
x->tx_buf = &packet->read_x_cmd;
|
||||
x->rx_buf = &packet->tc.x;
|
||||
x->len = 2;
|
||||
x->len = 3;
|
||||
spi_message_add_tail(x, m);
|
||||
}
|
||||
|
||||
|
@ -1085,14 +1056,10 @@ static void ads7846_setup_spi_msg(struct ads7846 *ts,
|
|||
m->context = ts;
|
||||
|
||||
x++;
|
||||
packet->read_z1 = READ_Z1(vref);
|
||||
x->tx_buf = &packet->read_z1;
|
||||
x->len = 1;
|
||||
spi_message_add_tail(x, m);
|
||||
|
||||
x++;
|
||||
packet->read_z1_cmd.cmd = READ_Z1(vref);
|
||||
x->tx_buf = &packet->read_z1_cmd;
|
||||
x->rx_buf = &packet->tc.z1;
|
||||
x->len = 2;
|
||||
x->len = 3;
|
||||
spi_message_add_tail(x, m);
|
||||
|
||||
/* ... maybe discard first sample ... */
|
||||
|
@ -1101,13 +1068,9 @@ static void ads7846_setup_spi_msg(struct ads7846 *ts,
|
|||
x->delay.unit = SPI_DELAY_UNIT_USECS;
|
||||
|
||||
x++;
|
||||
x->tx_buf = &packet->read_z1;
|
||||
x->len = 1;
|
||||
spi_message_add_tail(x, m);
|
||||
|
||||
x++;
|
||||
x->tx_buf = &packet->read_z1_cmd;
|
||||
x->rx_buf = &packet->tc.z1;
|
||||
x->len = 2;
|
||||
x->len = 3;
|
||||
spi_message_add_tail(x, m);
|
||||
}
|
||||
|
||||
|
@ -1117,14 +1080,10 @@ static void ads7846_setup_spi_msg(struct ads7846 *ts,
|
|||
m->context = ts;
|
||||
|
||||
x++;
|
||||
packet->read_z2 = READ_Z2(vref);
|
||||
x->tx_buf = &packet->read_z2;
|
||||
x->len = 1;
|
||||
spi_message_add_tail(x, m);
|
||||
|
||||
x++;
|
||||
packet->read_z2_cmd.cmd = READ_Z2(vref);
|
||||
x->tx_buf = &packet->read_z2_cmd;
|
||||
x->rx_buf = &packet->tc.z2;
|
||||
x->len = 2;
|
||||
x->len = 3;
|
||||
spi_message_add_tail(x, m);
|
||||
|
||||
/* ... maybe discard first sample ... */
|
||||
|
@ -1133,13 +1092,9 @@ static void ads7846_setup_spi_msg(struct ads7846 *ts,
|
|||
x->delay.unit = SPI_DELAY_UNIT_USECS;
|
||||
|
||||
x++;
|
||||
x->tx_buf = &packet->read_z2;
|
||||
x->len = 1;
|
||||
spi_message_add_tail(x, m);
|
||||
|
||||
x++;
|
||||
x->tx_buf = &packet->read_z2_cmd;
|
||||
x->rx_buf = &packet->tc.z2;
|
||||
x->len = 2;
|
||||
x->len = 3;
|
||||
spi_message_add_tail(x, m);
|
||||
}
|
||||
}
|
||||
|
@ -1150,24 +1105,10 @@ static void ads7846_setup_spi_msg(struct ads7846 *ts,
|
|||
spi_message_init(m);
|
||||
m->context = ts;
|
||||
|
||||
if (ts->model == 7845) {
|
||||
x++;
|
||||
packet->pwrdown_cmd[0] = PWRDOWN;
|
||||
packet->pwrdown_cmd[1] = 0;
|
||||
packet->pwrdown_cmd[2] = 0;
|
||||
x->tx_buf = &packet->pwrdown_cmd[0];
|
||||
x->len = 3;
|
||||
} else {
|
||||
x++;
|
||||
packet->pwrdown = PWRDOWN;
|
||||
x->tx_buf = &packet->pwrdown;
|
||||
x->len = 1;
|
||||
spi_message_add_tail(x, m);
|
||||
|
||||
x++;
|
||||
x->rx_buf = &packet->dummy;
|
||||
x->len = 2;
|
||||
}
|
||||
x++;
|
||||
packet->pwrdown_cmd.cmd = PWRDOWN;
|
||||
x->tx_buf = &packet->pwrdown_cmd;
|
||||
x->len = 3;
|
||||
|
||||
CS_CHANGE(*x);
|
||||
spi_message_add_tail(x, m);
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <linux/of.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <media/v4l2-device.h>
|
||||
|
@ -309,6 +310,7 @@ struct mxt_data {
|
|||
u8 multitouch;
|
||||
struct t7_config t7_cfg;
|
||||
struct mxt_dbg dbg;
|
||||
struct regulator_bulk_data regulators[2];
|
||||
struct gpio_desc *reset_gpio;
|
||||
bool use_retrigen_workaround;
|
||||
|
||||
|
@ -606,7 +608,6 @@ recheck:
|
|||
|
||||
static int mxt_send_bootloader_cmd(struct mxt_data *data, bool unlock)
|
||||
{
|
||||
int ret;
|
||||
u8 buf[2];
|
||||
|
||||
if (unlock) {
|
||||
|
@ -617,11 +618,7 @@ static int mxt_send_bootloader_cmd(struct mxt_data *data, bool unlock)
|
|||
buf[1] = 0x01;
|
||||
}
|
||||
|
||||
ret = mxt_bootloader_write(data, buf, 2);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
return mxt_bootloader_write(data, buf, sizeof(buf));
|
||||
}
|
||||
|
||||
static int __mxt_read_reg(struct i2c_client *client,
|
||||
|
@ -3134,8 +3131,24 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
|||
if (error)
|
||||
return error;
|
||||
|
||||
/*
|
||||
* VDDA is the analog voltage supply 2.57..3.47 V
|
||||
* VDD is the digital voltage supply 1.71..3.47 V
|
||||
*/
|
||||
data->regulators[0].supply = "vdda";
|
||||
data->regulators[1].supply = "vdd";
|
||||
error = devm_regulator_bulk_get(&client->dev, ARRAY_SIZE(data->regulators),
|
||||
data->regulators);
|
||||
if (error) {
|
||||
if (error != -EPROBE_DEFER)
|
||||
dev_err(&client->dev, "Failed to get regulators %d\n",
|
||||
error);
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Request the RESET line as asserted so we go into reset */
|
||||
data->reset_gpio = devm_gpiod_get_optional(&client->dev,
|
||||
"reset", GPIOD_OUT_LOW);
|
||||
"reset", GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(data->reset_gpio)) {
|
||||
error = PTR_ERR(data->reset_gpio);
|
||||
dev_err(&client->dev, "Failed to get reset gpio: %d\n", error);
|
||||
|
@ -3152,15 +3165,29 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
|||
|
||||
disable_irq(client->irq);
|
||||
|
||||
error = regulator_bulk_enable(ARRAY_SIZE(data->regulators),
|
||||
data->regulators);
|
||||
if (error) {
|
||||
dev_err(&client->dev, "failed to enable regulators: %d\n",
|
||||
error);
|
||||
return error;
|
||||
}
|
||||
/*
|
||||
* The device takes 40ms to come up after power-on according
|
||||
* to the mXT224 datasheet, page 13.
|
||||
*/
|
||||
msleep(MXT_BACKUP_TIME);
|
||||
|
||||
if (data->reset_gpio) {
|
||||
/* Wait a while and then de-assert the RESET GPIO line */
|
||||
msleep(MXT_RESET_GPIO_TIME);
|
||||
gpiod_set_value(data->reset_gpio, 1);
|
||||
gpiod_set_value(data->reset_gpio, 0);
|
||||
msleep(MXT_RESET_INVALID_CHG);
|
||||
}
|
||||
|
||||
error = mxt_initialize(data);
|
||||
if (error)
|
||||
return error;
|
||||
goto err_disable_regulators;
|
||||
|
||||
error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group);
|
||||
if (error) {
|
||||
|
@ -3174,6 +3201,9 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
|||
err_free_object:
|
||||
mxt_free_input_device(data);
|
||||
mxt_free_object_table(data);
|
||||
err_disable_regulators:
|
||||
regulator_bulk_disable(ARRAY_SIZE(data->regulators),
|
||||
data->regulators);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -3185,6 +3215,8 @@ static int mxt_remove(struct i2c_client *client)
|
|||
sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);
|
||||
mxt_free_input_device(data);
|
||||
mxt_free_object_table(data);
|
||||
regulator_bulk_disable(ARRAY_SIZE(data->regulators),
|
||||
data->regulators);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -3200,7 +3232,7 @@ static int __maybe_unused mxt_suspend(struct device *dev)
|
|||
|
||||
mutex_lock(&input_dev->mutex);
|
||||
|
||||
if (input_dev->users)
|
||||
if (input_device_enabled(input_dev))
|
||||
mxt_stop(data);
|
||||
|
||||
mutex_unlock(&input_dev->mutex);
|
||||
|
@ -3223,7 +3255,7 @@ static int __maybe_unused mxt_resume(struct device *dev)
|
|||
|
||||
mutex_lock(&input_dev->mutex);
|
||||
|
||||
if (input_dev->users)
|
||||
if (input_device_enabled(input_dev))
|
||||
mxt_start(data);
|
||||
|
||||
mutex_unlock(&input_dev->mutex);
|
||||
|
|
|
@ -414,7 +414,7 @@ static int __maybe_unused auo_pixcir_suspend(struct device *dev)
|
|||
*/
|
||||
if (device_may_wakeup(&client->dev)) {
|
||||
/* need to start device if not open, to be wakeup source */
|
||||
if (!input->users) {
|
||||
if (!input_device_enabled(input)) {
|
||||
ret = auo_pixcir_start(ts);
|
||||
if (ret)
|
||||
goto unlock;
|
||||
|
@ -422,7 +422,7 @@ static int __maybe_unused auo_pixcir_suspend(struct device *dev)
|
|||
|
||||
enable_irq_wake(client->irq);
|
||||
ret = auo_pixcir_power_mode(ts, AUO_PIXCIR_POWER_SLEEP);
|
||||
} else if (input->users) {
|
||||
} else if (input_device_enabled(input)) {
|
||||
ret = auo_pixcir_stop(ts);
|
||||
}
|
||||
|
||||
|
@ -445,14 +445,14 @@ static int __maybe_unused auo_pixcir_resume(struct device *dev)
|
|||
disable_irq_wake(client->irq);
|
||||
|
||||
/* need to stop device if it was not open on suspend */
|
||||
if (!input->users) {
|
||||
if (!input_device_enabled(input)) {
|
||||
ret = auo_pixcir_stop(ts);
|
||||
if (ret)
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
/* device wakes automatically from SLEEP */
|
||||
} else if (input->users) {
|
||||
} else if (input_device_enabled(input)) {
|
||||
ret = auo_pixcir_start(ts);
|
||||
}
|
||||
|
||||
|
|
|
@ -430,7 +430,7 @@ static int __maybe_unused bu21029_suspend(struct device *dev)
|
|||
|
||||
if (!device_may_wakeup(dev)) {
|
||||
mutex_lock(&bu21029->in_dev->mutex);
|
||||
if (bu21029->in_dev->users)
|
||||
if (input_device_enabled(bu21029->in_dev))
|
||||
bu21029_stop_chip(bu21029->in_dev);
|
||||
mutex_unlock(&bu21029->in_dev->mutex);
|
||||
}
|
||||
|
@ -445,7 +445,7 @@ static int __maybe_unused bu21029_resume(struct device *dev)
|
|||
|
||||
if (!device_may_wakeup(dev)) {
|
||||
mutex_lock(&bu21029->in_dev->mutex);
|
||||
if (bu21029->in_dev->users)
|
||||
if (input_device_enabled(bu21029->in_dev))
|
||||
bu21029_start_chip(bu21029->in_dev);
|
||||
mutex_unlock(&bu21029->in_dev->mutex);
|
||||
}
|
||||
|
|
|
@ -154,7 +154,7 @@ static int icn8318_suspend(struct device *dev)
|
|||
struct icn8318_data *data = i2c_get_clientdata(to_i2c_client(dev));
|
||||
|
||||
mutex_lock(&data->input->mutex);
|
||||
if (data->input->users)
|
||||
if (input_device_enabled(data->input))
|
||||
icn8318_stop(data->input);
|
||||
mutex_unlock(&data->input->mutex);
|
||||
|
||||
|
@ -166,7 +166,7 @@ static int icn8318_resume(struct device *dev)
|
|||
struct icn8318_data *data = i2c_get_clientdata(to_i2c_client(dev));
|
||||
|
||||
mutex_lock(&data->input->mutex);
|
||||
if (data->input->users)
|
||||
if (input_device_enabled(data->input))
|
||||
icn8318_start(data->input);
|
||||
mutex_unlock(&data->input->mutex);
|
||||
|
||||
|
|
|
@ -30,6 +30,20 @@
|
|||
|
||||
#define CY_CORE_STARTUP_RETRY_COUNT 3
|
||||
|
||||
static const char * const cyttsp4_tch_abs_string[] = {
|
||||
[CY_TCH_X] = "X",
|
||||
[CY_TCH_Y] = "Y",
|
||||
[CY_TCH_P] = "P",
|
||||
[CY_TCH_T] = "T",
|
||||
[CY_TCH_E] = "E",
|
||||
[CY_TCH_O] = "O",
|
||||
[CY_TCH_W] = "W",
|
||||
[CY_TCH_MAJ] = "MAJ",
|
||||
[CY_TCH_MIN] = "MIN",
|
||||
[CY_TCH_OR] = "OR",
|
||||
[CY_TCH_NUM_ABS] = "INVALID"
|
||||
};
|
||||
|
||||
static const u8 ldr_exit[] = {
|
||||
0xFF, 0x01, 0x3B, 0x00, 0x00, 0x4F, 0x6D, 0x17
|
||||
};
|
||||
|
|
|
@ -233,20 +233,6 @@ enum cyttsp4_tch_abs { /* for ordering within the extracted touch data array */
|
|||
CY_TCH_NUM_ABS
|
||||
};
|
||||
|
||||
static const char * const cyttsp4_tch_abs_string[] = {
|
||||
[CY_TCH_X] = "X",
|
||||
[CY_TCH_Y] = "Y",
|
||||
[CY_TCH_P] = "P",
|
||||
[CY_TCH_T] = "T",
|
||||
[CY_TCH_E] = "E",
|
||||
[CY_TCH_O] = "O",
|
||||
[CY_TCH_W] = "W",
|
||||
[CY_TCH_MAJ] = "MAJ",
|
||||
[CY_TCH_MIN] = "MIN",
|
||||
[CY_TCH_OR] = "OR",
|
||||
[CY_TCH_NUM_ABS] = "INVALID"
|
||||
};
|
||||
|
||||
struct cyttsp4_touch {
|
||||
int abs[CY_TCH_NUM_ABS];
|
||||
};
|
||||
|
|
|
@ -479,7 +479,7 @@ static int __maybe_unused cyttsp_suspend(struct device *dev)
|
|||
|
||||
mutex_lock(&ts->input->mutex);
|
||||
|
||||
if (ts->input->users) {
|
||||
if (input_device_enabled(ts->input)) {
|
||||
retval = cyttsp_disable(ts);
|
||||
if (retval == 0)
|
||||
ts->suspended = true;
|
||||
|
@ -496,7 +496,7 @@ static int __maybe_unused cyttsp_resume(struct device *dev)
|
|||
|
||||
mutex_lock(&ts->input->mutex);
|
||||
|
||||
if (ts->input->users)
|
||||
if (input_device_enabled(ts->input))
|
||||
cyttsp_enable(ts);
|
||||
|
||||
ts->suspended = false;
|
||||
|
|
|
@ -69,6 +69,9 @@
|
|||
#define EDT_RAW_DATA_RETRIES 100
|
||||
#define EDT_RAW_DATA_DELAY 1000 /* usec */
|
||||
|
||||
#define EDT_DEFAULT_NUM_X 1024
|
||||
#define EDT_DEFAULT_NUM_Y 1024
|
||||
|
||||
enum edt_pmode {
|
||||
EDT_PMODE_NOT_SUPPORTED,
|
||||
EDT_PMODE_HIBERNATE,
|
||||
|
@ -977,8 +980,7 @@ static void edt_ft5x06_ts_get_defaults(struct device *dev,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
edt_ft5x06_ts_get_parameters(struct edt_ft5x06_ts_data *tsdata)
|
||||
static void edt_ft5x06_ts_get_parameters(struct edt_ft5x06_ts_data *tsdata)
|
||||
{
|
||||
struct edt_reg_addr *reg_addr = &tsdata->reg_addr;
|
||||
|
||||
|
@ -997,21 +999,17 @@ edt_ft5x06_ts_get_parameters(struct edt_ft5x06_ts_data *tsdata)
|
|||
if (reg_addr->reg_report_rate != NO_REGISTER)
|
||||
tsdata->report_rate = edt_ft5x06_register_read(tsdata,
|
||||
reg_addr->reg_report_rate);
|
||||
if (tsdata->version == EDT_M06 ||
|
||||
tsdata->version == EDT_M09 ||
|
||||
tsdata->version == EDT_M12) {
|
||||
tsdata->num_x = EDT_DEFAULT_NUM_X;
|
||||
if (reg_addr->reg_num_x != NO_REGISTER)
|
||||
tsdata->num_x = edt_ft5x06_register_read(tsdata,
|
||||
reg_addr->reg_num_x);
|
||||
tsdata->num_y = EDT_DEFAULT_NUM_Y;
|
||||
if (reg_addr->reg_num_y != NO_REGISTER)
|
||||
tsdata->num_y = edt_ft5x06_register_read(tsdata,
|
||||
reg_addr->reg_num_y);
|
||||
} else {
|
||||
tsdata->num_x = -1;
|
||||
tsdata->num_y = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata)
|
||||
static void edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata)
|
||||
{
|
||||
struct edt_reg_addr *reg_addr = &tsdata->reg_addr;
|
||||
|
||||
|
@ -1041,22 +1039,25 @@ edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata)
|
|||
|
||||
case EV_FT:
|
||||
reg_addr->reg_threshold = EV_REGISTER_THRESHOLD;
|
||||
reg_addr->reg_report_rate = NO_REGISTER;
|
||||
reg_addr->reg_gain = EV_REGISTER_GAIN;
|
||||
reg_addr->reg_offset = NO_REGISTER;
|
||||
reg_addr->reg_offset_x = EV_REGISTER_OFFSET_X;
|
||||
reg_addr->reg_offset_y = EV_REGISTER_OFFSET_Y;
|
||||
reg_addr->reg_num_x = NO_REGISTER;
|
||||
reg_addr->reg_num_y = NO_REGISTER;
|
||||
reg_addr->reg_report_rate = NO_REGISTER;
|
||||
break;
|
||||
|
||||
case GENERIC_FT:
|
||||
/* this is a guesswork */
|
||||
reg_addr->reg_threshold = M09_REGISTER_THRESHOLD;
|
||||
reg_addr->reg_report_rate = NO_REGISTER;
|
||||
reg_addr->reg_gain = M09_REGISTER_GAIN;
|
||||
reg_addr->reg_offset = M09_REGISTER_OFFSET;
|
||||
reg_addr->reg_offset_x = NO_REGISTER;
|
||||
reg_addr->reg_offset_y = NO_REGISTER;
|
||||
reg_addr->reg_num_x = NO_REGISTER;
|
||||
reg_addr->reg_num_y = NO_REGISTER;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1195,20 +1196,10 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client,
|
|||
input->id.bustype = BUS_I2C;
|
||||
input->dev.parent = &client->dev;
|
||||
|
||||
if (tsdata->version == EDT_M06 ||
|
||||
tsdata->version == EDT_M09 ||
|
||||
tsdata->version == EDT_M12) {
|
||||
input_set_abs_params(input, ABS_MT_POSITION_X,
|
||||
0, tsdata->num_x * 64 - 1, 0, 0);
|
||||
input_set_abs_params(input, ABS_MT_POSITION_Y,
|
||||
0, tsdata->num_y * 64 - 1, 0, 0);
|
||||
} else {
|
||||
/* Unknown maximum values. Specify via devicetree */
|
||||
input_set_abs_params(input, ABS_MT_POSITION_X,
|
||||
0, 65535, 0, 0);
|
||||
input_set_abs_params(input, ABS_MT_POSITION_Y,
|
||||
0, 65535, 0, 0);
|
||||
}
|
||||
input_set_abs_params(input, ABS_MT_POSITION_X,
|
||||
0, tsdata->num_x * 64 - 1, 0, 0);
|
||||
input_set_abs_params(input, ABS_MT_POSITION_Y,
|
||||
0, tsdata->num_y * 64 - 1, 0, 0);
|
||||
|
||||
touchscreen_parse_properties(input, true, &tsdata->prop);
|
||||
|
||||
|
|
|
@ -241,7 +241,7 @@ static int __maybe_unused eeti_ts_suspend(struct device *dev)
|
|||
|
||||
mutex_lock(&input_dev->mutex);
|
||||
|
||||
if (input_dev->users)
|
||||
if (input_device_enabled(input_dev))
|
||||
eeti_ts_stop(eeti);
|
||||
|
||||
mutex_unlock(&input_dev->mutex);
|
||||
|
@ -263,7 +263,7 @@ static int __maybe_unused eeti_ts_resume(struct device *dev)
|
|||
|
||||
mutex_lock(&input_dev->mutex);
|
||||
|
||||
if (input_dev->users)
|
||||
if (input_device_enabled(input_dev))
|
||||
eeti_ts_start(eeti);
|
||||
|
||||
mutex_unlock(&input_dev->mutex);
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#define EKTF2127_RESPONSE 0x52
|
||||
#define EKTF2127_REQUEST 0x53
|
||||
#define EKTF2127_HELLO 0x55
|
||||
#define EKTF2127_REPORT2 0x5a
|
||||
#define EKTF2127_REPORT 0x5d
|
||||
#define EKTF2127_CALIB_DONE 0x66
|
||||
|
||||
|
@ -95,6 +96,29 @@ static void ektf2127_report_event(struct ektf2127_ts *ts, const u8 *buf)
|
|||
input_sync(ts->input);
|
||||
}
|
||||
|
||||
static void ektf2127_report2_contact(struct ektf2127_ts *ts, int slot,
|
||||
const u8 *buf, bool active)
|
||||
{
|
||||
input_mt_slot(ts->input, slot);
|
||||
input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, active);
|
||||
|
||||
if (active) {
|
||||
int x = (buf[0] & 0xf0) << 4 | buf[1];
|
||||
int y = (buf[0] & 0x0f) << 8 | buf[2];
|
||||
|
||||
touchscreen_report_pos(ts->input, &ts->prop, x, y, true);
|
||||
}
|
||||
}
|
||||
|
||||
static void ektf2127_report2_event(struct ektf2127_ts *ts, const u8 *buf)
|
||||
{
|
||||
ektf2127_report2_contact(ts, 0, &buf[1], !!(buf[7] & 2));
|
||||
ektf2127_report2_contact(ts, 1, &buf[4], !!(buf[7] & 4));
|
||||
|
||||
input_mt_sync_frame(ts->input);
|
||||
input_sync(ts->input);
|
||||
}
|
||||
|
||||
static irqreturn_t ektf2127_irq(int irq, void *dev_id)
|
||||
{
|
||||
struct ektf2127_ts *ts = dev_id;
|
||||
|
@ -113,6 +137,10 @@ static irqreturn_t ektf2127_irq(int irq, void *dev_id)
|
|||
ektf2127_report_event(ts, buf);
|
||||
break;
|
||||
|
||||
case EKTF2127_REPORT2:
|
||||
ektf2127_report2_event(ts, buf);
|
||||
break;
|
||||
|
||||
case EKTF2127_NOISE:
|
||||
if (buf[1] == EKTF2127_ENV_NOISY)
|
||||
dev_dbg(dev, "Environment is electrically noisy\n");
|
||||
|
@ -154,7 +182,7 @@ static int __maybe_unused ektf2127_suspend(struct device *dev)
|
|||
struct ektf2127_ts *ts = i2c_get_clientdata(to_i2c_client(dev));
|
||||
|
||||
mutex_lock(&ts->input->mutex);
|
||||
if (ts->input->users)
|
||||
if (input_device_enabled(ts->input))
|
||||
ektf2127_stop(ts->input);
|
||||
mutex_unlock(&ts->input->mutex);
|
||||
|
||||
|
@ -166,7 +194,7 @@ static int __maybe_unused ektf2127_resume(struct device *dev)
|
|||
struct ektf2127_ts *ts = i2c_get_clientdata(to_i2c_client(dev));
|
||||
|
||||
mutex_lock(&ts->input->mutex);
|
||||
if (ts->input->users)
|
||||
if (input_device_enabled(ts->input))
|
||||
ektf2127_start(ts->input);
|
||||
mutex_unlock(&ts->input->mutex);
|
||||
|
||||
|
@ -305,6 +333,7 @@ static int ektf2127_probe(struct i2c_client *client,
|
|||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id ektf2127_of_match[] = {
|
||||
{ .compatible = "elan,ektf2127" },
|
||||
{ .compatible = "elan,ektf2132" },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ektf2127_of_match);
|
||||
|
@ -312,6 +341,7 @@ MODULE_DEVICE_TABLE(of, ektf2127_of_match);
|
|||
|
||||
static const struct i2c_device_id ektf2127_i2c_id[] = {
|
||||
{ "ektf2127", 0 },
|
||||
{ "ektf2132", 0 },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, ektf2127_i2c_id);
|
||||
|
@ -327,6 +357,6 @@ static struct i2c_driver ektf2127_driver = {
|
|||
};
|
||||
module_i2c_driver(ektf2127_driver);
|
||||
|
||||
MODULE_DESCRIPTION("ELAN eKTF2127 I2C Touchscreen Driver");
|
||||
MODULE_DESCRIPTION("ELAN eKTF2127/eKTF2132 I2C Touchscreen Driver");
|
||||
MODULE_AUTHOR("Michel Verlaan, Siebren Vroegindeweij");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче