mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-23 20:24:12 +08:00
Merge branch 'next' into for-linus
Prepare input updates for 6.8 merge window.
This commit is contained in:
commit
e2a2501af1
@ -0,0 +1,63 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/input/adafruit,seesaw-gamepad.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Adafruit Mini I2C Gamepad with seesaw
|
||||
|
||||
maintainers:
|
||||
- Anshul Dalal <anshulusr@gmail.com>
|
||||
|
||||
description: |
|
||||
Adafruit Mini I2C Gamepad
|
||||
|
||||
+-----------------------------+
|
||||
| ___ |
|
||||
| / \ (X) |
|
||||
| | S | __ __ (Y) (A) |
|
||||
| \___/ |ST| |SE| (B) |
|
||||
| |
|
||||
+-----------------------------+
|
||||
|
||||
S -> 10-bit precision bidirectional analog joystick
|
||||
ST -> Start
|
||||
SE -> Select
|
||||
X, A, B, Y -> Digital action buttons
|
||||
|
||||
Datasheet: https://cdn-learn.adafruit.com/downloads/pdf/gamepad-qt.pdf
|
||||
Product page: https://www.adafruit.com/product/5743
|
||||
Arduino Driver: https://github.com/adafruit/Adafruit_Seesaw
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: adafruit,seesaw-gamepad
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
description:
|
||||
The gamepad's IRQ pin triggers a rising edge if interrupts are enabled.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
joystick@50 {
|
||||
compatible = "adafruit,seesaw-gamepad";
|
||||
interrupts = <18 IRQ_TYPE_EDGE_RISING>;
|
||||
reg = <0x50>;
|
||||
};
|
||||
};
|
@ -31,7 +31,23 @@ patternProperties:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
oneOf:
|
||||
- items:
|
||||
- description: Optional key interrupt or wakeup interrupt
|
||||
- items:
|
||||
- description: Key interrupt
|
||||
- description: Wakeup interrupt
|
||||
|
||||
interrupt-names:
|
||||
description:
|
||||
Optional interrupt names, can be used to specify a separate dedicated
|
||||
wake-up interrupt in addition to the gpio irq
|
||||
oneOf:
|
||||
- items:
|
||||
- enum: [ irq, wakeup ]
|
||||
- items:
|
||||
- const: irq
|
||||
- const: wakeup
|
||||
|
||||
label:
|
||||
description: Descriptive name of the key.
|
||||
@ -97,6 +113,20 @@ patternProperties:
|
||||
- required:
|
||||
- gpios
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
interrupts:
|
||||
minItems: 2
|
||||
required:
|
||||
- interrupts
|
||||
then:
|
||||
properties:
|
||||
interrupt-names:
|
||||
minItems: 2
|
||||
required:
|
||||
- interrupt-names
|
||||
|
||||
dependencies:
|
||||
wakeup-event-action: [ wakeup-source ]
|
||||
linux,input-value: [ gpios ]
|
||||
@ -137,6 +167,15 @@ examples:
|
||||
linux,code = <108>;
|
||||
interrupts = <1 IRQ_TYPE_EDGE_FALLING>;
|
||||
};
|
||||
|
||||
key-wakeup {
|
||||
label = "GPIO Key WAKEUP";
|
||||
linux,code = <143>;
|
||||
interrupts-extended = <&intc 2 IRQ_TYPE_EDGE_FALLING>,
|
||||
<&intc_wakeup 0 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "irq", "wakeup";
|
||||
wakeup-source;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
||||
|
@ -1,32 +0,0 @@
|
||||
Device-Tree bindings for GPIO attached mice
|
||||
|
||||
This simply uses standard GPIO handles to define a simple mouse connected
|
||||
to 5-7 GPIO lines.
|
||||
|
||||
Required properties:
|
||||
- compatible: must be "gpio-mouse"
|
||||
- scan-interval-ms: The scanning interval in milliseconds
|
||||
- up-gpios: GPIO line phandle to the line indicating "up"
|
||||
- down-gpios: GPIO line phandle to the line indicating "down"
|
||||
- left-gpios: GPIO line phandle to the line indicating "left"
|
||||
- right-gpios: GPIO line phandle to the line indicating "right"
|
||||
|
||||
Optional properties:
|
||||
- button-left-gpios: GPIO line handle to the left mouse button
|
||||
- button-middle-gpios: GPIO line handle to the middle mouse button
|
||||
- button-right-gpios: GPIO line handle to the right mouse button
|
||||
Example:
|
||||
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
gpio-mouse {
|
||||
compatible = "gpio-mouse";
|
||||
scan-interval-ms = <50>;
|
||||
up-gpios = <&gpio0 0 GPIO_ACTIVE_LOW>;
|
||||
down-gpios = <&gpio0 1 GPIO_ACTIVE_LOW>;
|
||||
left-gpios = <&gpio0 2 GPIO_ACTIVE_LOW>;
|
||||
right-gpios = <&gpio0 3 GPIO_ACTIVE_LOW>;
|
||||
button-left-gpios = <&gpio0 4 GPIO_ACTIVE_LOW>;
|
||||
button-middle-gpios = <&gpio0 5 GPIO_ACTIVE_LOW>;
|
||||
button-right-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
|
||||
};
|
68
Documentation/devicetree/bindings/input/gpio-mouse.yaml
Normal file
68
Documentation/devicetree/bindings/input/gpio-mouse.yaml
Normal file
@ -0,0 +1,68 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/input/gpio-mouse.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: GPIO attached mouse
|
||||
|
||||
description: |
|
||||
This simply uses standard GPIO handles to define a simple mouse connected
|
||||
to 5-7 GPIO lines.
|
||||
|
||||
maintainers:
|
||||
- Anshul Dalal <anshulusr@gmail.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: gpio-mouse
|
||||
|
||||
scan-interval-ms:
|
||||
maxItems: 1
|
||||
|
||||
up-gpios:
|
||||
maxItems: 1
|
||||
|
||||
down-gpios:
|
||||
maxItems: 1
|
||||
|
||||
left-gpios:
|
||||
maxItems: 1
|
||||
|
||||
right-gpios:
|
||||
maxItems: 1
|
||||
|
||||
button-left-gpios:
|
||||
maxItems: 1
|
||||
|
||||
button-middle-gpios:
|
||||
maxItems: 1
|
||||
|
||||
button-right-gpios:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- scan-interval-ms
|
||||
- up-gpios
|
||||
- down-gpios
|
||||
- left-gpios
|
||||
- right-gpios
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
gpio-mouse {
|
||||
compatible = "gpio-mouse";
|
||||
scan-interval-ms = <50>;
|
||||
up-gpios = <&gpio0 0 GPIO_ACTIVE_LOW>;
|
||||
down-gpios = <&gpio0 1 GPIO_ACTIVE_LOW>;
|
||||
left-gpios = <&gpio0 2 GPIO_ACTIVE_LOW>;
|
||||
right-gpios = <&gpio0 3 GPIO_ACTIVE_LOW>;
|
||||
button-left-gpios = <&gpio0 4 GPIO_ACTIVE_LOW>;
|
||||
button-middle-gpios = <&gpio0 5 GPIO_ACTIVE_LOW>;
|
||||
button-right-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
|
||||
};
|
@ -9,6 +9,9 @@ title: Azoteq IQS269A Capacitive Touch Controller
|
||||
maintainers:
|
||||
- Jeff LaBundy <jeff@labundy.com>
|
||||
|
||||
allOf:
|
||||
- $ref: input.yaml#
|
||||
|
||||
description: |
|
||||
The Azoteq IQS269A is an 8-channel capacitive touch controller that features
|
||||
additional Hall-effect and inductive sensing capabilities.
|
||||
@ -17,7 +20,10 @@ description: |
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: azoteq,iqs269a
|
||||
enum:
|
||||
- azoteq,iqs269a
|
||||
- azoteq,iqs269a-00
|
||||
- azoteq,iqs269a-d0
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
@ -204,6 +210,73 @@ properties:
|
||||
default: 1
|
||||
description: Specifies the slider coordinate filter strength.
|
||||
|
||||
azoteq,touch-hold-ms:
|
||||
multipleOf: 256
|
||||
minimum: 256
|
||||
maximum: 65280
|
||||
default: 5120
|
||||
description:
|
||||
Specifies the length of time (in ms) for which the channel selected by
|
||||
'azoteq,gpio3-select' must be held in a state of touch in order for an
|
||||
approximately 60-ms pulse to be asserted on the GPIO4 pin.
|
||||
|
||||
linux,keycodes:
|
||||
minItems: 1
|
||||
maxItems: 8
|
||||
description: |
|
||||
Specifies the numeric keycodes associated with each available gesture in
|
||||
the following order (enter 0 for unused gestures):
|
||||
0: Slider 0 tap
|
||||
1: Slider 0 hold
|
||||
2: Slider 0 positive flick or swipe
|
||||
3: Slider 0 negative flick or swipe
|
||||
4: Slider 1 tap
|
||||
5: Slider 1 hold
|
||||
6: Slider 1 positive flick or swipe
|
||||
7: Slider 1 negative flick or swipe
|
||||
|
||||
azoteq,gesture-swipe:
|
||||
type: boolean
|
||||
description:
|
||||
Directs the device to interpret axial gestures as a swipe (finger remains
|
||||
on slider) instead of a flick (finger leaves slider).
|
||||
|
||||
azoteq,timeout-tap-ms:
|
||||
multipleOf: 16
|
||||
minimum: 0
|
||||
maximum: 4080
|
||||
default: 400
|
||||
description:
|
||||
Specifies the length of time (in ms) within which a slider touch must be
|
||||
released in order to be interpreted as a tap. Default and maximum values
|
||||
as well as step size are reduced by a factor of 4 with device version 2.
|
||||
|
||||
azoteq,timeout-swipe-ms:
|
||||
multipleOf: 16
|
||||
minimum: 0
|
||||
maximum: 4080
|
||||
default: 2000
|
||||
description:
|
||||
Specifies the length of time (in ms) within which an axial gesture must be
|
||||
completed in order to be interpreted as a flick or swipe. Default and max-
|
||||
imum values as well as step size are reduced by a factor of 4 with device
|
||||
version 2.
|
||||
|
||||
azoteq,thresh-swipe:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
minimum: 0
|
||||
maximum: 255
|
||||
default: 128
|
||||
description:
|
||||
Specifies the number of points across which an axial gesture must travel
|
||||
in order to be interpreted as a flick or swipe.
|
||||
|
||||
dependencies:
|
||||
azoteq,gesture-swipe: ["linux,keycodes"]
|
||||
azoteq,timeout-tap-ms: ["linux,keycodes"]
|
||||
azoteq,timeout-swipe-ms: ["linux,keycodes"]
|
||||
azoteq,thresh-swipe: ["linux,keycodes"]
|
||||
|
||||
patternProperties:
|
||||
"^channel@[0-7]$":
|
||||
type: object
|
||||
@ -454,6 +527,21 @@ patternProperties:
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- azoteq,iqs269a-d0
|
||||
then:
|
||||
patternProperties:
|
||||
"^channel@[0-7]$":
|
||||
properties:
|
||||
azoteq,slider1-select: false
|
||||
else:
|
||||
properties:
|
||||
azoteq,touch-hold-ms: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
@ -484,6 +572,14 @@ examples:
|
||||
azoteq,hall-enable;
|
||||
azoteq,suspend-mode = <2>;
|
||||
|
||||
linux,keycodes = <KEY_PLAYPAUSE>,
|
||||
<KEY_STOPCD>,
|
||||
<KEY_NEXTSONG>,
|
||||
<KEY_PREVIOUSSONG>;
|
||||
|
||||
azoteq,timeout-tap-ms = <400>;
|
||||
azoteq,timeout-swipe-ms = <800>;
|
||||
|
||||
channel@0 {
|
||||
reg = <0x0>;
|
||||
|
||||
|
@ -90,26 +90,4 @@ required:
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/input/input.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
|
||||
pmic {
|
||||
compatible = "mediatek,mt6397";
|
||||
|
||||
keys {
|
||||
compatible = "mediatek,mt6397-keys";
|
||||
mediatek,long-press-mode = <1>;
|
||||
power-off-time-sec = <0>;
|
||||
|
||||
key-power {
|
||||
linux,keycodes = <KEY_POWER>;
|
||||
wakeup-source;
|
||||
};
|
||||
|
||||
key-home {
|
||||
linux,keycodes = <KEY_VOLUMEDOWN>;
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
||||
|
@ -45,13 +45,13 @@ properties:
|
||||
Enables the Linux input system's autorepeat feature on the input device.
|
||||
|
||||
linux,keycodes:
|
||||
minItems: 6
|
||||
maxItems: 6
|
||||
minItems: 3
|
||||
maxItems: 8
|
||||
description: |
|
||||
Specifies an array of numeric keycode values to
|
||||
be used for the channels. If this property is
|
||||
omitted, KEY_A, KEY_B, etc are used as defaults.
|
||||
The array must have exactly six entries.
|
||||
The number of entries must correspond to the number of channels.
|
||||
|
||||
microchip,sensor-gain:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
@ -70,6 +70,59 @@ properties:
|
||||
open drain. This property allows using the active
|
||||
high push-pull output.
|
||||
|
||||
microchip,sensitivity-delta-sense:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
default: 32
|
||||
enum: [1, 2, 4, 8, 16, 32, 64, 128]
|
||||
description:
|
||||
Controls the sensitivity multiplier of a touch detection.
|
||||
Higher value means more sensitive settings.
|
||||
At the more sensitive settings, touches are detected for a smaller delta
|
||||
capacitance corresponding to a "lighter" touch.
|
||||
|
||||
microchip,signal-guard:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
minItems: 3
|
||||
maxItems: 8
|
||||
items:
|
||||
enum: [0, 1]
|
||||
description: |
|
||||
0 - off
|
||||
1 - on
|
||||
The signal guard isolates the signal from virtual grounds.
|
||||
If enabled then the behavior of the channel is changed to signal guard.
|
||||
The number of entries must correspond to the number of channels.
|
||||
|
||||
microchip,input-threshold:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
minItems: 3
|
||||
maxItems: 8
|
||||
items:
|
||||
minimum: 0
|
||||
maximum: 127
|
||||
description:
|
||||
Specifies the delta threshold that is used to determine if a touch has
|
||||
been detected. A higher value means a larger difference in capacitance
|
||||
is required for a touch to be registered, making the touch sensor less
|
||||
sensitive.
|
||||
The number of entries must correspond to the number of channels.
|
||||
|
||||
microchip,calib-sensitivity:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
minItems: 3
|
||||
maxItems: 8
|
||||
items:
|
||||
enum: [1, 2, 4]
|
||||
description: |
|
||||
Specifies an array of numeric values that controls the gain
|
||||
used by the calibration routine to enable sensor inputs
|
||||
to be more sensitive for proximity detection.
|
||||
Gain is based on touch pad capacitance range
|
||||
1 - 5-50pF
|
||||
2 - 0-25pF
|
||||
4 - 0-12.5pF
|
||||
The number of entries must correspond to the number of channels.
|
||||
|
||||
patternProperties:
|
||||
"^led@[0-7]$":
|
||||
type: object
|
||||
@ -99,10 +152,29 @@ allOf:
|
||||
contains:
|
||||
enum:
|
||||
- microchip,cap1106
|
||||
- microchip,cap1203
|
||||
- microchip,cap1206
|
||||
- microchip,cap1293
|
||||
- microchip,cap1298
|
||||
then:
|
||||
patternProperties:
|
||||
"^led@[0-7]$": false
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- microchip,cap1106
|
||||
- microchip,cap1126
|
||||
- microchip,cap1188
|
||||
- microchip,cap1203
|
||||
- microchip,cap1206
|
||||
then:
|
||||
properties:
|
||||
microchip,signal-guard: false
|
||||
microchip,calib-sensitivity: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- interrupts
|
||||
@ -122,6 +194,8 @@ examples:
|
||||
reg = <0x28>;
|
||||
autorepeat;
|
||||
microchip,sensor-gain = <2>;
|
||||
microchip,sensitivity-delta-sense = <16>;
|
||||
microchip,input-threshold = <21>, <18>, <46>, <46>, <46>, <21>;
|
||||
|
||||
linux,keycodes = <103>, /* KEY_UP */
|
||||
<106>, /* KEY_RIGHT */
|
||||
|
@ -28,21 +28,4 @@ required:
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
sc2731_pmic: pmic@0 {
|
||||
compatible = "sprd,sc2731";
|
||||
reg = <0 0>;
|
||||
spi-max-frequency = <26000000>;
|
||||
interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
vibrator@eb4 {
|
||||
compatible = "sprd,sc2731-vibrator";
|
||||
reg = <0xeb4>;
|
||||
};
|
||||
};
|
||||
...
|
||||
|
@ -1,17 +0,0 @@
|
||||
* Texas Instruments - drv2665 Haptics driver
|
||||
|
||||
Required properties:
|
||||
- compatible - "ti,drv2665" - DRV2665
|
||||
- reg - I2C slave address
|
||||
- vbat-supply - Required supply regulator
|
||||
|
||||
Example:
|
||||
|
||||
haptics: haptics@59 {
|
||||
compatible = "ti,drv2665";
|
||||
reg = <0x59>;
|
||||
vbat-supply = <&vbat>;
|
||||
};
|
||||
|
||||
For more product information please see the link below:
|
||||
http://www.ti.com/product/drv2665
|
@ -1,17 +0,0 @@
|
||||
* Texas Instruments - drv2667 Haptics driver
|
||||
|
||||
Required properties:
|
||||
- compatible - "ti,drv2667" - DRV2667
|
||||
- reg - I2C slave address
|
||||
- vbat-supply - Required supply regulator
|
||||
|
||||
Example:
|
||||
|
||||
haptics: haptics@59 {
|
||||
compatible = "ti,drv2667";
|
||||
reg = <0x59>;
|
||||
vbat-supply = <&vbat>;
|
||||
};
|
||||
|
||||
For more product information please see the link below:
|
||||
http://www.ti.com/product/drv2667
|
50
Documentation/devicetree/bindings/input/ti,drv266x.yaml
Normal file
50
Documentation/devicetree/bindings/input/ti,drv266x.yaml
Normal file
@ -0,0 +1,50 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/input/ti,drv266x.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Texas Instruments - drv266x Haptics driver
|
||||
|
||||
description: |
|
||||
Product Page:
|
||||
http://www.ti.com/product/drv2665
|
||||
http://www.ti.com/product/drv2667
|
||||
|
||||
maintainers:
|
||||
- Anshul Dalal <anshulusr@gmail.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- ti,drv2665
|
||||
- ti,drv2667
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
vbat-supply:
|
||||
description: Required supply regulator
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- vbat-supply
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
haptics@59 {
|
||||
compatible = "ti,drv2667";
|
||||
reg = <0x59>;
|
||||
vbat-supply = <&vbat>;
|
||||
};
|
||||
};
|
@ -0,0 +1,72 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/input/touchscreen/neonode,zforce.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Neonode infrared touchscreen controller
|
||||
|
||||
maintainers:
|
||||
- Heiko Stuebner <heiko@sntech.de>
|
||||
|
||||
allOf:
|
||||
- $ref: touchscreen.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: neonode,zforce
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
reset-gpios:
|
||||
maxItems: 1
|
||||
|
||||
irq-gpios:
|
||||
maxItems: 1
|
||||
|
||||
x-size:
|
||||
deprecated: true
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
|
||||
y-size:
|
||||
deprecated: true
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
|
||||
vdd-supply: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- reset-gpios
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
touchscreen@50 {
|
||||
compatible = "neonode,zforce";
|
||||
reg = <0x50>;
|
||||
interrupts = <2 0>;
|
||||
vdd-supply = <®_zforce_vdd>;
|
||||
|
||||
reset-gpios = <&gpio5 9 0>; /* RST */
|
||||
irq-gpios = <&gpio5 6 0>; /* IRQ, optional */
|
||||
|
||||
touchscreen-min-x = <0>;
|
||||
touchscreen-size-x = <800>;
|
||||
touchscreen-min-y = <0>;
|
||||
touchscreen-size-y = <600>;
|
||||
};
|
||||
};
|
||||
...
|
@ -1,32 +0,0 @@
|
||||
* Samsung S6SY761 touchscreen controller
|
||||
|
||||
Required properties:
|
||||
- compatible : must be "samsung,s6sy761"
|
||||
- reg : I2C slave address, (e.g. 0x48)
|
||||
- interrupts : interrupt specification
|
||||
- avdd-supply : analogic power supply
|
||||
- vdd-supply : power supply
|
||||
|
||||
Optional properties:
|
||||
- touchscreen-size-x : see touchscreen.txt. This property is embedded in the
|
||||
device. If defined it forces a different x resolution.
|
||||
- touchscreen-size-y : see touchscreen.txt. This property is embedded in the
|
||||
device. If defined it forces a different y resolution.
|
||||
|
||||
Example:
|
||||
|
||||
i2c@00000000 {
|
||||
|
||||
/* ... */
|
||||
|
||||
touchscreen@48 {
|
||||
compatible = "samsung,s6sy761";
|
||||
reg = <0x48>;
|
||||
interrupt-parent = <&gpa1>;
|
||||
interrupts = <1 IRQ_TYPE_NONE>;
|
||||
avdd-supply = <&ldo30_reg>;
|
||||
vdd-supply = <&ldo31_reg>;
|
||||
touchscreen-size-x = <4096>;
|
||||
touchscreen-size-y = <4096>;
|
||||
};
|
||||
};
|
@ -0,0 +1,54 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/input/touchscreen/samsung,s6sy761.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Samsung S6SY761 touchscreen controller
|
||||
|
||||
maintainers:
|
||||
- Andi Shyti <andi.shyti@kernel.org>
|
||||
|
||||
allOf:
|
||||
- $ref: touchscreen.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: samsung,s6sy761
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
avdd-supply: true
|
||||
vdd-supply: true
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- avdd-supply
|
||||
- vdd-supply
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
touchscreen@48 {
|
||||
compatible = "samsung,s6sy761";
|
||||
reg = <0x48>;
|
||||
interrupt-parent = <&gpa1>;
|
||||
interrupts = <1 IRQ_TYPE_LEVEL_HIGH>;
|
||||
avdd-supply = <&ldo30_reg>;
|
||||
vdd-supply = <&ldo31_reg>;
|
||||
touchscreen-size-x = <4096>;
|
||||
touchscreen-size-y = <4096>;
|
||||
};
|
||||
};
|
@ -1,34 +0,0 @@
|
||||
* Neonode infrared touchscreen controller
|
||||
|
||||
Required properties:
|
||||
- compatible: must be "neonode,zforce"
|
||||
- reg: I2C address of the chip
|
||||
- interrupts: interrupt to which the chip is connected
|
||||
- reset-gpios: reset gpio the chip is connected to
|
||||
- x-size: horizontal resolution of touchscreen
|
||||
- y-size: vertical resolution of touchscreen
|
||||
|
||||
Optional properties:
|
||||
- irq-gpios : interrupt gpio the chip is connected to
|
||||
- vdd-supply: Regulator controlling the controller supply
|
||||
|
||||
Example:
|
||||
|
||||
i2c@00000000 {
|
||||
/* ... */
|
||||
|
||||
zforce_ts@50 {
|
||||
compatible = "neonode,zforce";
|
||||
reg = <0x50>;
|
||||
interrupts = <2 0>;
|
||||
vdd-supply = <®_zforce_vdd>;
|
||||
|
||||
reset-gpios = <&gpio5 9 0>; /* RST */
|
||||
irq-gpios = <&gpio5 6 0>; /* IRQ, optional */
|
||||
|
||||
x-size = <800>;
|
||||
y-size = <600>;
|
||||
};
|
||||
|
||||
/* ... */
|
||||
};
|
@ -441,6 +441,13 @@ W: http://wiki.analog.com/AD7879
|
||||
W: https://ez.analog.com/linux-software-drivers
|
||||
F: drivers/input/touchscreen/ad7879.c
|
||||
|
||||
ADAFRUIT MINI I2C GAMEPAD
|
||||
M: Anshul Dalal <anshulusr@gmail.com>
|
||||
L: linux-input@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/input/adafruit,seesaw-gamepad.yaml
|
||||
F: drivers/input/joystick/adafruit-seesaw.c
|
||||
|
||||
ADDRESS SPACE LAYOUT RANDOMIZATION (ASLR)
|
||||
M: Jiri Kosina <jikos@kernel.org>
|
||||
S: Maintained
|
||||
|
@ -1365,8 +1365,8 @@ static ssize_t input_dev_show_##name(struct device *dev, \
|
||||
{ \
|
||||
struct input_dev *input_dev = to_input_dev(dev); \
|
||||
\
|
||||
return scnprintf(buf, PAGE_SIZE, "%s\n", \
|
||||
input_dev->name ? input_dev->name : ""); \
|
||||
return sysfs_emit(buf, "%s\n", \
|
||||
input_dev->name ? input_dev->name : ""); \
|
||||
} \
|
||||
static DEVICE_ATTR(name, S_IRUGO, input_dev_show_##name, NULL)
|
||||
|
||||
@ -1458,7 +1458,7 @@ static ssize_t inhibited_show(struct device *dev,
|
||||
{
|
||||
struct input_dev *input_dev = to_input_dev(dev);
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", input_dev->inhibited);
|
||||
return sysfs_emit(buf, "%d\n", input_dev->inhibited);
|
||||
}
|
||||
|
||||
static ssize_t inhibited_store(struct device *dev,
|
||||
@ -1505,7 +1505,7 @@ static ssize_t input_dev_show_id_##name(struct device *dev, \
|
||||
char *buf) \
|
||||
{ \
|
||||
struct input_dev *input_dev = to_input_dev(dev); \
|
||||
return scnprintf(buf, PAGE_SIZE, "%04x\n", input_dev->id.name); \
|
||||
return sysfs_emit(buf, "%04x\n", input_dev->id.name); \
|
||||
} \
|
||||
static DEVICE_ATTR(name, S_IRUGO, input_dev_show_id_##name, NULL)
|
||||
|
||||
|
@ -412,4 +412,14 @@ config JOYSTICK_SENSEHAT
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called sensehat_joystick.
|
||||
|
||||
config JOYSTICK_SEESAW
|
||||
tristate "Adafruit Mini I2C Gamepad with Seesaw"
|
||||
depends on I2C
|
||||
select INPUT_SPARSEKMAP
|
||||
help
|
||||
Say Y here if you want to use the Adafruit Mini I2C Gamepad.
|
||||
|
||||
To compile this driver as a module, choose M here: the module will be
|
||||
called adafruit-seesaw.
|
||||
|
||||
endif
|
||||
|
@ -28,6 +28,7 @@ obj-$(CONFIG_JOYSTICK_N64) += n64joy.o
|
||||
obj-$(CONFIG_JOYSTICK_PSXPAD_SPI) += psxpad-spi.o
|
||||
obj-$(CONFIG_JOYSTICK_PXRC) += pxrc.o
|
||||
obj-$(CONFIG_JOYSTICK_QWIIC) += qwiic-joystick.o
|
||||
obj-$(CONFIG_JOYSTICK_SEESAW) += adafruit-seesaw.o
|
||||
obj-$(CONFIG_JOYSTICK_SENSEHAT) += sensehat-joystick.o
|
||||
obj-$(CONFIG_JOYSTICK_SIDEWINDER) += sidewinder.o
|
||||
obj-$(CONFIG_JOYSTICK_SPACEBALL) += spaceball.o
|
||||
|
315
drivers/input/joystick/adafruit-seesaw.c
Normal file
315
drivers/input/joystick/adafruit-seesaw.c
Normal file
@ -0,0 +1,315 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (C) 2023 Anshul Dalal <anshulusr@gmail.com>
|
||||
*
|
||||
* Driver for Adafruit Mini I2C Gamepad
|
||||
*
|
||||
* Based on the work of:
|
||||
* Oleh Kravchenko (Sparkfun Qwiic Joystick driver)
|
||||
*
|
||||
* Datasheet: https://cdn-learn.adafruit.com/downloads/pdf/gamepad-qt.pdf
|
||||
* Product page: https://www.adafruit.com/product/5743
|
||||
* Firmware and hardware sources: https://github.com/adafruit/Adafruit_Seesaw
|
||||
*
|
||||
* TODO:
|
||||
* - Add interrupt support
|
||||
*/
|
||||
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/bits.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/input/sparse-keymap.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#define SEESAW_DEVICE_NAME "seesaw-gamepad"
|
||||
|
||||
#define SEESAW_ADC_BASE 0x0900
|
||||
|
||||
#define SEESAW_GPIO_DIRCLR_BULK 0x0103
|
||||
#define SEESAW_GPIO_BULK 0x0104
|
||||
#define SEESAW_GPIO_BULK_SET 0x0105
|
||||
#define SEESAW_GPIO_PULLENSET 0x010b
|
||||
|
||||
#define SEESAW_STATUS_HW_ID 0x0001
|
||||
#define SEESAW_STATUS_SWRST 0x007f
|
||||
|
||||
#define SEESAW_ADC_OFFSET 0x07
|
||||
|
||||
#define SEESAW_BUTTON_A 0x05
|
||||
#define SEESAW_BUTTON_B 0x01
|
||||
#define SEESAW_BUTTON_X 0x06
|
||||
#define SEESAW_BUTTON_Y 0x02
|
||||
#define SEESAW_BUTTON_START 0x10
|
||||
#define SEESAW_BUTTON_SELECT 0x00
|
||||
|
||||
#define SEESAW_ANALOG_X 0x0e
|
||||
#define SEESAW_ANALOG_Y 0x0f
|
||||
|
||||
#define SEESAW_JOYSTICK_MAX_AXIS 1023
|
||||
#define SEESAW_JOYSTICK_FUZZ 2
|
||||
#define SEESAW_JOYSTICK_FLAT 4
|
||||
|
||||
#define SEESAW_GAMEPAD_POLL_INTERVAL_MS 16
|
||||
#define SEESAW_GAMEPAD_POLL_MIN 8
|
||||
#define SEESAW_GAMEPAD_POLL_MAX 32
|
||||
|
||||
static const unsigned long SEESAW_BUTTON_MASK =
|
||||
BIT(SEESAW_BUTTON_A) | BIT(SEESAW_BUTTON_B) | BIT(SEESAW_BUTTON_X) |
|
||||
BIT(SEESAW_BUTTON_Y) | BIT(SEESAW_BUTTON_START) |
|
||||
BIT(SEESAW_BUTTON_SELECT);
|
||||
|
||||
struct seesaw_gamepad {
|
||||
struct input_dev *input_dev;
|
||||
struct i2c_client *i2c_client;
|
||||
};
|
||||
|
||||
struct seesaw_data {
|
||||
u16 x;
|
||||
u16 y;
|
||||
u32 button_state;
|
||||
};
|
||||
|
||||
static const struct key_entry seesaw_buttons_new[] = {
|
||||
{ KE_KEY, SEESAW_BUTTON_A, .keycode = BTN_SOUTH },
|
||||
{ KE_KEY, SEESAW_BUTTON_B, .keycode = BTN_EAST },
|
||||
{ KE_KEY, SEESAW_BUTTON_X, .keycode = BTN_NORTH },
|
||||
{ KE_KEY, SEESAW_BUTTON_Y, .keycode = BTN_WEST },
|
||||
{ KE_KEY, SEESAW_BUTTON_START, .keycode = BTN_START },
|
||||
{ KE_KEY, SEESAW_BUTTON_SELECT, .keycode = BTN_SELECT },
|
||||
{ KE_END, 0 }
|
||||
};
|
||||
|
||||
static int seesaw_register_read(struct i2c_client *client, u16 reg, void *buf,
|
||||
int count)
|
||||
{
|
||||
__be16 register_buf = cpu_to_be16(reg);
|
||||
struct i2c_msg message_buf[2] = {
|
||||
{
|
||||
.addr = client->addr,
|
||||
.flags = client->flags,
|
||||
.len = sizeof(register_buf),
|
||||
.buf = (u8 *)®ister_buf,
|
||||
},
|
||||
{
|
||||
.addr = client->addr,
|
||||
.flags = client->flags | I2C_M_RD,
|
||||
.len = count,
|
||||
.buf = (u8 *)buf,
|
||||
},
|
||||
};
|
||||
int ret;
|
||||
|
||||
ret = i2c_transfer(client->adapter, message_buf,
|
||||
ARRAY_SIZE(message_buf));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int seesaw_register_write_u8(struct i2c_client *client, u16 reg,
|
||||
u8 value)
|
||||
{
|
||||
u8 write_buf[sizeof(reg) + sizeof(value)];
|
||||
int ret;
|
||||
|
||||
put_unaligned_be16(reg, write_buf);
|
||||
write_buf[sizeof(reg)] = value;
|
||||
|
||||
ret = i2c_master_send(client, write_buf, sizeof(write_buf));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int seesaw_register_write_u32(struct i2c_client *client, u16 reg,
|
||||
u32 value)
|
||||
{
|
||||
u8 write_buf[sizeof(reg) + sizeof(value)];
|
||||
int ret;
|
||||
|
||||
put_unaligned_be16(reg, write_buf);
|
||||
put_unaligned_be32(value, write_buf + sizeof(reg));
|
||||
ret = i2c_master_send(client, write_buf, sizeof(write_buf));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int seesaw_read_data(struct i2c_client *client, struct seesaw_data *data)
|
||||
{
|
||||
__be16 adc_data;
|
||||
__be32 read_buf;
|
||||
int err;
|
||||
|
||||
err = seesaw_register_read(client, SEESAW_GPIO_BULK,
|
||||
&read_buf, sizeof(read_buf));
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
data->button_state = ~be32_to_cpu(read_buf);
|
||||
|
||||
err = seesaw_register_read(client,
|
||||
SEESAW_ADC_BASE |
|
||||
(SEESAW_ADC_OFFSET + SEESAW_ANALOG_X),
|
||||
&adc_data, sizeof(adc_data));
|
||||
if (err)
|
||||
return err;
|
||||
/*
|
||||
* ADC reads left as max and right as 0, must be reversed since kernel
|
||||
* expects reports in opposite order.
|
||||
*/
|
||||
data->x = SEESAW_JOYSTICK_MAX_AXIS - be16_to_cpu(adc_data);
|
||||
|
||||
err = seesaw_register_read(client,
|
||||
SEESAW_ADC_BASE |
|
||||
(SEESAW_ADC_OFFSET + SEESAW_ANALOG_Y),
|
||||
&adc_data, sizeof(adc_data));
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
data->y = be16_to_cpu(adc_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void seesaw_poll(struct input_dev *input)
|
||||
{
|
||||
struct seesaw_gamepad *private = input_get_drvdata(input);
|
||||
struct seesaw_data data;
|
||||
int err, i;
|
||||
|
||||
err = seesaw_read_data(private->i2c_client, &data);
|
||||
if (err) {
|
||||
dev_err_ratelimited(&input->dev,
|
||||
"failed to read joystick state: %d\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
input_report_abs(input, ABS_X, data.x);
|
||||
input_report_abs(input, ABS_Y, data.y);
|
||||
|
||||
for_each_set_bit(i, &SEESAW_BUTTON_MASK,
|
||||
BITS_PER_TYPE(SEESAW_BUTTON_MASK)) {
|
||||
if (!sparse_keymap_report_event(input, i,
|
||||
data.button_state & BIT(i),
|
||||
false))
|
||||
dev_err_ratelimited(&input->dev,
|
||||
"failed to report keymap event");
|
||||
}
|
||||
|
||||
input_sync(input);
|
||||
}
|
||||
|
||||
static int seesaw_probe(struct i2c_client *client)
|
||||
{
|
||||
struct seesaw_gamepad *seesaw;
|
||||
u8 hardware_id;
|
||||
int err;
|
||||
|
||||
err = seesaw_register_write_u8(client, SEESAW_STATUS_SWRST, 0xFF);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Wait for the registers to reset before proceeding */
|
||||
usleep_range(10000, 15000);
|
||||
|
||||
seesaw = devm_kzalloc(&client->dev, sizeof(*seesaw), GFP_KERNEL);
|
||||
if (!seesaw)
|
||||
return -ENOMEM;
|
||||
|
||||
err = seesaw_register_read(client, SEESAW_STATUS_HW_ID,
|
||||
&hardware_id, sizeof(hardware_id));
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
dev_dbg(&client->dev, "Adafruit Seesaw Gamepad, Hardware ID: %02x\n",
|
||||
hardware_id);
|
||||
|
||||
/* Set Pin Mode to input and enable pull-up resistors */
|
||||
err = seesaw_register_write_u32(client, SEESAW_GPIO_DIRCLR_BULK,
|
||||
SEESAW_BUTTON_MASK);
|
||||
if (err)
|
||||
return err;
|
||||
err = seesaw_register_write_u32(client, SEESAW_GPIO_PULLENSET,
|
||||
SEESAW_BUTTON_MASK);
|
||||
if (err)
|
||||
return err;
|
||||
err = seesaw_register_write_u32(client, SEESAW_GPIO_BULK_SET,
|
||||
SEESAW_BUTTON_MASK);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
seesaw->i2c_client = client;
|
||||
seesaw->input_dev = devm_input_allocate_device(&client->dev);
|
||||
if (!seesaw->input_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
seesaw->input_dev->id.bustype = BUS_I2C;
|
||||
seesaw->input_dev->name = "Adafruit Seesaw Gamepad";
|
||||
seesaw->input_dev->phys = "i2c/" SEESAW_DEVICE_NAME;
|
||||
input_set_drvdata(seesaw->input_dev, seesaw);
|
||||
input_set_abs_params(seesaw->input_dev, ABS_X,
|
||||
0, SEESAW_JOYSTICK_MAX_AXIS,
|
||||
SEESAW_JOYSTICK_FUZZ, SEESAW_JOYSTICK_FLAT);
|
||||
input_set_abs_params(seesaw->input_dev, ABS_Y,
|
||||
0, SEESAW_JOYSTICK_MAX_AXIS,
|
||||
SEESAW_JOYSTICK_FUZZ, SEESAW_JOYSTICK_FLAT);
|
||||
|
||||
err = sparse_keymap_setup(seesaw->input_dev, seesaw_buttons_new, NULL);
|
||||
if (err) {
|
||||
dev_err(&client->dev,
|
||||
"failed to set up input device keymap: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = input_setup_polling(seesaw->input_dev, seesaw_poll);
|
||||
if (err) {
|
||||
dev_err(&client->dev, "failed to set up polling: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
input_set_poll_interval(seesaw->input_dev,
|
||||
SEESAW_GAMEPAD_POLL_INTERVAL_MS);
|
||||
input_set_max_poll_interval(seesaw->input_dev, SEESAW_GAMEPAD_POLL_MAX);
|
||||
input_set_min_poll_interval(seesaw->input_dev, SEESAW_GAMEPAD_POLL_MIN);
|
||||
|
||||
err = input_register_device(seesaw->input_dev);
|
||||
if (err) {
|
||||
dev_err(&client->dev, "failed to register joystick: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id seesaw_id_table[] = {
|
||||
{ SEESAW_DEVICE_NAME },
|
||||
{ /* Sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, seesaw_id_table);
|
||||
|
||||
static const struct of_device_id seesaw_of_table[] = {
|
||||
{ .compatible = "adafruit,seesaw-gamepad"},
|
||||
{ /* Sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, seesaw_of_table);
|
||||
|
||||
static struct i2c_driver seesaw_driver = {
|
||||
.driver = {
|
||||
.name = SEESAW_DEVICE_NAME,
|
||||
.of_match_table = seesaw_of_table,
|
||||
},
|
||||
.id_table = seesaw_id_table,
|
||||
.probe = seesaw_probe,
|
||||
};
|
||||
module_i2c_driver(seesaw_driver);
|
||||
|
||||
MODULE_AUTHOR("Anshul Dalal <anshulusr@gmail.com>");
|
||||
MODULE_DESCRIPTION("Adafruit Mini I2C Gamepad driver");
|
||||
MODULE_LICENSE("GPL");
|
@ -13,7 +13,7 @@
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/input/as5011.h>
|
||||
#include <linux/slab.h>
|
||||
@ -61,7 +61,7 @@ MODULE_LICENSE("GPL");
|
||||
struct as5011_device {
|
||||
struct input_dev *input_dev;
|
||||
struct i2c_client *i2c_client;
|
||||
unsigned int button_gpio;
|
||||
struct gpio_desc *button_gpiod;
|
||||
unsigned int button_irq;
|
||||
unsigned int axis_irq;
|
||||
};
|
||||
@ -114,7 +114,7 @@ static int as5011_i2c_read(struct i2c_client *client,
|
||||
static irqreturn_t as5011_button_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct as5011_device *as5011 = dev_id;
|
||||
int val = gpio_get_value_cansleep(as5011->button_gpio);
|
||||
int val = gpiod_get_value_cansleep(as5011->button_gpiod);
|
||||
|
||||
input_report_key(as5011->input_dev, BTN_JOYSTICK, !val);
|
||||
input_sync(as5011->input_dev);
|
||||
@ -248,7 +248,6 @@ static int as5011_probe(struct i2c_client *client)
|
||||
|
||||
as5011->i2c_client = client;
|
||||
as5011->input_dev = input_dev;
|
||||
as5011->button_gpio = plat_data->button_gpio;
|
||||
as5011->axis_irq = plat_data->axis_irq;
|
||||
|
||||
input_dev->name = "Austria Microsystem as5011 joystick";
|
||||
@ -262,18 +261,20 @@ static int as5011_probe(struct i2c_client *client)
|
||||
input_set_abs_params(as5011->input_dev, ABS_Y,
|
||||
AS5011_MIN_AXIS, AS5011_MAX_AXIS, AS5011_FUZZ, AS5011_FLAT);
|
||||
|
||||
error = gpio_request(as5011->button_gpio, "AS5011 button");
|
||||
if (error < 0) {
|
||||
dev_err(&client->dev, "Failed to request button gpio\n");
|
||||
as5011->button_gpiod = devm_gpiod_get(&client->dev, NULL, GPIOD_IN);
|
||||
if (IS_ERR(as5011->button_gpiod)) {
|
||||
error = PTR_ERR(as5011->button_gpiod);
|
||||
dev_err(&client->dev, "Failed to request button GPIO\n");
|
||||
goto err_free_mem;
|
||||
}
|
||||
gpiod_set_consumer_name(as5011->button_gpiod, "AS5011 button");
|
||||
|
||||
irq = gpio_to_irq(as5011->button_gpio);
|
||||
irq = gpiod_to_irq(as5011->button_gpiod);
|
||||
if (irq < 0) {
|
||||
dev_err(&client->dev,
|
||||
"Failed to get irq number for button gpio\n");
|
||||
error = irq;
|
||||
goto err_free_button_gpio;
|
||||
goto err_free_mem;
|
||||
}
|
||||
|
||||
as5011->button_irq = irq;
|
||||
@ -286,7 +287,7 @@ static int as5011_probe(struct i2c_client *client)
|
||||
if (error < 0) {
|
||||
dev_err(&client->dev,
|
||||
"Can't allocate button irq %d\n", as5011->button_irq);
|
||||
goto err_free_button_gpio;
|
||||
goto err_free_mem;
|
||||
}
|
||||
|
||||
error = as5011_configure_chip(as5011, plat_data);
|
||||
@ -317,8 +318,6 @@ err_free_axis_irq:
|
||||
free_irq(as5011->axis_irq, as5011);
|
||||
err_free_button_irq:
|
||||
free_irq(as5011->button_irq, as5011);
|
||||
err_free_button_gpio:
|
||||
gpio_free(as5011->button_gpio);
|
||||
err_free_mem:
|
||||
input_free_device(input_dev);
|
||||
kfree(as5011);
|
||||
@ -332,7 +331,6 @@ static void as5011_remove(struct i2c_client *client)
|
||||
|
||||
free_irq(as5011->axis_irq, as5011);
|
||||
free_irq(as5011->button_irq, as5011);
|
||||
gpio_free(as5011->button_gpio);
|
||||
|
||||
input_unregister_device(as5011->input_dev);
|
||||
kfree(as5011);
|
||||
|
@ -5,15 +5,17 @@
|
||||
* Copyright (C) 2018 Marcus Folkesson <marcus.folkesson@gmail.com>
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include <linux/usb.h>
|
||||
#include <linux/usb/input.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/input.h>
|
||||
|
||||
#define PXRC_VENDOR_ID 0x1781
|
||||
#define PXRC_PRODUCT_ID 0x0898
|
||||
@ -81,33 +83,28 @@ exit:
|
||||
static int pxrc_open(struct input_dev *input)
|
||||
{
|
||||
struct pxrc *pxrc = input_get_drvdata(input);
|
||||
int retval;
|
||||
int error;
|
||||
|
||||
mutex_lock(&pxrc->pm_mutex);
|
||||
retval = usb_submit_urb(pxrc->urb, GFP_KERNEL);
|
||||
if (retval) {
|
||||
guard(mutex)(&pxrc->pm_mutex);
|
||||
error = usb_submit_urb(pxrc->urb, GFP_KERNEL);
|
||||
if (error) {
|
||||
dev_err(&pxrc->intf->dev,
|
||||
"%s - usb_submit_urb failed, error: %d\n",
|
||||
__func__, retval);
|
||||
retval = -EIO;
|
||||
goto out;
|
||||
__func__, error);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
pxrc->is_open = true;
|
||||
|
||||
out:
|
||||
mutex_unlock(&pxrc->pm_mutex);
|
||||
return retval;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pxrc_close(struct input_dev *input)
|
||||
{
|
||||
struct pxrc *pxrc = input_get_drvdata(input);
|
||||
|
||||
mutex_lock(&pxrc->pm_mutex);
|
||||
guard(mutex)(&pxrc->pm_mutex);
|
||||
usb_kill_urb(pxrc->urb);
|
||||
pxrc->is_open = false;
|
||||
mutex_unlock(&pxrc->pm_mutex);
|
||||
}
|
||||
|
||||
static void pxrc_free_urb(void *_pxrc)
|
||||
@ -208,10 +205,9 @@ static int pxrc_suspend(struct usb_interface *intf, pm_message_t message)
|
||||
{
|
||||
struct pxrc *pxrc = usb_get_intfdata(intf);
|
||||
|
||||
mutex_lock(&pxrc->pm_mutex);
|
||||
guard(mutex)(&pxrc->pm_mutex);
|
||||
if (pxrc->is_open)
|
||||
usb_kill_urb(pxrc->urb);
|
||||
mutex_unlock(&pxrc->pm_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -219,14 +215,12 @@ static int pxrc_suspend(struct usb_interface *intf, pm_message_t message)
|
||||
static int pxrc_resume(struct usb_interface *intf)
|
||||
{
|
||||
struct pxrc *pxrc = usb_get_intfdata(intf);
|
||||
int retval = 0;
|
||||
|
||||
mutex_lock(&pxrc->pm_mutex);
|
||||
guard(mutex)(&pxrc->pm_mutex);
|
||||
if (pxrc->is_open && usb_submit_urb(pxrc->urb, GFP_KERNEL) < 0)
|
||||
retval = -EIO;
|
||||
return -EIO;
|
||||
|
||||
mutex_unlock(&pxrc->pm_mutex);
|
||||
return retval;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pxrc_pre_reset(struct usb_interface *intf)
|
||||
|
@ -1670,7 +1670,7 @@ static int xpad_led_probe(struct usb_xpad *xpad)
|
||||
if (!led)
|
||||
return -ENOMEM;
|
||||
|
||||
xpad->pad_nr = ida_simple_get(&xpad_pad_seq, 0, 0, GFP_KERNEL);
|
||||
xpad->pad_nr = ida_alloc(&xpad_pad_seq, GFP_KERNEL);
|
||||
if (xpad->pad_nr < 0) {
|
||||
error = xpad->pad_nr;
|
||||
goto err_free_mem;
|
||||
@ -1693,7 +1693,7 @@ static int xpad_led_probe(struct usb_xpad *xpad)
|
||||
return 0;
|
||||
|
||||
err_free_id:
|
||||
ida_simple_remove(&xpad_pad_seq, xpad->pad_nr);
|
||||
ida_free(&xpad_pad_seq, xpad->pad_nr);
|
||||
err_free_mem:
|
||||
kfree(led);
|
||||
xpad->led = NULL;
|
||||
@ -1706,7 +1706,7 @@ static void xpad_led_disconnect(struct usb_xpad *xpad)
|
||||
|
||||
if (xpad_led) {
|
||||
led_classdev_unregister(&xpad_led->led_cdev);
|
||||
ida_simple_remove(&xpad_pad_seq, xpad->pad_nr);
|
||||
ida_free(&xpad_pad_seq, xpad->pad_nr);
|
||||
kfree(xpad_led);
|
||||
}
|
||||
}
|
||||
|
@ -10,10 +10,11 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/leds.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/bitfield.h>
|
||||
|
||||
#define CAP11XX_REG_MAIN_CONTROL 0x00
|
||||
#define CAP11XX_REG_MAIN_CONTROL_GAIN_SHIFT (6)
|
||||
@ -24,6 +25,7 @@
|
||||
#define CAP11XX_REG_NOISE_FLAG_STATUS 0x0a
|
||||
#define CAP11XX_REG_SENOR_DELTA(X) (0x10 + (X))
|
||||
#define CAP11XX_REG_SENSITIVITY_CONTROL 0x1f
|
||||
#define CAP11XX_REG_SENSITIVITY_CONTROL_DELTA_SENSE_MASK 0x70
|
||||
#define CAP11XX_REG_CONFIG 0x20
|
||||
#define CAP11XX_REG_SENSOR_ENABLE 0x21
|
||||
#define CAP11XX_REG_SENSOR_CONFIG 0x22
|
||||
@ -32,6 +34,7 @@
|
||||
#define CAP11XX_REG_CALIBRATION 0x26
|
||||
#define CAP11XX_REG_INT_ENABLE 0x27
|
||||
#define CAP11XX_REG_REPEAT_RATE 0x28
|
||||
#define CAP11XX_REG_SIGNAL_GUARD_ENABLE 0x29
|
||||
#define CAP11XX_REG_MT_CONFIG 0x2a
|
||||
#define CAP11XX_REG_MT_PATTERN_CONFIG 0x2b
|
||||
#define CAP11XX_REG_MT_PATTERN 0x2d
|
||||
@ -47,6 +50,8 @@
|
||||
#define CAP11XX_REG_SENSOR_BASE_CNT(X) (0x50 + (X))
|
||||
#define CAP11XX_REG_LED_POLARITY 0x73
|
||||
#define CAP11XX_REG_LED_OUTPUT_CONTROL 0x74
|
||||
#define CAP11XX_REG_CALIB_SENSITIVITY_CONFIG 0x80
|
||||
#define CAP11XX_REG_CALIB_SENSITIVITY_CONFIG2 0x81
|
||||
|
||||
#define CAP11XX_REG_LED_DUTY_CYCLE_1 0x90
|
||||
#define CAP11XX_REG_LED_DUTY_CYCLE_2 0x91
|
||||
@ -78,12 +83,20 @@ struct cap11xx_led {
|
||||
|
||||
struct cap11xx_priv {
|
||||
struct regmap *regmap;
|
||||
struct device *dev;
|
||||
struct input_dev *idev;
|
||||
const struct cap11xx_hw_model *model;
|
||||
u8 id;
|
||||
|
||||
struct cap11xx_led *leds;
|
||||
int num_leds;
|
||||
|
||||
/* config */
|
||||
u8 analog_gain;
|
||||
u8 sensitivity_delta_sense;
|
||||
u8 signal_guard_inputs_mask;
|
||||
u32 thresholds[8];
|
||||
u32 calib_sensitivities[8];
|
||||
u32 keycodes[];
|
||||
};
|
||||
|
||||
@ -160,9 +173,6 @@ static bool cap11xx_volatile_reg(struct device *dev, unsigned int reg)
|
||||
case CAP11XX_REG_SENOR_DELTA(3):
|
||||
case CAP11XX_REG_SENOR_DELTA(4):
|
||||
case CAP11XX_REG_SENOR_DELTA(5):
|
||||
case CAP11XX_REG_PRODUCT_ID:
|
||||
case CAP11XX_REG_MANUFACTURER_ID:
|
||||
case CAP11XX_REG_REVISION:
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -177,10 +187,179 @@ static const struct regmap_config cap11xx_regmap_config = {
|
||||
.reg_defaults = cap11xx_reg_defaults,
|
||||
|
||||
.num_reg_defaults = ARRAY_SIZE(cap11xx_reg_defaults),
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
.cache_type = REGCACHE_MAPLE,
|
||||
.volatile_reg = cap11xx_volatile_reg,
|
||||
};
|
||||
|
||||
static int cap11xx_write_calib_sens_config_1(struct cap11xx_priv *priv)
|
||||
{
|
||||
return regmap_write(priv->regmap,
|
||||
CAP11XX_REG_CALIB_SENSITIVITY_CONFIG,
|
||||
(priv->calib_sensitivities[3] << 6) |
|
||||
(priv->calib_sensitivities[2] << 4) |
|
||||
(priv->calib_sensitivities[1] << 2) |
|
||||
priv->calib_sensitivities[0]);
|
||||
}
|
||||
|
||||
static int cap11xx_write_calib_sens_config_2(struct cap11xx_priv *priv)
|
||||
{
|
||||
return regmap_write(priv->regmap,
|
||||
CAP11XX_REG_CALIB_SENSITIVITY_CONFIG2,
|
||||
(priv->calib_sensitivities[7] << 6) |
|
||||
(priv->calib_sensitivities[6] << 4) |
|
||||
(priv->calib_sensitivities[5] << 2) |
|
||||
priv->calib_sensitivities[4]);
|
||||
}
|
||||
|
||||
static int cap11xx_init_keys(struct cap11xx_priv *priv)
|
||||
{
|
||||
struct device_node *node = priv->dev->of_node;
|
||||
struct device *dev = priv->dev;
|
||||
int i, error;
|
||||
u32 u32_val;
|
||||
|
||||
if (!node) {
|
||||
dev_err(dev, "Corresponding DT entry is not available\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!of_property_read_u32(node, "microchip,sensor-gain", &u32_val)) {
|
||||
if (priv->model->no_gain) {
|
||||
dev_warn(dev,
|
||||
"This model doesn't support 'sensor-gain'\n");
|
||||
} else if (is_power_of_2(u32_val) && u32_val <= 8) {
|
||||
priv->analog_gain = (u8)ilog2(u32_val);
|
||||
|
||||
error = regmap_update_bits(priv->regmap,
|
||||
CAP11XX_REG_MAIN_CONTROL,
|
||||
CAP11XX_REG_MAIN_CONTROL_GAIN_MASK,
|
||||
priv->analog_gain << CAP11XX_REG_MAIN_CONTROL_GAIN_SHIFT);
|
||||
if (error)
|
||||
return error;
|
||||
} else {
|
||||
dev_err(dev, "Invalid sensor-gain value %u\n", u32_val);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (of_property_read_bool(node, "microchip,irq-active-high")) {
|
||||
if (priv->id == CAP1106 ||
|
||||
priv->id == CAP1126 ||
|
||||
priv->id == CAP1188) {
|
||||
error = regmap_update_bits(priv->regmap,
|
||||
CAP11XX_REG_CONFIG2,
|
||||
CAP11XX_REG_CONFIG2_ALT_POL,
|
||||
0);
|
||||
if (error)
|
||||
return error;
|
||||
} else {
|
||||
dev_warn(dev,
|
||||
"This model doesn't support 'irq-active-high'\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (!of_property_read_u32(node, "microchip,sensitivity-delta-sense", &u32_val)) {
|
||||
if (!is_power_of_2(u32_val) || u32_val > 128) {
|
||||
dev_err(dev, "Invalid sensitivity-delta-sense value %u\n", u32_val);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
priv->sensitivity_delta_sense = (u8)ilog2(u32_val);
|
||||
u32_val = ~(FIELD_PREP(CAP11XX_REG_SENSITIVITY_CONTROL_DELTA_SENSE_MASK,
|
||||
priv->sensitivity_delta_sense));
|
||||
|
||||
error = regmap_update_bits(priv->regmap,
|
||||
CAP11XX_REG_SENSITIVITY_CONTROL,
|
||||
CAP11XX_REG_SENSITIVITY_CONTROL_DELTA_SENSE_MASK,
|
||||
u32_val);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
|
||||
if (!of_property_read_u32_array(node, "microchip,input-threshold",
|
||||
priv->thresholds, priv->model->num_channels)) {
|
||||
for (i = 0; i < priv->model->num_channels; i++) {
|
||||
if (priv->thresholds[i] > 127) {
|
||||
dev_err(dev, "Invalid input-threshold value %u\n",
|
||||
priv->thresholds[i]);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
error = regmap_write(priv->regmap,
|
||||
CAP11XX_REG_SENSOR_THRESH(i),
|
||||
priv->thresholds[i]);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
if (!of_property_read_u32_array(node, "microchip,calib-sensitivity",
|
||||
priv->calib_sensitivities,
|
||||
priv->model->num_channels)) {
|
||||
if (priv->id == CAP1293 || priv->id == CAP1298) {
|
||||
for (i = 0; i < priv->model->num_channels; i++) {
|
||||
if (!is_power_of_2(priv->calib_sensitivities[i]) ||
|
||||
priv->calib_sensitivities[i] > 4) {
|
||||
dev_err(dev, "Invalid calib-sensitivity value %u\n",
|
||||
priv->calib_sensitivities[i]);
|
||||
return -EINVAL;
|
||||
}
|
||||
priv->calib_sensitivities[i] = ilog2(priv->calib_sensitivities[i]);
|
||||
}
|
||||
|
||||
error = cap11xx_write_calib_sens_config_1(priv);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (priv->id == CAP1298) {
|
||||
error = cap11xx_write_calib_sens_config_2(priv);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
} else {
|
||||
dev_warn(dev,
|
||||
"This model doesn't support 'calib-sensitivity'\n");
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < priv->model->num_channels; i++) {
|
||||
if (!of_property_read_u32_index(node, "microchip,signal-guard",
|
||||
i, &u32_val)) {
|
||||
if (u32_val > 1)
|
||||
return -EINVAL;
|
||||
if (u32_val)
|
||||
priv->signal_guard_inputs_mask |= 0x01 << i;
|
||||
}
|
||||
}
|
||||
|
||||
if (priv->signal_guard_inputs_mask) {
|
||||
if (priv->id == CAP1293 || priv->id == CAP1298) {
|
||||
error = regmap_write(priv->regmap,
|
||||
CAP11XX_REG_SIGNAL_GUARD_ENABLE,
|
||||
priv->signal_guard_inputs_mask);
|
||||
if (error)
|
||||
return error;
|
||||
} else {
|
||||
dev_warn(dev,
|
||||
"This model doesn't support 'signal-guard'\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Provide some useful defaults */
|
||||
for (i = 0; i < priv->model->num_channels; i++)
|
||||
priv->keycodes[i] = KEY_A + i;
|
||||
|
||||
of_property_read_u32_array(node, "linux,keycodes",
|
||||
priv->keycodes, priv->model->num_channels);
|
||||
|
||||
/* Disable autorepeat. The Linux input system has its own handling. */
|
||||
error = regmap_write(priv->regmap, CAP11XX_REG_REPEAT_RATE, 0);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t cap11xx_thread_func(int irq_num, void *data)
|
||||
{
|
||||
struct cap11xx_priv *priv = data;
|
||||
@ -332,11 +511,9 @@ static int cap11xx_i2c_probe(struct i2c_client *i2c_client)
|
||||
const struct i2c_device_id *id = i2c_client_get_device_id(i2c_client);
|
||||
struct device *dev = &i2c_client->dev;
|
||||
struct cap11xx_priv *priv;
|
||||
struct device_node *node;
|
||||
const struct cap11xx_hw_model *cap;
|
||||
int i, error, irq, gain = 0;
|
||||
int i, error;
|
||||
unsigned int val, rev;
|
||||
u32 gain32;
|
||||
|
||||
if (id->driver_data >= ARRAY_SIZE(cap11xx_devices)) {
|
||||
dev_err(dev, "Invalid device ID %lu\n", id->driver_data);
|
||||
@ -355,6 +532,8 @@ static int cap11xx_i2c_probe(struct i2c_client *i2c_client)
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->dev = dev;
|
||||
|
||||
priv->regmap = devm_regmap_init_i2c(i2c_client, &cap11xx_regmap_config);
|
||||
if (IS_ERR(priv->regmap))
|
||||
return PTR_ERR(priv->regmap);
|
||||
@ -384,50 +563,15 @@ static int cap11xx_i2c_probe(struct i2c_client *i2c_client)
|
||||
return error;
|
||||
|
||||
dev_info(dev, "CAP11XX detected, model %s, revision 0x%02x\n",
|
||||
id->name, rev);
|
||||
|
||||
priv->model = cap;
|
||||
priv->id = id->driver_data;
|
||||
|
||||
dev_info(dev, "CAP11XX device detected, model %s, revision 0x%02x\n",
|
||||
id->name, rev);
|
||||
node = dev->of_node;
|
||||
|
||||
if (!of_property_read_u32(node, "microchip,sensor-gain", &gain32)) {
|
||||
if (cap->no_gain)
|
||||
dev_warn(dev,
|
||||
"This version doesn't support sensor gain\n");
|
||||
else if (is_power_of_2(gain32) && gain32 <= 8)
|
||||
gain = ilog2(gain32);
|
||||
else
|
||||
dev_err(dev, "Invalid sensor-gain value %d\n", gain32);
|
||||
}
|
||||
|
||||
if (id->driver_data == CAP1106 ||
|
||||
id->driver_data == CAP1126 ||
|
||||
id->driver_data == CAP1188) {
|
||||
if (of_property_read_bool(node, "microchip,irq-active-high")) {
|
||||
error = regmap_update_bits(priv->regmap,
|
||||
CAP11XX_REG_CONFIG2,
|
||||
CAP11XX_REG_CONFIG2_ALT_POL,
|
||||
0);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
/* Provide some useful defaults */
|
||||
for (i = 0; i < cap->num_channels; i++)
|
||||
priv->keycodes[i] = KEY_A + i;
|
||||
|
||||
of_property_read_u32_array(node, "linux,keycodes",
|
||||
priv->keycodes, cap->num_channels);
|
||||
|
||||
if (!cap->no_gain) {
|
||||
error = regmap_update_bits(priv->regmap,
|
||||
CAP11XX_REG_MAIN_CONTROL,
|
||||
CAP11XX_REG_MAIN_CONTROL_GAIN_MASK,
|
||||
gain << CAP11XX_REG_MAIN_CONTROL_GAIN_SHIFT);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Disable autorepeat. The Linux input system has its own handling. */
|
||||
error = regmap_write(priv->regmap, CAP11XX_REG_REPEAT_RATE, 0);
|
||||
error = cap11xx_init_keys(priv);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
@ -439,7 +583,7 @@ static int cap11xx_i2c_probe(struct i2c_client *i2c_client)
|
||||
priv->idev->id.bustype = BUS_I2C;
|
||||
priv->idev->evbit[0] = BIT_MASK(EV_KEY);
|
||||
|
||||
if (of_property_read_bool(node, "autorepeat"))
|
||||
if (of_property_read_bool(dev->of_node, "autorepeat"))
|
||||
__set_bit(EV_REP, priv->idev->evbit);
|
||||
|
||||
for (i = 0; i < cap->num_channels; i++)
|
||||
@ -474,13 +618,8 @@ static int cap11xx_i2c_probe(struct i2c_client *i2c_client)
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
irq = irq_of_parse_and_map(node, 0);
|
||||
if (!irq) {
|
||||
dev_err(dev, "Unable to parse or map IRQ\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
error = devm_request_threaded_irq(dev, irq, NULL, cap11xx_thread_func,
|
||||
error = devm_request_threaded_irq(dev, i2c_client->irq,
|
||||
NULL, cap11xx_thread_func,
|
||||
IRQF_ONESHOT, dev_name(dev), priv);
|
||||
if (error)
|
||||
return error;
|
||||
|
@ -45,7 +45,9 @@ struct gpio_button_data {
|
||||
unsigned int software_debounce; /* in msecs, for GPIO-driven buttons */
|
||||
|
||||
unsigned int irq;
|
||||
unsigned int wakeirq;
|
||||
unsigned int wakeup_trigger_type;
|
||||
|
||||
spinlock_t lock;
|
||||
bool disabled;
|
||||
bool key_pressed;
|
||||
@ -511,6 +513,7 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
|
||||
struct gpio_button_data *bdata = &ddata->data[idx];
|
||||
irq_handler_t isr;
|
||||
unsigned long irqflags;
|
||||
const char *wakedesc;
|
||||
int irq;
|
||||
int error;
|
||||
|
||||
@ -575,15 +578,23 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
|
||||
!gpiod_cansleep(bdata->gpiod);
|
||||
}
|
||||
|
||||
/*
|
||||
* If an interrupt was specified, use it instead of the gpio
|
||||
* interrupt and use the gpio for reading the state. A separate
|
||||
* interrupt may be used as the main button interrupt for
|
||||
* runtime PM to detect events also in deeper idle states. If a
|
||||
* dedicated wakeirq is used for system suspend only, see below
|
||||
* for bdata->wakeirq setup.
|
||||
*/
|
||||
if (button->irq) {
|
||||
bdata->irq = button->irq;
|
||||
} else {
|
||||
irq = gpiod_to_irq(bdata->gpiod);
|
||||
if (irq < 0) {
|
||||
error = irq;
|
||||
dev_err(dev,
|
||||
"Unable to get irq number for GPIO %d, error %d\n",
|
||||
button->gpio, error);
|
||||
dev_err_probe(dev, error,
|
||||
"Unable to get irq number for GPIO %d\n",
|
||||
button->gpio);
|
||||
return error;
|
||||
}
|
||||
bdata->irq = irq;
|
||||
@ -672,6 +683,36 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
|
||||
return error;
|
||||
}
|
||||
|
||||
if (!button->wakeirq)
|
||||
return 0;
|
||||
|
||||
/* Use :wakeup suffix like drivers/base/power/wakeirq.c does */
|
||||
wakedesc = devm_kasprintf(dev, GFP_KERNEL, "%s:wakeup", desc);
|
||||
if (!wakedesc)
|
||||
return -ENOMEM;
|
||||
|
||||
bdata->wakeirq = button->wakeirq;
|
||||
irqflags |= IRQF_NO_SUSPEND;
|
||||
|
||||
/*
|
||||
* Wakeirq shares the handler with the main interrupt, it's only
|
||||
* active during system suspend. See gpio_keys_button_enable_wakeup()
|
||||
* and gpio_keys_button_disable_wakeup().
|
||||
*/
|
||||
error = devm_request_any_context_irq(dev, bdata->wakeirq, isr,
|
||||
irqflags, wakedesc, bdata);
|
||||
if (error < 0) {
|
||||
dev_err(dev, "Unable to claim wakeirq %d; error %d\n",
|
||||
bdata->irq, error);
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable wakeirq until suspend. IRQF_NO_AUTOEN won't work if
|
||||
* IRQF_SHARED was set based on !button->can_disable.
|
||||
*/
|
||||
disable_irq(bdata->wakeirq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -728,7 +769,7 @@ gpio_keys_get_devtree_pdata(struct device *dev)
|
||||
struct gpio_keys_platform_data *pdata;
|
||||
struct gpio_keys_button *button;
|
||||
struct fwnode_handle *child;
|
||||
int nbuttons;
|
||||
int nbuttons, irq;
|
||||
|
||||
nbuttons = device_get_child_node_count(dev);
|
||||
if (nbuttons == 0)
|
||||
@ -750,9 +791,19 @@ gpio_keys_get_devtree_pdata(struct device *dev)
|
||||
device_property_read_string(dev, "label", &pdata->name);
|
||||
|
||||
device_for_each_child_node(dev, child) {
|
||||
if (is_of_node(child))
|
||||
button->irq =
|
||||
irq_of_parse_and_map(to_of_node(child), 0);
|
||||
if (is_of_node(child)) {
|
||||
irq = of_irq_get_byname(to_of_node(child), "irq");
|
||||
if (irq > 0)
|
||||
button->irq = irq;
|
||||
|
||||
irq = of_irq_get_byname(to_of_node(child), "wakeup");
|
||||
if (irq > 0)
|
||||
button->wakeirq = irq;
|
||||
|
||||
if (!button->irq && !button->wakeirq)
|
||||
button->irq =
|
||||
irq_of_parse_and_map(to_of_node(child), 0);
|
||||
}
|
||||
|
||||
if (fwnode_property_read_u32(child, "linux,code",
|
||||
&button->code)) {
|
||||
@ -921,6 +972,11 @@ gpio_keys_button_enable_wakeup(struct gpio_button_data *bdata)
|
||||
}
|
||||
}
|
||||
|
||||
if (bdata->wakeirq) {
|
||||
enable_irq(bdata->wakeirq);
|
||||
disable_irq(bdata->irq);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -929,6 +985,11 @@ gpio_keys_button_disable_wakeup(struct gpio_button_data *bdata)
|
||||
{
|
||||
int error;
|
||||
|
||||
if (bdata->wakeirq) {
|
||||
enable_irq(bdata->irq);
|
||||
disable_irq(bdata->wakeirq);
|
||||
}
|
||||
|
||||
/*
|
||||
* The trigger type is always both edges for gpio-based keys and we do
|
||||
* not support changing wakeup trigger for interrupt-based keys.
|
||||
|
@ -21,7 +21,6 @@
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/platform_data/gpio-omap.h>
|
||||
#include <linux/platform_data/keypad-omap.h>
|
||||
#include <linux/soc/ti/omap1-io.h>
|
||||
@ -49,9 +48,6 @@ struct omap_kp {
|
||||
|
||||
static DECLARE_TASKLET_DISABLED_OLD(kp_tasklet, omap_kp_tasklet);
|
||||
|
||||
static unsigned int *row_gpios;
|
||||
static unsigned int *col_gpios;
|
||||
|
||||
static irqreturn_t omap_kp_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
/* disable keyboard interrupt and schedule for handling */
|
||||
@ -180,7 +176,7 @@ static int omap_kp_probe(struct platform_device *pdev)
|
||||
struct omap_kp *omap_kp;
|
||||
struct input_dev *input_dev;
|
||||
struct omap_kp_platform_data *pdata = dev_get_platdata(&pdev->dev);
|
||||
int i, col_idx, row_idx, ret;
|
||||
int ret;
|
||||
unsigned int row_shift, keycodemax;
|
||||
|
||||
if (!pdata->rows || !pdata->cols || !pdata->keymap_data) {
|
||||
@ -209,17 +205,9 @@ static int omap_kp_probe(struct platform_device *pdev)
|
||||
if (pdata->delay)
|
||||
omap_kp->delay = pdata->delay;
|
||||
|
||||
if (pdata->row_gpios && pdata->col_gpios) {
|
||||
row_gpios = pdata->row_gpios;
|
||||
col_gpios = pdata->col_gpios;
|
||||
}
|
||||
|
||||
omap_kp->rows = pdata->rows;
|
||||
omap_kp->cols = pdata->cols;
|
||||
|
||||
col_idx = 0;
|
||||
row_idx = 0;
|
||||
|
||||
timer_setup(&omap_kp->timer, omap_kp_timer, 0);
|
||||
|
||||
/* get the irq and init timer*/
|
||||
@ -276,11 +264,6 @@ err4:
|
||||
err3:
|
||||
device_remove_file(&pdev->dev, &dev_attr_enable);
|
||||
err2:
|
||||
for (i = row_idx - 1; i >= 0; i--)
|
||||
gpio_free(row_gpios[i]);
|
||||
for (i = col_idx - 1; i >= 0; i--)
|
||||
gpio_free(col_gpios[i]);
|
||||
|
||||
kfree(omap_kp);
|
||||
input_free_device(input_dev);
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
@ -83,6 +84,7 @@ struct omap4_keypad {
|
||||
bool no_autorepeat;
|
||||
u64 keys;
|
||||
unsigned short *keymap;
|
||||
struct clk *fck;
|
||||
};
|
||||
|
||||
static int kbd_readl(struct omap4_keypad *keypad_data, u32 offset)
|
||||
@ -209,6 +211,10 @@ static int omap4_keypad_open(struct input_dev *input)
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
error = clk_prepare_enable(keypad_data->fck);
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
disable_irq(keypad_data->irq);
|
||||
|
||||
kbd_writel(keypad_data, OMAP4_KBD_CTRL,
|
||||
@ -226,10 +232,11 @@ static int omap4_keypad_open(struct input_dev *input)
|
||||
|
||||
enable_irq(keypad_data->irq);
|
||||
|
||||
out:
|
||||
pm_runtime_mark_last_busy(dev);
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
|
||||
return 0;
|
||||
return error;
|
||||
}
|
||||
|
||||
static void omap4_keypad_stop(struct omap4_keypad *keypad_data)
|
||||
@ -258,6 +265,7 @@ static void omap4_keypad_close(struct input_dev *input)
|
||||
disable_irq(keypad_data->irq);
|
||||
omap4_keypad_stop(keypad_data);
|
||||
enable_irq(keypad_data->irq);
|
||||
clk_disable_unprepare(keypad_data->fck);
|
||||
|
||||
pm_runtime_mark_last_busy(dev);
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
@ -356,6 +364,11 @@ static int omap4_keypad_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
keypad_data->irq = irq;
|
||||
keypad_data->fck = devm_clk_get(&pdev->dev, "fck");
|
||||
if (IS_ERR(keypad_data->fck))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(keypad_data->fck),
|
||||
"unable to get fck");
|
||||
|
||||
mutex_init(&keypad_data->lock);
|
||||
platform_set_drvdata(pdev, keypad_data);
|
||||
|
||||
|
@ -213,7 +213,7 @@ static struct regmap_config qt1050_regmap_config = {
|
||||
.val_bits = 8,
|
||||
.max_register = QT1050_RES_CAL,
|
||||
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
.cache_type = REGCACHE_MAPLE,
|
||||
|
||||
.wr_table = &qt1050_writeable_table,
|
||||
.rd_table = &qt1050_readable_table,
|
||||
|
@ -14,7 +14,6 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/tca6416_keypad.h>
|
||||
|
@ -9,11 +9,12 @@
|
||||
#include <linux/errno.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_wakeirq.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/mfd/da9063/core.h>
|
||||
#include <linux/mfd/da9063/registers.h>
|
||||
#include <linux/mfd/da9062/core.h>
|
||||
@ -74,13 +75,6 @@ static const struct da906x_chip_config da9062_regs = {
|
||||
.name = "da9062-onkey",
|
||||
};
|
||||
|
||||
static const struct of_device_id da9063_compatible_reg_id_table[] = {
|
||||
{ .compatible = "dlg,da9063-onkey", .data = &da9063_regs },
|
||||
{ .compatible = "dlg,da9062-onkey", .data = &da9062_regs },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, da9063_compatible_reg_id_table);
|
||||
|
||||
static void da9063_poll_on(struct work_struct *work)
|
||||
{
|
||||
struct da9063_onkey *onkey = container_of(work,
|
||||
@ -187,56 +181,43 @@ static irqreturn_t da9063_onkey_irq_handler(int irq, void *data)
|
||||
static int da9063_onkey_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct da9063_onkey *onkey;
|
||||
const struct of_device_id *match;
|
||||
int irq;
|
||||
int error;
|
||||
|
||||
match = of_match_node(da9063_compatible_reg_id_table,
|
||||
pdev->dev.of_node);
|
||||
if (!match)
|
||||
return -ENXIO;
|
||||
int irq;
|
||||
|
||||
onkey = devm_kzalloc(&pdev->dev, sizeof(struct da9063_onkey),
|
||||
GFP_KERNEL);
|
||||
if (!onkey) {
|
||||
dev_err(&pdev->dev, "Failed to allocate memory.\n");
|
||||
if (!onkey)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
onkey->config = match->data;
|
||||
onkey->config = device_get_match_data(&pdev->dev);
|
||||
if (!onkey->config)
|
||||
return -ENXIO;
|
||||
|
||||
onkey->dev = &pdev->dev;
|
||||
|
||||
onkey->regmap = dev_get_regmap(pdev->dev.parent, NULL);
|
||||
if (!onkey->regmap) {
|
||||
dev_err(&pdev->dev, "Parent regmap unavailable.\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
if (!onkey->regmap)
|
||||
return dev_err_probe(&pdev->dev, -ENXIO,
|
||||
"Parent regmap unavailable.\n");
|
||||
|
||||
onkey->key_power = !of_property_read_bool(pdev->dev.of_node,
|
||||
"dlg,disable-key-power");
|
||||
onkey->key_power = !device_property_read_bool(&pdev->dev,
|
||||
"dlg,disable-key-power");
|
||||
|
||||
onkey->input = devm_input_allocate_device(&pdev->dev);
|
||||
if (!onkey->input) {
|
||||
dev_err(&pdev->dev, "Failed to allocated input device.\n");
|
||||
if (!onkey->input)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
onkey->input->name = onkey->config->name;
|
||||
snprintf(onkey->phys, sizeof(onkey->phys), "%s/input0",
|
||||
onkey->config->name);
|
||||
onkey->input->phys = onkey->phys;
|
||||
onkey->input->dev.parent = &pdev->dev;
|
||||
|
||||
input_set_capability(onkey->input, EV_KEY, KEY_POWER);
|
||||
|
||||
error = devm_delayed_work_autocancel(&pdev->dev, &onkey->work,
|
||||
da9063_poll_on);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev,
|
||||
"Failed to add cancel poll action: %d\n",
|
||||
error);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
|
||||
irq = platform_get_irq_byname(pdev, "ONKEY");
|
||||
if (irq < 0)
|
||||
@ -246,11 +227,9 @@ static int da9063_onkey_probe(struct platform_device *pdev)
|
||||
NULL, da9063_onkey_irq_handler,
|
||||
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
|
||||
"ONKEY", onkey);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev,
|
||||
"Failed to request IRQ %d: %d\n", irq, error);
|
||||
return error;
|
||||
}
|
||||
if (error)
|
||||
return dev_err_probe(&pdev->dev, error,
|
||||
"Failed to allocate onkey IRQ\n");
|
||||
|
||||
error = dev_pm_set_wake_irq(&pdev->dev, irq);
|
||||
if (error)
|
||||
@ -261,15 +240,19 @@ static int da9063_onkey_probe(struct platform_device *pdev)
|
||||
device_init_wakeup(&pdev->dev, true);
|
||||
|
||||
error = input_register_device(onkey->input);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev,
|
||||
"Failed to register input device: %d\n", error);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id da9063_compatible_reg_id_table[] = {
|
||||
{ .compatible = "dlg,da9063-onkey", .data = &da9063_regs },
|
||||
{ .compatible = "dlg,da9062-onkey", .data = &da9062_regs },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, da9063_compatible_reg_id_table);
|
||||
|
||||
static struct platform_driver da9063_onkey_driver = {
|
||||
.probe = da9063_onkey_probe,
|
||||
.driver = {
|
||||
|
@ -1050,7 +1050,7 @@ static ssize_t ims_pcu_attribute_show(struct device *dev,
|
||||
container_of(dattr, struct ims_pcu_attribute, dattr);
|
||||
char *field = (char *)pcu + attr->field_offset;
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%.*s\n", attr->field_length, field);
|
||||
return sysfs_emit(buf, "%.*s\n", attr->field_length, field);
|
||||
}
|
||||
|
||||
static ssize_t ims_pcu_attribute_store(struct device *dev,
|
||||
@ -1206,7 +1206,7 @@ ims_pcu_update_firmware_status_show(struct device *dev,
|
||||
struct usb_interface *intf = to_usb_interface(dev);
|
||||
struct ims_pcu *pcu = usb_get_intfdata(intf);
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", pcu->update_firmware_status);
|
||||
return sysfs_emit(buf, "%d\n", pcu->update_firmware_status);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(update_firmware_status, S_IRUGO,
|
||||
@ -1309,7 +1309,7 @@ static ssize_t ims_pcu_ofn_reg_data_show(struct device *dev,
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%x\n", data);
|
||||
return sysfs_emit(buf, "%x\n", data);
|
||||
}
|
||||
|
||||
static ssize_t ims_pcu_ofn_reg_data_store(struct device *dev,
|
||||
@ -1344,7 +1344,7 @@ static ssize_t ims_pcu_ofn_reg_addr_show(struct device *dev,
|
||||
int error;
|
||||
|
||||
mutex_lock(&pcu->cmd_mutex);
|
||||
error = scnprintf(buf, PAGE_SIZE, "%x\n", pcu->ofn_reg_addr);
|
||||
error = sysfs_emit(buf, "%x\n", pcu->ofn_reg_addr);
|
||||
mutex_unlock(&pcu->cmd_mutex);
|
||||
|
||||
return error;
|
||||
@ -1397,7 +1397,7 @@ static ssize_t ims_pcu_ofn_bit_show(struct device *dev,
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", !!(data & (1 << attr->nr)));
|
||||
return sysfs_emit(buf, "%d\n", !!(data & (1 << attr->nr)));
|
||||
}
|
||||
|
||||
static ssize_t ims_pcu_ofn_bit_store(struct device *dev,
|
||||
|
@ -9,6 +9,7 @@
|
||||
* axial sliders presented by the device.
|
||||
*/
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
@ -26,6 +27,8 @@
|
||||
|
||||
#define IQS269_VER_INFO 0x00
|
||||
#define IQS269_VER_INFO_PROD_NUM 0x4F
|
||||
#define IQS269_VER_INFO_FW_NUM_2 0x03
|
||||
#define IQS269_VER_INFO_FW_NUM_3 0x10
|
||||
|
||||
#define IQS269_SYS_FLAGS 0x02
|
||||
#define IQS269_SYS_FLAGS_SHOW_RESET BIT(15)
|
||||
@ -53,6 +56,7 @@
|
||||
#define IQS269_SYS_SETTINGS_ULP_UPDATE_MASK GENMASK(10, 8)
|
||||
#define IQS269_SYS_SETTINGS_ULP_UPDATE_SHIFT 8
|
||||
#define IQS269_SYS_SETTINGS_ULP_UPDATE_MAX 7
|
||||
#define IQS269_SYS_SETTINGS_SLIDER_SWIPE BIT(7)
|
||||
#define IQS269_SYS_SETTINGS_RESEED_OFFSET BIT(6)
|
||||
#define IQS269_SYS_SETTINGS_EVENT_MODE BIT(5)
|
||||
#define IQS269_SYS_SETTINGS_EVENT_MODE_LP BIT(4)
|
||||
@ -69,6 +73,7 @@
|
||||
#define IQS269_FILT_STR_MAX 3
|
||||
|
||||
#define IQS269_EVENT_MASK_SYS BIT(6)
|
||||
#define IQS269_EVENT_MASK_GESTURE BIT(3)
|
||||
#define IQS269_EVENT_MASK_DEEP BIT(2)
|
||||
#define IQS269_EVENT_MASK_TOUCH BIT(1)
|
||||
#define IQS269_EVENT_MASK_PROX BIT(0)
|
||||
@ -97,6 +102,15 @@
|
||||
#define IQS269_MISC_B_TRACKING_UI_ENABLE BIT(4)
|
||||
#define IQS269_MISC_B_FILT_STR_SLIDER GENMASK(1, 0)
|
||||
|
||||
#define IQS269_TOUCH_HOLD_SLIDER_SEL 0x89
|
||||
#define IQS269_TOUCH_HOLD_DEFAULT 0x14
|
||||
#define IQS269_TOUCH_HOLD_MS_MIN 256
|
||||
#define IQS269_TOUCH_HOLD_MS_MAX 65280
|
||||
|
||||
#define IQS269_TIMEOUT_TAP_MS_MAX 4080
|
||||
#define IQS269_TIMEOUT_SWIPE_MS_MAX 4080
|
||||
#define IQS269_THRESH_SWIPE_MAX 255
|
||||
|
||||
#define IQS269_CHx_ENG_A_MEAS_CAP_SIZE BIT(15)
|
||||
#define IQS269_CHx_ENG_A_RX_GND_INACTIVE BIT(13)
|
||||
#define IQS269_CHx_ENG_A_LOCAL_CAP_SIZE BIT(12)
|
||||
@ -142,6 +156,10 @@
|
||||
|
||||
#define IQS269_MAX_REG 0xFF
|
||||
|
||||
#define IQS269_OTP_OPTION_DEFAULT 0x00
|
||||
#define IQS269_OTP_OPTION_TWS 0xD0
|
||||
#define IQS269_OTP_OPTION_HOLD BIT(7)
|
||||
|
||||
#define IQS269_NUM_CH 8
|
||||
#define IQS269_NUM_SL 2
|
||||
|
||||
@ -175,6 +193,20 @@ enum iqs269_event_id {
|
||||
IQS269_EVENT_DEEP_UP,
|
||||
};
|
||||
|
||||
enum iqs269_slider_id {
|
||||
IQS269_SLIDER_NONE,
|
||||
IQS269_SLIDER_KEY,
|
||||
IQS269_SLIDER_RAW,
|
||||
};
|
||||
|
||||
enum iqs269_gesture_id {
|
||||
IQS269_GESTURE_TAP,
|
||||
IQS269_GESTURE_HOLD,
|
||||
IQS269_GESTURE_FLICK_POS,
|
||||
IQS269_GESTURE_FLICK_NEG,
|
||||
IQS269_NUM_GESTURES,
|
||||
};
|
||||
|
||||
struct iqs269_switch_desc {
|
||||
unsigned int code;
|
||||
bool enabled;
|
||||
@ -234,7 +266,7 @@ struct iqs269_ver_info {
|
||||
u8 prod_num;
|
||||
u8 sw_num;
|
||||
u8 hw_num;
|
||||
u8 padding;
|
||||
u8 fw_num;
|
||||
} __packed;
|
||||
|
||||
struct iqs269_ch_reg {
|
||||
@ -285,16 +317,42 @@ struct iqs269_private {
|
||||
struct regmap *regmap;
|
||||
struct mutex lock;
|
||||
struct iqs269_switch_desc switches[ARRAY_SIZE(iqs269_events)];
|
||||
struct iqs269_ver_info ver_info;
|
||||
struct iqs269_sys_reg sys_reg;
|
||||
struct completion ati_done;
|
||||
struct input_dev *keypad;
|
||||
struct input_dev *slider[IQS269_NUM_SL];
|
||||
unsigned int keycode[ARRAY_SIZE(iqs269_events) * IQS269_NUM_CH];
|
||||
unsigned int sl_code[IQS269_NUM_SL][IQS269_NUM_GESTURES];
|
||||
unsigned int otp_option;
|
||||
unsigned int ch_num;
|
||||
bool hall_enable;
|
||||
bool ati_current;
|
||||
};
|
||||
|
||||
static enum iqs269_slider_id iqs269_slider_type(struct iqs269_private *iqs269,
|
||||
int slider_num)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Slider 1 is unavailable if the touch-and-hold option is enabled via
|
||||
* OTP. In that case, the channel selection register is repurposed for
|
||||
* the touch-and-hold timer ceiling.
|
||||
*/
|
||||
if (slider_num && (iqs269->otp_option & IQS269_OTP_OPTION_HOLD))
|
||||
return IQS269_SLIDER_NONE;
|
||||
|
||||
if (!iqs269->sys_reg.slider_select[slider_num])
|
||||
return IQS269_SLIDER_NONE;
|
||||
|
||||
for (i = 0; i < IQS269_NUM_GESTURES; i++)
|
||||
if (iqs269->sl_code[slider_num][i] != KEY_RESERVED)
|
||||
return IQS269_SLIDER_KEY;
|
||||
|
||||
return IQS269_SLIDER_RAW;
|
||||
}
|
||||
|
||||
static int iqs269_ati_mode_set(struct iqs269_private *iqs269,
|
||||
unsigned int ch_num, unsigned int mode)
|
||||
{
|
||||
@ -525,7 +583,8 @@ static int iqs269_parse_chan(struct iqs269_private *iqs269,
|
||||
if (fwnode_property_present(ch_node, "azoteq,slider0-select"))
|
||||
iqs269->sys_reg.slider_select[0] |= BIT(reg);
|
||||
|
||||
if (fwnode_property_present(ch_node, "azoteq,slider1-select"))
|
||||
if (fwnode_property_present(ch_node, "azoteq,slider1-select") &&
|
||||
!(iqs269->otp_option & IQS269_OTP_OPTION_HOLD))
|
||||
iqs269->sys_reg.slider_select[1] |= BIT(reg);
|
||||
|
||||
ch_reg = &iqs269->sys_reg.ch_reg[reg];
|
||||
@ -950,7 +1009,43 @@ static int iqs269_parse_prop(struct iqs269_private *iqs269)
|
||||
sys_reg->blocking = 0;
|
||||
|
||||
sys_reg->slider_select[0] = 0;
|
||||
sys_reg->slider_select[1] = 0;
|
||||
|
||||
/*
|
||||
* If configured via OTP to do so, the device asserts a pulse on the
|
||||
* GPIO4 pin for approximately 60 ms once a selected channel is held
|
||||
* in a state of touch for a configurable length of time.
|
||||
*
|
||||
* In that case, the register used for slider 1 channel selection is
|
||||
* repurposed for the touch-and-hold timer ceiling.
|
||||
*/
|
||||
if (iqs269->otp_option & IQS269_OTP_OPTION_HOLD) {
|
||||
if (!device_property_read_u32(&client->dev,
|
||||
"azoteq,touch-hold-ms", &val)) {
|
||||
if (val < IQS269_TOUCH_HOLD_MS_MIN ||
|
||||
val > IQS269_TOUCH_HOLD_MS_MAX) {
|
||||
dev_err(&client->dev,
|
||||
"Invalid touch-and-hold ceiling: %u\n",
|
||||
val);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sys_reg->slider_select[1] = val / 256;
|
||||
} else if (iqs269->ver_info.fw_num < IQS269_VER_INFO_FW_NUM_3) {
|
||||
/*
|
||||
* The default touch-and-hold timer ceiling initially
|
||||
* read from early revisions of silicon is invalid if
|
||||
* the device experienced a soft reset between power-
|
||||
* on and the read operation.
|
||||
*
|
||||
* To protect against this case, explicitly cache the
|
||||
* default value so that it is restored each time the
|
||||
* device is re-initialized.
|
||||
*/
|
||||
sys_reg->slider_select[1] = IQS269_TOUCH_HOLD_DEFAULT;
|
||||
}
|
||||
} else {
|
||||
sys_reg->slider_select[1] = 0;
|
||||
}
|
||||
|
||||
sys_reg->event_mask = ~((u8)IQS269_EVENT_MASK_SYS);
|
||||
|
||||
@ -1004,6 +1099,76 @@ static int iqs269_parse_prop(struct iqs269_private *iqs269)
|
||||
general |= (val << IQS269_SYS_SETTINGS_ULP_UPDATE_SHIFT);
|
||||
}
|
||||
|
||||
if (device_property_present(&client->dev, "linux,keycodes")) {
|
||||
int scale = 1;
|
||||
int count = device_property_count_u32(&client->dev,
|
||||
"linux,keycodes");
|
||||
if (count > IQS269_NUM_GESTURES * IQS269_NUM_SL) {
|
||||
dev_err(&client->dev, "Too many keycodes present\n");
|
||||
return -EINVAL;
|
||||
} else if (count < 0) {
|
||||
dev_err(&client->dev, "Failed to count keycodes: %d\n",
|
||||
count);
|
||||
return count;
|
||||
}
|
||||
|
||||
error = device_property_read_u32_array(&client->dev,
|
||||
"linux,keycodes",
|
||||
*iqs269->sl_code, count);
|
||||
if (error) {
|
||||
dev_err(&client->dev, "Failed to read keycodes: %d\n",
|
||||
error);
|
||||
return error;
|
||||
}
|
||||
|
||||
if (device_property_present(&client->dev,
|
||||
"azoteq,gesture-swipe"))
|
||||
general |= IQS269_SYS_SETTINGS_SLIDER_SWIPE;
|
||||
|
||||
/*
|
||||
* Early revisions of silicon use a more granular step size for
|
||||
* tap and swipe gesture timeouts; scale them appropriately.
|
||||
*/
|
||||
if (iqs269->ver_info.fw_num < IQS269_VER_INFO_FW_NUM_3)
|
||||
scale = 4;
|
||||
|
||||
if (!device_property_read_u32(&client->dev,
|
||||
"azoteq,timeout-tap-ms", &val)) {
|
||||
if (val > IQS269_TIMEOUT_TAP_MS_MAX / scale) {
|
||||
dev_err(&client->dev, "Invalid timeout: %u\n",
|
||||
val);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sys_reg->timeout_tap = val / (16 / scale);
|
||||
}
|
||||
|
||||
if (!device_property_read_u32(&client->dev,
|
||||
"azoteq,timeout-swipe-ms",
|
||||
&val)) {
|
||||
if (val > IQS269_TIMEOUT_SWIPE_MS_MAX / scale) {
|
||||
dev_err(&client->dev, "Invalid timeout: %u\n",
|
||||
val);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sys_reg->timeout_swipe = val / (16 / scale);
|
||||
}
|
||||
|
||||
if (!device_property_read_u32(&client->dev,
|
||||
"azoteq,thresh-swipe", &val)) {
|
||||
if (val > IQS269_THRESH_SWIPE_MAX) {
|
||||
dev_err(&client->dev, "Invalid threshold: %u\n",
|
||||
val);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sys_reg->thresh_swipe = val;
|
||||
}
|
||||
|
||||
sys_reg->event_mask &= ~IQS269_EVENT_MASK_GESTURE;
|
||||
}
|
||||
|
||||
general &= ~IQS269_SYS_SETTINGS_RESEED_OFFSET;
|
||||
if (device_property_present(&client->dev, "azoteq,reseed-offset"))
|
||||
general |= IQS269_SYS_SETTINGS_RESEED_OFFSET;
|
||||
@ -1012,10 +1177,11 @@ static int iqs269_parse_prop(struct iqs269_private *iqs269)
|
||||
|
||||
/*
|
||||
* As per the datasheet, enable streaming during normal-power mode if
|
||||
* either slider is in use. In that case, the device returns to event
|
||||
* mode during low-power mode.
|
||||
* raw coordinates will be read from either slider. In that case, the
|
||||
* device returns to event mode during low-power mode.
|
||||
*/
|
||||
if (sys_reg->slider_select[0] || sys_reg->slider_select[1])
|
||||
if (iqs269_slider_type(iqs269, 0) == IQS269_SLIDER_RAW ||
|
||||
iqs269_slider_type(iqs269, 1) == IQS269_SLIDER_RAW)
|
||||
general |= IQS269_SYS_SETTINGS_EVENT_MODE_LP;
|
||||
|
||||
general |= IQS269_SYS_SETTINGS_REDO_ATI;
|
||||
@ -1026,12 +1192,30 @@ static int iqs269_parse_prop(struct iqs269_private *iqs269)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct reg_sequence iqs269_tws_init[] = {
|
||||
{ IQS269_TOUCH_HOLD_SLIDER_SEL, IQS269_TOUCH_HOLD_DEFAULT },
|
||||
{ 0xF0, 0x580F },
|
||||
{ 0xF0, 0x59EF },
|
||||
};
|
||||
|
||||
static int iqs269_dev_init(struct iqs269_private *iqs269)
|
||||
{
|
||||
int error;
|
||||
|
||||
mutex_lock(&iqs269->lock);
|
||||
|
||||
/*
|
||||
* Early revisions of silicon require the following workaround in order
|
||||
* to restore any OTP-enabled functionality after a soft reset.
|
||||
*/
|
||||
if (iqs269->otp_option == IQS269_OTP_OPTION_TWS &&
|
||||
iqs269->ver_info.fw_num < IQS269_VER_INFO_FW_NUM_3) {
|
||||
error = regmap_multi_reg_write(iqs269->regmap, iqs269_tws_init,
|
||||
ARRAY_SIZE(iqs269_tws_init));
|
||||
if (error)
|
||||
goto err_mutex;
|
||||
}
|
||||
|
||||
error = regmap_update_bits(iqs269->regmap, IQS269_HALL_UI,
|
||||
IQS269_HALL_UI_ENABLE,
|
||||
iqs269->hall_enable ? ~0 : 0);
|
||||
@ -1106,19 +1290,37 @@ static int iqs269_input_init(struct iqs269_private *iqs269)
|
||||
}
|
||||
|
||||
for (i = 0; i < IQS269_NUM_SL; i++) {
|
||||
if (!iqs269->sys_reg.slider_select[i])
|
||||
if (iqs269_slider_type(iqs269, i) == IQS269_SLIDER_NONE)
|
||||
continue;
|
||||
|
||||
iqs269->slider[i] = devm_input_allocate_device(&client->dev);
|
||||
if (!iqs269->slider[i])
|
||||
return -ENOMEM;
|
||||
|
||||
iqs269->slider[i]->keycodemax = ARRAY_SIZE(iqs269->sl_code[i]);
|
||||
iqs269->slider[i]->keycode = iqs269->sl_code[i];
|
||||
iqs269->slider[i]->keycodesize = sizeof(**iqs269->sl_code);
|
||||
|
||||
iqs269->slider[i]->name = i ? "iqs269a_slider_1"
|
||||
: "iqs269a_slider_0";
|
||||
iqs269->slider[i]->id.bustype = BUS_I2C;
|
||||
|
||||
input_set_capability(iqs269->slider[i], EV_KEY, BTN_TOUCH);
|
||||
input_set_abs_params(iqs269->slider[i], ABS_X, 0, 255, 0, 0);
|
||||
for (j = 0; j < IQS269_NUM_GESTURES; j++)
|
||||
if (iqs269->sl_code[i][j] != KEY_RESERVED)
|
||||
input_set_capability(iqs269->slider[i], EV_KEY,
|
||||
iqs269->sl_code[i][j]);
|
||||
|
||||
/*
|
||||
* Present the slider as a narrow trackpad if one or more chan-
|
||||
* nels have been selected to participate, but no gestures have
|
||||
* been mapped to a keycode.
|
||||
*/
|
||||
if (iqs269_slider_type(iqs269, i) == IQS269_SLIDER_RAW) {
|
||||
input_set_capability(iqs269->slider[i],
|
||||
EV_KEY, BTN_TOUCH);
|
||||
input_set_abs_params(iqs269->slider[i],
|
||||
ABS_X, 0, 255, 0, 0);
|
||||
}
|
||||
|
||||
error = input_register_device(iqs269->slider[i]);
|
||||
if (error) {
|
||||
@ -1167,28 +1369,62 @@ static int iqs269_report(struct iqs269_private *iqs269)
|
||||
if (be16_to_cpu(flags.system) & IQS269_SYS_FLAGS_IN_ATI)
|
||||
return 0;
|
||||
|
||||
error = regmap_raw_read(iqs269->regmap, IQS269_SLIDER_X, slider_x,
|
||||
sizeof(slider_x));
|
||||
if (error) {
|
||||
dev_err(&client->dev, "Failed to read slider position: %d\n",
|
||||
error);
|
||||
return error;
|
||||
if (iqs269_slider_type(iqs269, 0) == IQS269_SLIDER_RAW ||
|
||||
iqs269_slider_type(iqs269, 1) == IQS269_SLIDER_RAW) {
|
||||
error = regmap_raw_read(iqs269->regmap, IQS269_SLIDER_X,
|
||||
slider_x, sizeof(slider_x));
|
||||
if (error) {
|
||||
dev_err(&client->dev,
|
||||
"Failed to read slider position: %d\n", error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < IQS269_NUM_SL; i++) {
|
||||
if (!iqs269->sys_reg.slider_select[i])
|
||||
flags.gesture >>= (i * IQS269_NUM_GESTURES);
|
||||
|
||||
switch (iqs269_slider_type(iqs269, i)) {
|
||||
case IQS269_SLIDER_NONE:
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Report BTN_TOUCH if any channel that participates in the
|
||||
* slider is in a state of touch.
|
||||
*/
|
||||
if (flags.states[IQS269_ST_OFFS_TOUCH] &
|
||||
iqs269->sys_reg.slider_select[i]) {
|
||||
input_report_key(iqs269->slider[i], BTN_TOUCH, 1);
|
||||
input_report_abs(iqs269->slider[i], ABS_X, slider_x[i]);
|
||||
} else {
|
||||
input_report_key(iqs269->slider[i], BTN_TOUCH, 0);
|
||||
case IQS269_SLIDER_KEY:
|
||||
for (j = 0; j < IQS269_NUM_GESTURES; j++)
|
||||
input_report_key(iqs269->slider[i],
|
||||
iqs269->sl_code[i][j],
|
||||
flags.gesture & BIT(j));
|
||||
|
||||
if (!(flags.gesture & (BIT(IQS269_GESTURE_FLICK_NEG) |
|
||||
BIT(IQS269_GESTURE_FLICK_POS) |
|
||||
BIT(IQS269_GESTURE_TAP))))
|
||||
break;
|
||||
|
||||
input_sync(iqs269->slider[i]);
|
||||
|
||||
/*
|
||||
* Momentary gestures are followed by a complementary
|
||||
* release cycle so as to emulate a full keystroke.
|
||||
*/
|
||||
for (j = 0; j < IQS269_NUM_GESTURES; j++)
|
||||
if (j != IQS269_GESTURE_HOLD)
|
||||
input_report_key(iqs269->slider[i],
|
||||
iqs269->sl_code[i][j],
|
||||
0);
|
||||
break;
|
||||
|
||||
case IQS269_SLIDER_RAW:
|
||||
/*
|
||||
* The slider is considered to be in a state of touch
|
||||
* if any selected channels are in a state of touch.
|
||||
*/
|
||||
state = flags.states[IQS269_ST_OFFS_TOUCH];
|
||||
state &= iqs269->sys_reg.slider_select[i];
|
||||
|
||||
input_report_key(iqs269->slider[i], BTN_TOUCH, state);
|
||||
|
||||
if (state)
|
||||
input_report_abs(iqs269->slider[i],
|
||||
ABS_X, slider_x[i]);
|
||||
break;
|
||||
}
|
||||
|
||||
input_sync(iqs269->slider[i]);
|
||||
@ -1286,7 +1522,7 @@ static ssize_t counts_show(struct device *dev,
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%u\n", le16_to_cpu(counts));
|
||||
return sysfs_emit(buf, "%u\n", le16_to_cpu(counts));
|
||||
}
|
||||
|
||||
static ssize_t hall_bin_show(struct device *dev,
|
||||
@ -1324,7 +1560,7 @@ static ssize_t hall_bin_show(struct device *dev,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%u\n", val);
|
||||
return sysfs_emit(buf, "%u\n", val);
|
||||
}
|
||||
|
||||
static ssize_t hall_enable_show(struct device *dev,
|
||||
@ -1332,7 +1568,7 @@ static ssize_t hall_enable_show(struct device *dev,
|
||||
{
|
||||
struct iqs269_private *iqs269 = dev_get_drvdata(dev);
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%u\n", iqs269->hall_enable);
|
||||
return sysfs_emit(buf, "%u\n", iqs269->hall_enable);
|
||||
}
|
||||
|
||||
static ssize_t hall_enable_store(struct device *dev,
|
||||
@ -1362,7 +1598,7 @@ static ssize_t ch_number_show(struct device *dev,
|
||||
{
|
||||
struct iqs269_private *iqs269 = dev_get_drvdata(dev);
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%u\n", iqs269->ch_num);
|
||||
return sysfs_emit(buf, "%u\n", iqs269->ch_num);
|
||||
}
|
||||
|
||||
static ssize_t ch_number_store(struct device *dev,
|
||||
@ -1391,8 +1627,7 @@ static ssize_t rx_enable_show(struct device *dev,
|
||||
struct iqs269_private *iqs269 = dev_get_drvdata(dev);
|
||||
struct iqs269_ch_reg *ch_reg = iqs269->sys_reg.ch_reg;
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%u\n",
|
||||
ch_reg[iqs269->ch_num].rx_enable);
|
||||
return sysfs_emit(buf, "%u\n", ch_reg[iqs269->ch_num].rx_enable);
|
||||
}
|
||||
|
||||
static ssize_t rx_enable_store(struct device *dev,
|
||||
@ -1432,7 +1667,7 @@ static ssize_t ati_mode_show(struct device *dev,
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%u\n", val);
|
||||
return sysfs_emit(buf, "%u\n", val);
|
||||
}
|
||||
|
||||
static ssize_t ati_mode_store(struct device *dev,
|
||||
@ -1465,7 +1700,7 @@ static ssize_t ati_base_show(struct device *dev,
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%u\n", val);
|
||||
return sysfs_emit(buf, "%u\n", val);
|
||||
}
|
||||
|
||||
static ssize_t ati_base_store(struct device *dev,
|
||||
@ -1498,7 +1733,7 @@ static ssize_t ati_target_show(struct device *dev,
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%u\n", val);
|
||||
return sysfs_emit(buf, "%u\n", val);
|
||||
}
|
||||
|
||||
static ssize_t ati_target_store(struct device *dev,
|
||||
@ -1525,9 +1760,9 @@ static ssize_t ati_trigger_show(struct device *dev,
|
||||
{
|
||||
struct iqs269_private *iqs269 = dev_get_drvdata(dev);
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%u\n",
|
||||
iqs269->ati_current &&
|
||||
completion_done(&iqs269->ati_done));
|
||||
return sysfs_emit(buf, "%u\n",
|
||||
iqs269->ati_current &&
|
||||
completion_done(&iqs269->ati_done));
|
||||
}
|
||||
|
||||
static ssize_t ati_trigger_store(struct device *dev,
|
||||
@ -1596,7 +1831,6 @@ static const struct regmap_config iqs269_regmap_config = {
|
||||
|
||||
static int iqs269_probe(struct i2c_client *client)
|
||||
{
|
||||
struct iqs269_ver_info ver_info;
|
||||
struct iqs269_private *iqs269;
|
||||
int error;
|
||||
|
||||
@ -1618,14 +1852,16 @@ static int iqs269_probe(struct i2c_client *client)
|
||||
mutex_init(&iqs269->lock);
|
||||
init_completion(&iqs269->ati_done);
|
||||
|
||||
error = regmap_raw_read(iqs269->regmap, IQS269_VER_INFO, &ver_info,
|
||||
sizeof(ver_info));
|
||||
iqs269->otp_option = (uintptr_t)device_get_match_data(&client->dev);
|
||||
|
||||
error = regmap_raw_read(iqs269->regmap, IQS269_VER_INFO,
|
||||
&iqs269->ver_info, sizeof(iqs269->ver_info));
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (ver_info.prod_num != IQS269_VER_INFO_PROD_NUM) {
|
||||
if (iqs269->ver_info.prod_num != IQS269_VER_INFO_PROD_NUM) {
|
||||
dev_err(&client->dev, "Unrecognized product number: 0x%02X\n",
|
||||
ver_info.prod_num);
|
||||
iqs269->ver_info.prod_num);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -1728,7 +1964,18 @@ static int iqs269_resume(struct device *dev)
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(iqs269_pm, iqs269_suspend, iqs269_resume);
|
||||
|
||||
static const struct of_device_id iqs269_of_match[] = {
|
||||
{ .compatible = "azoteq,iqs269a" },
|
||||
{
|
||||
.compatible = "azoteq,iqs269a",
|
||||
.data = (void *)IQS269_OTP_OPTION_DEFAULT,
|
||||
},
|
||||
{
|
||||
.compatible = "azoteq,iqs269a-00",
|
||||
.data = (void *)IQS269_OTP_OPTION_DEFAULT,
|
||||
},
|
||||
{
|
||||
.compatible = "azoteq,iqs269a-d0",
|
||||
.data = (void *)IQS269_OTP_OPTION_TWS,
|
||||
},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, iqs269_of_match);
|
||||
|
@ -307,7 +307,7 @@ static int max77693_haptic_probe(struct platform_device *pdev)
|
||||
haptic->suspend_state = false;
|
||||
|
||||
/* Variant-specific init */
|
||||
haptic->dev_type = platform_get_device_id(pdev)->driver_data;
|
||||
haptic->dev_type = max77693->type;
|
||||
switch (haptic->dev_type) {
|
||||
case TYPE_MAX77693:
|
||||
haptic->regmap_haptic = max77693->regmap_haptic;
|
||||
@ -406,16 +406,24 @@ static DEFINE_SIMPLE_DEV_PM_OPS(max77693_haptic_pm_ops,
|
||||
max77693_haptic_resume);
|
||||
|
||||
static const struct platform_device_id max77693_haptic_id[] = {
|
||||
{ "max77693-haptic", TYPE_MAX77693 },
|
||||
{ "max77843-haptic", TYPE_MAX77843 },
|
||||
{ "max77693-haptic", },
|
||||
{ "max77843-haptic", },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, max77693_haptic_id);
|
||||
|
||||
static const struct of_device_id of_max77693_haptic_dt_match[] = {
|
||||
{ .compatible = "maxim,max77693-haptic", },
|
||||
{ .compatible = "maxim,max77843-haptic", },
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, of_max77693_haptic_dt_match);
|
||||
|
||||
static struct platform_driver max77693_haptic_driver = {
|
||||
.driver = {
|
||||
.name = "max77693-haptic",
|
||||
.pm = pm_sleep_ptr(&max77693_haptic_pm_ops),
|
||||
.of_match_table = of_max77693_haptic_dt_match,
|
||||
},
|
||||
.probe = max77693_haptic_probe,
|
||||
.id_table = max77693_haptic_id,
|
||||
|
@ -756,16 +756,16 @@ static ssize_t cyapa_show_suspend_scanrate(struct device *dev,
|
||||
|
||||
switch (pwr_cmd) {
|
||||
case PWR_MODE_BTN_ONLY:
|
||||
len = scnprintf(buf, PAGE_SIZE, "%s\n", BTN_ONLY_MODE_NAME);
|
||||
len = sysfs_emit(buf, "%s\n", BTN_ONLY_MODE_NAME);
|
||||
break;
|
||||
|
||||
case PWR_MODE_OFF:
|
||||
len = scnprintf(buf, PAGE_SIZE, "%s\n", OFF_MODE_NAME);
|
||||
len = sysfs_emit(buf, "%s\n", OFF_MODE_NAME);
|
||||
break;
|
||||
|
||||
default:
|
||||
len = scnprintf(buf, PAGE_SIZE, "%u\n",
|
||||
cyapa->gen == CYAPA_GEN3 ?
|
||||
len = sysfs_emit(buf, "%u\n",
|
||||
cyapa->gen == CYAPA_GEN3 ?
|
||||
cyapa_pwr_cmd_to_sleep_time(pwr_cmd) :
|
||||
sleep_time);
|
||||
break;
|
||||
@ -877,8 +877,8 @@ static ssize_t cyapa_show_rt_suspend_scanrate(struct device *dev,
|
||||
|
||||
mutex_unlock(&cyapa->state_sync_lock);
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%u\n",
|
||||
cyapa->gen == CYAPA_GEN3 ?
|
||||
return sysfs_emit(buf, "%u\n",
|
||||
cyapa->gen == CYAPA_GEN3 ?
|
||||
cyapa_pwr_cmd_to_sleep_time(pwr_cmd) :
|
||||
sleep_time);
|
||||
}
|
||||
@ -988,8 +988,8 @@ static ssize_t cyapa_show_fm_ver(struct device *dev,
|
||||
error = mutex_lock_interruptible(&cyapa->state_sync_lock);
|
||||
if (error)
|
||||
return error;
|
||||
error = scnprintf(buf, PAGE_SIZE, "%d.%d\n", cyapa->fw_maj_ver,
|
||||
cyapa->fw_min_ver);
|
||||
error = sysfs_emit(buf, "%d.%d\n",
|
||||
cyapa->fw_maj_ver, cyapa->fw_min_ver);
|
||||
mutex_unlock(&cyapa->state_sync_lock);
|
||||
return error;
|
||||
}
|
||||
@ -1004,7 +1004,7 @@ static ssize_t cyapa_show_product_id(struct device *dev,
|
||||
error = mutex_lock_interruptible(&cyapa->state_sync_lock);
|
||||
if (error)
|
||||
return error;
|
||||
size = scnprintf(buf, PAGE_SIZE, "%s\n", cyapa->product_id);
|
||||
size = sysfs_emit(buf, "%s\n", cyapa->product_id);
|
||||
mutex_unlock(&cyapa->state_sync_lock);
|
||||
return size;
|
||||
}
|
||||
@ -1209,8 +1209,8 @@ static ssize_t cyapa_show_mode(struct device *dev,
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
size = scnprintf(buf, PAGE_SIZE, "gen%d %s\n",
|
||||
cyapa->gen, cyapa_state_to_string(cyapa));
|
||||
size = sysfs_emit(buf, "gen%d %s\n",
|
||||
cyapa->gen, cyapa_state_to_string(cyapa));
|
||||
|
||||
mutex_unlock(&cyapa->state_sync_lock);
|
||||
return size;
|
||||
|
@ -860,7 +860,7 @@ static ssize_t cyapa_gen3_show_baseline(struct device *dev,
|
||||
|
||||
dev_dbg(dev, "Baseline report successful. Max: %d Min: %d\n",
|
||||
max_baseline, min_baseline);
|
||||
ret = scnprintf(buf, PAGE_SIZE, "%d %d\n", max_baseline, min_baseline);
|
||||
ret = sysfs_emit(buf, "%d %d\n", max_baseline, min_baseline);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
|
@ -2418,12 +2418,12 @@ resume_scanning:
|
||||
return resume_error ? resume_error : error;
|
||||
|
||||
/* 12. Output data strings */
|
||||
size = scnprintf(buf, PAGE_SIZE, "%d %d %d %d %d %d %d %d %d %d %d ",
|
||||
size = sysfs_emit(buf, "%d %d %d %d %d %d %d %d %d %d %d ",
|
||||
gidac_mutual_min, gidac_mutual_max, gidac_mutual_ave,
|
||||
lidac_mutual_min, lidac_mutual_max, lidac_mutual_ave,
|
||||
gidac_self_rx, gidac_self_tx,
|
||||
lidac_self_min, lidac_self_max, lidac_self_ave);
|
||||
size += scnprintf(buf + size, PAGE_SIZE - size,
|
||||
size += sysfs_emit_at(buf, size,
|
||||
"%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
|
||||
raw_cap_mutual_min, raw_cap_mutual_max, raw_cap_mutual_ave,
|
||||
raw_cap_self_min, raw_cap_self_max, raw_cap_self_ave,
|
||||
|
@ -629,14 +629,14 @@ static ssize_t cyapa_gen6_show_baseline(struct device *dev,
|
||||
if (error)
|
||||
goto resume_scanning;
|
||||
|
||||
size = scnprintf(buf, PAGE_SIZE, "%d %d %d %d %d %d ",
|
||||
data[0], /* RX Attenuator Mutual */
|
||||
data[1], /* IDAC Mutual */
|
||||
data[2], /* RX Attenuator Self RX */
|
||||
data[3], /* IDAC Self RX */
|
||||
data[4], /* RX Attenuator Self TX */
|
||||
data[5] /* IDAC Self TX */
|
||||
);
|
||||
size = sysfs_emit(buf, "%d %d %d %d %d %d ",
|
||||
data[0], /* RX Attenuator Mutual */
|
||||
data[1], /* IDAC Mutual */
|
||||
data[2], /* RX Attenuator Self RX */
|
||||
data[3], /* IDAC Self RX */
|
||||
data[4], /* RX Attenuator Self TX */
|
||||
data[5] /* IDAC Self TX */
|
||||
);
|
||||
|
||||
/* 3. Read Attenuator Trim. */
|
||||
data_len = sizeof(data);
|
||||
@ -648,8 +648,8 @@ static ssize_t cyapa_gen6_show_baseline(struct device *dev,
|
||||
|
||||
/* set attenuator trim values. */
|
||||
for (i = 0; i < data_len; i++)
|
||||
size += scnprintf(buf + size, PAGE_SIZE - size, "%d ", data[i]);
|
||||
size += scnprintf(buf + size, PAGE_SIZE - size, "\n");
|
||||
size += sysfs_emit_at(buf, size, "%d ", data[i]);
|
||||
size += sysfs_emit_at(buf, size, "\n");
|
||||
|
||||
resume_scanning:
|
||||
/* 4. Resume Scanning*/
|
||||
|
@ -572,7 +572,7 @@ static ssize_t elan_sysfs_read_fw_checksum(struct device *dev,
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct elan_tp_data *data = i2c_get_clientdata(client);
|
||||
|
||||
return sprintf(buf, "0x%04x\n", data->fw_checksum);
|
||||
return sysfs_emit(buf, "0x%04x\n", data->fw_checksum);
|
||||
}
|
||||
|
||||
static ssize_t elan_sysfs_read_product_id(struct device *dev,
|
||||
@ -582,8 +582,8 @@ static ssize_t elan_sysfs_read_product_id(struct device *dev,
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct elan_tp_data *data = i2c_get_clientdata(client);
|
||||
|
||||
return sprintf(buf, ETP_PRODUCT_ID_FORMAT_STRING "\n",
|
||||
data->product_id);
|
||||
return sysfs_emit(buf, ETP_PRODUCT_ID_FORMAT_STRING "\n",
|
||||
data->product_id);
|
||||
}
|
||||
|
||||
static ssize_t elan_sysfs_read_fw_ver(struct device *dev,
|
||||
@ -593,7 +593,7 @@ static ssize_t elan_sysfs_read_fw_ver(struct device *dev,
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct elan_tp_data *data = i2c_get_clientdata(client);
|
||||
|
||||
return sprintf(buf, "%d.0\n", data->fw_version);
|
||||
return sysfs_emit(buf, "%d.0\n", data->fw_version);
|
||||
}
|
||||
|
||||
static ssize_t elan_sysfs_read_sm_ver(struct device *dev,
|
||||
@ -603,7 +603,7 @@ static ssize_t elan_sysfs_read_sm_ver(struct device *dev,
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct elan_tp_data *data = i2c_get_clientdata(client);
|
||||
|
||||
return sprintf(buf, "%d.0\n", data->sm_version);
|
||||
return sysfs_emit(buf, "%d.0\n", data->sm_version);
|
||||
}
|
||||
|
||||
static ssize_t elan_sysfs_read_iap_ver(struct device *dev,
|
||||
@ -613,7 +613,7 @@ static ssize_t elan_sysfs_read_iap_ver(struct device *dev,
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct elan_tp_data *data = i2c_get_clientdata(client);
|
||||
|
||||
return sprintf(buf, "%d.0\n", data->iap_version);
|
||||
return sysfs_emit(buf, "%d.0\n", data->iap_version);
|
||||
}
|
||||
|
||||
static ssize_t elan_sysfs_update_fw(struct device *dev,
|
||||
@ -754,7 +754,7 @@ static ssize_t elan_sysfs_read_mode(struct device *dev,
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
return sprintf(buf, "%d\n", (int)mode);
|
||||
return sysfs_emit(buf, "%d\n", (int)mode);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(product_id, S_IRUGO, elan_sysfs_read_product_id, NULL);
|
||||
@ -858,7 +858,7 @@ static ssize_t min_show(struct device *dev,
|
||||
goto out;
|
||||
}
|
||||
|
||||
retval = snprintf(buf, PAGE_SIZE, "%d", data->min_baseline);
|
||||
retval = sysfs_emit(buf, "%d", data->min_baseline);
|
||||
|
||||
out:
|
||||
mutex_unlock(&data->sysfs_mutex);
|
||||
@ -881,7 +881,7 @@ static ssize_t max_show(struct device *dev,
|
||||
goto out;
|
||||
}
|
||||
|
||||
retval = snprintf(buf, PAGE_SIZE, "%d", data->max_baseline);
|
||||
retval = sysfs_emit(buf, "%d", data->max_baseline);
|
||||
|
||||
out:
|
||||
mutex_unlock(&data->sysfs_mutex);
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/input/navpoint.h>
|
||||
#include <linux/interrupt.h>
|
||||
@ -32,7 +32,7 @@ struct navpoint {
|
||||
struct ssp_device *ssp;
|
||||
struct input_dev *input;
|
||||
struct device *dev;
|
||||
int gpio;
|
||||
struct gpio_desc *gpiod;
|
||||
int index;
|
||||
u8 data[1 + HEADER_LENGTH(0xff)];
|
||||
};
|
||||
@ -170,16 +170,14 @@ static void navpoint_up(struct navpoint *navpoint)
|
||||
dev_err(navpoint->dev,
|
||||
"timeout waiting for SSSR[CSS] to clear\n");
|
||||
|
||||
if (gpio_is_valid(navpoint->gpio))
|
||||
gpio_set_value(navpoint->gpio, 1);
|
||||
gpiod_set_value(navpoint->gpiod, 1);
|
||||
}
|
||||
|
||||
static void navpoint_down(struct navpoint *navpoint)
|
||||
{
|
||||
struct ssp_device *ssp = navpoint->ssp;
|
||||
|
||||
if (gpio_is_valid(navpoint->gpio))
|
||||
gpio_set_value(navpoint->gpio, 0);
|
||||
gpiod_set_value(navpoint->gpiod, 0);
|
||||
|
||||
pxa_ssp_write_reg(ssp, SSCR0, 0);
|
||||
|
||||
@ -216,18 +214,9 @@ static int navpoint_probe(struct platform_device *pdev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (gpio_is_valid(pdata->gpio)) {
|
||||
error = gpio_request_one(pdata->gpio, GPIOF_OUT_INIT_LOW,
|
||||
"SYNAPTICS_ON");
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
|
||||
ssp = pxa_ssp_request(pdata->port, pdev->name);
|
||||
if (!ssp) {
|
||||
error = -ENODEV;
|
||||
goto err_free_gpio;
|
||||
}
|
||||
if (!ssp)
|
||||
return -ENODEV;
|
||||
|
||||
/* HaRET does not disable devices before jumping into Linux */
|
||||
if (pxa_ssp_read_reg(ssp, SSCR0) & SSCR0_SSE) {
|
||||
@ -242,10 +231,18 @@ static int navpoint_probe(struct platform_device *pdev)
|
||||
goto err_free_mem;
|
||||
}
|
||||
|
||||
navpoint->gpiod = gpiod_get_optional(&pdev->dev,
|
||||
NULL, GPIOD_OUT_LOW);
|
||||
if (IS_ERR(navpoint->gpiod)) {
|
||||
error = PTR_ERR(navpoint->gpiod);
|
||||
dev_err(&pdev->dev, "error getting GPIO\n");
|
||||
goto err_free_mem;
|
||||
}
|
||||
gpiod_set_consumer_name(navpoint->gpiod, "SYNAPTICS_ON");
|
||||
|
||||
navpoint->ssp = ssp;
|
||||
navpoint->input = input;
|
||||
navpoint->dev = &pdev->dev;
|
||||
navpoint->gpio = pdata->gpio;
|
||||
|
||||
input->name = pdev->name;
|
||||
input->dev.parent = &pdev->dev;
|
||||
@ -288,17 +285,12 @@ err_free_mem:
|
||||
input_free_device(input);
|
||||
kfree(navpoint);
|
||||
pxa_ssp_free(ssp);
|
||||
err_free_gpio:
|
||||
if (gpio_is_valid(pdata->gpio))
|
||||
gpio_free(pdata->gpio);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static void navpoint_remove(struct platform_device *pdev)
|
||||
{
|
||||
const struct navpoint_platform_data *pdata =
|
||||
dev_get_platdata(&pdev->dev);
|
||||
struct navpoint *navpoint = platform_get_drvdata(pdev);
|
||||
struct ssp_device *ssp = navpoint->ssp;
|
||||
|
||||
@ -308,9 +300,6 @@ static void navpoint_remove(struct platform_device *pdev)
|
||||
kfree(navpoint);
|
||||
|
||||
pxa_ssp_free(ssp);
|
||||
|
||||
if (gpio_is_valid(pdata->gpio))
|
||||
gpio_free(pdata->gpio);
|
||||
}
|
||||
|
||||
static int navpoint_suspend(struct device *dev)
|
||||
|
@ -267,8 +267,7 @@ static ssize_t rmi_driver_manufacturer_id_show(struct device *dev,
|
||||
struct rmi_driver_data *data = dev_get_drvdata(dev);
|
||||
struct f01_data *f01 = dev_get_drvdata(&data->f01_container->dev);
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n",
|
||||
f01->properties.manufacturer_id);
|
||||
return sysfs_emit(buf, "%d\n", f01->properties.manufacturer_id);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(manufacturer_id, 0444,
|
||||
@ -280,7 +279,7 @@ static ssize_t rmi_driver_dom_show(struct device *dev,
|
||||
struct rmi_driver_data *data = dev_get_drvdata(dev);
|
||||
struct f01_data *f01 = dev_get_drvdata(&data->f01_container->dev);
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%s\n", f01->properties.dom);
|
||||
return sysfs_emit(buf, "%s\n", f01->properties.dom);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(date_of_manufacture, 0444, rmi_driver_dom_show, NULL);
|
||||
@ -292,7 +291,7 @@ static ssize_t rmi_driver_product_id_show(struct device *dev,
|
||||
struct rmi_driver_data *data = dev_get_drvdata(dev);
|
||||
struct f01_data *f01 = dev_get_drvdata(&data->f01_container->dev);
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%s\n", f01->properties.product_id);
|
||||
return sysfs_emit(buf, "%s\n", f01->properties.product_id);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(product_id, 0444, rmi_driver_product_id_show, NULL);
|
||||
@ -304,7 +303,7 @@ static ssize_t rmi_driver_firmware_id_show(struct device *dev,
|
||||
struct rmi_driver_data *data = dev_get_drvdata(dev);
|
||||
struct f01_data *f01 = dev_get_drvdata(&data->f01_container->dev);
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", f01->properties.firmware_id);
|
||||
return sysfs_emit(buf, "%d\n", f01->properties.firmware_id);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(firmware_id, 0444, rmi_driver_firmware_id_show, NULL);
|
||||
@ -318,8 +317,8 @@ static ssize_t rmi_driver_package_id_show(struct device *dev,
|
||||
|
||||
u32 package_id = f01->properties.package_id;
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%04x.%04x\n",
|
||||
package_id & 0xffff, (package_id >> 16) & 0xffff);
|
||||
return sysfs_emit(buf, "%04x.%04x\n",
|
||||
package_id & 0xffff, (package_id >> 16) & 0xffff);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(package_id, 0444, rmi_driver_package_id_show, NULL);
|
||||
|
@ -2818,8 +2818,8 @@ static ssize_t mxt_fw_version_show(struct device *dev,
|
||||
{
|
||||
struct mxt_data *data = dev_get_drvdata(dev);
|
||||
struct mxt_info *info = data->info;
|
||||
return scnprintf(buf, PAGE_SIZE, "%u.%u.%02X\n",
|
||||
info->version >> 4, info->version & 0xf, info->build);
|
||||
return sysfs_emit(buf, "%u.%u.%02X\n",
|
||||
info->version >> 4, info->version & 0xf, info->build);
|
||||
}
|
||||
|
||||
/* Hardware Version is returned as FamilyID.VariantID */
|
||||
@ -2828,8 +2828,7 @@ static ssize_t mxt_hw_version_show(struct device *dev,
|
||||
{
|
||||
struct mxt_data *data = dev_get_drvdata(dev);
|
||||
struct mxt_info *info = data->info;
|
||||
return scnprintf(buf, PAGE_SIZE, "%u.%u\n",
|
||||
info->family_id, info->variant_id);
|
||||
return sysfs_emit(buf, "%u.%u\n", info->family_id, info->variant_id);
|
||||
}
|
||||
|
||||
static ssize_t mxt_show_instance(char *buf, int count,
|
||||
@ -2839,19 +2838,18 @@ static ssize_t mxt_show_instance(char *buf, int count,
|
||||
int i;
|
||||
|
||||
if (mxt_obj_instances(object) > 1)
|
||||
count += scnprintf(buf + count, PAGE_SIZE - count,
|
||||
"Instance %u\n", instance);
|
||||
count += sysfs_emit_at(buf, count, "Instance %u\n", instance);
|
||||
|
||||
for (i = 0; i < mxt_obj_size(object); i++)
|
||||
count += scnprintf(buf + count, PAGE_SIZE - count,
|
||||
"\t[%2u]: %02x (%d)\n", i, val[i], val[i]);
|
||||
count += scnprintf(buf + count, PAGE_SIZE - count, "\n");
|
||||
count += sysfs_emit_at(buf, count, "\t[%2u]: %02x (%d)\n",
|
||||
i, val[i], val[i]);
|
||||
count += sysfs_emit_at(buf, count, "\n");
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t mxt_object_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct mxt_data *data = dev_get_drvdata(dev);
|
||||
struct mxt_object *object;
|
||||
@ -2872,8 +2870,7 @@ static ssize_t mxt_object_show(struct device *dev,
|
||||
if (!mxt_object_readable(object->type))
|
||||
continue;
|
||||
|
||||
count += scnprintf(buf + count, PAGE_SIZE - count,
|
||||
"T%u:\n", object->type);
|
||||
count += sysfs_emit_at(buf, count, "T%u:\n", object->type);
|
||||
|
||||
for (j = 0; j < mxt_obj_instances(object); j++) {
|
||||
u16 size = mxt_obj_size(object);
|
||||
|
@ -431,7 +431,7 @@ static ssize_t edt_ft5x06_setting_show(struct device *dev,
|
||||
*field = val;
|
||||
}
|
||||
|
||||
count = scnprintf(buf, PAGE_SIZE, "%d\n", val);
|
||||
count = sysfs_emit(buf, "%d\n", val);
|
||||
out:
|
||||
mutex_unlock(&tsdata->mutex);
|
||||
return error ?: count;
|
||||
|
@ -928,8 +928,7 @@ static ssize_t hideep_fw_version_show(struct device *dev,
|
||||
ssize_t len;
|
||||
|
||||
mutex_lock(&ts->dev_mutex);
|
||||
len = scnprintf(buf, PAGE_SIZE, "%04x\n",
|
||||
be16_to_cpu(ts->dwz_info.release_ver));
|
||||
len = sysfs_emit(buf, "%04x\n", be16_to_cpu(ts->dwz_info.release_ver));
|
||||
mutex_unlock(&ts->dev_mutex);
|
||||
|
||||
return len;
|
||||
@ -943,8 +942,7 @@ static ssize_t hideep_product_id_show(struct device *dev,
|
||||
ssize_t len;
|
||||
|
||||
mutex_lock(&ts->dev_mutex);
|
||||
len = scnprintf(buf, PAGE_SIZE, "%04x\n",
|
||||
be16_to_cpu(ts->dwz_info.product_id));
|
||||
len = sysfs_emit(buf, "%04x\n", be16_to_cpu(ts->dwz_info.product_id));
|
||||
mutex_unlock(&ts->dev_mutex);
|
||||
|
||||
return len;
|
||||
|
@ -202,7 +202,7 @@ static ssize_t hycon_hy46xx_setting_show(struct device *dev,
|
||||
*field = val;
|
||||
}
|
||||
|
||||
count = scnprintf(buf, PAGE_SIZE, "%d\n", val);
|
||||
count = sysfs_emit(buf, "%d\n", val);
|
||||
|
||||
out:
|
||||
mutex_unlock(&tsdata->mutex);
|
||||
|
@ -512,12 +512,12 @@ static ssize_t firmware_version_show(struct device *dev,
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct ilitek_ts_data *ts = i2c_get_clientdata(client);
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE,
|
||||
"fw version: [%02X%02X.%02X%02X.%02X%02X.%02X%02X]\n",
|
||||
ts->firmware_ver[0], ts->firmware_ver[1],
|
||||
ts->firmware_ver[2], ts->firmware_ver[3],
|
||||
ts->firmware_ver[4], ts->firmware_ver[5],
|
||||
ts->firmware_ver[6], ts->firmware_ver[7]);
|
||||
return sysfs_emit(buf,
|
||||
"fw version: [%02X%02X.%02X%02X.%02X%02X.%02X%02X]\n",
|
||||
ts->firmware_ver[0], ts->firmware_ver[1],
|
||||
ts->firmware_ver[2], ts->firmware_ver[3],
|
||||
ts->firmware_ver[4], ts->firmware_ver[5],
|
||||
ts->firmware_ver[6], ts->firmware_ver[7]);
|
||||
}
|
||||
static DEVICE_ATTR_RO(firmware_version);
|
||||
|
||||
@ -527,8 +527,8 @@ static ssize_t product_id_show(struct device *dev,
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct ilitek_ts_data *ts = i2c_get_clientdata(client);
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "product id: [%04X], module: [%s]\n",
|
||||
ts->mcu_ver, ts->product_id);
|
||||
return sysfs_emit(buf, "product id: [%04X], module: [%s]\n",
|
||||
ts->mcu_ver, ts->product_id);
|
||||
}
|
||||
static DEVICE_ATTR_RO(product_id);
|
||||
|
||||
|
@ -943,12 +943,12 @@ static ssize_t fw_info_show(struct device *dev,
|
||||
if (!iqs5xx->dev_id_info.bl_status)
|
||||
return -ENODATA;
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%u.%u.%u.%u:%u.%u\n",
|
||||
be16_to_cpu(iqs5xx->dev_id_info.prod_num),
|
||||
be16_to_cpu(iqs5xx->dev_id_info.proj_num),
|
||||
iqs5xx->dev_id_info.major_ver,
|
||||
iqs5xx->dev_id_info.minor_ver,
|
||||
iqs5xx->exp_file[0], iqs5xx->exp_file[1]);
|
||||
return sysfs_emit(buf, "%u.%u.%u.%u:%u.%u\n",
|
||||
be16_to_cpu(iqs5xx->dev_id_info.prod_num),
|
||||
be16_to_cpu(iqs5xx->dev_id_info.proj_num),
|
||||
iqs5xx->dev_id_info.major_ver,
|
||||
iqs5xx->dev_id_info.minor_ver,
|
||||
iqs5xx->exp_file[0], iqs5xx->exp_file[1]);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_WO(fw_file);
|
||||
|
@ -2401,12 +2401,12 @@ static ssize_t fw_info_show(struct device *dev,
|
||||
{
|
||||
struct iqs7211_private *iqs7211 = dev_get_drvdata(dev);
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%u.%u.%u.%u:%u.%u\n",
|
||||
le16_to_cpu(iqs7211->ver_info.prod_num),
|
||||
le32_to_cpu(iqs7211->ver_info.patch),
|
||||
le16_to_cpu(iqs7211->ver_info.major),
|
||||
le16_to_cpu(iqs7211->ver_info.minor),
|
||||
iqs7211->exp_file[1], iqs7211->exp_file[0]);
|
||||
return sysfs_emit(buf, "%u.%u.%u.%u:%u.%u\n",
|
||||
le16_to_cpu(iqs7211->ver_info.prod_num),
|
||||
le32_to_cpu(iqs7211->ver_info.patch),
|
||||
le16_to_cpu(iqs7211->ver_info.major),
|
||||
le16_to_cpu(iqs7211->ver_info.minor),
|
||||
iqs7211->exp_file[1], iqs7211->exp_file[0]);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RO(fw_info);
|
||||
|
@ -1336,9 +1336,9 @@ static ssize_t mip4_sysfs_read_fw_version(struct device *dev,
|
||||
/* Take lock to prevent racing with firmware update */
|
||||
mutex_lock(&ts->input->mutex);
|
||||
|
||||
count = snprintf(buf, PAGE_SIZE, "%04X %04X %04X %04X\n",
|
||||
ts->fw_version.boot, ts->fw_version.core,
|
||||
ts->fw_version.app, ts->fw_version.param);
|
||||
count = sysfs_emit(buf, "%04X %04X %04X %04X\n",
|
||||
ts->fw_version.boot, ts->fw_version.core,
|
||||
ts->fw_version.app, ts->fw_version.param);
|
||||
|
||||
mutex_unlock(&ts->input->mutex);
|
||||
|
||||
@ -1362,8 +1362,8 @@ static ssize_t mip4_sysfs_read_hw_version(struct device *dev,
|
||||
* product_name shows the name or version of the hardware
|
||||
* paired with current firmware in the chip.
|
||||
*/
|
||||
count = snprintf(buf, PAGE_SIZE, "%.*s\n",
|
||||
(int)sizeof(ts->product_name), ts->product_name);
|
||||
count = sysfs_emit(buf, "%.*s\n",
|
||||
(int)sizeof(ts->product_name), ts->product_name);
|
||||
|
||||
mutex_unlock(&ts->input->mutex);
|
||||
|
||||
@ -1382,7 +1382,7 @@ static ssize_t mip4_sysfs_read_product_id(struct device *dev,
|
||||
|
||||
mutex_lock(&ts->input->mutex);
|
||||
|
||||
count = snprintf(buf, PAGE_SIZE, "%04X\n", ts->product_id);
|
||||
count = sysfs_emit(buf, "%04X\n", ts->product_id);
|
||||
|
||||
mutex_unlock(&ts->input->mutex);
|
||||
|
||||
@ -1401,8 +1401,8 @@ static ssize_t mip4_sysfs_read_ic_name(struct device *dev,
|
||||
|
||||
mutex_lock(&ts->input->mutex);
|
||||
|
||||
count = snprintf(buf, PAGE_SIZE, "%.*s\n",
|
||||
(int)sizeof(ts->ic_name), ts->ic_name);
|
||||
count = sysfs_emit(buf, "%.*s\n",
|
||||
(int)sizeof(ts->ic_name), ts->ic_name);
|
||||
|
||||
mutex_unlock(&ts->input->mutex);
|
||||
|
||||
|
@ -456,8 +456,8 @@ static ssize_t mtouch_firmware_rev_show(struct device *dev,
|
||||
struct usbtouch_usb *usbtouch = usb_get_intfdata(intf);
|
||||
struct mtouch_priv *priv = usbtouch->priv;
|
||||
|
||||
return scnprintf(output, PAGE_SIZE, "%1x.%1x\n",
|
||||
priv->fw_rev_major, priv->fw_rev_minor);
|
||||
return sysfs_emit(output, "%1x.%1x\n",
|
||||
priv->fw_rev_major, priv->fw_rev_minor);
|
||||
}
|
||||
static DEVICE_ATTR(firmware_rev, 0444, mtouch_firmware_rev_show, NULL);
|
||||
|
||||
|
@ -887,7 +887,7 @@ static ssize_t config_csum_show(struct device *dev,
|
||||
cfg_csum = wdt->param.xmls_id1;
|
||||
cfg_csum = (cfg_csum << 16) | wdt->param.xmls_id2;
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%x\n", cfg_csum);
|
||||
return sysfs_emit(buf, "%x\n", cfg_csum);
|
||||
}
|
||||
|
||||
static ssize_t fw_version_show(struct device *dev,
|
||||
@ -896,7 +896,7 @@ static ssize_t fw_version_show(struct device *dev,
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct wdt87xx_data *wdt = i2c_get_clientdata(client);
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%x\n", wdt->param.fw_id);
|
||||
return sysfs_emit(buf, "%x\n", wdt->param.fw_id);
|
||||
}
|
||||
|
||||
static ssize_t plat_id_show(struct device *dev,
|
||||
@ -905,7 +905,7 @@ static ssize_t plat_id_show(struct device *dev,
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct wdt87xx_data *wdt = i2c_get_clientdata(client);
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%x\n", wdt->param.plat_id);
|
||||
return sysfs_emit(buf, "%x\n", wdt->param.plat_id);
|
||||
}
|
||||
|
||||
static ssize_t update_config_store(struct device *dev,
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <linux/device.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/input/mt.h>
|
||||
#include <linux/input/touchscreen.h>
|
||||
#include <linux/platform_data/zforce_ts.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/of.h>
|
||||
@ -106,6 +107,7 @@ struct zforce_point {
|
||||
struct zforce_ts {
|
||||
struct i2c_client *client;
|
||||
struct input_dev *input;
|
||||
struct touchscreen_properties prop;
|
||||
const struct zforce_ts_platdata *pdata;
|
||||
char phys[32];
|
||||
|
||||
@ -266,7 +268,6 @@ static int zforce_setconfig(struct zforce_ts *ts, char b1)
|
||||
static int zforce_start(struct zforce_ts *ts)
|
||||
{
|
||||
struct i2c_client *client = ts->client;
|
||||
const struct zforce_ts_platdata *pdata = ts->pdata;
|
||||
int ret;
|
||||
|
||||
dev_dbg(&client->dev, "starting device\n");
|
||||
@ -277,7 +278,7 @@ static int zforce_start(struct zforce_ts *ts)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = zforce_resolution(ts, pdata->x_max, pdata->y_max);
|
||||
ret = zforce_resolution(ts, ts->prop.max_x, ts->prop.max_y);
|
||||
if (ret) {
|
||||
dev_err(&client->dev, "Unable to set resolution, %d\n", ret);
|
||||
goto error;
|
||||
@ -337,7 +338,6 @@ static int zforce_stop(struct zforce_ts *ts)
|
||||
static int zforce_touch_event(struct zforce_ts *ts, u8 *payload)
|
||||
{
|
||||
struct i2c_client *client = ts->client;
|
||||
const struct zforce_ts_platdata *pdata = ts->pdata;
|
||||
struct zforce_point point;
|
||||
int count, i, num = 0;
|
||||
|
||||
@ -355,8 +355,8 @@ static int zforce_touch_event(struct zforce_ts *ts, u8 *payload)
|
||||
point.coord_y =
|
||||
payload[9 * i + 4] << 8 | payload[9 * i + 3];
|
||||
|
||||
if (point.coord_x > pdata->x_max ||
|
||||
point.coord_y > pdata->y_max) {
|
||||
if (point.coord_x > ts->prop.max_x ||
|
||||
point.coord_y > ts->prop.max_y) {
|
||||
dev_warn(&client->dev, "coordinates (%d,%d) invalid\n",
|
||||
point.coord_x, point.coord_y);
|
||||
point.coord_x = point.coord_y = 0;
|
||||
@ -390,10 +390,9 @@ static int zforce_touch_event(struct zforce_ts *ts, u8 *payload)
|
||||
point.state != STATE_UP);
|
||||
|
||||
if (point.state != STATE_UP) {
|
||||
input_report_abs(ts->input, ABS_MT_POSITION_X,
|
||||
point.coord_x);
|
||||
input_report_abs(ts->input, ABS_MT_POSITION_Y,
|
||||
point.coord_y);
|
||||
touchscreen_report_pos(ts->input, &ts->prop,
|
||||
point.coord_x, point.coord_y,
|
||||
true);
|
||||
input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR,
|
||||
point.area_major);
|
||||
input_report_abs(ts->input, ABS_MT_TOUCH_MINOR,
|
||||
@ -719,15 +718,8 @@ static struct zforce_ts_platdata *zforce_parse_dt(struct device *dev)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
if (of_property_read_u32(np, "x-size", &pdata->x_max)) {
|
||||
dev_err(dev, "failed to get x-size property\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
if (of_property_read_u32(np, "y-size", &pdata->y_max)) {
|
||||
dev_err(dev, "failed to get y-size property\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
of_property_read_u32(np, "x-size", &pdata->x_max);
|
||||
of_property_read_u32(np, "y-size", &pdata->y_max);
|
||||
|
||||
return pdata;
|
||||
}
|
||||
@ -856,6 +848,12 @@ static int zforce_probe(struct i2c_client *client)
|
||||
input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0,
|
||||
pdata->y_max, 0, 0);
|
||||
|
||||
touchscreen_parse_properties(input_dev, true, &ts->prop);
|
||||
if (ts->prop.max_x == 0 || ts->prop.max_y == 0) {
|
||||
dev_err(&client->dev, "no size specified\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0,
|
||||
ZFORCE_MAX_AREA, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_MT_TOUCH_MINOR, 0,
|
||||
|
@ -27,10 +27,10 @@ ssize_t vivaldi_function_row_physmap_show(const struct vivaldi_data *data,
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < data->num_function_row_keys; i++)
|
||||
size += scnprintf(buf + size, PAGE_SIZE - size,
|
||||
"%s%02X", size ? " " : "", physmap[i]);
|
||||
size += sysfs_emit_at(buf, size,
|
||||
"%s%02X", size ? " " : "", physmap[i]);
|
||||
if (size)
|
||||
size += scnprintf(buf + size, PAGE_SIZE - size, "\n");
|
||||
size += sysfs_emit_at(buf, size, "\n");
|
||||
|
||||
return size;
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ struct device;
|
||||
* disable button via sysfs
|
||||
* @value: axis value for %EV_ABS
|
||||
* @irq: Irq number in case of interrupt keys
|
||||
* @wakeirq: Optional dedicated wake-up interrupt
|
||||
*/
|
||||
struct gpio_keys_button {
|
||||
unsigned int code;
|
||||
@ -34,6 +35,7 @@ struct gpio_keys_button {
|
||||
bool can_disable;
|
||||
int value;
|
||||
unsigned int irq;
|
||||
unsigned int wakeirq;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -7,7 +7,6 @@
|
||||
*/
|
||||
|
||||
struct as5011_platform_data {
|
||||
unsigned int button_gpio;
|
||||
unsigned int axis_irq; /* irq number */
|
||||
unsigned long axis_irqflags;
|
||||
char xp, xn; /* threshold for x axis */
|
||||
|
@ -5,5 +5,4 @@
|
||||
|
||||
struct navpoint_platform_data {
|
||||
int port; /* PXA SSP port for pxa_ssp_request() */
|
||||
int gpio; /* GPIO for power on/off */
|
||||
};
|
||||
|
@ -19,9 +19,6 @@ struct omap_kp_platform_data {
|
||||
bool rep;
|
||||
unsigned long delay;
|
||||
bool dbounce;
|
||||
/* specific to OMAP242x*/
|
||||
unsigned int *row_gpios;
|
||||
unsigned int *col_gpios;
|
||||
};
|
||||
|
||||
/* Group (0..3) -- when multiple keys are pressed, only the
|
||||
|
Loading…
Reference in New Issue
Block a user