Input updates for 6.8 merge window:

- a new driver for Adafruit Seesaw gamepad device
 
 - Zforce touchscreen will handle standard device properties for axis
   swap/inversion
 
 - handling of advanced sensitivity settings in Microchip CAP11xx
   capacitive sensor driver
 
 - more drivers have been converted to use newer gpiod API
 
 - support for dedicated wakeup IRQs in gpio-keys dirver
 
 - support for slider gestures and OTP variants in iqs269a driver
 
 - atkbd will report keyboard version as 0xab83 in cases when GET ID
   command was skipped (to deal with problematic firmware on newer
   laptops), restoring the previous behavior
 
 - other assorted cleanups and changes
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYIAB0WIQST2eWILY88ieB2DOtAj56VGEWXnAUCZalqoQAKCRBAj56VGEWX
 nOqHAP4u4b/r4w2aeULy3kpESgbUQ1vXpFUus/6AHTw1FAtbsgD/XxV3ZWKZ0H8J
 VfZ81yXvT3WstJM7p7YNP0GGXJ/HRQg=
 =l0Z8
 -----END PGP SIGNATURE-----

Merge tag 'input-for-v6.8-rc0' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input

Pull input updates from Dmitry Torokhov:

 - a new driver for Adafruit Seesaw gamepad device

 - Zforce touchscreen will handle standard device properties for axis
   swap/inversion

 - handling of advanced sensitivity settings in Microchip CAP11xx
   capacitive sensor driver

 - more drivers have been converted to use newer gpiod API

 - support for dedicated wakeup IRQs in gpio-keys dirver

 - support for slider gestures and OTP variants in iqs269a driver

 - atkbd will report keyboard version as 0xab83 in cases when GET ID
   command was skipped (to deal with problematic firmware on newer
   laptops), restoring the previous behavior

 - other assorted cleanups and changes

* tag 'input-for-v6.8-rc0' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (44 commits)
  Input: atkbd - use ab83 as id when skipping the getid command
  Input: driver for Adafruit Seesaw Gamepad
  dt-bindings: input: bindings for Adafruit Seesaw Gamepad
  Input: da9063_onkey - avoid explicitly setting input's parent
  Input: da9063_onkey - avoid using OF-specific APIs
  Input: iqs269a - add support for OTP variants
  dt-bindings: input: iqs269a: Add bindings for OTP variants
  Input: iqs269a - add support for slider gestures
  dt-bindings: input: iqs269a: Add bindings for slider gestures
  Input: gpio-keys - filter gpio_keys -EPROBE_DEFER error messages
  Input: zforce_ts - accept standard touchscreen properties
  dt-bindings: touchscreen: neonode,zforce: Use standard properties
  dt-bindings: touchscreen: convert neonode,zforce to json-schema
  dt-bindings: input: convert drv266x to json-schema
  Input: da9063 - use dev_err_probe()
  Input: da9063 - drop redundant prints in probe()
  Input: da9063 - simplify obtaining OF match data
  Input: as5011 - convert to GPIO descriptor
  Input: omap-keypad - drop optional GPIO support
  Input: tca6416-keypad - drop unused include
  ...
This commit is contained in:
Linus Torvalds 2024-01-18 17:21:35 -08:00
commit 0f289bdd41
57 changed files with 1634 additions and 551 deletions

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

@ -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 = <&reg_zforce_vdd>;
reset-gpios = <&gpio5 9 0>; /* RST */
irq-gpios = <&gpio5 6 0>; /* IRQ, optional */
x-size = <800>;
y-size = <600>;
};
/* ... */
};

View File

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

View File

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

View File

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

View File

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

View 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 *)&register_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");

View File

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

View File

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

View File

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

View File

@ -791,9 +791,9 @@ static bool atkbd_is_portable_device(void)
* not work. So in this case simply assume a keyboard is connected to avoid
* confusing some laptop keyboards.
*
* Skipping ATKBD_CMD_GETID ends up using a fake keyboard id. Using a fake id is
* ok in translated mode, only atkbd_select_set() checks atkbd->id and in
* translated mode that is a no-op.
* Skipping ATKBD_CMD_GETID ends up using a fake keyboard id. Using the standard
* 0xab83 id is ok in translated mode, only atkbd_select_set() checks atkbd->id
* and in translated mode that is a no-op.
*/
static bool atkbd_skip_getid(struct atkbd *atkbd)
{
@ -811,6 +811,7 @@ static int atkbd_probe(struct atkbd *atkbd)
{
struct ps2dev *ps2dev = &atkbd->ps2dev;
unsigned char param[2];
bool skip_getid;
/*
* Some systems, where the bit-twiddling when testing the io-lines of the
@ -832,7 +833,8 @@ static int atkbd_probe(struct atkbd *atkbd)
*/
param[0] = param[1] = 0xa5; /* initialize with invalid values */
if (atkbd_skip_getid(atkbd) || ps2_command(ps2dev, param, ATKBD_CMD_GETID)) {
skip_getid = atkbd_skip_getid(atkbd);
if (skip_getid || ps2_command(ps2dev, param, ATKBD_CMD_GETID)) {
/*
* If the get ID command was skipped or failed, we check if we can at least set
@ -842,7 +844,7 @@ static int atkbd_probe(struct atkbd *atkbd)
param[0] = 0;
if (ps2_command(ps2dev, param, ATKBD_CMD_SETLEDS))
return -1;
atkbd->id = 0xabba;
atkbd->id = skip_getid ? 0xab83 : 0xabba;
return 0;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -5,5 +5,4 @@
struct navpoint_platform_data {
int port; /* PXA SSP port for pxa_ssp_request() */
int gpio; /* GPIO for power on/off */
};

View File

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