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:
Linus Torvalds 2020-12-15 16:18:23 -08:00
commit ee249d30fa
121 changed files with 2991 additions and 2383 deletions

View file

@ -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>;
};
};

View file

@ -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>;
};

View file

@ -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>;
};
};
...

View file

@ -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>;
};
};

View file

@ -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>;
};
};

View file

@ -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
>;
};

View file

@ -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>;
};
};

View file

@ -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>;
};
};

View file

@ -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

View file

@ -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
------------------------

View file

@ -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
~~~~~~~~~~~~~~~~~

View file

@ -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

View file

@ -589,7 +589,7 @@ &i2c2 {
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>;

View file

@ -143,7 +143,7 @@ touchscreen@4a {
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";
};

View file

@ -140,7 +140,7 @@ touchscreen@4a {
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";
};

View file

@ -145,7 +145,7 @@ touchscreen@4a {
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";
};

View file

@ -144,7 +144,7 @@ touchscreen@4a {
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";
};

View file

@ -99,7 +99,7 @@ touchscreen@4a {
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 */

View file

@ -124,7 +124,7 @@ touchscreen@4a {
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";
};

View file

@ -430,7 +430,7 @@ touchscreen@4a {
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>,

View file

@ -632,7 +632,7 @@ touchscreen@4a {
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>;
};
};

View file

@ -446,7 +446,7 @@ touchscreen@4c {
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>;

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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)

View file

@ -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) {
/*

View file

@ -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.

View file

@ -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,
};

View file

@ -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;

View file

@ -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

View file

@ -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);

View file

@ -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);
}

View file

@ -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;

View file

@ -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);

View file

@ -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)

View file

@ -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;

View file

@ -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,
},
};

View file

@ -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);

View file

@ -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)

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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");

1329
drivers/input/misc/da7280.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -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");

View file

@ -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");

View file

@ -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");

View file

@ -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;

View file

@ -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);

View file

@ -1,4 +1,4 @@
/**
/*
* Copyright (C) 2011 Philippe Rétornaz
*
* Based on twl4030-pwrbutton driver by:

View file

@ -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:

View file

@ -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);

View file

@ -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);

View file

@ -1,4 +1,4 @@
/**
/*
* wm831x-on.c - WM831X ON pin driver
*
* Copyright (C) 2009 Wolfson Microelectronics plc

View file

@ -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

View file

@ -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;

View file

@ -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. */

View file

@ -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. */

View file

@ -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);

View file

@ -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"

View file

@ -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

View file

@ -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;
}

View file

@ -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.
*/

View file

@ -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;

View file

@ -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);

View file

@ -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.
*/

View file

@ -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.

View file

@ -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

View file

@ -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;

View file

@ -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 sensors 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 sensors 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 */

View file

@ -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,

View file

@ -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;

View file

@ -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 {

View file

@ -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.

View file

@ -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);
}

View file

@ -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

View file

@ -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

File diff suppressed because it is too large Load diff

View file

@ -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;

View file

@ -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)

View file

@ -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);

View file

@ -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 @@ static int mxt_check_bootloader(struct mxt_data *data, unsigned int state,
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);

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);

View file

@ -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
};

View file

@ -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];
};

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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");

Some files were not shown because too many files have changed in this diff Show more